aarch64: Implement 128-bit extension to ACLE sysreg r/w builtins

Implement the ACLE builtins for 128-bit system register manipulation:

  * __uint128_t __arm_rsr128(const char *special_register);
  * void __arm_wsr128(const char *special_register, __uint128_t value);

gcc/ChangeLog:

	* config/aarch64/aarch64-builtins.cc (AARCH64_RSR128): New
	`enum aarch64_builtins' value.
	(AARCH64_WSR128): Likewise.
	(aarch64_init_rwsr_builtins): Init `__builtin_aarch64_rsr128'
	and `__builtin_aarch64_wsr128' builtins.
	(aarch64_expand_rwsr_builtin): Extend function to handle
	`__builtin_aarch64_{rsr|wsr}128'.
	* config/aarch64/aarch64-protos.h (aarch64_retrieve_sysreg):
	Update function signature.
	* config/aarch64/aarch64.cc (F_REG_128): New.
	(aarch64_retrieve_sysreg): Add 128-bit register mode check.
	* config/aarch64/aarch64.md (UNSPEC_SYSREG_RTI): New.
	(UNSPEC_SYSREG_WTI): Likewise.
	(aarch64_read_sysregti): Likewise.
	(aarch64_write_sysregti): Likewise.
	* config/aarch64/arm_acle.h (__arm_rsr128): New.
	(__arm_wsr128): Likewise.
This commit is contained in:
Victor Do Nascimento 2023-10-29 00:38:59 +01:00
parent eac59af05a
commit 88157c8817
5 changed files with 80 additions and 11 deletions

View file

