xref: /llvm-project/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp (revision 2d1f6d67c56e56a33ec8f49d584d2352d33a4081)
1 //===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- 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 /// \file
11 /// \brief This file is part of the ARC Disassembler.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "ARC.h"
16 #include "ARCRegisterInfo.h"
17 #include "MCTargetDesc/ARCMCTargetDesc.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
20 #include "llvm/MC/MCFixedLenDisassembler.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
24 #include "llvm/Support/TargetRegistry.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "arc-disassembler"
29 
30 using DecodeStatus = MCDisassembler::DecodeStatus;
31 
32 namespace {
33 
34 /// \brief A disassembler class for ARC.
35 class ARCDisassembler : public MCDisassembler {
36 public:
37   std::unique_ptr<MCInstrInfo const> const MCII;
38 
39   ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
40                   MCInstrInfo const *MCII)
41       : MCDisassembler(STI, Ctx), MCII(MCII) {}
42 
43   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
44                               ArrayRef<uint8_t> Bytes, uint64_t Address,
45                               raw_ostream &VStream,
46                               raw_ostream &CStream) const override;
47 };
48 
49 } // end anonymous namespace
50 
51 static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
52                               uint64_t &Size, uint32_t &Insn) {
53   Size = 4;
54   // Read 2 16-bit values, but swap hi/lo parts.
55   Insn =
56       (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
57   return true;
58 }
59 
60 static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
61                               uint64_t &Size, uint64_t &Insn) {
62   Size = 8;
63   Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
64          ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
65          ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
66          ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
67   return true;
68 }
69 
70 static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
71                               uint64_t &Size, uint32_t &Insn) {
72   Size = 2;
73   Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
74   return true;
75 }
76 
77 static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &, unsigned,
78                                                      uint64_t, const void *);
79 
80 static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &, unsigned,
81                                                     uint64_t, const void *);
82 
83 static MCDisassembler::DecodeStatus
84 DecodeBranchTargetS9(MCInst &, unsigned, uint64_t, const void *);
85 
86 static MCDisassembler::DecodeStatus
87 DecodeBranchTargetS21(MCInst &, unsigned, uint64_t, const void *);
88 
89 static MCDisassembler::DecodeStatus
90 DecodeBranchTargetS25(MCInst &, unsigned, uint64_t, const void *);
91 
92 static MCDisassembler::DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
93                                                  const void *);
94 
95 static MCDisassembler::DecodeStatus
96 DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
97 
98 static MCDisassembler::DecodeStatus
99 DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
100 
101 static MCDisassembler::DecodeStatus
102 DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
103 
104 static const uint16_t GPR32DecoderTable[] = {
105     ARC::R0,  ARC::R1,    ARC::R2,  ARC::R3,   ARC::R4,  ARC::R5,  ARC::R6,
106     ARC::R7,  ARC::R8,    ARC::R9,  ARC::R10,  ARC::R11, ARC::R12, ARC::R13,
107     ARC::R14, ARC::R15,   ARC::R16, ARC::R17,  ARC::R18, ARC::R19, ARC::R20,
108     ARC::R21, ARC::R22,   ARC::R23, ARC::R24,  ARC::R25, ARC::GP,  ARC::FP,
109     ARC::SP,  ARC::ILINK, ARC::R30, ARC::BLINK};
110 
111 static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
112                                              uint64_t Address,
113                                              const void *Decoder) {
114   if (RegNo >= 32) {
115     DEBUG(dbgs() << "Not a GPR32 register.");
116     return MCDisassembler::Fail;
117   }
118   unsigned Reg = GPR32DecoderTable[RegNo];
119   Inst.addOperand(MCOperand::createReg(Reg));
120   return MCDisassembler::Success;
121 }
122 
123 #include "ARCGenDisassemblerTables.inc"
124 
125 static unsigned decodeCField(unsigned Insn) {
126   return fieldFromInstruction(Insn, 6, 6);
127 }
128 
129 static unsigned decodeBField(unsigned Insn) {
130   return (fieldFromInstruction(Insn, 12, 3) << 3) |
131          fieldFromInstruction(Insn, 24, 3);
132 }
133 
134 static unsigned decodeAField(unsigned Insn) {
135   return fieldFromInstruction(Insn, 0, 6);
136 }
137 
138 static MCDisassembler::DecodeStatus
139 DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Dec) {
140   // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
141   unsigned S9 = Insn & 0x1ff;
142   unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
143   DecodeGPR32RegisterClass(Inst, R, Address, Dec);
144   Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
145   return MCDisassembler::Success;
146 }
147 
148 static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &Inst,
149                                                     unsigned InsnS9,
150                                                     uint64_t Address,
151                                                     const void *Decoder) {
152   Inst.addOperand(MCOperand::createImm(SignExtend32<9>(0x1ff & InsnS9)));
153   return MCDisassembler::Success;
154 }
155 
156 static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &Inst,
157                                                      unsigned InsnS12,
158                                                      uint64_t Address,
159                                                      const void *Decoder) {
160   Inst.addOperand(MCOperand::createImm(SignExtend32<12>(0xfff & InsnS12)));
161   return MCDisassembler::Success;
162 }
163 
164 static MCDisassembler::DecodeStatus DecodeBranchTargetS9(MCInst &Inst,
165                                                          unsigned S,
166                                                          uint64_t Address,
167                                                          const void *Decoder) {
168   Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S)));
169   return MCDisassembler::Success;
170 }
171 
172 static MCDisassembler::DecodeStatus DecodeBranchTargetS21(MCInst &Inst,
173                                                           unsigned S,
174                                                           uint64_t Address,
175                                                           const void *Decoder) {
176   Inst.addOperand(MCOperand::createImm(SignExtend32<21>(S)));
177   return MCDisassembler::Success;
178 }
179 
180 static MCDisassembler::DecodeStatus DecodeBranchTargetS25(MCInst &Inst,
181                                                           unsigned S,
182                                                           uint64_t Address,
183                                                           const void *Decoder) {
184   Inst.addOperand(MCOperand::createImm(SignExtend32<25>(S)));
185   return MCDisassembler::Success;
186 }
187 
188 static MCDisassembler::DecodeStatus
189 DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
190                         const void *Decoder) {
191   unsigned SrcC, DstB, LImm;
192   DstB = decodeBField(Insn);
193   if (DstB != 62) {
194     DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
195     return MCDisassembler::Fail;
196   }
197   SrcC = decodeCField(Insn);
198   DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
199   LImm = (Insn >> 32);
200   Inst.addOperand(MCOperand::createImm(LImm));
201   Inst.addOperand(MCOperand::createImm(0));
202   return MCDisassembler::Success;
203 }
204 
205 static MCDisassembler::DecodeStatus
206 DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
207                         const void *Decoder) {
208   unsigned DstA, SrcB, LImm;
209   DEBUG(dbgs() << "Decoding LdLImm:\n");
210   SrcB = decodeBField(Insn);
211   if (SrcB != 62) {
212     DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
213     return MCDisassembler::Fail;
214   }
215   DstA = decodeAField(Insn);
216   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
217   LImm = (Insn >> 32);
218   Inst.addOperand(MCOperand::createImm(LImm));
219   Inst.addOperand(MCOperand::createImm(0));
220   return MCDisassembler::Success;
221 }
222 
223 static MCDisassembler::DecodeStatus
224 DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
225                          const void *Decoder) {
226   unsigned DstA, SrcB;
227   DEBUG(dbgs() << "Decoding LdRLimm\n");
228   DstA = decodeAField(Insn);
229   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
230   SrcB = decodeBField(Insn);
231   DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
232   if (decodeCField(Insn) != 62) {
233     DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
234     return MCDisassembler::Fail;
235   }
236   Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
237   return MCDisassembler::Success;
238 }
239 
240 MCDisassembler::DecodeStatus ARCDisassembler::getInstruction(
241     MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
242     raw_ostream &vStream, raw_ostream &cStream) const {
243   MCDisassembler::DecodeStatus Result;
244   if (Bytes.size() < 2) {
245     Size = 0;
246     return Fail;
247   }
248   uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
249   // 0x00 -> 0x07 are 32-bit instructions.
250   // 0x08 -> 0x1F are 16-bit instructions.
251   if (DecodeByte < 0x08) {
252     // 32-bit instruction.
253     if (Bytes.size() < 4) {
254       // Did we decode garbage?
255       Size = 0;
256       return Fail;
257     }
258     if (Bytes.size() >= 8) {
259       // Attempt to decode 64-bit instruction.
260       uint64_t Insn64;
261       if (!readInstruction64(Bytes, Address, Size, Insn64))
262         return Fail;
263       Result =
264           decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
265       if (Result == MCDisassembler::Success) {
266         DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
267         return MCDisassembler::Success;
268       }
269       DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
270     }
271     uint32_t Insn32;
272     if (!readInstruction32(Bytes, Address, Size, Insn32)) {
273       return Fail;
274     }
275     // Calling the auto-generated decoder function.
276     return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
277   }
278 
279   // 16-bit instruction.
280   uint32_t Insn16;
281   if (!readInstruction16(Bytes, Address, Size, Insn16)) {
282     return Fail;
283   }
284   // Calling the auto-generated decoder function.
285   return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
286 }
287 
288 static MCDisassembler *createARCDisassembler(const Target &T,
289                                              const MCSubtargetInfo &STI,
290                                              MCContext &Ctx) {
291   return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
292 }
293 
294 extern "C" void LLVMInitializeARCDisassembler() {
295   // Register the disassembler.
296   TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
297                                          createARCDisassembler);
298 }
299