Ignore 0x66 prefix for call/jmp/jcc in 64-bit mode
authorH.J. Lu <hjl.tools@gmail.com>
Sat, 9 May 2015 00:13:30 +0000 (17:13 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Sat, 9 May 2015 13:44:29 +0000 (06:44 -0700)
The operand size prefix (0x66) is ignored for 32-bit PC-relative call,
jmp and jcc in 64-bit mode.

gas/testsuite/

PR binutis/18386
* gas/i386/i386.exp: Run x86-64-jump.
* gas/i386/x86-64-branch.d: Updated.
* gas/i386/ilp32/x86-64-branch.d: Likewise.
* gas/i386/x86-64-branch.s: Add tests for the operand size prefix
with call, jmp and jb.
* gas/i386/x86-64-jump.d: New file.
* gas/i386/x86-64-jump.s: Likewise.

ld/testsuite/

PR binutis/18386
* ld-x86-64/tlsgdesc.dd: Updated.
* ld-x86-64/tlspic.dd: Likewise.

opcodes/

PR binutis/18386
* i386-dis.c (X86_64_E8): New.
(X86_64_E9): Likewise.
Update comments on 'T', 'U', 'V'.  Add comments for '^'.
(dis386): Replace callT/jmpT with X86_64_E8/X86_64_E9.
(x86_64_table): Add X86_64_E8 and X86_64_E9.
(mod_table): Replace {T|} with ^ on Jcall/Jmp.
(putop): Handle '^'.
(OP_J): Ignore the operand size prefix in 64-bit.  Don't check
REX_W.

gas/testsuite/gas/i386/i386.exp
gas/testsuite/gas/i386/ilp32/x86-64-branch.d
gas/testsuite/gas/i386/x86-64-branch.d
gas/testsuite/gas/i386/x86-64-branch.s
gas/testsuite/gas/i386/x86-64-jump.d [new file with mode: 0644]
gas/testsuite/gas/i386/x86-64-jump.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/tlsgdesc.dd
ld/testsuite/ld-x86-64/tlspic.dd
opcodes/i386-dis.c

index bedd84c5f3237c705d0ac4a1e3767bc86dc072f0..9492e80e5ffee880d2a1a7342f7cd73fceae6dc7 100644 (file)
@@ -754,6 +754,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
 
        run_dump_test "x86-64-relax-2"
        run_dump_test "x86-64-relax-3"
+
+       run_dump_test "x86-64-jump"
     }
 
     set ASFLAGS "$old_ASFLAGS"
index 9118db129b1a65aef67c5967856fc76b1e736f2d..9fcb8cacde10ba4470f7eeef52ed916affb87359 100644 (file)
@@ -1,7 +1,7 @@
 #source: ../x86-64-branch.s
 #as: -J
 #objdump: -drw
-#name: x86-64 (ILP32) indirect branch
+#name: x86-64 (ILP32) branch
 
 .*: +file format .*
 
@@ -20,6 +20,9 @@ Disassembly of section .text:
 [      ]*[a-f0-9]+:    66 ff 20                jmpw   \*\(%rax\)
 [      ]*[a-f0-9]+:    e8 00 00 00 00          callq  0x1f     1b: R_X86_64_PC32       \*ABS\*\+0x10003c
 [      ]*[a-f0-9]+:    e9 00 00 00 00          jmpq   0x24     20: R_X86_64_PC32       \*ABS\*\+0x10003c
+[      ]*[a-f0-9]+:    66 e8 00 00 00 00       data16 callq 0x2a       26: R_X86_64_PC32       foo-0x4
+[      ]*[a-f0-9]+:    66 e9 00 00 00 00       data16 jmpq 0x30        2c: R_X86_64_PC32       foo-0x4
+[      ]*[a-f0-9]+:    66 0f 82 00 00 00 00    data16 jb 0x37  33: R_X86_64_PC32       foo-0x4
 [      ]*[a-f0-9]+:    ff d0                   callq  \*%rax
 [      ]*[a-f0-9]+:    ff d0                   callq  \*%rax
 [      ]*[a-f0-9]+:    66 ff d0                callw  \*%ax
