summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
diff options
context:
space:
mode:
authorCraig Topper <craig.topper@intel.com>2018-08-13 22:06:28 +0000
committerCraig Topper <craig.topper@intel.com>2018-08-13 22:06:28 +0000
commitcade635c77004ddfabe97a0bbefefcf90d322ed8 (patch)
tree7b6b617cd6b25d4cdbcf54e90ce07550aef04150 /llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
parent3534874fbf71ea4fb7d26e3096f29cbfb96b7bc8 (diff)
downloadbcm5719-llvm-cade635c77004ddfabe97a0bbefefcf90d322ed8.tar.gz
bcm5719-llvm-cade635c77004ddfabe97a0bbefefcf90d322ed8.zip
[X86] Don't ignore 0x66 prefix on relative jumps in 64-bit mode. Fix opcode selection of relative jumps in 16-bit mode. Treat jno/jo like other jcc instructions.
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
Diffstat (limited to 'llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp')
-rw-r--r--llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp51
1 files changed, 12 insertions, 39 deletions
diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
index 1ac304f3be0..b6320bd0612 100644
--- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
+++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
@@ -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;
OpenPOWER on IntegriCloud