summaryrefslogtreecommitdiff
path: root/gas/config/tc-i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r--gas/config/tc-i386.c67
1 files changed, 60 insertions, 7 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 3df0a47a030..a9314f560b7 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -6883,19 +6883,40 @@ match_template (char mnem_suffix)
case 1:
if (!operand_type_match (overlap0, i.types[0]))
continue;
+
+ /* Allow the ModR/M encoding to be requested by using the {load} or
+ {store} pseudo prefix on an applicable insn. */
+ if (!t->opcode_modifier.modrm
+ && i.reg_operands == 1
+ && ((i.dir_encoding == dir_encoding_load
+ && t->mnem_off != MN_pop)
+ || (i.dir_encoding == dir_encoding_store
+ && t->mnem_off != MN_push))
+ /* Avoid BSWAP. */
+ && t->mnem_off != MN_bswap)
+ continue;
break;
+
case 2:
/* xchg %eax, %eax is a special case. It is an alias for nop
only in 32bit mode and we can use opcode 0x90. In 64bit
mode, we can't use 0x90 for xchg %eax, %eax since it should
zero-extend %eax to %rax. */
- if (flag_code == CODE_64BIT
- && t->base_opcode == 0x90
- && t->opcode_space == SPACE_BASE
- && i.types[0].bitfield.instance == Accum
- && i.types[0].bitfield.dword
- && i.types[1].bitfield.instance == Accum)
- continue;
+ if (t->base_opcode == 0x90
+ && t->opcode_space == SPACE_BASE)
+ {
+ if (flag_code == CODE_64BIT
+ && i.types[0].bitfield.instance == Accum
+ && i.types[0].bitfield.dword
+ && i.types[1].bitfield.instance == Accum)
+ continue;
+
+ /* Allow the ModR/M encoding to be requested by using the
+ {load} or {store} pseudo prefix. */
+ if (i.dir_encoding == dir_encoding_load
+ || i.dir_encoding == dir_encoding_store)
+ continue;
+ }
if (t->base_opcode == MOV_AX_DISP32
&& t->opcode_space == SPACE_BASE
@@ -6909,6 +6930,38 @@ match_template (char mnem_suffix)
match the accumulator-only encoding of mov. */
if (i.hle_prefix)
continue;
+
+ /* Allow the ModR/M encoding to be requested by using a suitable
+ {load} or {store} pseudo prefix. */
+ if (i.dir_encoding == (i.types[0].bitfield.instance == Accum
+ ? dir_encoding_store
+ : dir_encoding_load)
+ && !i.types[0].bitfield.disp64
+ && !i.types[1].bitfield.disp64)
+ continue;
+ }
+
+ /* Allow the ModR/M encoding to be requested by using the {load} or
+ {store} pseudo prefix on an applicable insn. */
+ if (!t->opcode_modifier.modrm
+ && i.reg_operands == 1
+ && i.imm_operands == 1
+ && (i.dir_encoding == dir_encoding_load
+ || i.dir_encoding == dir_encoding_store)
+ && t->opcode_space == SPACE_BASE)
+ {
+ if (t->base_opcode == 0xb0 /* mov $imm, %reg */
+ && i.dir_encoding == dir_encoding_store)
+ continue;
+
+ if ((t->base_opcode | 0x38) == 0x3c /* <alu> $imm, %acc */
+ && (t->base_opcode != 0x3c /* cmp $imm, %acc */
+ || i.dir_encoding == dir_encoding_load))
+ continue;
+
+ if (t->base_opcode == 0xa8 /* test $imm, %acc */
+ && i.dir_encoding == dir_encoding_load)
+ continue;
}
/* Fall through. */