1//===- 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 "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"
24
25using namespace llvm;
26
27typedef MCDisassembler::DecodeStatus DecodeStatus;
28
29namespace {
30
31/// MipsDisassemblerBase - a disasembler class for Mips.
32class MipsDisassemblerBase : public MCDisassembler {
33public:
34  /// Constructor     - Initializes the disassembler.
35  ///
36  MipsDisassemblerBase(const MCSubtargetInfo &STI, const MCRegisterInfo *Info,
37                       bool bigEndian) :
38    MCDisassembler(STI), RegInfo(Info), isBigEndian(bigEndian) {}
39
40  virtual ~MipsDisassemblerBase() {}
41
42  const MCRegisterInfo *getRegInfo() const { return RegInfo; }
43
44private:
45  const MCRegisterInfo *RegInfo;
46protected:
47  bool isBigEndian;
48};
49
50/// MipsDisassembler - a disasembler class for Mips32.
51class MipsDisassembler : public MipsDisassemblerBase {
52public:
53  /// Constructor     - Initializes the disassembler.
54  ///
55  MipsDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info,
56                   bool bigEndian) :
57    MipsDisassemblerBase(STI, Info, bigEndian) {}
58
59  /// getInstruction - See MCDisassembler.
60  virtual DecodeStatus getInstruction(MCInst &instr,
61                                      uint64_t &size,
62                                      const MemoryObject &region,
63                                      uint64_t address,
64                                      raw_ostream &vStream,
65                                      raw_ostream &cStream) const;
66};
67
68
69/// Mips64Disassembler - a disasembler class for Mips64.
70class Mips64Disassembler : public MipsDisassemblerBase {
71public:
72  /// Constructor     - Initializes the disassembler.
73  ///
74  Mips64Disassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info,
75                     bool bigEndian) :
76    MipsDisassemblerBase(STI, Info, bigEndian) {}
77
78  /// getInstruction - See MCDisassembler.
79  virtual DecodeStatus getInstruction(MCInst &instr,
80                                      uint64_t &size,
81                                      const MemoryObject &region,
82                                      uint64_t address,
83                                      raw_ostream &vStream,
84                                      raw_ostream &cStream) const;
85};
86
87} // end anonymous namespace
88
89// Forward declare these because the autogenerated code will reference them.
90// Definitions are further down.
91static DecodeStatus DecodeCPU64RegsRegisterClass(MCInst &Inst,
92                                                 unsigned RegNo,
93                                                 uint64_t Address,
94                                                 const void *Decoder);
95
96static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst,
97                                                 unsigned RegNo,
98                                                 uint64_t Address,
99                                                 const void *Decoder);
100
101static DecodeStatus DecodeCPURegsRegisterClass(MCInst &Inst,
102                                               unsigned RegNo,
103                                               uint64_t Address,
104                                               const void *Decoder);
105
106static DecodeStatus DecodeDSPRegsRegisterClass(MCInst &Inst,
107                                               unsigned RegNo,
108                                               uint64_t Address,
109                                               const void *Decoder);
110
111static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst,
112                                             unsigned RegNo,
113                                             uint64_t Address,
114                                             const void *Decoder);
115
116static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst,
117                                             unsigned RegNo,
118                                             uint64_t Address,
119                                             const void *Decoder);
120
121static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst,
122                                           unsigned RegNo,
123                                           uint64_t Address,
124                                           const void *Decoder);
125
126static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst,
127                                              unsigned Insn,
128                                              uint64_t Address,
129                                              const void *Decoder);
130
131static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst,
132                                              unsigned RegNo,
133                                              uint64_t Address,
134                                              const void *Decoder);
135
136static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst,
137                                                unsigned Insn,
138                                                uint64_t Address,
139                                                const void *Decoder);
140
141static DecodeStatus DecodeACRegsRegisterClass(MCInst &Inst,
142                                              unsigned RegNo,
143                                              uint64_t Address,
144                                              const void *Decoder);
145
146static DecodeStatus DecodeBranchTarget(MCInst &Inst,
147                                       unsigned Offset,
148                                       uint64_t Address,
149                                       const void *Decoder);
150
151static DecodeStatus DecodeBC1(MCInst &Inst,
152                              unsigned Insn,
153                              uint64_t Address,
154                              const void *Decoder);
155
156
157static DecodeStatus DecodeJumpTarget(MCInst &Inst,
158                                     unsigned Insn,
159                                     uint64_t Address,
160                                     const void *Decoder);
161
162static DecodeStatus DecodeMem(MCInst &Inst,
163                              unsigned Insn,
164                              uint64_t Address,
165                              const void *Decoder);
166
167static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn,
168                               uint64_t Address,
169                               const void *Decoder);
170
171static DecodeStatus DecodeSimm16(MCInst &Inst,
172                                 unsigned Insn,
173                                 uint64_t Address,
174                                 const void *Decoder);
175
176static DecodeStatus DecodeCondCode(MCInst &Inst,
177                                   unsigned Insn,
178                                   uint64_t Address,
179                                   const void *Decoder);
180
181static DecodeStatus DecodeInsSize(MCInst &Inst,
182                                  unsigned Insn,
183                                  uint64_t Address,
184                                  const void *Decoder);
185
186static DecodeStatus DecodeExtSize(MCInst &Inst,
187                                  unsigned Insn,
188                                  uint64_t Address,
189                                  const void *Decoder);
190
191namespace llvm {
192extern Target TheMipselTarget, TheMipsTarget, TheMips64Target,
193              TheMips64elTarget;
194}
195
196static MCDisassembler *createMipsDisassembler(
197                       const Target &T,
198                       const MCSubtargetInfo &STI) {
199  return new MipsDisassembler(STI, T.createMCRegInfo(""), true);
200}
201
202static MCDisassembler *createMipselDisassembler(
203                       const Target &T,
204                       const MCSubtargetInfo &STI) {
205  return new MipsDisassembler(STI, T.createMCRegInfo(""), false);
206}
207
208static MCDisassembler *createMips64Disassembler(
209                       const Target &T,
210                       const MCSubtargetInfo &STI) {
211  return new Mips64Disassembler(STI, T.createMCRegInfo(""), true);
212}
213
214static MCDisassembler *createMips64elDisassembler(
215                       const Target &T,
216                       const MCSubtargetInfo &STI) {
217  return new Mips64Disassembler(STI, T.createMCRegInfo(""), false);
218}
219
220extern "C" void LLVMInitializeMipsDisassembler() {
221  // Register the disassembler.
222  TargetRegistry::RegisterMCDisassembler(TheMipsTarget,
223                                         createMipsDisassembler);
224  TargetRegistry::RegisterMCDisassembler(TheMipselTarget,
225                                         createMipselDisassembler);
226  TargetRegistry::RegisterMCDisassembler(TheMips64Target,
227                                         createMips64Disassembler);
228  TargetRegistry::RegisterMCDisassembler(TheMips64elTarget,
229                                         createMips64elDisassembler);
230}
231
232
233#include "MipsGenDisassemblerTables.inc"
234
235  /// readInstruction - read four bytes from the MemoryObject
236  /// and return 32 bit word sorted according to the given endianess
237static DecodeStatus readInstruction32(const MemoryObject &region,
238                                      uint64_t address,
239                                      uint64_t &size,
240                                      uint32_t &insn,
241                                      bool isBigEndian) {
242  uint8_t Bytes[4];
243
244  // We want to read exactly 4 Bytes of data.
245  if (region.readBytes(address, 4, (uint8_t*)Bytes, NULL) == -1) {
246    size = 0;
247    return MCDisassembler::Fail;
248  }
249
250  if (isBigEndian) {
251    // Encoded as a big-endian 32-bit word in the stream.
252    insn = (Bytes[3] <<  0) |
253           (Bytes[2] <<  8) |
254           (Bytes[1] << 16) |
255           (Bytes[0] << 24);
256  }
257  else {
258    // Encoded as a small-endian 32-bit word in the stream.
259    insn = (Bytes[0] <<  0) |
260           (Bytes[1] <<  8) |
261           (Bytes[2] << 16) |
262           (Bytes[3] << 24);
263  }
264
265  return MCDisassembler::Success;
266}
267
268DecodeStatus
269MipsDisassembler::getInstruction(MCInst &instr,
270                                 uint64_t &Size,
271                                 const MemoryObject &Region,
272                                 uint64_t Address,
273                                 raw_ostream &vStream,
274                                 raw_ostream &cStream) const {
275  uint32_t Insn;
276
277  DecodeStatus Result = readInstruction32(Region, Address, Size,
278                                          Insn, isBigEndian);
279  if (Result == MCDisassembler::Fail)
280    return MCDisassembler::Fail;
281
282  // Calling the auto-generated decoder function.
283  Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address,
284                             this, STI);
285  if (Result != MCDisassembler::Fail) {
286    Size = 4;
287    return Result;
288  }
289
290  return MCDisassembler::Fail;
291}
292
293DecodeStatus
294Mips64Disassembler::getInstruction(MCInst &instr,
295                                   uint64_t &Size,
296                                   const MemoryObject &Region,
297                                   uint64_t Address,
298                                   raw_ostream &vStream,
299                                   raw_ostream &cStream) const {
300  uint32_t Insn;
301
302  DecodeStatus Result = readInstruction32(Region, Address, Size,
303                                          Insn, isBigEndian);
304  if (Result == MCDisassembler::Fail)
305    return MCDisassembler::Fail;
306
307  // Calling the auto-generated decoder function.
308  Result = decodeInstruction(DecoderTableMips6432, instr, Insn, Address,
309                             this, STI);
310  if (Result != MCDisassembler::Fail) {
311    Size = 4;
312    return Result;
313  }
314  // If we fail to decode in Mips64 decoder space we can try in Mips32
315  Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address,
316                             this, STI);
317  if (Result != MCDisassembler::Fail) {
318    Size = 4;
319    return Result;
320  }
321
322  return MCDisassembler::Fail;
323}
324
325static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) {
326  const MipsDisassemblerBase *Dis = static_cast<const MipsDisassemblerBase*>(D);
327  return *(Dis->getRegInfo()->getRegClass(RC).begin() + RegNo);
328}
329
330static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst,
331                                                 unsigned RegNo,
332                                                 uint64_t Address,
333                                                 const void *Decoder) {
334
335  return MCDisassembler::Fail;
336
337}
338
339static DecodeStatus DecodeCPU64RegsRegisterClass(MCInst &Inst,
340                                                 unsigned RegNo,
341                                                 uint64_t Address,
342                                                 const void *Decoder) {
343
344  if (RegNo > 31)
345    return MCDisassembler::Fail;
346
347  unsigned Reg = getReg(Decoder, Mips::CPU64RegsRegClassID, RegNo);
348  Inst.addOperand(MCOperand::CreateReg(Reg));
349  return MCDisassembler::Success;
350}
351
352static DecodeStatus DecodeCPURegsRegisterClass(MCInst &Inst,
353                                               unsigned RegNo,
354                                               uint64_t Address,
355                                               const void *Decoder) {
356  if (RegNo > 31)
357    return MCDisassembler::Fail;
358  unsigned Reg = getReg(Decoder, Mips::CPURegsRegClassID, RegNo);
359  Inst.addOperand(MCOperand::CreateReg(Reg));
360  return MCDisassembler::Success;
361}
362
363static DecodeStatus DecodeDSPRegsRegisterClass(MCInst &Inst,
364                                               unsigned RegNo,
365                                               uint64_t Address,
366                                               const void *Decoder) {
367  return DecodeCPURegsRegisterClass(Inst, RegNo, Address, Decoder);
368}
369
370static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst,
371                                             unsigned RegNo,
372                                             uint64_t Address,
373                                             const void *Decoder) {
374  if (RegNo > 31)
375    return MCDisassembler::Fail;
376
377  unsigned Reg = getReg(Decoder, Mips::FGR64RegClassID, RegNo);
378  Inst.addOperand(MCOperand::CreateReg(Reg));
379  return MCDisassembler::Success;
380}
381
382static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst,
383                                             unsigned RegNo,
384                                             uint64_t Address,
385                                             const void *Decoder) {
386  if (RegNo > 31)
387    return MCDisassembler::Fail;
388
389  unsigned Reg = getReg(Decoder, Mips::FGR32RegClassID, RegNo);
390  Inst.addOperand(MCOperand::CreateReg(Reg));
391  return MCDisassembler::Success;
392}
393
394static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst,
395                                           unsigned RegNo,
396                                           uint64_t Address,
397                                           const void *Decoder) {
398  Inst.addOperand(MCOperand::CreateReg(RegNo));
399  return MCDisassembler::Success;
400}
401
402static DecodeStatus DecodeMem(MCInst &Inst,
403                              unsigned Insn,
404                              uint64_t Address,
405                              const void *Decoder) {
406  int Offset = SignExtend32<16>(Insn & 0xffff);
407  unsigned Reg = fieldFromInstruction(Insn, 16, 5);
408  unsigned Base = fieldFromInstruction(Insn, 21, 5);
409
410  Reg = getReg(Decoder, Mips::CPURegsRegClassID, Reg);
411  Base = getReg(Decoder, Mips::CPURegsRegClassID, Base);
412
413  if(Inst.getOpcode() == Mips::SC){
414    Inst.addOperand(MCOperand::CreateReg(Reg));
415  }
416
417  Inst.addOperand(MCOperand::CreateReg(Reg));
418  Inst.addOperand(MCOperand::CreateReg(Base));
419  Inst.addOperand(MCOperand::CreateImm(Offset));
420
421  return MCDisassembler::Success;
422}
423
424static DecodeStatus DecodeFMem(MCInst &Inst,
425                               unsigned Insn,
426                               uint64_t Address,
427                               const void *Decoder) {
428  int Offset = SignExtend32<16>(Insn & 0xffff);
429  unsigned Reg = fieldFromInstruction(Insn, 16, 5);
430  unsigned Base = fieldFromInstruction(Insn, 21, 5);
431
432  Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg);
433  Base = getReg(Decoder, Mips::CPURegsRegClassID, Base);
434
435  Inst.addOperand(MCOperand::CreateReg(Reg));
436  Inst.addOperand(MCOperand::CreateReg(Base));
437  Inst.addOperand(MCOperand::CreateImm(Offset));
438
439  return MCDisassembler::Success;
440}
441
442
443static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst,
444                                              unsigned RegNo,
445                                              uint64_t Address,
446                                              const void *Decoder) {
447  // Currently only hardware register 29 is supported.
448  if (RegNo != 29)
449    return  MCDisassembler::Fail;
450  Inst.addOperand(MCOperand::CreateReg(Mips::HWR29));
451  return MCDisassembler::Success;
452}
453
454static DecodeStatus DecodeCondCode(MCInst &Inst,
455                                   unsigned Insn,
456                                   uint64_t Address,
457                                   const void *Decoder) {
458  int CondCode = Insn & 0xf;
459  Inst.addOperand(MCOperand::CreateImm(CondCode));
460  return MCDisassembler::Success;
461}
462
463static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst,
464                                              unsigned RegNo,
465                                              uint64_t Address,
466                                              const void *Decoder) {
467  if (RegNo > 30 || RegNo %2)
468    return MCDisassembler::Fail;
469
470  ;
471  unsigned Reg = getReg(Decoder, Mips::AFGR64RegClassID, RegNo /2);
472  Inst.addOperand(MCOperand::CreateReg(Reg));
473  return MCDisassembler::Success;
474}
475
476static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst,
477                                                unsigned RegNo,
478                                                uint64_t Address,
479                                                const void *Decoder) {
480  //Currently only hardware register 29 is supported
481  if (RegNo != 29)
482    return  MCDisassembler::Fail;
483  Inst.addOperand(MCOperand::CreateReg(Mips::HWR29_64));
484  return MCDisassembler::Success;
485}
486
487static DecodeStatus DecodeACRegsRegisterClass(MCInst &Inst,
488                                              unsigned RegNo,
489                                              uint64_t Address,
490                                              const void *Decoder) {
491  if (RegNo >= 4)
492    return MCDisassembler::Fail;
493
494  unsigned Reg = getReg(Decoder, Mips::ACRegsRegClassID, RegNo);
495  Inst.addOperand(MCOperand::CreateReg(Reg));
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 = fieldFromInstruction(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}
557