[X86] Don't ignore 0x66 prefix on relative jumps in 64-bit mode. Fix opcode selection...
authorCraig Topper <craig.topper@intel.com>
Mon, 13 Aug 2018 22:06:28 +0000 (22:06 +0000)
committerCraig Topper <craig.topper@intel.com>
Mon, 13 Aug 2018 22:06:28 +0000 (22:06 +0000)
The behavior in 64-bit mode is different between Intel and AMD CPUs. Intel ignores the 0x66 prefix. AMD does not. objump doesn't ignore the 0x66 prefix. Since LLVM aims to match objdump behavior, we should do the same.

While I was trying to fix this I had change brtarget16/32 to use ENCODING_IW/ID instead of ENCODING_Iv to get the 0x66+REX.W case to act sort of sanely. It's still wrong, but that's a problem for another day.

The change in encoding exposed the fact that 16-bit mode disassembly of relative jumps was creating JMP_4 with a 2 byte immediate. It should have been JMP_2. From just printing you can't tell the difference, but if you dumped the encoding it wouldn't have matched what we started with.

While fixing that, it exposed that jo/jno opcodes were missing from the switch that this patch deleted and there were no test cases for them.

Fixes PR38537.

llvm-svn: 339622

llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
llvm/test/MC/Disassembler/X86/x86-64.txt
llvm/utils/TableGen/X86RecognizableInstr.cpp

index 1ac304f..b6320bd 100644 (file)
@@ -983,45 +983,18 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
       insn->opcode == 0xE3)
     attrMask ^= ATTR_ADSIZE;
 
-  /*
-   * In 64-bit mode all f64 superscripted opcodes ignore opcode size prefix
-   * CALL/JMP/JCC instructions need to ignore 0x66 and consume 4 bytes
-   */
-
-  if ((insn->mode == MODE_64BIT) && insn->hasOpSize) {
-    switch (insn->opcode) {
-    case 0xE8:
-    case 0xE9:
-      // Take care of psubsb and other mmx instructions.
-      if (insn->opcodeType == ONEBYTE) {
-        attrMask ^= ATTR_OPSIZE;
-        insn->immediateSize = 4;
-        insn->displacementSize = 4;
-      }
-      break;
-    case 0x82:
-    case 0x83:
-    case 0x84:
-    case 0x85:
-    case 0x86:
-    case 0x87:
-    case 0x88:
-    case 0x89:
-    case 0x8A:
-    case 0x8B:
-    case 0x8C:
-    case 0x8D:
-    case 0x8E:
-    case 0x8F:
-      // Take care of lea and three byte ops.
-      if (insn->opcodeType == TWOBYTE) {
-        attrMask ^= ATTR_OPSIZE;
-        insn->immediateSize = 4;
-        insn->displacementSize = 4;
-      }
-      break;
-    }
-  }
+  // If we're in 16-bit mode and this is one of the relative jumps and opsize
+  // prefix isn't present, we need to force the opsize attribute since the
+  // prefix is inverted relative to 32-bit mode.
+  if (insn->mode == MODE_16BIT && !insn->hasOpSize &&
+      insn->opcodeType == ONEBYTE &&
+      (insn->opcode == 0xE8 || insn->opcode == 0xE9))
+    attrMask |= ATTR_OPSIZE;
+
+  if (insn->mode == MODE_16BIT && !insn->hasOpSize &&
+      insn->opcodeType == TWOBYTE &&
+      insn->opcode >= 0x80 && insn->opcode <= 0x8F)
+    attrMask |= ATTR_OPSIZE;
 
   if (getIDWithAttrMask(&instructionID, insn, attrMask))
     return -1;
index bcaa7da..ae0e95a 100644 (file)
 # CHECK: movq %rax, 1515870810
 0x67, 0x48 0xa3 0x5a 0x5a 0x5a 0x5a
 
-# CHECK: callq -32769
-0x66 0xe8 0xff 0x7f 0xff 0xff
+# CHECK: callw 32767
+0x66 0xe8 0xff 0x7f
 
-# CHECK: callq -32769
-0x66 0x66 0x48 0xe8 0xff 0x7f 0xff 0xff
+# CHECK: callw 32767
+0x66 0x66 0x48 0xe8 0xff 0x7f
 
 # CHECK: jmp -32769
 0xe9 0xff 0x7f 0xff 0xff
 
-# CHECK: jmp -32769
-0x66 0xe9 0xff 0x7f 0xff 0xff
+# CHECK: jmp 32767
+0x66 0xe9 0xff 0x7f
 
-# CHECK: jmp -32769
-0x66 0x66 0x48 0xe9 0xff 0x7f 0xff 0xff
+# CHECK: jmp 32767
+0x66 0x66 0x48 0xe9 0xff 0x7f
+
+# CHECK: jo -32769
+0x0f 0x80 0xff 0x7f 0xff 0xff
+
+# CHECK: jo 32767
+0x66 0x0f 0x80 0xff 0x7f
+
+# CHECK: jno -32769
+0x0f 0x81 0xff 0x7f 0xff 0xff
+
+# CHECK: jno 32767
+0x66 0x0f 0x81 0xff 0x7f
 
 # CHECK: jb -32769
 0x0f 0x82 0xff 0x7f 0xff 0xff
 
