ix86: wrap constants
authorJan Beulich <jbeulich@suse.com>
Mon, 7 Jun 2021 06:49:33 +0000 (08:49 +0200)
committerJan Beulich <jbeulich@suse.com>
Mon, 7 Jun 2021 06:49:33 +0000 (08:49 +0200)
Non-64-bit code should get handled the same with or without BFD64. This
wasn't the case though in a number of situations (and quite likely there
are more that I haven't spotted yet).

It's not very nice to tie the check in md_apply_fix() to object_64bit,
but afaict at that time we have no record anymore of the mode an insn
was assembled in (it might also have been data). This doesn't look to be
the first inconsistency of this kind, though. In x86_cons() it's even
less clear what the right approach would be: flag_code shouldn't matter
for data emission, but instead we'd need to know from which mode(s) the
data actually gets accessed. On this basis, signed_cons() also gets
adjusted.

gas/ChangeLog
gas/config/tc-i386.c
gas/testsuite/gas/i386/i386.exp
gas/testsuite/gas/i386/wrap32-data.d [new file with mode: 0644]
gas/testsuite/gas/i386/wrap32-text.d [new file with mode: 0644]
gas/testsuite/gas/i386/wrap32.s [new file with mode: 0644]

index 67b4583f212fd1afa04c6652a274172e01c9392f..b1d65569ce8e9dba7fd1d6cf28ff6b301c7984c3 100644 (file)
@@ -1,3 +1,12 @@
+2021-06-07  Jan Beulich  <jbeulich@suse.com>
+
+       * config/tc-i386.c (extend_to_32bit_address): New.
+       (x86_cons, i386_finalize_immediate, md_apply_fix): Use it.
+       (signed_cons): Use object_64bit.
+       * testsuite/gas/i386/wrap32.s, testsuite/gas/i386/wrap32-data.d,
+       testsuite/gas/i386/wrap32-text.d: New.
+       * testsuite/gas/i386/i386.exp: Run new tests.
+
 2021-06-03  Alan Modra  <amodra@gmail.com>
 
        PR 1202
index d3441988e3475e7690658b36e9bbdb01cea0abcf..a6bc597a3548c08744dc4544560156d2f8496637 100644 (file)
@@ -2457,6 +2457,19 @@ fits_in_unsigned_long (addressT num ATTRIBUTE_UNUSED)
 #endif
 }                              /* fits_in_unsigned_long() */
 
