Properly handle multiple opcode prefixes
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 2 May 2014 18:22:04 +0000 (11:22 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 5 May 2014 21:25:14 +0000 (14:25 -0700)
This patch updates multiple opcode prefix processing:

1. Always print prefix together with bad opcode.
2. Since the last seen segment register prefix is active, we only print
the active segment register in the memory operand.
3. The 0xf2 and 0xf3 prefixes take precedence over the 0x66 prefix as the
opcode prefix.  Also the last of the 0xf2 and 0xf3 prefixes wins.
4. Ignore invalid 0xf2/0xf3 prefixes if they aren't mandatory.

gas/testsuite/

PR binutils/16893
* gas/i386/katmai.d: Expect "gs" as prefix.

* gas/i386/long-1.s: Replace movapd with movss.
* gas/i386/x86-64-long-1.s: Likewise.
* gas/i386/long-1-intel.d: Updated.
* gas/i386/long-1.d: Likewise.
* gas/i386/x86-64-long-1-intel.d: Likewise.
* gas/i386/x86-64-long-1.d: Likewise.

* gas/i386/prefix.s: Add tests for multiple 0x66, 0x67, 0xf0,
0xf2 and 0xf3 prefixes.
* gas/i386/prefix.d: Updated.

opcodes/

PR binutils/16893
* i386-dis.c (twobyte_has_mandatory_prefix): New variable.
(end_codep): Likewise.
(mandatory_prefix): Likewise.
(active_seg_prefix): Likewise.
(ckprefix): Set active_seg_prefix to the active segment register
prefix.
(seg_prefix): Removed.
(get_valid_dis386): Use the last of PREFIX_REPNZ and PREFIX_REPZ
for prefix index.  Ignore the index if it is invalid and the
mandatory prefix isn't required.
(print_insn): Set mandatory_prefix if the PREFIX_XXX prefix is
mandatory.  Don't set PREFIX_REPZ/PREFIX_REPNZ/PREFIX_LOCK bits
in used_prefixes here.  Don't print unused prefixes.  Check
active_seg_prefix for the active segment register prefix.
Restore the DFLAG bit in sizeflag if the data size prefix is
unused.  Check the unused mandatory PREFIX_XXX prefixes
(append_seg): Only print the segment register which gets used.
(OP_E_memory): Check active_seg_prefix for the segment register
prefix.
(OP_OFF): Likewise.
(OP_OFF64): Likewise.
(OP_DSreg): Set active_seg_prefix to PREFIX_DS if it is unset.

12 files changed:
gas/testsuite/ChangeLog
gas/testsuite/gas/i386/katmai.d
gas/testsuite/gas/i386/long-1-intel.d
gas/testsuite/gas/i386/long-1.d
gas/testsuite/gas/i386/long-1.s
gas/testsuite/gas/i386/prefix.d
gas/testsuite/gas/i386/prefix.s
gas/testsuite/gas/i386/x86-64-long-1-intel.d
gas/testsuite/gas/i386/x86-64-long-1.d
gas/testsuite/gas/i386/x86-64-long-1.s
opcodes/ChangeLog
opcodes/i386-dis.c

index 928adc4a0017321f2bc18c2168416cba15638364..8a92fe925a30068ac8192bc95df089233a2370d0 100644 (file)
@@ -1,3 +1,19 @@
+2014-05-05  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/16893
+       * gas/i386/katmai.d: Expect "gs" as prefix.
+
+       * gas/i386/long-1.s: Replace movapd with movss.
+       * gas/i386/x86-64-long-1.s: Likewise.
+       * gas/i386/long-1-intel.d: Updated.
+       * gas/i386/long-1.d: Likewise.
+       * gas/i386/x86-64-long-1-intel.d: Likewise.
+       * gas/i386/x86-64-long-1.d: Likewise.
+
+       * gas/i386/prefix.s: Add tests for multiple 0x66, 0x67, 0xf0,
+       0xf2 and 0xf3 prefixes.
+       * gas/i386/prefix.d: Updated.
+
 2014-05-02  H.J. Lu  <hongjiu.lu@intel.com>
 
        * gas/i386/opcode-intel.d: Undo the last change.
index a1c6b97964ab5918482744f85dc0e3286cc81191..50e573f60e379f9253260c6d75140aefdc6b41bd 100644 (file)
@@ -160,7 +160,6 @@ Disassembly of section .text:
  237:  0f 18 0c 98 [   ]*prefetcht0 \(%eax,%ebx,4\)
  23b:  0f 18 12 [      ]*prefetcht1 \(%edx\)
  23e:  0f 18 19 [      ]*prefetcht2 \(%ecx\)
- 241:  65 [    ]*gs
- 242:  0f ae[  ]*\(bad\).*
+ 241:  65 0f ae[       ]*gs \(bad\).*
  244:  ff 00 [         ]*incl   \(%eax\)
 #pass
index 7a734626abfd804eb50d74ee6359109663f377f9..2e5213641bead8eba8a5a31c2c33e57c3e12683d 100644 (file)
@@ -8,7 +8,7 @@
 Disassembly of section .text:
 
 0+ <foo>:
-[      ]*[a-f0-9]+:    f2 f0 f0 f0 f2 f2 f2 f2 f2 f2 f0 f0 66 0f 28    repnz lock lock lock repnz repnz repnz repnz repnz repnz lock lock \(bad\)
+[      ]*[a-f0-9]+:    f2 f0 f0 f0 f2 f2 f2 f2 f2 f2 f0 f0 f3 0f 10    repnz lock lock lock repnz repnz repnz repnz repnz repnz lock lock \(bad\)
 [      ]*[a-f0-9]+:    00 f2                   add    dl,dh
-[      ]*[a-f0-9]+:    f0 f0 f0 f2 f2 f2 f2 f0 f0 f0 f0 66 0f 28 00    lock lock lock repnz repnz repnz repnz lock lock lock lock movapd xmm0,XMMWORD PTR \[eax\]
+[      ]*[a-f0-9]+:    f0 f0 f0 f2 f2 f2 f2 f0 f0 f0 f0 f3 0f 10 00    lock lock lock repnz repnz repnz repnz lock lock lock lock movss xmm0,DWORD PTR \[eax\]
 #pass
index 1dccd3674affb8fd15341fa686f11106f6b84add..a8cd073b35a640297a3d1f7efde1ef664223ecbe 100644 (file)
@@ -7,7 +7,7 @@
 Disassembly of section .text:
 
 0+ <foo>:
-[      ]*[a-f0-9]+:    f2 f0 f0 f0 f2 f2 f2 f2 f2 f2 f0 f0 66 0f 28    repnz lock lock lock repnz repnz repnz repnz repnz repnz lock lock \(bad\)
+[      ]*[a-f0-9]+:    f2 f0 f0 f0 f2 f2 f2 f2 f2 f2 f0 f0 f3 0f 10    repnz lock lock lock repnz repnz repnz repnz repnz repnz lock lock \(bad\)
 [      ]*[a-f0-9]+:    00 f2                   add    %dh,%dl
-[      ]*[a-f0-9]+:    f0 f0 f0 f2 f2 f2 f2 f0 f0 f0 f0 66 0f 28 00    lock lock lock repnz repnz repnz repnz lock lock lock lock movapd \(%eax\),%xmm0
+[      ]*[a-f0-9]+:    f0 f0 f0 f2 f2 f2 f2 f0 f0 f0 f0 f3 0f 10 00    lock lock lock repnz repnz repnz repnz lock lock lock lock movss \(%eax\),%xmm0
 #pass
index 4551068bc5334e31f5a57f755386e583f2180380..b7e509dea88461e9a933220e3fddb5b675939a5c 100644 (file)
@@ -14,7 +14,7 @@ foo:
 .byte 0xf2
 .byte 0xf0
 .byte 0xf0
-movapd (%eax), %xmm0
+movss  (%eax), %xmm0
 .byte 0xf2
 .byte 0xf0
 .byte 0xf0
@@ -27,4 +27,4 @@ movapd        (%eax), %xmm0
 .byte 0xf0
 .byte 0xf0
 .byte 0xf0
-movapd (%eax), %xmm0
+movss  (%eax), %xmm0
index 4139658cac8ddf296dcad36d3b818b75c4dec7c9..d9f0ae2e78768617575af10d2e20eac44ed32e4f 100644 (file)
@@ -5,11 +5,60 @@
 
 Disassembly of section .text:
 
-0+000 <foo>:
-   0:  9b 26 67 d9 3c[         ]+fstcw[        ]+%es:\(%si\)
-   5:  9b df e0 [      ]*fstsw  %ax
-   8:  9b df e0 [      ]*fstsw  %ax
-   b:  9b 67 df e0 [   ]*addr16 fstsw %ax
-   f:  36 67 66 f3 a7 [        ]*repz cmpsw %es:\(%di\),%ss:\(%si\)
-  14:  26 9b[  ]*es fwait
+0+ <foo>:
+[      ]*[a-f0-9]+:    9b 26 67 d9 3c          fstcw  %es:\(%si\)
+[      ]*[a-f0-9]+:    9b df e0                fstsw  %ax
+[      ]*[a-f0-9]+:    9b df e0                fstsw  %ax
+[      ]*[a-f0-9]+:    9b 67 df e0             addr16 fstsw %ax
+[      ]*[a-f0-9]+:    36 67 66 f3 a7          repz cmpsw %es:\(%di\),%ss:\(%si\)
+[      ]*[a-f0-9]+:    26 9b                   es fwait
+[      ]*[a-f0-9]+:    66 f2 0f 38 17          data16 \(bad\) 
+[      ]*[a-f0-9]+:    f2 66 0f 54             repnz \(bad\)
+[      ]*[a-f0-9]+:    f2 0f 54                repnz \(bad\)
+[      ]*[a-f0-9]+:    f2 66 0f 11 22          data16 movsd %xmm4,\(%edx\)
+[      ]*[a-f0-9]+:    f2 67 66 0f 11 22       data16 movsd %xmm4,\(%bp,%si\)
+[      ]*[a-f0-9]+:    f2 67 f0 66 0f 11 22    lock data16 movsd %xmm4,\(%bp,%si\)
+[      ]*[a-f0-9]+:    f3 66 0f 11 22          data16 movss %xmm4,\(%edx\)
+[      ]*[a-f0-9]+:    f3 67 f0 66 0f 11 22    lock data16 movss %xmm4,\(%bp,%si\)
+[      ]*[a-f0-9]+:    f3 67 f2 66 0f 11 22    repz data16 movsd %xmm4,\(%bp,%si\)
+[      ]*[a-f0-9]+:    f3 66 3e 0f 11 22       data16 movss %xmm4,%ds:\(%edx\)
+[      ]*[a-f0-9]+:    f2 66 36 0f 11 22       data16 movsd %xmm4,%ss:\(%edx\)
+[      ]*[a-f0-9]+:    f3 f0 f2 66 36 0f 11 22         repz lock data16 movsd %xmm4,%ss:\(%edx\)
+[      ]*[a-f0-9]+:    f2 66 3e 36 0f 11 22    data16 ds movsd %xmm4,%ss:\(%edx\)
+[      ]*[a-f0-9]+:    f2 67 66 3e 36 0f 11 22         data16 ds movsd %xmm4,%ss:\(%bp,%si\)
+[      ]*[a-f0-9]+:    f2 67 f0 66 3e 36 0f 11 22      lock data16 ds movsd %xmm4,%ss:\(%bp,%si\)
+[      ]*[a-f0-9]+:    f3 66 3e 36 0f 11 22    data16 ds movss %xmm4,%ss:\(%edx\)
+[      ]*[a-f0-9]+:    f3 f0 66 3e 36 0f 11 22         lock data16 ds movss %xmm4,%ss:\(%edx\)
+[      ]*[a-f0-9]+:    f3 67 f2 66 3e 36 0f 11 22      repz data16 ds movsd %xmm4,%ss:\(%bp,%si\)
+[      ]*[a-f0-9]+:    f2 66 90                repnz xchg %ax,%ax
+[      ]*[a-f0-9]+:    f2 67 66 90             repnz addr16 xchg %ax,%ax
+[      ]*[a-f0-9]+:    f2 67 f0 66 90          repnz addr16 lock xchg %ax,%ax
+[      ]*[a-f0-9]+:    f3 66 90                data16 pause 
+[      ]*[a-f0-9]+:    f3 67 f0 66 90          addr16 lock data16 pause 
+[      ]*[a-f0-9]+:    f3 67 f2 66 90          repz addr16 repnz xchg %ax,%ax
+[      ]*[a-f0-9]+:    f2 3e 90                repnz ds nop
+[      ]*[a-f0-9]+:    f2 f0 67 3e 90          repnz lock addr16 ds nop
+[      ]*[a-f0-9]+:    f3 3e 90                ds pause 
+[      ]*[a-f0-9]+:    f3 66 3e 90             data16 ds pause 
+[      ]*[a-f0-9]+:    f3 f0 3e 90             lock ds pause 
+[      ]*[a-f0-9]+:    f3 f0 67 3e 90          lock addr16 ds pause 
+[      ]*[a-f0-9]+:    f3 f2 67 3e 90          repz repnz addr16 ds nop
+[      ]*[a-f0-9]+:    66 f0 36 90             lock ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    f2 36 90                repnz ss nop
+[      ]*[a-f0-9]+:    f2 66 36 90             repnz ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    f2 f0 36 90             repnz lock ss nop
+[      ]*[a-f0-9]+:    f2 f0 67 36 90          repnz lock addr16 ss nop
+[      ]*[a-f0-9]+:    f3 36 90                ss pause 
+[      ]*[a-f0-9]+:    f3 67 36 90             addr16 ss pause 
+[      ]*[a-f0-9]+:    f3 f0 67 36 90          lock addr16 ss pause 
+[      ]*[a-f0-9]+:    f3 f2 36 90             repz repnz ss nop
+[      ]*[a-f0-9]+:    f3 f2 67 36 90          repz repnz addr16 ss nop
+[      ]*[a-f0-9]+:    f3 f0 f2 66 36 90       repz lock repnz ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    66 3e 36 90             ds ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    67 66 3e 36 90          addr16 ds ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    67 f0 66 3e 36 90       addr16 lock ds ss xchg %ax,%ax
+[      ]*[a-f0-9]+:    f3 66 3e 36 90          data16 ds ss pause 
+[      ]*[a-f0-9]+:    f3 f0 66 3e 36 90       lock data16 ds ss pause 
+[      ]*[a-f0-9]+:    f3 f2 67 3e 36 90       repz repnz addr16 ds ss nop
+[      ]*[a-f0-9]+:    f3 67 f2 66 3e 36 90    repz addr16 repnz ds ss xchg %ax,%ax
 #pass
index 2bf3c71f59e63cb3b991cc934c61967e29e79421..07020ead08cc675c5974603fb6c1f1f2a970cbc7 100644 (file)
@@ -4,5 +4,357 @@
 
  es fwait
 
+       .byte 0x66
+       .byte 0xf2
+       .byte 0x0f
+       .byte 0x38
+       .byte 0x17
+
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x0f
+       .byte 0x54
+
+       .byte 0xf2
+       .byte 0x0f
+       .byte 0x54
+
+# data16 movsd %xmm4,(%edx)
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# data16 movsd %xmm4,(%bp,%si)
+       .byte 0xf2
+       .byte 0x67
+       .byte 0x66
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# lock data16 movsd %xmm4,(%bp,%si)
+       .byte 0xf2
+       .byte 0x67
+       .byte 0xf0
+       .byte 0x66
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# data16 movss %xmm4,(%edx)
+       .byte 0xf3
+       .byte 0x66
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# lock data16 movss %xmm4,(%bp,%si)
+       .byte 0xf3
+       .byte 0x67
+       .byte 0xf0
+       .byte 0x66
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# repz data16 movsd %xmm4,(%bp,%si)
+       .byte 0xf3
+       .byte 0x67
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# data16 movss %xmm4,%ds:(%edx)
+       .byte 0xf3
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# data16 movsd %xmm4,%ss:(%edx)
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x36
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# repz lock data16 movsd %xmm4,%ss:(%edx)
+       .byte 0xf3
+       .byte 0xf0
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x36
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# data16 ds movsd %xmm4,%ss:(%edx)
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# data16 ds movsd %xmm4,%ss:(%bp,%si)
+       .byte 0xf2
+       .byte 0x67
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# lock data16 ds movsd %xmm4,%ss:(%bp,%si)
+       .byte 0xf2
+       .byte 0x67
+       .byte 0xf0
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# data16 ds movss %xmm4,%ss:(%edx)
+       .byte 0xf3
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# lock data16 ds movss %xmm4,%ss:(%edx)
+       .byte 0xf3
+       .byte 0xf0
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# repz data16 ds movsd %xmm4,%ss:(%bp,%si)
+       .byte 0xf3
+       .byte 0x67
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x0f
+       .byte 0x11
+       .byte 0x22
+
+# repnz; xchg %ax,%ax
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x90
+
+# repnz; addr16 xchg %ax,%ax
+       .byte 0xf2
+       .byte 0x67
+       .byte 0x66
+       .byte 0x90
+
+# repnz; addr16 lock xchg %ax,%ax
+       .byte 0xf2
+       .byte 0x67
+       .byte 0xf0
+       .byte 0x66
+       .byte 0x90
+
+# data16 pause
+       .byte 0xf3
+       .byte 0x66
+       .byte 0x90
+
+# addr16 lock data16 pause
+       .byte 0xf3
+       .byte 0x67
+       .byte 0xf0
+       .byte 0x66
+       .byte 0x90
+
+# repz; addr16; repnz; xchg %ax,%ax
+       .byte 0xf3
+       .byte 0x67
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x90
+
+# repnz; ds nop
+       .byte 0xf2
+       .byte 0x3e
+       .byte 0x90
+
+# repnz; lock addr16 ds nop
+       .byte 0xf2
+       .byte 0xf0
+       .byte 0x67
+       .byte 0x3e
+       .byte 0x90
+
+# ds pause
+       .byte 0xf3
+       .byte 0x3e
+       .byte 0x90
+
+# data16 ds pause
+       .byte 0xf3
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x90
+
+# lock ds pause
+       .byte 0xf3
+       .byte 0xf0
+       .byte 0x3e
+       .byte 0x90
+
+# lock addr16 ds pause
+       .byte 0xf3
+       .byte 0xf0
+       .byte 0x67
+       .byte 0x3e
+       .byte 0x90
+
+# repz; repnz; addr16 ds nop
+       .byte 0xf3
+       .byte 0xf2
+       .byte 0x67
+       .byte 0x3e
+       .byte 0x90
+
+# lock ss xchg %ax,%ax
+       .byte 0x66
+       .byte 0xf0
+       .byte 0x36
+       .byte 0x90
+
+# repnz; ss nop
+       .byte 0xf2
+       .byte 0x36
+       .byte 0x90
+
+# repnz; ss xchg %ax,%ax
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x36
+       .byte 0x90
+
+# repnz; lock ss nop
+       .byte 0xf2
+       .byte 0xf0
+       .byte 0x36
+       .byte 0x90
+
+# repnz; lock addr16 ss nop
+       .byte 0xf2
+       .byte 0xf0
+       .byte 0x67
+       .byte 0x36
+       .byte 0x90
+
+# ss pause
+       .byte 0xf3
+       .byte 0x36
+       .byte 0x90
+
+# addr16 ss pause
+       .byte 0xf3
+       .byte 0x67
+       .byte 0x36
+       .byte 0x90
+
+# lock addr16 ss pause
+       .byte 0xf3
+       .byte 0xf0
+       .byte 0x67
+       .byte 0x36
+       .byte 0x90
+
+# repz; repnz; ss nop
+       .byte 0xf3
+       .byte 0xf2
+       .byte 0x36
+       .byte 0x90
+
+# repz; repnz; addr16 ss nop
+       .byte 0xf3
+       .byte 0xf2
+       .byte 0x67
+       .byte 0x36
+       .byte 0x90
+
+# repz; lock; repnz; ss xchg %ax,%ax
+       .byte 0xf3
+       .byte 0xf0
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x36
+       .byte 0x90
+
+# ds ss xchg %ax,%ax
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x90
+
+# addr16 ds ss xchg %ax,%ax
+       .byte 0x67
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x90
+
+# addr16 lock ds ss xchg %ax,%ax
+       .byte 0x67
+       .byte 0xf0
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x90
+
+# data16 ds ss pause
+       .byte 0xf3
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x90
+
+# lock data16 ds ss pause
+       .byte 0xf3
+       .byte 0xf0
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x90
+
+# repz; repnz; addr16 ds ss nop
+       .byte 0xf3
+       .byte 0xf2
+       .byte 0x67
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x90
+
+# repz; addr16; repnz; ds ss xchg %ax,%ax
+       .byte 0xf3
+       .byte 0x67
+       .byte 0xf2
+       .byte 0x66
+       .byte 0x3e
+       .byte 0x36
+       .byte 0x90
+
 # Get a good alignment.
  .p2align      4,0
index 28b291a5854dca5e27dd1384a0d65beaa9e797f8..0ced3f0ba0fea2a469c6637bdf6872943db9e922 100644 (file)
@@ -8,7 +8,7 @@
 Disassembly of section .text:
 
 0+ <foo>:
-[      ]*[a-f0-9]+:    f2 f0 f0 f0 f2 f2 f2 f2 f2 f2 f0 f0 66 0f 28    repnz lock lock lock repnz repnz repnz repnz repnz repnz lock lock \(bad\)
+[      ]*[a-f0-9]+:    f2 f0 f0 f0 f2 f2 f2 f2 f2 f2 f0 f0 f3 0f 10    repnz lock lock lock repnz repnz repnz repnz repnz repnz lock lock \(bad\)
 [      ]*[a-f0-9]+:    00 f2                   add    dl,dh
-[      ]*[a-f0-9]+:    f0 f0 f0 f2 f2 f2 f2 f0 f0 f0 f0 66 0f 28 00    lock lock lock repnz repnz repnz repnz lock lock lock lock movapd xmm0,XMMWORD PTR \[rax\]
+[      ]*[a-f0-9]+:    f0 f0 f0 f2 f2 f2 f2 f0 f0 f0 f0 f3 0f 10 00    lock lock lock repnz repnz repnz repnz lock lock lock lock movss xmm0,DWORD PTR \[rax\]
 #pass
index dbb603a9f321198d144143b9d3f6a7c095b7a75e..20be6f431c569127cc2dc1bfb826eac38c886191 100644 (file)
@@ -7,7 +7,7 @@
 Disassembly of section .text:
 
 0+ <foo>:
-[      ]*[a-f0-9]+:    f2 f0 f0 f0 f2 f2 f2 f2 f2 f2 f0 f0 66 0f 28    repnz lock lock lock repnz repnz repnz repnz repnz repnz lock lock \(bad\)
+[      ]*[a-f0-9]+:    f2 f0 f0 f0 f2 f2 f2 f2 f2 f2 f0 f0 f3 0f 10    repnz lock lock lock repnz repnz repnz repnz repnz repnz lock lock \(bad\)
 [      ]*[a-f0-9]+:    00 f2                   add    %dh,%dl
-[      ]*[a-f0-9]+:    f0 f0 f0 f2 f2 f2 f2 f0 f0 f0 f0 66 0f 28 00    lock lock lock repnz repnz repnz repnz lock lock lock lock movapd \(%rax\),%xmm0
+[      ]*[a-f0-9]+:    f0 f0 f0 f2 f2 f2 f2 f0 f0 f0 f0 f3 0f 10 00    lock lock lock repnz repnz repnz repnz lock lock lock lock movss \(%rax\),%xmm0
 #pass
index 73f9a533a2805ebf2b67e2e786abbf03d9b46f45..2b912428dc062739145eb1d09f0b3482ead03cd3 100644 (file)
@@ -14,7 +14,7 @@ foo:
 .byte 0xf2
 .byte 0xf0
 .byte 0xf0
-movapd (%rax), %xmm0
+movss  (%rax), %xmm0
 .byte 0xf2
 .byte 0xf0
 .byte 0xf0
@@ -27,4 +27,4 @@ movapd        (%rax), %xmm0
 .byte 0xf0
 .byte 0xf0
 .byte 0xf0
-movapd (%rax), %xmm0
+movss  (%rax), %xmm0
index 2e4affeb47161d5d75a6961f4b53c2c4701c7ada..47555e6b262c31ddf2e8dc4f6a523e86017489e9 100644 (file)
@@ -1,3 +1,29 @@
+2014-05-05  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/16893
+       * i386-dis.c (twobyte_has_mandatory_prefix): New variable.
+       (end_codep): Likewise.
+       (mandatory_prefix): Likewise.
+       (active_seg_prefix): Likewise.
+       (ckprefix): Set active_seg_prefix to the active segment register
+       prefix.
+       (seg_prefix): Removed.
+       (get_valid_dis386): Use the last of PREFIX_REPNZ and PREFIX_REPZ
+       for prefix index.  Ignore the index if it is invalid and the
+       mandatory prefix isn't required.
+       (print_insn): Set mandatory_prefix if the PREFIX_XXX prefix is
+       mandatory.  Don't set PREFIX_REPZ/PREFIX_REPNZ/PREFIX_LOCK bits
+       in used_prefixes here.  Don't print unused prefixes.  Check
+       active_seg_prefix for the active segment register prefix.
+       Restore the DFLAG bit in sizeflag if the data size prefix is
+       unused.  Check the unused mandatory PREFIX_XXX prefixes
+       (append_seg): Only print the segment register which gets used.
+       (OP_E_memory): Check active_seg_prefix for the segment register
+       prefix.
+       (OP_OFF): Likewise.
+       (OP_OFF64): Likewise.
+       (OP_DSreg): Set active_seg_prefix to PREFIX_DS if it is unset.
+
 2014-05-02  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR binutils/16886
index 99bb4828333d77e219bc0044989509a1bb605152..0ec27ca70774fef6844c6f7f7a52433e44b86589 100644 (file)
@@ -2845,6 +2845,29 @@ static const unsigned char twobyte_has_modrm[256] = {
   /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
 };
 
+static const unsigned char twobyte_has_mandatory_prefix[256] = {
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+  /*       -------------------------------        */
+  /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
+  /* 10 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 1f */
+  /* 20 */ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0, /* 2f */
+  /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */
+  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
+  /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */
+  /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
+  /* 70 */ 1,0,0,0,1,1,1,1,0,0,1,1,1,1,1,1, /* 7f */
+  /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
+  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
+  /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
+  /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
+  /* c0 */ 0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0, /* cf */
+  /* d0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
+  /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
+  /* f0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0  /* ff */
+  /*       -------------------------------        */
+  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f        */
+};
+
 static char obuf[100];
 static char *obufp;
 static char *mnemonicendp;
@@ -2852,6 +2875,7 @@ static char scratchbuf[100];
 static unsigned char *start_codep;
 static unsigned char *insn_codep;
 static unsigned char *codep;
+static unsigned char *end_codep;
 static int last_lock_prefix;
 static int last_repz_prefix;
 static int last_repnz_prefix;
@@ -2859,6 +2883,10 @@ static int last_data_prefix;
 static int last_addr_prefix;
 static int last_rex_prefix;
 static int last_seg_prefix;
+/* The PREFIX_REPZ/PREFIX_REPNZ/PREFIX_DATA prefix is mandatory.  */
+static int mandatory_prefix;
+/* The active segment register prefix.  */
+static int active_seg_prefix;
 #define MAX_CODE_LENGTH 15
 /* We can up to 14 prefixes since the maximum instruction length is
    15bytes.  */
@@ -11607,6 +11635,7 @@ ckprefix (void)
   last_addr_prefix = -1;
   last_rex_prefix = -1;
   last_seg_prefix = -1;
+  active_seg_prefix = 0;
   for (i = 0; i < (int) ARRAY_SIZE (all_prefixes); i++)
     all_prefixes[i] = 0;
   i = 0;
@@ -11656,26 +11685,32 @@ ckprefix (void)
        case 0x2e:
          prefixes |= PREFIX_CS;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_CS;
          break;
        case 0x36:
          prefixes |= PREFIX_SS;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_SS;
          break;
        case 0x3e:
          prefixes |= PREFIX_DS;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_DS;
          break;
        case 0x26:
          prefixes |= PREFIX_ES;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_ES;
          break;
        case 0x64:
          prefixes |= PREFIX_FS;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_FS;
          break;
        case 0x65:
          prefixes |= PREFIX_GS;
          last_seg_prefix = i;
+         active_seg_prefix = PREFIX_GS;
          break;
        case 0x66:
          prefixes |= PREFIX_DATA;
@@ -11718,28 +11753,6 @@ ckprefix (void)
   return 0;
 }
 