@@ -30,6 +33,6 @@ Disassembly of section .text:
 [      ]*[a-f0-9]+:    66 ff e0                jmpw   \*%ax
 [      ]*[a-f0-9]+:    66 ff e0                jmpw   \*%ax
 [      ]*[a-f0-9]+:    66 ff 20                jmpw   \*\(%rax\)
-[      ]*[a-f0-9]+:    e8 00 00 00 00          callq  0x43     3f: R_X86_64_PC32       \*ABS\*\+0x10003c
-[      ]*[a-f0-9]+:    e9 00 00 00 00          jmpq   0x48     44: R_X86_64_PC32       \*ABS\*\+0x10003c
+[      ]*[a-f0-9]+:    e8 00 00 00 00          callq  0x56     52: R_X86_64_PC32       \*ABS\*\+0x10003c
+[      ]*[a-f0-9]+:    e9 00 00 00 00          jmpq   0x5b     57: R_X86_64_PC32       \*ABS\*\+0x10003c
 #pass
index fee2099b74d2f3211c5ba8168e894fc286ce101e..49e17a40dff621b72ff50f08cf75fbd69e06dd29 100644 (file)
@@ -1,6 +1,6 @@
 #as: -J
 #objdump: -dw
-#name: x86-64 indirect branch
+#name: x86-64 branch
 
 .*: +file format .*
 
@@ -19,6 +19,9 @@ Disassembly of section .text:
 [      ]*[a-f0-9]+:    66 ff 20                jmpw   \*\(%rax\)
 [      ]*[a-f0-9]+:    e8 (00|5b) 00 (00|10) 00        callq  (0x1f|10007a <.text\+0x10007a>)
 [      ]*[a-f0-9]+:    e9 (00|60) 00 (00|10) 00        jmpq   (0x24|100084 <.text\+0x100084>)
+[      ]*[a-f0-9]+:    66 e8 00 00 00 00       data16 callq (0x2a|2a <.text\+0x2a>)
+[      ]*[a-f0-9]+:    66 e9 00 00 00 00       data16 jmpq (0x30|30 <.text\+0x30>)
+[      ]*[a-f0-9]+:    66 0f 82 00 00 00 00    data16 jb (0x37|37 <.text\+0x37>)
 [      ]*[a-f0-9]+:    ff d0                   callq  \*%rax
 [      ]*[a-f0-9]+:    ff d0                   callq  \*%rax
 [      ]*[a-f0-9]+:    66 ff d0                callw  \*%ax
@@ -29,6 +32,6 @@ Disassembly of section .text:
 [      ]*[a-f0-9]+:    66 ff e0                jmpw   \*%ax
 [      ]*[a-f0-9]+:    66 ff e0                jmpw   \*%ax
 [      ]*[a-f0-9]+:    66 ff 20                jmpw   \*\(%rax\)
-[      ]*[a-f0-9]+:    e8 (00|7f) 00 (00|10) 00        callq  (0x43|1000c2 <.text\+0x1000c2>)
-[      ]*[a-f0-9]+:    e9 (00|84) 00 (00|10) 00        jmpq   (0x48|1000cc <.text\+0x1000cc>)
+[      ]*[a-f0-9]+:    e8 (00|92) 00 (00|10) 00        callq  (0x56|1000e8 <.text\+0x1000e8>)
+[      ]*[a-f0-9]+:    e9 (00|97) 00 (00|10) 00        jmpq   (0x5b|1000f2 <.text\+0x1000f2>)
 #pass
index 4c1861f542e227bfb3370b1f8b2108487e44e515..9451d7644555f12ac4e63bc074b02fa113936ceb 100644 (file)
        call    0x100040
        jmp     0x100040
 
