public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH][Binutils][GAS] arm: Add unwind support for mixed register lists
@ 2022-05-04 10:41 Victor Do Nascimento
  2022-05-18 15:31 ` Nick Clifton
  0 siblings, 1 reply; 4+ messages in thread
From: Victor Do Nascimento @ 2022-05-04 10:41 UTC (permalink / raw)
  To: binutils

Hi,

This patch extends support for the encoding of the Return Address Authentication pseudo-register in lists containing other register types - e.g. '.save {r4,ra_auth_code,lr}'.
Lists are broken down into sub-lists allowing assembler to emit the correct new pacbti unwind opcode for the RA_AUTH_CODE pseudo register.

Tested for arm-none-eabi.

Thanks,
Victor.

gas/Changelog:

	* testsuite/gas/arm/unwind-pacbti-m.s: Expand test for mixed
 	register type lists.
 	* testsuite/gas/arm/unwind-pacbti-m.d: Likewise.
	* testsuite/gas/arm/unwind-pacbti-m-readelf.d: Likewise.
	* config/tc-arm.c (parse_reg_list): Add handling of mixed register types.
	(reg_names): Enumerate pseudoregister according to mapped physical
    register number.
	(s_arm_unwind_save_pseudo): Modify function signature.
	(s_arm_unwind_save_core): Likewise.
	(s_arm_unwind_save_mixed): New function.
	(s_arm_unwind_save): Generate register list mask to pass to nested
    functions.
---
 gas/config/tc-arm.c                           | 117 +++++++++++++-----
 .../gas/arm/unwind-pacbti-m-readelf.d         |  12 +-
 gas/testsuite/gas/arm/unwind-pacbti-m.d       |  14 ++-
 gas/testsuite/gas/arm/unwind-pacbti-m.s       |   6 +
 4 files changed, 107 insertions(+), 42 deletions(-)

diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index ca4f97b164ae8b0196e1830dc49e4927f8ea2480..8873269d76a482352c69d2d40a248549e7d6ba90 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -1942,6 +1942,22 @@ parse_reg_list (char ** strp, enum reg_list_els etype)
 		rt = REG_TYPE_PSEUDO;
 
 	      reg = arm_reg_parse (&str, rt);
+
+	      /* Skip over allowed registers of alternative types in mixed-type
+	         register lists.  */
+	      if (reg == FAIL && rt == REG_TYPE_PSEUDO
+		  && ((reg = arm_reg_parse (&str, REG_TYPE_RN)) != FAIL))
+		{
+		  cur_reg = reg;
+		  continue;
+		}
+	      else if (reg == FAIL && rt == REG_TYPE_RN
+		       && ((reg = arm_reg_parse (&str, REG_TYPE_PSEUDO)) != FAIL))
+		{
+		  cur_reg = reg;
+		  continue;
+		}
+
 	      if (etype == REGLIST_CLRM)
 		{
 		  if (reg == REG_SP || reg == REG_PC)
@@ -4281,22 +4297,11 @@ s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
 /* Parse a directive saving pseudo registers.  */
 
 static void
-s_arm_unwind_save_pseudo (void)
+s_arm_unwind_save_pseudo (long range)
 {
   valueT op;
-  long range;
-
-  range = parse_reg_list (&input_line_pointer, REGLIST_PSEUDO);
-  if (range == FAIL)
-    {
-      as_bad (_("expected pseudo register list"));
-      ignore_rest_of_line ();
-      return;
-    }
-
-  demand_empty_rest_of_line ();
 
-  if (range & (1 << 9))
+  if (range & (1 << 12))
     {
       /* Opcode for restoring RA_AUTH_CODE.  */
       op = 0xb4;
@@ -4308,22 +4313,11 @@ s_arm_unwind_save_pseudo (void)
 /* Parse a directive saving core registers.  */
 
 static void
-s_arm_unwind_save_core (void)
+s_arm_unwind_save_core (long range)
 {
   valueT op;
-  long range;
   int n;
 
-  range = parse_reg_list (&input_line_pointer, REGLIST_RN);
-  if (range == FAIL)
-    {
-      as_bad (_("expected register list"));
-      ignore_rest_of_line ();
-      return;
-    }
-
-  demand_empty_rest_of_line ();
-
   /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
      into .unwind_save {..., sp...}.  We aren't bothered about the value of
      ip because it is clobbered by calls.  */
@@ -4722,6 +4716,40 @@ s_arm_unwind_save_mmxwcg (void)
   ignore_rest_of_line ();
 }
 
+static void
+s_arm_unwind_save_mixed (long range, long mask_range)
+{
+  const long roof = ((sizeof (long) * CHAR_BIT) - 1)
+    - __builtin_clzl (mask_range);
+
+  long subrange = 0;
+  unsigned lim_lo = 0;
+  unsigned lim_hi = 0;
+
+  /* Iterate over pseudoregister to establish subrange bounds.  */
+  for (; lim_hi <= roof; lim_hi++)
+    {
+      if (mask_range & (1 << lim_hi))
+	{
+	  /* Once we know where to split our range, construct subrange.  */
+	  for (unsigned n = lim_lo; n < lim_hi; n++)
+	    {
+	      if (range & (1 << n))
+		subrange |= (1 << n);
+	    }
+
+	  s_arm_unwind_save_core (subrange);
+	  s_arm_unwind_save_pseudo (1 << lim_hi);
+
+	  subrange = 0;
+	  lim_lo = lim_hi + 1;
+	}
+    }
+
+  lim_lo = 0xffff << roof;
+  subrange = range & lim_lo;
+  s_arm_unwind_save_core (subrange);
+}
 
 /* Parse an unwind_save directive.
    If the argument is non-zero, this is a .vsave directive.  */
@@ -4729,7 +4757,8 @@ s_arm_unwind_save_mmxwcg (void)
 static void
 s_arm_unwind_save (int arch_v6)
 {
-  char *peek;
+  char *peek, *mask_peek;
+  long range, mask_range;
   struct reg_entry *reg;
   bool had_brace = false;
 
@@ -4737,7 +4766,7 @@ s_arm_unwind_save (int arch_v6)
     as_bad (MISSING_FNSTART);
 
   /* Figure out what sort of save we have.  */
-  peek = input_line_pointer;
+  peek = mask_peek = input_line_pointer;
 
   if (*peek == '{')
     {
@@ -4767,13 +4796,35 @@ s_arm_unwind_save (int arch_v6)
       s_arm_unwind_save_fpa (reg->number);
       return;
 
+    case REG_TYPE_PSEUDO:
     case REG_TYPE_RN:
-      s_arm_unwind_save_core ();
-      return;
+      mask_range = parse_reg_list (&mask_peek, REGLIST_PSEUDO);
+      range = parse_reg_list (&input_line_pointer, REGLIST_RN);
 
-    case REG_TYPE_PSEUDO:
-      s_arm_unwind_save_pseudo ();
-      return;
+      if (range == FAIL || mask_range == FAIL)
+	{
+	  as_bad (_("expected register list"));
+	  ignore_rest_of_line ();
+	  return;
+	}
+
+      demand_empty_rest_of_line ();
+
+      if (!mask_range)
+	{
+	  s_arm_unwind_save_core (range);
+	  return;
+	}
+      else if (!range)
+	{
+	  s_arm_unwind_save_pseudo (mask_range);
+	  return;
+	}
+      else
+	{
+	  s_arm_unwind_save_mixed (range, mask_range);
+	  return;
+	}
 
     case REG_TYPE_VFD:
       if (arch_v6)
@@ -23976,7 +24027,7 @@ static const struct reg_entry reg_names[] =
      for tc_arm_regname_to_dw2regnum to translate to DWARF reg number using
      134 + reg_number should the range 134 to 142 be used for more pseudo regs
      in the future.  This also helps fit RA_AUTH_CODE into a bitmask.  */
-  REGDEF(ra_auth_code,9,PSEUDO),
+  REGDEF(ra_auth_code,12,PSEUDO),
 };
 #undef REGDEF
 #undef REGNUM
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d b/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
index ba1d76dd18fbe0ca2c391c12ddcb180d1de3b32b..d8d647bb7f0d943ceeec47e2f4fc8d34bb0ea057 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
@@ -6,11 +6,15 @@
 # VxWorks needs a special variant of this file.
 #skip: *-*-vxworks*
 
-Unwind section '.ARM.exidx' at offset 0x40 contains 1 entry:
+Unwind section '.ARM.exidx' at offset 0x60 contains 1 entry:
 
-0x0 <foo>: 0x80b4a8b0
-  Compact model index: 0
+0x0 <foo>: @0x0
+  Compact model index: 1
+  0x84 0x00 pop {r14}
+  0xb4      pop {ra_auth_code}
+  0x84 0x00 pop {r14}
+  0xb4      pop {ra_auth_code}
+  0xa3      pop {r4, r5, r6, r7}
   0xb4      pop {ra_auth_code}
   0xa8      pop {r4, r14}
   0xb0      finish
-
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m.d b/gas/testsuite/gas/arm/unwind-pacbti-m.d
index 28021758a7487097689ef4c44cc25546ccac5221..06cb3145e4254b34c2d95616d7ea20506af3a42a 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m.d
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m.d
@@ -8,16 +8,20 @@
 .*:     file format.*
 
 RELOCATION RECORDS FOR \[.ARM.exidx\]:
-OFFSET   TYPE              VALUE 
+OFFSET   TYPE              VALUE.
 00000000 R_ARM_PREL31      .text
-00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr0
+00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr1
+00000004 R_ARM_PREL31      .ARM.extab
 
 
 Contents of section .text:
- 0000 (10b54df8 04cd5df8 04cb10bd|b510f84d cd04f85d cb04bd10)  .*
+ 0000 (10b54df8 04cd5df8 04cb2de9 f050bde8|e8bd50f0 e92dcb04 f85dcd04 f84db510)  .*
+ 0010 (f0502de9 0050bde8 005010bd|bd105000 e8bd5000 e92d50f0)  .*
+Contents of section .ARM.extab:
+ 0000 (00840281 b40084b4 b0a8b4a3|a3b4a8b0 b48400b4 81028400) 00000000  .*
 Contents of section .ARM.exidx:
- 0000 00000000 (b0a8b480|80b4a8b0)  .*
+ 0000 00000000 00000000  .*
 Contents of section .ARM.attributes:
  0000 41(290000 00|000000 29)616561 62690001 (1f000000|0000001f)  .*
  0010 05382e31 2d4d2e4d 41494e00 0615074d  .*
- 0020 09033202 34024a01 4c01               .*
+ 0020 09033202 34024a01 4c01  .*
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m.s b/gas/testsuite/gas/arm/unwind-pacbti-m.s
index 5a6ea2eec2b8e48dd49963f0a4b93fa29c3c3a49..37202293133e95f7e94490aaa1729afb30a0afe7 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m.s
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m.s
@@ -16,5 +16,11 @@ foo:
 	push	{r12}
 	.save {ra_auth_code}
 	pop	{r12}
+	push	{r4-r7, ip, lr}
+	.save {r4-r7, ra_auth_code, lr}
+	pop	{r4-r7, ip, lr}
+	push	{ip, lr}
+	.save {ra_auth_code, lr}
+	pop {ip, lr}
 	pop	{r4, pc}
 	.fnend
-- 
2.17.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH][Binutils][GAS] arm: Add unwind support for mixed register lists
  2022-05-04 10:41 [PATCH][Binutils][GAS] arm: Add unwind support for mixed register lists Victor Do Nascimento
@ 2022-05-18 15:31 ` Nick Clifton
  0 siblings, 0 replies; 4+ messages in thread
