diff options
author | Sean Callanan <scallanan@apple.com> | 2010-05-05 22:47:27 +0000 |
---|---|---|
committer | Sean Callanan <scallanan@apple.com> | 2010-05-05 22:47:27 +0000 |
commit | be192dd1e987361ecf51ff385cbf541cb7f779be (patch) | |
tree | 00b29b61573663ea8dcdfc3f66c5da44af3eb45f /lib/Target/X86/Disassembler/X86Disassembler.cpp | |
parent | d47f3c803f4e1e7f84e8fdcd3c9a5120ae5d37ad (diff) |
Fixed a sign-extension bug in the X86 disassembler
that was causing PC-relative branch targets to be
evaluated incorrectly. Also added support for
checking operand values to the llvm-mc tester.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103128 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/X86/Disassembler/X86Disassembler.cpp')
-rw-r--r-- | lib/Target/X86/Disassembler/X86Disassembler.cpp | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/lib/Target/X86/Disassembler/X86Disassembler.cpp b/lib/Target/X86/Disassembler/X86Disassembler.cpp index 62e7357b8f..797fd89350 100644 --- a/lib/Target/X86/Disassembler/X86Disassembler.cpp +++ b/lib/Target/X86/Disassembler/X86Disassembler.cpp @@ -155,7 +155,57 @@ static void translateRegister(MCInst &mcInst, Reg reg) { /// /// @param mcInst - The MCInst to append to. /// @param immediate - The immediate value to append. -static void translateImmediate(MCInst &mcInst, uint64_t immediate) { +/// @param operand - The operand, as stored in the descriptor table. +/// @param insn - The internal instruction. +static void translateImmediate(MCInst &mcInst, + uint64_t immediate, + OperandSpecifier &operand, + InternalInstruction &insn) { + // Sign-extend the immediate if necessary. + + OperandType type = operand.type; + + if (type == TYPE_RELv) { + switch (insn.displacementSize) { + default: + break; + case 8: + type = TYPE_MOFFS8; + break; + case 16: + type = TYPE_MOFFS16; + break; + case 32: + type = TYPE_MOFFS32; + break; + case 64: + type = TYPE_MOFFS64; + break; + } + } + + switch (type) { + case TYPE_MOFFS8: + case TYPE_REL8: + if(immediate & 0x80) + immediate |= ~(0xffull); + break; + case TYPE_MOFFS16: + if(immediate & 0x8000) + immediate |= ~(0xffffull); + break; + case TYPE_MOFFS32: + case TYPE_REL32: + case TYPE_REL64: + if(immediate & 0x80000000) + immediate |= ~(0xffffffffull); + break; + case TYPE_MOFFS64: + default: + // operand is 64 bits wide. Do nothing. + break; + } + mcInst.addOperand(MCOperand::CreateImm(immediate)); } @@ -447,8 +497,10 @@ static bool translateOperand(MCInst &mcInst, case ENCODING_IO: case ENCODING_Iv: case ENCODING_Ia: - translateImmediate(mcInst, - insn.immediates[insn.numImmediatesTranslated++]); + translateImmediate(mcInst, + insn.immediates[insn.numImmediatesTranslated++], + operand, + insn); return false; case ENCODING_RB: case ENCODING_RW: |