+       .byte 0x66
+       call    foo
+       .byte 0x66
+       jmp     foo
+       .byte 0x66
+       jb      foo
+
        .intel_syntax noprefix
        call    rax
        callq   rax
diff --git a/gas/testsuite/gas/i386/x86-64-jump.d b/gas/testsuite/gas/i386/x86-64-jump.d
new file mode 100644 (file)
index 0000000..edb34e6
--- /dev/null
@@ -0,0 +1,43 @@
+#objdump: -drw
+#name: x86-64 jump
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <.text>:
+[      ]*[a-f0-9]+:    eb fe                   jmp    (0x0|0 <.text>)
+[      ]*[a-f0-9]+:    e9 00 00 00 00          jmpq   0x7      3: R_X86_64_PC32        xxx-0x4
+[      ]*[a-f0-9]+:    ff 24 25 00 00 00 00    jmpq   \*0x0    a: R_X86_64_32S xxx
+[      ]*[a-f0-9]+:    ff e7                   jmpq   \*%rdi
+[      ]*[a-f0-9]+:    ff 27                   jmpq   \*\(%rdi\)
+[      ]*[a-f0-9]+:    ff 2c bd 00 00 00 00    ljmp   \*0x0\(,%rdi,4\) 15: R_X86_64_32S        xxx
+[      ]*[a-f0-9]+:    66 ff 2c bd 00 00 00 00         ljmpw  \*0x0\(,%rdi,4\) 1d: R_X86_64_32S        xxx
+[      ]*[a-f0-9]+:    ff 2c 25 00 00 00 00    ljmp   \*0x0    24: R_X86_64_32S        xxx
+[      ]*[a-f0-9]+:    66 ff 2c 25 00 00 00 00         ljmpw  \*0x0    2c: R_X86_64_32S        xxx
+[      ]*[a-f0-9]+:    e8 cb ff ff ff          callq  0x0
+[      ]*[a-f0-9]+:    e8 00 00 00 00          callq  0x3a     36: R_X86_64_PC32       xxx-0x4
+[      ]*[a-f0-9]+:    ff 14 25 00 00 00 00    callq  \*0x0    3d: R_X86_64_32S        xxx
+[      ]*[a-f0-9]+:    ff d7                   callq  \*%rdi
+[      ]*[a-f0-9]+:    ff 17                   callq  \*\(%rdi\)
+[      ]*[a-f0-9]+:    ff 1c bd 00 00 00 00    lcall  \*0x0\(,%rdi,4\) 48: R_X86_64_32S        xxx
+[      ]*[a-f0-9]+:    66 ff 1c bd 00 00 00 00         lcallw \*0x0\(,%rdi,4\) 50: R_X86_64_32S        xxx
+[      ]*[a-f0-9]+:    ff 1c 25 00 00 00 00    lcall  \*0x0    57: R_X86_64_32S        xxx
+[      ]*[a-f0-9]+:    66 ff 1c 25 00 00 00 00         lcallw \*0x0    5f: R_X86_64_32S        xxx
+[      ]*[a-f0-9]+:    67 e3 00                jecxz  0x66     65: R_X86_64_PC8        \$\+0x2
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    e3 00                   jrcxz  0x69     68: R_X86_64_PC8        \$\+0x1
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    66 ff 13                callw  \*\(%rbx\)
+[      ]*[a-f0-9]+:    ff 1b                   lcall  \*\(%rbx\)
+[      ]*[a-f0-9]+:    66 ff 23                jmpw   \*\(%rbx\)
+[      ]*[a-f0-9]+:    ff 2b                   ljmp   \*\(%rbx\)
+[      ]*[a-f0-9]+:    eb 00                   jmp    0x76
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    67 e3 00                jecxz  0x7a
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    e3 00                   jrcxz  0x7d
+[      ]*[a-f0-9]+:    90                      nop
+[      ]*[a-f0-9]+:    eb 00                   jmp    0x80
+#pass
diff --git a/gas/testsuite/gas/i386/x86-64-jump.s b/gas/testsuite/gas/i386/x86-64-jump.s
new file mode 100644 (file)
index 0000000..96ae66e
--- /dev/null
@@ -0,0 +1,41 @@
+.psize 0
+.text
+.extern xxx
+
+1:     jmp     1b
+       jmp     xxx
+       jmp     *xxx
+       jmp     *%rdi
+       jmp     *(%rdi)
+       ljmp    *xxx(,%rdi,4)
+       ljmpw   *xxx(,%rdi,4)
+       ljmp    *xxx
+       ljmpw   *xxx
+
+       call    1b
+       call    xxx
+       call    *xxx
+       call    *%rdi
+       call    *(%rdi)
+       lcall   *xxx(,%rdi,4)
+       lcallw  *xxx(,%rdi,4)
+       lcall   *xxx
+       lcallw  *xxx
+
+       jecxz   3+$
+       nop
+       jrcxz   2+$
+       nop
+
+       .intel_syntax noprefix
+       call    word ptr [rbx]
+       call    fword ptr [rbx]
+       jmp     word ptr [rbx]
+       jmp     fword ptr [rbx]
+       jmp     $+2
+       nop
+       jecxz   3+$
+       nop
+       jrcxz   2+$
+       nop
+       jmp     .+2
index 85b219fdd934e1be839cf1cc442b9ec0a14007f3..88eb953f9b0dacb51426f70ee14158d78db44d26 100644 (file)
@@ -41,7 +41,7 @@ Disassembly of section .text:
  +[0-9a-f]+:   66 48 8d 3d ([0-9a-f]{2} ){3}[  ]+data16 lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x180>
  +[0-9a-f]+:   [0-9a-f]{2} *
 #                              -> R_X86_64_DTPMOD64    sG1