-# CHECK: jb -32769
-0x66 0x0f 0x82 0xff 0x7f 0xff 0xff
+# CHECK: jb 32767
+0x66 0x0f 0x82 0xff 0x7f
 
 # CHECK: jae -32769
 0x0f 0x83 0xff 0x7f 0xff 0xff
 
-# CHECK: jae -32769
-0x66 0x0f 0x83 0xff 0x7f 0xff 0xff
+# CHECK: jae 32767
+0x66 0x0f 0x83 0xff 0x7f
 
 # CHECK: je -32769
 0x0f 0x84 0xff 0x7f 0xff 0xff
 
-# CHECK: je -32769
-0x66 0x0f 0x84 0xff 0x7f 0xff 0xff
+# CHECK: je 32767
+0x66 0x0f 0x84 0xff 0x7f
 
 # CHECK: jne -32769
 0x0f 0x85 0xff 0x7f 0xff 0xff
 
-# CHECK: jne -32769
-0x66 0x0f 0x85 0xff 0x7f 0xff 0xff
+# CHECK: jne 32767
+0x66 0x0f 0x85 0xff 0x7f
 
 # CHECK: jbe -32769
 0x0f 0x86 0xff 0x7f 0xff 0xff
 
-# CHECK: jbe -32769
-0x66 0x0f 0x86 0xff 0x7f 0xff 0xff
+# CHECK: jbe 32767
+0x66 0x0f 0x86 0xff 0x7f
 
 # CHECK: ja -32769
 0x0f 0x87 0xff 0x7f 0xff 0xff
 
-# CHECK: ja -32769
-0x66 0x0f 0x87 0xff 0x7f 0xff 0xff
+# CHECK: ja 32767
+0x66 0x0f 0x87 0xff 0x7f
 
 # CHECK: js -32769
 0x0f 0x88 0xff 0x7f 0xff 0xff
 
-# CHECK: js -32769
-0x66 0x0f 0x88 0xff 0x7f 0xff 0xff
+# CHECK: js 32767
+0x66 0x0f 0x88 0xff 0x7f
 
 # CHECK: jns -32769
 0x0f 0x89 0xff 0x7f 0xff 0xff
 
-# CHECK: jns -32769
-0x66 0x0f 0x89 0xff 0x7f 0xff 0xff
+# CHECK: jns 32767
+0x66 0x0f 0x89 0xff 0x7f
 
 # CHECK: jp -32769
 0x0f 0x8a 0xff 0x7f 0xff 0xff
 
-# CHECK: jp -32769
-0x66 0x0f 0x8a 0xff 0x7f 0xff 0xff
+# CHECK: jp 32767
+0x66 0x0f 0x8a 0xff 0x7f
 
 # CHECK: jnp -32769
 0x0f 0x8b 0xff 0x7f 0xff 0xff
 
-# CHECK: jnp -32769
-0x66 0x0f 0x8b 0xff 0x7f 0xff 0xff
+# CHECK: jnp 32767
+0x66 0x0f 0x8b 0xff 0x7f
 
 # CHECK: jl -32769
 0x0f 0x8c 0xff 0x7f 0xff 0xff
 
-# CHECK: jl -32769
-0x66 0x0f 0x8c 0xff 0x7f 0xff 0xff
+# CHECK: jl 32767
+0x66 0x0f 0x8c 0xff 0x7f
 
 # CHECK: jge -32769
 0x0f 0x8d 0xff 0x7f 0xff 0xff
 
-# CHECK: jge -32769
-0x66 0x0f 0x8d 0xff 0x7f 0xff 0xff
+# CHECK: jge 32767
+0x66 0x0f 0x8d 0xff 0x7f
 
 # CHECK: jle -32769
 0x0f 0x8e 0xff 0x7f 0xff 0xff
 
-# CHECK: jle -32769
-0x66 0x0f 0x8e 0xff 0x7f 0xff 0xff
+# CHECK: jle 32767
+0x66 0x0f 0x8e 0xff 0x7f
 
 # CHECK: jg -32769
 0x0f 0x8f 0xff 0x7f 0xff 0xff
 
-# CHECK: jg -32769
-0x66 0x0f 0x8f 0xff 0x7f 0xff 0xff
+# CHECK: jg 32767
+0x66 0x0f 0x8f 0xff 0x7f
 
 # CHECK: lcallw        *-32769(%rip)
 0x66 0xff 0x1d 0xff 0x7f 0xff 0xff
index efd5c19..2f9b428 100644 (file)
@@ -1132,8 +1132,8 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s,
   ENCODING("i64i32imm_pcrel", ENCODING_ID)
   ENCODING("i16imm_pcrel",    ENCODING_IW)
   ENCODING("i32imm_pcrel",    ENCODING_ID)
-  ENCODING("brtarget32",      ENCODING_Iv)
-  ENCODING("brtarget16",      ENCODING_Iv)
+  ENCODING("brtarget32",      ENCODING_ID)
+  ENCODING("brtarget16",      ENCODING_IW)
   ENCODING("brtarget8",       ENCODING_IB)
   ENCODING("i64imm",          ENCODING_IO)
   ENCODING("offset16_8",      ENCODING_Ia)