Skip to content

Commit 88157c8

Browse files
author
Victor Do Nascimento
committed
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.
1 parent eac59af commit 88157c8

5 files changed

Lines changed: 80 additions & 11 deletions

File tree

gcc/config/aarch64/aarch64-builtins.cc

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -815,11 +815,13 @@ enum aarch64_builtins
815815
AARCH64_RSR64,
816816
AARCH64_RSRF,
817817
AARCH64_RSRF64,
818+
AARCH64_RSR128,
818819
AARCH64_WSR,
819820
AARCH64_WSRP,
820821
AARCH64_WSR64,
821822
AARCH64_WSRF,
822823
AARCH64_WSRF64,
824+
AARCH64_WSR128,
823825
AARCH64_BUILTIN_MAX
824826
};
825827

@@ -1842,6 +1844,10 @@ aarch64_init_rwsr_builtins (void)
18421844
= build_function_type_list (double_type_node, const_char_ptr_type, NULL);
18431845
AARCH64_INIT_RWSR_BUILTINS_DECL (RSRF64, rsrf64, fntype);
18441846

1847+
fntype
1848+
= build_function_type_list (uint128_type_node, const_char_ptr_type, NULL);
1849+
AARCH64_INIT_RWSR_BUILTINS_DECL (RSR128, rsr128, fntype);
1850+
18451851
fntype
18461852
= build_function_type_list (void_type_node, const_char_ptr_type,
18471853
uint32_type_node, NULL);
@@ -1867,6 +1873,12 @@ aarch64_init_rwsr_builtins (void)
18671873
= build_function_type_list (void_type_node, const_char_ptr_type,
18681874
double_type_node, NULL);
18691875
AARCH64_INIT_RWSR_BUILTINS_DECL (WSRF64, wsrf64, fntype);
1876+
1877+
fntype
1878+
= build_function_type_list (void_type_node, const_char_ptr_type,
1879+
uint128_type_node, NULL);
1880+
AARCH64_INIT_RWSR_BUILTINS_DECL (WSR128, wsr128, fntype);
1881+
18701882
}
18711883

18721884
/* Initialize the memory tagging extension (MTE) builtins. */
@@ -2710,6 +2722,7 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
27102722
tree arg0, arg1;
27112723
rtx const_str, input_val, subreg;
27122724
enum machine_mode mode;
2725+
enum insn_code icode;
27132726
class expand_operand ops[2];
27142727

27152728
arg0 = CALL_EXPR_ARG (exp, 0);
@@ -2718,7 +2731,18 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
27182731
|| fcode == AARCH64_WSRP
27192732
|| fcode == AARCH64_WSR64
27202733
|| fcode == AARCH64_WSRF
2721-
|| fcode == AARCH64_WSRF64);
2734+
|| fcode == AARCH64_WSRF64
2735+
|| fcode == AARCH64_WSR128);
2736+
2737+
bool op128 = (fcode == AARCH64_RSR128 || fcode == AARCH64_WSR128);
2738+
enum machine_mode sysreg_mode = op128 ? TImode : DImode;
2739+
2740+
if (op128 && !TARGET_D128)
2741+
{
2742+
error_at (EXPR_LOCATION (exp), "128-bit system register support requires"
2743+
" the %<d128%> extension");
2744+
return const0_rtx;
2745+
}
27222746