-static int
-seg_prefix (int pref)
-{
-  switch (pref)
-    {
-    case 0x2e:
-      return PREFIX_CS;
-    case 0x36:
-      return PREFIX_SS;
-    case 0x3e:
-      return PREFIX_DS;
-    case 0x26:
-      return PREFIX_ES;
-    case 0x64:
-      return PREFIX_FS;
-    case 0x65:
-      return PREFIX_GS;
-    default:
-      return 0;
-    }
-}
-
 /* Return the name of the prefix byte PREF, or NULL if PREF is not a
    prefix byte.  */
 
@@ -11961,32 +11974,47 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
        }
       else
        {
+         int last_prefix = -1;
+         int prefix = 0;
          vindex = 0;
-         used_prefixes |= (prefixes & PREFIX_REPZ);
-         if (prefixes & PREFIX_REPZ)
-           {
-             vindex = 1;
-             all_prefixes[last_repz_prefix] = 0;
-           }
-         else
+         /* We check PREFIX_REPNZ and PREFIX_REPZ before PREFIX_DATA.
+            When there are multiple PREFIX_REPNZ and PREFIX_REPZ, the
+            last one wins.  */
+         if ((prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) != 0)
            {
-             /* We should check PREFIX_REPNZ and PREFIX_REPZ before
-                PREFIX_DATA.  */
-             used_prefixes |= (prefixes & PREFIX_REPNZ);
-             if (prefixes & PREFIX_REPNZ)
+             if (last_repz_prefix > last_repnz_prefix)
                {
-                 vindex = 3;
-                 all_prefixes[last_repnz_prefix] = 0;
+                 vindex = 1;
+                 prefix = PREFIX_REPZ;
+                 last_prefix = last_repz_prefix;
                }
              else
                {
-                 used_prefixes |= (prefixes & PREFIX_DATA);
-                 if (prefixes & PREFIX_DATA)
-                   {
-                     vindex = 2;
-                     all_prefixes[last_data_prefix] = 0;
-                   }
+                 vindex = 3;
+                 prefix = PREFIX_REPNZ;
+                 last_prefix = last_repnz_prefix;
                }
+
+             /* Ignore the invalid index if it isn't mandatory.  */
+             if (!mandatory_prefix
+                 && (prefix_table[dp->op[1].bytemode][vindex].name
+                     == NULL)
+                 && (prefix_table[dp->op[1].bytemode][vindex].op[0].bytemode
+                     == 0))
+               vindex = 0;
+           }
+
+         if (vindex == 0 && (prefixes & PREFIX_DATA) != 0)
+           {
+             vindex = 2;
+             prefix = PREFIX_DATA;
+             last_prefix = last_data_prefix;
+           }
+
+         if (vindex != 0)
+           {
+             used_prefixes |= prefix;
+             all_prefixes[last_prefix] = 0;
            }
        }
       dp = &prefix_table[dp->op[1].bytemode][vindex];
