-//===- X86Disassembler.cpp - Disassembler for x86 and x86_64 ----*- C++ -*-===//
+//===-- X86Disassembler.cpp - Disassembler for x86 and x86_64 -------------===//
//
// The LLVM Compiler Infrastructure
//
#include "X86Disassembler.h"
#include "X86DisassemblerDecoder.h"
-#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/EDInstInfo.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/Target/TargetRegistry.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/MemoryObject.h"
-#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
-#include "../X86GenRegisterNames.inc"
+#define GET_REGINFO_ENUM
+#include "X86GenRegisterInfo.inc"
+#define GET_INSTRINFO_ENUM
+#include "X86GenInstrInfo.inc"
+#include "X86GenEDInfo.inc"
using namespace llvm;
using namespace llvm::X86Disassembler;
+void x86DisassemblerDebug(const char *file,
+ unsigned line,
+ const char *s) {
+ dbgs() << file << ":" << line << ": " << s;
+}
+
+const char *x86DisassemblerGetInstrName(unsigned Opcode, void *mii) {
+ const MCInstrInfo *MII = static_cast<const MCInstrInfo *>(mii);
+ return MII->getName(Opcode);
+}
+
+#define debug(s) DEBUG(x86DisassemblerDebug(__FILE__, __LINE__, s));
+
namespace llvm {
// Fill-ins to make the compiler happy. These constants are never actually
}
-static void translateInstruction(MCInst &target,
- InternalInstruction &source);
+static bool translateInstruction(MCInst &target,
+ InternalInstruction &source,
+ const MCDisassembler *Dis);
-X86GenericDisassembler::X86GenericDisassembler(DisassemblerMode mode) :
- MCDisassembler(),
- fMode(mode) {
-}
+X86GenericDisassembler::X86GenericDisassembler(const MCSubtargetInfo &STI,
+ DisassemblerMode mode,
+ const MCInstrInfo *MII)
+ : MCDisassembler(STI), MII(MII), fMode(mode) {}
X86GenericDisassembler::~X86GenericDisassembler() {
+ delete MII;
+}
+
+const EDInstInfo *X86GenericDisassembler::getEDInfo() const {
+ return instInfoX86;
}
/// regionReader - a callback function that wraps the readByte method from
// Public interface for the disassembler
//
-bool X86GenericDisassembler::getInstruction(MCInst &instr,
- uint64_t &size,
- const MemoryObject ®ion,
- uint64_t address,
- raw_ostream &vStream) const {
+MCDisassembler::DecodeStatus
+X86GenericDisassembler::getInstruction(MCInst &instr,
+ uint64_t &size,
+ const MemoryObject ®ion,
+ uint64_t address,
+ raw_ostream &vStream,
+ raw_ostream &cStream) const {
+ CommentStream = &cStream;
+
InternalInstruction internalInstr;
+
+ dlog_t loggerFn = logger;
+ if (&vStream == &nulls())
+ loggerFn = 0; // Disable logging completely if it's going to nulls().
int ret = decodeInstruction(&internalInstr,
regionReader,
(void*)®ion,
- logger,
+ loggerFn,
(void*)&vStream,
+ (void*)MII,
address,
fMode);
- if(ret) {
+ if (ret) {
size = internalInstr.readerCursor - address;
- return false;
+ return Fail;
}
else {
size = internalInstr.length;
- translateInstruction(instr, internalInstr);
- return true;
+ return (!translateInstruction(instr, internalInstr, this)) ?
+ Success : Fail;
}
}
mcInst.addOperand(MCOperand::CreateReg(llvmRegnum));
}
+/// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
+/// immediate Value in the MCInst.
+///
+/// @param Value - The immediate Value, has had any PC adjustment made by
+/// the caller.
+/// @param isBranch - If the instruction is a branch instruction
+/// @param Address - The starting address of the instruction
+/// @param Offset - The byte offset to this immediate in the instruction
+/// @param Width - The byte width of this immediate in the instruction
+///
+/// If the getOpInfo() function was set when setupForSymbolicDisassembly() was
+/// called then that function is called to get any symbolic information for the
+/// immediate in the instruction using the Address, Offset and Width. If that
+/// returns non-zero then the symbolic information it returns is used to create
+/// an MCExpr and that is added as an operand to the MCInst. If getOpInfo()
+/// returns zero and isBranch is true then a symbol look up for immediate Value
+/// is done and if a symbol is found an MCExpr is created with that, else
+/// an MCExpr with the immediate Value is created. This function returns true
+/// if it adds an operand to the MCInst and false otherwise.
+static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
+ uint64_t Address, uint64_t Offset,
+ uint64_t Width, MCInst &MI,
+ const MCDisassembler *Dis) {
+ LLVMOpInfoCallback getOpInfo = Dis->getLLVMOpInfoCallback();
+ struct LLVMOpInfo1 SymbolicOp;
+ memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
+ SymbolicOp.Value = Value;
+ void *DisInfo = Dis->getDisInfoBlock();
+
+ if (!getOpInfo ||
+ !getOpInfo(DisInfo, Address, Offset, Width, 1, &SymbolicOp)) {
+ // Clear SymbolicOp.Value from above and also all other fields.
+ memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1));
+ LLVMSymbolLookupCallback SymbolLookUp = Dis->getLLVMSymbolLookupCallback();
+ if (!SymbolLookUp)
+ return false;
+ uint64_t ReferenceType;
+ if (isBranch)
+ ReferenceType = LLVMDisassembler_ReferenceType_In_Branch;
+ else
+ ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
+ const char *ReferenceName;
+ const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address,
+ &ReferenceName);
+ if (Name) {
+ SymbolicOp.AddSymbol.Name = Name;
+ SymbolicOp.AddSymbol.Present = true;
+ }
+ // For branches always create an MCExpr so it gets printed as hex address.
+ else if (isBranch) {
+ SymbolicOp.Value = Value;
+ }
+ if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub)
+ (*Dis->CommentStream) << "symbol stub for: " << ReferenceName;
+ if (!Name && !isBranch)
+ return false;
+ }
+
+ MCContext *Ctx = Dis->getMCContext();
+ const MCExpr *Add = NULL;
+ if (SymbolicOp.AddSymbol.Present) {
+ if (SymbolicOp.AddSymbol.Name) {
+ StringRef Name(SymbolicOp.AddSymbol.Name);
+ MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name);
+ Add = MCSymbolRefExpr::Create(Sym, *Ctx);
+ } else {
+ Add = MCConstantExpr::Create((int)SymbolicOp.AddSymbol.Value, *Ctx);
+ }
+ }
+
+ const MCExpr *Sub = NULL;
+ if (SymbolicOp.SubtractSymbol.Present) {
+ if (SymbolicOp.SubtractSymbol.Name) {
+ StringRef Name(SymbolicOp.SubtractSymbol.Name);
+ MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name);
+ Sub = MCSymbolRefExpr::Create(Sym, *Ctx);
+ } else {
+ Sub = MCConstantExpr::Create((int)SymbolicOp.SubtractSymbol.Value, *Ctx);
+ }
+ }
+
+ const MCExpr *Off = NULL;
+ if (SymbolicOp.Value != 0)
+ Off = MCConstantExpr::Create(SymbolicOp.Value, *Ctx);
+
+ const MCExpr *Expr;
+ if (Sub) {
+ const MCExpr *LHS;
+ if (Add)
+ LHS = MCBinaryExpr::CreateSub(Add, Sub, *Ctx);
+ else
+ LHS = MCUnaryExpr::CreateMinus(Sub, *Ctx);
+ if (Off != 0)
+ Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx);
+ else
+ Expr = LHS;
+ } else if (Add) {
+ if (Off != 0)
+ Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx);
+ else
+ Expr = Add;
+ } else {
+ if (Off != 0)
+ Expr = Off;
+ else
+ Expr = MCConstantExpr::Create(0, *Ctx);
+ }
+
+ MI.addOperand(MCOperand::CreateExpr(Expr));
+
+ return true;
+}
+
+/// tryAddingPcLoadReferenceComment - trys to add a comment as to what is being
+/// referenced by a load instruction with the base register that is the rip.
+/// These can often be addresses in a literal pool. The Address of the
+/// instruction and its immediate Value are used to determine the address
+/// being referenced in the literal pool entry. The SymbolLookUp call back will
+/// return a pointer to a literal 'C' string if the referenced address is an
+/// address into a section with 'C' string literals.
+static void tryAddingPcLoadReferenceComment(uint64_t Address, uint64_t Value,
+ const void *Decoder) {
+ const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder);
+ LLVMSymbolLookupCallback SymbolLookUp = Dis->getLLVMSymbolLookupCallback();
+ if (SymbolLookUp) {
+ void *DisInfo = Dis->getDisInfoBlock();
+ uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load;
+ const char *ReferenceName;
+ (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName);
+ if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr)
+ (*Dis->CommentStream) << "literal pool for: " << ReferenceName;
+ }
+}
+
/// translateImmediate - Appends an immediate operand to an MCInst.
///
/// @param mcInst - The MCInst to append to.
/// @param immediate - The immediate value to append.
-static void translateImmediate(MCInst &mcInst, uint64_t immediate) {
- mcInst.addOperand(MCOperand::CreateImm(immediate));
+/// @param operand - The operand, as stored in the descriptor table.
+/// @param insn - The internal instruction.
+static void translateImmediate(MCInst &mcInst, uint64_t immediate,
+ const OperandSpecifier &operand,
+ InternalInstruction &insn,
+ const MCDisassembler *Dis) {
+ // Sign-extend the immediate if necessary.
+
+ OperandType type = (OperandType)operand.type;
+
+ if (type == TYPE_RELv) {
+ switch (insn.displacementSize) {
+ default:
+ break;
+ case 1:
+ type = TYPE_MOFFS8;
+ break;
+ case 2:
+ type = TYPE_MOFFS16;
+ break;
+ case 4:
+ type = TYPE_MOFFS32;
+ break;
+ case 8:
+ type = TYPE_MOFFS64;
+ break;
+ }
+ }
+ // By default sign-extend all X86 immediates based on their encoding.
+ else if (type == TYPE_IMM8 || type == TYPE_IMM16 || type == TYPE_IMM32 ||
+ type == TYPE_IMM64) {
+ uint32_t Opcode = mcInst.getOpcode();
+ switch (operand.encoding) {
+ default:
+ break;
+ case ENCODING_IB:
+ // Special case those X86 instructions that use the imm8 as a set of
+ // bits, bit count, etc. and are not sign-extend.
+ if (Opcode != X86::BLENDPSrri && Opcode != X86::BLENDPDrri &&
+ Opcode != X86::PBLENDWrri && Opcode != X86::MPSADBWrri &&
+ Opcode != X86::DPPSrri && Opcode != X86::DPPDrri &&
+ Opcode != X86::INSERTPSrr && Opcode != X86::VBLENDPSYrri &&
+ Opcode != X86::VBLENDPSYrmi && Opcode != X86::VBLENDPDYrri &&
+ Opcode != X86::VBLENDPDYrmi && Opcode != X86::VPBLENDWrri &&
+ Opcode != X86::VMPSADBWrri && Opcode != X86::VDPPSYrri &&
+ Opcode != X86::VDPPSYrmi && Opcode != X86::VDPPDrri &&
+ Opcode != X86::VINSERTPSrr)
+ type = TYPE_MOFFS8;
+ break;
+ case ENCODING_IW:
+ type = TYPE_MOFFS16;
+ break;
+ case ENCODING_ID:
+ type = TYPE_MOFFS32;
+ break;
+ case ENCODING_IO:
+ type = TYPE_MOFFS64;
+ break;
+ }
+ }
+
+ bool isBranch = false;
+ uint64_t pcrel = 0;
+ switch (type) {
+ case TYPE_XMM128:
+ mcInst.addOperand(MCOperand::CreateReg(X86::XMM0 + (immediate >> 4)));
+ return;
+ case TYPE_XMM256:
+ mcInst.addOperand(MCOperand::CreateReg(X86::YMM0 + (immediate >> 4)));
+ return;
+ case TYPE_REL8:
+ isBranch = true;
+ pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize;
+ // fall through to sign extend the immediate if needed.
+ case TYPE_MOFFS8:
+ if(immediate & 0x80)
+ immediate |= ~(0xffull);
+ break;
+ case TYPE_MOFFS16:
+ if(immediate & 0x8000)
+ immediate |= ~(0xffffull);
+ break;
+ case TYPE_REL32:
+ case TYPE_REL64:
+ isBranch = true;
+ pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize;
+ // fall through to sign extend the immediate if needed.
+ case TYPE_MOFFS32:
+ if(immediate & 0x80000000)
+ immediate |= ~(0xffffffffull);
+ break;
+ case TYPE_MOFFS64:
+ default:
+ // operand is 64 bits wide. Do nothing.
+ break;
+ }
+
+ if(!tryAddingSymbolicOperand(immediate + pcrel, isBranch, insn.startLocation,
+ insn.immediateOffset, insn.immediateSize,
+ mcInst, Dis))
+ mcInst.addOperand(MCOperand::CreateImm(immediate));
}
/// translateRMRegister - Translates a register stored in the R/M field of the
/// @param mcInst - The MCInst to append to.
/// @param insn - The internal instruction to extract the R/M field
/// from.
-static void translateRMRegister(MCInst &mcInst,
+/// @return - 0 on success; -1 otherwise
+static bool translateRMRegister(MCInst &mcInst,
InternalInstruction &insn) {
- assert(insn.eaBase != EA_BASE_sib && insn.eaBase != EA_BASE_sib64 &&
- "A R/M register operand may not have a SIB byte");
+ if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) {
+ debug("A R/M register operand may not have a SIB byte");
+ return true;
+ }
switch (insn.eaBase) {
+ default:
+ debug("Unexpected EA base register");
+ return true;
case EA_BASE_NONE:
- llvm_unreachable("EA_BASE_NONE for ModR/M base");
- break;
+ debug("EA_BASE_NONE for ModR/M base");
+ return true;
#define ENTRY(x) case EA_BASE_##x:
ALL_EA_BASES
#undef ENTRY
- llvm_unreachable("A R/M register operand may not have a base; "
- "the operand must be a register.");
- break;
-#define ENTRY(x) \
+ debug("A R/M register operand may not have a base; "
+ "the operand must be a register.");
+ return true;
+#define ENTRY(x) \
case EA_REG_##x: \
mcInst.addOperand(MCOperand::CreateReg(X86::x)); break;
ALL_REGS
#undef ENTRY
- default:
- llvm_unreachable("Unexpected EA base register");
}
+
+ return false;
}
/// translateRMMemory - Translates a memory operand stored in the Mod and R/M
/// @param mcInst - The MCInst to append to.
/// @param insn - The instruction to extract Mod, R/M, and SIB fields
/// from.
-static void translateRMMemory(MCInst &mcInst,
- InternalInstruction &insn) {
+/// @return - 0 on success; nonzero otherwise
+static bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn,
+ const MCDisassembler *Dis) {
// Addresses in an MCInst are represented as five operands:
// 1. basereg (register) The R/M base, or (if there is a SIB) the
// SIB base
MCOperand indexReg;
MCOperand displacement;
MCOperand segmentReg;
+ uint64_t pcrel = 0;
if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) {
if (insn.sibBase != SIB_BASE_NONE) {
switch (insn.sibBase) {
default:
- llvm_unreachable("Unexpected sibBase");
+ debug("Unexpected sibBase");
+ return true;
#define ENTRY(x) \
- case SIB_BASE_##x: \
+ case SIB_BASE_##x: \
baseReg = MCOperand::CreateReg(X86::x); break;
ALL_SIB_BASES
#undef ENTRY
if (insn.sibIndex != SIB_INDEX_NONE) {
switch (insn.sibIndex) {
default:
- llvm_unreachable("Unexpected sibIndex");
-#define ENTRY(x) \
+ debug("Unexpected sibIndex");
+ return true;
+#define ENTRY(x) \
case SIB_INDEX_##x: \
indexReg = MCOperand::CreateReg(X86::x); break;
EA_BASES_32BIT
} else {
switch (insn.eaBase) {
case EA_BASE_NONE:
- assert(insn.eaDisplacement != EA_DISP_NONE &&
- "EA_BASE_NONE and EA_DISP_NONE for ModR/M base");
-
- if (insn.mode == MODE_64BIT)
+ if (insn.eaDisplacement == EA_DISP_NONE) {
+ debug("EA_BASE_NONE and EA_DISP_NONE for ModR/M base");
+ return true;
+ }
+ if (insn.mode == MODE_64BIT){
+ pcrel = insn.startLocation +
+ insn.displacementOffset + insn.displacementSize;
+ tryAddingPcLoadReferenceComment(insn.startLocation +
+ insn.displacementOffset,
+ insn.displacement + pcrel, Dis);
baseReg = MCOperand::CreateReg(X86::RIP); // Section 2.2.1.6
+ }
else
baseReg = MCOperand::CreateReg(0);
indexReg = MCOperand::CreateReg(0);
switch (insn.eaBase) {
default:
- llvm_unreachable("Unexpected eaBase");
- break;
+ debug("Unexpected eaBase");
+ return true;
// Here, we will use the fill-ins defined above. However,
// BX_SI, BX_DI, BP_SI, and BP_DI are all handled above and
// sib and sib64 were handled in the top-level if, so they're only
#define ENTRY(x) case EA_REG_##x:
ALL_REGS
#undef ENTRY
- llvm_unreachable("A R/M memory operand may not be a register; "
- "the base field must be a base.");
- break;
+ debug("A R/M memory operand may not be a register; "
+ "the base field must be a base.");
+ return true;
}
}
+
+ scaleAmount = MCOperand::CreateImm(1);
}
displacement = MCOperand::CreateImm(insn.displacement);
mcInst.addOperand(baseReg);
mcInst.addOperand(scaleAmount);
mcInst.addOperand(indexReg);
- mcInst.addOperand(displacement);
+ if(!tryAddingSymbolicOperand(insn.displacement + pcrel, false,
+ insn.startLocation, insn.displacementOffset,
+ insn.displacementSize, mcInst, Dis))
+ mcInst.addOperand(displacement);
mcInst.addOperand(segmentReg);
+ return false;
}
/// translateRM - Translates an operand stored in the R/M (and possibly SIB)
/// @param operand - The operand, as stored in the descriptor table.
/// @param insn - The instruction to extract Mod, R/M, and SIB fields
/// from.
-static void translateRM(MCInst &mcInst,
- OperandSpecifier &operand,
- InternalInstruction &insn) {
+/// @return - 0 on success; nonzero otherwise
+static bool translateRM(MCInst &mcInst, const OperandSpecifier &operand,
+ InternalInstruction &insn, const MCDisassembler *Dis) {
switch (operand.type) {
default:
- llvm_unreachable("Unexpected type for a R/M operand");
+ debug("Unexpected type for a R/M operand");
+ return true;
case TYPE_R8:
case TYPE_R16:
case TYPE_R32:
case TYPE_XMM32:
case TYPE_XMM64:
case TYPE_XMM128:
+ case TYPE_XMM256:
case TYPE_DEBUGREG:
- case TYPE_CR32:
- case TYPE_CR64:
- translateRMRegister(mcInst, insn);
- break;
+ case TYPE_CONTROLREG:
+ return translateRMRegister(mcInst, insn);
case TYPE_M:
case TYPE_M8:
case TYPE_M16:
case TYPE_M32:
case TYPE_M64:
case TYPE_M128:
+ case TYPE_M256:
case TYPE_M512:
case TYPE_Mv:
case TYPE_M32FP:
case TYPE_M1616:
case TYPE_M1632:
case TYPE_M1664:
- translateRMMemory(mcInst, insn);
- break;
+ case TYPE_LEA:
+ return translateRMMemory(mcInst, insn, Dis);
}
}
///
/// @param mcInst - The MCInst to append to.
/// @param stackPos - The stack position to translate.
-static void translateFPRegister(MCInst &mcInst,
- uint8_t stackPos) {
- assert(stackPos < 8 && "Invalid FP stack position");
+/// @return - 0 on success; nonzero otherwise.
+static bool translateFPRegister(MCInst &mcInst,
+ uint8_t stackPos) {
+ if (stackPos >= 8) {
+ debug("Invalid FP stack position");
+ return true;
+ }
mcInst.addOperand(MCOperand::CreateReg(X86::ST0 + stackPos));
+
+ return false;
}
/// translateOperand - Translates an operand stored in an internal instruction
/// @param mcInst - The MCInst to append to.
/// @param operand - The operand, as stored in the descriptor table.
/// @param insn - The internal instruction.
-static void translateOperand(MCInst &mcInst,
- OperandSpecifier &operand,
- InternalInstruction &insn) {
+/// @return - false on success; true otherwise.
+static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand,
+ InternalInstruction &insn,
+ const MCDisassembler *Dis) {
switch (operand.encoding) {
default:
- llvm_unreachable("Unhandled operand encoding during translation");
+ debug("Unhandled operand encoding during translation");
+ return true;
case ENCODING_REG:
translateRegister(mcInst, insn.reg);
- break;
+ return false;
case ENCODING_RM:
- translateRM(mcInst, operand, insn);
- break;
+ return translateRM(mcInst, operand, insn, Dis);
case ENCODING_CB:
case ENCODING_CW:
case ENCODING_CD:
case ENCODING_CP:
case ENCODING_CO:
case ENCODING_CT:
- llvm_unreachable("Translation of code offsets isn't supported.");
+ debug("Translation of code offsets isn't supported.");
+ return true;
case ENCODING_IB:
case ENCODING_IW:
case ENCODING_ID:
case ENCODING_IO:
case ENCODING_Iv:
case ENCODING_Ia:
- translateImmediate(mcInst,
- insn.immediates[insn.numImmediatesTranslated++]);
- break;
+ translateImmediate(mcInst,
+ insn.immediates[insn.numImmediatesTranslated++],
+ operand,
+ insn,
+ Dis);
+ return false;
case ENCODING_RB:
case ENCODING_RW:
case ENCODING_RD:
case ENCODING_RO:
translateRegister(mcInst, insn.opcodeRegister);
- break;
+ return false;
case ENCODING_I:
- translateFPRegister(mcInst, insn.opcodeModifier);
- break;
+ return translateFPRegister(mcInst, insn.opcodeModifier);
case ENCODING_Rv:
translateRegister(mcInst, insn.opcodeRegister);
- break;
+ return false;
+ case ENCODING_VVVV:
+ translateRegister(mcInst, insn.vvvv);
+ return false;
case ENCODING_DUP:
- translateOperand(mcInst,
- insn.spec->operands[operand.type - TYPE_DUP0],
- insn);
- break;
+ return translateOperand(mcInst,
+ insn.spec->operands[operand.type - TYPE_DUP0],
+ insn, Dis);
}
}
///
/// @param mcInst - The MCInst to populate with the instruction's data.
/// @param insn - The internal instruction.
-static void translateInstruction(MCInst &mcInst,
- InternalInstruction &insn) {
- assert(insn.spec);
+/// @return - false on success; true otherwise.
+static bool translateInstruction(MCInst &mcInst,
+ InternalInstruction &insn,
+ const MCDisassembler *Dis) {
+ if (!insn.spec) {
+ debug("Instruction has no specification");
+ return true;
+ }
mcInst.setOpcode(insn.instructionID);
insn.numImmediatesTranslated = 0;
for (index = 0; index < X86_MAX_OPERANDS; ++index) {
- if (insn.spec->operands[index].encoding != ENCODING_NONE)
- translateOperand(mcInst, insn.spec->operands[index], insn);
+ if (insn.spec->operands[index].encoding != ENCODING_NONE) {
+ if (translateOperand(mcInst, insn.spec->operands[index], insn, Dis)) {
+ return true;
+ }
+ }
}
+
+ return false;
}
-static const MCDisassembler *createX86_32Disassembler(const Target &T) {
- return new X86Disassembler::X86_32Disassembler;
+static MCDisassembler *createX86_32Disassembler(const Target &T,
+ const MCSubtargetInfo &STI) {
+ return new X86Disassembler::X86GenericDisassembler(STI, MODE_32BIT,
+ T.createMCInstrInfo());
}
-static const MCDisassembler *createX86_64Disassembler(const Target &T) {
- return new X86Disassembler::X86_64Disassembler;
+static MCDisassembler *createX86_64Disassembler(const Target &T,
+ const MCSubtargetInfo &STI) {
+ return new X86Disassembler::X86GenericDisassembler(STI, MODE_64BIT,
+ T.createMCInstrInfo());
}
extern "C" void LLVMInitializeX86Disassembler() {