@ -815,11 +815,13 @@ enum aarch64_builtins
AARCH64_RSR64,
AARCH64_RSRF,
AARCH64_RSRF64,
AARCH64_RSR128,
AARCH64_WSR,
AARCH64_WSRP,
AARCH64_WSR64,
AARCH64_WSRF,
AARCH64_WSRF64,
AARCH64_WSR128,
AARCH64_BUILTIN_MAX
};
@ -1842,6 +1844,10 @@ aarch64_init_rwsr_builtins (void)
= 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 (uint128_type_node, const_char_ptr_type, NULL);
AARCH64_INIT_RWSR_BUILTINS_DECL (RSR128, rsr128, fntype);
fntype
= build_function_type_list (void_type_node, const_char_ptr_type,
uint32_type_node, NULL);
@ -1867,6 +1873,12 @@ aarch64_init_rwsr_builtins (void)
= build_function_type_list (void_type_node, const_char_ptr_type,
double_type_node, NULL);
AARCH64_INIT_RWSR_BUILTINS_DECL (WSRF64, wsrf64, fntype);
fntype
= build_function_type_list (void_type_node, const_char_ptr_type,
uint128_type_node, NULL);
AARCH64_INIT_RWSR_BUILTINS_DECL (WSR128, wsr128, fntype);
}
/* Initialize the memory tagging extension (MTE) builtins. */
@ -2710,6 +2722,7 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
tree arg0, arg1;
rtx const_str, input_val, subreg;
enum machine_mode mode;
enum insn_code icode;
class expand_operand ops[2];
arg0 = CALL_EXPR_ARG (exp, 0);
@ -2718,7 +2731,18 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
|| fcode == AARCH64_WSRP
|| fcode == AARCH64_WSR64
|| fcode == AARCH64_WSRF
|| fcode == AARCH64_WSRF64);
|| fcode == AARCH64_WSRF64
|| fcode == AARCH64_WSR128);
bool op128 = (fcode == AARCH64_RSR128 || fcode == AARCH64_WSR128);
enum machine_mode sysreg_mode = op128 ? TImode : DImode;
if (op128 && !TARGET_D128)
{
error_at (EXPR_LOCATION (exp), "128-bit system register support requires"
" the %<d128%> extension");
return const0_rtx;
}
/* Argument 0 (system register name) must be a string literal. */
gcc_assert (TREE_CODE (arg0) == ADDR_EXPR
@ -2740,7 +2764,8 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
for (unsigned pos = 0; pos <= len; pos++)
sysreg_name[pos] = TOLOWER (sysreg_name[pos]);
const char *name_output = aarch64_retrieve_sysreg (sysreg_name, write_op);
const char* name_output = aarch64_retrieve_sysreg ((const char *) sysreg_name,
write_op, op128);
if (name_output == NULL)
{
error_at (EXPR_LOCATION (exp), "invalid system register name %qs",
@ -2760,13 +2785,17 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
mode = TYPE_MODE (TREE_TYPE (arg1));
input_val = copy_to_mode_reg (mode, expand_normal (arg1));
icode = (op128 ? CODE_FOR_aarch64_write_sysregti
: CODE_FOR_aarch64_write_sysregdi);
switch (fcode)
{
case AARCH64_WSR:
case AARCH64_WSRP:
case AARCH64_WSR64:
case AARCH64_WSRF64:
subreg = lowpart_subreg (DImode, input_val, mode);
case AARCH64_WSR128:
subreg = lowpart_subreg (sysreg_mode, input_val, mode);
break;
case AARCH64_WSRF:
subreg = gen_lowpart_SUBREG (SImode, input_val);
@ -2775,8 +2804,8 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
}
create_fixed_operand (&ops[0], const_str);
create_input_operand (&ops[1], subreg, DImode);
expand_insn (CODE_FOR_aarch64_write_sysregdi, 2, ops);
create_input_operand (&ops[1], subreg, sysreg_mode);
expand_insn (icode, 2, ops);
return target;
}
@ -2784,10 +2813,13 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
/* Read operations are implied by !write_op. */
gcc_assert (call_expr_nargs (exp) == 1);
icode = (op128 ? CODE_FOR_aarch64_read_sysregti
: CODE_FOR_aarch64_read_sysregdi);
/* Emit the initial read_sysregdi rtx. */
create_output_operand (&ops[0], target, DImode);
create_output_operand (&ops[0], target, sysreg_mode);
create_fixed_operand (&ops[1], const_str);
expand_insn (CODE_FOR_aarch64_read_sysregdi, 2, ops);
expand_insn (icode, 2, ops);
target = ops[0].value;
/* Do any necessary post-processing on the result. */
@ -2797,7 +2829,8 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
case AARCH64_RSRP:
case AARCH64_RSR64:
case AARCH64_RSRF64:
return lowpart_subreg (TYPE_MODE (TREE_TYPE (exp)), target, DImode);
case AARCH64_RSR128:
return lowpart_subreg (TYPE_MODE (TREE_TYPE (exp)), target, sysreg_mode);
case AARCH64_RSRF:
subreg = gen_lowpart_SUBREG (SImode, target);
return gen_lowpart_SUBREG (SFmode, subreg);
@ -3044,11 +3077,13 @@ aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,
case AARCH64_RSR64:
case AARCH64_RSRF:
case AARCH64_RSRF64:
case AARCH64_RSR128:
case AARCH64_WSR:
case AARCH64_WSRP:
case AARCH64_WSR64:
case AARCH64_WSRF:
case AARCH64_WSRF64:
case AARCH64_WSR128:
return aarch64_expand_rwsr_builtin (exp, target, fcode);
}

View file

@ -840,7 +840,7 @@ bool aarch64_sve_ptrue_svpattern_p (rtx, struct simd_immediate_info *);
bool aarch64_simd_valid_immediate (rtx, struct simd_immediate_info *,
enum simd_immediate_check w = AARCH64_CHECK_MOV);
bool aarch64_valid_sysreg_name_p (const char *);
const char *aarch64_retrieve_sysreg (const char *, bool);
const char *aarch64_retrieve_sysreg (const char *, bool, bool);
rtx aarch64_check_zero_based_sve_index_immediate (rtx);
bool aarch64_maybe_generate_simd_constant (rtx, rtx, machine_mode);
bool aarch64_simd_special_constant_p (rtx, machine_mode);

View file

@ -498,6 +498,8 @@ typedef struct {
#define F_ARCHEXT (1 << 4)
/* Flag indicating register name is alias for another system register. */
#define F_REG_ALIAS (1 << 5)
/* Flag indicatinig registers which may be implemented with 128-bits. */
#define F_REG_128 (1 << 6)
/* Database of system registers, their encodings and architectural
requirements. */
@ -29083,9 +29085,10 @@ aarch64_valid_sysreg_name_p (const char *regname)
/* Return the generic sysreg specification for a valid system register
name, otherwise NULL. WRITE_P is true iff the register is being
written to. */
written to. IS128OP indicates the requested system register should
be checked for a 128-bit implementation. */
const char *
aarch64_retrieve_sysreg (const char *regname, bool write_p)
aarch64_retrieve_sysreg (const char *regname, bool write_p, bool is128op)
{
const sysreg_t *sysreg = aarch64_lookup_sysreg_map (regname);
if (sysreg == NULL)
@ -29095,6 +29098,8 @@ aarch64_retrieve_sysreg (const char *regname, bool write_p)
else
return NULL;
}
if (is128op && !(sysreg->properties & F_REG_128))
return NULL;
if ((write_p && (sysreg->properties & F_REG_READ))
|| (!write_p && (sysreg->properties & F_REG_WRITE)))
return NULL;

View file

@ -339,7 +339,9 @@
UNSPEC_RDFFR
UNSPEC_WRFFR
UNSPEC_SYSREG_RDI
UNSPEC_SYSREG_RTI
UNSPEC_SYSREG_WDI
UNSPEC_SYSREG_WTI
;; Represents an SVE-style lane index, in which the indexing applies
;; within the containing 128-bit block.
UNSPEC_SVE_LANE_SELECT
@ -558,6 +560,14 @@
"mrs\t%x0, %1"
)
(define_insn "aarch64_read_sysregti"
[(set (match_operand:TI 0 "register_operand" "=r")
(unspec_volatile:TI [(match_operand 1 "aarch64_sysreg_string" "")]
UNSPEC_SYSREG_RTI))]
"TARGET_D128"
"mrrs\t%x0, %H0, %x1"
)
(define_insn "aarch64_write_sysregdi"
[(unspec_volatile:DI [(match_operand 0 "aarch64_sysreg_string" "")
(match_operand:DI 1 "register_operand" "rZ")]
@ -566,6 +576,14 @@
"msr\t%0, %x1"
)
(define_insn "aarch64_write_sysregti"
[(unspec_volatile:TI [(match_operand 0 "aarch64_sysreg_string" "")
(match_operand:TI 1 "register_operand" "r")]
UNSPEC_SYSREG_WTI)]
"TARGET_D128"
"msrr\t%x0, %x1, %H1"
)
(define_insn "indirect_jump"
[(set (pc) (match_operand:DI 0 "register_operand" "r"))]
""

View file

@ -344,6 +344,17 @@ __rndrrs (uint64_t *__res)
#define __arm_wsrf64(__regname, __value) \
__builtin_aarch64_wsrf64 (__regname, __value)
#pragma GCC push_options
#pragma GCC target ("+nothing+d128")
#define __arm_rsr128(__regname) \
__builtin_aarch64_rsr128 (__regname)
#define __arm_wsr128(__regname, __value) \
__builtin_aarch64_wsr128 (__regname, __value)
#pragma GCC pop_options
#ifdef __cplusplus
}
#endif