diff options
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r-- | gas/config/tc-i386.c | 67 |
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. */ |