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 47b438615abdc826a2fef33895b50dc60e3f39f988Roman Divackyconst char *x86DisassemblerGetInstrName(unsigned Opcode, const 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. 98b438615abdc826a2fef33895b50dc60e3f39f988Roman Divackystatic int regionReader(const void* arg, uint8_t* byte, uint64_t address) { 99b438615abdc826a2fef33895b50dc60e3f39f988Roman Divacky const MemoryObject* region = static_cast<const 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, 138b438615abdc826a2fef33895b50dc60e3f39f988Roman Divacky (const void*)®ion, 13915c9a1f60c2e9d9cb854d5c0072755be91d1cc96Benjamin Kramer loggerFn, 1408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan (void*)&vStream, 141b438615abdc826a2fef33895b50dc60e3f39f988Roman Divacky (const 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 323991271d9c454c9d599b63e4ebdd27b546e1782a1Craig Topper OperandType type = (OperandType)operand.type; 324be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan 325c007eff5365d4216bcb243a3eea9c372267d0964Kevin Enderby bool isBranch = false; 326c007eff5365d4216bcb243a3eea9c372267d0964Kevin Enderby uint64_t pcrel = 0; 327be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if (type == TYPE_RELv) { 328c007eff5365d4216bcb243a3eea9c372267d0964Kevin Enderby isBranch = true; 329c007eff5365d4216bcb243a3eea9c372267d0964Kevin Enderby pcrel = insn.startLocation + 33016b7dd64e91f1b05b40ebfeb64b49f3ac17cb426Kevin Enderby insn.immediateOffset + insn.immediateSize; 331be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan switch (insn.displacementSize) { 332be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan default: 333be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 33489e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 1: 335be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan type = TYPE_MOFFS8; 336be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 33789e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 2: 338be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan type = TYPE_MOFFS16; 339be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 34089e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 4: 341be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan type = TYPE_MOFFS32; 342be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 34389e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 8: 344be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan type = TYPE_MOFFS64; 345be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 346be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan } 347be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan } 348d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby // By default sign-extend all X86 immediates based on their encoding. 349d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby else if (type == TYPE_IMM8 || type == TYPE_IMM16 || type == TYPE_IMM32 || 350d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby type == TYPE_IMM64) { 351d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby uint32_t Opcode = mcInst.getOpcode(); 352d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby switch (operand.encoding) { 353d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby default: 354d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 355d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_IB: 356d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby // Special case those X86 instructions that use the imm8 as a set of 357d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby // bits, bit count, etc. and are not sign-extend. 358d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby if (Opcode != X86::BLENDPSrri && Opcode != X86::BLENDPDrri && 35956cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::PBLENDWrri && Opcode != X86::MPSADBWrri && 36056cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::DPPSrri && Opcode != X86::DPPDrri && 36156cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::INSERTPSrr && Opcode != X86::VBLENDPSYrri && 36256cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::VBLENDPSYrmi && Opcode != X86::VBLENDPDYrri && 36356cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::VBLENDPDYrmi && Opcode != X86::VPBLENDWrri && 36456cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::VMPSADBWrri && Opcode != X86::VDPPSYrri && 36556cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::VDPPSYrmi && Opcode != X86::VDPPDrri && 36656cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::VINSERTPSrr) 36756cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling type = TYPE_MOFFS8; 368d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 369d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_IW: 370d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby type = TYPE_MOFFS16; 371d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 372d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_ID: 373d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby type = TYPE_MOFFS32; 374d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 375d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_IO: 376d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby type = TYPE_MOFFS64; 377d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 378d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby } 379d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby } 380be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan 381be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan switch (type) { 382bf4043768c6726db523f99460645842e5024fc7fCraig Topper case TYPE_XMM32: 383bf4043768c6726db523f99460645842e5024fc7fCraig Topper case TYPE_XMM64: 3843bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper case TYPE_XMM128: 3853bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper mcInst.addOperand(MCOperand::CreateReg(X86::XMM0 + (immediate >> 4))); 3863bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper return; 3873bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper case TYPE_XMM256: 3883bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper mcInst.addOperand(MCOperand::CreateReg(X86::YMM0 + (immediate >> 4))); 3893bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper return; 390be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_REL8: 391b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby isBranch = true; 392b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize; 393b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby // fall through to sign extend the immediate if needed. 394b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby case TYPE_MOFFS8: 395be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if(immediate & 0x80) 396be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan immediate |= ~(0xffull); 397be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 398be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_MOFFS16: 399be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if(immediate & 0x8000) 400be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan immediate |= ~(0xffffull); 401be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 402be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_REL32: 403be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_REL64: 404b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby isBranch = true; 405b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize; 406b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby // fall through to sign extend the immediate if needed. 407b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby case TYPE_MOFFS32: 408be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if(immediate & 0x80000000) 409be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan immediate |= ~(0xffffffffull); 410be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 411be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_MOFFS64: 412be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan default: 413be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan // operand is 64 bits wide. Do nothing. 414be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 415be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan } 416be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan 417b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if(!tryAddingSymbolicOperand(immediate + pcrel, isBranch, insn.startLocation, 418b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.immediateOffset, insn.immediateSize, 419b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby mcInst, Dis)) 420b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby mcInst.addOperand(MCOperand::CreateImm(immediate)); 4218ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 4228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4238ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRMRegister - Translates a register stored in the R/M field of the 4248ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// ModR/M byte to its LLVM equivalent and appends it to an MCInst. 4258ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 4268ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The internal instruction to extract the R/M field 4278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// from. 428a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; -1 otherwise 429a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananstatic bool translateRMRegister(MCInst &mcInst, 4308ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan InternalInstruction &insn) { 431a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) { 432a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("A R/M register operand may not have a SIB byte"); 433a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 434a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 4358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.eaBase) { 437a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan default: 438a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected EA base register"); 439a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 4408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_NONE: 441a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("EA_BASE_NONE for ModR/M base"); 442a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 4438ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) case EA_BASE_##x: 4448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_EA_BASES 4458ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 446a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("A R/M register operand may not have a base; " 447a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan "the operand must be a register."); 448a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 449a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan#define ENTRY(x) \ 4508ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_REG_##x: \ 4518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(MCOperand::CreateReg(X86::x)); break; 4528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_REGS 4538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 4548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 455a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 456a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 4578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 4588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRMMemory - Translates a memory operand stored in the Mod and R/M 4608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// fields of an internal instruction (and possibly its SIB byte) to a memory 4618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// operand in LLVM's format, and appends it to an MCInst. 4628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 4638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 4648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The instruction to extract Mod, R/M, and SIB fields 4658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// from. 466a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; nonzero otherwise 467b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderbystatic bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn, 468b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 4698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // Addresses in an MCInst are represented as five operands: 4708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 1. basereg (register) The R/M base, or (if there is a SIB) the 4718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // SIB base 4728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 2. scaleamount (immediate) 1, or (if there is a SIB) the specified 4738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // scale amount 4748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 3. indexreg (register) x86_registerNONE, or (if there is a SIB) 4758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // the index (which is multiplied by the 4768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // scale amount) 4778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 4. displacement (immediate) 0, or the displacement if there is one 4788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 5. segmentreg (register) x86_registerNONE for now, but could be set 4798ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // if we have segment overrides 4808ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4818ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand baseReg; 4828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand scaleAmount; 4838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand indexReg; 4848ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand displacement; 4858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand segmentReg; 486b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby uint64_t pcrel = 0; 4878ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4888ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) { 4898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (insn.sibBase != SIB_BASE_NONE) { 4908ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.sibBase) { 4918ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 492a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected sibBase"); 493a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 4948ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) \ 4957fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan case SIB_BASE_##x: \ 4968ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::x); break; 4978ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_SIB_BASES 4988ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 4998ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5008ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } else { 5018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(0); 5028ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5031f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren 5041f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // Check whether we are handling VSIB addressing mode for GATHER. 5051f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // If sibIndex was set to SIB_INDEX_NONE, index offset is 4 and 5061f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // we should use SIB_INDEX_XMM4|YMM4 for VSIB. 5071f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // I don't see a way to get the correct IndexReg in readSIB: 5081f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // We can tell whether it is VSIB or SIB after instruction ID is decoded, 5091f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // but instruction ID may not be decoded yet when calling readSIB. 5101f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren uint32_t Opcode = mcInst.getOpcode(); 51140307c7dbe2d104784763c28697d7926793674afManman Ren bool IndexIs128 = (Opcode == X86::VGATHERDPDrm || 51240307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERDPDYrm || 51340307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERQPDrm || 51440307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERDPSrm || 51540307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERQPSrm || 51640307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERDQrm || 51740307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERDQYrm || 51840307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERQQrm || 51940307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERDDrm || 52040307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERQDrm); 52140307c7dbe2d104784763c28697d7926793674afManman Ren bool IndexIs256 = (Opcode == X86::VGATHERQPDYrm || 52240307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERDPSYrm || 52340307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERQPSYrm || 52440307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERQQYrm || 52540307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERDDYrm || 52640307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERQDYrm); 52740307c7dbe2d104784763c28697d7926793674afManman Ren if (IndexIs128 || IndexIs256) { 5281f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren unsigned IndexOffset = insn.sibIndex - 5291f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren (insn.addressSize == 8 ? SIB_INDEX_RAX:SIB_INDEX_EAX); 53040307c7dbe2d104784763c28697d7926793674afManman Ren SIBIndex IndexBase = IndexIs256 ? SIB_INDEX_YMM0 : SIB_INDEX_XMM0; 5311f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren insn.sibIndex = (SIBIndex)(IndexBase + 5321f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren (insn.sibIndex == SIB_INDEX_NONE ? 4 : IndexOffset)); 5331f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren } 5341f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren 5358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (insn.sibIndex != SIB_INDEX_NONE) { 5368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.sibIndex) { 5378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 538a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected sibIndex"); 539a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 5407fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan#define ENTRY(x) \ 5418ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case SIB_INDEX_##x: \ 5428ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::x); break; 5438ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan EA_BASES_32BIT 5448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan EA_BASES_64BIT 5451f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren REGS_XMM 5461f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren REGS_YMM 5478ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 5488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } else { 5508ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(0); 5518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 5538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan scaleAmount = MCOperand::CreateImm(insn.sibScale); 5548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } else { 5558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.eaBase) { 5568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_NONE: 557a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (insn.eaDisplacement == EA_DISP_NONE) { 558a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("EA_BASE_NONE and EA_DISP_NONE for ModR/M base"); 559a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 560a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 561b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (insn.mode == MODE_64BIT){ 562b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby pcrel = insn.startLocation + 563b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.displacementOffset + insn.displacementSize; 5648bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby tryAddingPcLoadReferenceComment(insn.startLocation + 5658bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby insn.displacementOffset, 5668bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby insn.displacement + pcrel, Dis); 5678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::RIP); // Section 2.2.1.6 568b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 5698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan else 5708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(0); 5718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 5728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(0); 5738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BX_SI: 5758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BX); 5768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::SI); 5778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BX_DI: 5798ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BX); 5808ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::DI); 5818ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BP_SI: 5838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BP); 5848ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::SI); 5858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5868ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BP_DI: 5878ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BP); 5888ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::DI); 5898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5908ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 5918ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(0); 5928ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.eaBase) { 5938ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 594a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected eaBase"); 595a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 5968ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // Here, we will use the fill-ins defined above. However, 5978ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // BX_SI, BX_DI, BP_SI, and BP_DI are all handled above and 5988ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // sib and sib64 were handled in the top-level if, so they're only 5998ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // placeholders to keep the compiler happy. 6008ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) \ 6018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_##x: \ 6028ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::x); break; 6038ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_EA_BASES 6048ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 6058ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) case EA_REG_##x: 6068ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_REGS 6078ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 608a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("A R/M memory operand may not be a register; " 609a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan "the base field must be a base."); 610a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 6118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 6128ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 6137fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan 6147fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan scaleAmount = MCOperand::CreateImm(1); 6158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 6168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan displacement = MCOperand::CreateImm(insn.displacement); 6188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan static const uint8_t segmentRegnums[SEG_OVERRIDE_max] = { 6208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 0, // SEG_OVERRIDE_NONE 6218ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::CS, 6228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::SS, 6238ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::DS, 6248ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::ES, 6258ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::FS, 6268ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan X86::GS 6278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan }; 6288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6298ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan segmentReg = MCOperand::CreateReg(segmentRegnums[insn.segmentOverride]); 6308ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6318ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(baseReg); 6328ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(scaleAmount); 6338ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(indexReg); 634b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if(!tryAddingSymbolicOperand(insn.displacement + pcrel, false, 635b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.startLocation, insn.displacementOffset, 636b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.displacementSize, mcInst, Dis)) 637b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby mcInst.addOperand(displacement); 63837a746bc854d050ded5e280a13aad359852eb06aChris Lattner mcInst.addOperand(segmentReg); 639a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 6408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 6418ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6428ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRM - Translates an operand stored in the R/M (and possibly SIB) 6438ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// byte of an instruction to LLVM form, and appends it to an MCInst. 6448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 6458ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 6468ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param operand - The operand, as stored in the descriptor table. 6478ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The instruction to extract Mod, R/M, and SIB fields 6488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// from. 649a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; nonzero otherwise 6504d1dca92bd6d4aad7121e28c7ffc93c0a6a187d7Benjamin Kramerstatic bool translateRM(MCInst &mcInst, const OperandSpecifier &operand, 651b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, const MCDisassembler *Dis) { 6528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (operand.type) { 6538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 654a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected type for a R/M operand"); 655a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 6568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R8: 6578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R16: 6588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R32: 6598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R64: 6608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_Rv: 6618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_MM: 6628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_MM32: 6638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_MM64: 6648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM: 6658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM32: 6668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM64: 6678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM128: 668a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan case TYPE_XMM256: 6698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_DEBUGREG: 6701a8b789a4b8290d263c1c75411788ca45bae3230Sean Callanan case TYPE_CONTROLREG: 671a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return translateRMRegister(mcInst, insn); 6728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M: 6738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M8: 6748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M16: 6758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M32: 6768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M64: 6778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M128: 678a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan case TYPE_M256: 6798ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M512: 6808ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_Mv: 6818ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M32FP: 6828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M64FP: 6838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M80FP: 6848ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M16INT: 6858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M32INT: 6868ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M64INT: 6878ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M1616: 6888ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M1632: 6898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M1664: 6907fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan case TYPE_LEA: 691b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return translateRMMemory(mcInst, insn, Dis); 6928ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 6938ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 6948ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6958ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateFPRegister - Translates a stack position on the FPU stack to its 6968ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// LLVM form, and appends it to an MCInst. 6978ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 6988ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 6998ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param stackPos - The stack position to translate. 700a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; nonzero otherwise. 701a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananstatic bool translateFPRegister(MCInst &mcInst, 702a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan uint8_t stackPos) { 703a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (stackPos >= 8) { 704a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Invalid FP stack position"); 705a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 706a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 7078ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7088ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(MCOperand::CreateReg(X86::ST0 + stackPos)); 709a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 710a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 7118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 7128ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7138ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateOperand - Translates an operand stored in an internal instruction 7148ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// to LLVM's format and appends it to an MCInst. 7158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 7168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 7178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param operand - The operand, as stored in the descriptor table. 7188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The internal instruction. 719a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - false on success; true otherwise. 7204d1dca92bd6d4aad7121e28c7ffc93c0a6a187d7Benjamin Kramerstatic bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand, 721b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, 722b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 7238ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (operand.encoding) { 7248ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 725a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unhandled operand encoding during translation"); 726a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 7278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_REG: 7288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan translateRegister(mcInst, insn.reg); 729a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 7308ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RM: 731b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return translateRM(mcInst, operand, insn, Dis); 7328ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CB: 7338ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CW: 7348ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CD: 7358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CP: 7368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CO: 7378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CT: 738a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Translation of code offsets isn't supported."); 739a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 7408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_IB: 7418ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_IW: 7428ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_ID: 7438ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_IO: 7448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_Iv: 7458ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_Ia: 746be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan translateImmediate(mcInst, 747be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan insn.immediates[insn.numImmediatesTranslated++], 748be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan operand, 749b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn, 750b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Dis); 751a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 7528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RB: 7538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RW: 7548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RD: 7558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RO: 7568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan translateRegister(mcInst, insn.opcodeRegister); 757a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 7588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_I: 759a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return translateFPRegister(mcInst, insn.opcodeModifier); 7608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_Rv: 7618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan translateRegister(mcInst, insn.opcodeRegister); 762a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 763a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan case ENCODING_VVVV: 764a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan translateRegister(mcInst, insn.vvvv); 765a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan return false; 7668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_DUP: 7675a2c607153993fb7f7e04f9482520b64dffe5757Craig Topper return translateOperand(mcInst, insn.operands[operand.type - TYPE_DUP0], 768b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn, Dis); 7698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 7708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 7718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateInstruction - Translates an internal instruction and all its 7738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// operands to an MCInst. 7748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 7758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to populate with the instruction's data. 7768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The internal instruction. 777a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - false on success; true otherwise. 778a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananstatic bool translateInstruction(MCInst &mcInst, 779b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, 780b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 781a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (!insn.spec) { 782a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Instruction has no specification"); 783a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 784a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 7858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7868ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.setOpcode(insn.instructionID); 7878ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7888ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan int index; 7898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7908ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan insn.numImmediatesTranslated = 0; 7918ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7928ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan for (index = 0; index < X86_MAX_OPERANDS; ++index) { 7935a2c607153993fb7f7e04f9482520b64dffe5757Craig Topper if (insn.operands[index].encoding != ENCODING_NONE) { 7945a2c607153993fb7f7e04f9482520b64dffe5757Craig Topper if (translateOperand(mcInst, insn.operands[index], insn, Dis)) { 795a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 796a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 797a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 7988ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 799a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 800a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 8018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 8025f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar 803953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramerstatic MCDisassembler *createX86_32Disassembler(const Target &T, 804953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer const MCSubtargetInfo &STI) { 805953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer return new X86Disassembler::X86GenericDisassembler(STI, MODE_32BIT, 806953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer T.createMCInstrInfo()); 8075f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar} 8085f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar 809953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramerstatic MCDisassembler *createX86_64Disassembler(const Target &T, 810953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer const MCSubtargetInfo &STI) { 811953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer return new X86Disassembler::X86GenericDisassembler(STI, MODE_64BIT, 812953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer T.createMCInstrInfo()); 8135f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar} 8145f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar 8155f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbarextern "C" void LLVMInitializeX86Disassembler() { 8165f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar // Register the disassembler. 8175f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar TargetRegistry::RegisterMCDisassembler(TheX86_32Target, 8185f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar createX86_32Disassembler); 8195f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar TargetRegistry::RegisterMCDisassembler(TheX86_64Target, 8205f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar createX86_64Disassembler); 8215f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar} 822