[PATCH] ix86: wrap constants
H.J. Lu
hjl.tools@gmail.com
Fri Jun 4 12:26:10 GMT 2021
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.
More information about the Binutils
mailing list