27232747
/* Argument 0 (system register name) must be a string literal. */
27242748
gcc_assert (TREE_CODE (arg0) == ADDR_EXPR
@@ -2740,7 +2764,8 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
27402764
for (unsigned pos = 0; pos <= len; pos++)
27412765
sysreg_name[pos] = TOLOWER (sysreg_name[pos]);
27422766

2743-
const char *name_output = aarch64_retrieve_sysreg (sysreg_name, write_op);
2767+
const char* name_output = aarch64_retrieve_sysreg ((const char *) sysreg_name,
2768+
write_op, op128);
27442769
if (name_output == NULL)
27452770
{
27462771
error_at (EXPR_LOCATION (exp), "invalid system register name %qs",
@@ -2760,13 +2785,17 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
27602785
mode = TYPE_MODE (TREE_TYPE (arg1));
27612786
input_val = copy_to_mode_reg (mode, expand_normal (arg1));
27622787

2788+
icode = (op128 ? CODE_FOR_aarch64_write_sysregti
2789+
: CODE_FOR_aarch64_write_sysregdi);
2790+
27632791
switch (fcode)
27642792
{
27652793
case AARCH64_WSR:
27662794
case AARCH64_WSRP:
27672795
case AARCH64_WSR64:
27682796
case AARCH64_WSRF64:
2769-
subreg = lowpart_subreg (DImode, input_val, mode);
2797+
case AARCH64_WSR128:
2798+
subreg = lowpart_subreg (sysreg_mode, input_val, mode);
27702799
break;
27712800
case AARCH64_WSRF:
27722801
subreg = gen_lowpart_SUBREG (SImode, input_val);
@@ -2775,19 +2804,22 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
27752804
}
27762805

27772806
create_fixed_operand (&ops[0], const_str);
2778-
create_input_operand (&ops[1], subreg, DImode);
2779-
expand_insn (CODE_FOR_aarch64_write_sysregdi, 2, ops);
2807+
create_input_operand (&ops[1], subreg, sysreg_mode);
2808+
expand_insn (icode, 2, ops);
27802809

27812810
return target;
27822811
}
27832812

27842813
/* Read operations are implied by !write_op. */
27852814
gcc_assert (call_expr_nargs (exp) == 1);
27862815

2816+
icode = (op128 ? CODE_FOR_aarch64_read_sysregti
2817+
: CODE_FOR_aarch64_read_sysregdi);
2818+
27872819
/* Emit the initial read_sysregdi rtx. */
2788-
create_output_operand (&ops[0], target, DImode);
2820+
create_output_operand (&ops[0], target, sysreg_mode);
27892821
create_fixed_operand (&ops[1], const_str);
2790-
expand_insn (CODE_FOR_aarch64_read_sysregdi, 2, ops);
2822+
expand_insn (icode, 2, ops);
27912823
target = ops[0].value;
27922824

27932825
/* Do any necessary post-processing on the result. */
@@ -2797,7 +2829,8 @@ aarch64_expand_rwsr_builtin (tree exp, rtx target, int fcode)
27972829
case AARCH64_RSRP:
27982830
case AARCH64_RSR64:
27992831
case AARCH64_RSRF64:
2800-
return lowpart_subreg (TYPE_MODE (TREE_TYPE (exp)), target, DImode);
2832+
case AARCH64_RSR128:
2833+
return lowpart_subreg (TYPE_MODE (TREE_TYPE (exp)), target, sysreg_mode);
28012834
case AARCH64_RSRF:
28022835
subreg = gen_lowpart_SUBREG (SImode, target);
28032836
return gen_lowpart_SUBREG (SFmode, subreg);
@@ -3044,11 +3077,13 @@ aarch64_general_expand_builtin (unsigned int fcode, tree exp, rtx target,
30443077
case AARCH64_RSR64:
30453078
case AARCH64_RSRF:
30463079
case AARCH64_RSRF64:
3080+
case AARCH64_RSR128:
30473081
case AARCH64_WSR:
30483082
case AARCH64_WSRP:
30493083
case AARCH64_WSR64:
30503084
case AARCH64_WSRF:
30513085
case AARCH64_WSRF64:
3086+
case AARCH64_WSR128:
30523087
return aarch64_expand_rwsr_builtin (exp, target, fcode);
30533088
}
30543089

gcc/config/aarch64/aarch64-protos.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ bool aarch64_sve_ptrue_svpattern_p (rtx, struct simd_immediate_info *);
840840
bool aarch64_simd_valid_immediate (rtx, struct simd_immediate_info *,
841841
enum simd_immediate_check w = AARCH64_CHECK_MOV);
842842
bool aarch64_valid_sysreg_name_p (const char *);
843-
const char *aarch64_retrieve_sysreg (const char *, bool);
843+
const char *aarch64_retrieve_sysreg (const char *, bool, bool);
844844
rtx aarch64_check_zero_based_sve_index_immediate (rtx);
845845
bool aarch64_maybe_generate_simd_constant (rtx, rtx, machine_mode);
846846
bool aarch64_simd_special_constant_p (rtx, machine_mode);

gcc/config/aarch64/aarch64.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,8 @@ typedef struct {
498498
#define F_ARCHEXT (1 << 4)
499499
/* Flag indicating register name is alias for another system register. */
500500
#define F_REG_ALIAS (1 << 5)
501+
/* Flag indicatinig registers which may be implemented with 128-bits. */
502+
#define F_REG_128 (1 << 6)
501503

502504
/* Database of system registers, their encodings and architectural
503505
requirements. */
@@ -29083,9 +29085,10 @@ aarch64_valid_sysreg_name_p (const char *regname)
2908329085

2908429086
/* Return the generic sysreg specification for a valid system register
2908529087
name, otherwise NULL. WRITE_P is true iff the register is being
29086-
written to. */
29088+
written to. IS128OP indicates the requested system register should
29089+
be checked for a 128-bit implementation. */
2908729090
const char *
29088-
aarch64_retrieve_sysreg (const char *regname, bool write_p)
29091+
aarch64_retrieve_sysreg (const char *regname, bool write_p, bool is128op)
2908929092
{
2909029093
const sysreg_t *sysreg = aarch64_lookup_sysreg_map (regname);
2909129094
if (sysreg == NULL)
@@ -29095,6 +29098,8 @@ aarch64_retrieve_sysreg (const char *regname, bool write_p)
2909529098
else
2909629099
return NULL;
2909729100
}
29101+
if (is128op && !(sysreg->properties & F_REG_128))
29102+
return NULL;
2909829103
if ((write_p && (sysreg->properties & F_REG_READ))
2909929104
|| (!write_p && (sysreg->properties & F_REG_WRITE)))
2910029105
return NULL;

gcc/config/aarch64/aarch64.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,9 @@
339339
UNSPEC_RDFFR
340340
UNSPEC_WRFFR
341341
UNSPEC_SYSREG_RDI
342+
UNSPEC_SYSREG_RTI
342343
UNSPEC_SYSREG_WDI
344+
UNSPEC_SYSREG_WTI
343345
;; Represents an SVE-style lane index, in which the indexing applies
344346
;; within the containing 128-bit block.
345347
UNSPEC_SVE_LANE_SELECT
@@ -558,6 +560,14 @@
558560
"mrs\t%x0, %1"
559561
)
560562

563+
(define_insn "aarch64_read_sysregti"
564+
[(set (match_operand:TI 0 "register_operand" "=r")
565+
(unspec_volatile:TI [(match_operand 1 "aarch64_sysreg_string" "")]
566+
UNSPEC_SYSREG_RTI))]
567+
"TARGET_D128"
568+
"mrrs\t%x0, %H0, %x1"
569+
)
570+
561571
(define_insn "aarch64_write_sysregdi"
562572
[(unspec_volatile:DI [(match_operand 0 "aarch64_sysreg_string" "")
563573
(match_operand:DI 1 "register_operand" "rZ")]
@@ -566,6 +576,14 @@
566576
"msr\t%0, %x1"
567577
)
568578

579+
(define_insn "aarch64_write_sysregti"
580+
[(unspec_volatile:TI [(match_operand 0 "aarch64_sysreg_string" "")
581+
(match_operand:TI 1 "register_operand" "r")]
582+
UNSPEC_SYSREG_WTI)]
583+
"TARGET_D128"
584+
"msrr\t%x0, %x1, %H1"
585+
)
586+
569587
(define_insn "indirect_jump"
570588
[(set (pc) (match_operand:DI 0 "register_operand" "r"))]
571589
""

gcc/config/aarch64/arm_acle.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,17 @@ __rndrrs (uint64_t *__res)
344344
#define __arm_wsrf64(__regname, __value) \
345345
__builtin_aarch64_wsrf64 (__regname, __value)
346346

347+
#pragma GCC push_options
348+
#pragma GCC target ("+nothing+d128")
349+
350+
#define __arm_rsr128(__regname) \
351+
__builtin_aarch64_rsr128 (__regname)
352+
353+
#define __arm_wsr128(__regname, __value) \
354+
__builtin_aarch64_wsr128 (__regname, __value)
355+
356+
#pragma GCC pop_options
357+
347358
#ifdef __cplusplus
348359
}
349360
#endif

0 commit comments

Comments
 (0)