@@ -12001,6 +12029,7 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
       FETCH_DATA (info, codep + 2);
       vindex = *codep++;
       dp = &three_byte_table[dp->op[1].bytemode][vindex];
+      end_codep = codep;
       modrm.mod = (*codep >> 6) & 3;
       modrm.reg = (*codep >> 3) & 7;
       modrm.rm = *codep & 7;
@@ -12083,6 +12112,7 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
       vindex = *codep++;
       dp = &xop_table[vex_table_index][vindex];
 
+      end_codep = codep;
       FETCH_DATA (info, codep + 1);
       modrm.mod = (*codep >> 6) & 3;
       modrm.reg = (*codep >> 3) & 7;
@@ -12144,6 +12174,7 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
       codep++;
       vindex = *codep++;
       dp = &vex_table[vex_table_index][vindex];
+      end_codep = codep;
       /* There is no MODRM byte for VEX [82|77].  */
       if (vindex != 0x77 && vindex != 0x82)
        {
@@ -12192,6 +12223,7 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
       codep++;
       vindex = *codep++;
       dp = &vex_table[dp->op[1].bytemode][vindex];
+      end_codep = codep;
       /* There is no MODRM byte for VEX [82|77].  */
       if (vindex != 0x77 && vindex != 0x82)
        {
@@ -12286,6 +12318,7 @@ get_valid_dis386 (const struct dis386 *dp, disassemble_info *info)
       codep++;
       vindex = *codep++;
       dp = &evex_table[vex_table_index][vindex];
+      end_codep = codep;
       FETCH_DATA (info, codep + 1);
       modrm.mod = (*codep >> 6) & 3;
       modrm.reg = (*codep >> 3) & 7;
@@ -12565,22 +12598,17 @@ print_insn (bfd_vma pc, disassemble_info *info)
       threebyte = *++codep;
       dp = &dis386_twobyte[threebyte];
       need_modrm = twobyte_has_modrm[*codep];
+      mandatory_prefix = twobyte_has_mandatory_prefix[*codep];
       codep++;
     }
   else
     {
       dp = &dis386[*codep];
       need_modrm = onebyte_has_modrm[*codep];
+      mandatory_prefix = 0;
       codep++;
     }
 
-  if ((prefixes & PREFIX_REPZ))
-    used_prefixes |= PREFIX_REPZ;
-  if ((prefixes & PREFIX_REPNZ))
-    used_prefixes |= PREFIX_REPNZ;
-  if ((prefixes & PREFIX_LOCK))
-    used_prefixes |= PREFIX_LOCK;
-
   default_prefixes = 0;
   if (prefixes & PREFIX_ADDR)
     {
@@ -12615,6 +12643,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
        }
     }
 
