blob: 2f76d5f22a12af7d856d6c32e2745c63acbe0b5a [file] [log] [blame]
Akira Hatanaka71928e62012-04-17 18:03:21 +00001//===- MipsDisassembler.cpp - Disassembler for Mips -------------*- 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//===----------------------------------------------------------------------===//
9//
10// This file is part of the Mips Disassembler.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Mips.h"
15#include "MipsSubtarget.h"
16#include "llvm/MC/EDInstInfo.h"
17#include "llvm/MC/MCDisassembler.h"
18#include "llvm/Support/MemoryObject.h"
19#include "llvm/Support/TargetRegistry.h"
20#include "llvm/MC/MCSubtargetInfo.h"
21#include "llvm/MC/MCInst.h"
22#include "llvm/MC/MCRegisterInfo.h"
23#include "llvm/Support/MathExtras.h"
24
25
26#include "MipsGenEDInfo.inc"
27
28using namespace llvm;
29
30typedef MCDisassembler::DecodeStatus DecodeStatus;
31
Benjamin Kramercb3e98c2012-05-01 14:34:24 +000032namespace {
33
Akira Hatanaka71928e62012-04-17 18:03:21 +000034/// MipsDisassembler - a disasembler class for Mips32.
35class MipsDisassembler : public MCDisassembler {
36public:
37 /// Constructor - Initializes the disassembler.
38 ///
39 MipsDisassembler(const MCSubtargetInfo &STI, bool bigEndian) :
40 MCDisassembler(STI), isBigEndian(bigEndian) {
41 }
42
43 ~MipsDisassembler() {
44 }
45
46 /// getInstruction - See MCDisassembler.
47 DecodeStatus getInstruction(MCInst &instr,
48 uint64_t &size,
49 const MemoryObject &region,
50 uint64_t address,
51 raw_ostream &vStream,
52 raw_ostream &cStream) const;
53
54 /// getEDInfo - See MCDisassembler.
55 const EDInstInfo *getEDInfo() const;
56
57private:
58 bool isBigEndian;
59};
60
61
62/// Mips64Disassembler - a disasembler class for Mips64.
63class Mips64Disassembler : public MCDisassembler {
64public:
65 /// Constructor - Initializes the disassembler.
66 ///
67 Mips64Disassembler(const MCSubtargetInfo &STI, bool bigEndian) :
68 MCDisassembler(STI), isBigEndian(bigEndian) {
69 }
70
71 ~Mips64Disassembler() {
72 }
73
74 /// getInstruction - See MCDisassembler.
75 DecodeStatus getInstruction(MCInst &instr,
76 uint64_t &size,
77 const MemoryObject &region,
78 uint64_t address,
79 raw_ostream &vStream,
80 raw_ostream &cStream) const;
81
82 /// getEDInfo - See MCDisassembler.
83 const EDInstInfo *getEDInfo() const;
84
85private:
86 bool isBigEndian;
87};
88
Benjamin Kramercb3e98c2012-05-01 14:34:24 +000089} // end anonymous namespace
90
Akira Hatanaka71928e62012-04-17 18:03:21 +000091const EDInstInfo *MipsDisassembler::getEDInfo() const {
92 return instInfoMips;
93}
94
95const EDInstInfo *Mips64Disassembler::getEDInfo() const {
96 return instInfoMips;
97}
98
99// Decoder tables for Mips register
100static const unsigned CPURegsTable[] = {
101 Mips::ZERO, Mips::AT, Mips::V0, Mips::V1,
102 Mips::A0, Mips::A1, Mips::A2, Mips::A3,
103 Mips::T0, Mips::T1, Mips::T2, Mips::T3,
104 Mips::T4, Mips::T5, Mips::T6, Mips::T7,
105 Mips::S0, Mips::S1, Mips::S2, Mips::S3,
106 Mips::S4, Mips::S5, Mips::S6, Mips::S7,
107 Mips::T8, Mips::T9, Mips::K0, Mips::K1,
108 Mips::GP, Mips::SP, Mips::FP, Mips::RA
109};
110
111static const unsigned FGR32RegsTable[] = {
112 Mips::F0, Mips::F1, Mips::F2, Mips::F3,
113 Mips::F4, Mips::F5, Mips::F6, Mips::F7,
114 Mips::F8, Mips::F9, Mips::F10, Mips::F11,
115 Mips::F12, Mips::F13, Mips::F14, Mips::F15,
116 Mips::F16, Mips::F17, Mips::F18, Mips::F18,
117 Mips::F20, Mips::F21, Mips::F22, Mips::F23,
118 Mips::F24, Mips::F25, Mips::F26, Mips::F27,
119 Mips::F28, Mips::F29, Mips::F30, Mips::F31
120};
121
122static const unsigned CPU64RegsTable[] = {
123 Mips::ZERO_64, Mips::AT_64, Mips::V0_64, Mips::V1_64,
124 Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64,
125 Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64,
126 Mips::T4_64, Mips::T5_64, Mips::T6_64, Mips::T7_64,
127 Mips::S0_64, Mips::S1_64, Mips::S2_64, Mips::S3_64,
128 Mips::S4_64, Mips::S5_64, Mips::S6_64, Mips::S7_64,
129 Mips::T8_64, Mips::T9_64, Mips::K0_64, Mips::K1_64,
130 Mips::GP_64, Mips::SP_64, Mips::FP_64, Mips::RA_64
131};
132
133static const unsigned FGR64RegsTable[] = {
134 Mips::D0_64, Mips::D1_64, Mips::D2_64, Mips::D3_64,
135 Mips::D4_64, Mips::D5_64, Mips::D6_64, Mips::D7_64,
136 Mips::D8_64, Mips::D9_64, Mips::D10_64, Mips::D11_64,
137 Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64,
138 Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64,
139 Mips::D20_64, Mips::D21_64, Mips::D22_64, Mips::D23_64,
140 Mips::D24_64, Mips::D25_64, Mips::D26_64, Mips::D27_64,
141 Mips::D28_64, Mips::D29_64, Mips::D30_64, Mips::D31_64
142};
143
144static const unsigned AFGR64RegsTable[] = {
145 Mips::D0, Mips::D1, Mips::D2, Mips::D3,
146 Mips::D4, Mips::D5, Mips::D6, Mips::D7,
147 Mips::D8, Mips::D9, Mips::D10, Mips::D11,
148 Mips::D12, Mips::D13, Mips::D14, Mips::D15
149};
150
151// Forward declare these because the autogenerated code will reference them.
152// Definitions are further down.
153static DecodeStatus DecodeCPU64RegsRegisterClass(MCInst &Inst,
154 unsigned RegNo,
155 uint64_t Address,
156 const void *Decoder);
157
158static DecodeStatus DecodeCPURegsRegisterClass(MCInst &Inst,
159 unsigned RegNo,
160 uint64_t Address,
161 const void *Decoder);
162
163static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst,
164 unsigned RegNo,
165 uint64_t Address,
166 const void *Decoder);
167
168static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst,
169 unsigned RegNo,
170 uint64_t Address,
171 const void *Decoder);
172
173static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst,
174 unsigned RegNo,
175 uint64_t Address,
176 const void *Decoder);
177
178static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst,
179 unsigned Insn,
180 uint64_t Address,
181 const void *Decoder);
182
183static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst,
184 unsigned RegNo,
185 uint64_t Address,
186 const void *Decoder);
187
188static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst,
189 unsigned Insn,
190 uint64_t Address,
191 const void *Decoder);
192
193static DecodeStatus DecodeBranchTarget(MCInst &Inst,
194 unsigned Offset,
195 uint64_t Address,
196 const void *Decoder);
197
198static DecodeStatus DecodeBC1(MCInst &Inst,
199 unsigned Insn,
200 uint64_t Address,
201 const void *Decoder);
202
203
204static DecodeStatus DecodeJumpTarget(MCInst &Inst,
205 unsigned Insn,
206 uint64_t Address,
207 const void *Decoder);
208
209static DecodeStatus DecodeMem(MCInst &Inst,
210 unsigned Insn,
211 uint64_t Address,
212 const void *Decoder);
213
214static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn,
215 uint64_t Address,
216 const void *Decoder);
217
218static DecodeStatus DecodeSimm16(MCInst &Inst,
219 unsigned Insn,
220 uint64_t Address,
221 const void *Decoder);
222
223static DecodeStatus DecodeCondCode(MCInst &Inst,
224 unsigned Insn,
225 uint64_t Address,
226 const void *Decoder);
227
228static DecodeStatus DecodeInsSize(MCInst &Inst,
229 unsigned Insn,
230 uint64_t Address,
231 const void *Decoder);
232
233static DecodeStatus DecodeExtSize(MCInst &Inst,
234 unsigned Insn,
235 uint64_t Address,
236 const void *Decoder);
237
238namespace llvm {
239extern Target TheMipselTarget, TheMipsTarget, TheMips64Target,
240 TheMips64elTarget;
241}
242
243static MCDisassembler *createMipsDisassembler(
244 const Target &T,
245 const MCSubtargetInfo &STI) {
246 return new MipsDisassembler(STI,true);
247}
248
249static MCDisassembler *createMipselDisassembler(
250 const Target &T,
251 const MCSubtargetInfo &STI) {
252 return new MipsDisassembler(STI,false);
253}
254
255static MCDisassembler *createMips64Disassembler(
256 const Target &T,
257 const MCSubtargetInfo &STI) {
258 return new Mips64Disassembler(STI,true);
259}
260
261static MCDisassembler *createMips64elDisassembler(
262 const Target &T,
263 const MCSubtargetInfo &STI) {
264 return new Mips64Disassembler(STI, false);
265}
266
267extern "C" void LLVMInitializeMipsDisassembler() {
268 // Register the disassembler.
269 TargetRegistry::RegisterMCDisassembler(TheMipsTarget,
270 createMipsDisassembler);
271 TargetRegistry::RegisterMCDisassembler(TheMipselTarget,
272 createMipselDisassembler);
273 TargetRegistry::RegisterMCDisassembler(TheMips64Target,
274 createMips64Disassembler);
275 TargetRegistry::RegisterMCDisassembler(TheMips64elTarget,
276 createMips64elDisassembler);
277}
278
279
280#include "MipsGenDisassemblerTables.inc"
281
282 /// readInstruction - read four bytes from the MemoryObject
283 /// and return 32 bit word sorted according to the given endianess
284static DecodeStatus readInstruction32(const MemoryObject &region,
285 uint64_t address,
286 uint64_t &size,
287 uint32_t &insn,
288 bool isBigEndian) {
289 uint8_t Bytes[4];
290
291 // We want to read exactly 4 Bytes of data.
292 if (region.readBytes(address, 4, (uint8_t*)Bytes, NULL) == -1) {
293 size = 0;
294 return MCDisassembler::Fail;
295 }
296
297 if (isBigEndian) {
298 // Encoded as a big-endian 32-bit word in the stream.
299 insn = (Bytes[3] << 0) |
300 (Bytes[2] << 8) |
301 (Bytes[1] << 16) |
302 (Bytes[0] << 24);
303 }
304 else {
305 // Encoded as a small-endian 32-bit word in the stream.
306 insn = (Bytes[0] << 0) |
307 (Bytes[1] << 8) |
308 (Bytes[2] << 16) |
309 (Bytes[3] << 24);
310 }
311
312 return MCDisassembler::Success;
313}
314
315DecodeStatus
316MipsDisassembler::getInstruction(MCInst &instr,
317 uint64_t &Size,
318 const MemoryObject &Region,
319 uint64_t Address,
320 raw_ostream &vStream,
321 raw_ostream &cStream) const {
322 uint32_t Insn;
323
324 DecodeStatus Result = readInstruction32(Region, Address, Size,
325 Insn, isBigEndian);
326 if (Result == MCDisassembler::Fail)
327 return MCDisassembler::Fail;
328
329 // Calling the auto-generated decoder function.
330 Result = decodeMipsInstruction32(instr, Insn, Address, this, STI);
331 if (Result != MCDisassembler::Fail) {
332 Size = 4;
333 return Result;
334 }
335
336 return MCDisassembler::Fail;
337}
338
339DecodeStatus
340Mips64Disassembler::getInstruction(MCInst &instr,
341 uint64_t &Size,
342 const MemoryObject &Region,
343 uint64_t Address,
344 raw_ostream &vStream,
345 raw_ostream &cStream) const {
346 uint32_t Insn;
347
348 DecodeStatus Result = readInstruction32(Region, Address, Size,
349 Insn, isBigEndian);
350 if (Result == MCDisassembler::Fail)
351 return MCDisassembler::Fail;
352
353 // Calling the auto-generated decoder function.
354 Result = decodeMips64Instruction32(instr, Insn, Address, this, STI);
355 if (Result != MCDisassembler::Fail) {
356 Size = 4;
357 return Result;
358 }
359 // If we fail to decode in Mips64 decoder space we can try in Mips32
360 Result = decodeMipsInstruction32(instr, Insn, Address, this, STI);
361 if (Result != MCDisassembler::Fail) {
362 Size = 4;
363 return Result;
364 }
365
366 return MCDisassembler::Fail;
367}
368
369static DecodeStatus DecodeCPU64RegsRegisterClass(MCInst &Inst,
370 unsigned RegNo,
371 uint64_t Address,
372 const void *Decoder) {
373
374 if (RegNo > 31)
375 return MCDisassembler::Fail;
376
377 Inst.addOperand(MCOperand::CreateReg(CPU64RegsTable[RegNo]));
378 return MCDisassembler::Success;
379}
380
381static DecodeStatus DecodeCPURegsRegisterClass(MCInst &Inst,
382 unsigned RegNo,
383 uint64_t Address,
384 const void *Decoder) {
385 if (RegNo > 31)
386 return MCDisassembler::Fail;
387
388 Inst.addOperand(MCOperand::CreateReg(CPURegsTable[RegNo]));
389 return MCDisassembler::Success;
390}
391
392static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst,
393 unsigned RegNo,
394 uint64_t Address,
395 const void *Decoder) {
396 if (RegNo > 31)
397 return MCDisassembler::Fail;
398
399 Inst.addOperand(MCOperand::CreateReg(FGR64RegsTable[RegNo]));
400 return MCDisassembler::Success;
401}
402
403static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst,
404 unsigned RegNo,
405 uint64_t Address,
406 const void *Decoder) {
407 if (RegNo > 31)
408 return MCDisassembler::Fail;
409
410 Inst.addOperand(MCOperand::CreateReg(FGR32RegsTable[RegNo]));
411 return MCDisassembler::Success;
412}
413
414static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst,
415 unsigned RegNo,
416 uint64_t Address,
417 const void *Decoder) {
418 Inst.addOperand(MCOperand::CreateReg(RegNo));
419 return MCDisassembler::Success;
420}
421
422static DecodeStatus DecodeMem(MCInst &Inst,
423 unsigned Insn,
424 uint64_t Address,
425 const void *Decoder) {
426 int Offset = SignExtend32<16>(Insn & 0xffff);
427 int Reg = (int)fieldFromInstruction32(Insn, 16, 5);
428 int Base = (int)fieldFromInstruction32(Insn, 21, 5);
429
430 if(Inst.getOpcode() == Mips::SC){
431 Inst.addOperand(MCOperand::CreateReg(CPURegsTable[Reg]));
432 }
433
434 Inst.addOperand(MCOperand::CreateReg(CPURegsTable[Reg]));
435 Inst.addOperand(MCOperand::CreateReg(CPURegsTable[Base]));
436 Inst.addOperand(MCOperand::CreateImm(Offset));
437
438 return MCDisassembler::Success;
439}
440
441static DecodeStatus DecodeFMem(MCInst &Inst,
442 unsigned Insn,
443 uint64_t Address,
444 const void *Decoder) {
445 int Offset = SignExtend32<16>(Insn & 0xffff);
446 int Reg = (int)fieldFromInstruction32(Insn, 16, 5);
447 int Base = (int)fieldFromInstruction32(Insn, 21, 5);
448
449 Inst.addOperand(MCOperand::CreateReg(FGR64RegsTable[Reg]));
450 Inst.addOperand(MCOperand::CreateReg(CPURegsTable[Base]));
451 Inst.addOperand(MCOperand::CreateImm(Offset));
452
453 return MCDisassembler::Success;
454}
455
456
457static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst,
458 unsigned RegNo,
459 uint64_t Address,
460 const void *Decoder) {
461 // Currently only hardware register 29 is supported.
462 if (RegNo != 29)
463 return MCDisassembler::Fail;
464 Inst.addOperand(MCOperand::CreateReg(Mips::HWR29));
465 return MCDisassembler::Success;
466}
467
468static DecodeStatus DecodeCondCode(MCInst &Inst,
469 unsigned Insn,
470 uint64_t Address,
471 const void *Decoder) {
472 int CondCode = Insn & 0xf;
473 Inst.addOperand(MCOperand::CreateImm(CondCode));
474 return MCDisassembler::Success;
475}
476
477static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst,
478 unsigned RegNo,
479 uint64_t Address,
480 const void *Decoder) {
481 if (RegNo > 31)
482 return MCDisassembler::Fail;
483
484 Inst.addOperand(MCOperand::CreateReg(AFGR64RegsTable[RegNo]));
485 return MCDisassembler::Success;
486}
487
488static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst,
489 unsigned RegNo,
490 uint64_t Address,
491 const void *Decoder) {
492 //Currently only hardware register 29 is supported
493 if (RegNo != 29)
494 return MCDisassembler::Fail;
495 Inst.addOperand(MCOperand::CreateReg(Mips::HWR29));
496 return MCDisassembler::Success;
497}
498
499static DecodeStatus DecodeBranchTarget(MCInst &Inst,
500 unsigned Offset,
501 uint64_t Address,
502 const void *Decoder) {
503 unsigned BranchOffset = Offset & 0xffff;
504 BranchOffset = SignExtend32<18>(BranchOffset << 2) + 4;
505 Inst.addOperand(MCOperand::CreateImm(BranchOffset));
506 return MCDisassembler::Success;
507}
508
509static DecodeStatus DecodeBC1(MCInst &Inst,
510 unsigned Insn,
511 uint64_t Address,
512 const void *Decoder) {
513 unsigned BranchOffset = Insn & 0xffff;
514 BranchOffset = SignExtend32<18>(BranchOffset << 2) + 4;
515 Inst.addOperand(MCOperand::CreateImm(BranchOffset));
516 return MCDisassembler::Success;
517}
518
519static DecodeStatus DecodeJumpTarget(MCInst &Inst,
520 unsigned Insn,
521 uint64_t Address,
522 const void *Decoder) {
523
524 unsigned JumpOffset = fieldFromInstruction32(Insn, 0, 26) << 2;
525 Inst.addOperand(MCOperand::CreateImm(JumpOffset));
526 return MCDisassembler::Success;
527}
528
529
530static DecodeStatus DecodeSimm16(MCInst &Inst,
531 unsigned Insn,
532 uint64_t Address,
533 const void *Decoder) {
534 Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Insn)));
535 return MCDisassembler::Success;
536}
537
538static DecodeStatus DecodeInsSize(MCInst &Inst,
539 unsigned Insn,
540 uint64_t Address,
541 const void *Decoder) {
542 // First we need to grab the pos(lsb) from MCInst.
543 int Pos = Inst.getOperand(2).getImm();
544 int Size = (int) Insn - Pos + 1;
545 Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Size)));
546 return MCDisassembler::Success;
547}
548
549static DecodeStatus DecodeExtSize(MCInst &Inst,
550 unsigned Insn,
551 uint64_t Address,
552 const void *Decoder) {
553 int Size = (int) Insn + 1;
554 Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Size)));
555 return MCDisassembler::Success;
556}