xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===- AVRDisassembler.cpp - Disassembler for AVR ---------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file is part of the AVR Disassembler.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "AVR.h"
140b57cec5SDimitry Andric #include "AVRRegisterInfo.h"
150b57cec5SDimitry Andric #include "AVRSubtarget.h"
160b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h"
170b57cec5SDimitry Andric #include "TargetInfo/AVRTargetInfo.h"
180b57cec5SDimitry Andric 
19*06c3fb27SDimitry Andric #include "llvm/ADT/DenseMap.h"
20*06c3fb27SDimitry Andric #include "llvm/ADT/STLExtras.h"
21*06c3fb27SDimitry Andric 
220b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
2481ad6265SDimitry Andric #include "llvm/MC/MCDecoderOps.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCDisassembler/MCDisassembler.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #define DEBUG_TYPE "avr-disassembler"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric typedef MCDisassembler::DecodeStatus DecodeStatus;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric namespace {
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric /// A disassembler class for AVR.
380b57cec5SDimitry Andric class AVRDisassembler : public MCDisassembler {
390b57cec5SDimitry Andric public:
AVRDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)400b57cec5SDimitry Andric   AVRDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
410b57cec5SDimitry Andric       : MCDisassembler(STI, Ctx) {}
4281ad6265SDimitry Andric   virtual ~AVRDisassembler() = default;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
450b57cec5SDimitry Andric                               ArrayRef<uint8_t> Bytes, uint64_t Address,
460b57cec5SDimitry Andric                               raw_ostream &CStream) const override;
470b57cec5SDimitry Andric };
48349cc55cSDimitry Andric } // namespace
490b57cec5SDimitry Andric 
createAVRDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)500b57cec5SDimitry Andric static MCDisassembler *createAVRDisassembler(const Target &T,
510b57cec5SDimitry Andric                                              const MCSubtargetInfo &STI,
520b57cec5SDimitry Andric                                              MCContext &Ctx) {
530b57cec5SDimitry Andric   return new AVRDisassembler(STI, Ctx);
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
LLVMInitializeAVRDisassembler()56480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRDisassembler() {
570b57cec5SDimitry Andric   // Register the disassembler.
580b57cec5SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getTheAVRTarget(),
590b57cec5SDimitry Andric                                          createAVRDisassembler);
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
625ffd83dbSDimitry Andric static const uint16_t GPRDecoderTable[] = {
63349cc55cSDimitry Andric     AVR::R0,  AVR::R1,  AVR::R2,  AVR::R3,  AVR::R4,  AVR::R5,  AVR::R6,
64349cc55cSDimitry Andric     AVR::R7,  AVR::R8,  AVR::R9,  AVR::R10, AVR::R11, AVR::R12, AVR::R13,
65349cc55cSDimitry Andric     AVR::R14, AVR::R15, AVR::R16, AVR::R17, AVR::R18, AVR::R19, AVR::R20,
66349cc55cSDimitry Andric     AVR::R21, AVR::R22, AVR::R23, AVR::R24, AVR::R25, AVR::R26, AVR::R27,
675ffd83dbSDimitry Andric     AVR::R28, AVR::R29, AVR::R30, AVR::R31,
685ffd83dbSDimitry Andric };
695ffd83dbSDimitry Andric 
DecodeGPR8RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const MCDisassembler * Decoder)700b57cec5SDimitry Andric static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo,
71349cc55cSDimitry Andric                                             uint64_t Address,
7281ad6265SDimitry Andric                                             const MCDisassembler *Decoder) {
735ffd83dbSDimitry Andric   if (RegNo > 31)
745ffd83dbSDimitry Andric     return MCDisassembler::Fail;
755ffd83dbSDimitry Andric 
765ffd83dbSDimitry Andric   unsigned Register = GPRDecoderTable[RegNo];
775ffd83dbSDimitry Andric   Inst.addOperand(MCOperand::createReg(Register));
780b57cec5SDimitry Andric   return MCDisassembler::Success;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
DecodeLD8RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const MCDisassembler * Decoder)810b57cec5SDimitry Andric static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo,
82349cc55cSDimitry Andric                                            uint64_t Address,
8381ad6265SDimitry Andric                                            const MCDisassembler *Decoder) {
845ffd83dbSDimitry Andric   if (RegNo > 15)
855ffd83dbSDimitry Andric     return MCDisassembler::Fail;
865ffd83dbSDimitry Andric 
875ffd83dbSDimitry Andric   unsigned Register = GPRDecoderTable[RegNo + 16];
885ffd83dbSDimitry Andric   Inst.addOperand(MCOperand::createReg(Register));
890b57cec5SDimitry Andric   return MCDisassembler::Success;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
92349cc55cSDimitry Andric static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,
9381ad6265SDimitry Andric                                  const MCDisassembler *Decoder);
945ffd83dbSDimitry Andric 
95349cc55cSDimitry Andric static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,
9681ad6265SDimitry Andric                                  const MCDisassembler *Decoder);
975ffd83dbSDimitry Andric 
98349cc55cSDimitry Andric static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,
9981ad6265SDimitry Andric                                  const MCDisassembler *Decoder);
1005ffd83dbSDimitry Andric 
1015ffd83dbSDimitry Andric static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Insn,
10281ad6265SDimitry Andric                                      uint64_t Address,
10381ad6265SDimitry Andric                                      const MCDisassembler *Decoder);
1045ffd83dbSDimitry Andric 
105349cc55cSDimitry Andric static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,
10681ad6265SDimitry Andric                               const MCDisassembler *Decoder);
1075ffd83dbSDimitry Andric 
108349cc55cSDimitry Andric static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,
10981ad6265SDimitry Andric                                 const MCDisassembler *Decoder);
1105ffd83dbSDimitry Andric 
1115ffd83dbSDimitry Andric static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
11281ad6265SDimitry Andric                                     uint64_t Address,
11381ad6265SDimitry Andric                                     const MCDisassembler *Decoder);
1145ffd83dbSDimitry Andric 
1155ffd83dbSDimitry Andric static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
11681ad6265SDimitry Andric                                     uint64_t Address,
11781ad6265SDimitry Andric                                     const MCDisassembler *Decoder);
1185ffd83dbSDimitry Andric 
119349cc55cSDimitry Andric static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,
12081ad6265SDimitry Andric                                 const MCDisassembler *Decoder);
1215ffd83dbSDimitry Andric 
1225ffd83dbSDimitry Andric static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
12381ad6265SDimitry Andric                                     uint64_t Address,
12481ad6265SDimitry Andric                                     const MCDisassembler *Decoder);
12581ad6265SDimitry Andric 
12681ad6265SDimitry Andric static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
12781ad6265SDimitry Andric                                 const MCDisassembler *Decoder);
12881ad6265SDimitry Andric 
129bdd1243dSDimitry Andric static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address,
130bdd1243dSDimitry Andric                                const MCDisassembler *Decoder);
131bdd1243dSDimitry Andric 
132*06c3fb27SDimitry Andric static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,
133*06c3fb27SDimitry Andric                                      uint64_t Address,
134*06c3fb27SDimitry Andric                                      const MCDisassembler *Decoder);
135*06c3fb27SDimitry Andric 
13681ad6265SDimitry Andric static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
13781ad6265SDimitry Andric                                     uint64_t Address,
13881ad6265SDimitry Andric                                     const MCDisassembler *Decoder);
1395ffd83dbSDimitry Andric 
1400b57cec5SDimitry Andric #include "AVRGenDisassemblerTables.inc"
1410b57cec5SDimitry Andric 
decodeFIOARr(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)142349cc55cSDimitry Andric static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,
14381ad6265SDimitry Andric                                  const MCDisassembler *Decoder) {
1445ffd83dbSDimitry Andric   unsigned addr = 0;
1455ffd83dbSDimitry Andric   addr |= fieldFromInstruction(Insn, 0, 4);
1465ffd83dbSDimitry Andric   addr |= fieldFromInstruction(Insn, 9, 2) << 4;
1475ffd83dbSDimitry Andric   unsigned reg = fieldFromInstruction(Insn, 4, 5);
1485ffd83dbSDimitry Andric   Inst.addOperand(MCOperand::createImm(addr));
149349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
150349cc55cSDimitry Andric       MCDisassembler::Fail)
1515ffd83dbSDimitry Andric     return MCDisassembler::Fail;
1525ffd83dbSDimitry Andric   return MCDisassembler::Success;
1535ffd83dbSDimitry Andric }
1545ffd83dbSDimitry Andric 
decodeFIORdA(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)155349cc55cSDimitry Andric static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,
15681ad6265SDimitry Andric                                  const MCDisassembler *Decoder) {
1575ffd83dbSDimitry Andric   unsigned addr = 0;
1585ffd83dbSDimitry Andric   addr |= fieldFromInstruction(Insn, 0, 4);
1595ffd83dbSDimitry Andric   addr |= fieldFromInstruction(Insn, 9, 2) << 4;
1605ffd83dbSDimitry Andric   unsigned reg = fieldFromInstruction(Insn, 4, 5);
161349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
162349cc55cSDimitry Andric       MCDisassembler::Fail)
1635ffd83dbSDimitry Andric     return MCDisassembler::Fail;
1645ffd83dbSDimitry Andric   Inst.addOperand(MCOperand::createImm(addr));
1655ffd83dbSDimitry Andric   return MCDisassembler::Success;
1665ffd83dbSDimitry Andric }
1675ffd83dbSDimitry Andric 
decodeFIOBIT(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)168349cc55cSDimitry Andric static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,
16981ad6265SDimitry Andric                                  const MCDisassembler *Decoder) {
1705ffd83dbSDimitry Andric   unsigned addr = fieldFromInstruction(Insn, 3, 5);
1715ffd83dbSDimitry Andric   unsigned b = fieldFromInstruction(Insn, 0, 3);
1725ffd83dbSDimitry Andric   Inst.addOperand(MCOperand::createImm(addr));
1735ffd83dbSDimitry Andric   Inst.addOperand(MCOperand::createImm(b));
1745ffd83dbSDimitry Andric   return MCDisassembler::Success;
1755ffd83dbSDimitry Andric }
1765ffd83dbSDimitry Andric 
decodeCallTarget(MCInst & Inst,unsigned Field,uint64_t Address,const MCDisassembler * Decoder)1775ffd83dbSDimitry Andric static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Field,
17881ad6265SDimitry Andric                                      uint64_t Address,
17981ad6265SDimitry Andric                                      const MCDisassembler *Decoder) {
1805ffd83dbSDimitry Andric   // Call targets need to be shifted left by one so this needs a custom
1815ffd83dbSDimitry Andric   // decoder.
1825ffd83dbSDimitry Andric   Inst.addOperand(MCOperand::createImm(Field << 1));
1835ffd83dbSDimitry Andric   return MCDisassembler::Success;
1845ffd83dbSDimitry Andric }
1855ffd83dbSDimitry Andric 
decodeFRd(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)186349cc55cSDimitry Andric static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,
18781ad6265SDimitry Andric                               const MCDisassembler *Decoder) {
1885ffd83dbSDimitry Andric   unsigned d = fieldFromInstruction(Insn, 4, 5);
189349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
190349cc55cSDimitry Andric       MCDisassembler::Fail)
1915ffd83dbSDimitry Andric     return MCDisassembler::Fail;
1925ffd83dbSDimitry Andric   return MCDisassembler::Success;
1935ffd83dbSDimitry Andric }
1945ffd83dbSDimitry Andric 
decodeFLPMX(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)195349cc55cSDimitry Andric static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,
19681ad6265SDimitry Andric                                 const MCDisassembler *Decoder) {
1975ffd83dbSDimitry Andric   if (decodeFRd(Inst, Insn, Address, Decoder) == MCDisassembler::Fail)
1985ffd83dbSDimitry Andric     return MCDisassembler::Fail;
1995ffd83dbSDimitry Andric   Inst.addOperand(MCOperand::createReg(AVR::R31R30));
2005ffd83dbSDimitry Andric   return MCDisassembler::Success;
2015ffd83dbSDimitry Andric }
2025ffd83dbSDimitry Andric 
decodeFFMULRdRr(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)2035ffd83dbSDimitry Andric static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
20481ad6265SDimitry Andric                                     uint64_t Address,
20581ad6265SDimitry Andric                                     const MCDisassembler *Decoder) {
2065ffd83dbSDimitry Andric   unsigned d = fieldFromInstruction(Insn, 4, 3) + 16;
2075ffd83dbSDimitry Andric   unsigned r = fieldFromInstruction(Insn, 0, 3) + 16;
208349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
209349cc55cSDimitry Andric       MCDisassembler::Fail)
2105ffd83dbSDimitry Andric     return MCDisassembler::Fail;
211349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
212349cc55cSDimitry Andric       MCDisassembler::Fail)
2135ffd83dbSDimitry Andric     return MCDisassembler::Fail;
2145ffd83dbSDimitry Andric   return MCDisassembler::Success;
2155ffd83dbSDimitry Andric }
2165ffd83dbSDimitry Andric 
decodeFMOVWRdRr(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)2175ffd83dbSDimitry Andric static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
21881ad6265SDimitry Andric                                     uint64_t Address,
21981ad6265SDimitry Andric                                     const MCDisassembler *Decoder) {
2205ffd83dbSDimitry Andric   unsigned r = fieldFromInstruction(Insn, 4, 4) * 2;
2215ffd83dbSDimitry Andric   unsigned d = fieldFromInstruction(Insn, 0, 4) * 2;
222349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
223349cc55cSDimitry Andric       MCDisassembler::Fail)
2245ffd83dbSDimitry Andric     return MCDisassembler::Fail;
225349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
226349cc55cSDimitry Andric       MCDisassembler::Fail)
2275ffd83dbSDimitry Andric     return MCDisassembler::Fail;
2285ffd83dbSDimitry Andric   return MCDisassembler::Success;
2295ffd83dbSDimitry Andric }
2305ffd83dbSDimitry Andric 
decodeFWRdK(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)231349cc55cSDimitry Andric static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,
23281ad6265SDimitry Andric                                 const MCDisassembler *Decoder) {
2335ffd83dbSDimitry Andric   unsigned d = fieldFromInstruction(Insn, 4, 2) * 2 + 24; // starts at r24:r25
2345ffd83dbSDimitry Andric   unsigned k = 0;
2355ffd83dbSDimitry Andric   k |= fieldFromInstruction(Insn, 0, 4);
2365ffd83dbSDimitry Andric   k |= fieldFromInstruction(Insn, 6, 2) << 4;
237349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
238349cc55cSDimitry Andric       MCDisassembler::Fail)
2395ffd83dbSDimitry Andric     return MCDisassembler::Fail;
240349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
241349cc55cSDimitry Andric       MCDisassembler::Fail)
2425ffd83dbSDimitry Andric     return MCDisassembler::Fail;
2435ffd83dbSDimitry Andric   Inst.addOperand(MCOperand::createImm(k));
2445ffd83dbSDimitry Andric   return MCDisassembler::Success;
2455ffd83dbSDimitry Andric }
2465ffd83dbSDimitry Andric 
decodeFMUL2RdRr(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)2475ffd83dbSDimitry Andric static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
24881ad6265SDimitry Andric                                     uint64_t Address,
24981ad6265SDimitry Andric                                     const MCDisassembler *Decoder) {
2505ffd83dbSDimitry Andric   unsigned rd = fieldFromInstruction(Insn, 4, 4) + 16;
2515ffd83dbSDimitry Andric   unsigned rr = fieldFromInstruction(Insn, 0, 4) + 16;
252349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, rd, Address, Decoder) ==
253349cc55cSDimitry Andric       MCDisassembler::Fail)
2545ffd83dbSDimitry Andric     return MCDisassembler::Fail;
255349cc55cSDimitry Andric   if (DecodeGPR8RegisterClass(Inst, rr, Address, Decoder) ==
256349cc55cSDimitry Andric       MCDisassembler::Fail)
2575ffd83dbSDimitry Andric     return MCDisassembler::Fail;
2585ffd83dbSDimitry Andric   return MCDisassembler::Success;
2595ffd83dbSDimitry Andric }
2605ffd83dbSDimitry Andric 
decodeMemri(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)26181ad6265SDimitry Andric static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
26281ad6265SDimitry Andric                                 const MCDisassembler *Decoder) {
26381ad6265SDimitry Andric   // As in the EncoderMethod `AVRMCCodeEmitter::encodeMemri`, the memory
26481ad6265SDimitry Andric   // address is encoded into 7-bit, in which bits 0-5 are the immediate offset,
26581ad6265SDimitry Andric   // and the bit-6 is the pointer register bit (Z=0, Y=1).
26681ad6265SDimitry Andric   if (Insn > 127)
26781ad6265SDimitry Andric     return MCDisassembler::Fail;
26881ad6265SDimitry Andric 
26981ad6265SDimitry Andric   // Append the base register operand.
27081ad6265SDimitry Andric   Inst.addOperand(
27181ad6265SDimitry Andric       MCOperand::createReg((Insn & 0x40) ? AVR::R29R28 : AVR::R31R30));
27281ad6265SDimitry Andric   // Append the immediate offset operand.
27381ad6265SDimitry Andric   Inst.addOperand(MCOperand::createImm(Insn & 0x3f));
27481ad6265SDimitry Andric 
27581ad6265SDimitry Andric   return MCDisassembler::Success;
27681ad6265SDimitry Andric }
27781ad6265SDimitry Andric 
decodeFBRk(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)278bdd1243dSDimitry Andric static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address,
279bdd1243dSDimitry Andric                                const MCDisassembler *Decoder) {
280bdd1243dSDimitry Andric   // Decode the opcode.
281bdd1243dSDimitry Andric   switch (Insn & 0xf000) {
282bdd1243dSDimitry Andric   case 0xc000:
283bdd1243dSDimitry Andric     Inst.setOpcode(AVR::RJMPk);
284bdd1243dSDimitry Andric     break;
285bdd1243dSDimitry Andric   case 0xd000:
286bdd1243dSDimitry Andric     Inst.setOpcode(AVR::RCALLk);
287bdd1243dSDimitry Andric     break;
288bdd1243dSDimitry Andric   default: // Unknown relative branch instruction.
289bdd1243dSDimitry Andric     return MCDisassembler::Fail;
290bdd1243dSDimitry Andric   }
291bdd1243dSDimitry Andric   // Decode the relative offset.
292bdd1243dSDimitry Andric   int16_t Offset = ((int16_t)((Insn & 0xfff) << 4)) >> 3;
293bdd1243dSDimitry Andric   Inst.addOperand(MCOperand::createImm(Offset));
294bdd1243dSDimitry Andric   return MCDisassembler::Success;
295bdd1243dSDimitry Andric }
296bdd1243dSDimitry Andric 
decodeCondBranch(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)297*06c3fb27SDimitry Andric static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,
298*06c3fb27SDimitry Andric                                      uint64_t Address,
299*06c3fb27SDimitry Andric                                      const MCDisassembler *Decoder) {
300*06c3fb27SDimitry Andric   // These 8 instructions are not defined as aliases of BRBS/BRBC.
301*06c3fb27SDimitry Andric   DenseMap<unsigned, unsigned> brInsts = {
302*06c3fb27SDimitry Andric       {0x000, AVR::BRLOk}, {0x400, AVR::BRSHk}, {0x001, AVR::BREQk},
303*06c3fb27SDimitry Andric       {0x401, AVR::BRNEk}, {0x002, AVR::BRMIk}, {0x402, AVR::BRPLk},
304*06c3fb27SDimitry Andric       {0x004, AVR::BRLTk}, {0x404, AVR::BRGEk}};
305*06c3fb27SDimitry Andric 
306*06c3fb27SDimitry Andric   // Get the relative offset.
307*06c3fb27SDimitry Andric   int16_t Offset = ((int16_t)((Insn & 0x3f8) << 6)) >> 8;
308*06c3fb27SDimitry Andric 
309*06c3fb27SDimitry Andric   // Search the instruction pattern.
310*06c3fb27SDimitry Andric   auto NotAlias = [&Insn](const std::pair<unsigned, unsigned> &I) {
311*06c3fb27SDimitry Andric     return (Insn & 0x407) != I.first;
312*06c3fb27SDimitry Andric   };
313*06c3fb27SDimitry Andric   llvm::partition(brInsts, NotAlias);
314*06c3fb27SDimitry Andric   auto It = llvm::partition_point(brInsts, NotAlias);
315*06c3fb27SDimitry Andric 
316*06c3fb27SDimitry Andric   // Decode the instruction.
317*06c3fb27SDimitry Andric   if (It != brInsts.end()) {
318*06c3fb27SDimitry Andric     // This instruction is not an alias of BRBC/BRBS.
319*06c3fb27SDimitry Andric     Inst.setOpcode(It->second);
320*06c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Offset));
321*06c3fb27SDimitry Andric   } else {
322*06c3fb27SDimitry Andric     // Fall back to an ordinary BRBS/BRBC.
323*06c3fb27SDimitry Andric     Inst.setOpcode(Insn & 0x400 ? AVR::BRBCsk : AVR::BRBSsk);
324*06c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Insn & 7));
325*06c3fb27SDimitry Andric     Inst.addOperand(MCOperand::createImm(Offset));
326*06c3fb27SDimitry Andric   }
327*06c3fb27SDimitry Andric 
328*06c3fb27SDimitry Andric   return MCDisassembler::Success;
329*06c3fb27SDimitry Andric }
330*06c3fb27SDimitry Andric 
decodeLoadStore(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)33181ad6265SDimitry Andric static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
33281ad6265SDimitry Andric                                     uint64_t Address,
33381ad6265SDimitry Andric                                     const MCDisassembler *Decoder) {
33481ad6265SDimitry Andric   // Get the register will be loaded or stored.
33581ad6265SDimitry Andric   unsigned RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];
33681ad6265SDimitry Andric 
33781ad6265SDimitry Andric   // Decode LDD/STD with offset less than 8.
33881ad6265SDimitry Andric   if ((Insn & 0xf000) == 0x8000) {
33981ad6265SDimitry Andric     unsigned RegBase = (Insn & 0x8) ? AVR::R29R28 : AVR::R31R30;
34081ad6265SDimitry Andric     unsigned Offset = Insn & 7; // We need not consider offset > 7.
34181ad6265SDimitry Andric     if ((Insn & 0x200) == 0) {  // Decode LDD.
34281ad6265SDimitry Andric       Inst.setOpcode(AVR::LDDRdPtrQ);
34381ad6265SDimitry Andric       Inst.addOperand(MCOperand::createReg(RegVal));
34481ad6265SDimitry Andric       Inst.addOperand(MCOperand::createReg(RegBase));
34581ad6265SDimitry Andric       Inst.addOperand(MCOperand::createImm(Offset));
34681ad6265SDimitry Andric     } else { // Decode STD.
34781ad6265SDimitry Andric       Inst.setOpcode(AVR::STDPtrQRr);
34881ad6265SDimitry Andric       Inst.addOperand(MCOperand::createReg(RegBase));
34981ad6265SDimitry Andric       Inst.addOperand(MCOperand::createImm(Offset));
35081ad6265SDimitry Andric       Inst.addOperand(MCOperand::createReg(RegVal));
35181ad6265SDimitry Andric     }
35281ad6265SDimitry Andric     return MCDisassembler::Success;
35381ad6265SDimitry Andric   }
35481ad6265SDimitry Andric 
35581ad6265SDimitry Andric   // Decode the following 14 instructions. Bit 9 indicates load(0) or store(1),
35681ad6265SDimitry Andric   // bits 8~4 indicate the value register, bits 3-2 indicate the base address
35781ad6265SDimitry Andric   // register (11-X, 10-Y, 00-Z), bits 1~0 indicate the mode (00-basic,
35881ad6265SDimitry Andric   // 01-postinc, 10-predec).
35981ad6265SDimitry Andric   // ST X,  Rr : 1001 001r rrrr 1100
36081ad6265SDimitry Andric   // ST X+, Rr : 1001 001r rrrr 1101
36181ad6265SDimitry Andric   // ST -X, Rr : 1001 001r rrrr 1110
36281ad6265SDimitry Andric   // ST Y+, Rr : 1001 001r rrrr 1001
36381ad6265SDimitry Andric   // ST -Y, Rr : 1001 001r rrrr 1010
36481ad6265SDimitry Andric   // ST Z+, Rr : 1001 001r rrrr 0001
36581ad6265SDimitry Andric   // ST -Z, Rr : 1001 001r rrrr 0010
36681ad6265SDimitry Andric   // LD Rd, X  : 1001 000d dddd 1100
36781ad6265SDimitry Andric   // LD Rd, X+ : 1001 000d dddd 1101
36881ad6265SDimitry Andric   // LD Rd, -X : 1001 000d dddd 1110
36981ad6265SDimitry Andric   // LD Rd, Y+ : 1001 000d dddd 1001
37081ad6265SDimitry Andric   // LD Rd, -Y : 1001 000d dddd 1010
37181ad6265SDimitry Andric   // LD Rd, Z+ : 1001 000d dddd 0001
37281ad6265SDimitry Andric   // LD Rd, -Z : 1001 000d dddd 0010
37381ad6265SDimitry Andric   if ((Insn & 0xfc00) != 0x9000 || (Insn & 0xf) == 0)
37481ad6265SDimitry Andric     return MCDisassembler::Fail;
37581ad6265SDimitry Andric 
37681ad6265SDimitry Andric   // Get the base address register.
37781ad6265SDimitry Andric   unsigned RegBase;
37881ad6265SDimitry Andric   switch (Insn & 0xc) {
37981ad6265SDimitry Andric   case 0xc:
38081ad6265SDimitry Andric     RegBase = AVR::R27R26;
38181ad6265SDimitry Andric     break;
38281ad6265SDimitry Andric   case 0x8:
38381ad6265SDimitry Andric     RegBase = AVR::R29R28;
38481ad6265SDimitry Andric     break;
38581ad6265SDimitry Andric   case 0x0:
38681ad6265SDimitry Andric     RegBase = AVR::R31R30;
38781ad6265SDimitry Andric     break;
38881ad6265SDimitry Andric   default:
38981ad6265SDimitry Andric     return MCDisassembler::Fail;
39081ad6265SDimitry Andric   }
39181ad6265SDimitry Andric 
39281ad6265SDimitry Andric   // Set the opcode.
39381ad6265SDimitry Andric   switch (Insn & 0x203) {
39481ad6265SDimitry Andric   case 0x200:
39581ad6265SDimitry Andric     Inst.setOpcode(AVR::STPtrRr);
39681ad6265SDimitry Andric     Inst.addOperand(MCOperand::createReg(RegBase));
39781ad6265SDimitry Andric     Inst.addOperand(MCOperand::createReg(RegVal));
39881ad6265SDimitry Andric     return MCDisassembler::Success;
39981ad6265SDimitry Andric   case 0x201:
40081ad6265SDimitry Andric     Inst.setOpcode(AVR::STPtrPiRr);
40181ad6265SDimitry Andric     break;
40281ad6265SDimitry Andric   case 0x202:
40381ad6265SDimitry Andric     Inst.setOpcode(AVR::STPtrPdRr);
40481ad6265SDimitry Andric     break;
40581ad6265SDimitry Andric   case 0:
40681ad6265SDimitry Andric     Inst.setOpcode(AVR::LDRdPtr);
40781ad6265SDimitry Andric     Inst.addOperand(MCOperand::createReg(RegVal));
40881ad6265SDimitry Andric     Inst.addOperand(MCOperand::createReg(RegBase));
40981ad6265SDimitry Andric     return MCDisassembler::Success;
41081ad6265SDimitry Andric   case 1:
41181ad6265SDimitry Andric     Inst.setOpcode(AVR::LDRdPtrPi);
41281ad6265SDimitry Andric     break;
41381ad6265SDimitry Andric   case 2:
41481ad6265SDimitry Andric     Inst.setOpcode(AVR::LDRdPtrPd);
41581ad6265SDimitry Andric     break;
41681ad6265SDimitry Andric   default:
41781ad6265SDimitry Andric     return MCDisassembler::Fail;
41881ad6265SDimitry Andric   }
41981ad6265SDimitry Andric 
42081ad6265SDimitry Andric   // Build postinc/predec machine instructions.
42181ad6265SDimitry Andric   if ((Insn & 0x200) == 0) { // This is a load instruction.
42281ad6265SDimitry Andric     Inst.addOperand(MCOperand::createReg(RegVal));
42381ad6265SDimitry Andric     Inst.addOperand(MCOperand::createReg(RegBase));
42481ad6265SDimitry Andric     Inst.addOperand(MCOperand::createReg(RegBase));
42581ad6265SDimitry Andric   } else { // This is a store instruction.
42681ad6265SDimitry Andric     Inst.addOperand(MCOperand::createReg(RegBase));
42781ad6265SDimitry Andric     Inst.addOperand(MCOperand::createReg(RegBase));
42881ad6265SDimitry Andric     Inst.addOperand(MCOperand::createReg(RegVal));
42981ad6265SDimitry Andric     // STPtrPiRr and STPtrPdRr have an extra immediate operand.
43081ad6265SDimitry Andric     Inst.addOperand(MCOperand::createImm(1));
43181ad6265SDimitry Andric   }
43281ad6265SDimitry Andric 
43381ad6265SDimitry Andric   return MCDisassembler::Success;
43481ad6265SDimitry Andric }
43581ad6265SDimitry Andric 
readInstruction16(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)4360b57cec5SDimitry Andric static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
4370b57cec5SDimitry Andric                                       uint64_t &Size, uint32_t &Insn) {
4380b57cec5SDimitry Andric   if (Bytes.size() < 2) {
4390b57cec5SDimitry Andric     Size = 0;
4400b57cec5SDimitry Andric     return MCDisassembler::Fail;
4410b57cec5SDimitry Andric   }
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   Size = 2;
4440b57cec5SDimitry Andric   Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   return MCDisassembler::Success;
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric 
readInstruction32(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)4490b57cec5SDimitry Andric static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
4500b57cec5SDimitry Andric                                       uint64_t &Size, uint32_t &Insn) {
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric   if (Bytes.size() < 4) {
4530b57cec5SDimitry Andric     Size = 0;
4540b57cec5SDimitry Andric     return MCDisassembler::Fail;
4550b57cec5SDimitry Andric   }
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric   Size = 4;
458349cc55cSDimitry Andric   Insn =
459349cc55cSDimitry Andric       (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   return MCDisassembler::Success;
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric 
getDecoderTable(uint64_t Size)4640b57cec5SDimitry Andric static const uint8_t *getDecoderTable(uint64_t Size) {
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   switch (Size) {
467349cc55cSDimitry Andric   case 2:
468349cc55cSDimitry Andric     return DecoderTable16;
469349cc55cSDimitry Andric   case 4:
470349cc55cSDimitry Andric     return DecoderTable32;
471349cc55cSDimitry Andric   default:
472349cc55cSDimitry Andric     llvm_unreachable("instructions must be 16 or 32-bits");
4730b57cec5SDimitry Andric   }
4740b57cec5SDimitry Andric }
4750b57cec5SDimitry Andric 
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CStream) const4760b57cec5SDimitry Andric DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
4770b57cec5SDimitry Andric                                              ArrayRef<uint8_t> Bytes,
4780b57cec5SDimitry Andric                                              uint64_t Address,
4790b57cec5SDimitry Andric                                              raw_ostream &CStream) const {
4800b57cec5SDimitry Andric   uint32_t Insn;
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   DecodeStatus Result;
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   // Try decode a 16-bit instruction.
4850b57cec5SDimitry Andric   {
4860b57cec5SDimitry Andric     Result = readInstruction16(Bytes, Address, Size, Insn);
4870b57cec5SDimitry Andric 
488349cc55cSDimitry Andric     if (Result == MCDisassembler::Fail)
489349cc55cSDimitry Andric       return MCDisassembler::Fail;
4900b57cec5SDimitry Andric 
491bdd1243dSDimitry Andric     // Try to decode AVRTiny instructions.
492*06c3fb27SDimitry Andric     if (STI.hasFeature(AVR::FeatureTinyEncoding)) {
493bdd1243dSDimitry Andric       Result = decodeInstruction(DecoderTableAVRTiny16, Instr, Insn, Address,
494bdd1243dSDimitry Andric                                  this, STI);
495bdd1243dSDimitry Andric       if (Result != MCDisassembler::Fail)
496bdd1243dSDimitry Andric         return Result;
497bdd1243dSDimitry Andric     }
498bdd1243dSDimitry Andric 
4990b57cec5SDimitry Andric     // Try to auto-decode a 16-bit instruction.
500349cc55cSDimitry Andric     Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
501349cc55cSDimitry Andric                                this, STI);
50281ad6265SDimitry Andric     if (Result != MCDisassembler::Fail)
50381ad6265SDimitry Andric       return Result;
5040b57cec5SDimitry Andric 
50581ad6265SDimitry Andric     // Try to decode to a load/store instruction. ST/LD need a specified
50681ad6265SDimitry Andric     // DecoderMethod, as they already have a specified PostEncoderMethod.
50781ad6265SDimitry Andric     Result = decodeLoadStore(Instr, Insn, Address, this);
5080b57cec5SDimitry Andric     if (Result != MCDisassembler::Fail)
5090b57cec5SDimitry Andric       return Result;
5100b57cec5SDimitry Andric   }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   // Try decode a 32-bit instruction.
5130b57cec5SDimitry Andric   {
5140b57cec5SDimitry Andric     Result = readInstruction32(Bytes, Address, Size, Insn);
5150b57cec5SDimitry Andric 
516349cc55cSDimitry Andric     if (Result == MCDisassembler::Fail)
517349cc55cSDimitry Andric       return MCDisassembler::Fail;
5180b57cec5SDimitry Andric 
519349cc55cSDimitry Andric     Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
520349cc55cSDimitry Andric                                this, STI);
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric     if (Result != MCDisassembler::Fail) {
5230b57cec5SDimitry Andric       return Result;
5240b57cec5SDimitry Andric     }
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric     return MCDisassembler::Fail;
5270b57cec5SDimitry Andric   }
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
53181ad6265SDimitry Andric                                    const MCDisassembler *Decoder);
532