diff options
author | Jan Beulich <jbeulich@novell.com> | 2018-03-08 08:25:31 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2018-03-08 08:25:31 +0100 |
commit | 73053c1fc454fe8554db170f1a30a3442546824e (patch) | |
tree | 1507f5205537d3d963418059c1617062ebd2e9ec /gas | |
parent | 6a7524c6aa18f5afa4977314eb01f0360e752789 (diff) | |
download | gdb-73053c1fc454fe8554db170f1a30a3442546824e.zip gdb-73053c1fc454fe8554db170f1a30a3442546824e.tar.gz gdb-73053c1fc454fe8554db170f1a30a3442546824e.tar.bz2 |
x86: fold AVX vcvtpd2ps memory forms
This requires a change to ModR/M handling: Recording of displacement
types must not discard operand size information. Change the respective
code to alter only .disp<N>.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 5 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 47 |
2 files changed, 42 insertions, 10 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 8a6161d..564a269 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +2018-03-08 Jan Beulich <jbeulich@suse.com> + + * config/tc-i386.c (operand_type_and_not): New. + (build_modrm_byte): Use it to prevent clearing unrelated bits. + 2018-03-08 Alan Modra <amodra@gmail.com> * config/tc-ppc.c (ppc_handle_align): Correct last patch. Really diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index a10a36c..24fa4c7 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -1786,6 +1786,26 @@ operand_type_and (i386_operand_type x, i386_operand_type y) } static INLINE i386_operand_type +operand_type_and_not (i386_operand_type x, i386_operand_type y) +{ + switch (ARRAY_SIZE (x.array)) + { + case 3: + x.array [2] &= ~y.array [2]; + /* Fall through. */ + case 2: + x.array [1] &= ~y.array [1]; + /* Fall through. */ + case 1: + x.array [0] &= ~y.array [0]; + break; + default: + abort (); + } + return x; +} + +static INLINE i386_operand_type operand_type_or (i386_operand_type x, i386_operand_type y) { switch (ARRAY_SIZE (x.array)) @@ -6867,6 +6887,8 @@ build_modrm_byte (void) fake_zero_displacement = 1; if (i.index_reg == 0) { + i386_operand_type newdisp; + gas_assert (!i.tm.opcode_modifier.vecsib); /* Operand is just <disp> */ if (flag_code == CODE_64BIT) @@ -6878,20 +6900,21 @@ build_modrm_byte (void) i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; i.sib.base = NO_BASE_REGISTER; i.sib.index = NO_INDEX_REGISTER; - i.types[op] = ((i.prefix[ADDR_PREFIX] == 0) - ? disp32s : disp32); + newdisp = (!i.prefix[ADDR_PREFIX] ? disp32s : disp32); } else if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)) { i.rm.regmem = NO_BASE_REGISTER_16; - i.types[op] = disp16; + newdisp = disp16; } else { i.rm.regmem = NO_BASE_REGISTER; - i.types[op] = disp32; + newdisp = disp32; } + i.types[op] = operand_type_and_not (i.types[op], anydisp); + i.types[op] = operand_type_or (i.types[op], newdisp); } else if (!i.tm.opcode_modifier.vecsib) { @@ -6973,14 +6996,18 @@ build_modrm_byte (void) if (flag_code == CODE_64BIT && operand_type_check (i.types[op], disp)) { - i386_operand_type temp; - operand_type_set (&temp, 0); - temp.bitfield.disp8 = i.types[op].bitfield.disp8; - i.types[op] = temp; + i.types[op].bitfield.disp16 = 0; + i.types[op].bitfield.disp64 = 0; if (i.prefix[ADDR_PREFIX] == 0) - i.types[op].bitfield.disp32s = 1; + { + i.types[op].bitfield.disp32 = 0; + i.types[op].bitfield.disp32s = 1; + } else - i.types[op].bitfield.disp32 = 1; + { + i.types[op].bitfield.disp32 = 1; + i.types[op].bitfield.disp32s = 0; + } } if (!i.tm.opcode_modifier.vecsib) |