+static INLINE valueT extend_to_32bit_address (addressT num)
+{
+#ifdef BFD64
+  if (fits_in_unsigned_long(num))
+    return (num ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
+
+  if (!fits_in_signed_long (num))
+    return num & 0xffffffff;
+#endif
+
+  return num;
+}
+
 static INLINE int
 fits_in_disp8 (offsetT num)
 {
@@ -10457,13 +10470,17 @@ x86_cons (expressionS *exp, int size)
   if (intel_syntax)
     i386_intel_simplify (exp);
 
+  /* If not 64bit, massage value, to account for wraparound when !BFD64.  */
+  if (size == 4 && exp->X_op == O_constant && !object_64bit)
+    exp->X_add_number = extend_to_32bit_address (exp->X_add_number);
+
   return got_reloc;
 }
 
 static void
 signed_cons (int size)
 {
-  if (flag_code == CODE_64BIT)
+  if (object_64bit)
     cons_sign = 1;
   cons (size);
   cons_sign = -1;
@@ -10718,11 +10735,11 @@ i386_finalize_immediate (segT exp_seg ATTRIBUTE_UNUSED, expressionS *exp,
     {
       /* Size it properly later.  */
       i.types[this_operand].bitfield.imm64 = 1;
-      /* If not 64bit, sign extend val.  */
-      if (flag_code != CODE_64BIT
-         && (exp->X_add_number & ~(((addressT) 2 << 31) - 1)) == 0)
-       exp->X_add_number
-         = (exp->X_add_number ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);
+
+      /* If not 64bit, sign/zero extend val, to account for wraparound
+        when !BFD64.  */
+      if (flag_code != CODE_64BIT)
+       exp->X_add_number = extend_to_32bit_address (exp->X_add_number);
     }
 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT))
   else if (OUTPUT_FLAVOR == bfd_target_aout_flavour
@@ -12640,6 +12657,11 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
        break;
       }
 #endif /* defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)  */
+
+  /* If not 64bit, massage value, to account for wraparound when !BFD64.  */
+  if (!object_64bit)
+    value = extend_to_32bit_address (value);
+
   *valP = value;
 #endif /* !defined (TE_Mach)  */
 
index a459c6fe392eb152fca35ba6fd0c856e3afb4e32..efcccafc0344aa438c7b97662bb55a4acdb81ad8 100644 (file)
@@ -148,6 +148,8 @@ if [gas_32_check] then {
     run_dump_test "addr32"
     run_dump_test "code16"
     run_list_test "oversized16" "-al"
+    run_dump_test "wrap32-text"
+    run_dump_test "wrap32-data"
     run_dump_test "sse4_1"
     run_dump_test "sse4_1-intel"
     run_dump_test "sse4_2"
diff --git a/gas/testsuite/gas/i386/wrap32-data.d b/gas/testsuite/gas/i386/wrap32-data.d
new file mode 100644 (file)
index 0000000..bebec98
--- /dev/null
@@ -0,0 +1,23 @@
+#name: i386 32-bit wrapping calculations (data/ELF)
+#source: wrap32.s
+#objdump: -rsj .data
+
+.*: +file format .*
+
+RELOCATION RECORDS FOR \[\.data\]:
+
+OFFSET +TYPE +VALUE *
+0*10 (R_386_32|dir32) *sym
+0*14 (R_386_32|dir32) *sym
+0*18 (R_386_32|dir32) *sym
+0*1c (R_386_32|dir32) *sym
+0*30 (R_386_32|dir32) *sym
+0*34 (R_386_32|dir32) *sym
+0*38 (R_386_32|dir32) *sym
+0*3c (R_386_32|dir32) *sym
+
+Contents of section .data:
+ 0+00 f4 ?00 ?00 ?00 f4 ?00 ?00 ?00 90 ?00 ?00 ?00 90 ?00 ?00 ?00 .*
+ 0+10 00 ?ff ?ff ?ff 00 ?ff ?ff ?ff f4 ?00 ?00 ?00 f4 ?00 ?00 ?00 .*
+ 0+20 f4 ?02 ?00 ?70 f4 ?00 ?00 ?80 90 ?02 ?00 ?70 90 ?00 ?00 ?80 .*
+ 0+30 00 ?01 ?00 ?70 00 ?ff ?ff ?7f f4 ?02 ?00 ?70 f4 ?00 ?00 ?80 .*
diff --git a/gas/testsuite/gas/i386/wrap32-text.d b/gas/testsuite/gas/i386/wrap32-text.d
new file mode 100644 (file)
index 0000000..3ebbd85
--- /dev/null
@@ -0,0 +1,43 @@
+#name: i386 32-bit wrapping calculations (text)
+#source: wrap32.s
+#objdump: -dwr
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <wrap>:
+[      ]*[0-9a-f]+:[   ]+b8 f4 00 00 00        mov    \$0xf4,%eax
+[      ]*[0-9a-f]+:[   ]+ba f4 00 00 00        mov    \$0xf4,%edx
+[      ]*[0-9a-f]+:[   ]+b8 90 00 00 00        mov    \$0x90,%eax
+[      ]*[0-9a-f]+:[   ]+ba 90 00 00 00        mov    \$0x90,%edx
+[      ]*[0-9a-f]+:[   ]+b8 00 ff ff ff        mov    \$0xffffff00,%eax[       ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+ba 00 ff ff ff        mov    \$0xffffff00,%edx[       ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+b8 f4 00 00 00        mov    \$0xf4,%eax[     ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+ba f4 00 00 00        mov    \$0xf4,%edx[     ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+c7 00 f4 00 00 00     movl   \$0xf4,\(%eax\)
+[      ]*[0-9a-f]+:[   ]+c7 02 f4 00 00 00     movl   \$0xf4,\(%edx\)
+[      ]*[0-9a-f]+:[   ]+c7 00 90 00 00 00     movl   \$0x90,\(%eax\)
+[      ]*[0-9a-f]+:[   ]+c7 02 90 00 00 00     movl   \$0x90,\(%edx\)
+[      ]*[0-9a-f]+:[   ]+c7 00 00 ff ff ff     movl   \$0xffffff00,\(%eax\)[   ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+c7 02 00 ff ff ff     movl   \$0xffffff00,\(%edx\)[   ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+c7 00 f4 00 00 00     movl   \$0xf4,\(%eax\)[         ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+c7 02 f4 00 00 00     movl   \$0xf4,\(%edx\)[         ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+81 c1 f4 00 00 00     add    \$0xf4,%ecx
+[      ]*[0-9a-f]+:[   ]+81 c2 f4 00 00 00     add    \$0xf4,%edx
+[      ]*[0-9a-f]+:[   ]+81 c1 90 00 00 00     add    \$0x90,%ecx
+[      ]*[0-9a-f]+:[   ]+81 c2 90 00 00 00     add    \$0x90,%edx
+[      ]*[0-9a-f]+:[   ]+81 c1 00 ff ff ff     add    \$0xffffff00,%ecx[       ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+81 c2 00 ff ff ff     add    \$0xffffff00,%edx[       ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+81 c1 f4 00 00 00     add    \$0xf4,%ecx[     ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+81 c2 f4 00 00 00     add    \$0xf4,%edx[     ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+81 00 f4 00 00 00     addl   \$0xf4,\(%eax\)
+[      ]*[0-9a-f]+:[   ]+81 02 f4 00 00 00     addl   \$0xf4,\(%edx\)
+[      ]*[0-9a-f]+:[   ]+81 00 90 00 00 00     addl   \$0x90,\(%eax\)
+[      ]*[0-9a-f]+:[   ]+81 02 90 00 00 00     addl   \$0x90,\(%edx\)
+[      ]*[0-9a-f]+:[   ]+81 00 00 ff ff ff     addl   \$0xffffff00,\(%eax\)[   ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+81 02 00 ff ff ff     addl   \$0xffffff00,\(%edx\)[   ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+81 00 f4 00 00 00     addl   \$0xf4,\(%eax\)[         ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+81 02 f4 00 00 00     addl   \$0xf4,\(%edx\)[         ]+[0-9a-f]+: (R_386_32|dir32)[  ]+sym
+[      ]*[0-9a-f]+:[   ]+c3                    ret *
+#pass
diff --git a/gas/testsuite/gas/i386/wrap32.s b/gas/testsuite/gas/i386/wrap32.s
new file mode 100644 (file)
index 0000000..0198484
--- /dev/null
@@ -0,0 +1,60 @@
+       .text
+wrap:
+       mov     $500 - 0x100, %eax
+       mov     $500 + 0xffffff00, %edx
+       mov     $val - 0x100, %eax
+       mov     $val + 0xffffff00, %edx
+       mov     $sym - 0x100, %eax
+       mov     $sym + 0xffffff00, %edx
+       mov     $sym + 500 - 0x100, %eax
+       mov     $sym + 500 + 0xffffff00, %edx
+
+       movl    $500 - 0x100, (%eax)
+       movl    $500 + 0xffffff00, (%edx)
+       movl    $val - 0x100, (%eax)
+       movl    $val + 0xffffff00, (%edx)
+       movl    $sym - 0x100, (%eax)
+       movl    $sym + 0xffffff00, (%edx)
+       movl    $sym + 500 - 0x100, (%eax)
+       movl    $sym + 500 + 0xffffff00, (%edx)
+
+       add     $500 - 0x100, %ecx
+       add     $500 + 0xffffff00, %edx
+       add     $val - 0x100, %ecx
+       add     $val + 0xffffff00, %edx
+       add     $sym - 0x100, %ecx
+       add     $sym + 0xffffff00, %edx
+       add     $sym + 500 - 0x100, %ecx
+       add     $sym + 500 + 0xffffff00, %edx
+
+       addl    $500 - 0x100, (%eax)
+       addl    $500 + 0xffffff00, (%edx)
+       addl    $val - 0x100, (%eax)
+       addl    $val + 0xffffff00, (%edx)
+       addl    $sym - 0x100, (%eax)
+       addl    $sym + 0xffffff00, (%edx)
+       addl    $sym + 500 - 0x100, (%eax)
+       addl    $sym + 500 + 0xffffff00, (%edx)
+
+       ret
+
+       .data
+       .long 500 - 0x100
+       .long 500 + 0xffffff00
+       .long val - 0x100
+       .long val + 0xffffff00
+       .long sym - 0x100
+       .long sym + 0xffffff00
+       .long sym + 500 - 0x100
+       .long sym + 500 + 0xffffff00
+
+       .slong 500 - 0x8fffff00
+       .slong 500 + 0x7fffff00
+       .slong val - 0x8fffff00
+       .slong val + 0x7fffff00
+       .slong sym - 0x8fffff00
+       .slong sym + 0x7fffff00
+       .slong sym + 500 - 0x8fffff00
+       .slong sym + 500 + 0x7fffff00
+
+       .equ val, 400