+  end_codep = codep;
   if (need_modrm)
     {
       FETCH_DATA (info, codep + 1);
@@ -12663,24 +12692,6 @@ print_insn (bfd_vma pc, disassemble_info *info)
        }
     }
 
-  /* See if any prefixes were not used.  If so, print the first one
-     separately.  If we don't do this, we'll wind up printing an
-     instruction stream which does not precisely correspond to the
-     bytes we are disassembling.  */
-  if ((prefixes & ~(used_prefixes | default_prefixes)) != 0)
-    {
-      for (i = 0; i < (int) ARRAY_SIZE (all_prefixes); i++)
-       if (all_prefixes[i])
-         {
-           const char *name;
-           name = prefix_name (all_prefixes[i], priv.orig_sizeflag);
-           if (name == NULL)
-             name = INTERNAL_DISASSEMBLER_ERROR;
-           (*info->fprintf_func) (info->stream, "%s", name);
-           return 1;
-         }
-    }
-
   /* Check if the REX prefix is used.  */
   if (rex_ignored == 0 && (rex ^ rex_used) == 0 && last_rex_prefix >= 0)
     all_prefixes[last_rex_prefix] = 0;
@@ -12688,8 +12699,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
   /* Check if the SEG prefix is used.  */
   if ((prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS | PREFIX_ES
                   | PREFIX_FS | PREFIX_GS)) != 0
