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