Implement the aarch64 intrinsics for reading and writing system
registers with the following signatures:
uint32_t __arm_rsr(const char *special_register);
uint64_t __arm_rsr64(const char *special_register);
void* __arm_rsrp(const char *special_register);
float __arm_rsrf(const char *special_register);
double __arm_rsrf64(const char *special_register);
void __arm_wsr(const char *special_register, uint32_t value);
void __arm_wsr64(const char *special_register, uint64_t value);
void __arm_wsrp(const char *special_register, const void *value);
void __arm_wsrf(const char *special_register, float value);
void __arm_wsrf64(const char *special_register, double value);
gcc/ChangeLog:
* gcc/config/aarch64/aarch64-builtins.cc (enum aarch64_builtins):
Add enums for new builtins.
(aarch64_init_rwsr_builtins): New.
(aarch64_general_init_builtins): Call aarch64_init_rwsr_builtins.
(aarch64_expand_rwsr_builtin): New.
(aarch64_general_expand_builtin): Call aarch64_general_expand_builtin.
* gcc/config/aarch64/aarch64.md (read_sysregdi): New insn_and_split.
(write_sysregdi): Likewise.
* gcc/config/aarch64/arm_acle.h (__arm_rsr): New.
(__arm_rsrp): Likewise.
(__arm_rsr64): Likewise.
(__arm_rsrf): Likewise.
(__arm_rsrf64): Likewise.
(__arm_wsr): Likewise.
(__arm_wsrp): Likewise.
(__arm_wsr64): Likewise.
(__arm_wsrf): Likewise.
(__arm_wsrf64): Likewise.
gcc/testsuite/ChangeLog:
* gcc/testsuite/gcc.target/aarch64/acle/rwsr.c: New.
* gcc/testsuite/gcc.target/aarch64/acle/rwsr-1.c: Likewise.
---
gcc/config/aarch64/aarch64-builtins.cc | 200 ++++++++++++++++++
gcc/config/aarch64/aarch64.md | 17 ++
gcc/config/aarch64/arm_acle.h | 30 +++
.../gcc.target/aarch64/acle/rwsr-1.c | 20 ++
gcc/testsuite/gcc.target/aarch64/acle/rwsr.c | 144 +++++++++++++
5 files changed, 411 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/rwsr-1.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/rwsr.c
diff --git a/gcc/config/aarch64/aarch64-builtins.cc
b/gcc/config/aarch64/aarch64-builtins.cc
index 04f59fd9a54..d8bb2a989a5 100644
--- a/gcc/config/aarch64/aarch64-builtins.cc
+++ b/gcc/config/aarch64/aarch64-builtins.cc
@@ -808,6 +808,17 @@ enum aarch64_builtins
AARCH64_RBIT,
AARCH64_RBITL,
AARCH64_RBITLL,
+ /* System register builtins. */
+ AARCH64_RSR,
+ AARCH64_RSRP,
+ AARCH64_RSR64,
+ AARCH64_RSRF,
+ AARCH64_RSRF64,
+ AARCH64_WSR,
+ AARCH64_WSRP,
+ AARCH64_WSR64,
+ AARCH64_WSRF,
+ AARCH64_WSRF64,
AARCH64_BUILTIN_MAX
};
@@ -1798,6 +1809,65 @@ aarch64_init_rng_builtins (void)
AARCH64_BUILTIN_RNG_RNDRRS);
}
+/* Add builtins for reading system register. */
+static void
+aarch64_init_rwsr_builtins (void)
+{
+ tree fntype = NULL;
+ tree const_char_ptr_type
+ = build_pointer_type (build_type_variant (char_type_node, true, false));
+
+#define AARCH64_INIT_RWSR_BUILTINS_DECL(F, N, T) \
+ aarch64_builtin_decls[AARCH64_##F] \
+ = aarch64_general_add_builtin ("__builtin_aarch64_"#N, T, AARCH64_##F);
+
+ fntype
+ = build_function_type_list (uint32_type_node, const_char_ptr_type, NULL);
+ AARCH64_INIT_RWSR_BUILTINS_DECL (RSR, rsr, fntype);
+
+ fntype
+ = build_function_type_list (ptr_type_node, const_char_ptr_type, NULL);
+ AARCH64_INIT_RWSR_BUILTINS_DECL (RSRP, rsrp, fntype);
+
+ fntype
+ = build_function_type_list (uint64_type_node, const_char_ptr_type, NULL);
+ AARCH64_INIT_RWSR_BUILTINS_DECL (RSR64, rsr64, fntype);
+
+ fntype
+ = build_function_type_list (float_type_node, const_char_ptr_type, NULL);
+ AARCH64_INIT_RWSR_BUILTINS_DECL (RSRF, rsrf, fntype);
+
+ fntype
+ = build_function_type_list (double_type_node, const_char_ptr_type, NULL);
+ AARCH64_INIT_RWSR_BUILTINS_DECL (RSRF64, rsrf64, fntype);
+
+ fntype
+ = build_function_type_list (void_type_node, const_char_ptr_type,
+ uint32_type_node, NULL);
+
+ AARCH64_INIT_RWSR_BUILTINS_DECL (WSR, wsr, fntype);
+
+ fntype
+ = build_function_type_list (void_type_node, const_char_ptr_type,
+ const_ptr_type_node, NULL);
+ AARCH64_INIT_RWSR_BUILTINS_DECL (WSRP, wsrp, fntype);
+
+ fntype
+ = build_function_type_list (void_type_node, const_char_ptr_type,
+ uint64_type_node, NULL);
+ AARCH64_INIT_RWSR_BUILTINS_DECL (WSR64, wsr64, fntype);
+
+ fntype
+ = build_function_type_list (void_type_node, const_char_ptr_type,
+ float_type_node, NULL);
+ AARCH64_INIT_RWSR_BUILTINS_DECL (WSRF, wsrf, fntype);
+
+ fntype
+ = build_function_type_list (void_type_node, const_char_ptr_type,
+ double_type_node, NULL);
+ AARCH64_INIT_RWSR_BUILTINS_DECL (WSRF64, wsrf64, fntype);
+}
+
/* Initialize the memory tagging extension (MTE) builtins. */
struct
{
@@ -2019,6 +2089,8 @@ aarch64_general_init_builtins (void)
aarch64_init_rng_builtins ();
aarch64_init_data_intrinsics ();
+ aarch64_init_rwsr_builtins ();
+
tree ftype_jcvt
= build_function_type_list (intSI_type_node, double_type_node, NULL);
aarch64_builtin_decls[AARCH64_JSCVT]
@@ -2599,6 +2671,123 @@ aarch64_expand_rng_builtin (tree exp, rtx target, int
fcode, int ignore)
return target;
}
+/* Expand the read/write system register builtin EXPs. */
+rtx
+aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
+{
+ tree arg0, arg1;
+ rtx const_str, input_val, subreg;
+ enum machine_mode mode;
+ class expand_operand ops[2];
+
+ arg0 = CALL_EXPR_ARG (exp, 0);
+
+ bool write_op = (fcode == AARCH64_WSR
+ || fcode == AARCH64_WSRP
+ || fcode == AARCH64_WSR64
+ || fcode == AARCH64_WSRF
+ || fcode == AARCH64_WSRF64);
+ bool read_op = (fcode == AARCH64_RSR
+ || fcode == AARCH64_RSRP
+ || fcode == AARCH64_RSR64
+ || fcode == AARCH64_RSRF
+ || fcode == AARCH64_RSRF64);