-      && (used_prefixes
-         & seg_prefix (all_prefixes[last_seg_prefix])) != 0)
+      && (used_prefixes & active_seg_prefix) != 0)
     all_prefixes[last_seg_prefix] = 0;
 
   /* Check if the ADDR prefix is used.  */
@@ -12697,10 +12707,15 @@ print_insn (bfd_vma pc, disassemble_info *info)
       && (used_prefixes & PREFIX_ADDR) != 0)
     all_prefixes[last_addr_prefix] = 0;
 
-  /* Check if the DATA prefix is used.  */
-  if ((prefixes & PREFIX_DATA) != 0
-      && (used_prefixes & PREFIX_DATA) != 0)
-    all_prefixes[last_data_prefix] = 0;
+  /* Check if the DATA prefix is used.  Restore the DFLAG bit in
+     sizeflag if the DATA prefix is unused.  */
+  if ((prefixes & PREFIX_DATA) != 0)
+    {
+      if ((used_prefixes & PREFIX_DATA) != 0)
+       all_prefixes[last_data_prefix] = 0;
+      else if ((default_prefixes & PREFIX_DATA) == 0)
+       sizeflag ^= DFLAG;
+    }
 
   prefix_length = 0;
   for (i = 0; i < (int) ARRAY_SIZE (all_prefixes); i++)