- +[0-9a-f]+:   66 66 48 e8 ([0-9a-f]{2} ){3}[  ]+data16 data16 callq [0-9a-f]+ <__tls_get_addr@plt>
+ +[0-9a-f]+:   66 66 48 e8 ([0-9a-f]{2} ){3}[  ]+data16 data16 rex.W callq [0-9a-f]+ <__tls_get_addr@plt>
  +[0-9a-f]+:   [0-9a-f]{2} *
 #                              -> R_X86_64_JUMP_SLOT   __tls_get_addr
  +[0-9a-f]+:   90[     ]+nop *
@@ -66,7 +66,7 @@ Disassembly of section .text:
  +[0-9a-f]+:   66 48 8d 3d ([0-9a-f]{2} ){3}[  ]+data16 lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x160>
  +[0-9a-f]+:   [0-9a-f]{2} *
 #                              -> R_X86_64_DTPMOD64    sG2
- +[0-9a-f]+:   66 66 48 e8 ([0-9a-f]{2} ){3}[  ]+data16 data16 callq [0-9a-f]+ <__tls_get_addr@plt>
+ +[0-9a-f]+:   66 66 48 e8 ([0-9a-f]{2} ){3}[  ]+data16 data16 rex.W callq [0-9a-f]+ <__tls_get_addr@plt>
  +[0-9a-f]+:   [0-9a-f]{2} *
 #                              -> R_X86_64_JUMP_SLOT   __tls_get_addr
  +[0-9a-f]+:   90[     ]+nop *
index 26d83e971e672915fd1595903b5558dc375feebe..aab8181a238afb7e99a8a1322af1dd8d9bd5b30b 100644 (file)
@@ -20,7 +20,7 @@ Disassembly of section .text:
  +1008:        66 48 8d 3d ([0-9a-f]{2} ){3}[  ]+data16 lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x180>
  +100f:        [0-9a-f         ]+
 #                              -> R_X86_64_DTPMOD64    sg1
