mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
AK: Add support for some trivial math functions on aarch64
These all require just a single instruction each, we only have to differentiate between register prefixes accordingly.
This commit is contained in:
parent
650d2fdc2d
commit
eb5651870e
Notes:
sideshowbarker
2024-07-17 05:58:44 +09:00
Author: https://github.com/Hendiadyoin1 Commit: https://github.com/SerenityOS/serenity/commit/eb5651870e Pull-request: https://github.com/SerenityOS/serenity/pull/15564 Reviewed-by: https://github.com/linusg
1 changed files with 85 additions and 0 deletions
85
AK/Math.h
85
AK/Math.h
|
@ -55,6 +55,24 @@ constexpr size_t product_odd() { return value * product_odd<value - 2>(); }
|
||||||
return __builtin_##function##f(args); \
|
return __builtin_##function##f(args); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define AARCH64_INSTRUCTION(instruction, arg) \
|
||||||
|
if constexpr (IsSame<T, long double>) \
|
||||||
|
TODO(); \
|
||||||
|
if constexpr (IsSame<T, double>) { \
|
||||||
|
double res; \
|
||||||
|
asm(#instruction " %d0, %d1" \
|
||||||
|
: "=w"(res) \
|
||||||
|
: "w"(##arg)); \
|
||||||
|
return res; \
|
||||||
|
} \
|
||||||
|
if constexpr (IsSame<T, float>) { \
|
||||||
|
float res; \
|
||||||
|
asm(#instruction " %s0, %s1" \
|
||||||
|
: "=w"(res) \
|
||||||
|
: "w"(##arg)); \
|
||||||
|
return res; \
|
||||||
|
}
|
||||||
|
|
||||||
namespace Division {
|
namespace Division {
|
||||||
template<FloatingPoint T>
|
template<FloatingPoint T>
|
||||||
constexpr T fmod(T x, T y)
|
constexpr T fmod(T x, T y)
|
||||||
|
@ -110,6 +128,8 @@ constexpr T sqrt(T x)
|
||||||
: "=t"(res)
|
: "=t"(res)
|
||||||
: "0"(x));
|
: "0"(x));
|
||||||
return res;
|
return res;
|
||||||
|
#elif ARCH(AARCH64)
|
||||||
|
AARCH64_INSTRUCTION(fsqrt, x);
|
||||||
#else
|
#else
|
||||||
return __builtin_sqrt(x);
|
return __builtin_sqrt(x);
|
||||||
#endif
|
#endif
|
||||||
|
@ -118,6 +138,9 @@ constexpr T sqrt(T x)
|
||||||
template<FloatingPoint T>
|
template<FloatingPoint T>
|
||||||
constexpr T rsqrt(T x)
|
constexpr T rsqrt(T x)
|
||||||
{
|
{
|
||||||
|
#if ARCH(AARCH64)
|
||||||
|
AARCH64_INSTRUCTION(frsqrte, x);
|
||||||
|
#endif
|
||||||
return (T)1. / sqrt(x);
|
return (T)1. / sqrt(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +237,8 @@ constexpr T fabs(T x)
|
||||||
"fabs"
|
"fabs"
|
||||||
: "+t"(x));
|
: "+t"(x));
|
||||||
return x;
|
return x;
|
||||||
|
#elif ARCH(AARCH64)
|
||||||
|
AARCH64_INSTRUCTION(abs, x);
|
||||||
#else
|
#else
|
||||||
return __builtin_fabs(x);
|
return __builtin_fabs(x);
|
||||||
#endif
|
#endif
|
||||||
|
@ -581,6 +606,61 @@ ALWAYS_INLINE I round_to(P value)
|
||||||
: "st");
|
: "st");
|
||||||
}
|
}
|
||||||
return static_cast<I>(ret);
|
return static_cast<I>(ret);
|
||||||
|
#elif ARCH(AARCH64)
|
||||||
|
if constexpr (IsSigned<I>) {
|
||||||
|
if constexpr (sizeof(I) <= sizeof(i32)) {
|
||||||
|
i32 res;
|
||||||
|
if constexpr (IsSame<P, float>) {
|
||||||
|
asm("fcvtns %w0, %s1"
|
||||||
|
: "=r"(res), "w"(value));
|
||||||
|
} else if constexpr (IsSame<P, double>) {
|
||||||
|
asm("fcvtns %w0, %d1"
|
||||||
|
: "=r"(res), "w"(value));
|
||||||
|
} else if constexpr (IsSame<P, long double>) {
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
return static_cast<I>(res);
|
||||||
|
}
|
||||||
|
static_cast<sizeof(I) == 8>; // either long or long long aka i64
|
||||||
|
i64 res;
|
||||||
|
if constexpr (IsSame<P, float>) {
|
||||||
|
asm("fcvtns %0, %s1"
|
||||||
|
: "=r"(res), "w"(value));
|
||||||
|
} else if constexpr (IsSame<P, double>) {
|
||||||
|
asm("fcvtns %0, %d1"
|
||||||
|
: "=r"(res), "w"(value));
|
||||||
|
} else if constexpr (IsSame<P, long double>) {
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
return static_cast<I>(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (sizeof(I) <= sizeof(u32)) {
|
||||||
|
u32 res;
|
||||||
|
if constexpr (IsSame<P, float>) {
|
||||||
|
asm("fcvtnu %w0, %s1"
|
||||||
|
: "=r"(res), "w"(value));
|
||||||
|
} else if constexpr (IsSame<P, double>) {
|
||||||
|
asm("fcvtnu %w0, %d1"
|
||||||
|
: "=r"(res), "w"(value));
|
||||||
|
} else if constexpr (IsSame<P, long double>) {
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
return static_cast<I>(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static_cast<sizeof(I) == 8>; // either unsigned long or unsigned long long aka u64
|
||||||
|
u64 res;
|
||||||
|
if constexpr (IsSame<P, float>) {
|
||||||
|
asm("fcvtnu %0, %s1"
|
||||||
|
: "=r"(res), "w"(value));
|
||||||
|
} else if constexpr (IsSame<P, double>) {
|
||||||
|
asm("fcvtnu %0, %d1"
|
||||||
|
: "=r"(res), "w"(value));
|
||||||
|
} else if constexpr (IsSame<P, long double>) {
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
return static_cast<I>(res);
|
||||||
#else
|
#else
|
||||||
if constexpr (IsSame<P, long double>)
|
if constexpr (IsSame<P, long double>)
|
||||||
return static_cast<I>(__builtin_llrintl(value));
|
return static_cast<I>(__builtin_llrintl(value));
|
||||||
|
@ -676,10 +756,15 @@ constexpr T ceil(T num)
|
||||||
? static_cast<i64>(num)
|
? static_cast<i64>(num)
|
||||||
: static_cast<i64>(num) + ((num > 0) ? 1 : 0);
|
: static_cast<i64>(num) + ((num > 0) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
#if ARCH(AARCH64)
|
||||||
|
AARCH64_INSTRUCTION(frintp, num);
|
||||||
|
#else
|
||||||
return __builtin_ceil(num);
|
return __builtin_ceil(num);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef CONSTEXPR_STATE
|
#undef CONSTEXPR_STATE
|
||||||
|
#undef AARCH64_INSTRUCTION
|
||||||
}
|
}
|
||||||
|
|
||||||
using AK::round_to;
|
using AK::round_to;
|
||||||
|
|
Loading…
Reference in a new issue