xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp (revision 1f1e2261e341e6ca6862f82261066ef1705f0a7a)
1 //===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file is part of the ARC Disassembler.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "ARC.h"
15 #include "ARCRegisterInfo.h"
16 #include "MCTargetDesc/ARCMCTargetDesc.h"
17 #include "TargetInfo/ARCTargetInfo.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/MC/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 /// 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 &CStream) const override;
46 };
47 
48 } // end anonymous namespace
49 
50 static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
51                               uint64_t &Size, uint32_t &Insn) {
52   Size = 4;
53   // Read 2 16-bit values, but swap hi/lo parts.
54   Insn =
55       (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
56   return true;
57 }
58 
59 static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
60                               uint64_t &Size, uint64_t &Insn) {
61   Size = 8;
62   Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
63          ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
64          ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
65          ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
66   return true;
67 }
68 
69 static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
70                               uint64_t &Size, uint64_t &Insn) {
71   Size = 6;
72   Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
73          ((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
74          ((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
75   return true;
76 }
77 
78 static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
79                               uint64_t &Size, uint32_t &Insn) {
80   Size = 2;
81   Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
82   return true;
83 }
84 
85 template <unsigned B>
86 static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
87                                         uint64_t Address = 0,
88                                         const void *Decoder = nullptr);
89 
90 template <unsigned B>
91 static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
92                                         uint64_t Address = 0,
93                                         const void *Decoder = nullptr);
94 
95 template <unsigned B>
96 static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
97                                         uint64_t Address, const void *Decoder);
98 
99 static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *);
100 
101 static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
102                                             const void *);
103 
104 static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
105                                             const void *);
106 
107 static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
108                                              const void *);
109 
110 static DecodeStatus DecodeSOPwithRS12(MCInst &, uint64_t, uint64_t,
111                                       const void *);
112 
113 static DecodeStatus DecodeSOPwithRU6(MCInst &, uint64_t, uint64_t,
114                                      const void *);
115 
116 static DecodeStatus DecodeCCRU6Instruction(MCInst &, uint64_t, uint64_t,
117                                            const void *);
118 
119 static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
120                                               const void *);
121 
122 static const uint16_t GPR32DecoderTable[] = {
123     ARC::R0,  ARC::R1,    ARC::R2,  ARC::R3,   ARC::R4,  ARC::R5,  ARC::R6,
124     ARC::R7,  ARC::R8,    ARC::R9,  ARC::R10,  ARC::R11, ARC::R12, ARC::R13,
125     ARC::R14, ARC::R15,   ARC::R16, ARC::R17,  ARC::R18, ARC::R19, ARC::R20,
126     ARC::R21, ARC::R22,   ARC::R23, ARC::R24,  ARC::R25, ARC::GP,  ARC::FP,
127     ARC::SP,  ARC::ILINK, ARC::R30, ARC::BLINK};
128 
129 static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
130                                              uint64_t Address,
131                                              const void *Decoder) {
132   if (RegNo >= 32) {
133     LLVM_DEBUG(dbgs() << "Not a GPR32 register.");
134     return MCDisassembler::Fail;
135   }
136 
137   unsigned Reg = GPR32DecoderTable[RegNo];
138   Inst.addOperand(MCOperand::createReg(Reg));
139   return MCDisassembler::Success;
140 }
141 
142 static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
143                                                uint64_t Address,
144                                                const void *Decoder) {
145   // Enumerates registers from ranges [r0-r3],[r12-r15].
146   if (RegNo > 3)
147     RegNo += 8; // 4 for r12, etc...
148 
149   return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
150 }
151 
152 #include "ARCGenDisassemblerTables.inc"
153 
154 static unsigned decodeCField(unsigned Insn) {
155   return fieldFromInstruction(Insn, 6, 6);
156 }
157 
158 static unsigned decodeBField(unsigned Insn) {
159   return (fieldFromInstruction(Insn, 12, 3) << 3) |
160          fieldFromInstruction(Insn, 24, 3);
161 }
162 
163 static unsigned decodeAField(unsigned Insn) {
164   return fieldFromInstruction(Insn, 0, 6);
165 }
166 
167 static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
168                                  const void *Dec) {
169   // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
170   unsigned S9 = Insn & 0x1ff;
171   unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
172   DecodeGPR32RegisterClass(Inst, R, Address, Dec);
173   Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
174   return MCDisassembler::Success;
175 }
176 
177 static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
178                                   uint64_t Value, const void *Decoder) {
179   static const uint64_t AtLeast = 2;
180   // TODO: Try to force emitter to use MCDisassembler* instead of void*.
181   auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
182   return (nullptr != Disassembler &&
183           Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
184                                                  AtLeast));
185 }
186 
187 static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
188                                      uint64_t Offset, const void *Decoder) {
189   uint64_t NextAddress = Address + Offset;
190 
191   if (!DecodeSymbolicOperand(Inst, Address, NextAddress, Decoder))
192     Inst.addOperand(MCOperand::createImm(Offset));
193 }
194 
195 template <unsigned B>
196 static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
197                                         uint64_t Address, const void *Decoder) {
198 
199   static_assert(B > 0, "field is empty");
200   DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
201   return MCDisassembler::Success;
202 }
203 
204 template <unsigned B>
205 static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
206                                         uint64_t /*Address*/,
207                                         const void * /*Decoder*/) {
208 
209   static_assert(B > 0, "field is empty");
210   Inst.addOperand(MCOperand::createImm(
211       SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
212   return MCDisassembler::Success;
213 }
214 
215 template <unsigned B>
216 static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
217                                           uint64_t /*Address*/,
218                                           const void * /*Decoder*/) {
219 
220   static_assert(B > 0, "field is empty");
221   const unsigned max = (1u << B) - 1;
222   Inst.addOperand(
223       MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
224   return MCDisassembler::Success;
225 }
226 
227 static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
228                                             uint64_t Address,
229                                             const void *Decoder) {
230   unsigned SrcC, DstB, LImm;
231   DstB = decodeBField(Insn);
232   if (DstB != 62) {
233     LLVM_DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
234     return MCDisassembler::Fail;
235   }
236   SrcC = decodeCField(Insn);
237   DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
238   LImm = (Insn >> 32);
239   Inst.addOperand(MCOperand::createImm(LImm));
240   Inst.addOperand(MCOperand::createImm(0));
241   return MCDisassembler::Success;
242 }
243 
244 static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
245                                             uint64_t Address,
246                                             const void *Decoder) {
247   unsigned DstA, SrcB, LImm;
248   LLVM_DEBUG(dbgs() << "Decoding LdLImm:\n");
249   SrcB = decodeBField(Insn);
250   if (SrcB != 62) {
251     LLVM_DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
252     return MCDisassembler::Fail;
253   }
254   DstA = decodeAField(Insn);
255   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
256   LImm = (Insn >> 32);
257   Inst.addOperand(MCOperand::createImm(LImm));
258   Inst.addOperand(MCOperand::createImm(0));
259   return MCDisassembler::Success;
260 }
261 
262 static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
263                                              uint64_t Address,
264                                              const void *Decoder) {
265   unsigned DstA, SrcB;
266   LLVM_DEBUG(dbgs() << "Decoding LdRLimm\n");
267   DstA = decodeAField(Insn);
268   DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
269   SrcB = decodeBField(Insn);
270   DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
271   if (decodeCField(Insn) != 62) {
272     LLVM_DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
273     return MCDisassembler::Fail;
274   }
275   Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
276   return MCDisassembler::Success;
277 }
278 
279 static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
280                                               uint64_t Address,
281                                               const void *Decoder) {
282   LLVM_DEBUG(dbgs() << "Decoding MOV_S h-register\n");
283   using Field = decltype(Insn);
284   Field H = fieldFromInstruction(Insn, 5, 3) |
285             (fieldFromInstruction(Insn, 0, 2) << 3);
286   Field G = fieldFromInstruction(Insn, 8, 3) |
287             (fieldFromInstruction(Insn, 3, 2) << 3);
288 
289   auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
290                                                        Field Value) {
291     if (30 == RegNum) {
292       Inst.addOperand(MCOperand::createImm(Value));
293       return MCDisassembler::Success;
294     }
295 
296     return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
297   };
298 
299   if (MCDisassembler::Success != DecodeRegisterOrImm(G, 0))
300     return MCDisassembler::Fail;
301 
302   return DecodeRegisterOrImm(H, Insn >> 16u);
303 }
304 
305 static DecodeStatus DecodeCCRU6Instruction(MCInst &Inst, uint64_t Insn,
306                                            uint64_t Address,
307                                            const void *Decoder) {
308   unsigned DstB;
309   LLVM_DEBUG(dbgs() << "Decoding CCRU6 instruction:\n");
310   DstB = decodeBField(Insn);
311   DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
312   using Field = decltype(Insn);
313   Field U6Field = fieldFromInstruction(Insn, 6, 6);
314   Inst.addOperand(MCOperand::createImm(U6Field));
315   Field CCField = fieldFromInstruction(Insn, 0, 4);
316   Inst.addOperand(MCOperand::createImm(CCField));
317   return MCDisassembler::Success;
318 }
319 
320 static DecodeStatus DecodeSOPwithRU6(MCInst &Inst, uint64_t Insn,
321                                      uint64_t Address, const void *Decoder) {
322   unsigned DstB = decodeBField(Insn);
323   DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
324   using Field = decltype(Insn);
325   Field U6 = fieldFromInstruction(Insn, 6, 6);
326   Inst.addOperand(MCOperand::createImm(U6));
327   return MCDisassembler::Success;
328 }
329 
330 static DecodeStatus DecodeSOPwithRS12(MCInst &Inst, uint64_t Insn,
331                                       uint64_t Address, const void *Decoder) {
332   unsigned DstB = decodeBField(Insn);
333   DecodeGPR32RegisterClass(Inst, DstB, Address, Decoder);
334   using Field = decltype(Insn);
335   Field Lower = fieldFromInstruction(Insn, 6, 6);
336   Field Upper = fieldFromInstruction(Insn, 0, 5);
337   Field Sign = fieldFromInstruction(Insn, 5, 1) ? -1 : 1;
338   Field Result = Sign * ((Upper << 6) + Lower);
339   Inst.addOperand(MCOperand::createImm(Result));
340   return MCDisassembler::Success;
341 }
342 
343 DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
344                                              ArrayRef<uint8_t> Bytes,
345                                              uint64_t Address,
346                                              raw_ostream &cStream) const {
347   MCDisassembler::DecodeStatus Result;
348   if (Bytes.size() < 2) {
349     Size = 0;
350     return Fail;
351   }
352   uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
353   // 0x00 -> 0x07 are 32-bit instructions.
354   // 0x08 -> 0x1F are 16-bit instructions.
355   if (DecodeByte < 0x08) {
356     // 32-bit instruction.
357     if (Bytes.size() < 4) {
358       // Did we decode garbage?
359       Size = 0;
360       return Fail;
361     }
362     if (Bytes.size() >= 8) {
363       // Attempt to decode 64-bit instruction.
364       uint64_t Insn64;
365       if (!readInstruction64(Bytes, Address, Size, Insn64))
366         return Fail;
367       Result =
368           decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
369       if (Success == Result) {
370         LLVM_DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
371         return Result;
372       }
373       LLVM_DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
374     }
375     uint32_t Insn32;
376     if (!readInstruction32(Bytes, Address, Size, Insn32)) {
377       return Fail;
378     }
379     // Calling the auto-generated decoder function.
380     return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
381   } else {
382     if (Bytes.size() >= 6) {
383       // Attempt to treat as instr. with limm data.
384       uint64_t Insn48;
385       if (!readInstruction48(Bytes, Address, Size, Insn48))
386         return Fail;
387       Result =
388           decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
389       if (Success == Result) {
390         LLVM_DEBUG(
391             dbgs() << "Successfully decoded 16-bit instruction with limm.");
392         return Result;
393       }
394       LLVM_DEBUG(
395           dbgs() << "Not a 16-bit instruction with limm, try without it.");
396     }
397 
398     uint32_t Insn16;
399     if (!readInstruction16(Bytes, Address, Size, Insn16))
400       return Fail;
401 
402     // Calling the auto-generated decoder function.
403     return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
404   }
405 }
406 
407 static MCDisassembler *createARCDisassembler(const Target &T,
408                                              const MCSubtargetInfo &STI,
409                                              MCContext &Ctx) {
410   return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
411 }
412 
413 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARCDisassembler() {
414   // Register the disassembler.
415   TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
416                                          createARCDisassembler);
417 }
418