[binutils-gdb] s390: gas: Fix conversion of FP register names to DWARF register numbers

Jens Remus jremus@sourceware.org
Tue Jan 20 09:34:26 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ed179000ec8d17aa119a2fcb6548e60a492134d6

commit ed179000ec8d17aa119a2fcb6548e60a492134d6
Author: Jens Remus <jremus@linux.ibm.com>
Date:   Tue Jan 20 10:33:55 2026 +0100

    s390: gas: Fix conversion of FP register names to DWARF register numbers
    
    The assembler supports register names in CFI directives.  For floating-
    point (FP) registers f0..f15 the register numbers 0..15 are erroneously
    converted to DWARF register numbers 16..31 by adding 16.  This is wrong
    as the s390 64-bit (s390x) ELF ABI [1] specifies the DWARF register
    numbers for the FP registers as follows:
    
      DWARF               BINARY    BINARY DWARF
      REGISTER  REGISTER  REGISTER  REGISTER
      NUMBER    NAME      NUMBER    NUMBER
      16        f0        0b0000 -> 0b10000
      17        f2        0b0010 -> 0b10001
      18        f4        0b0100 -> 0b10010
      19        f6        0b0110 -> 0b10011
      20        f1        0b0001 -> 0b10100
      21        f3        0b0011 -> 0b10101
      22        f5        0b0101 -> 0b10110
      23        f7        0b0111 -> 0b10111
      24        f8        0b1000 -> 0b11000
      25        f10       0b1010 -> 0b11001
      26        f12       0b1100 -> 0b11010
      27        f14       0b1110 -> 0b11011
      28        f9        0b1001 -> 0b11100
      29        f11       0b1011 -> 0b11101
      30        f13       0b1101 -> 0b11110
      31        f15       0b1111 -> 0b11111
    
    Convert a FP register number (0..15) to its respective DWARF register
    number (16..31) as follows:
    Right rotate the least significant three bits and add 16.
    
    Add a test case for the use of general register (GR; r0..r15) and
    floating-point register (FPR; f0..f15) names in CFI directives.
    
    [1]: s390x ELF ABI, https://github.com/IBM/s390x-abi/releases
    
    gas/
            * config/tc-s390.c (tc_s390_regname_to_dw2regnum): Fix
            conversion of FP register names to DWARF register numbers.
    
    gas/testsuite/
            * gas/s390/s390.exp (cfi-regnames, cfi-regnames-err): Run new
            tests.
            * gas/s390/cfi-regnames.d: New test for GR and FPR names in CFI
            directives.
            * gas/s390/cfi-regnames.s: Likewise.
            * gas/s390/cfi-regnames-err.l: Likewise.
            * gas/s390/cfi-regnames-err.s: Likewise.
    
    Signed-off-by: Jens Remus <jremus@linux.ibm.com>

Diff:
---
 gas/config/tc-s390.c                      | 12 ++++++++++-
 gas/testsuite/gas/s390/cfi-regnames-err.l |  8 +++++++
 gas/testsuite/gas/s390/cfi-regnames-err.s |  9 ++++++++
 gas/testsuite/gas/s390/cfi-regnames.d     | 36 +++++++++++++++++++++++++++++++
 gas/testsuite/gas/s390/cfi-regnames.s     | 33 ++++++++++++++++++++++++++++
 gas/testsuite/gas/s390/s390.exp           |  2 ++
 6 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/gas/config/tc-s390.c b/gas/config/tc-s390.c
index 535c424ca04..9af835bb4b9 100644
--- a/gas/config/tc-s390.c
+++ b/gas/config/tc-s390.c
@@ -2879,7 +2879,17 @@ tc_s390_regname_to_dw2regnum (char *regname)
     {
       regnum = reg_name_search (regname);
       if (regname[0] == 'f' && regnum != -1)
-        regnum += 16;
+	{
+	  /* Convert from floating-point register number (0..15)
+	   * to DWARF floating point register number (15..31):
+	   * Right rotate the least significant three bits and add 16.  */
+	  int dw2_regnum;
+	  dw2_regnum = (regnum & 0b110) >> 1;
+	  dw2_regnum |= (regnum & 0b1) << 2;
+	  dw2_regnum |= (regnum & 0b1000);
+	  dw2_regnum += 16;
+	  regnum = dw2_regnum;
+	}
     }
   else if (strcmp (regname, "ap") == 0)
     regnum = 32;
