Skip to content

Commit

Permalink
AK: Add support for some trivial math functions on aarch64
Browse files Browse the repository at this point in the history
These all require just a single instruction each, we only have to
differentiate between register prefixes accordingly.
  • Loading branch information
Hendiadyoin1 authored and linusg committed Oct 13, 2022
1 parent 650d2fd commit eb56518
Showing 1 changed file with 85 additions and 0 deletions.
85 changes: 85 additions & 0 deletions AK/Math.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,24 @@ constexpr size_t product_odd() { return value * product_odd<value - 2>(); }
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 {
template<FloatingPoint T>
constexpr T fmod(T x, T y)
Expand Down Expand Up @@ -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
Expand All @@ -118,6 +138,9 @@ constexpr T sqrt(T x)
template<FloatingPoint T>
constexpr T rsqrt(T x)
{
#if ARCH(AARCH64)
AARCH64_INSTRUCTION(frsqrte, x);
#endif
return (T)1. / sqrt(x);
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -581,6 +606,61 @@ ALWAYS_INLINE I round_to(P value)
: "st");
}
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
if constexpr (IsSame<P, long double>)
return static_cast<I>(__builtin_llrintl(value));
Expand Down Expand Up @@ -676,10 +756,15 @@ constexpr T ceil(T num)
? static_cast<i64>(num)
: static_cast<i64>(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;

0 comments on commit eb56518

Please sign in to comment.