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" 19b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby#include "llvm/MC/MCContext.h" 205f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar#include "llvm/MC/MCDisassembler.h" 21d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/MC/MCExpr.h" 228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#include "llvm/MC/MCInst.h" 23953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer#include "llvm/MC/MCInstrInfo.h" 24b950585cc5a0d665e9accfe5ce490cd269756f2eJames Molloy#include "llvm/MC/MCSubtargetInfo.h" 25a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan#include "llvm/Support/Debug.h" 268ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#include "llvm/Support/MemoryObject.h" 273e74d6fdd248e20a280f1dff3da9a6c689c2c4c3Evan Cheng#include "llvm/Support/TargetRegistry.h" 288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#include "llvm/Support/raw_ostream.h" 290122c9051a0157908e3f4e1c604435339ac4761dSean Callanan 30dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesusing namespace llvm; 31dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesusing namespace llvm::X86Disassembler; 32dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 33dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "x86-disassembler" 34dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 3573f50d9bc3bd46cc0abeba9bb0d46977ba1aea42Evan Cheng#define GET_REGINFO_ENUM 3673f50d9bc3bd46cc0abeba9bb0d46977ba1aea42Evan Cheng#include "X86GenRegisterInfo.inc" 37d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby#define GET_INSTRINFO_ENUM 38d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby#include "X86GenInstrInfo.inc" 3936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#define GET_SUBTARGETINFO_ENUM 4036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "X86GenSubtargetInfo.inc" 410122c9051a0157908e3f4e1c604435339ac4761dSean Callanan 42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid llvm::X86Disassembler::Debug(const char *file, unsigned line, 43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const char *s) { 44a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan dbgs() << file << ":" << line << ": " << s; 45a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan} 46a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 47dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesconst char *llvm::X86Disassembler::GetInstrName(unsigned Opcode, 48dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const void *mii) { 49953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer const MCInstrInfo *MII = static_cast<const MCInstrInfo *>(mii); 50953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer return MII->getName(Opcode); 51953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer} 52953362cdfbf1088153f65376c86d22ee0176bcdfBenjamin Kramer 53dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define debug(s) DEBUG(Debug(__FILE__, __LINE__, s)); 54a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanannamespace llvm { 568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// Fill-ins to make the compiler happy. These constants are never actually 588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// assigned; they are just filler to make an automatically-generated switch 598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// statement work. 608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanannamespace X86 { 618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan enum { 628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan BX_SI = 500, 638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan BX_DI = 501, 648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan BP_SI = 502, 658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan BP_DI = 503, 668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan sib = 504, 678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan sib64 = 505 688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan }; 698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 710122c9051a0157908e3f4e1c604435339ac4761dSean Callananextern Target TheX86_32Target, TheX86_64Target; 720122c9051a0157908e3f4e1c604435339ac4761dSean Callanan 738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 75a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananstatic bool translateInstruction(MCInst &target, 76b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &source, 77b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis); 788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 79dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesX86GenericDisassembler::X86GenericDisassembler( 80dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCSubtargetInfo &STI, 81dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MCContext &Ctx, 82dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::unique_ptr<const MCInstrInfo> MII) 83dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines : MCDisassembler(STI, Ctx), MII(std::move(MII)) { 8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines switch (STI.getFeatureBits() & 8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines (X86::Mode16Bit | X86::Mode32Bit | X86::Mode64Bit)) { 8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case X86::Mode16Bit: 8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fMode = MODE_16BIT; 8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case X86::Mode32Bit: 9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fMode = MODE_32BIT; 9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case X86::Mode64Bit: 9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines fMode = MODE_64BIT; 9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines break; 9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines default: 9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines llvm_unreachable("Invalid CPU mode"); 9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 9836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 998ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1008ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// regionReader - a callback function that wraps the readByte method from 1018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// MemoryObject. 1028ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 1038ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param arg - The generic callback parameter. In this case, this should 1048ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// be a pointer to a MemoryObject. 1058ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param byte - A pointer to the byte to be read. 1068ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param address - The address to be read. 107b438615abdc826a2fef33895b50dc60e3f39f988Roman Divackystatic int regionReader(const void* arg, uint8_t* byte, uint64_t address) { 108b438615abdc826a2fef33895b50dc60e3f39f988Roman Divacky const MemoryObject* region = static_cast<const MemoryObject*>(arg); 1098ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return region->readByte(address, byte); 1108ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 1118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1128ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// logger - a callback function that wraps the operator<< method from 1138ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// raw_ostream. 1148ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 1158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param arg - The generic callback parameter. This should be a pointe 1168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// to a raw_ostream. 1178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param log - A string to be logged. logger() adds a newline. 1188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananstatic void logger(void* arg, const char* log) { 1198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (!arg) 1208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return; 1218ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan raw_ostream &vStream = *(static_cast<raw_ostream*>(arg)); 1238ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan vStream << log << "\n"; 1248ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 1258ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1268ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 1278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// Public interface for the disassembler 1288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 1298ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 13083e3f67fb68d497b600da83a62f000fcce7868a9Owen AndersonMCDisassembler::DecodeStatus 13183e3f67fb68d497b600da83a62f000fcce7868a9Owen AndersonX86GenericDisassembler::getInstruction(MCInst &instr, 13283e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson uint64_t &size, 133adef06a71458ded0716935a61b3d43d164d4df12Derek Schuff const MemoryObject ®ion, 13483e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson uint64_t address, 13598c5ddabca1debf935a07d14d0cbc9732374bdb8Owen Anderson raw_ostream &vStream, 13698c5ddabca1debf935a07d14d0cbc9732374bdb8Owen Anderson raw_ostream &cStream) const { 137b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby CommentStream = &cStream; 138b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 1398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan InternalInstruction internalInstr; 14015c9a1f60c2e9d9cb854d5c0072755be91d1cc96Benjamin Kramer 14115c9a1f60c2e9d9cb854d5c0072755be91d1cc96Benjamin Kramer dlog_t loggerFn = logger; 14215c9a1f60c2e9d9cb854d5c0072755be91d1cc96Benjamin Kramer if (&vStream == &nulls()) 143dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines loggerFn = nullptr; // Disable logging completely if it's going to nulls(). 1448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1458ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan int ret = decodeInstruction(&internalInstr, 1468ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan regionReader, 147b438615abdc826a2fef33895b50dc60e3f39f988Roman Divacky (const void*)®ion, 14815c9a1f60c2e9d9cb854d5c0072755be91d1cc96Benjamin Kramer loggerFn, 1498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan (void*)&vStream, 150dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines (const void*)MII.get(), 1518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan address, 1528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan fMode); 1538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 154a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (ret) { 1558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan size = internalInstr.readerCursor - address; 15683e3f67fb68d497b600da83a62f000fcce7868a9Owen Anderson return Fail; 1578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan else { 1598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan size = internalInstr.length; 160b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return (!translateInstruction(instr, internalInstr, this)) ? 161b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Success : Fail; 1628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 1648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 1668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// Private code that translates from struct InternalInstructions to MCInsts. 1678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 1688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRegister - Translates an internal register to the appropriate LLVM 1708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// register, and appends it as an operand to an MCInst. 1718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 1728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 1738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param reg - The Reg to append. 1748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananstatic void translateRegister(MCInst &mcInst, Reg reg) { 1758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) X86::x, 1768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan uint8_t llvmRegnums[] = { 1778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_REGS 1788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 0 1798ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan }; 1808ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 1818ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan uint8_t llvmRegnum = llvmRegnums[reg]; 1838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(MCOperand::CreateReg(llvmRegnum)); 1848ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 1858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 186b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the 187b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// immediate Value in the MCInst. 188b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// 189b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// @param Value - The immediate Value, has had any PC adjustment made by 190b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// the caller. 191b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// @param isBranch - If the instruction is a branch instruction 192b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// @param Address - The starting address of the instruction 193b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// @param Offset - The byte offset to this immediate in the instruction 194b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// @param Width - The byte width of this immediate in the instruction 195b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// 196b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// If the getOpInfo() function was set when setupForSymbolicDisassembly() was 197b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// called then that function is called to get any symbolic information for the 198b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// immediate in the instruction using the Address, Offset and Width. If that 199b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// returns non-zero then the symbolic information it returns is used to create 200b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// an MCExpr and that is added as an operand to the MCInst. If getOpInfo() 201b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// returns zero and isBranch is true then a symbol look up for immediate Value 202b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// is done and if a symbol is found an MCExpr is created with that, else 203b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// an MCExpr with the immediate Value is created. This function returns true 204b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby/// if it adds an operand to the MCInst and false otherwise. 205b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderbystatic bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, 206b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby uint64_t Address, uint64_t Offset, 207b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby uint64_t Width, MCInst &MI, 208b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 2092c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, 2102c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Offset, Width); 211b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby} 212b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby 2138bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// tryAddingPcLoadReferenceComment - trys to add a comment as to what is being 2148bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// referenced by a load instruction with the base register that is the rip. 2158bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// These can often be addresses in a literal pool. The Address of the 2168bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// instruction and its immediate Value are used to determine the address 2178bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// being referenced in the literal pool entry. The SymbolLookUp call back will 2188bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// return a pointer to a literal 'C' string if the referenced address is an 2198bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby/// address into a section with 'C' string literals. 2208bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderbystatic void tryAddingPcLoadReferenceComment(uint64_t Address, uint64_t Value, 2218bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby const void *Decoder) { 2228bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby const MCDisassembler *Dis = static_cast<const MCDisassembler*>(Decoder); 2232c94d0faa0e1c268893d5e04dc77e8a35889db00Ahmed Bougacha Dis->tryAddingPcLoadReferenceComment(Value, Address); 2248bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby} 2258bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby 22636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic const uint8_t segmentRegnums[SEG_OVERRIDE_max] = { 22736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 0, // SEG_OVERRIDE_NONE 22836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines X86::CS, 22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines X86::SS, 23036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines X86::DS, 23136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines X86::ES, 23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines X86::FS, 23336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines X86::GS 23436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}; 23536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 23636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// translateSrcIndex - Appends a source index operand to an MCInst. 23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// 23836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// @param mcInst - The MCInst to append to. 23936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// @param insn - The internal instruction. 24036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool translateSrcIndex(MCInst &mcInst, InternalInstruction &insn) { 24136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned baseRegNo; 24236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 24336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (insn.mode == MODE_64BIT) 24436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines baseRegNo = insn.prefixPresent[0x67] ? X86::ESI : X86::RSI; 24536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (insn.mode == MODE_32BIT) 24636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines baseRegNo = insn.prefixPresent[0x67] ? X86::SI : X86::ESI; 24736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else { 24836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(insn.mode == MODE_16BIT); 24936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines baseRegNo = insn.prefixPresent[0x67] ? X86::ESI : X86::SI; 25036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 25136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCOperand baseReg = MCOperand::CreateReg(baseRegNo); 25236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines mcInst.addOperand(baseReg); 25336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 25436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCOperand segmentReg; 25536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines segmentReg = MCOperand::CreateReg(segmentRegnums[insn.segmentOverride]); 25636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines mcInst.addOperand(segmentReg); 25736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return false; 25836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 25936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 26036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// translateDstIndex - Appends a destination index operand to an MCInst. 26136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// 26236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// @param mcInst - The MCInst to append to. 26336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// @param insn - The internal instruction. 26436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 26536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool translateDstIndex(MCInst &mcInst, InternalInstruction &insn) { 26636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines unsigned baseRegNo; 26736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 26836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (insn.mode == MODE_64BIT) 26936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines baseRegNo = insn.prefixPresent[0x67] ? X86::EDI : X86::RDI; 27036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (insn.mode == MODE_32BIT) 27136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines baseRegNo = insn.prefixPresent[0x67] ? X86::DI : X86::EDI; 27236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else { 27336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines assert(insn.mode == MODE_16BIT); 27436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines baseRegNo = insn.prefixPresent[0x67] ? X86::EDI : X86::DI; 27536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 27636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCOperand baseReg = MCOperand::CreateReg(baseRegNo); 27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines mcInst.addOperand(baseReg); 27836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return false; 27936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 2818ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateImmediate - Appends an immediate operand to an MCInst. 2828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 2838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 2848ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param immediate - The immediate value to append. 285be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan/// @param operand - The operand, as stored in the descriptor table. 286be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan/// @param insn - The internal instruction. 2874d1dca92bd6d4aad7121e28c7ffc93c0a6a187d7Benjamin Kramerstatic void translateImmediate(MCInst &mcInst, uint64_t immediate, 2884d1dca92bd6d4aad7121e28c7ffc93c0a6a187d7Benjamin Kramer const OperandSpecifier &operand, 289b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, 290b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 291be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan // Sign-extend the immediate if necessary. 292be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan 293991271d9c454c9d599b63e4ebdd27b546e1782a1Craig Topper OperandType type = (OperandType)operand.type; 294be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan 295c007eff5365d4216bcb243a3eea9c372267d0964Kevin Enderby bool isBranch = false; 296c007eff5365d4216bcb243a3eea9c372267d0964Kevin Enderby uint64_t pcrel = 0; 297be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if (type == TYPE_RELv) { 298c007eff5365d4216bcb243a3eea9c372267d0964Kevin Enderby isBranch = true; 299c007eff5365d4216bcb243a3eea9c372267d0964Kevin Enderby pcrel = insn.startLocation + 30016b7dd64e91f1b05b40ebfeb64b49f3ac17cb426Kevin Enderby insn.immediateOffset + insn.immediateSize; 301be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan switch (insn.displacementSize) { 302be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan default: 303be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 30489e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 1: 305a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper if(immediate & 0x80) 306a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper immediate |= ~(0xffull); 307be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 30889e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 2: 309a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper if(immediate & 0x8000) 310a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper immediate |= ~(0xffffull); 311be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 31289e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 4: 313a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper if(immediate & 0x80000000) 314a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper immediate |= ~(0xffffffffull); 315be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 31689e59e6343303696e14d4c134582dda083cf7408Sean Callanan case 8: 317be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 318be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan } 319be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan } 320d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby // By default sign-extend all X86 immediates based on their encoding. 321d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby else if (type == TYPE_IMM8 || type == TYPE_IMM16 || type == TYPE_IMM32 || 322dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines type == TYPE_IMM64 || type == TYPE_IMMv) { 323d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby uint32_t Opcode = mcInst.getOpcode(); 324d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby switch (operand.encoding) { 325d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby default: 326d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 327d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_IB: 328d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby // Special case those X86 instructions that use the imm8 as a set of 329d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby // bits, bit count, etc. and are not sign-extend. 330d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby if (Opcode != X86::BLENDPSrri && Opcode != X86::BLENDPDrri && 33156cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::PBLENDWrri && Opcode != X86::MPSADBWrri && 33256cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::DPPSrri && Opcode != X86::DPPDrri && 33356cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::INSERTPSrr && Opcode != X86::VBLENDPSYrri && 33456cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::VBLENDPSYrmi && Opcode != X86::VBLENDPDYrri && 33556cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::VBLENDPDYrmi && Opcode != X86::VPBLENDWrri && 33656cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::VMPSADBWrri && Opcode != X86::VDPPSYrri && 33756cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::VDPPSYrmi && Opcode != X86::VDPPDrri && 33856cb2298663017eb77aa4f4dda8db7ecd1b58173Bill Wendling Opcode != X86::VINSERTPSrr) 339a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper if(immediate & 0x80) 340a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper immediate |= ~(0xffull); 341d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 342d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_IW: 343a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper if(immediate & 0x8000) 344a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper immediate |= ~(0xffffull); 345d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 346d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_ID: 347a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper if(immediate & 0x80000000) 348a4959f3f6eb9b6ab3cbbe085a2797208682e96c6Craig Topper immediate |= ~(0xffffffffull); 349d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 350d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby case ENCODING_IO: 351d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby break; 352d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby } 353d5705fe50d58dd2b686b26d1683315f785246ce0Kevin Enderby } 354be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan 355be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan switch (type) { 356bf4043768c6726db523f99460645842e5024fc7fCraig Topper case TYPE_XMM32: 357bf4043768c6726db523f99460645842e5024fc7fCraig Topper case TYPE_XMM64: 3583bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper case TYPE_XMM128: 3593bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper mcInst.addOperand(MCOperand::CreateReg(X86::XMM0 + (immediate >> 4))); 3603bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper return; 3613bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper case TYPE_XMM256: 3623bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper mcInst.addOperand(MCOperand::CreateReg(X86::YMM0 + (immediate >> 4))); 3633bb43a829e03ed8ea671f5bc331772ef7afc3313Craig Topper return; 364c18f4efc5dd24adcc653806455fc7ae8508e9c66Elena Demikhovsky case TYPE_XMM512: 365c18f4efc5dd24adcc653806455fc7ae8508e9c66Elena Demikhovsky mcInst.addOperand(MCOperand::CreateReg(X86::ZMM0 + (immediate >> 4))); 366c18f4efc5dd24adcc653806455fc7ae8508e9c66Elena Demikhovsky return; 367be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_REL8: 368b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby isBranch = true; 369b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize; 370be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if(immediate & 0x80) 371be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan immediate |= ~(0xffull); 372be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 373be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_REL32: 374be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan case TYPE_REL64: 375b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby isBranch = true; 376b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby pcrel = insn.startLocation + insn.immediateOffset + insn.immediateSize; 377be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan if(immediate & 0x80000000) 378be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan immediate |= ~(0xffffffffull); 379be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 380be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan default: 381be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan // operand is 64 bits wide. Do nothing. 382be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan break; 383be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan } 384f86778a84898b773c54e249a015be183acf13c30Craig Topper 385b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if(!tryAddingSymbolicOperand(immediate + pcrel, isBranch, insn.startLocation, 386b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.immediateOffset, insn.immediateSize, 387b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby mcInst, Dis)) 388b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby mcInst.addOperand(MCOperand::CreateImm(immediate)); 38936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 39036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (type == TYPE_MOFFS8 || type == TYPE_MOFFS16 || 39136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines type == TYPE_MOFFS32 || type == TYPE_MOFFS64) { 39236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines MCOperand segmentReg; 39336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines segmentReg = MCOperand::CreateReg(segmentRegnums[insn.segmentOverride]); 39436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines mcInst.addOperand(segmentReg); 39536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 3968ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 3978ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 3988ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRMRegister - Translates a register stored in the R/M field of the 3998ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// ModR/M byte to its LLVM equivalent and appends it to an MCInst. 4008ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 4018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The internal instruction to extract the R/M field 4028ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// from. 403a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; -1 otherwise 404a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananstatic bool translateRMRegister(MCInst &mcInst, 4058ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan InternalInstruction &insn) { 406a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) { 407a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("A R/M register operand may not have a SIB byte"); 408a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 409a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 4108ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.eaBase) { 412a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan default: 413a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected EA base register"); 414a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 4158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_NONE: 416a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("EA_BASE_NONE for ModR/M base"); 417a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 4188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) case EA_BASE_##x: 4198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_EA_BASES 4208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 421a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("A R/M register operand may not have a base; " 422a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan "the operand must be a register."); 423a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 424a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan#define ENTRY(x) \ 4258ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_REG_##x: \ 4268ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(MCOperand::CreateReg(X86::x)); break; 4278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_REGS 4288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 4298ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 430a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 431a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 4328ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 4338ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4348ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRMMemory - Translates a memory operand stored in the Mod and R/M 4358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// fields of an internal instruction (and possibly its SIB byte) to a memory 4368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// operand in LLVM's format, and appends it to an MCInst. 4378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 4388ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 4398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The instruction to extract Mod, R/M, and SIB fields 4408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// from. 441a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; nonzero otherwise 442b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderbystatic bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn, 443b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 4448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // Addresses in an MCInst are represented as five operands: 4458ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 1. basereg (register) The R/M base, or (if there is a SIB) the 4468ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // SIB base 4478ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 2. scaleamount (immediate) 1, or (if there is a SIB) the specified 4488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // scale amount 4498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 3. indexreg (register) x86_registerNONE, or (if there is a SIB) 4508ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // the index (which is multiplied by the 4518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // scale amount) 4528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 4. displacement (immediate) 0, or the displacement if there is one 4538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // 5. segmentreg (register) x86_registerNONE for now, but could be set 4548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // if we have segment overrides 4558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand baseReg; 4578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand scaleAmount; 4588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand indexReg; 4598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand displacement; 4608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan MCOperand segmentReg; 461b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby uint64_t pcrel = 0; 4628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 4638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) { 4648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (insn.sibBase != SIB_BASE_NONE) { 4658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.sibBase) { 4668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 467a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected sibBase"); 468a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 4698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) \ 4707fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan case SIB_BASE_##x: \ 4718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::x); break; 4728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_SIB_BASES 4738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 4748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 4758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } else { 4768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(0); 4778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 4781f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren 4791f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // Check whether we are handling VSIB addressing mode for GATHER. 4801f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // If sibIndex was set to SIB_INDEX_NONE, index offset is 4 and 4811f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // we should use SIB_INDEX_XMM4|YMM4 for VSIB. 4821f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // I don't see a way to get the correct IndexReg in readSIB: 4831f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // We can tell whether it is VSIB or SIB after instruction ID is decoded, 4841f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren // but instruction ID may not be decoded yet when calling readSIB. 4851f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren uint32_t Opcode = mcInst.getOpcode(); 48640307c7dbe2d104784763c28697d7926793674afManman Ren bool IndexIs128 = (Opcode == X86::VGATHERDPDrm || 48740307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERDPDYrm || 48840307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERQPDrm || 48940307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERDPSrm || 49040307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERQPSrm || 49140307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERDQrm || 49240307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERDQYrm || 49340307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERQQrm || 49440307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERDDrm || 49540307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERQDrm); 49640307c7dbe2d104784763c28697d7926793674afManman Ren bool IndexIs256 = (Opcode == X86::VGATHERQPDYrm || 49740307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERDPSYrm || 49840307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VGATHERQPSYrm || 49936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Opcode == X86::VGATHERDPDZrm || 50036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Opcode == X86::VPGATHERDQZrm || 50140307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERQQYrm || 50240307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERDDYrm || 50340307c7dbe2d104784763c28697d7926793674afManman Ren Opcode == X86::VPGATHERQDYrm); 50436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool IndexIs512 = (Opcode == X86::VGATHERQPDZrm || 50536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Opcode == X86::VGATHERDPSZrm || 50636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Opcode == X86::VGATHERQPSZrm || 50736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Opcode == X86::VPGATHERQQZrm || 50836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Opcode == X86::VPGATHERDDZrm || 50936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Opcode == X86::VPGATHERQDZrm); 51036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (IndexIs128 || IndexIs256 || IndexIs512) { 5111f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren unsigned IndexOffset = insn.sibIndex - 5121f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren (insn.addressSize == 8 ? SIB_INDEX_RAX:SIB_INDEX_EAX); 51336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SIBIndex IndexBase = IndexIs512 ? SIB_INDEX_ZMM0 : 51436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines IndexIs256 ? SIB_INDEX_YMM0 : SIB_INDEX_XMM0; 5151f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren insn.sibIndex = (SIBIndex)(IndexBase + 5161f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren (insn.sibIndex == SIB_INDEX_NONE ? 4 : IndexOffset)); 5171f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren } 5181f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren 5198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (insn.sibIndex != SIB_INDEX_NONE) { 5208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.sibIndex) { 5218ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 522a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected sibIndex"); 523a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 5247fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan#define ENTRY(x) \ 5258ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case SIB_INDEX_##x: \ 5268ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::x); break; 5278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan EA_BASES_32BIT 5288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan EA_BASES_64BIT 5291f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren REGS_XMM 5301f7a1b68a07ea6bdf521525a7928f4a8c5216713Manman Ren REGS_YMM 531c18f4efc5dd24adcc653806455fc7ae8508e9c66Elena Demikhovsky REGS_ZMM 5328ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 5338ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5348ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } else { 5358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(0); 5368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 5388ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan scaleAmount = MCOperand::CreateImm(insn.sibScale); 5398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } else { 5408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.eaBase) { 5418ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_NONE: 542a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (insn.eaDisplacement == EA_DISP_NONE) { 543a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("EA_BASE_NONE and EA_DISP_NONE for ModR/M base"); 544a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 545a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 546b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if (insn.mode == MODE_64BIT){ 547b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby pcrel = insn.startLocation + 548b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.displacementOffset + insn.displacementSize; 5498bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby tryAddingPcLoadReferenceComment(insn.startLocation + 5508bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby insn.displacementOffset, 5518bee081a2cc6a84de125525215fffb4cc1cbe12aKevin Enderby insn.displacement + pcrel, Dis); 5528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::RIP); // Section 2.2.1.6 553b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby } 5548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan else 5558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(0); 5568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 5578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(0); 5588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BX_SI: 5608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BX); 5618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::SI); 5628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BX_DI: 5648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BX); 5658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::DI); 5668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BP_SI: 5688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BP); 5698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::SI); 5708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_BP_DI: 5728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::BP); 5738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(X86::DI); 5748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan break; 5758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 5768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan indexReg = MCOperand::CreateReg(0); 5778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (insn.eaBase) { 5788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 579a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected eaBase"); 580a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 5818ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // Here, we will use the fill-ins defined above. However, 5828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // BX_SI, BX_DI, BP_SI, and BP_DI are all handled above and 5838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // sib and sib64 were handled in the top-level if, so they're only 5848ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan // placeholders to keep the compiler happy. 5858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) \ 5868ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case EA_BASE_##x: \ 5878ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan baseReg = MCOperand::CreateReg(X86::x); break; 5888ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_EA_BASES 5898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 5908ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define ENTRY(x) case EA_REG_##x: 5918ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ALL_REGS 5928ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#undef ENTRY 593a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("A R/M memory operand may not be a register; " 594a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan "the base field must be a base."); 595a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 5968ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5978ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 5987fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan 5997fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan scaleAmount = MCOperand::CreateImm(1); 6008ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 6018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6028ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan displacement = MCOperand::CreateImm(insn.displacement); 60336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 6048ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan segmentReg = MCOperand::CreateReg(segmentRegnums[insn.segmentOverride]); 6058ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6068ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(baseReg); 6078ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(scaleAmount); 6088ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.addOperand(indexReg); 609b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby if(!tryAddingSymbolicOperand(insn.displacement + pcrel, false, 610b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.startLocation, insn.displacementOffset, 611b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn.displacementSize, mcInst, Dis)) 612b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby mcInst.addOperand(displacement); 61337a746bc854d050ded5e280a13aad359852eb06aChris Lattner mcInst.addOperand(segmentReg); 614a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 6158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 6168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateRM - Translates an operand stored in the R/M (and possibly SIB) 6188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// byte of an instruction to LLVM form, and appends it to an MCInst. 6198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 6208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 6218ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param operand - The operand, as stored in the descriptor table. 6228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The instruction to extract Mod, R/M, and SIB fields 6238ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// from. 624a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - 0 on success; nonzero otherwise 6254d1dca92bd6d4aad7121e28c7ffc93c0a6a187d7Benjamin Kramerstatic bool translateRM(MCInst &mcInst, const OperandSpecifier &operand, 626b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, const MCDisassembler *Dis) { 6278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (operand.type) { 6288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 629a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unexpected type for a R/M operand"); 630a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 6318ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R8: 6328ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R16: 6338ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R32: 6348ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_R64: 6358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_Rv: 6368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_MM: 6378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_MM32: 6388ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_MM64: 6398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM: 6408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM32: 6418ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM64: 6428ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_XMM128: 643a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan case TYPE_XMM256: 644c18f4efc5dd24adcc653806455fc7ae8508e9c66Elena Demikhovsky case TYPE_XMM512: 64536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case TYPE_VK1: 64636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case TYPE_VK8: 64736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case TYPE_VK16: 6488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_DEBUGREG: 6491a8b789a4b8290d263c1c75411788ca45bae3230Sean Callanan case TYPE_CONTROLREG: 650a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return translateRMRegister(mcInst, insn); 6518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M: 6528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M8: 6538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M16: 6548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M32: 6558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M64: 6568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M128: 657a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan case TYPE_M256: 6588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M512: 6598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_Mv: 6608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M32FP: 6618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M64FP: 6628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M80FP: 6638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M16INT: 6648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M32INT: 6658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M64INT: 6668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M1616: 6678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M1632: 6688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case TYPE_M1664: 6697fb35a2fd83f5deadefcb230669b07e1d5b98137Sean Callanan case TYPE_LEA: 670b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return translateRMMemory(mcInst, insn, Dis); 6718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 6728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 6738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 6748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateFPRegister - Translates a stack position on the FPU stack to its 6758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// LLVM form, and appends it to an MCInst. 6768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 6778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 6788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param stackPos - The stack position to translate. 67936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic void translateFPRegister(MCInst &mcInst, 68036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t stackPos) { 68136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines mcInst.addOperand(MCOperand::CreateReg(X86::ST0 + stackPos)); 68236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 68336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 68436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// translateMaskRegister - Translates a 3-bit mask register number to 68536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// LLVM form, and appends it to an MCInst. 68636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// 68736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// @param mcInst - The MCInst to append to. 68836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// @param maskRegNum - Number of mask register from 0 to 7. 68936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// @return - false on success; true otherwise. 69036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic bool translateMaskRegister(MCInst &mcInst, 69136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint8_t maskRegNum) { 69236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (maskRegNum >= 8) { 69336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines debug("Invalid mask register number"); 694a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 695a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 696a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 69736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines mcInst.addOperand(MCOperand::CreateReg(X86::K0 + maskRegNum)); 698a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 6998ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 7008ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateOperand - Translates an operand stored in an internal instruction 7028ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// to LLVM's format and appends it to an MCInst. 7038ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 7048ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to append to. 7058ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param operand - The operand, as stored in the descriptor table. 7068ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The internal instruction. 707a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - false on success; true otherwise. 7084d1dca92bd6d4aad7121e28c7ffc93c0a6a187d7Benjamin Kramerstatic bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand, 709b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, 710b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 7118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan switch (operand.encoding) { 7128ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan default: 713a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Unhandled operand encoding during translation"); 714a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 7158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_REG: 7168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan translateRegister(mcInst, insn.reg); 717a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 71836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ENCODING_WRITEMASK: 71936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return translateMaskRegister(mcInst, insn.writemask); 7208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RM: 721b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby return translateRM(mcInst, operand, insn, Dis); 7228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CB: 7238ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CW: 7248ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CD: 7258ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CP: 7268ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CO: 7278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_CT: 728a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Translation of code offsets isn't supported."); 729a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 7308ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_IB: 7318ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_IW: 7328ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_ID: 7338ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_IO: 7348ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_Iv: 7358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_Ia: 736be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan translateImmediate(mcInst, 737be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan insn.immediates[insn.numImmediatesTranslated++], 738be192dd1e987361ecf51ff385cbf541cb7f779beSean Callanan operand, 739b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn, 740b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby Dis); 741a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 74236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ENCODING_SI: 74336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return translateSrcIndex(mcInst, insn); 74436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ENCODING_DI: 74536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return translateDstIndex(mcInst, insn); 7468ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RB: 7478ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RW: 7488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RD: 7498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_RO: 7508ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_Rv: 7518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan translateRegister(mcInst, insn.opcodeRegister); 752a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 75336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines case ENCODING_FP: 75436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines translateFPRegister(mcInst, insn.modRM & 7); 75536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return false; 756a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan case ENCODING_VVVV: 757a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan translateRegister(mcInst, insn.vvvv); 758a21e2eae3def2fe39caed861dcb73c76c715569bSean Callanan return false; 7598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan case ENCODING_DUP: 7605a2c607153993fb7f7e04f9482520b64dffe5757Craig Topper return translateOperand(mcInst, insn.operands[operand.type - TYPE_DUP0], 761b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby insn, Dis); 7628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 7638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 7648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// translateInstruction - Translates an internal instruction and all its 7668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// operands to an MCInst. 7678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// 7688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param mcInst - The MCInst to populate with the instruction's data. 7698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// @param insn - The internal instruction. 770a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan/// @return - false on success; true otherwise. 771a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callananstatic bool translateInstruction(MCInst &mcInst, 772b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby InternalInstruction &insn, 773b80d571ea85db5d52fafed0523cf59e693502198Kevin Enderby const MCDisassembler *Dis) { 774a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan if (!insn.spec) { 775a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan debug("Instruction has no specification"); 776a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 777a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 7788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7798ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan mcInst.setOpcode(insn.instructionID); 78046d7de7a192f43eb568c26c88e2dc2b804c09614Kevin Enderby // If when reading the prefix bytes we determined the overlapping 0xf2 or 0xf3 78146d7de7a192f43eb568c26c88e2dc2b804c09614Kevin Enderby // prefix bytes should be disassembled as xrelease and xacquire then set the 78246d7de7a192f43eb568c26c88e2dc2b804c09614Kevin Enderby // opcode to those instead of the rep and repne opcodes. 78346d7de7a192f43eb568c26c88e2dc2b804c09614Kevin Enderby if (insn.xAcquireRelease) { 78446d7de7a192f43eb568c26c88e2dc2b804c09614Kevin Enderby if(mcInst.getOpcode() == X86::REP_PREFIX) 78546d7de7a192f43eb568c26c88e2dc2b804c09614Kevin Enderby mcInst.setOpcode(X86::XRELEASE_PREFIX); 78646d7de7a192f43eb568c26c88e2dc2b804c09614Kevin Enderby else if(mcInst.getOpcode() == X86::REPNE_PREFIX) 78746d7de7a192f43eb568c26c88e2dc2b804c09614Kevin Enderby mcInst.setOpcode(X86::XACQUIRE_PREFIX); 78846d7de7a192f43eb568c26c88e2dc2b804c09614Kevin Enderby } 7898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 7908ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan insn.numImmediatesTranslated = 0; 7918ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 792dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (const auto &Op : insn.operands) { 793dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Op.encoding != ENCODING_NONE) { 794dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (translateOperand(mcInst, Op, insn, Dis)) { 795a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return true; 796a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 797a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan } 7988ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 799a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan 800a144c3f34dd8adc093d9be6cbc3e6f39d47c75ddSean Callanan return false; 8018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} 8025f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar 80336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstatic MCDisassembler *createX86Disassembler(const Target &T, 804dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const MCSubtargetInfo &STI, 805dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines MCContext &Ctx) { 806dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::unique_ptr<const MCInstrInfo> MII(T.createMCInstrInfo()); 807dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return new X86Disassembler::X86GenericDisassembler(STI, Ctx, std::move(MII)); 8085f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar} 8095f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar 8105f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbarextern "C" void LLVMInitializeX86Disassembler() { 8115f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar // Register the disassembler. 8125f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar TargetRegistry::RegisterMCDisassembler(TheX86_32Target, 81336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines createX86Disassembler); 8145f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar TargetRegistry::RegisterMCDisassembler(TheX86_64Target, 81536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines createX86Disassembler); 8165f9b9efa1719d2b716581ccce977bed65865cc18Daniel Dunbar} 817