@@ -12714,6 +12729,26 @@ print_insn (bfd_vma pc, disassemble_info *info)
        (*info->fprintf_func) (info->stream, "%s ", name);
       }
 
+  /* If the mandatory PREFIX_REPZ/PREFIX_REPNZ/PREFIX_DATA prefix is
+     unused, opcode is invalid.  Since the PREFIX_DATA prefix may be
+     used by putop and MMX/SSE operand and may be overriden by the
+     PREFIX_REPZ/PREFIX_REPNZ fix, we check the PREFIX_DATA prefix
+     separately.  */
+  if (mandatory_prefix
+      && dp != &bad_opcode
+      && (((prefixes
+           & (PREFIX_REPZ | PREFIX_REPNZ)) != 0
+          && (used_prefixes
+              & (PREFIX_REPZ | PREFIX_REPNZ)) == 0)
+         || ((((prefixes
+                & (PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA))
+               == PREFIX_DATA)
+              && (used_prefixes & PREFIX_DATA) == 0))))
+    {
+      (*info->fprintf_func) (info->stream, "(bad)");
+      return end_codep - priv.the_buffer;
+    }
+
   /* Check maximum code length.  */
   if ((codep - start_codep) > MAX_CODE_LENGTH)
     {
@@ -13681,35 +13716,33 @@ oappend (const char *s)
 static void
 append_seg (void)
 {
-  if (prefixes & PREFIX_CS)
+  /* Only print the active segment register.  */
+  if (!active_seg_prefix)
+    return;
+
+  used_prefixes |= active_seg_prefix;
+  switch (active_seg_prefix)
     {
-      used_prefixes |= PREFIX_CS;
+    case PREFIX_CS:
       oappend_maybe_intel ("%cs:");
-    }
-  if (prefixes & PREFIX_DS)
-    {
-      used_prefixes |= PREFIX_DS;
+      break;
+    case PREFIX_DS:
       oappend_maybe_intel ("%ds:");
-    }
-  if (prefixes & PREFIX_SS)
-    {
-      used_prefixes |= PREFIX_SS;
+      break;
+    case PREFIX_SS:
       oappend_maybe_intel ("%ss:");
-    }
-  if (prefixes & PREFIX_ES)
-    {
-      used_prefixes |= PREFIX_ES;
+      break;
+    case PREFIX_ES:
       oappend_maybe_intel ("%es:");
-    }
-  if (prefixes & PREFIX_FS)
-    {
-      used_prefixes |= PREFIX_FS;
+      break;
+    case PREFIX_FS:
       oappend_maybe_intel ("%fs:");
-    }
-  if (prefixes & PREFIX_GS)
-    {
-      used_prefixes |= PREFIX_GS;
+      break;
+    case PREFIX_GS:
       oappend_maybe_intel ("%gs:");
+      break;
+    default:
+      break;
     }
 }
 
@@ -14541,10 +14574,7 @@ OP_E_memory (int bytemode, int sizeflag)
        {
          if (modrm.mod != 0 || base == 5)
            {
-             if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
-                             | PREFIX_ES | PREFIX_FS | PREFIX_GS))
-               ;
-             else
+             if (!active_seg_prefix)
                {
                  oappend (names_seg[ds_reg - es_reg]);
                  oappend (":");
@@ -14617,10 +14647,7 @@ OP_E_memory (int bytemode, int sizeflag)
        }
       else if (intel_syntax)
        {
-         if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
-                         | PREFIX_ES | PREFIX_FS | PREFIX_GS))
-           ;
-         else
+         if (!active_seg_prefix)
            {
              oappend (names_seg[ds_reg - es_reg]);
              oappend (":");
@@ -15178,8 +15205,7 @@ OP_OFF (int bytemode, int sizeflag)
 
   if (intel_syntax)
     {
-      if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
-                       | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+      if (!active_seg_prefix)
        {
          oappend (names_seg[ds_reg - es_reg]);
          oappend (":");
@@ -15209,8 +15235,7 @@ OP_OFF64 (int bytemode, int sizeflag)
 
   if (intel_syntax)
     {
-      if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
-                       | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
+      if (!active_seg_prefix)
        {
          oappend (names_seg[ds_reg - es_reg]);
          oappend (":");
@@ -15286,14 +15311,10 @@ OP_DSreg (int code, int sizeflag)
          intel_operand_size (b_mode, sizeflag);
        }
     }
-  if ((prefixes
-       & (PREFIX_CS
-         | PREFIX_DS
-         | PREFIX_SS
-         | PREFIX_ES
-         | PREFIX_FS
-         | PREFIX_GS)) == 0)
-    prefixes |= PREFIX_DS;
+  /* Set active_seg_prefix to PREFIX_DS if it is unset so that the
+     default segment register DS is printed.  */
+  if (!active_seg_prefix)
+    active_seg_prefix = PREFIX_DS;
   append_seg ();
   ptr_reg (code, sizeflag);
 }