aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2018-03-08 08:25:31 +0100
committerJan Beulich <jbeulich@suse.com>2018-03-08 08:25:31 +0100
commit73053c1fc454fe8554db170f1a30a3442546824e (patch)
tree1507f5205537d3d963418059c1617062ebd2e9ec /gas
parent6a7524c6aa18f5afa4977314eb01f0360e752789 (diff)
downloadgdb-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/ChangeLog5
-rw-r--r--gas/config/tc-i386.c47
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)