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