- +1010:        66 66 48 e8 [0-9a-f     ]+data16 data16 callq [0-9a-f]+ <.*>
+ +1010:        66 66 48 e8 [0-9a-f     ]+data16 data16 rex.W callq [0-9a-f]+ <.*>
 #                              -> R_X86_64_JUMP_SLOT   __tls_get_addr
  +1017:        [0-9a-f         ]+
  +1018:        90[     ]+nop *
@@ -40,7 +40,7 @@ Disassembly of section .text:
  +1030:        66 48 8d 3d ([0-9a-f]{2} ){3}[  ]+data16 lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x130>
  +1037:        [0-9a-f         ]+
 #                              -> R_X86_64_DTPMOD64    [0 0x2000000000000000]
- +1038:        66 66 48 e8 [0-9a-f     ]+data16 data16 callq [0-9a-f]+ <.*>
+ +1038:        66 66 48 e8 [0-9a-f     ]+data16 data16 rex.W callq [0-9a-f]+ <.*>
 #                              -> R_X86_64_JUMP_SLOT   __tls_get_addr
  +103f:        [0-9a-f         ]+
  +1040:        90[     ]+nop *
@@ -60,7 +60,7 @@ Disassembly of section .text:
  +1058:        66 48 8d 3d ([0-9a-f]{2} ){3}[  ]+data16 lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x1a8>
  +105f:        [0-9a-f         ]+
 #                              -> R_X86_64_DTPMOD64    [0 0x4000000000000000]
- +1060:        66 66 48 e8 [0-9a-f     ]+data16 data16 callq [0-9a-f]+ <.*>
+ +1060:        66 66 48 e8 [0-9a-f     ]+data16 data16 rex.W callq [0-9a-f]+ <.*>
 #                              -> R_X86_64_JUMP_SLOT   __tls_get_addr
  +1067:        [0-9a-f         ]+
  +1068:        90[     ]+nop *
@@ -80,7 +80,7 @@ Disassembly of section .text:
  +1080:        66 48 8d 3d ([0-9a-f]{2} ){3}[  ]+data16 lea 0x[0-9a-f]+\(%rip\),%rdi +# [0-9a-f]+ <_DYNAMIC\+0x160>
  +1087:        [0-9a-f         ]+
 #                              -> R_X86_64_DTPMOD64    [0 0x6000000000000000]
- +1088:        66 66 48 e8 [0-9a-f     ]+data16 data16 callq [0-9a-f]+ <.*>
+ +1088:        66 66 48 e8 [0-9a-f     ]+data16 data16 rex.W callq [0-9a-f]+ <.*>
 #                              -> R_X86_64_JUMP_SLOT   __tls_get_addr
  +108f:        [0-9a-f         ]+
  +1090:        90[     ]+nop *
index 88c17583d2b11b7eda0f0dbb479db4906a0c1f77..941f699b5948874f3c8536ef1b335dde781b9d8b 100644 (file)
@@ -1632,6 +1632,8 @@ enum
   X86_64_CE,
   X86_64_D4,
   X86_64_D5,
+  X86_64_E8,
+  X86_64_E9,
   X86_64_EA,
   X86_64_0F01_REG_0,
   X86_64_0F01_REG_1,
