diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2019-11-08 09:31:06 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2019-11-08 09:31:17 -0800 |
commit | dc2be329b9508395b7270b7c3bebc19a6f1e2e07 (patch) | |
tree | 04840e8c94ba97be2d64220119e2a70cb77f9c39 /gas | |
parent | 992a70401ec229425ee75b2ad9b731f30d2de391 (diff) | |
download | fsf-binutils-gdb-dc2be329b9508395b7270b7c3bebc19a6f1e2e07.zip fsf-binutils-gdb-dc2be329b9508395b7270b7c3bebc19a6f1e2e07.tar.gz fsf-binutils-gdb-dc2be329b9508395b7270b7c3bebc19a6f1e2e07.tar.bz2 |
i386: Only check suffix in instruction mnemonic
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.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 9 | ||||
-rw-r--r-- | gas/config/tc-i386.c | 75 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/code16.d | 15 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/code16.s | 9 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/i386.exp | 1 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/x86-64-branch-4.l | 4 |
6 files changed, 69 insertions, 44 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 75e056c..29cf763 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +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, diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index ba6b82a..abbb93a 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -5693,7 +5693,7 @@ match_template (char mnem_suffix) 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; @@ -5708,33 +5708,33 @@ match_template (char mnem_suffix) 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. */ @@ -5768,23 +5768,14 @@ match_template (char mnem_suffix) || (!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); diff --git a/gas/testsuite/gas/i386/code16.d b/gas/testsuite/gas/i386/code16.d new file mode 100644 index 0000000..b860448 --- /dev/null +++ b/gas/testsuite/gas/i386/code16.d @@ -0,0 +1,15 @@ +#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 diff --git a/gas/testsuite/gas/i386/code16.s b/gas/testsuite/gas/i386/code16.s new file mode 100644 index 0000000..d18fa51 --- /dev/null +++ b/gas/testsuite/gas/i386/code16.s @@ -0,0 +1,9 @@ + .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] diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index ff2d235..4e7f8b9 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -132,6 +132,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] 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" diff --git a/gas/testsuite/gas/i386/x86-64-branch-4.l b/gas/testsuite/gas/i386/x86-64-branch-4.l index db55394..8f681f8 100644 --- a/gas/testsuite/gas/i386/x86-64-branch-4.l +++ b/gas/testsuite/gas/i386/x86-64-branch-4.l @@ -7,11 +7,11 @@ .*: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 |