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