diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 928adc4a001..8a92fe925a3 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2014-05-05 H.J. Lu + + 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 * gas/i386/opcode-intel.d: Undo the last change. diff --git a/gas/testsuite/gas/i386/katmai.d b/gas/testsuite/gas/i386/katmai.d index a1c6b97964a..50e573f60e3 100644 --- a/gas/testsuite/gas/i386/katmai.d +++ b/gas/testsuite/gas/i386/katmai.d @@ -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 diff --git a/gas/testsuite/gas/i386/long-1-intel.d b/gas/testsuite/gas/i386/long-1-intel.d index 7a734626abf..2e5213641be 100644 --- a/gas/testsuite/gas/i386/long-1-intel.d +++ b/gas/testsuite/gas/i386/long-1-intel.d @@ -8,7 +8,7 @@ Disassembly of section .text: 0+ : -[ ]*[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 diff --git a/gas/testsuite/gas/i386/long-1.d b/gas/testsuite/gas/i386/long-1.d index 1dccd3674af..a8cd073b35a 100644 --- a/gas/testsuite/gas/i386/long-1.d +++ b/gas/testsuite/gas/i386/long-1.d @@ -7,7 +7,7 @@ Disassembly of section .text: 0+ : -[ ]*[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 diff --git a/gas/testsuite/gas/i386/long-1.s b/gas/testsuite/gas/i386/long-1.s index 4551068bc53..b7e509dea88 100644 --- a/gas/testsuite/gas/i386/long-1.s +++ b/gas/testsuite/gas/i386/long-1.s @@ -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 diff --git a/gas/testsuite/gas/i386/prefix.d b/gas/testsuite/gas/i386/prefix.d index 4139658cac8..d9f0ae2e787 100644 --- a/gas/testsuite/gas/i386/prefix.d +++ b/gas/testsuite/gas/i386/prefix.d @@ -5,11 +5,60 @@ Disassembly of section .text: -0+000 : - 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+ : +[ ]*[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 diff --git a/gas/testsuite/gas/i386/prefix.s b/gas/testsuite/gas/i386/prefix.s index 2bf3c71f59e..07020ead08c 100644 --- a/gas/testsuite/gas/i386/prefix.s +++ b/gas/testsuite/gas/i386/prefix.s @@ -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 diff --git a/gas/testsuite/gas/i386/x86-64-long-1-intel.d b/gas/testsuite/gas/i386/x86-64-long-1-intel.d index 28b291a5854..0ced3f0ba0f 100644 --- a/gas/testsuite/gas/i386/x86-64-long-1-intel.d +++ b/gas/testsuite/gas/i386/x86-64-long-1-intel.d @@ -8,7 +8,7 @@ Disassembly of section .text: 0+ : -[ ]*[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 diff --git a/gas/testsuite/gas/i386/x86-64-long-1.d b/gas/testsuite/gas/i386/x86-64-long-1.d index dbb603a9f32..20be6f431c5 100644 --- a/gas/testsuite/gas/i386/x86-64-long-1.d +++ b/gas/testsuite/gas/i386/x86-64-long-1.d @@ -7,7 +7,7 @@ Disassembly of section .text: 0+ : -[ ]*[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 diff --git a/gas/testsuite/gas/i386/x86-64-long-1.s b/gas/testsuite/gas/i386/x86-64-long-1.s index 73f9a533a28..2b912428dc0 100644 --- a/gas/testsuite/gas/i386/x86-64-long-1.s +++ b/gas/testsuite/gas/i386/x86-64-long-1.s @@ -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 diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 2e4affeb471..47555e6b262 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,29 @@ +2014-05-05 H.J. Lu + + 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 PR binutils/16886 diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 99bb4828333..0ec27ca7077 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -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) + /* 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) { - vindex = 1; - all_prefixes[last_repz_prefix] = 0; - } - else - { - /* 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); }