The ACLE declares several helper types and functions to facilitate construction of `fpm` arguments.
gcc/ChangeLog: * config/aarch64/arm_acle.h (fpm_t): New type representing fpmr values. (enum __ARM_FPM_FORMAT): New enum representing valid fp8 formats. (enum __ARM_FPM_OVERFLOW): New enum representing how some fp8 calculations work. (arm_fpm_init): New. (arm_set_fpm_src1_format): Likewise. (arm_set_fpm_src2_format): Likewise. (arm_set_fpm_dst_format): Likewise. (arm_set_fpm_overflow_cvt): Likewise. (arm_set_fpm_overflow_mul): Likewise. (arm_set_fpm_lscale): Likewise. (arm_set_fpm_lscale2): Likewise. (arm_set_fpm_nscale): Likewise. gcc/testsuite/ChangeLog: * gcc.target/aarch64/acle/fp8-helpers.c: New test of fpmr helper functions. --- gcc/config/aarch64/arm_acle.h | 33 ++++++++++++ .../gcc.target/aarch64/acle/fp8-helpers.c | 52 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/fp8-helpers.c
diff --git a/gcc/config/aarch64/arm_acle.h b/gcc/config/aarch64/arm_acle.h index 2aa681090fa..fd4fa855b90 100644 --- a/gcc/config/aarch64/arm_acle.h +++ b/gcc/config/aarch64/arm_acle.h @@ -385,6 +385,39 @@ __rndrrs (uint64_t *__res) #pragma GCC pop_options +typedef uint64_t fpm_t; + +enum __ARM_FPM_FORMAT +{ + __ARM_FPM_E5M2, + __ARM_FPM_E4M3, +}; + +enum __ARM_FPM_OVERFLOW +{ + __ARM_FPM_INFNAN, + __ARM_FPM_SATURATE, +}; + +#define __arm_fpm_init() (0) + +#define __arm_set_fpm_src1_format(__fpm, __format) \ + ((__fpm & ~(uint64_t)0x7) | (__format & (uint64_t)0x7)) +#define __arm_set_fpm_src2_format(__fpm, __format) \ + ((__fpm & ~((uint64_t)0x7 << 3)) | ((__format & (uint64_t)0x7) << 3)) +#define __arm_set_fpm_dst_format(__fpm, __format) \ + ((__fpm & ~((uint64_t)0x7 << 6)) | ((__format & (uint64_t)0x7) << 6)) +#define __arm_set_fpm_overflow_cvt(__fpm, __behaviour) \ + ((__fpm & ~((uint64_t)0x1 << 15)) | ((__behaviour & (uint64_t)0x1) << 15)) +#define __arm_set_fpm_overflow_mul(__fpm, __behaviour) \ + ((__fpm & ~((uint64_t)0x1 << 14)) | ((__behaviour & (uint64_t)0x1) << 14)) +#define __arm_set_fpm_lscale(__fpm, __scale) \ + ((__fpm & ~((uint64_t)0x7f << 16)) | ((__scale & (uint64_t)0x7f) << 16)) +#define __arm_set_fpm_lscale2(__fpm, __scale) \ + ((__fpm & ~((uint64_t)0x3f << 32)) | ((__scale & (uint64_t)0x3f) << 32)) +#define __arm_set_fpm_nscale(__fpm, __scale) \ + ((__fpm & ~((uint64_t)0xff << 24)) | ((__scale & (uint64_t)0xff) << 24)) + #ifdef __cplusplus } #endif diff --git a/gcc/testsuite/gcc.target/aarch64/acle/fp8-helpers.c b/gcc/testsuite/gcc.target/aarch64/acle/fp8-helpers.c new file mode 100644 index 00000000000..e235c3621d1 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/fp8-helpers.c @@ -0,0 +1,52 @@ +/* Test the fp8 ACLE helper functions. */ +/* { dg-do compile } */ +/* { dg-options "-std=c90 -pedantic-errors -O1 -march=armv9.4-a+fp8" } */ + +#include <arm_acle.h> + +void +test_prepare_fpmr_sysreg () +{ + +#define _S_EQ(expr, expected) \ + _Static_assert (expr == expected, #expr " == " #expected) + + _S_EQ (__arm_fpm_init (), 0); + + /* Bits [2:0] */ + _S_EQ (__arm_set_fpm_src1_format (__arm_fpm_init (), __ARM_FPM_E5M2), 0); + _S_EQ (__arm_set_fpm_src1_format (__arm_fpm_init (), __ARM_FPM_E4M3), 0x1); + + /* Bits [5:3] */ + _S_EQ (__arm_set_fpm_src2_format (__arm_fpm_init (), __ARM_FPM_E5M2), 0); + _S_EQ (__arm_set_fpm_src2_format (__arm_fpm_init (), __ARM_FPM_E4M3), 0x8); + + /* Bits [8:6] */ + _S_EQ (__arm_set_fpm_dst_format (__arm_fpm_init (), __ARM_FPM_E5M2), 0); + _S_EQ (__arm_set_fpm_dst_format (__arm_fpm_init (), __ARM_FPM_E4M3), 0x40); + + /* Bit 14 */ + _S_EQ (__arm_set_fpm_overflow_mul (__arm_fpm_init (), __ARM_FPM_INFNAN), 0); + _S_EQ (__arm_set_fpm_overflow_mul (__arm_fpm_init (), __ARM_FPM_SATURATE), + 0x4000); + + /* Bit 15 */ + _S_EQ (__arm_set_fpm_overflow_cvt (__arm_fpm_init (), __ARM_FPM_INFNAN), 0); + _S_EQ (__arm_set_fpm_overflow_cvt (__arm_fpm_init (), __ARM_FPM_SATURATE), + 0x8000); + + /* Bits [22:16] */ + _S_EQ (__arm_set_fpm_lscale (__arm_fpm_init (), 0), 0); + _S_EQ (__arm_set_fpm_lscale (__arm_fpm_init (), 127), 0x7F0000); + + /* Bits [37:32] */ + _S_EQ (__arm_set_fpm_lscale2 (__arm_fpm_init (), 0), 0); + _S_EQ (__arm_set_fpm_lscale2 (__arm_fpm_init (), 63), 0x3F00000000); + + /* Bits [31:24] */ + _S_EQ (__arm_set_fpm_nscale (__arm_fpm_init (), 0), 0); + _S_EQ (__arm_set_fpm_nscale (__arm_fpm_init (), 127), 0x7F000000); + _S_EQ (__arm_set_fpm_nscale (__arm_fpm_init (), -128), 0x80000000); + +#undef _S_EQ +}