diff --git a/gas/testsuite/gas/s390/cfi-regnames-err.l b/gas/testsuite/gas/s390/cfi-regnames-err.l
new file mode 100644
index 00000000000..7944f9b78fc
--- /dev/null
+++ b/gas/testsuite/gas/s390/cfi-regnames-err.l
@@ -0,0 +1,8 @@
+#name: s390/s390x register names in CFI directives errors
+.*: Assembler messages:
+# Invalid general register names
+.*:4: Error: bad register expression
+.*:5: Error: bad register expression
+# Invalid floating-point register names
+.*:7: Error: bad register expression
+.*:8: Error: bad register expression
diff --git a/gas/testsuite/gas/s390/cfi-regnames-err.s b/gas/testsuite/gas/s390/cfi-regnames-err.s
new file mode 100644
index 00000000000..55eae2cf151
--- /dev/null
+++ b/gas/testsuite/gas/s390/cfi-regnames-err.s
@@ -0,0 +1,9 @@
+	.text
+	.cfi_startproc
+# Invalid general register names
+	.cfi_register r0, r16
+	.cfi_register %r0, %r16
+# Invalid floating-point register names
+	.cfi_register f0, f16
+	.cfi_register %f0, %f16
+	.cfi_endproc
diff --git a/gas/testsuite/gas/s390/cfi-regnames.d b/gas/testsuite/gas/s390/cfi-regnames.d
new file mode 100644
index 00000000000..8e474058735
--- /dev/null
+++ b/gas/testsuite/gas/s390/cfi-regnames.d
@@ -0,0 +1,36 @@
+#name: s390/s390x register names in CFI directives
+#objdump: -Wf
+
+.*: +file format .*
+
+Contents of the .eh_frame section:
+
+#...
+
+# General register (GR) names r0..r15
+00000018 0000000000000028 0000001c FDE cie=00000000 pc=0000000000000000..0000000000000004
+  DW_CFA_advance_loc: 2 to 0000000000000002
+  DW_CFA_register: r0 in r1
+  DW_CFA_register: r2 in r3
+  DW_CFA_register: r4 in r5
+  DW_CFA_register: r6 in r7
+  DW_CFA_register: r8 in r9
+  DW_CFA_register: r10 in r11
+  DW_CFA_register: r12 in r13
+  DW_CFA_register: r14 in r15
+  DW_CFA_nop
+  DW_CFA_nop
+
+# Floating-point register (FPR) names f0..f15
+00000044 0000000000000028 00000048 FDE cie=00000000 pc=0000000000000004..0000000000000008
+  DW_CFA_advance_loc: 2 to 0000000000000006
+  DW_CFA_register: r16 \(f0\) in r20 \(f1\)
+  DW_CFA_register: r17 \(f2\) in r21 \(f3\)
+  DW_CFA_register: r18 \(f4\) in r22 \(f5\)
+  DW_CFA_register: r19 \(f6\) in r23 \(f7\)
+  DW_CFA_register: r24 \(f8\) in r28 \(f9\)
+  DW_CFA_register: r25 \(f10\) in r29 \(f11\)
+  DW_CFA_register: r26 \(f12\) in r30 \(f13\)
+  DW_CFA_register: r27 \(f14\) in r31 \(f15\)
+  DW_CFA_nop
+  DW_CFA_nop
diff --git a/gas/testsuite/gas/s390/cfi-regnames.s b/gas/testsuite/gas/s390/cfi-regnames.s
new file mode 100644
index 00000000000..cd11d4da450
--- /dev/null
+++ b/gas/testsuite/gas/s390/cfi-regnames.s
@@ -0,0 +1,33 @@
+	.text
+# General register (GR) names r0..r15
+	.type gr, @function
+gr:
+	.cfi_startproc
+	.word 0
+	.cfi_register r0, r1
+	.cfi_register r2, r3
+	.cfi_register r4, r5
+	.cfi_register r6, r7
+	.cfi_register r8, r9
+	.cfi_register r10, r11
+	.cfi_register r12, r13
+	.cfi_register r14, r15
+	.word 0
+	.cfi_endproc
+	.size gr, .-gr
+# Floating-point register (FPR) names f0..f15
+	.type fpr, @function
+fpr:
+	.cfi_startproc
+	.word 0
+	.cfi_register f0, f1
+	.cfi_register f2, f3
+	.cfi_register f4, f5
+	.cfi_register f6, f7
+	.cfi_register f8, f9
+	.cfi_register f10, f11
+	.cfi_register f12, f13
+	.cfi_register f14, f15
+	.word 0
+	.cfi_endproc
+	.size fpr, .-fpr
diff --git a/gas/testsuite/gas/s390/s390.exp b/gas/testsuite/gas/s390/s390.exp
index 1d5d97f4863..49876aa00e3 100644
--- a/gas/testsuite/gas/s390/s390.exp
+++ b/gas/testsuite/gas/s390/s390.exp
@@ -64,4 +64,6 @@ if [expr [istarget "s390-*-*"] ||  [istarget "s390x-*-*"]]  then {
     run_list_test "zarch-warn-areg-zero" "-m64 -mwarn-areg-zero"
     run_list_test "zarch-warn-regtype-mismatch-strict" "-m64 -mwarn-regtype-mismatch=strict"
     run_list_test "zarch-warn-regtype-mismatch-relaxed" "-m64 -mwarn-regtype-mismatch=relaxed"
+    run_dump_test "cfi-regnames" ""
+    run_list_test "cfi-regnames-err" ""
 }


More information about the Binutils-cvs mailing list