We should check suffix in instruction mnemonic when matching instruction.
In Intel syntax, normally we check for memory operand size. But the same
mnemonic with 2 different encodings can have the same memory operand
size and i.suffix is set to LONG_DOUBLE_MNEM_SUFFIX from memory operand
size in Intel syntax to distinguish them. When there is no suffix in
mnemonic, we check LONG_DOUBLE_MNEM_SUFFIX in i.suffix for mnemonic
suffix.
gas/
PR gas/25167
* config/tc-i386.c (match_template): Don't check instruction
suffix set from operand.
* testsuite/gas/i386/code16.d: New file.
* testsuite/gas/i386/code16.s: Likewise.
* testsuite/gas/i386/i386.exp: Run code16.
* testsuite/gas/i386/x86-64-branch-4.l: Updated.
opcodes/
PR gas/25167
* i386-opc.tbl: Remove IgnoreSize from cmpsd and movsd.
* i386-tbl.h: Regenerated.
+2019-11-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR gas/25167
+ * config/tc-i386.c (match_template): Don't check instruction
+ suffix set from operand.
+ * testsuite/gas/i386/code16.d: New file.
+ * testsuite/gas/i386/code16.s: Likewise.
+ * testsuite/gas/i386/i386.exp: Run code16.
+
2019-11-08 Jan Beulich <jbeulich@suse.com>
* config/tc-i386.c (optimize_encoding, build_modrm_byte,
i386_operand_type overlap0, overlap1, overlap2, overlap3;
i386_operand_type overlap4;
unsigned int found_reverse_match;
- i386_opcode_modifier suffix_check, mnemsuf_check;
+ i386_opcode_modifier suffix_check;
i386_operand_type operand_types [MAX_OPERANDS];
int addr_prefix_disp;
unsigned int j;
found_reverse_match = 0;
addr_prefix_disp = -1;
+ /* Prepare for mnemonic suffix check. */
memset (&suffix_check, 0, sizeof (suffix_check));
- if (intel_syntax && i.broadcast)
- /* nothing */;
- else if (i.suffix == BYTE_MNEM_SUFFIX)
- suffix_check.no_bsuf = 1;
- else if (i.suffix == WORD_MNEM_SUFFIX)
- suffix_check.no_wsuf = 1;
- else if (i.suffix == SHORT_MNEM_SUFFIX)
- suffix_check.no_ssuf = 1;
- else if (i.suffix == LONG_MNEM_SUFFIX)
- suffix_check.no_lsuf = 1;
- else if (i.suffix == QWORD_MNEM_SUFFIX)
- suffix_check.no_qsuf = 1;
- else if (i.suffix == LONG_DOUBLE_MNEM_SUFFIX)
- suffix_check.no_ldsuf = 1;
-
- memset (&mnemsuf_check, 0, sizeof (mnemsuf_check));
- if (intel_syntax)
+ switch (mnem_suffix)
{
- switch (mnem_suffix)
- {
- case BYTE_MNEM_SUFFIX: mnemsuf_check.no_bsuf = 1; break;
- case WORD_MNEM_SUFFIX: mnemsuf_check.no_wsuf = 1; break;
- case SHORT_MNEM_SUFFIX: mnemsuf_check.no_ssuf = 1; break;
- case LONG_MNEM_SUFFIX: mnemsuf_check.no_lsuf = 1; break;
- case QWORD_MNEM_SUFFIX: mnemsuf_check.no_qsuf = 1; break;
- }
+ case BYTE_MNEM_SUFFIX:
+ suffix_check.no_bsuf = 1;
+ break;
+ case WORD_MNEM_SUFFIX:
+ suffix_check.no_wsuf = 1;
+ break;
+ case SHORT_MNEM_SUFFIX:
+ suffix_check.no_ssuf = 1;
+ break;
+ case LONG_MNEM_SUFFIX:
+ suffix_check.no_lsuf = 1;
+ break;
+ case QWORD_MNEM_SUFFIX:
+ suffix_check.no_qsuf = 1;
+ break;
+ default:
+ /* NB: In Intel syntax, normally we can check for memory operand
+ size when there is no mnemonic suffix. But jmp and call have
+ 2 different encodings with Dword memory operand size, one with
+ No_ldSuf and the other without. i.suffix is set to
+ LONG_DOUBLE_MNEM_SUFFIX to skip the one with No_ldSuf. */
+ if (i.suffix == LONG_DOUBLE_MNEM_SUFFIX)
+ suffix_check.no_ldsuf = 1;
}
/* Must have right number of operands. */
|| (!intel64 && t->opcode_modifier.intel64))
continue;
- /* Check the suffix, except for some instructions in intel mode. */
+ /* Check the suffix. */
i.error = invalid_instruction_suffix;
- if ((!intel_syntax || !t->opcode_modifier.ignoresize)
- && ((t->opcode_modifier.no_bsuf && suffix_check.no_bsuf)
- || (t->opcode_modifier.no_wsuf && suffix_check.no_wsuf)
- || (t->opcode_modifier.no_lsuf && suffix_check.no_lsuf)
- || (t->opcode_modifier.no_ssuf && suffix_check.no_ssuf)
- || (t->opcode_modifier.no_qsuf && suffix_check.no_qsuf)
- || (t->opcode_modifier.no_ldsuf && suffix_check.no_ldsuf)))
- continue;
- /* In Intel mode all mnemonic suffixes must be explicitly allowed. */
- if ((t->opcode_modifier.no_bsuf && mnemsuf_check.no_bsuf)
- || (t->opcode_modifier.no_wsuf && mnemsuf_check.no_wsuf)
- || (t->opcode_modifier.no_lsuf && mnemsuf_check.no_lsuf)
- || (t->opcode_modifier.no_ssuf && mnemsuf_check.no_ssuf)
- || (t->opcode_modifier.no_qsuf && mnemsuf_check.no_qsuf)
- || (t->opcode_modifier.no_ldsuf && mnemsuf_check.no_ldsuf))
+ if ((t->opcode_modifier.no_bsuf && suffix_check.no_bsuf)
+ || (t->opcode_modifier.no_wsuf && suffix_check.no_wsuf)
+ || (t->opcode_modifier.no_lsuf && suffix_check.no_lsuf)
+ || (t->opcode_modifier.no_ssuf && suffix_check.no_ssuf)
+ || (t->opcode_modifier.no_qsuf && suffix_check.no_qsuf)
+ || (t->opcode_modifier.no_ldsuf && suffix_check.no_ldsuf))
continue;
size_match = operand_size_match (t);
--- /dev/null
+#objdump: -drw -mi8086
+#name: i386 with .code16
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <.text>:
+ +[a-f0-9]+: f3 66 a5 rep movsl %ds:\(%si\),%es:\(%di\)
+ +[a-f0-9]+: f3 66 a7 repz cmpsl %es:\(%di\),%ds:\(%si\)
+ +[a-f0-9]+: 66 f3 a5 rep movsl %ds:\(%si\),%es:\(%di\)
+ +[a-f0-9]+: 66 f3 a7 repz cmpsl %es:\(%di\),%ds:\(%si\)
+ +[a-f0-9]+: 66 f3 a5 rep movsl %ds:\(%si\),%es:\(%di\)
+ +[a-f0-9]+: 66 f3 a7 repz cmpsl %es:\(%di\),%ds:\(%si\)
+#pass
--- /dev/null
+ .text
+ .code16
+ rep; movsd
+ rep; cmpsd
+ rep movsd %ds:(%si),%es:(%di)
+ rep cmpsd %es:(%di),%ds:(%si)
+ .intel_syntax noprefix
+ rep movsd dword ptr es:[di], dword ptr ds:[si]
+ rep cmpsd dword ptr ds:[si], dword ptr es:[di]
run_dump_test "noreg32"
run_dump_test "addr16"
run_dump_test "addr32"
+ run_dump_test "code16"
run_list_test "oversized16" "-al"
run_dump_test "sse4_1"
run_dump_test "sse4_1-intel"
.*:9: Error: operand type mismatch for `call'
.*:10: Error: invalid instruction suffix for `call'
.*:11: Error: invalid instruction suffix for `call'
-.*:12: Error: invalid instruction suffix for `call'
+.*:12: Error: operand size mismatch for `call'
.*:13: Error: operand type mismatch for `jmp'
.*:14: Error: invalid instruction suffix for `jmp'
.*:15: Error: invalid instruction suffix for `jmp'
-.*:16: Error: invalid instruction suffix for `jmp'
+.*:16: Error: operand size mismatch for `jmp'
GAS LISTING .*
#...
[ ]*1[ ]+\.text
+2019-11-08 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR gas/25167
+ * i386-opc.tbl: Remove IgnoreSize from cmpsd and movsd.
+ * i386-tbl.h: Regenerated.
+
2019-11-08 Jan Beulich <jbeulich@suse.com>
* i386-gen.c (operand_type_init): Add Class= to
cmppd, 3, 0x660fc2, None, 2, CpuSSE2, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Imm8, RegXMM|Unspecified|BaseIndex, RegXMM }
// Intel mode string compare.
cmpsd, 0, 0xa7, None, 1, 0, Size32|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsString|RepPrefixOk, { 0 }
-cmpsd, 2, 0xa7, None, 1, 0, Size32|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsString|RepPrefixOk, { Dword|Unspecified|BaseIndex|EsSeg, Dword|Unspecified|BaseIndex }
+cmpsd, 2, 0xa7, None, 1, 0, Size32|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsString|RepPrefixOk, { Dword|Unspecified|BaseIndex|EsSeg, Dword|Unspecified|BaseIndex }
cmpsd, 3, 0xf2c2, None, 1, CpuAVX, Modrm|Vex=3|VexOpcode=0|VexVVVV=1|VexW=1|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { Imm8, Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
cmpsd, 3, 0xf20fc2, None, 2, CpuSSE2, Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Imm8, Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
comisd, 2, 0x662f, None, 1, CpuAVX, Modrm|Vex=3|VexOpcode=0|VexW=1|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
movntpd, 2, 0x660f2b, None, 2, CpuSSE2, Modrm|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { RegXMM, Xmmword|Unspecified|BaseIndex }
// Intel mode string move.
movsd, 0, 0xa5, None, 1, 0, Size32|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsString|RepPrefixOk, { 0 }
-movsd, 2, 0xa5, None, 1, 0, Size32|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsString|RepPrefixOk, { Dword|Unspecified|BaseIndex, Dword|Unspecified|BaseIndex|EsSeg }
+movsd, 2, 0xa5, None, 1, 0, Size32|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|IsString|RepPrefixOk, { Dword|Unspecified|BaseIndex, Dword|Unspecified|BaseIndex|EsSeg }
movsd, 2, 0xf210, None, 1, CpuAVX, D|Modrm|Vex=3|VexOpcode=0|VexW=1|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { Qword|Unspecified|BaseIndex, RegXMM }
movsd, 2, 0xf210, None, 1, CpuAVX, D|Modrm|Vex=3|VexOpcode=0|VexVVVV=1|VexW=1|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf|SSE2AVX, { RegXMM, RegXMM }
movsd, 2, 0xf20f10, None, 2, CpuSSE2, D|Modrm|IgnoreSize|No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_qSuf|No_ldSuf, { Qword|Unspecified|BaseIndex|RegXMM, RegXMM }
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 1, 1, 1, 1, 1,
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 1, 1, 1, 1,
1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0 },
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 1, 1, 1, 1, 1,
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 1, 1, 1, 1,
1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0 },