From 61e963e52545189ca34ae8a6e43b42a258acc33d Mon Sep 17 00:00:00 2001 From: Myles Busig Date: Sat, 3 Aug 2024 16:08:22 -0600 Subject: [PATCH] Replace fixed point multiplication with C++ implementation Fixed point multiplication used an ARM inline assembly routine. This was fast, but unfortunately, caused some odd attempted inlining problems when used from Thumb-mode code. This commit replaces this assembly routine with a C++ implementation that performs equal or better than the assembly routine in most cases. The C++ implementation is slightly slower when called from Thumb-mode code because GCC inlines the operation instead of calling a standalone ARM-mode routine placed in IWRAM. The performance tradeoff is acceptable though because of the fixes, portability, and ARM-mode performance improvements it provides. --- include/mtl/fixed.hpp | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/include/mtl/fixed.hpp b/include/mtl/fixed.hpp index 02b84e3..59e0a06 100644 --- a/include/mtl/fixed.hpp +++ b/include/mtl/fixed.hpp @@ -125,25 +125,11 @@ public: /** * \brief Fixed point multiplication - * - * Uses an assembly implementation to multiply the two numbers. */ - fixed operator*(fixed rhs) const { - int32_t raw_result; - asm( - ".arm;" - "smull r8, r9, %[a], %[b];" - "lsr %[res], r8, #6;" - "orr %[res], r9, lsl #26;" - : [res] "=r" (raw_result) - : [a] "r" (x), - [b] "r" (rhs.x) - : "r8", "r9" - ); - - return from_raw(raw_result); + constexpr fixed operator*(fixed rhs) const { + return from_raw(((int64_t)x * rhs.x) >> 6); } - fixed& operator*=(fixed rhs) { + constexpr fixed& operator*=(fixed rhs) { *this = *this * rhs; return *this; }