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
+}