ix86: wrap constants

Message ID 51fd75ea-9591-6720-c3eb-b6f6ace02840@suse.com
State New
Headers show
Series
  • ix86: wrap constants
Related show

Commit Message

Alan Modra via Binutils June 4, 2021, 12:14 p.m.
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/
2021-06-XX  Jan Beulich  <jbeulich@suse.com>

	* config/tc-i386.c (extend_to_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.

Comments

Alan Modra via Binutils June 4, 2021, 12:26 p.m. | #1
On Fri, Jun 4, 2021 at 5:14 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> 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/

> 2021-06-XX  Jan Beulich  <jbeulich@suse.com>

>

>         * config/tc-i386.c (extend_to_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.

>

> --- a/gas/config/tc-i386.c

> +++ b/gas/config/tc-i386.c

> @@ -2457,6 +2457,19 @@ fits_in_unsigned_long (addressT num ATTR

>  #endif

>  }                              /* fits_in_unsigned_long() */

>

> +static INLINE valueT extend_to_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


Shouldn't this check apply only to 32-bit objects?

> +  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_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 AT

>      {

>        /* 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_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,

>         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_address (value);

> +

>    *valP = value;

>  #endif /* !defined (TE_Mach)  */

>

> --- a/gas/testsuite/gas/i386/i386.exp

> +++ b/gas/testsuite/gas/i386/i386.exp

> @@ -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"

> --- /dev/null

> +++ b/gas/testsuite/gas/i386/wrap32-data.d

> @@ -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 .*

> --- /dev/null

> +++ b/gas/testsuite/gas/i386/wrap32-text.d

> @@ -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

> --- /dev/null

> +++ b/gas/testsuite/gas/i386/wrap32.s

> @@ -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

>



-- 
H.J.
Alan Modra via Binutils June 4, 2021, 12:34 p.m. | #2
On 04.06.2021 14:26, H.J. Lu wrote:
> On Fri, Jun 4, 2021 at 5:14 AM Jan Beulich <jbeulich@suse.com> wrote:

>>

>> 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/

>> 2021-06-XX  Jan Beulich  <jbeulich@suse.com>

>>

>>         * config/tc-i386.c (extend_to_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.

>>

>> --- a/gas/config/tc-i386.c

>> +++ b/gas/config/tc-i386.c

>> @@ -2457,6 +2457,19 @@ fits_in_unsigned_long (addressT num ATTR

>>  #endif

>>  }                              /* fits_in_unsigned_long() */

>>

>> +static INLINE valueT extend_to_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

> 

> Shouldn't this check apply only to 32-bit objects?


It already does (as far as it should; the check should really
apply to non-64-bit code only) - callers use either !object_64bit
up front, or "flag_code != CODE_64BIT". As per what the description
says, the latter is really how we'd like it to be (because for
32-bit code it shouldn't matter what container it lives in), but
- in x86_cons() applicability of flag_code is at best questionable,
- in md_apply_fix() we don't have that information available.

Jan
Alan Modra via Binutils June 4, 2021, 1:08 p.m. | #3
On Fri, Jun 4, 2021 at 5:34 AM Jan Beulich <jbeulich@suse.com> wrote:
>

> On 04.06.2021 14:26, H.J. Lu wrote:

> > On Fri, Jun 4, 2021 at 5:14 AM Jan Beulich <jbeulich@suse.com> wrote:

> >>

> >> 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/

> >> 2021-06-XX  Jan Beulich  <jbeulich@suse.com>

> >>

> >>         * config/tc-i386.c (extend_to_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.

> >>

> >> --- a/gas/config/tc-i386.c

> >> +++ b/gas/config/tc-i386.c

> >> @@ -2457,6 +2457,19 @@ fits_in_unsigned_long (addressT num ATTR

> >>  #endif

> >>  }                              /* fits_in_unsigned_long() */

> >>

> >> +static INLINE valueT extend_to_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

> >

> > Shouldn't this check apply only to 32-bit objects?

>

> It already does (as far as it should; the check should really

> apply to non-64-bit code only) - callers use either !object_64bit

> up front, or "flag_code != CODE_64BIT". As per what the description

> says, the latter is really how we'd like it to be (because for

> 32-bit code it shouldn't matter what container it lives in), but

> - in x86_cons() applicability of flag_code is at best questionable,

> - in md_apply_fix() we don't have that information available.

>


Can you rename extend_to_address to something like
extend_to_32bit_address?  OK with that change.

Thanks.

-- 
H.J.

Patch

--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -2457,6 +2457,19 @@  fits_in_unsigned_long (addressT num ATTR
 #endif
 }				/* fits_in_unsigned_long() */
 
+static INLINE valueT extend_to_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_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 AT
     {
       /* 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_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,
 	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_address (value);
+
   *valP = value;
 #endif /* !defined (TE_Mach)  */
 
--- a/gas/testsuite/gas/i386/i386.exp
+++ b/gas/testsuite/gas/i386/i386.exp
@@ -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"
--- /dev/null
+++ b/gas/testsuite/gas/i386/wrap32-data.d
@@ -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 .*
--- /dev/null
+++ b/gas/testsuite/gas/i386/wrap32-text.d
@@ -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
--- /dev/null
+++ b/gas/testsuite/gas/i386/wrap32.s
@@ -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