From 28a167a40651c4b50ef00c5fb92383b96390bfec Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 23 Apr 2021 09:16:57 +0200 Subject: x86: re-order optimize_disp() While I can't point out any specific case where things break, it looks wrong to have the consumer of a flag before its producer. Set .disp32 first, then do the possible conversion to signed 32-bit, and finally check whether the value fits in a signed long. --- gas/ChangeLog | 5 +++++ gas/config/tc-i386.c | 34 ++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index a820eab..669fb6b 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,10 @@ 2021-04-23 Jan Beulich + * config/tc-i386.c (optimize_disp): Move down BFD64 section. + Move up setting of disp32. + +2021-04-23 Jan Beulich + * config/tc-i386.c (pe): Don't truncate expression value. (i386_finalize_displacement): Likewise. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 007d774..5180320 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -5707,19 +5707,6 @@ optimize_disp (void) op_disp = (((op_disp & 0xffff) ^ 0x8000) - 0x8000); i.types[op].bitfield.disp64 = 0; } -#ifdef BFD64 - /* Optimize 64-bit displacement to 32-bit for 64-bit BFD. */ - if (i.types[op].bitfield.disp32 - && (op_disp & ~(((offsetT) 2 << 31) - 1)) == 0) - { - /* If this operand is at most 32 bits, convert - to a signed 32 bit number and don't use 64bit - displacement. */ - op_disp &= (((offsetT) 2 << 31) - 1); - op_disp = (op_disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31); - i.types[op].bitfield.disp64 = 0; - } -#endif if (!op_disp && i.types[op].bitfield.baseindex) { i.types[op].bitfield.disp8 = 0; @@ -5730,17 +5717,32 @@ optimize_disp (void) i.op[op].disps = 0; i.disp_operands--; } +#ifdef BFD64 else if (flag_code == CODE_64BIT) { + if (i.prefix[ADDR_PREFIX] + && fits_in_unsigned_long (op_disp)) + i.types[op].bitfield.disp32 = 1; + + /* Optimize 64-bit displacement to 32-bit for 64-bit BFD. */ + if (i.types[op].bitfield.disp32 + && (op_disp & ~(((offsetT) 2 << 31) - 1)) == 0) + { + /* If this operand is at most 32 bits, convert + to a signed 32 bit number and don't use 64bit + displacement. */ + op_disp &= (((offsetT) 2 << 31) - 1); + op_disp = (op_disp ^ ((offsetT) 1 << 31)) - ((addressT) 1 << 31); + i.types[op].bitfield.disp64 = 0; + } + if (fits_in_signed_long (op_disp)) { i.types[op].bitfield.disp64 = 0; i.types[op].bitfield.disp32s = 1; } - if (i.prefix[ADDR_PREFIX] - && fits_in_unsigned_long (op_disp)) - i.types[op].bitfield.disp32 = 1; } +#endif if ((i.types[op].bitfield.disp32 || i.types[op].bitfield.disp32s || i.types[op].bitfield.disp16) -- cgit v1.1