X86Disassembler.cpp revision 8bee081a2cc6a84de125525215fffb4cc1cbe12a
131d157ae1ac2cd9c787dc3c1d28e64c682803844Jia Liu//===-- X86Disassembler.cpp - Disassembler for x86 and x86_64 -------------===// 25f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar// 35f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar// The LLVM Compiler Infrastructure 45f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar// 55f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar// This file is distributed under the University of Illinois Open Source 65f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar// License. See LICENSE.TXT for details. 75f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar// 85f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar//===----------------------------------------------------------------------===// 98ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 108ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// This file is part of the X86 Disassembler. 118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// It contains code to translate the data produced by the decoder into 128ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// MCInsts. 138ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// Documentation for the disassembler can be found in X86Disassembler.h. 148ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan//===----------------------------------------------------------------------===// 165f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar 178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#include "X86Disassembler.h" 188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#include "X86DisassemblerDecoder.h" 198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 209899f70a7406d632c82849978bf6981f1ee4ccb5Sean Callanan#include "llvm/MC/EDInstInfo.h" 21b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby#include "llvm/MC/MCExpr.h" 22b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby#include "llvm/MC/MCContext.h" 235f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar#include "llvm/MC/MCDisassembler.h" 248ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#include "llvm/MC/MCInst.h" 25953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer#include "llvm/MC/MCInstrInfo.h" 26b950585cc5a0d665e9accfe5ce490cd269756f2eJames Molloy#include "llvm/MC/MCSubtargetInfo.h" 27a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan#include "llvm/Support/Debug.h" 288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#include "llvm/Support/MemoryObject.h" 293e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h" 308ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#include "llvm/Support/raw_ostream.h" 310122c9051a0157908e3f4e1c604435339ac4761dSean Callanan 3273f50d9bc3bd46cc0abeba9bb0d46977ba1aea42Evan Cheng#define GET_REGINFO_ENUM 3373f50d9bc3bd46cc0abeba9bb0d46977ba1aea42Evan Cheng#include "X86GenRegisterInfo.inc" 34d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby#define GET_INSTRINFO_ENUM 35d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby#include "X86GenInstrInfo.inc" 369899f70a7406d632c82849978bf6981f1ee4ccb5Sean Callanan#include "X86GenEDInfo.inc" 370122c9051a0157908e3f4e1c604435339ac4761dSean Callanan 385f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbarusing namespace llvm; 398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananusing namespace llvm::X86Disassembler; 408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 41a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananvoid x86DisassemblerDebug(const char *file, 42a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan unsigned line, 43a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan const char *s) { 44a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan dbgs() << file << ":" << line << ": " << s; 45a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan} 46a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 47953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramerconst char *x86DisassemblerGetInstrName(unsigned Opcode, void *mii) { 48953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer const MCInstrInfo *MII = static_cast<const MCInstrInfo *>(mii); 49953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer return MII->getName(Opcode); 50953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer} 51953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer 52a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan#define debug(s) DEBUG(x86DisassemblerDebug(__FILE__, __LINE__, s)); 53a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanannamespace llvm { 558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// Fill-ins to make the compiler happy. These constants are never actually 578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// assigned; they are just filler to make an automatically-generated switch 588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// statement work. 598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanannamespace X86 { 608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan enum { 618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan BX_SI = 500, 628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan BX_DI = 501, 638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan BP_SI = 502, 648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan BP_DI = 503, 658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan sib = 504, 668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan sib64 = 505 678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan }; 688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 700122c9051a0157908e3f4e1c604435339ac4761dSean Callananextern Target TheX86_32Target, TheX86_64Target; 710122c9051a0157908e3f4e1c604435339ac4761dSean Callanan 728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 74a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananstatic bool translateInstruction(MCInst &target, 75b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &source, 76b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis); 778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 78953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin KramerX86GenericDisassembler::X86GenericDisassembler(const MCSubtargetInfo &STI, 79953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer DisassemblerMode mode, 80953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer const MCInstrInfo *MII) 81953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer : MCDisassembler(STI), MII(MII), fMode(mode) {} 828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean CallananX86GenericDisassembler::~X86GenericDisassembler() { 84953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer delete MII; 858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 868ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 8788b6fc06db667bd26d6ef661597affaa6abfdd0dBenjamin Kramerconst EDInstInfo *X86GenericDisassembler::getEDInfo() const { 889899f70a7406d632c82849978bf6981f1ee4ccb5Sean Callanan return instInfoX86; 899899f70a7406d632c82849978bf6981f1ee4ccb5Sean Callanan} 909899f70a7406d632c82849978bf6981f1ee4ccb5Sean Callanan 918ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// regionReader - a callback function that wraps the readByte method from 928ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// MemoryObject. 938ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 948ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param arg - The generic callback parameter. In this case, this should 958ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// be a pointer to a MemoryObject. 968ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param byte - A pointer to the byte to be read. 978ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param address - The address to be read. 988ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananstatic int regionReader(void* arg, uint8_t* byte, uint64_t address) { 998ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MemoryObject* region = static_cast<MemoryObject*>(arg); 1008ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return region->readByte(address, byte); 1018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 1028ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1038ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// logger - a callback function that wraps the operator<< method from 1048ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// raw_ostream. 1058ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 1068ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param arg - The generic callback parameter. This should be a pointe 1078ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// to a raw_ostream. 1088ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param log - A string to be logged. logger() adds a newline. 1098ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananstatic void logger(void* arg, const char* log) { 1108ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (!arg) 1118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return; 1128ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1138ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan raw_ostream &vStream = *(static_cast<raw_ostream*>(arg)); 1148ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan vStream << log << "\n"; 1158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 1168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 1188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// Public interface for the disassembler 1198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 1208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 12183e3f67fb68d497b600da83a62f000fcce7868a9Owen AndersonMCDisassembler::DecodeStatus 12283e3f67fb68d497b600da83a62f000fcce7868a9Owen AndersonX86GenericDisassembler::getInstruction(MCInst &instr, 12383e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson uint64_t &size, 124adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff const MemoryObject ®ion, 12583e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson uint64_t address, 12698c5ddabca1debf935a07d14d0cbc9732374bdb8Owen Anderson raw_ostream &vStream, 12798c5ddabca1debf935a07d14d0cbc9732374bdb8Owen Anderson raw_ostream &cStream) const { 128b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby CommentStream = &cStream; 129b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 1308ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan InternalInstruction internalInstr; 13115c9a1f60c2e9d9cb854d5c0072755be91d1cc96Benjamin Kramer 13215c9a1f60c2e9d9cb854d5c0072755be91d1cc96Benjamin Kramer dlog_t loggerFn = logger; 13315c9a1f60c2e9d9cb854d5c0072755be91d1cc96Benjamin Kramer if (&vStream == &nulls()) 13415c9a1f60c2e9d9cb854d5c0072755be91d1cc96Benjamin Kramer loggerFn = 0; // Disable logging completely if it's going to nulls(). 1358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan int ret = decodeInstruction(&internalInstr, 1378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan regionReader, 1388ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan (void*)®ion, 13915c9a1f60c2e9d9cb854d5c0072755be91d1cc96Benjamin Kramer loggerFn, 1408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan (void*)&vStream, 141953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer (void*)MII, 1428ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan address, 1438ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan fMode); 1448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 145a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (ret) { 1468ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan size = internalInstr.readerCursor - address; 14783e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson return Fail; 1488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan else { 1508ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan size = internalInstr.length; 151b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return (!translateInstruction(instr, internalInstr, this)) ? 152b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Success : Fail; 1538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 1558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 1578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// Private code that translates from struct InternalInstructions to MCInsts. 1588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 1598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRegister - Translates an internal register to the appropriate LLVM 1618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// register, and appends it as an operand to an MCInst. 1628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 1638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 1648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param reg - The Reg to append. 1658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananstatic void translateRegister(MCInst &mcInst, Reg reg) { 1668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) X86::x, 1678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan uint8_t llvmRegnums[] = { 1688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_REGS 1698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 0 1708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan }; 1718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 1728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan uint8_t llvmRegnum = llvmRegnums[reg]; 1748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(MCOperand::CreateReg(llvmRegnum)); 1758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 1768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 177b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the 178b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// immediate Value in the MCInst. 179b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// 180b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// @param Value - The immediate Value, has had any PC adjustment made by 181b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// the caller. 182b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// @param isBranch - If the instruction is a branch instruction 183b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// @param Address - The starting address of the instruction 184b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// @param Offset - The byte offset to this immediate in the instruction 185b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// @param Width - The byte width of this immediate in the instruction 186b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// 187b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// If the getOpInfo() function was set when setupForSymbolicDisassembly() was 188b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// called then that function is called to get any symbolic information for the 189b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// immediate in the instruction using the Address, Offset and Width. If that 190b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// returns non-zero then the symbolic information it returns is used to create 191b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// an MCExpr and that is added as an operand to the MCInst. If getOpInfo() 192b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// returns zero and isBranch is true then a symbol look up for immediate Value 193b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// is done and if a symbol is found an MCExpr is created with that, else 194b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// an MCExpr with the immediate Value is created. This function returns true 195b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// if it adds an operand to the MCInst and false otherwise. 196b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderbystatic bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, 197b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby uint64_t Address, uint64_t Offset, 198b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby uint64_t Width, MCInst &MI, 199b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 200b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby LLVMOpInfoCallback getOpInfo = Dis->getLLVMOpInfoCallback(); 201b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby struct LLVMOpInfo1 SymbolicOp; 202b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); 203b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby SymbolicOp.Value = Value; 204b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby void *DisInfo = Dis->getDisInfoBlock(); 205b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 206b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (!getOpInfo || 207b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby !getOpInfo(DisInfo, Address, Offset, Width, 1, &SymbolicOp)) { 208b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby // Clear SymbolicOp.Value from above and also all other fields. 209b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); 210b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby LLVMSymbolLookupCallback SymbolLookUp = Dis->getLLVMSymbolLookupCallback(); 211b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (!SymbolLookUp) 212b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return false; 213b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby uint64_t ReferenceType; 214b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (isBranch) 215b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby ReferenceType = LLVMDisassembler_ReferenceType_In_Branch; 216b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby else 217b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; 218b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const char *ReferenceName; 219b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address, 220b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby &ReferenceName); 221b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (Name) { 222b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby SymbolicOp.AddSymbol.Name = Name; 223b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby SymbolicOp.AddSymbol.Present = true; 224b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 225b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby // For branches always create an MCExpr so it gets printed as hex address. 226b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby else if (isBranch) { 227b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby SymbolicOp.Value = Value; 228b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 229b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub) 230b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby (*Dis->CommentStream) << "symbol stub for: " << ReferenceName; 231b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (!Name && !isBranch) 232b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return false; 233b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 234b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 235b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby MCContext *Ctx = Dis->getMCContext(); 236b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCExpr *Add = NULL; 237b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (SymbolicOp.AddSymbol.Present) { 238b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (SymbolicOp.AddSymbol.Name) { 239b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby StringRef Name(SymbolicOp.AddSymbol.Name); 240b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name); 241b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Add = MCSymbolRefExpr::Create(Sym, *Ctx); 242b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } else { 243b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Add = MCConstantExpr::Create((int)SymbolicOp.AddSymbol.Value, *Ctx); 244b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 245b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 246b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 247b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCExpr *Sub = NULL; 248b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (SymbolicOp.SubtractSymbol.Present) { 249b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (SymbolicOp.SubtractSymbol.Name) { 250b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby StringRef Name(SymbolicOp.SubtractSymbol.Name); 251b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name); 252b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Sub = MCSymbolRefExpr::Create(Sym, *Ctx); 253b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } else { 254b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Sub = MCConstantExpr::Create((int)SymbolicOp.SubtractSymbol.Value, *Ctx); 255b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 256b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 257b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 258b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCExpr *Off = NULL; 259b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (SymbolicOp.Value != 0) 260b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Off = MCConstantExpr::Create(SymbolicOp.Value, *Ctx); 261b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 262b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCExpr *Expr; 263b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (Sub) { 264b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCExpr *LHS; 265b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (Add) 266b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby LHS = MCBinaryExpr::CreateSub(Add, Sub, *Ctx); 267b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby else 268b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby LHS = MCUnaryExpr::CreateMinus(Sub, *Ctx); 269b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (Off != 0) 270b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx); 271b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby else 272b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Expr = LHS; 273b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } else if (Add) { 274b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (Off != 0) 275b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx); 276b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby else 277b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Expr = Add; 278b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } else { 279b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (Off != 0) 280b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Expr = Off; 281b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby else 282b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Expr = MCConstantExpr::Create(0, *Ctx); 283b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 284b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 285b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby MI.addOperand(MCOperand::CreateExpr(Expr)); 286b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 287b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return true; 288b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby} 289b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 2908bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// tryAddingPcLoadReferenceComment - trys to add a comment as to what is being 2918bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// referenced by a load instruction with the base register that is the rip. 2928bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// These can often be addresses in a literal pool. The Address of the 2938bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// instruction and its immediate Value are used to determine the address 2948bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// being referenced in the literal pool entry. The SymbolLookUp call back will 2958bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// return a pointer to a literal 'C' string if the referenced address is an 2968bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// address into a section with 'C' string literals. 2978bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderbystatic void tryAddingPcLoadReferenceComment(uint64_t Address, uint64_t Value, 2988bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby const void *Decoder) { 2998bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder); 3008bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby LLVMSymbolLookupCallback SymbolLookUp = Dis->getLLVMSymbolLookupCallback(); 3018bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby if (SymbolLookUp) { 3028bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby void *DisInfo = Dis->getDisInfoBlock(); 3038bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load; 3048bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby const char *ReferenceName; 3058bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName); 3068bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) 3078bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby (*Dis->CommentStream) << "literal pool for: " << ReferenceName; 3088bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby } 3098bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby} 3108bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby 3118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateImmediate - Appends an immediate operand to an MCInst. 3128ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 3138ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 3148ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param immediate - The immediate value to append. 315be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan/// @param operand - The operand, as stored in the descriptor table. 316be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan/// @param insn - The internal instruction. 3174d1dca92bd6d4aad7121e28c7ffc93c0a6a187d7Benjamin Kramerstatic void translateImmediate(MCInst &mcInst, uint64_t immediate, 3184d1dca92bd6d4aad7121e28c7ffc93c0a6a187d7Benjamin Kramer const OperandSpecifier &operand, 319b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, 320b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 321be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan // Sign-extend the immediate if necessary. 322be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan 323be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan OperandType type = operand.type; 324be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan 325be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if (type == TYPE_RELv) { 326be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan switch (insn.displacementSize) { 327be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan default: 328be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 32989e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 1: 330be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan type = TYPE_MOFFS8; 331be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 33289e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 2: 333be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan type = TYPE_MOFFS16; 334be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 33589e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 4: 336be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan type = TYPE_MOFFS32; 337be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 33889e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 8: 339be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan type = TYPE_MOFFS64; 340be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 341be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan } 342be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan } 343d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby // By default sign-extend all X86 immediates based on their encoding. 344d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby else if (type == TYPE_IMM8 || type == TYPE_IMM16 || type == TYPE_IMM32 || 345d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby type == TYPE_IMM64) { 346d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby uint32_t Opcode = mcInst.getOpcode(); 347d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby switch (operand.encoding) { 348d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby default: 349d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 350d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_IB: 351d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby // Special case those X86 instructions that use the imm8 as a set of 352d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby // bits, bit count, etc. and are not sign-extend. 353d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby if (Opcode != X86::BLENDPSrri && Opcode != X86::BLENDPDrri && 354d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby Opcode != X86::PBLENDWrri && Opcode != X86::MPSADBWrri && 355d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby Opcode != X86::DPPSrri && Opcode != X86::DPPDrri && 356d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby Opcode != X86::INSERTPSrr && Opcode != X86::VBLENDPSYrri && 357d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby Opcode != X86::VBLENDPSYrmi && Opcode != X86::VBLENDPDYrri && 358d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby Opcode != X86::VBLENDPDYrmi && Opcode != X86::VPBLENDWrri && 359d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby Opcode != X86::VMPSADBWrri && Opcode != X86::VDPPSYrri && 360d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby Opcode != X86::VDPPSYrmi && Opcode != X86::VDPPDrri && 361d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby Opcode != X86::VINSERTPSrr) 362d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby type = TYPE_MOFFS8; 363d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 364d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_IW: 365d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby type = TYPE_MOFFS16; 366d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 367d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_ID: 368d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby type = TYPE_MOFFS32; 369d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 370d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_IO: 371d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby type = TYPE_MOFFS64; 372d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 373d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby } 374d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby } 375be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan 376b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby bool isBranch = false; 377b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby uint64_t pcrel = 0; 378be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan switch (type) { 3793bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper case TYPE_XMM128: 3803bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper mcInst.addOperand(MCOperand::CreateReg(X86::XMM0 + (immediate >> 4))); 3813bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper return; 3823bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper case TYPE_XMM256: 3833bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper mcInst.addOperand(MCOperand::CreateReg(X86::YMM0 + (immediate >> 4))); 3843bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper return; 385be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_REL8: 386b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby isBranch = true; 387b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize; 388b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby // fall through to sign extend the immediate if needed. 389b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby case TYPE_MOFFS8: 390be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if(immediate & 0x80) 391be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan immediate |= ~(0xffull); 392be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 393be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_MOFFS16: 394be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if(immediate & 0x8000) 395be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan immediate |= ~(0xffffull); 396be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 397be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_REL32: 398be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_REL64: 399b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby isBranch = true; 400b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize; 401b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby // fall through to sign extend the immediate if needed. 402b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby case TYPE_MOFFS32: 403be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if(immediate & 0x80000000) 404be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan immediate |= ~(0xffffffffull); 405be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 406be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_MOFFS64: 407be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan default: 408be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan // operand is 64 bits wide. Do nothing. 409be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 410be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan } 411be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan 412b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if(!tryAddingSymbolicOperand(immediate + pcrel, isBranch, insn.startLocation, 413b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.immediateOffset, insn.immediateSize, 414b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby mcInst, Dis)) 415b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby mcInst.addOperand(MCOperand::CreateImm(immediate)); 4168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 4178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRMRegister - Translates a register stored in the R/M field of the 4198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// ModR/M byte to its LLVM equivalent and appends it to an MCInst. 4208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 4218ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The internal instruction to extract the R/M field 4228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// from. 423a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; -1 otherwise 424a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananstatic bool translateRMRegister(MCInst &mcInst, 4258ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan InternalInstruction &insn) { 426a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) { 427a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("A R/M register operand may not have a SIB byte"); 428a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 429a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 4308ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4318ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.eaBase) { 432a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan default: 433a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected EA base register"); 434a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 4358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_NONE: 436a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("EA_BASE_NONE for ModR/M base"); 437a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 4388ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) case EA_BASE_##x: 4398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_EA_BASES 4408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 441a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("A R/M register operand may not have a base; " 442a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan "the operand must be a register."); 443a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 444a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan#define ENTRY(x) \ 4458ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_REG_##x: \ 4468ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(MCOperand::CreateReg(X86::x)); break; 4478ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_REGS 4488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 4498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 450a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 451a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 4528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 4538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRMMemory - Translates a memory operand stored in the Mod and R/M 4558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// fields of an internal instruction (and possibly its SIB byte) to a memory 4568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// operand in LLVM's format, and appends it to an MCInst. 4578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 4588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 4598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The instruction to extract Mod, R/M, and SIB fields 4608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// from. 461a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; nonzero otherwise 462b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderbystatic bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn, 463b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 4648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // Addresses in an MCInst are represented as five operands: 4658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 1. basereg (register) The R/M base, or (if there is a SIB) the 4668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // SIB base 4678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 2. scaleamount (immediate) 1, or (if there is a SIB) the specified 4688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // scale amount 4698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 3. indexreg (register) x86_registerNONE, or (if there is a SIB) 4708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // the index (which is multiplied by the 4718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // scale amount) 4728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 4. displacement (immediate) 0, or the displacement if there is one 4738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 5. segmentreg (register) x86_registerNONE for now, but could be set 4748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // if we have segment overrides 4758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand baseReg; 4778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand scaleAmount; 4788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand indexReg; 4798ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand displacement; 4808ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand segmentReg; 481b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby uint64_t pcrel = 0; 4828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) { 4848ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (insn.sibBase != SIB_BASE_NONE) { 4858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.sibBase) { 4868ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 487a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected sibBase"); 488a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 4898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) \ 4907fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan case SIB_BASE_##x: \ 4918ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::x); break; 4928ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_SIB_BASES 4938ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 4948ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 4958ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } else { 4968ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(0); 4978ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 4988ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4998ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (insn.sibIndex != SIB_INDEX_NONE) { 5008ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.sibIndex) { 5018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 502a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected sibIndex"); 503a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 5047fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan#define ENTRY(x) \ 5058ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case SIB_INDEX_##x: \ 5068ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::x); break; 5078ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan EA_BASES_32BIT 5088ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan EA_BASES_64BIT 5098ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 5108ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } else { 5128ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(0); 5138ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5148ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 5158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan scaleAmount = MCOperand::CreateImm(insn.sibScale); 5168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } else { 5178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.eaBase) { 5188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_NONE: 519a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (insn.eaDisplacement == EA_DISP_NONE) { 520a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("EA_BASE_NONE and EA_DISP_NONE for ModR/M base"); 521a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 522a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 523b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (insn.mode == MODE_64BIT){ 524b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby pcrel = insn.startLocation + 525b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.displacementOffset + insn.displacementSize; 5268bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby tryAddingPcLoadReferenceComment(insn.startLocation + 5278bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby insn.displacementOffset, 5288bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby insn.displacement + pcrel, Dis); 5298ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::RIP); // Section 2.2.1.6 530b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 5318ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan else 5328ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(0); 5338ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 5348ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(0); 5358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BX_SI: 5378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BX); 5388ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::SI); 5398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BX_DI: 5418ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BX); 5428ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::DI); 5438ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BP_SI: 5458ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BP); 5468ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::SI); 5478ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BP_DI: 5498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BP); 5508ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::DI); 5518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 5538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(0); 5548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.eaBase) { 5558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 556a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected eaBase"); 557a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 5588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // Here, we will use the fill-ins defined above. However, 5598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // BX_SI, BX_DI, BP_SI, and BP_DI are all handled above and 5608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // sib and sib64 were handled in the top-level if, so they're only 5618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // placeholders to keep the compiler happy. 5628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) \ 5638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_##x: \ 5648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::x); break; 5658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_EA_BASES 5668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 5678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) case EA_REG_##x: 5688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_REGS 5698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 570a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("A R/M memory operand may not be a register; " 571a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan "the base field must be a base."); 572a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 5738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5757fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan 5767fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan scaleAmount = MCOperand::CreateImm(1); 5778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 5798ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan displacement = MCOperand::CreateImm(insn.displacement); 5808ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 5818ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan static const uint8_t segmentRegnums[SEG_OVERRIDE_max] = { 5828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 0, // SEG_OVERRIDE_NONE 5838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::CS, 5848ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::SS, 5858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::DS, 5868ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::ES, 5878ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::FS, 5888ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::GS 5898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan }; 5908ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 5918ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan segmentReg = MCOperand::CreateReg(segmentRegnums[insn.segmentOverride]); 5928ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 5938ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(baseReg); 5948ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(scaleAmount); 5958ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(indexReg); 596b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if(!tryAddingSymbolicOperand(insn.displacement + pcrel, false, 597b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.startLocation, insn.displacementOffset, 598b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.displacementSize, mcInst, Dis)) 599b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby mcInst.addOperand(displacement); 60037a746bc854d050ded5e280a13aad359852eb06aChris Lattner mcInst.addOperand(segmentReg); 601a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 6028ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 6038ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6048ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRM - Translates an operand stored in the R/M (and possibly SIB) 6058ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// byte of an instruction to LLVM form, and appends it to an MCInst. 6068ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 6078ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 6088ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param operand - The operand, as stored in the descriptor table. 6098ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The instruction to extract Mod, R/M, and SIB fields 6108ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// from. 611a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; nonzero otherwise 6124d1dca92bd6d4aad7121e28c7ffc93c0a6a187d7Benjamin Kramerstatic bool translateRM(MCInst &mcInst, const OperandSpecifier &operand, 613b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, const MCDisassembler *Dis) { 6148ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (operand.type) { 6158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 616a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected type for a R/M operand"); 617a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 6188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R8: 6198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R16: 6208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R32: 6218ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R64: 6228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_Rv: 6238ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_MM: 6248ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_MM32: 6258ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_MM64: 6268ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM: 6278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM32: 6288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM64: 6298ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM128: 630a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan case TYPE_XMM256: 6318ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_DEBUGREG: 6321a8b789a4b8290d263c1c75411788ca45bae3230Sean Callanan case TYPE_CONTROLREG: 633a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return translateRMRegister(mcInst, insn); 6348ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M: 6358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M8: 6368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M16: 6378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M32: 6388ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M64: 6398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M128: 640a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan case TYPE_M256: 6418ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M512: 6428ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_Mv: 6438ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M32FP: 6448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M64FP: 6458ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M80FP: 6468ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M16INT: 6478ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M32INT: 6488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M64INT: 6498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M1616: 6508ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M1632: 6518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M1664: 6527fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan case TYPE_LEA: 653b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return translateRMMemory(mcInst, insn, Dis); 6548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 6558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 6568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateFPRegister - Translates a stack position on the FPU stack to its 6588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// LLVM form, and appends it to an MCInst. 6598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 6608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 6618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param stackPos - The stack position to translate. 662a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; nonzero otherwise. 663a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananstatic bool translateFPRegister(MCInst &mcInst, 664a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan uint8_t stackPos) { 665a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (stackPos >= 8) { 666a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Invalid FP stack position"); 667a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 668a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 6698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(MCOperand::CreateReg(X86::ST0 + stackPos)); 671a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 672a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 6738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 6748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateOperand - Translates an operand stored in an internal instruction 6768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// to LLVM's format and appends it to an MCInst. 6778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 6788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 6798ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param operand - The operand, as stored in the descriptor table. 6808ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The internal instruction. 681a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - false on success; true otherwise. 6824d1dca92bd6d4aad7121e28c7ffc93c0a6a187d7Benjamin Kramerstatic bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand, 683b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, 684b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 6858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (operand.encoding) { 6868ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 687a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unhandled operand encoding during translation"); 688a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 6898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_REG: 6908ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan translateRegister(mcInst, insn.reg); 691a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 6928ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RM: 693b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return translateRM(mcInst, operand, insn, Dis); 6948ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CB: 6958ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CW: 6968ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CD: 6978ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CP: 6988ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CO: 6998ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CT: 700a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Translation of code offsets isn't supported."); 701a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 7028ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_IB: 7038ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_IW: 7048ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_ID: 7058ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_IO: 7068ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_Iv: 7078ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_Ia: 708be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan translateImmediate(mcInst, 709be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan insn.immediates[insn.numImmediatesTranslated++], 710be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan operand, 711b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn, 712b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Dis); 713a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 7148ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RB: 7158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RW: 7168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RD: 7178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RO: 7188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan translateRegister(mcInst, insn.opcodeRegister); 719a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 7208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_I: 721a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return translateFPRegister(mcInst, insn.opcodeModifier); 7228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_Rv: 7238ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan translateRegister(mcInst, insn.opcodeRegister); 724a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 725a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan case ENCODING_VVVV: 726a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan translateRegister(mcInst, insn.vvvv); 727a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan return false; 7288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_DUP: 729a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return translateOperand(mcInst, 730a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan insn.spec->operands[operand.type - TYPE_DUP0], 731b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn, Dis); 7328ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 7338ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 7348ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateInstruction - Translates an internal instruction and all its 7368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// operands to an MCInst. 7378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 7388ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to populate with the instruction's data. 7398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The internal instruction. 740a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - false on success; true otherwise. 741a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananstatic bool translateInstruction(MCInst &mcInst, 742b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, 743b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 744a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (!insn.spec) { 745a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Instruction has no specification"); 746a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 747a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 7488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.setOpcode(insn.instructionID); 7508ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan int index; 7528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan insn.numImmediatesTranslated = 0; 7548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan for (index = 0; index < X86_MAX_OPERANDS; ++index) { 756a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (insn.spec->operands[index].encoding != ENCODING_NONE) { 757b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (translateOperand(mcInst, insn.spec->operands[index], insn, Dis)) { 758a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 759a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 760a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 7618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 762a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 763a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 7648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 7655f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar 766953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramerstatic MCDisassembler *createX86_32Disassembler(const Target &T, 767953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer const MCSubtargetInfo &STI) { 768953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer return new X86Disassembler::X86GenericDisassembler(STI, MODE_32BIT, 769953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer T.createMCInstrInfo()); 7705f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar} 7715f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar 772953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramerstatic MCDisassembler *createX86_64Disassembler(const Target &T, 773953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer const MCSubtargetInfo &STI) { 774953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer return new X86Disassembler::X86GenericDisassembler(STI, MODE_64BIT, 775953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer T.createMCInstrInfo()); 7765f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar} 7775f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar 7785f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbarextern "C" void LLVMInitializeX86Disassembler() { 7795f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar // Register the disassembler. 7805f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar TargetRegistry::RegisterMCDisassembler(TheX86_32Target, 7815f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar createX86_32Disassembler); 7825f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar TargetRegistry::RegisterMCDisassembler(TheX86_64Target, 7835f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar createX86_64Disassembler); 7845f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar} 785