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