blob: 17dbd7f237f389a3fcdc1017b941e1b590e252fc [file] [log] [blame]
Daniel Dunbar5f9b9ef2009-11-25 06:53:08 +00001//===- X86Disassembler.cpp - Disassembler for x86 and x86_64 ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Sean Callanan8ed9f512009-12-19 02:59:52 +00009//
10// This file is part of the X86 Disassembler.
11// It contains code to translate the data produced by the decoder into
12// MCInsts.
13// Documentation for the disassembler can be found in X86Disassembler.h.
14//
15//===----------------------------------------------------------------------===//
16
17#include "X86Disassembler.h"
18#include "X86DisassemblerDecoder.h"
Daniel Dunbar5f9b9ef2009-11-25 06:53:08 +000019
20#include "llvm/MC/MCDisassembler.h"
Sean Callanan8ed9f512009-12-19 02:59:52 +000021#include "llvm/MC/MCDisassembler.h"
22#include "llvm/MC/MCInst.h"
Daniel Dunbar5f9b9ef2009-11-25 06:53:08 +000023#include "llvm/Target/TargetRegistry.h"
Sean Callanan8ed9f512009-12-19 02:59:52 +000024#include "llvm/Support/MemoryObject.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/raw_ostream.h"
Sean Callanan0122c902009-12-22 01:11:26 +000027
28#include "../X86GenRegisterNames.inc"
29
Daniel Dunbar5f9b9ef2009-11-25 06:53:08 +000030using namespace llvm;
Sean Callanan8ed9f512009-12-19 02:59:52 +000031using namespace llvm::X86Disassembler;
32
33namespace llvm {
34
35// Fill-ins to make the compiler happy. These constants are never actually
36// assigned; they are just filler to make an automatically-generated switch
37// statement work.
38namespace X86 {
39 enum {
40 BX_SI = 500,
41 BX_DI = 501,
42 BP_SI = 502,
43 BP_DI = 503,
44 sib = 504,
45 sib64 = 505
46 };
47}
48
Sean Callanan0122c902009-12-22 01:11:26 +000049extern Target TheX86_32Target, TheX86_64Target;
50
Sean Callanan8ed9f512009-12-19 02:59:52 +000051}
52
53static void translateInstruction(MCInst &target,
54 InternalInstruction &source);
55
56X86GenericDisassembler::X86GenericDisassembler(DisassemblerMode mode) :
57 MCDisassembler(),
58 fMode(mode) {
59}
60
61X86GenericDisassembler::~X86GenericDisassembler() {
62}
63
64/// regionReader - a callback function that wraps the readByte method from
65/// MemoryObject.
66///
67/// @param arg - The generic callback parameter. In this case, this should
68/// be a pointer to a MemoryObject.
69/// @param byte - A pointer to the byte to be read.
70/// @param address - The address to be read.
71static int regionReader(void* arg, uint8_t* byte, uint64_t address) {
72 MemoryObject* region = static_cast<MemoryObject*>(arg);
73 return region->readByte(address, byte);
74}
75
76/// logger - a callback function that wraps the operator<< method from
77/// raw_ostream.
78///
79/// @param arg - The generic callback parameter. This should be a pointe
80/// to a raw_ostream.
81/// @param log - A string to be logged. logger() adds a newline.
82static void logger(void* arg, const char* log) {
83 if (!arg)
84 return;
85
86 raw_ostream &vStream = *(static_cast<raw_ostream*>(arg));
87 vStream << log << "\n";
88}
89
90//
91// Public interface for the disassembler
92//
93
94bool X86GenericDisassembler::getInstruction(MCInst &instr,
95 uint64_t &size,
96 const MemoryObject &region,
97 uint64_t address,
98 raw_ostream &vStream) const {
99 InternalInstruction internalInstr;
100
101 int ret = decodeInstruction(&internalInstr,
102 regionReader,
103 (void*)&region,
104 logger,
105 (void*)&vStream,
106 address,
107 fMode);
108
109 if(ret) {
110 size = internalInstr.readerCursor - address;
111 return false;
112 }
113 else {
114 size = internalInstr.length;
115 translateInstruction(instr, internalInstr);
116 return true;
117 }
118}
119
120//
121// Private code that translates from struct InternalInstructions to MCInsts.
122//
123
124/// translateRegister - Translates an internal register to the appropriate LLVM
125/// register, and appends it as an operand to an MCInst.
126///
127/// @param mcInst - The MCInst to append to.
128/// @param reg - The Reg to append.
129static void translateRegister(MCInst &mcInst, Reg reg) {
130#define ENTRY(x) X86::x,
131 uint8_t llvmRegnums[] = {
132 ALL_REGS
133 0
134 };
135#undef ENTRY
136
137 uint8_t llvmRegnum = llvmRegnums[reg];
138 mcInst.addOperand(MCOperand::CreateReg(llvmRegnum));
139}
140
141/// translateImmediate - Appends an immediate operand to an MCInst.
142///
143/// @param mcInst - The MCInst to append to.
144/// @param immediate - The immediate value to append.
145static void translateImmediate(MCInst &mcInst, uint64_t immediate) {
146 mcInst.addOperand(MCOperand::CreateImm(immediate));
147}
148
149/// translateRMRegister - Translates a register stored in the R/M field of the
150/// ModR/M byte to its LLVM equivalent and appends it to an MCInst.
151/// @param mcInst - The MCInst to append to.
152/// @param insn - The internal instruction to extract the R/M field
153/// from.
154static void translateRMRegister(MCInst &mcInst,
155 InternalInstruction &insn) {
156 assert(insn.eaBase != EA_BASE_sib && insn.eaBase != EA_BASE_sib64 &&
157 "A R/M register operand may not have a SIB byte");
158
159 switch (insn.eaBase) {
160 case EA_BASE_NONE:
161 llvm_unreachable("EA_BASE_NONE for ModR/M base");
162 break;
163#define ENTRY(x) case EA_BASE_##x:
164 ALL_EA_BASES
165#undef ENTRY
166 llvm_unreachable("A R/M register operand may not have a base; "
167 "the operand must be a register.");
168 break;
169#define ENTRY(x) \
170 case EA_REG_##x: \
171 mcInst.addOperand(MCOperand::CreateReg(X86::x)); break;
172 ALL_REGS
173#undef ENTRY
174 default:
175 llvm_unreachable("Unexpected EA base register");
176 }
177}
178
179/// translateRMMemory - Translates a memory operand stored in the Mod and R/M
180/// fields of an internal instruction (and possibly its SIB byte) to a memory
181/// operand in LLVM's format, and appends it to an MCInst.
182///
183/// @param mcInst - The MCInst to append to.
184/// @param insn - The instruction to extract Mod, R/M, and SIB fields
185/// from.
186static void translateRMMemory(MCInst &mcInst,
187 InternalInstruction &insn) {
188 // Addresses in an MCInst are represented as five operands:
189 // 1. basereg (register) The R/M base, or (if there is a SIB) the
190 // SIB base
191 // 2. scaleamount (immediate) 1, or (if there is a SIB) the specified
192 // scale amount
193 // 3. indexreg (register) x86_registerNONE, or (if there is a SIB)
194 // the index (which is multiplied by the
195 // scale amount)
196 // 4. displacement (immediate) 0, or the displacement if there is one
197 // 5. segmentreg (register) x86_registerNONE for now, but could be set
198 // if we have segment overrides
199
200 MCOperand baseReg;
201 MCOperand scaleAmount;
202 MCOperand indexReg;
203 MCOperand displacement;
204 MCOperand segmentReg;
205
206 if (insn.eaBase == EA_BASE_sib || insn.eaBase == EA_BASE_sib64) {
207 if (insn.sibBase != SIB_BASE_NONE) {
208 switch (insn.sibBase) {
209 default:
210 llvm_unreachable("Unexpected sibBase");
211#define ENTRY(x) \
212 case SIB_BASE_##x: \
213 baseReg = MCOperand::CreateReg(X86::x); break;
214 ALL_SIB_BASES
215#undef ENTRY
216 }
217 } else {
218 baseReg = MCOperand::CreateReg(0);
219 }
220
221 if (insn.sibIndex != SIB_INDEX_NONE) {
222 switch (insn.sibIndex) {
223 default:
224 llvm_unreachable("Unexpected sibIndex");
225#define ENTRY(x) \
226 case SIB_INDEX_##x: \
227 indexReg = MCOperand::CreateReg(X86::x); break;
228 EA_BASES_32BIT
229 EA_BASES_64BIT
230#undef ENTRY
231 }
232 } else {
233 indexReg = MCOperand::CreateReg(0);
234 }
235
236 scaleAmount = MCOperand::CreateImm(insn.sibScale);
237 } else {
238 switch (insn.eaBase) {
239 case EA_BASE_NONE:
240 assert(insn.eaDisplacement != EA_DISP_NONE &&
241 "EA_BASE_NONE and EA_DISP_NONE for ModR/M base");
242
243 if (insn.mode == MODE_64BIT)
244 baseReg = MCOperand::CreateReg(X86::RIP); // Section 2.2.1.6
245 else
246 baseReg = MCOperand::CreateReg(0);
247
248 indexReg = MCOperand::CreateReg(0);
249 break;
250 case EA_BASE_BX_SI:
251 baseReg = MCOperand::CreateReg(X86::BX);
252 indexReg = MCOperand::CreateReg(X86::SI);
253 break;
254 case EA_BASE_BX_DI:
255 baseReg = MCOperand::CreateReg(X86::BX);
256 indexReg = MCOperand::CreateReg(X86::DI);
257 break;
258 case EA_BASE_BP_SI:
259 baseReg = MCOperand::CreateReg(X86::BP);
260 indexReg = MCOperand::CreateReg(X86::SI);
261 break;
262 case EA_BASE_BP_DI:
263 baseReg = MCOperand::CreateReg(X86::BP);
264 indexReg = MCOperand::CreateReg(X86::DI);
265 break;
266 default:
267 indexReg = MCOperand::CreateReg(0);
268 switch (insn.eaBase) {
269 default:
270 llvm_unreachable("Unexpected eaBase");
271 break;
272 // Here, we will use the fill-ins defined above. However,
273 // BX_SI, BX_DI, BP_SI, and BP_DI are all handled above and
274 // sib and sib64 were handled in the top-level if, so they're only
275 // placeholders to keep the compiler happy.
276#define ENTRY(x) \
277 case EA_BASE_##x: \
278 baseReg = MCOperand::CreateReg(X86::x); break;
279 ALL_EA_BASES
280#undef ENTRY
281#define ENTRY(x) case EA_REG_##x:
282 ALL_REGS
283#undef ENTRY
284 llvm_unreachable("A R/M memory operand may not be a register; "
285 "the base field must be a base.");
286 break;
287 }
288 }
289 }
290
291 displacement = MCOperand::CreateImm(insn.displacement);
292
293 static const uint8_t segmentRegnums[SEG_OVERRIDE_max] = {
294 0, // SEG_OVERRIDE_NONE
295 X86::CS,
296 X86::SS,
297 X86::DS,
298 X86::ES,
299 X86::FS,
300 X86::GS
301 };
302
303 segmentReg = MCOperand::CreateReg(segmentRegnums[insn.segmentOverride]);
304
305 mcInst.addOperand(baseReg);
306 mcInst.addOperand(scaleAmount);
307 mcInst.addOperand(indexReg);
308 mcInst.addOperand(displacement);
309 mcInst.addOperand(segmentReg);
310}
311
312/// translateRM - Translates an operand stored in the R/M (and possibly SIB)
313/// byte of an instruction to LLVM form, and appends it to an MCInst.
314///
315/// @param mcInst - The MCInst to append to.
316/// @param operand - The operand, as stored in the descriptor table.
317/// @param insn - The instruction to extract Mod, R/M, and SIB fields
318/// from.
319static void translateRM(MCInst &mcInst,
320 OperandSpecifier &operand,
321 InternalInstruction &insn) {
322 switch (operand.type) {
323 default:
324 llvm_unreachable("Unexpected type for a R/M operand");
325 case TYPE_R8:
326 case TYPE_R16:
327 case TYPE_R32:
328 case TYPE_R64:
329 case TYPE_Rv:
330 case TYPE_MM:
331 case TYPE_MM32:
332 case TYPE_MM64:
333 case TYPE_XMM:
334 case TYPE_XMM32:
335 case TYPE_XMM64:
336 case TYPE_XMM128:
337 case TYPE_DEBUGREG:
338 case TYPE_CR32:
339 case TYPE_CR64:
340 translateRMRegister(mcInst, insn);
341 break;
342 case TYPE_M:
343 case TYPE_M8:
344 case TYPE_M16:
345 case TYPE_M32:
346 case TYPE_M64:
347 case TYPE_M128:
348 case TYPE_M512:
349 case TYPE_Mv:
350 case TYPE_M32FP:
351 case TYPE_M64FP:
352 case TYPE_M80FP:
353 case TYPE_M16INT:
354 case TYPE_M32INT:
355 case TYPE_M64INT:
356 case TYPE_M1616:
357 case TYPE_M1632:
358 case TYPE_M1664:
359 translateRMMemory(mcInst, insn);
360 break;
361 }
362}
363
364/// translateFPRegister - Translates a stack position on the FPU stack to its
365/// LLVM form, and appends it to an MCInst.
366///
367/// @param mcInst - The MCInst to append to.
368/// @param stackPos - The stack position to translate.
369static void translateFPRegister(MCInst &mcInst,
370 uint8_t stackPos) {
371 assert(stackPos < 8 && "Invalid FP stack position");
372
373 mcInst.addOperand(MCOperand::CreateReg(X86::ST0 + stackPos));
374}
375
376/// translateOperand - Translates an operand stored in an internal instruction
377/// to LLVM's format and appends it to an MCInst.
378///
379/// @param mcInst - The MCInst to append to.
380/// @param operand - The operand, as stored in the descriptor table.
381/// @param insn - The internal instruction.
382static void translateOperand(MCInst &mcInst,
383 OperandSpecifier &operand,
384 InternalInstruction &insn) {
385 switch (operand.encoding) {
386 default:
387 llvm_unreachable("Unhandled operand encoding during translation");
388 case ENCODING_REG:
389 translateRegister(mcInst, insn.reg);
390 break;
391 case ENCODING_RM:
392 translateRM(mcInst, operand, insn);
393 break;
394 case ENCODING_CB:
395 case ENCODING_CW:
396 case ENCODING_CD:
397 case ENCODING_CP:
398 case ENCODING_CO:
399 case ENCODING_CT:
400 llvm_unreachable("Translation of code offsets isn't supported.");
401 case ENCODING_IB:
402 case ENCODING_IW:
403 case ENCODING_ID:
404 case ENCODING_IO:
405 case ENCODING_Iv:
406 case ENCODING_Ia:
407 translateImmediate(mcInst,
408 insn.immediates[insn.numImmediatesTranslated++]);
409 break;
410 case ENCODING_RB:
411 case ENCODING_RW:
412 case ENCODING_RD:
413 case ENCODING_RO:
414 translateRegister(mcInst, insn.opcodeRegister);
415 break;
416 case ENCODING_I:
417 translateFPRegister(mcInst, insn.opcodeModifier);
418 break;
419 case ENCODING_Rv:
420 translateRegister(mcInst, insn.opcodeRegister);
421 break;
422 case ENCODING_DUP:
423 translateOperand(mcInst,
424 insn.spec->operands[operand.type - TYPE_DUP0],
425 insn);
426 break;
427 }
428}
429
430/// translateInstruction - Translates an internal instruction and all its
431/// operands to an MCInst.
432///
433/// @param mcInst - The MCInst to populate with the instruction's data.
434/// @param insn - The internal instruction.
435static void translateInstruction(MCInst &mcInst,
436 InternalInstruction &insn) {
437 assert(insn.spec);
438
439 mcInst.setOpcode(insn.instructionID);
440
441 int index;
442
443 insn.numImmediatesTranslated = 0;
444
445 for (index = 0; index < X86_MAX_OPERANDS; ++index) {
446 if (insn.spec->operands[index].encoding != ENCODING_NONE)
447 translateOperand(mcInst, insn.spec->operands[index], insn);
448 }
449}
Daniel Dunbar5f9b9ef2009-11-25 06:53:08 +0000450
451static const MCDisassembler *createX86_32Disassembler(const Target &T) {
Sean Callanan8ed9f512009-12-19 02:59:52 +0000452 return new X86Disassembler::X86_32Disassembler;
Daniel Dunbar5f9b9ef2009-11-25 06:53:08 +0000453}
454
455static const MCDisassembler *createX86_64Disassembler(const Target &T) {
Sean Callanan8ed9f512009-12-19 02:59:52 +0000456 return new X86Disassembler::X86_64Disassembler;
Daniel Dunbar5f9b9ef2009-11-25 06:53:08 +0000457}
458
459extern "C" void LLVMInitializeX86Disassembler() {
460 // Register the disassembler.
461 TargetRegistry::RegisterMCDisassembler(TheX86_32Target,
462 createX86_32Disassembler);
463 TargetRegistry::RegisterMCDisassembler(TheX86_64Target,
464 createX86_64Disassembler);
465}