1 //===- MipsDisassembler.cpp - Disassembler for Mips -------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is part of the Mips Disassembler.
12 //===----------------------------------------------------------------------===//
15 #include "MipsRegisterInfo.h"
16 #include "MipsSubtarget.h"
17 #include "llvm/MC/MCDisassembler.h"
18 #include "llvm/MC/MCFixedLenDisassembler.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCSubtargetInfo.h"
21 #include "llvm/Support/MathExtras.h"
22 #include "llvm/Support/MemoryObject.h"
23 #include "llvm/Support/TargetRegistry.h"
27 typedef MCDisassembler::DecodeStatus DecodeStatus;
31 /// MipsDisassemblerBase - a disasembler class for Mips.
32 class MipsDisassemblerBase : public MCDisassembler {
34 /// Constructor - Initializes the disassembler.
36 MipsDisassemblerBase(const MCSubtargetInfo &STI, const MCRegisterInfo *Info,
38 MCDisassembler(STI), RegInfo(Info), isBigEndian(bigEndian) {}
40 virtual ~MipsDisassemblerBase() {}
42 const MCRegisterInfo *getRegInfo() const { return RegInfo; }
45 const MCRegisterInfo *RegInfo;
50 /// MipsDisassembler - a disasembler class for Mips32.
51 class MipsDisassembler : public MipsDisassemblerBase {
53 /// Constructor - Initializes the disassembler.
55 MipsDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info,
57 MipsDisassemblerBase(STI, Info, bigEndian) {}
59 /// getInstruction - See MCDisassembler.
60 virtual DecodeStatus getInstruction(MCInst &instr,
62 const MemoryObject ®ion,
65 raw_ostream &cStream) const;
69 /// Mips64Disassembler - a disasembler class for Mips64.
70 class Mips64Disassembler : public MipsDisassemblerBase {
72 /// Constructor - Initializes the disassembler.
74 Mips64Disassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info,
76 MipsDisassemblerBase(STI, Info, bigEndian) {}
78 /// getInstruction - See MCDisassembler.
79 virtual DecodeStatus getInstruction(MCInst &instr,
81 const MemoryObject ®ion,
84 raw_ostream &cStream) const;
87 } // end anonymous namespace
89 // Forward declare these because the autogenerated code will reference them.
90 // Definitions are further down.
91 static DecodeStatus DecodeCPU64RegsRegisterClass(MCInst &Inst,
96 static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst,
101 static DecodeStatus DecodeCPURegsRegisterClass(MCInst &Inst,
104 const void *Decoder);
106 static DecodeStatus DecodeDSPRegsRegisterClass(MCInst &Inst,
109 const void *Decoder);
111 static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst,
114 const void *Decoder);
116 static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst,
119 const void *Decoder);
121 static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst,
124 const void *Decoder);
126 static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst,
129 const void *Decoder);
131 static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst,
134 const void *Decoder);
136 static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst,
139 const void *Decoder);
141 static DecodeStatus DecodeACRegsDSPRegisterClass(MCInst &Inst,
144 const void *Decoder);
146 static DecodeStatus DecodeHIRegsDSPRegisterClass(MCInst &Inst,
149 const void *Decoder);
151 static DecodeStatus DecodeLORegsDSPRegisterClass(MCInst &Inst,
154 const void *Decoder);
156 static DecodeStatus DecodeBranchTarget(MCInst &Inst,
159 const void *Decoder);
161 static DecodeStatus DecodeBC1(MCInst &Inst,
164 const void *Decoder);
167 static DecodeStatus DecodeJumpTarget(MCInst &Inst,
170 const void *Decoder);
172 static DecodeStatus DecodeMem(MCInst &Inst,
175 const void *Decoder);
177 static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn,
179 const void *Decoder);
181 static DecodeStatus DecodeSimm16(MCInst &Inst,
184 const void *Decoder);
186 static DecodeStatus DecodeCondCode(MCInst &Inst,
189 const void *Decoder);
191 static DecodeStatus DecodeInsSize(MCInst &Inst,
194 const void *Decoder);
196 static DecodeStatus DecodeExtSize(MCInst &Inst,
199 const void *Decoder);
202 extern Target TheMipselTarget, TheMipsTarget, TheMips64Target,
206 static MCDisassembler *createMipsDisassembler(
208 const MCSubtargetInfo &STI) {
209 return new MipsDisassembler(STI, T.createMCRegInfo(""), true);
212 static MCDisassembler *createMipselDisassembler(
214 const MCSubtargetInfo &STI) {
215 return new MipsDisassembler(STI, T.createMCRegInfo(""), false);
218 static MCDisassembler *createMips64Disassembler(
220 const MCSubtargetInfo &STI) {
221 return new Mips64Disassembler(STI, T.createMCRegInfo(""), true);
224 static MCDisassembler *createMips64elDisassembler(
226 const MCSubtargetInfo &STI) {
227 return new Mips64Disassembler(STI, T.createMCRegInfo(""), false);
230 extern "C" void LLVMInitializeMipsDisassembler() {
231 // Register the disassembler.
232 TargetRegistry::RegisterMCDisassembler(TheMipsTarget,
233 createMipsDisassembler);
234 TargetRegistry::RegisterMCDisassembler(TheMipselTarget,
235 createMipselDisassembler);
236 TargetRegistry::RegisterMCDisassembler(TheMips64Target,
237 createMips64Disassembler);
238 TargetRegistry::RegisterMCDisassembler(TheMips64elTarget,
239 createMips64elDisassembler);
243 #include "MipsGenDisassemblerTables.inc"
245 /// readInstruction - read four bytes from the MemoryObject
246 /// and return 32 bit word sorted according to the given endianess
247 static DecodeStatus readInstruction32(const MemoryObject ®ion,
254 // We want to read exactly 4 Bytes of data.
255 if (region.readBytes(address, 4, Bytes) == -1) {
257 return MCDisassembler::Fail;
261 // Encoded as a big-endian 32-bit word in the stream.
262 insn = (Bytes[3] << 0) |
268 // Encoded as a small-endian 32-bit word in the stream.
269 insn = (Bytes[0] << 0) |
275 return MCDisassembler::Success;
279 MipsDisassembler::getInstruction(MCInst &instr,
281 const MemoryObject &Region,
283 raw_ostream &vStream,
284 raw_ostream &cStream) const {
287 DecodeStatus Result = readInstruction32(Region, Address, Size,
289 if (Result == MCDisassembler::Fail)
290 return MCDisassembler::Fail;
292 // Calling the auto-generated decoder function.
293 Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address,
295 if (Result != MCDisassembler::Fail) {
300 return MCDisassembler::Fail;
304 Mips64Disassembler::getInstruction(MCInst &instr,
306 const MemoryObject &Region,
308 raw_ostream &vStream,
309 raw_ostream &cStream) const {
312 DecodeStatus Result = readInstruction32(Region, Address, Size,
314 if (Result == MCDisassembler::Fail)
315 return MCDisassembler::Fail;
317 // Calling the auto-generated decoder function.
318 Result = decodeInstruction(DecoderTableMips6432, instr, Insn, Address,
320 if (Result != MCDisassembler::Fail) {
324 // If we fail to decode in Mips64 decoder space we can try in Mips32
325 Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address,
327 if (Result != MCDisassembler::Fail) {
332 return MCDisassembler::Fail;
335 static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) {
336 const MipsDisassemblerBase *Dis = static_cast<const MipsDisassemblerBase*>(D);
337 return *(Dis->getRegInfo()->getRegClass(RC).begin() + RegNo);
340 static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst,
343 const void *Decoder) {
345 return MCDisassembler::Fail;
349 static DecodeStatus DecodeCPU64RegsRegisterClass(MCInst &Inst,
352 const void *Decoder) {
355 return MCDisassembler::Fail;
357 unsigned Reg = getReg(Decoder, Mips::CPU64RegsRegClassID, RegNo);
358 Inst.addOperand(MCOperand::CreateReg(Reg));
359 return MCDisassembler::Success;
362 static DecodeStatus DecodeCPURegsRegisterClass(MCInst &Inst,
365 const void *Decoder) {
367 return MCDisassembler::Fail;
368 unsigned Reg = getReg(Decoder, Mips::CPURegsRegClassID, RegNo);
369 Inst.addOperand(MCOperand::CreateReg(Reg));
370 return MCDisassembler::Success;
373 static DecodeStatus DecodeDSPRegsRegisterClass(MCInst &Inst,
376 const void *Decoder) {
377 return DecodeCPURegsRegisterClass(Inst, RegNo, Address, Decoder);
380 static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst,
383 const void *Decoder) {
385 return MCDisassembler::Fail;
387 unsigned Reg = getReg(Decoder, Mips::FGR64RegClassID, RegNo);
388 Inst.addOperand(MCOperand::CreateReg(Reg));
389 return MCDisassembler::Success;
392 static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst,
395 const void *Decoder) {
397 return MCDisassembler::Fail;
399 unsigned Reg = getReg(Decoder, Mips::FGR32RegClassID, RegNo);
400 Inst.addOperand(MCOperand::CreateReg(Reg));
401 return MCDisassembler::Success;
404 static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst,
407 const void *Decoder) {
408 Inst.addOperand(MCOperand::CreateReg(RegNo));
409 return MCDisassembler::Success;
412 static DecodeStatus DecodeMem(MCInst &Inst,
415 const void *Decoder) {
416 int Offset = SignExtend32<16>(Insn & 0xffff);
417 unsigned Reg = fieldFromInstruction(Insn, 16, 5);
418 unsigned Base = fieldFromInstruction(Insn, 21, 5);
420 Reg = getReg(Decoder, Mips::CPURegsRegClassID, Reg);
421 Base = getReg(Decoder, Mips::CPURegsRegClassID, Base);
423 if(Inst.getOpcode() == Mips::SC){
424 Inst.addOperand(MCOperand::CreateReg(Reg));
427 Inst.addOperand(MCOperand::CreateReg(Reg));
428 Inst.addOperand(MCOperand::CreateReg(Base));
429 Inst.addOperand(MCOperand::CreateImm(Offset));
431 return MCDisassembler::Success;
434 static DecodeStatus DecodeFMem(MCInst &Inst,
437 const void *Decoder) {
438 int Offset = SignExtend32<16>(Insn & 0xffff);
439 unsigned Reg = fieldFromInstruction(Insn, 16, 5);
440 unsigned Base = fieldFromInstruction(Insn, 21, 5);
442 Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg);
443 Base = getReg(Decoder, Mips::CPURegsRegClassID, Base);
445 Inst.addOperand(MCOperand::CreateReg(Reg));
446 Inst.addOperand(MCOperand::CreateReg(Base));
447 Inst.addOperand(MCOperand::CreateImm(Offset));
449 return MCDisassembler::Success;
453 static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst,
456 const void *Decoder) {
457 // Currently only hardware register 29 is supported.
459 return MCDisassembler::Fail;
460 Inst.addOperand(MCOperand::CreateReg(Mips::HWR29));
461 return MCDisassembler::Success;
464 static DecodeStatus DecodeCondCode(MCInst &Inst,
467 const void *Decoder) {
468 int CondCode = Insn & 0xf;
469 Inst.addOperand(MCOperand::CreateImm(CondCode));
470 return MCDisassembler::Success;
473 static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst,
476 const void *Decoder) {
477 if (RegNo > 30 || RegNo %2)
478 return MCDisassembler::Fail;
481 unsigned Reg = getReg(Decoder, Mips::AFGR64RegClassID, RegNo /2);
482 Inst.addOperand(MCOperand::CreateReg(Reg));
483 return MCDisassembler::Success;
486 static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst,
489 const void *Decoder) {
490 //Currently only hardware register 29 is supported
492 return MCDisassembler::Fail;
493 Inst.addOperand(MCOperand::CreateReg(Mips::HWR29_64));
494 return MCDisassembler::Success;
497 static DecodeStatus DecodeACRegsDSPRegisterClass(MCInst &Inst,
500 const void *Decoder) {
502 return MCDisassembler::Fail;
504 unsigned Reg = getReg(Decoder, Mips::ACRegsDSPRegClassID, RegNo);
505 Inst.addOperand(MCOperand::CreateReg(Reg));
506 return MCDisassembler::Success;
509 static DecodeStatus DecodeHIRegsDSPRegisterClass(MCInst &Inst,
512 const void *Decoder) {
514 return MCDisassembler::Fail;
516 unsigned Reg = getReg(Decoder, Mips::HIRegsDSPRegClassID, RegNo);
517 Inst.addOperand(MCOperand::CreateReg(Reg));
518 return MCDisassembler::Success;
521 static DecodeStatus DecodeLORegsDSPRegisterClass(MCInst &Inst,
524 const void *Decoder) {
526 return MCDisassembler::Fail;
528 unsigned Reg = getReg(Decoder, Mips::LORegsDSPRegClassID, RegNo);
529 Inst.addOperand(MCOperand::CreateReg(Reg));
530 return MCDisassembler::Success;
533 static DecodeStatus DecodeBranchTarget(MCInst &Inst,
536 const void *Decoder) {
537 unsigned BranchOffset = Offset & 0xffff;
538 BranchOffset = SignExtend32<18>(BranchOffset << 2) + 4;
539 Inst.addOperand(MCOperand::CreateImm(BranchOffset));
540 return MCDisassembler::Success;
543 static DecodeStatus DecodeBC1(MCInst &Inst,
546 const void *Decoder) {
547 unsigned BranchOffset = Insn & 0xffff;
548 BranchOffset = SignExtend32<18>(BranchOffset << 2) + 4;
549 Inst.addOperand(MCOperand::CreateImm(BranchOffset));
550 return MCDisassembler::Success;
553 static DecodeStatus DecodeJumpTarget(MCInst &Inst,
556 const void *Decoder) {
558 unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 2;
559 Inst.addOperand(MCOperand::CreateImm(JumpOffset));
560 return MCDisassembler::Success;
564 static DecodeStatus DecodeSimm16(MCInst &Inst,
567 const void *Decoder) {
568 Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Insn)));
569 return MCDisassembler::Success;
572 static DecodeStatus DecodeInsSize(MCInst &Inst,
575 const void *Decoder) {
576 // First we need to grab the pos(lsb) from MCInst.
577 int Pos = Inst.getOperand(2).getImm();
578 int Size = (int) Insn - Pos + 1;
579 Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Size)));
580 return MCDisassembler::Success;
583 static DecodeStatus DecodeExtSize(MCInst &Inst,
586 const void *Decoder) {
587 int Size = (int) Insn + 1;
588 Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Size)));
589 return MCDisassembler::Success;