From: Nick Clifton @ 2022-05-18 15:31 UTC (permalink / raw)
  To: Victor Do Nascimento, binutils

Hi Victor,

> This patch extends support for the encoding of the Return Address Authentication pseudo-register in lists containing other register types - e.g. '.save {r4,ra_auth_code,lr}'.
> Lists are broken down into sub-lists allowing assembler to emit the correct new pacbti unwind opcode for the RA_AUTH_CODE pseudo register.

Patch approved and applied.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH][Binutils][GAS] arm: Add unwind support for mixed register lists
  2022-05-05 11:07 Srinath Parvathaneni
@ 2022-05-05 11:36 ` Srinath Parvathaneni
  0 siblings, 0 replies; 4+ messages in thread
From: Srinath Parvathaneni @ 2022-05-05 11:36 UTC (permalink / raw)
  To: binutils, Srinath Parvathaneni; +Cc: Richard Earnshaw, Victor Do Nascimento

Hi All,

The patch in the trailing email is @Victor Do Nascimento<mailto:Victor.DoNascimento@arm.com>'s patch which was already posted here (https://sourceware.org/pipermail/binutils/2022-May/120672.html ) and I have re-send it the mailing list by mistake, please ignore it.

Apologies @Victor Do Nascimento<mailto:Victor.DoNascimento@arm.com>.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH][Binutils][GAS] arm: Add unwind support for mixed register lists
@ 2022-05-05 11:07 Srinath Parvathaneni
  2022-05-05 11:36 ` Srinath Parvathaneni
  0 siblings, 1 reply; 4+ messages in thread
