1234353Sdim//===-- X86Disassembler.cpp - Disassembler for x86 and x86_64 -------------===// 2199989Srdivacky// 3199989Srdivacky// The LLVM Compiler Infrastructure 4199989Srdivacky// 5199989Srdivacky// This file is distributed under the University of Illinois Open Source 6199989Srdivacky// License. See LICENSE.TXT for details. 7199989Srdivacky// 8199989Srdivacky//===----------------------------------------------------------------------===// 9201360Srdivacky// 10201360Srdivacky// This file is part of the X86 Disassembler. 11201360Srdivacky// It contains code to translate the data produced by the decoder into 12201360Srdivacky// MCInsts. 13201360Srdivacky// Documentation for the disassembler can be found in X86Disassembler.h. 14201360Srdivacky// 15201360Srdivacky//===----------------------------------------------------------------------===// 16199989Srdivacky 17201360Srdivacky#include "X86Disassembler.h" 18201360Srdivacky#include "X86DisassemblerDecoder.h" 19234353Sdim#include "llvm/MC/MCContext.h" 20199989Srdivacky#include "llvm/MC/MCDisassembler.h" 21249423Sdim#include "llvm/MC/MCExpr.h" 22201360Srdivacky#include "llvm/MC/MCInst.h" 23234353Sdim#include "llvm/MC/MCInstrInfo.h" 24226633Sdim#include "llvm/MC/MCSubtargetInfo.h" 25206124Srdivacky#include "llvm/Support/Debug.h" 26201360Srdivacky#include "llvm/Support/MemoryObject.h" 27226633Sdim#include "llvm/Support/TargetRegistry.h" 28201360Srdivacky#include "llvm/Support/raw_ostream.h" 29201360Srdivacky 30224145Sdim#define GET_REGINFO_ENUM 31224145Sdim#include "X86GenRegisterInfo.inc" 32226633Sdim#define GET_INSTRINFO_ENUM 33226633Sdim#include "X86GenInstrInfo.inc" 34201360Srdivacky 35199989Srdivackyusing namespace llvm; 36201360Srdivackyusing namespace llvm::X86Disassembler; 37199989Srdivacky 38206124Srdivackyvoid x86DisassemblerDebug(const char *file, 39206124Srdivacky unsigned line, 40206124Srdivacky const char *s) { 41206124Srdivacky dbgs() << file << ":" << line << ": " << s; 42206124Srdivacky} 43206124Srdivacky 44243830Sdimconst char *x86DisassemblerGetInstrName(unsigned Opcode, const void *mii) { 45234353Sdim const MCInstrInfo *MII = static_cast<const MCInstrInfo *>(mii); 46234353Sdim return MII->getName(Opcode); 47234353Sdim} 48234353Sdim 49206124Srdivacky#define debug(s) DEBUG(x86DisassemblerDebug(__FILE__, __LINE__, s)); 50206124Srdivacky 51201360Srdivackynamespace llvm { 52201360Srdivacky 53201360Srdivacky// Fill-ins to make the compiler happy. These constants are never actually 54201360Srdivacky// assigned; they are just filler to make an automatically-generated switch 55201360Srdivacky// statement work. 56201360Srdivackynamespace X86 { 57201360Srdivacky enum { 58201360Srdivacky BX_SI = 500, 59201360Srdivacky BX_DI = 501, 60201360Srdivacky BP_SI = 502, 61201360Srdivacky BP_DI = 503, 62201360Srdivacky sib = 504, 63201360Srdivacky sib64 = 505 64201360Srdivacky }; 65201360Srdivacky} 66201360Srdivacky 67201360Srdivackyextern Target TheX86_32Target, TheX86_64Target; 68201360Srdivacky 69201360Srdivacky} 70201360Srdivacky 71206124Srdivackystatic bool translateInstruction(MCInst &target, 72234353Sdim InternalInstruction &source, 73234353Sdim const MCDisassembler *Dis); 74201360Srdivacky 75234353SdimX86GenericDisassembler::X86GenericDisassembler(const MCSubtargetInfo &STI, 76234353Sdim DisassemblerMode mode, 77234353Sdim const MCInstrInfo *MII) 78234353Sdim : MCDisassembler(STI), MII(MII), fMode(mode) {} 79201360Srdivacky 80201360SrdivackyX86GenericDisassembler::~X86GenericDisassembler() { 81234353Sdim delete MII; 82201360Srdivacky} 83201360Srdivacky 84201360Srdivacky/// regionReader - a callback function that wraps the readByte method from 85201360Srdivacky/// MemoryObject. 86201360Srdivacky/// 87201360Srdivacky/// @param arg - The generic callback parameter. In this case, this should 88201360Srdivacky/// be a pointer to a MemoryObject. 89201360Srdivacky/// @param byte - A pointer to the byte to be read. 90201360Srdivacky/// @param address - The address to be read. 91243830Sdimstatic int regionReader(const void* arg, uint8_t* byte, uint64_t address) { 92243830Sdim const MemoryObject* region = static_cast<const MemoryObject*>(arg); 93201360Srdivacky return region->readByte(address, byte); 94201360Srdivacky} 95201360Srdivacky 96201360Srdivacky/// logger - a callback function that wraps the operator<< method from 97201360Srdivacky/// raw_ostream. 98201360Srdivacky/// 99201360Srdivacky/// @param arg - The generic callback parameter. This should be a pointe 100201360Srdivacky/// to a raw_ostream. 101201360Srdivacky/// @param log - A string to be logged. logger() adds a newline. 102201360Srdivackystatic void logger(void* arg, const char* log) { 103201360Srdivacky if (!arg) 104201360Srdivacky return; 105201360Srdivacky 106201360Srdivacky raw_ostream &vStream = *(static_cast<raw_ostream*>(arg)); 107201360Srdivacky vStream << log << "\n"; 108201360Srdivacky} 109201360Srdivacky 110201360Srdivacky// 111201360Srdivacky// Public interface for the disassembler 112201360Srdivacky// 113201360Srdivacky 114226633SdimMCDisassembler::DecodeStatus 115226633SdimX86GenericDisassembler::getInstruction(MCInst &instr, 116226633Sdim uint64_t &size, 117226633Sdim const MemoryObject ®ion, 118226633Sdim uint64_t address, 119226633Sdim raw_ostream &vStream, 120226633Sdim raw_ostream &cStream) const { 121234353Sdim CommentStream = &cStream; 122234353Sdim 123201360Srdivacky InternalInstruction internalInstr; 124226633Sdim 125226633Sdim dlog_t loggerFn = logger; 126226633Sdim if (&vStream == &nulls()) 127226633Sdim loggerFn = 0; // Disable logging completely if it's going to nulls(). 128201360Srdivacky 129201360Srdivacky int ret = decodeInstruction(&internalInstr, 130201360Srdivacky regionReader, 131243830Sdim (const void*)®ion, 132226633Sdim loggerFn, 133201360Srdivacky (void*)&vStream, 134243830Sdim (const void*)MII, 135201360Srdivacky address, 136201360Srdivacky fMode); 137201360Srdivacky 138206124Srdivacky if (ret) { 139201360Srdivacky size = internalInstr.readerCursor - address; 140226633Sdim return Fail; 141201360Srdivacky } 142201360Srdivacky else { 143201360Srdivacky size = internalInstr.length; 144234353Sdim return (!translateInstruction(instr, internalInstr, this)) ? 145234353Sdim Success : Fail; 146201360Srdivacky } 147201360Srdivacky} 148201360Srdivacky 149201360Srdivacky// 150201360Srdivacky// Private code that translates from struct InternalInstructions to MCInsts. 151201360Srdivacky// 152201360Srdivacky 153201360Srdivacky/// translateRegister - Translates an internal register to the appropriate LLVM 154201360Srdivacky/// register, and appends it as an operand to an MCInst. 155201360Srdivacky/// 156201360Srdivacky/// @param mcInst - The MCInst to append to. 157201360Srdivacky/// @param reg - The Reg to append. 158201360Srdivackystatic void translateRegister(MCInst &mcInst, Reg reg) { 159201360Srdivacky#define ENTRY(x) X86::x, 160201360Srdivacky uint8_t llvmRegnums[] = { 161201360Srdivacky ALL_REGS 162201360Srdivacky 0 163201360Srdivacky }; 164201360Srdivacky#undef ENTRY 165201360Srdivacky 166201360Srdivacky uint8_t llvmRegnum = llvmRegnums[reg]; 167201360Srdivacky mcInst.addOperand(MCOperand::CreateReg(llvmRegnum)); 168201360Srdivacky} 169201360Srdivacky 170234353Sdim/// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the 171234353Sdim/// immediate Value in the MCInst. 172234353Sdim/// 173234353Sdim/// @param Value - The immediate Value, has had any PC adjustment made by 174234353Sdim/// the caller. 175234353Sdim/// @param isBranch - If the instruction is a branch instruction 176234353Sdim/// @param Address - The starting address of the instruction 177234353Sdim/// @param Offset - The byte offset to this immediate in the instruction 178234353Sdim/// @param Width - The byte width of this immediate in the instruction 179234353Sdim/// 180234353Sdim/// If the getOpInfo() function was set when setupForSymbolicDisassembly() was 181234353Sdim/// called then that function is called to get any symbolic information for the 182234353Sdim/// immediate in the instruction using the Address, Offset and Width. If that 183234353Sdim/// returns non-zero then the symbolic information it returns is used to create 184234353Sdim/// an MCExpr and that is added as an operand to the MCInst. If getOpInfo() 185234353Sdim/// returns zero and isBranch is true then a symbol look up for immediate Value 186234353Sdim/// is done and if a symbol is found an MCExpr is created with that, else 187234353Sdim/// an MCExpr with the immediate Value is created. This function returns true 188234353Sdim/// if it adds an operand to the MCInst and false otherwise. 189234353Sdimstatic bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, 190234353Sdim uint64_t Address, uint64_t Offset, 191234353Sdim uint64_t Width, MCInst &MI, 192234353Sdim const MCDisassembler *Dis) { 193263508Sdim return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, 194263508Sdim Offset, Width); 195234353Sdim} 196234353Sdim 197234353Sdim/// tryAddingPcLoadReferenceComment - trys to add a comment as to what is being 198234353Sdim/// referenced by a load instruction with the base register that is the rip. 199234353Sdim/// These can often be addresses in a literal pool. The Address of the 200234353Sdim/// instruction and its immediate Value are used to determine the address 201234353Sdim/// being referenced in the literal pool entry. The SymbolLookUp call back will 202234353Sdim/// return a pointer to a literal 'C' string if the referenced address is an 203234353Sdim/// address into a section with 'C' string literals. 204234353Sdimstatic void tryAddingPcLoadReferenceComment(uint64_t Address, uint64_t Value, 205234353Sdim const void *Decoder) { 206234353Sdim const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder); 207263508Sdim Dis->tryAddingPcLoadReferenceComment(Value, Address); 208234353Sdim} 209234353Sdim 210201360Srdivacky/// translateImmediate - Appends an immediate operand to an MCInst. 211201360Srdivacky/// 212201360Srdivacky/// @param mcInst - The MCInst to append to. 213201360Srdivacky/// @param immediate - The immediate value to append. 214208599Srdivacky/// @param operand - The operand, as stored in the descriptor table. 215208599Srdivacky/// @param insn - The internal instruction. 216218893Sdimstatic void translateImmediate(MCInst &mcInst, uint64_t immediate, 217218893Sdim const OperandSpecifier &operand, 218234353Sdim InternalInstruction &insn, 219234353Sdim const MCDisassembler *Dis) { 220208599Srdivacky // Sign-extend the immediate if necessary. 221208599Srdivacky 222234353Sdim OperandType type = (OperandType)operand.type; 223208599Srdivacky 224239462Sdim bool isBranch = false; 225239462Sdim uint64_t pcrel = 0; 226208599Srdivacky if (type == TYPE_RELv) { 227239462Sdim isBranch = true; 228239462Sdim pcrel = insn.startLocation + 229239462Sdim insn.immediateOffset + insn.immediateSize; 230208599Srdivacky switch (insn.displacementSize) { 231208599Srdivacky default: 232208599Srdivacky break; 233219077Sdim case 1: 234263508Sdim if(immediate & 0x80) 235263508Sdim immediate |= ~(0xffull); 236208599Srdivacky break; 237219077Sdim case 2: 238263508Sdim if(immediate & 0x8000) 239263508Sdim immediate |= ~(0xffffull); 240208599Srdivacky break; 241219077Sdim case 4: 242263508Sdim if(immediate & 0x80000000) 243263508Sdim immediate |= ~(0xffffffffull); 244208599Srdivacky break; 245219077Sdim case 8: 246208599Srdivacky break; 247208599Srdivacky } 248208599Srdivacky } 249226633Sdim // By default sign-extend all X86 immediates based on their encoding. 250226633Sdim else if (type == TYPE_IMM8 || type == TYPE_IMM16 || type == TYPE_IMM32 || 251226633Sdim type == TYPE_IMM64) { 252226633Sdim uint32_t Opcode = mcInst.getOpcode(); 253226633Sdim switch (operand.encoding) { 254226633Sdim default: 255226633Sdim break; 256226633Sdim case ENCODING_IB: 257226633Sdim // Special case those X86 instructions that use the imm8 as a set of 258226633Sdim // bits, bit count, etc. and are not sign-extend. 259226633Sdim if (Opcode != X86::BLENDPSrri && Opcode != X86::BLENDPDrri && 260239462Sdim Opcode != X86::PBLENDWrri && Opcode != X86::MPSADBWrri && 261239462Sdim Opcode != X86::DPPSrri && Opcode != X86::DPPDrri && 262239462Sdim Opcode != X86::INSERTPSrr && Opcode != X86::VBLENDPSYrri && 263239462Sdim Opcode != X86::VBLENDPSYrmi && Opcode != X86::VBLENDPDYrri && 264239462Sdim Opcode != X86::VBLENDPDYrmi && Opcode != X86::VPBLENDWrri && 265239462Sdim Opcode != X86::VMPSADBWrri && Opcode != X86::VDPPSYrri && 266239462Sdim Opcode != X86::VDPPSYrmi && Opcode != X86::VDPPDrri && 267239462Sdim Opcode != X86::VINSERTPSrr) 268263508Sdim if(immediate & 0x80) 269263508Sdim immediate |= ~(0xffull); 270226633Sdim break; 271226633Sdim case ENCODING_IW: 272263508Sdim if(immediate & 0x8000) 273263508Sdim immediate |= ~(0xffffull); 274226633Sdim break; 275226633Sdim case ENCODING_ID: 276263508Sdim if(immediate & 0x80000000) 277263508Sdim immediate |= ~(0xffffffffull); 278226633Sdim break; 279226633Sdim case ENCODING_IO: 280226633Sdim break; 281226633Sdim } 282226633Sdim } 283208599Srdivacky 284208599Srdivacky switch (type) { 285243830Sdim case TYPE_XMM32: 286243830Sdim case TYPE_XMM64: 287226633Sdim case TYPE_XMM128: 288226633Sdim mcInst.addOperand(MCOperand::CreateReg(X86::XMM0 + (immediate >> 4))); 289226633Sdim return; 290226633Sdim case TYPE_XMM256: 291226633Sdim mcInst.addOperand(MCOperand::CreateReg(X86::YMM0 + (immediate >> 4))); 292226633Sdim return; 293263508Sdim case TYPE_XMM512: 294263508Sdim mcInst.addOperand(MCOperand::CreateReg(X86::ZMM0 + (immediate >> 4))); 295263508Sdim return; 296234353Sdim case TYPE_REL8: 297234353Sdim isBranch = true; 298234353Sdim pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize; 299208599Srdivacky if(immediate & 0x80) 300208599Srdivacky immediate |= ~(0xffull); 301208599Srdivacky break; 302208599Srdivacky case TYPE_REL32: 303208599Srdivacky case TYPE_REL64: 304234353Sdim isBranch = true; 305234353Sdim pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize; 306208599Srdivacky if(immediate & 0x80000000) 307208599Srdivacky immediate |= ~(0xffffffffull); 308208599Srdivacky break; 309208599Srdivacky default: 310208599Srdivacky // operand is 64 bits wide. Do nothing. 311208599Srdivacky break; 312208599Srdivacky } 313263508Sdim 314234353Sdim if(!tryAddingSymbolicOperand(immediate + pcrel, isBranch, insn.startLocation, 315234353Sdim insn.immediateOffset, insn.immediateSize, 316234353Sdim mcInst, Dis)) 317234353Sdim mcInst.addOperand(MCOperand::CreateImm(immediate)); 318201360Srdivacky} 319201360Srdivacky 320201360Srdivacky/// translateRMRegister - Translates a register stored in the R/M field of the 321201360Srdivacky/// ModR/M byte to its LLVM equivalent and appends it to an MCInst. 322201360Srdivacky/// @param mcInst - The MCInst to append to. 323201360Srdivacky/// @param insn - The internal instruction to extract the R/M field 324201360Srdivacky/// from. 325206124Srdivacky/// @return - 0 on success; -1 otherwise 326206124Srdivackystatic bool translateRMRegister(MCInst &mcInst, 327201360Srdivacky InternalInstruction &insn) { 328206124Srdivacky if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) { 329206124Srdivacky debug("A R/M register operand may not have a SIB byte"); 330206124Srdivacky return true; 331206124Srdivacky } 332201360Srdivacky 333201360Srdivacky switch (insn.eaBase) { 334206124Srdivacky default: 335206124Srdivacky debug("Unexpected EA base register"); 336206124Srdivacky return true; 337201360Srdivacky case EA_BASE_NONE: 338206124Srdivacky debug("EA_BASE_NONE for ModR/M base"); 339206124Srdivacky return true; 340201360Srdivacky#define ENTRY(x) case EA_BASE_##x: 341201360Srdivacky ALL_EA_BASES 342201360Srdivacky#undef ENTRY 343206124Srdivacky debug("A R/M register operand may not have a base; " 344206124Srdivacky "the operand must be a register."); 345206124Srdivacky return true; 346206124Srdivacky#define ENTRY(x) \ 347201360Srdivacky case EA_REG_##x: \ 348201360Srdivacky mcInst.addOperand(MCOperand::CreateReg(X86::x)); break; 349201360Srdivacky ALL_REGS 350201360Srdivacky#undef ENTRY 351201360Srdivacky } 352206124Srdivacky 353206124Srdivacky return false; 354201360Srdivacky} 355201360Srdivacky 356201360Srdivacky/// translateRMMemory - Translates a memory operand stored in the Mod and R/M 357201360Srdivacky/// fields of an internal instruction (and possibly its SIB byte) to a memory 358201360Srdivacky/// operand in LLVM's format, and appends it to an MCInst. 359201360Srdivacky/// 360201360Srdivacky/// @param mcInst - The MCInst to append to. 361201360Srdivacky/// @param insn - The instruction to extract Mod, R/M, and SIB fields 362201360Srdivacky/// from. 363206124Srdivacky/// @return - 0 on success; nonzero otherwise 364234353Sdimstatic bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn, 365234353Sdim const MCDisassembler *Dis) { 366201360Srdivacky // Addresses in an MCInst are represented as five operands: 367201360Srdivacky // 1. basereg (register) The R/M base, or (if there is a SIB) the 368201360Srdivacky // SIB base 369201360Srdivacky // 2. scaleamount (immediate) 1, or (if there is a SIB) the specified 370201360Srdivacky // scale amount 371201360Srdivacky // 3. indexreg (register) x86_registerNONE, or (if there is a SIB) 372201360Srdivacky // the index (which is multiplied by the 373201360Srdivacky // scale amount) 374201360Srdivacky // 4. displacement (immediate) 0, or the displacement if there is one 375201360Srdivacky // 5. segmentreg (register) x86_registerNONE for now, but could be set 376201360Srdivacky // if we have segment overrides 377201360Srdivacky 378201360Srdivacky MCOperand baseReg; 379201360Srdivacky MCOperand scaleAmount; 380201360Srdivacky MCOperand indexReg; 381201360Srdivacky MCOperand displacement; 382201360Srdivacky MCOperand segmentReg; 383234353Sdim uint64_t pcrel = 0; 384201360Srdivacky 385201360Srdivacky if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) { 386201360Srdivacky if (insn.sibBase != SIB_BASE_NONE) { 387201360Srdivacky switch (insn.sibBase) { 388201360Srdivacky default: 389206124Srdivacky debug("Unexpected sibBase"); 390206124Srdivacky return true; 391201360Srdivacky#define ENTRY(x) \ 392201360Srdivacky case SIB_BASE_##x: \ 393201360Srdivacky baseReg = MCOperand::CreateReg(X86::x); break; 394201360Srdivacky ALL_SIB_BASES 395201360Srdivacky#undef ENTRY 396201360Srdivacky } 397201360Srdivacky } else { 398201360Srdivacky baseReg = MCOperand::CreateReg(0); 399201360Srdivacky } 400239462Sdim 401239462Sdim // Check whether we are handling VSIB addressing mode for GATHER. 402239462Sdim // If sibIndex was set to SIB_INDEX_NONE, index offset is 4 and 403239462Sdim // we should use SIB_INDEX_XMM4|YMM4 for VSIB. 404239462Sdim // I don't see a way to get the correct IndexReg in readSIB: 405239462Sdim // We can tell whether it is VSIB or SIB after instruction ID is decoded, 406239462Sdim // but instruction ID may not be decoded yet when calling readSIB. 407239462Sdim uint32_t Opcode = mcInst.getOpcode(); 408239462Sdim bool IndexIs128 = (Opcode == X86::VGATHERDPDrm || 409239462Sdim Opcode == X86::VGATHERDPDYrm || 410239462Sdim Opcode == X86::VGATHERQPDrm || 411239462Sdim Opcode == X86::VGATHERDPSrm || 412239462Sdim Opcode == X86::VGATHERQPSrm || 413239462Sdim Opcode == X86::VPGATHERDQrm || 414239462Sdim Opcode == X86::VPGATHERDQYrm || 415239462Sdim Opcode == X86::VPGATHERQQrm || 416239462Sdim Opcode == X86::VPGATHERDDrm || 417239462Sdim Opcode == X86::VPGATHERQDrm); 418239462Sdim bool IndexIs256 = (Opcode == X86::VGATHERQPDYrm || 419239462Sdim Opcode == X86::VGATHERDPSYrm || 420239462Sdim Opcode == X86::VGATHERQPSYrm || 421239462Sdim Opcode == X86::VPGATHERQQYrm || 422239462Sdim Opcode == X86::VPGATHERDDYrm || 423239462Sdim Opcode == X86::VPGATHERQDYrm); 424239462Sdim if (IndexIs128 || IndexIs256) { 425239462Sdim unsigned IndexOffset = insn.sibIndex - 426239462Sdim (insn.addressSize == 8 ? SIB_INDEX_RAX:SIB_INDEX_EAX); 427239462Sdim SIBIndex IndexBase = IndexIs256 ? SIB_INDEX_YMM0 : SIB_INDEX_XMM0; 428239462Sdim insn.sibIndex = (SIBIndex)(IndexBase + 429239462Sdim (insn.sibIndex == SIB_INDEX_NONE ? 4 : IndexOffset)); 430239462Sdim } 431239462Sdim 432201360Srdivacky if (insn.sibIndex != SIB_INDEX_NONE) { 433201360Srdivacky switch (insn.sibIndex) { 434201360Srdivacky default: 435206124Srdivacky debug("Unexpected sibIndex"); 436206124Srdivacky return true; 437201360Srdivacky#define ENTRY(x) \ 438201360Srdivacky case SIB_INDEX_##x: \ 439201360Srdivacky indexReg = MCOperand::CreateReg(X86::x); break; 440201360Srdivacky EA_BASES_32BIT 441201360Srdivacky EA_BASES_64BIT 442239462Sdim REGS_XMM 443239462Sdim REGS_YMM 444263508Sdim REGS_ZMM 445201360Srdivacky#undef ENTRY 446201360Srdivacky } 447201360Srdivacky } else { 448201360Srdivacky indexReg = MCOperand::CreateReg(0); 449201360Srdivacky } 450201360Srdivacky 451201360Srdivacky scaleAmount = MCOperand::CreateImm(insn.sibScale); 452201360Srdivacky } else { 453201360Srdivacky switch (insn.eaBase) { 454201360Srdivacky case EA_BASE_NONE: 455206124Srdivacky if (insn.eaDisplacement == EA_DISP_NONE) { 456206124Srdivacky debug("EA_BASE_NONE and EA_DISP_NONE for ModR/M base"); 457206124Srdivacky return true; 458206124Srdivacky } 459234353Sdim if (insn.mode == MODE_64BIT){ 460234353Sdim pcrel = insn.startLocation + 461234353Sdim insn.displacementOffset + insn.displacementSize; 462234353Sdim tryAddingPcLoadReferenceComment(insn.startLocation + 463234353Sdim insn.displacementOffset, 464234353Sdim insn.displacement + pcrel, Dis); 465201360Srdivacky baseReg = MCOperand::CreateReg(X86::RIP); // Section 2.2.1.6 466234353Sdim } 467201360Srdivacky else 468201360Srdivacky baseReg = MCOperand::CreateReg(0); 469201360Srdivacky 470201360Srdivacky indexReg = MCOperand::CreateReg(0); 471201360Srdivacky break; 472201360Srdivacky case EA_BASE_BX_SI: 473201360Srdivacky baseReg = MCOperand::CreateReg(X86::BX); 474201360Srdivacky indexReg = MCOperand::CreateReg(X86::SI); 475201360Srdivacky break; 476201360Srdivacky case EA_BASE_BX_DI: 477201360Srdivacky baseReg = MCOperand::CreateReg(X86::BX); 478201360Srdivacky indexReg = MCOperand::CreateReg(X86::DI); 479201360Srdivacky break; 480201360Srdivacky case EA_BASE_BP_SI: 481201360Srdivacky baseReg = MCOperand::CreateReg(X86::BP); 482201360Srdivacky indexReg = MCOperand::CreateReg(X86::SI); 483201360Srdivacky break; 484201360Srdivacky case EA_BASE_BP_DI: 485201360Srdivacky baseReg = MCOperand::CreateReg(X86::BP); 486201360Srdivacky indexReg = MCOperand::CreateReg(X86::DI); 487201360Srdivacky break; 488201360Srdivacky default: 489201360Srdivacky indexReg = MCOperand::CreateReg(0); 490201360Srdivacky switch (insn.eaBase) { 491201360Srdivacky default: 492206124Srdivacky debug("Unexpected eaBase"); 493206124Srdivacky return true; 494201360Srdivacky // Here, we will use the fill-ins defined above. However, 495201360Srdivacky // BX_SI, BX_DI, BP_SI, and BP_DI are all handled above and 496201360Srdivacky // sib and sib64 were handled in the top-level if, so they're only 497201360Srdivacky // placeholders to keep the compiler happy. 498201360Srdivacky#define ENTRY(x) \ 499201360Srdivacky case EA_BASE_##x: \ 500201360Srdivacky baseReg = MCOperand::CreateReg(X86::x); break; 501201360Srdivacky ALL_EA_BASES 502201360Srdivacky#undef ENTRY 503201360Srdivacky#define ENTRY(x) case EA_REG_##x: 504201360Srdivacky ALL_REGS 505201360Srdivacky#undef ENTRY 506206124Srdivacky debug("A R/M memory operand may not be a register; " 507206124Srdivacky "the base field must be a base."); 508206124Srdivacky return true; 509201360Srdivacky } 510201360Srdivacky } 511201360Srdivacky 512201360Srdivacky scaleAmount = MCOperand::CreateImm(1); 513201360Srdivacky } 514201360Srdivacky 515201360Srdivacky displacement = MCOperand::CreateImm(insn.displacement); 516201360Srdivacky 517201360Srdivacky static const uint8_t segmentRegnums[SEG_OVERRIDE_max] = { 518201360Srdivacky 0, // SEG_OVERRIDE_NONE 519201360Srdivacky X86::CS, 520201360Srdivacky X86::SS, 521201360Srdivacky X86::DS, 522201360Srdivacky X86::ES, 523201360Srdivacky X86::FS, 524201360Srdivacky X86::GS 525201360Srdivacky }; 526201360Srdivacky 527201360Srdivacky segmentReg = MCOperand::CreateReg(segmentRegnums[insn.segmentOverride]); 528201360Srdivacky 529201360Srdivacky mcInst.addOperand(baseReg); 530201360Srdivacky mcInst.addOperand(scaleAmount); 531201360Srdivacky mcInst.addOperand(indexReg); 532234353Sdim if(!tryAddingSymbolicOperand(insn.displacement + pcrel, false, 533234353Sdim insn.startLocation, insn.displacementOffset, 534234353Sdim insn.displacementSize, mcInst, Dis)) 535234353Sdim mcInst.addOperand(displacement); 536210299Sed mcInst.addOperand(segmentReg); 537206124Srdivacky return false; 538201360Srdivacky} 539201360Srdivacky 540201360Srdivacky/// translateRM - Translates an operand stored in the R/M (and possibly SIB) 541201360Srdivacky/// byte of an instruction to LLVM form, and appends it to an MCInst. 542201360Srdivacky/// 543201360Srdivacky/// @param mcInst - The MCInst to append to. 544201360Srdivacky/// @param operand - The operand, as stored in the descriptor table. 545201360Srdivacky/// @param insn - The instruction to extract Mod, R/M, and SIB fields 546201360Srdivacky/// from. 547206124Srdivacky/// @return - 0 on success; nonzero otherwise 548218893Sdimstatic bool translateRM(MCInst &mcInst, const OperandSpecifier &operand, 549234353Sdim InternalInstruction &insn, const MCDisassembler *Dis) { 550201360Srdivacky switch (operand.type) { 551201360Srdivacky default: 552206124Srdivacky debug("Unexpected type for a R/M operand"); 553206124Srdivacky return true; 554201360Srdivacky case TYPE_R8: 555201360Srdivacky case TYPE_R16: 556201360Srdivacky case TYPE_R32: 557201360Srdivacky case TYPE_R64: 558201360Srdivacky case TYPE_Rv: 559201360Srdivacky case TYPE_MM: 560201360Srdivacky case TYPE_MM32: 561201360Srdivacky case TYPE_MM64: 562201360Srdivacky case TYPE_XMM: 563201360Srdivacky case TYPE_XMM32: 564201360Srdivacky case TYPE_XMM64: 565201360Srdivacky case TYPE_XMM128: 566221345Sdim case TYPE_XMM256: 567263508Sdim case TYPE_XMM512: 568201360Srdivacky case TYPE_DEBUGREG: 569208599Srdivacky case TYPE_CONTROLREG: 570206124Srdivacky return translateRMRegister(mcInst, insn); 571201360Srdivacky case TYPE_M: 572201360Srdivacky case TYPE_M8: 573201360Srdivacky case TYPE_M16: 574201360Srdivacky case TYPE_M32: 575201360Srdivacky case TYPE_M64: 576201360Srdivacky case TYPE_M128: 577221345Sdim case TYPE_M256: 578201360Srdivacky case TYPE_M512: 579201360Srdivacky case TYPE_Mv: 580201360Srdivacky case TYPE_M32FP: 581201360Srdivacky case TYPE_M64FP: 582201360Srdivacky case TYPE_M80FP: 583201360Srdivacky case TYPE_M16INT: 584201360Srdivacky case TYPE_M32INT: 585201360Srdivacky case TYPE_M64INT: 586201360Srdivacky case TYPE_M1616: 587201360Srdivacky case TYPE_M1632: 588201360Srdivacky case TYPE_M1664: 589201360Srdivacky case TYPE_LEA: 590234353Sdim return translateRMMemory(mcInst, insn, Dis); 591201360Srdivacky } 592201360Srdivacky} 593201360Srdivacky 594201360Srdivacky/// translateFPRegister - Translates a stack position on the FPU stack to its 595201360Srdivacky/// LLVM form, and appends it to an MCInst. 596201360Srdivacky/// 597201360Srdivacky/// @param mcInst - The MCInst to append to. 598201360Srdivacky/// @param stackPos - The stack position to translate. 599206124Srdivacky/// @return - 0 on success; nonzero otherwise. 600206124Srdivackystatic bool translateFPRegister(MCInst &mcInst, 601206124Srdivacky uint8_t stackPos) { 602206124Srdivacky if (stackPos >= 8) { 603206124Srdivacky debug("Invalid FP stack position"); 604206124Srdivacky return true; 605206124Srdivacky } 606201360Srdivacky 607201360Srdivacky mcInst.addOperand(MCOperand::CreateReg(X86::ST0 + stackPos)); 608206124Srdivacky 609206124Srdivacky return false; 610201360Srdivacky} 611201360Srdivacky 612201360Srdivacky/// translateOperand - Translates an operand stored in an internal instruction 613201360Srdivacky/// to LLVM's format and appends it to an MCInst. 614201360Srdivacky/// 615201360Srdivacky/// @param mcInst - The MCInst to append to. 616201360Srdivacky/// @param operand - The operand, as stored in the descriptor table. 617201360Srdivacky/// @param insn - The internal instruction. 618206124Srdivacky/// @return - false on success; true otherwise. 619218893Sdimstatic bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand, 620234353Sdim InternalInstruction &insn, 621234353Sdim const MCDisassembler *Dis) { 622201360Srdivacky switch (operand.encoding) { 623201360Srdivacky default: 624206124Srdivacky debug("Unhandled operand encoding during translation"); 625206124Srdivacky return true; 626201360Srdivacky case ENCODING_REG: 627201360Srdivacky translateRegister(mcInst, insn.reg); 628206124Srdivacky return false; 629201360Srdivacky case ENCODING_RM: 630234353Sdim return translateRM(mcInst, operand, insn, Dis); 631201360Srdivacky case ENCODING_CB: 632201360Srdivacky case ENCODING_CW: 633201360Srdivacky case ENCODING_CD: 634201360Srdivacky case ENCODING_CP: 635201360Srdivacky case ENCODING_CO: 636201360Srdivacky case ENCODING_CT: 637206124Srdivacky debug("Translation of code offsets isn't supported."); 638206124Srdivacky return true; 639201360Srdivacky case ENCODING_IB: 640201360Srdivacky case ENCODING_IW: 641201360Srdivacky case ENCODING_ID: 642201360Srdivacky case ENCODING_IO: 643201360Srdivacky case ENCODING_Iv: 644201360Srdivacky case ENCODING_Ia: 645208599Srdivacky translateImmediate(mcInst, 646208599Srdivacky insn.immediates[insn.numImmediatesTranslated++], 647208599Srdivacky operand, 648234353Sdim insn, 649234353Sdim Dis); 650206124Srdivacky return false; 651201360Srdivacky case ENCODING_RB: 652201360Srdivacky case ENCODING_RW: 653201360Srdivacky case ENCODING_RD: 654201360Srdivacky case ENCODING_RO: 655201360Srdivacky translateRegister(mcInst, insn.opcodeRegister); 656206124Srdivacky return false; 657201360Srdivacky case ENCODING_I: 658206124Srdivacky return translateFPRegister(mcInst, insn.opcodeModifier); 659201360Srdivacky case ENCODING_Rv: 660201360Srdivacky translateRegister(mcInst, insn.opcodeRegister); 661206124Srdivacky return false; 662221345Sdim case ENCODING_VVVV: 663221345Sdim translateRegister(mcInst, insn.vvvv); 664221345Sdim return false; 665201360Srdivacky case ENCODING_DUP: 666239462Sdim return translateOperand(mcInst, insn.operands[operand.type - TYPE_DUP0], 667234353Sdim insn, Dis); 668201360Srdivacky } 669201360Srdivacky} 670201360Srdivacky 671201360Srdivacky/// translateInstruction - Translates an internal instruction and all its 672201360Srdivacky/// operands to an MCInst. 673201360Srdivacky/// 674201360Srdivacky/// @param mcInst - The MCInst to populate with the instruction's data. 675201360Srdivacky/// @param insn - The internal instruction. 676206124Srdivacky/// @return - false on success; true otherwise. 677206124Srdivackystatic bool translateInstruction(MCInst &mcInst, 678234353Sdim InternalInstruction &insn, 679234353Sdim const MCDisassembler *Dis) { 680206124Srdivacky if (!insn.spec) { 681206124Srdivacky debug("Instruction has no specification"); 682206124Srdivacky return true; 683206124Srdivacky } 684201360Srdivacky 685201360Srdivacky mcInst.setOpcode(insn.instructionID); 686263508Sdim // If when reading the prefix bytes we determined the overlapping 0xf2 or 0xf3 687263508Sdim // prefix bytes should be disassembled as xrelease and xacquire then set the 688263508Sdim // opcode to those instead of the rep and repne opcodes. 689263508Sdim if (insn.xAcquireRelease) { 690263508Sdim if(mcInst.getOpcode() == X86::REP_PREFIX) 691263508Sdim mcInst.setOpcode(X86::XRELEASE_PREFIX); 692263508Sdim else if(mcInst.getOpcode() == X86::REPNE_PREFIX) 693263508Sdim mcInst.setOpcode(X86::XACQUIRE_PREFIX); 694263508Sdim } 695201360Srdivacky 696201360Srdivacky int index; 697201360Srdivacky 698201360Srdivacky insn.numImmediatesTranslated = 0; 699201360Srdivacky 700201360Srdivacky for (index = 0; index < X86_MAX_OPERANDS; ++index) { 701239462Sdim if (insn.operands[index].encoding != ENCODING_NONE) { 702239462Sdim if (translateOperand(mcInst, insn.operands[index], insn, Dis)) { 703206124Srdivacky return true; 704206124Srdivacky } 705206124Srdivacky } 706201360Srdivacky } 707206124Srdivacky 708206124Srdivacky return false; 709201360Srdivacky} 710201360Srdivacky 711234353Sdimstatic MCDisassembler *createX86_32Disassembler(const Target &T, 712234353Sdim const MCSubtargetInfo &STI) { 713234353Sdim return new X86Disassembler::X86GenericDisassembler(STI, MODE_32BIT, 714234353Sdim T.createMCInstrInfo()); 715199989Srdivacky} 716199989Srdivacky 717234353Sdimstatic MCDisassembler *createX86_64Disassembler(const Target &T, 718234353Sdim const MCSubtargetInfo &STI) { 719234353Sdim return new X86Disassembler::X86GenericDisassembler(STI, MODE_64BIT, 720234353Sdim T.createMCInstrInfo()); 721199989Srdivacky} 722199989Srdivacky 723199989Srdivackyextern "C" void LLVMInitializeX86Disassembler() { 724199989Srdivacky // Register the disassembler. 725199989Srdivacky TargetRegistry::RegisterMCDisassembler(TheX86_32Target, 726199989Srdivacky createX86_32Disassembler); 727199989Srdivacky TargetRegistry::RegisterMCDisassembler(TheX86_64Target, 728199989Srdivacky createX86_64Disassembler); 729199989Srdivacky} 730