@@ -74,7 +74,8 @@
"wr8", "wr9", "wr10", "wr11", \
"wr12", "wr13", "wr14", "wr15", \
"wcgr0", "wcgr1", "wcgr2", "wcgr3", \
- "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0" \
+ "cc", "vfpcc", "sfp", "afp", "apsrq", "apsrge", "p0", \
+ "ra_auth_code" \
}
#endif
@@ -815,7 +815,8 @@ extern const int arm_arch_cde_coproc_bits[];
s16-s31 S VFP variable (aka d8-d15).
vfpcc Not a real register. Represents the VFP condition
code flags.
- vpr Used to represent MVE VPR predication. */
+ vpr Used to represent MVE VPR predication.
+ ra_auth_code Pseudo register to save PAC. */
/* The stack backtrace structure is as follows:
fp points to here: | save code pointer | [fp]
@@ -856,7 +857,7 @@ extern const int arm_arch_cde_coproc_bits[];
1,1,1,1,1,1,1,1, \
1,1,1,1, \
/* Specials. */ \
- 1,1,1,1,1,1,1 \
+ 1,1,1,1,1,1,1,1 \
}
/* 1 for registers not available across function calls.
@@ -886,7 +887,7 @@ extern const int arm_arch_cde_coproc_bits[];
1,1,1,1,1,1,1,1, \
1,1,1,1, \
/* Specials. */ \
- 1,1,1,1,1,1,1 \
+ 1,1,1,1,1,1,1,1 \
}
#ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
@@ -1062,10 +1063,10 @@ extern const int arm_arch_cde_coproc_bits[];
&& (LAST_VFP_REGNUM - (REGNUM) >= 2 * (N) - 1))
/* The number of hard registers is 16 ARM + 1 CC + 1 SFP + 1 AFP
- + 1 APSRQ + 1 APSRGE + 1 VPR. */
+ + 1 APSRQ + 1 APSRGE + 1 VPR + 1 Pseudo register to save PAC. */
/* Intel Wireless MMX Technology registers add 16 + 4 more. */
/* VFP (VFP3) adds 32 (64) + 1 VFPCC. */
-#define FIRST_PSEUDO_REGISTER 107
+#define FIRST_PSEUDO_REGISTER 108
#define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
@@ -1248,12 +1249,15 @@ extern int arm_regs_in_sequence[];
CC_REGNUM, VFPCC_REGNUM, \
FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM, \
SP_REGNUM, PC_REGNUM, APSRQ_REGNUM, \
- APSRGE_REGNUM, VPR_REGNUM \
+ APSRGE_REGNUM, VPR_REGNUM, RA_AUTH_CODE \
}
#define IS_VPR_REGNUM(REGNUM) \
((REGNUM) == VPR_REGNUM)
+#define IS_PAC_Pseudo_REGNUM(REGNUM) \
+ ((REGNUM) == RA_AUTH_CODE)
+
/* Use different register alloc ordering for Thumb. */
#define ADJUST_REG_ALLOC_ORDER arm_order_regs_for_local_alloc ()
@@ -1292,6 +1296,7 @@ enum reg_class
SFP_REG,
AFP_REG,
VPR_REG,
+ PAC_REG,
ALL_REGS,
LIM_REG_CLASSES
};
@@ -1321,6 +1326,7 @@ enum reg_class
"SFP_REG", \
"AFP_REG", \
"VPR_REG", \
+ "PAC_REG", \
"ALL_REGS" \
}
@@ -1349,6 +1355,7 @@ enum reg_class
{ 0x00000000, 0x00000000, 0x00000000, 0x00000040 }, /* SFP_REG */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000080 }, /* AFP_REG */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000400 }, /* VPR_REG. */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000800 }, /* PAC_REG. */ \
{ 0xFFFF7FFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000000F } /* ALL_REGS. */ \
}
@@ -22000,7 +22000,9 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
{
if (mask & (1 << i))
{
- reg = gen_rtx_REG (SImode, i);
+ rtx reg1 = reg = gen_rtx_REG (SImode, i);
+ if (arm_pac_enabled_for_curr_function_p () && i == IP_REGNUM)
+ reg1 = gen_rtx_REG (SImode, RA_AUTH_CODE);
XVECEXP (par, 0, 0)
= gen_rtx_SET (gen_frame_mem
@@ -22018,7 +22020,7 @@ emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
if (dwarf_regs_mask & (1 << i))
{
tmp = gen_rtx_SET (gen_frame_mem (SImode, stack_pointer_rtx),
- reg);
+ reg1);
RTX_FRAME_RELATED_P (tmp) = 1;
XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
}
@@ -23505,7 +23507,10 @@ arm_expand_prologue (void)
saved_regs += arm_save_coproc_regs ();
if (arm_pac_enabled_for_curr_function_p ())
- emit_multi_reg_push (1 << IP_REGNUM, 1 << IP_REGNUM);
+ {
+ insn = emit_multi_reg_push (1 << IP_REGNUM, 1 << IP_REGNUM);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
if (frame_pointer_needed && TARGET_ARM)
{
@@ -25435,6 +25440,9 @@ arm_regno_class (int regno)
if (IS_VPR_REGNUM (regno))
return VPR_REG;
+ if (IS_PAC_Pseudo_REGNUM (regno))
+ return PAC_REG;
+
if (TARGET_THUMB1)
{
if (regno == STACK_POINTER_REGNUM)
@@ -29429,6 +29437,9 @@ arm_dbx_register_number (unsigned int regno)
if (IS_IWMMXT_REGNUM (regno))
return 112 + regno - FIRST_IWMMXT_REGNUM;
+ if (IS_PAC_Pseudo_REGNUM (regno))
+ return 143;
+
return DWARF_FRAME_REGISTERS;
}
@@ -29550,6 +29561,11 @@ arm_unwind_emit_sequence (FILE * out_file, rtx p)
reg_size = 8;
fprintf (out_file, "\t.vsave {");
}
+ else if (IS_PAC_Pseudo_REGNUM (reg))
+ {
+ reg_size = 4;
+ fprintf (out_file, "\t.save {");
+ }
else
/* Unknown register type. */
gcc_unreachable ();
@@ -29579,6 +29595,8 @@ arm_unwind_emit_sequence (FILE * out_file, rtx p)
double precision register names. */
if (IS_VFP_REGNUM (reg))
asm_fprintf (out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2);
+ else if (IS_PAC_Pseudo_REGNUM (reg))
+ asm_fprintf (asm_out_file, "ra_auth_code");
else
asm_fprintf (out_file, "%r", reg);
@@ -30447,7 +30465,10 @@ arm_conditional_register_usage (void)
}
if (TARGET_HAVE_PACBTI)
- call_used_regs[IP_REGNUM] = 1;
+ {
+ call_used_regs[IP_REGNUM] = 1;
+ fixed_regs[RA_AUTH_CODE] = 0;
+ }
/* The Q and GE bits are only accessed via special ACLE patterns. */
CLEAR_HARD_REG_BIT (operand_reg_set, APSRQ_REGNUM);
@@ -42,6 +42,7 @@
(APSRQ_REGNUM 104) ; Q bit pseudo register
(APSRGE_REGNUM 105) ; GE bits pseudo register
(VPR_REGNUM 106) ; Vector Predication Register - MVE register.
+ (RA_AUTH_CODE 107) ; Pseudo register to save PAC.
]
)
;; 3rd operand to select_dominance_cc_mode
new file mode 100644
@@ -0,0 +1,31 @@
+/* Check that GCC does .save and .cfi_offset directives with RA_AUTH_CODE pseudo hard-register. */
+/* { dg-do compile } */
+/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mcpu=*" } } */
+/* { dg-options "-march=armv8.1-m.main -mbranch-protection=pac-ret+leaf -mthumb -mfloat-abi=softfp --save-temps -O2 -fasynchronous-unwind-tables -g" } */
+
+#include <stdio.h>
+#define ARM_UNWIND_INFO
+
+struct name {
+ int a;
+ char b;
+} list;
+
+void func (struct name list);
+
+int main()
+{
+ list.a = 10;
+ list.b = 'c';
+ func (list);
+ return 0;
+}
+
+void func (struct name list)
+{
+ printf ("list.d = %d\n", list.a);
+ printf ("list.b = %c\n", list.b);
+}
+
+/* { dg-final { scan-assembler "\.save \{ra_auth_code\}" } } */
+/* { dg-final { scan-assembler "\.cfi_offset 143, \-8" } } */