From: Srinath Parvathaneni @ 2022-05-05 11:07 UTC (permalink / raw)
  To: binutils; +Cc: Richard.Earnshaw, nickc, kyrylo.tkachov

[-- Attachment #1: Type: text/plain, Size: 8638 bytes --]

Hi,

This patch extends support for the encoding of the Return Address Authentication pseudo-register in lists containing other register types - e.g. '.save {r4,ra_auth_code,lr}'.
Lists are broken down into sub-lists allowing assembler to emit the correct new pacbti unwind opcode for the RA_AUTH_CODE pseudo register.

Tested for arm-none-eabi.

Thanks,
Victor.

gas/Changelog:

    * testsuite/gas/arm/unwind-pacbti-m.s: Expand test for mixed
    register type lists.
    * testsuite/gas/arm/unwind-pacbti-m.d: Likewise.
    * testsuite/gas/arm/unwind-pacbti-m-readelf.d: Likewise.
    * config/tc-arm.c (parse_reg_list): Add handling of mixed register types.
    (reg_names): Enumerate pseudoregister according to mapped physical
    register number.
    (s_arm_unwind_save_pseudo): Modify function signature.
    (s_arm_unwind_save_core): Likewise.
    (s_arm_unwind_save_mixed): New function.
    (s_arm_unwind_save): Generate register list mask to pass to nested
    functions.


###############     Attachment also inlined for ease of reply    ###############


diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index ca4f97b164ae8b0196e1830dc49e4927f8ea2480..8873269d76a482352c69d2d40a248549e7d6ba90 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -1942,6 +1942,22 @@ parse_reg_list (char ** strp, enum reg_list_els etype)
 		rt = REG_TYPE_PSEUDO;
 
 	      reg = arm_reg_parse (&str, rt);
+
+	      /* Skip over allowed registers of alternative types in mixed-type
+	         register lists.  */
+	      if (reg == FAIL && rt == REG_TYPE_PSEUDO
+		  && ((reg = arm_reg_parse (&str, REG_TYPE_RN)) != FAIL))
+		{
+		  cur_reg = reg;
+		  continue;
+		}
+	      else if (reg == FAIL && rt == REG_TYPE_RN
+		       && ((reg = arm_reg_parse (&str, REG_TYPE_PSEUDO)) != FAIL))
+		{
+		  cur_reg = reg;
+		  continue;
+		}
+
 	      if (etype == REGLIST_CLRM)
 		{
 		  if (reg == REG_SP || reg == REG_PC)
@@ -4281,22 +4297,11 @@ s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
 /* Parse a directive saving pseudo registers.  */
 
 static void
-s_arm_unwind_save_pseudo (void)
+s_arm_unwind_save_pseudo (long range)
 {
   valueT op;
-  long range;
-
-  range = parse_reg_list (&input_line_pointer, REGLIST_PSEUDO);
-  if (range == FAIL)
-    {
-      as_bad (_("expected pseudo register list"));
-      ignore_rest_of_line ();
-      return;
-    }
-
-  demand_empty_rest_of_line ();
 
-  if (range & (1 << 9))
+  if (range & (1 << 12))
     {
       /* Opcode for restoring RA_AUTH_CODE.  */
       op = 0xb4;
@@ -4308,22 +4313,11 @@ s_arm_unwind_save_pseudo (void)
 /* Parse a directive saving core registers.  */
 
 static void
-s_arm_unwind_save_core (void)
+s_arm_unwind_save_core (long range)
 {
   valueT op;
-  long range;
   int n;
 
-  range = parse_reg_list (&input_line_pointer, REGLIST_RN);
-  if (range == FAIL)
-    {
-      as_bad (_("expected register list"));
-      ignore_rest_of_line ();
-      return;
-    }
-
-  demand_empty_rest_of_line ();
-
   /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
      into .unwind_save {..., sp...}.  We aren't bothered about the value of
      ip because it is clobbered by calls.  */
@@ -4722,6 +4716,40 @@ s_arm_unwind_save_mmxwcg (void)
   ignore_rest_of_line ();
 }
 
+static void
+s_arm_unwind_save_mixed (long range, long mask_range)
+{
+  const long roof = ((sizeof (long) * CHAR_BIT) - 1)
+    - __builtin_clzl (mask_range);
+
+  long subrange = 0;
+  unsigned lim_lo = 0;
+  unsigned lim_hi = 0;
+
+  /* Iterate over pseudoregister to establish subrange bounds.  */
+  for (; lim_hi <= roof; lim_hi++)
+    {
+      if (mask_range & (1 << lim_hi))
+	{
+	  /* Once we know where to split our range, construct subrange.  */
+	  for (unsigned n = lim_lo; n < lim_hi; n++)
+	    {
+	      if (range & (1 << n))
+		subrange |= (1 << n);
+	    }
+
+	  s_arm_unwind_save_core (subrange);
+	  s_arm_unwind_save_pseudo (1 << lim_hi);
+
+	  subrange = 0;
+	  lim_lo = lim_hi + 1;
+	}
+    }
+
+  lim_lo = 0xffff << roof;
+  subrange = range & lim_lo;
+  s_arm_unwind_save_core (subrange);
+}
 
 /* Parse an unwind_save directive.
    If the argument is non-zero, this is a .vsave directive.  */
@@ -4729,7 +4757,8 @@ s_arm_unwind_save_mmxwcg (void)
 static void
 s_arm_unwind_save (int arch_v6)
 {
-  char *peek;
+  char *peek, *mask_peek;
+  long range, mask_range;
   struct reg_entry *reg;
   bool had_brace = false;
 
@@ -4737,7 +4766,7 @@ s_arm_unwind_save (int arch_v6)
     as_bad (MISSING_FNSTART);
 
   /* Figure out what sort of save we have.  */
-  peek = input_line_pointer;
+  peek = mask_peek = input_line_pointer;
 
   if (*peek == '{')
     {
@@ -4767,13 +4796,35 @@ s_arm_unwind_save (int arch_v6)
       s_arm_unwind_save_fpa (reg->number);
       return;
 
+    case REG_TYPE_PSEUDO:
     case REG_TYPE_RN:
-      s_arm_unwind_save_core ();
-      return;
+      mask_range = parse_reg_list (&mask_peek, REGLIST_PSEUDO);
+      range = parse_reg_list (&input_line_pointer, REGLIST_RN);
 
-    case REG_TYPE_PSEUDO:
-      s_arm_unwind_save_pseudo ();
-      return;
+      if (range == FAIL || mask_range == FAIL)
+	{
+	  as_bad (_("expected register list"));
+	  ignore_rest_of_line ();
+	  return;
+	}
+
+      demand_empty_rest_of_line ();
+
+      if (!mask_range)
+	{
+	  s_arm_unwind_save_core (range);
+	  return;
+	}
+      else if (!range)
+	{
+	  s_arm_unwind_save_pseudo (mask_range);
+	  return;
+	}
+      else
+	{
+	  s_arm_unwind_save_mixed (range, mask_range);
+	  return;
+	}
 
     case REG_TYPE_VFD:
       if (arch_v6)
@@ -23976,7 +24027,7 @@ static const struct reg_entry reg_names[] =
      for tc_arm_regname_to_dw2regnum to translate to DWARF reg number using
      134 + reg_number should the range 134 to 142 be used for more pseudo regs
      in the future.  This also helps fit RA_AUTH_CODE into a bitmask.  */
-  REGDEF(ra_auth_code,9,PSEUDO),
+  REGDEF(ra_auth_code,12,PSEUDO),
 };
 #undef REGDEF
 #undef REGNUM
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d b/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
index ba1d76dd18fbe0ca2c391c12ddcb180d1de3b32b..d8d647bb7f0d943ceeec47e2f4fc8d34bb0ea057 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
@@ -6,11 +6,15 @@
 # VxWorks needs a special variant of this file.
 #skip: *-*-vxworks*
 
-Unwind section '.ARM.exidx' at offset 0x40 contains 1 entry:
+Unwind section '.ARM.exidx' at offset 0x60 contains 1 entry:
 
-0x0 <foo>: 0x80b4a8b0
-  Compact model index: 0
+0x0 <foo>: @0x0
+  Compact model index: 1
+  0x84 0x00 pop {r14}
+  0xb4      pop {ra_auth_code}
+  0x84 0x00 pop {r14}
+  0xb4      pop {ra_auth_code}
+  0xa3      pop {r4, r5, r6, r7}
   0xb4      pop {ra_auth_code}
   0xa8      pop {r4, r14}
   0xb0      finish
-
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m.d b/gas/testsuite/gas/arm/unwind-pacbti-m.d
index 28021758a7487097689ef4c44cc25546ccac5221..06cb3145e4254b34c2d95616d7ea20506af3a42a 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m.d
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m.d
@@ -8,16 +8,20 @@
 .*:     file format.*
 
 RELOCATION RECORDS FOR \[.ARM.exidx\]:
-OFFSET   TYPE              VALUE 
+OFFSET   TYPE              VALUE.
 00000000 R_ARM_PREL31      .text
-00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr0
+00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr1
+00000004 R_ARM_PREL31      .ARM.extab
 
 
 Contents of section .text:
- 0000 (10b54df8 04cd5df8 04cb10bd|b510f84d cd04f85d cb04bd10)  .*
+ 0000 (10b54df8 04cd5df8 04cb2de9 f050bde8|e8bd50f0 e92dcb04 f85dcd04 f84db510)  .*
+ 0010 (f0502de9 0050bde8 005010bd|bd105000 e8bd5000 e92d50f0)  .*
+Contents of section .ARM.extab:
+ 0000 (00840281 b40084b4 b0a8b4a3|a3b4a8b0 b48400b4 81028400) 00000000  .*
 Contents of section .ARM.exidx:
- 0000 00000000 (b0a8b480|80b4a8b0)  .*
+ 0000 00000000 00000000  .*
 Contents of section .ARM.attributes:
  0000 41(290000 00|000000 29)616561 62690001 (1f000000|0000001f)  .*
  0010 05382e31 2d4d2e4d 41494e00 0615074d  .*
- 0020 09033202 34024a01 4c01               .*
+ 0020 09033202 34024a01 4c01  .*
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m.s b/gas/testsuite/gas/arm/unwind-pacbti-m.s
index 5a6ea2eec2b8e48dd49963f0a4b93fa29c3c3a49..37202293133e95f7e94490aaa1729afb30a0afe7 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m.s
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m.s
@@ -16,5 +16,11 @@ foo:
 	push	{r12}
 	.save {ra_auth_code}
 	pop	{r12}
+	push	{r4-r7, ip, lr}
+	.save {r4-r7, ra_auth_code, lr}
+	pop	{r4-r7, ip, lr}
+	push	{ip, lr}
+	.save {ra_auth_code, lr}
+	pop {ip, lr}
 	pop	{r4, pc}
 	.fnend


[-- Attachment #2: rb15673.patch --]
[-- Type: text/plain, Size: 7569 bytes --]

diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index ca4f97b164ae8b0196e1830dc49e4927f8ea2480..8873269d76a482352c69d2d40a248549e7d6ba90 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -1942,6 +1942,22 @@ parse_reg_list (char ** strp, enum reg_list_els etype)
 		rt = REG_TYPE_PSEUDO;
 
 	      reg = arm_reg_parse (&str, rt);
+
+	      /* Skip over allowed registers of alternative types in mixed-type
+	         register lists.  */
+	      if (reg == FAIL && rt == REG_TYPE_PSEUDO
+		  && ((reg = arm_reg_parse (&str, REG_TYPE_RN)) != FAIL))
+		{
+		  cur_reg = reg;
+		  continue;
+		}
+	      else if (reg == FAIL && rt == REG_TYPE_RN
+		       && ((reg = arm_reg_parse (&str, REG_TYPE_PSEUDO)) != FAIL))
+		{
+		  cur_reg = reg;
+		  continue;
+		}
+
 	      if (etype == REGLIST_CLRM)
 		{
 		  if (reg == REG_SP || reg == REG_PC)
@@ -4281,22 +4297,11 @@ s_arm_unwind_personality (int ignored ATTRIBUTE_UNUSED)
 /* Parse a directive saving pseudo registers.  */
 
 static void
-s_arm_unwind_save_pseudo (void)
+s_arm_unwind_save_pseudo (long range)
 {
   valueT op;
-  long range;
-
-  range = parse_reg_list (&input_line_pointer, REGLIST_PSEUDO);
-  if (range == FAIL)
-    {
-      as_bad (_("expected pseudo register list"));
-      ignore_rest_of_line ();
-      return;
-    }
-
-  demand_empty_rest_of_line ();
 
-  if (range & (1 << 9))
+  if (range & (1 << 12))
     {
       /* Opcode for restoring RA_AUTH_CODE.  */
       op = 0xb4;
@@ -4308,22 +4313,11 @@ s_arm_unwind_save_pseudo (void)
 /* Parse a directive saving core registers.  */
 
 static void
-s_arm_unwind_save_core (void)
+s_arm_unwind_save_core (long range)
 {
   valueT op;
-  long range;
   int n;
 
-  range = parse_reg_list (&input_line_pointer, REGLIST_RN);
-  if (range == FAIL)
-    {
-      as_bad (_("expected register list"));
-      ignore_rest_of_line ();
-      return;
-    }
-
-  demand_empty_rest_of_line ();
-
   /* Turn .unwind_movsp ip followed by .unwind_save {..., ip, ...}
      into .unwind_save {..., sp...}.  We aren't bothered about the value of
      ip because it is clobbered by calls.  */
@@ -4722,6 +4716,40 @@ s_arm_unwind_save_mmxwcg (void)
   ignore_rest_of_line ();
 }
 
+static void
+s_arm_unwind_save_mixed (long range, long mask_range)
+{
+  const long roof = ((sizeof (long) * CHAR_BIT) - 1)
+    - __builtin_clzl (mask_range);
+
+  long subrange = 0;
+  unsigned lim_lo = 0;
+  unsigned lim_hi = 0;
+
+  /* Iterate over pseudoregister to establish subrange bounds.  */
+  for (; lim_hi <= roof; lim_hi++)
+    {
+      if (mask_range & (1 << lim_hi))
+	{
+	  /* Once we know where to split our range, construct subrange.  */
+	  for (unsigned n = lim_lo; n < lim_hi; n++)
+	    {
+	      if (range & (1 << n))
+		subrange |= (1 << n);
+	    }
+
+	  s_arm_unwind_save_core (subrange);
+	  s_arm_unwind_save_pseudo (1 << lim_hi);
+
+	  subrange = 0;
+	  lim_lo = lim_hi + 1;
+	}
+    }
+
+  lim_lo = 0xffff << roof;
+  subrange = range & lim_lo;
+  s_arm_unwind_save_core (subrange);
+}
 
 /* Parse an unwind_save directive.
    If the argument is non-zero, this is a .vsave directive.  */
@@ -4729,7 +4757,8 @@ s_arm_unwind_save_mmxwcg (void)
 static void
 s_arm_unwind_save (int arch_v6)
 {
-  char *peek;
+  char *peek, *mask_peek;
+  long range, mask_range;
   struct reg_entry *reg;
   bool had_brace = false;
 
@@ -4737,7 +4766,7 @@ s_arm_unwind_save (int arch_v6)
     as_bad (MISSING_FNSTART);
 
   /* Figure out what sort of save we have.  */
-  peek = input_line_pointer;
+  peek = mask_peek = input_line_pointer;
 
   if (*peek == '{')
     {
@@ -4767,13 +4796,35 @@ s_arm_unwind_save (int arch_v6)
       s_arm_unwind_save_fpa (reg->number);
       return;
 
+    case REG_TYPE_PSEUDO:
     case REG_TYPE_RN:
-      s_arm_unwind_save_core ();
-      return;
+      mask_range = parse_reg_list (&mask_peek, REGLIST_PSEUDO);
+      range = parse_reg_list (&input_line_pointer, REGLIST_RN);
 
-    case REG_TYPE_PSEUDO:
-      s_arm_unwind_save_pseudo ();
-      return;
+      if (range == FAIL || mask_range == FAIL)
+	{
+	  as_bad (_("expected register list"));
+	  ignore_rest_of_line ();
+	  return;
+	}
+
+      demand_empty_rest_of_line ();
+
+      if (!mask_range)
+	{
+	  s_arm_unwind_save_core (range);
+	  return;
+	}
+      else if (!range)
+	{
+	  s_arm_unwind_save_pseudo (mask_range);
+	  return;
+	}
+      else
+	{
+	  s_arm_unwind_save_mixed (range, mask_range);
+	  return;
+	}
 
     case REG_TYPE_VFD:
       if (arch_v6)
@@ -23976,7 +24027,7 @@ static const struct reg_entry reg_names[] =
      for tc_arm_regname_to_dw2regnum to translate to DWARF reg number using
      134 + reg_number should the range 134 to 142 be used for more pseudo regs
      in the future.  This also helps fit RA_AUTH_CODE into a bitmask.  */
-  REGDEF(ra_auth_code,9,PSEUDO),
+  REGDEF(ra_auth_code,12,PSEUDO),
 };
 #undef REGDEF
 #undef REGNUM
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d b/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
index ba1d76dd18fbe0ca2c391c12ddcb180d1de3b32b..d8d647bb7f0d943ceeec47e2f4fc8d34bb0ea057 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m-readelf.d
@@ -6,11 +6,15 @@
 # VxWorks needs a special variant of this file.
 #skip: *-*-vxworks*
 
-Unwind section '.ARM.exidx' at offset 0x40 contains 1 entry:
+Unwind section '.ARM.exidx' at offset 0x60 contains 1 entry:
 
-0x0 <foo>: 0x80b4a8b0
-  Compact model index: 0
+0x0 <foo>: @0x0
+  Compact model index: 1
+  0x84 0x00 pop {r14}
+  0xb4      pop {ra_auth_code}
+  0x84 0x00 pop {r14}
+  0xb4      pop {ra_auth_code}
+  0xa3      pop {r4, r5, r6, r7}
   0xb4      pop {ra_auth_code}
   0xa8      pop {r4, r14}
   0xb0      finish
-
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m.d b/gas/testsuite/gas/arm/unwind-pacbti-m.d
index 28021758a7487097689ef4c44cc25546ccac5221..06cb3145e4254b34c2d95616d7ea20506af3a42a 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m.d
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m.d
@@ -8,16 +8,20 @@
 .*:     file format.*
 
 RELOCATION RECORDS FOR \[.ARM.exidx\]:
-OFFSET   TYPE              VALUE 
+OFFSET   TYPE              VALUE.
 00000000 R_ARM_PREL31      .text
-00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr0
+00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr1
+00000004 R_ARM_PREL31      .ARM.extab
 
 
 Contents of section .text:
- 0000 (10b54df8 04cd5df8 04cb10bd|b510f84d cd04f85d cb04bd10)  .*
+ 0000 (10b54df8 04cd5df8 04cb2de9 f050bde8|e8bd50f0 e92dcb04 f85dcd04 f84db510)  .*
+ 0010 (f0502de9 0050bde8 005010bd|bd105000 e8bd5000 e92d50f0)  .*
+Contents of section .ARM.extab:
+ 0000 (00840281 b40084b4 b0a8b4a3|a3b4a8b0 b48400b4 81028400) 00000000  .*
 Contents of section .ARM.exidx:
- 0000 00000000 (b0a8b480|80b4a8b0)  .*
+ 0000 00000000 00000000  .*
 Contents of section .ARM.attributes:
  0000 41(290000 00|000000 29)616561 62690001 (1f000000|0000001f)  .*
  0010 05382e31 2d4d2e4d 41494e00 0615074d  .*
- 0020 09033202 34024a01 4c01               .*
+ 0020 09033202 34024a01 4c01  .*
diff --git a/gas/testsuite/gas/arm/unwind-pacbti-m.s b/gas/testsuite/gas/arm/unwind-pacbti-m.s
index 5a6ea2eec2b8e48dd49963f0a4b93fa29c3c3a49..37202293133e95f7e94490aaa1729afb30a0afe7 100644
--- a/gas/testsuite/gas/arm/unwind-pacbti-m.s
+++ b/gas/testsuite/gas/arm/unwind-pacbti-m.s
@@ -16,5 +16,11 @@ foo:
 	push	{r12}
 	.save {ra_auth_code}
 	pop	{r12}
+	push	{r4-r7, ip, lr}
+	.save {r4-r7, ra_auth_code, lr}
+	pop	{r4-r7, ip, lr}
+	push	{ip, lr}
+	.save {ra_auth_code, lr}
+	pop {ip, lr}
 	pop	{r4, pc}
 	.fnend


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-05-18 15:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-04 10:41 [PATCH][Binutils][GAS] arm: Add unwind support for mixed register lists Victor Do Nascimento
2022-05-18 15:31 ` Nick Clifton
2022-05-05 11:07 Srinath Parvathaneni
2022-05-05 11:36 ` Srinath Parvathaneni

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).