@@ -2401,9 +2403,12 @@ struct dis386 {
          is true
    'R' => print 'w', 'l' or 'q' ('d' for 'l' and 'e' in Intel mode)
    'S' => print 'w', 'l' or 'q' if suffix_always is true
-   'T' => print 'q' in 64bit mode and behave as 'P' otherwise
-   'U' => print 'q' in 64bit mode and behave as 'Q' otherwise
-   'V' => print 'q' in 64bit mode and behave as 'S' otherwise
+   'T' => print 'q' in 64bit mode if instruction has no operand size
+         prefix and behave as 'P' otherwise
+   'U' => print 'q' in 64bit mode if instruction has no operand size
+         prefix and behave as 'Q' otherwise
+   'V' => print 'q' in 64bit mode if instruction has no operand size
+         prefix and behave as 'S' otherwise
    'W' => print 'b', 'w' or 'l' ('d' in Intel mode)
    'X' => print 's', 'd' depending on data16 prefix (for XMM)
    'Y' => 'q' if instruction has an REX 64bit overwrite prefix and
@@ -2411,6 +2416,8 @@ struct dis386 {
    'Z' => print 'q' in 64bit mode and behave as 'L' otherwise
    '!' => change condition from true to false or from false to true.
    '%' => add 1 upper case letter to the macro.
+   '^' => print 'w' or 'l' depending on operand size prefix or
+         suffix_always is true (lcall/ljmp).
 
    2 upper case letter macros:
    "XY" => print 'x' or 'y' if suffix_always is true or no register
@@ -2697,8 +2704,8 @@ static const struct dis386 dis386[] = {
   { "outB",            { Ib, AL }, 0 },
   { "outG",            { Ib, zAX }, 0 },
   /* e8 */
-  { "callT",           { Jv, BND }, 0 },
-  { "jmpT",            { Jv, BND }, 0 },
+  { X86_64_TABLE (X86_64_E8) },
+  { X86_64_TABLE (X86_64_E9) },
   { X86_64_TABLE (X86_64_EA) },
   { "jmp",             { Jb, BND }, 0 },
   { "inB",             { AL, indirDX }, 0 },
@@ -6834,6 +6841,18 @@ static const struct dis386 x86_64_table[][2] = {
     { "aad", { Ib }, 0 },
   },
 
+  /* X86_64_E8 */
+  {
+    { "callP",         { Jv, BND }, 0 },
+    { "callq",         { Jv, BND }, 0 }
+  },
+
+  /* X86_64_E9 */
+  {
+    { "jmpP",          { Jv, BND }, 0 },
+    { "jmpq",          { Jv, BND }, 0 }
+  },
+
   /* X86_64_EA */
   {
     { "Jjmp{T|}", { Ap }, 0 },
@@ -11576,11 +11595,11 @@ static const struct dis386 mod_table[][2] = {
   },
   {
     /* MOD_FF_REG_3 */
-    { "Jcall{T|}", { indirEp }, 0 },
+    { "Jcall^", { indirEp }, 0 },
   },
   {
     /* MOD_FF_REG_5 */
-    { "Jjmp{T|}", { indirEp }, 0 },
+    { "Jjmp^", { indirEp }, 0 },
   },
   {
     /* MOD_0F01_REG_0 */
@@ -14177,6 +14196,18 @@ case_S:
                *obufp++ = vex.w ? 'q': 'd';
            }
          break;
+       case '^':
+         if (intel_syntax)
+           break;
+         if ((prefixes & PREFIX_DATA) || (sizeflag & SUFFIX_ALWAYS))
+           {
+             if (sizeflag & DFLAG)
+               *obufp++ = 'l';
+             else
+               *obufp++ = 'w';
+             used_prefixes |= (prefixes & PREFIX_DATA);
+           }
+         break;
        }
       alt = 0;
     }
@@ -15693,8 +15724,7 @@ OP_J (int bytemode, int sizeflag)
        disp -= 0x100;
       break;
     case v_mode:
-      USED_REX (REX_W);
-      if ((sizeflag & DFLAG) || (rex & REX_W))
+      if (address_mode == mode_64bit || (sizeflag & DFLAG))
        disp = get32s ();
       else
        {
@@ -15710,7 +15740,7 @@ OP_J (int bytemode, int sizeflag)
            segment = ((start_pc + codep - start_codep)
                       & ~((bfd_vma) 0xffff));
        }
-      if (!(rex & REX_W))
+      if (address_mode != mode_64bit)
        used_prefixes |= (prefixes & PREFIX_DATA);
       break;
     default: