diff --git a/AK/Math.h b/AK/Math.h index ebf9856f933b0d..17184e52b0450d 100644 --- a/AK/Math.h +++ b/AK/Math.h @@ -55,6 +55,24 @@ constexpr size_t product_odd() { return value * product_odd(); } return __builtin_##function##f(args); \ } +#define AARCH64_INSTRUCTION(instruction, arg) \ + if constexpr (IsSame) \ + TODO(); \ + if constexpr (IsSame) { \ + double res; \ + asm(#instruction " %d0, %d1" \ + : "=w"(res) \ + : "w"(##arg)); \ + return res; \ + } \ + if constexpr (IsSame) { \ + float res; \ + asm(#instruction " %s0, %s1" \ + : "=w"(res) \ + : "w"(##arg)); \ + return res; \ + } + namespace Division { template constexpr T fmod(T x, T y) @@ -110,6 +128,8 @@ constexpr T sqrt(T x) : "=t"(res) : "0"(x)); return res; +#elif ARCH(AARCH64) + AARCH64_INSTRUCTION(fsqrt, x); #else return __builtin_sqrt(x); #endif @@ -118,6 +138,9 @@ constexpr T sqrt(T x) template constexpr T rsqrt(T x) { +#if ARCH(AARCH64) + AARCH64_INSTRUCTION(frsqrte, x); +#endif return (T)1. / sqrt(x); } @@ -214,6 +237,8 @@ constexpr T fabs(T x) "fabs" : "+t"(x)); return x; +#elif ARCH(AARCH64) + AARCH64_INSTRUCTION(abs, x); #else return __builtin_fabs(x); #endif @@ -581,6 +606,61 @@ ALWAYS_INLINE I round_to(P value) : "st"); } return static_cast(ret); +#elif ARCH(AARCH64) + if constexpr (IsSigned) { + if constexpr (sizeof(I) <= sizeof(i32)) { + i32 res; + if constexpr (IsSame) { + asm("fcvtns %w0, %s1" + : "=r"(res), "w"(value)); + } else if constexpr (IsSame) { + asm("fcvtns %w0, %d1" + : "=r"(res), "w"(value)); + } else if constexpr (IsSame) { + TODO(); + } + return static_cast(res); + } + static_cast; // either long or long long aka i64 + i64 res; + if constexpr (IsSame) { + asm("fcvtns %0, %s1" + : "=r"(res), "w"(value)); + } else if constexpr (IsSame) { + asm("fcvtns %0, %d1" + : "=r"(res), "w"(value)); + } else if constexpr (IsSame) { + TODO(); + } + return static_cast(res); + } + + if constexpr (sizeof(I) <= sizeof(u32)) { + u32 res; + if constexpr (IsSame) { + asm("fcvtnu %w0, %s1" + : "=r"(res), "w"(value)); + } else if constexpr (IsSame) { + asm("fcvtnu %w0, %d1" + : "=r"(res), "w"(value)); + } else if constexpr (IsSame) { + TODO(); + } + return static_cast(res); + } + + static_cast; // either unsigned long or unsigned long long aka u64 + u64 res; + if constexpr (IsSame) { + asm("fcvtnu %0, %s1" + : "=r"(res), "w"(value)); + } else if constexpr (IsSame) { + asm("fcvtnu %0, %d1" + : "=r"(res), "w"(value)); + } else if constexpr (IsSame) { + TODO(); + } + return static_cast(res); #else if constexpr (IsSame) return static_cast(__builtin_llrintl(value)); @@ -676,10 +756,15 @@ constexpr T ceil(T num) ? static_cast(num) : static_cast(num) + ((num > 0) ? 1 : 0); } +#if ARCH(AARCH64) + AARCH64_INSTRUCTION(frintp, num); +#else return __builtin_ceil(num); +#endif } #undef CONSTEXPR_STATE +#undef AARCH64_INSTRUCTION } using AK::round_to;