1479a13c0SDylan McKay //===- AVRDisassembler.cpp - Disassembler for AVR ---------------*- C++ -*-===//
2479a13c0SDylan McKay //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6479a13c0SDylan McKay //
7479a13c0SDylan McKay //===----------------------------------------------------------------------===//
8479a13c0SDylan McKay //
9479a13c0SDylan McKay // This file is part of the AVR Disassembler.
10479a13c0SDylan McKay //
11479a13c0SDylan McKay //===----------------------------------------------------------------------===//
12479a13c0SDylan McKay
13479a13c0SDylan McKay #include "AVR.h"
14479a13c0SDylan McKay #include "AVRRegisterInfo.h"
15479a13c0SDylan McKay #include "AVRSubtarget.h"
16479a13c0SDylan McKay #include "MCTargetDesc/AVRMCTargetDesc.h"
17e982b420SRichard Trieu #include "TargetInfo/AVRTargetInfo.h"
18479a13c0SDylan McKay
196bda14b3SChandler Carruth #include "llvm/MC/MCAsmInfo.h"
206bda14b3SChandler Carruth #include "llvm/MC/MCContext.h"
21*c644488aSSheng #include "llvm/MC/MCDecoderOps.h"
22479a13c0SDylan McKay #include "llvm/MC/MCDisassembler/MCDisassembler.h"
23479a13c0SDylan McKay #include "llvm/MC/MCInst.h"
2489b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
25479a13c0SDylan McKay
26479a13c0SDylan McKay using namespace llvm;
27479a13c0SDylan McKay
28479a13c0SDylan McKay #define DEBUG_TYPE "avr-disassembler"
29479a13c0SDylan McKay
30479a13c0SDylan McKay typedef MCDisassembler::DecodeStatus DecodeStatus;
31479a13c0SDylan McKay
32479a13c0SDylan McKay namespace {
33479a13c0SDylan McKay
34479a13c0SDylan McKay /// A disassembler class for AVR.
35479a13c0SDylan McKay class AVRDisassembler : public MCDisassembler {
36479a13c0SDylan McKay public:
AVRDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)37479a13c0SDylan McKay AVRDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
38479a13c0SDylan McKay : MCDisassembler(STI, Ctx) {}
393a3cb929SKazu Hirata virtual ~AVRDisassembler() = default;
40479a13c0SDylan McKay
41479a13c0SDylan McKay DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
42479a13c0SDylan McKay ArrayRef<uint8_t> Bytes, uint64_t Address,
43479a13c0SDylan McKay raw_ostream &CStream) const override;
44479a13c0SDylan McKay };
455449d2daSShivam Gupta } // namespace
46479a13c0SDylan McKay
createAVRDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)47479a13c0SDylan McKay static MCDisassembler *createAVRDisassembler(const Target &T,
48479a13c0SDylan McKay const MCSubtargetInfo &STI,
49479a13c0SDylan McKay MCContext &Ctx) {
50479a13c0SDylan McKay return new AVRDisassembler(STI, Ctx);
51479a13c0SDylan McKay }
52479a13c0SDylan McKay
LLVMInitializeAVRDisassembler()530dbcb363STom Stellard extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRDisassembler() {
54479a13c0SDylan McKay // Register the disassembler.
5500009d48SDylan McKay TargetRegistry::RegisterMCDisassembler(getTheAVRTarget(),
56479a13c0SDylan McKay createAVRDisassembler);
57479a13c0SDylan McKay }
58479a13c0SDylan McKay
595b2046c9SAyke van Laethem static const uint16_t GPRDecoderTable[] = {
605449d2daSShivam Gupta AVR::R0, AVR::R1, AVR::R2, AVR::R3, AVR::R4, AVR::R5, AVR::R6,
615449d2daSShivam Gupta AVR::R7, AVR::R8, AVR::R9, AVR::R10, AVR::R11, AVR::R12, AVR::R13,
625449d2daSShivam Gupta AVR::R14, AVR::R15, AVR::R16, AVR::R17, AVR::R18, AVR::R19, AVR::R20,
635449d2daSShivam Gupta AVR::R21, AVR::R22, AVR::R23, AVR::R24, AVR::R25, AVR::R26, AVR::R27,
645b2046c9SAyke van Laethem AVR::R28, AVR::R29, AVR::R30, AVR::R31,
655b2046c9SAyke van Laethem };
665b2046c9SAyke van Laethem
DecodeGPR8RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const MCDisassembler * Decoder)67479a13c0SDylan McKay static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo,
685449d2daSShivam Gupta uint64_t Address,
694ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
705b2046c9SAyke van Laethem if (RegNo > 31)
715b2046c9SAyke van Laethem return MCDisassembler::Fail;
725b2046c9SAyke van Laethem
735b2046c9SAyke van Laethem unsigned Register = GPRDecoderTable[RegNo];
745b2046c9SAyke van Laethem Inst.addOperand(MCOperand::createReg(Register));
75479a13c0SDylan McKay return MCDisassembler::Success;
76479a13c0SDylan McKay }
77479a13c0SDylan McKay
DecodeLD8RegisterClass(MCInst & Inst,unsigned RegNo,uint64_t Address,const MCDisassembler * Decoder)78479a13c0SDylan McKay static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo,
795449d2daSShivam Gupta uint64_t Address,
804ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
815b2046c9SAyke van Laethem if (RegNo > 15)
825b2046c9SAyke van Laethem return MCDisassembler::Fail;
835b2046c9SAyke van Laethem
845b2046c9SAyke van Laethem unsigned Register = GPRDecoderTable[RegNo + 16];
855b2046c9SAyke van Laethem Inst.addOperand(MCOperand::createReg(Register));
86479a13c0SDylan McKay return MCDisassembler::Success;
87479a13c0SDylan McKay }
88479a13c0SDylan McKay
895449d2daSShivam Gupta static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,
904ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
911ba78097SAyke van Laethem
925449d2daSShivam Gupta static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,
934ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
941ba78097SAyke van Laethem
955449d2daSShivam Gupta static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,
964ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
971ba78097SAyke van Laethem
9815bf42d5SAyke van Laethem static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Insn,
994ae9745aSMaksim Panchenko uint64_t Address,
1004ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
10115bf42d5SAyke van Laethem
1025449d2daSShivam Gupta static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,
1034ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
10401c2209dSAyke van Laethem
1055449d2daSShivam Gupta static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,
1064ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
1079f09c29fSAyke van Laethem
108ec9efb85SAyke van Laethem static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
1094ae9745aSMaksim Panchenko uint64_t Address,
1104ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
111ec9efb85SAyke van Laethem
112eac4a601SAyke van Laethem static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
1134ae9745aSMaksim Panchenko uint64_t Address,
1144ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
115eac4a601SAyke van Laethem
1165449d2daSShivam Gupta static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,
1174ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
118eac4a601SAyke van Laethem
119ec9efb85SAyke van Laethem static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
1204ae9745aSMaksim Panchenko uint64_t Address,
1214ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
122ec9efb85SAyke van Laethem
123cef2739dSBen Shi static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
124cef2739dSBen Shi const MCDisassembler *Decoder);
125cef2739dSBen Shi
126cef2739dSBen Shi static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
127cef2739dSBen Shi uint64_t Address,
128cef2739dSBen Shi const MCDisassembler *Decoder);
129cef2739dSBen Shi
130479a13c0SDylan McKay #include "AVRGenDisassemblerTables.inc"
131479a13c0SDylan McKay
decodeFIOARr(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)1325449d2daSShivam Gupta static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,
1334ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1341ba78097SAyke van Laethem unsigned addr = 0;
1351ba78097SAyke van Laethem addr |= fieldFromInstruction(Insn, 0, 4);
1361ba78097SAyke van Laethem addr |= fieldFromInstruction(Insn, 9, 2) << 4;
1371ba78097SAyke van Laethem unsigned reg = fieldFromInstruction(Insn, 4, 5);
1381ba78097SAyke van Laethem Inst.addOperand(MCOperand::createImm(addr));
1395449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
1405449d2daSShivam Gupta MCDisassembler::Fail)
1411ba78097SAyke van Laethem return MCDisassembler::Fail;
1421ba78097SAyke van Laethem return MCDisassembler::Success;
1431ba78097SAyke van Laethem }
1441ba78097SAyke van Laethem
decodeFIORdA(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)1455449d2daSShivam Gupta static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,
1464ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1471ba78097SAyke van Laethem unsigned addr = 0;
1481ba78097SAyke van Laethem addr |= fieldFromInstruction(Insn, 0, 4);
1491ba78097SAyke van Laethem addr |= fieldFromInstruction(Insn, 9, 2) << 4;
1501ba78097SAyke van Laethem unsigned reg = fieldFromInstruction(Insn, 4, 5);
1515449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==
1525449d2daSShivam Gupta MCDisassembler::Fail)
1531ba78097SAyke van Laethem return MCDisassembler::Fail;
1541ba78097SAyke van Laethem Inst.addOperand(MCOperand::createImm(addr));
1551ba78097SAyke van Laethem return MCDisassembler::Success;
1561ba78097SAyke van Laethem }
1571ba78097SAyke van Laethem
decodeFIOBIT(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)1585449d2daSShivam Gupta static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,
1594ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1601ba78097SAyke van Laethem unsigned addr = fieldFromInstruction(Insn, 3, 5);
1611ba78097SAyke van Laethem unsigned b = fieldFromInstruction(Insn, 0, 3);
1621ba78097SAyke van Laethem Inst.addOperand(MCOperand::createImm(addr));
1631ba78097SAyke van Laethem Inst.addOperand(MCOperand::createImm(b));
1641ba78097SAyke van Laethem return MCDisassembler::Success;
1651ba78097SAyke van Laethem }
1661ba78097SAyke van Laethem
decodeCallTarget(MCInst & Inst,unsigned Field,uint64_t Address,const MCDisassembler * Decoder)16715bf42d5SAyke van Laethem static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Field,
1684ae9745aSMaksim Panchenko uint64_t Address,
1694ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
17015bf42d5SAyke van Laethem // Call targets need to be shifted left by one so this needs a custom
17115bf42d5SAyke van Laethem // decoder.
17215bf42d5SAyke van Laethem Inst.addOperand(MCOperand::createImm(Field << 1));
17315bf42d5SAyke van Laethem return MCDisassembler::Success;
17415bf42d5SAyke van Laethem }
17515bf42d5SAyke van Laethem
decodeFRd(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)1765449d2daSShivam Gupta static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,
1774ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
17801c2209dSAyke van Laethem unsigned d = fieldFromInstruction(Insn, 4, 5);
1795449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
1805449d2daSShivam Gupta MCDisassembler::Fail)
18101c2209dSAyke van Laethem return MCDisassembler::Fail;
18201c2209dSAyke van Laethem return MCDisassembler::Success;
18301c2209dSAyke van Laethem }
18401c2209dSAyke van Laethem
decodeFLPMX(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)1855449d2daSShivam Gupta static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,
1864ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
1879f09c29fSAyke van Laethem if (decodeFRd(Inst, Insn, Address, Decoder) == MCDisassembler::Fail)
1889f09c29fSAyke van Laethem return MCDisassembler::Fail;
1899f09c29fSAyke van Laethem Inst.addOperand(MCOperand::createReg(AVR::R31R30));
1909f09c29fSAyke van Laethem return MCDisassembler::Success;
1919f09c29fSAyke van Laethem }
1929f09c29fSAyke van Laethem
decodeFFMULRdRr(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)193ec9efb85SAyke van Laethem static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,
1944ae9745aSMaksim Panchenko uint64_t Address,
1954ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
196ec9efb85SAyke van Laethem unsigned d = fieldFromInstruction(Insn, 4, 3) + 16;
197ec9efb85SAyke van Laethem unsigned r = fieldFromInstruction(Insn, 0, 3) + 16;
1985449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
1995449d2daSShivam Gupta MCDisassembler::Fail)
200ec9efb85SAyke van Laethem return MCDisassembler::Fail;
2015449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
2025449d2daSShivam Gupta MCDisassembler::Fail)
203ec9efb85SAyke van Laethem return MCDisassembler::Fail;
204ec9efb85SAyke van Laethem return MCDisassembler::Success;
205ec9efb85SAyke van Laethem }
206ec9efb85SAyke van Laethem
decodeFMOVWRdRr(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)207eac4a601SAyke van Laethem static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,
2084ae9745aSMaksim Panchenko uint64_t Address,
2094ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
210eac4a601SAyke van Laethem unsigned r = fieldFromInstruction(Insn, 4, 4) * 2;
211eac4a601SAyke van Laethem unsigned d = fieldFromInstruction(Insn, 0, 4) * 2;
2125449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==
2135449d2daSShivam Gupta MCDisassembler::Fail)
214eac4a601SAyke van Laethem return MCDisassembler::Fail;
2155449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
2165449d2daSShivam Gupta MCDisassembler::Fail)
217eac4a601SAyke van Laethem return MCDisassembler::Fail;
218eac4a601SAyke van Laethem return MCDisassembler::Success;
219eac4a601SAyke van Laethem }
220eac4a601SAyke van Laethem
decodeFWRdK(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)2215449d2daSShivam Gupta static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,
2224ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
223eac4a601SAyke van Laethem unsigned d = fieldFromInstruction(Insn, 4, 2) * 2 + 24; // starts at r24:r25
224eac4a601SAyke van Laethem unsigned k = 0;
225eac4a601SAyke van Laethem k |= fieldFromInstruction(Insn, 0, 4);
226eac4a601SAyke van Laethem k |= fieldFromInstruction(Insn, 6, 2) << 4;
2275449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
2285449d2daSShivam Gupta MCDisassembler::Fail)
229eac4a601SAyke van Laethem return MCDisassembler::Fail;
2305449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==
2315449d2daSShivam Gupta MCDisassembler::Fail)
232eac4a601SAyke van Laethem return MCDisassembler::Fail;
233eac4a601SAyke van Laethem Inst.addOperand(MCOperand::createImm(k));
234eac4a601SAyke van Laethem return MCDisassembler::Success;
235eac4a601SAyke van Laethem }
236eac4a601SAyke van Laethem
decodeFMUL2RdRr(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)237ec9efb85SAyke van Laethem static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,
2384ae9745aSMaksim Panchenko uint64_t Address,
2394ae9745aSMaksim Panchenko const MCDisassembler *Decoder) {
240ec9efb85SAyke van Laethem unsigned rd = fieldFromInstruction(Insn, 4, 4) + 16;
241ec9efb85SAyke van Laethem unsigned rr = fieldFromInstruction(Insn, 0, 4) + 16;
2425449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, rd, Address, Decoder) ==
2435449d2daSShivam Gupta MCDisassembler::Fail)
244ec9efb85SAyke van Laethem return MCDisassembler::Fail;
2455449d2daSShivam Gupta if (DecodeGPR8RegisterClass(Inst, rr, Address, Decoder) ==
2465449d2daSShivam Gupta MCDisassembler::Fail)
247ec9efb85SAyke van Laethem return MCDisassembler::Fail;
248ec9efb85SAyke van Laethem return MCDisassembler::Success;
249ec9efb85SAyke van Laethem }
250ec9efb85SAyke van Laethem
decodeMemri(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)251cef2739dSBen Shi static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,
252cef2739dSBen Shi const MCDisassembler *Decoder) {
253cef2739dSBen Shi // As in the EncoderMethod `AVRMCCodeEmitter::encodeMemri`, the memory
254cef2739dSBen Shi // address is encoded into 7-bit, in which bits 0-5 are the immediate offset,
255cef2739dSBen Shi // and the bit-6 is the pointer register bit (Z=0, Y=1).
256cef2739dSBen Shi if (Insn > 127)
257cef2739dSBen Shi return MCDisassembler::Fail;
258cef2739dSBen Shi
259cef2739dSBen Shi // Append the base register operand.
260cef2739dSBen Shi Inst.addOperand(
261cef2739dSBen Shi MCOperand::createReg((Insn & 0x40) ? AVR::R29R28 : AVR::R31R30));
262cef2739dSBen Shi // Append the immediate offset operand.
263cef2739dSBen Shi Inst.addOperand(MCOperand::createImm(Insn & 0x3f));
264cef2739dSBen Shi
265cef2739dSBen Shi return MCDisassembler::Success;
266cef2739dSBen Shi }
267cef2739dSBen Shi
decodeLoadStore(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)268cef2739dSBen Shi static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,
269cef2739dSBen Shi uint64_t Address,
270cef2739dSBen Shi const MCDisassembler *Decoder) {
271b1dcd6baSBen Shi // Get the register will be loaded or stored.
272b1dcd6baSBen Shi unsigned RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];
273b1dcd6baSBen Shi
274cef2739dSBen Shi // Decode LDD/STD with offset less than 8.
275cef2739dSBen Shi if ((Insn & 0xf000) == 0x8000) {
276cef2739dSBen Shi unsigned RegBase = (Insn & 0x8) ? AVR::R29R28 : AVR::R31R30;
277cef2739dSBen Shi unsigned Offset = Insn & 7; // We need not consider offset > 7.
278cef2739dSBen Shi if ((Insn & 0x200) == 0) { // Decode LDD.
279cef2739dSBen Shi Inst.setOpcode(AVR::LDDRdPtrQ);
280cef2739dSBen Shi Inst.addOperand(MCOperand::createReg(RegVal));
281cef2739dSBen Shi Inst.addOperand(MCOperand::createReg(RegBase));
282cef2739dSBen Shi Inst.addOperand(MCOperand::createImm(Offset));
283cef2739dSBen Shi } else { // Decode STD.
284cef2739dSBen Shi Inst.setOpcode(AVR::STDPtrQRr);
285cef2739dSBen Shi Inst.addOperand(MCOperand::createReg(RegBase));
286cef2739dSBen Shi Inst.addOperand(MCOperand::createImm(Offset));
287cef2739dSBen Shi Inst.addOperand(MCOperand::createReg(RegVal));
288cef2739dSBen Shi }
289cef2739dSBen Shi return MCDisassembler::Success;
290cef2739dSBen Shi }
291cef2739dSBen Shi
292b1dcd6baSBen Shi // Decode the following 14 instructions. Bit 9 indicates load(0) or store(1),
293b1dcd6baSBen Shi // bits 8~4 indicate the value register, bits 3-2 indicate the base address
294b1dcd6baSBen Shi // register (11-X, 10-Y, 00-Z), bits 1~0 indicate the mode (00-basic,
295b1dcd6baSBen Shi // 01-postinc, 10-predec).
296b1dcd6baSBen Shi // ST X, Rr : 1001 001r rrrr 1100
297b1dcd6baSBen Shi // ST X+, Rr : 1001 001r rrrr 1101
298b1dcd6baSBen Shi // ST -X, Rr : 1001 001r rrrr 1110
299b1dcd6baSBen Shi // ST Y+, Rr : 1001 001r rrrr 1001
300b1dcd6baSBen Shi // ST -Y, Rr : 1001 001r rrrr 1010
301b1dcd6baSBen Shi // ST Z+, Rr : 1001 001r rrrr 0001
302b1dcd6baSBen Shi // ST -Z, Rr : 1001 001r rrrr 0010
303b1dcd6baSBen Shi // LD Rd, X : 1001 000d dddd 1100
304b1dcd6baSBen Shi // LD Rd, X+ : 1001 000d dddd 1101
305b1dcd6baSBen Shi // LD Rd, -X : 1001 000d dddd 1110
306b1dcd6baSBen Shi // LD Rd, Y+ : 1001 000d dddd 1001
307b1dcd6baSBen Shi // LD Rd, -Y : 1001 000d dddd 1010
308b1dcd6baSBen Shi // LD Rd, Z+ : 1001 000d dddd 0001
309b1dcd6baSBen Shi // LD Rd, -Z : 1001 000d dddd 0010
310b1dcd6baSBen Shi if ((Insn & 0xfc00) != 0x9000 || (Insn & 0xf) == 0)
311cef2739dSBen Shi return MCDisassembler::Fail;
312b1dcd6baSBen Shi
313b1dcd6baSBen Shi // Get the base address register.
314b1dcd6baSBen Shi unsigned RegBase;
315b1dcd6baSBen Shi switch (Insn & 0xc) {
316b1dcd6baSBen Shi case 0xc:
317b1dcd6baSBen Shi RegBase = AVR::R27R26;
318b1dcd6baSBen Shi break;
319b1dcd6baSBen Shi case 0x8:
320b1dcd6baSBen Shi RegBase = AVR::R29R28;
321b1dcd6baSBen Shi break;
322b1dcd6baSBen Shi case 0x0:
323b1dcd6baSBen Shi RegBase = AVR::R31R30;
324b1dcd6baSBen Shi break;
325b1dcd6baSBen Shi default:
326b1dcd6baSBen Shi return MCDisassembler::Fail;
327b1dcd6baSBen Shi }
328b1dcd6baSBen Shi
329b1dcd6baSBen Shi // Set the opcode.
330b1dcd6baSBen Shi switch (Insn & 0x203) {
331b1dcd6baSBen Shi case 0x200:
332b1dcd6baSBen Shi Inst.setOpcode(AVR::STPtrRr);
333b1dcd6baSBen Shi Inst.addOperand(MCOperand::createReg(RegBase));
334b1dcd6baSBen Shi Inst.addOperand(MCOperand::createReg(RegVal));
335b1dcd6baSBen Shi return MCDisassembler::Success;
336b1dcd6baSBen Shi case 0x201:
337b1dcd6baSBen Shi Inst.setOpcode(AVR::STPtrPiRr);
338b1dcd6baSBen Shi break;
339b1dcd6baSBen Shi case 0x202:
340b1dcd6baSBen Shi Inst.setOpcode(AVR::STPtrPdRr);
341b1dcd6baSBen Shi break;
342b1dcd6baSBen Shi case 0:
343b1dcd6baSBen Shi Inst.setOpcode(AVR::LDRdPtr);
344b1dcd6baSBen Shi Inst.addOperand(MCOperand::createReg(RegVal));
345b1dcd6baSBen Shi Inst.addOperand(MCOperand::createReg(RegBase));
346b1dcd6baSBen Shi return MCDisassembler::Success;
347b1dcd6baSBen Shi case 1:
348b1dcd6baSBen Shi Inst.setOpcode(AVR::LDRdPtrPi);
349b1dcd6baSBen Shi break;
350b1dcd6baSBen Shi case 2:
351b1dcd6baSBen Shi Inst.setOpcode(AVR::LDRdPtrPd);
352b1dcd6baSBen Shi break;
353b1dcd6baSBen Shi default:
354b1dcd6baSBen Shi return MCDisassembler::Fail;
355b1dcd6baSBen Shi }
356b1dcd6baSBen Shi
357b1dcd6baSBen Shi // Build postinc/predec machine instructions.
358b1dcd6baSBen Shi if ((Insn & 0x200) == 0) { // This is a load instruction.
359b1dcd6baSBen Shi Inst.addOperand(MCOperand::createReg(RegVal));
360b1dcd6baSBen Shi Inst.addOperand(MCOperand::createReg(RegBase));
361b1dcd6baSBen Shi Inst.addOperand(MCOperand::createReg(RegBase));
362b1dcd6baSBen Shi } else { // This is a store instruction.
363b1dcd6baSBen Shi Inst.addOperand(MCOperand::createReg(RegBase));
364b1dcd6baSBen Shi Inst.addOperand(MCOperand::createReg(RegBase));
365b1dcd6baSBen Shi Inst.addOperand(MCOperand::createReg(RegVal));
366b1dcd6baSBen Shi // STPtrPiRr and STPtrPdRr have an extra immediate operand.
367b1dcd6baSBen Shi Inst.addOperand(MCOperand::createImm(1));
368b1dcd6baSBen Shi }
369b1dcd6baSBen Shi
370b1dcd6baSBen Shi return MCDisassembler::Success;
371cef2739dSBen Shi }
372cef2739dSBen Shi
readInstruction16(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)373479a13c0SDylan McKay static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
374479a13c0SDylan McKay uint64_t &Size, uint32_t &Insn) {
375479a13c0SDylan McKay if (Bytes.size() < 2) {
376479a13c0SDylan McKay Size = 0;
377479a13c0SDylan McKay return MCDisassembler::Fail;
378479a13c0SDylan McKay }
379479a13c0SDylan McKay
380479a13c0SDylan McKay Size = 2;
381479a13c0SDylan McKay Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
382479a13c0SDylan McKay
383479a13c0SDylan McKay return MCDisassembler::Success;
384479a13c0SDylan McKay }
385479a13c0SDylan McKay
readInstruction32(ArrayRef<uint8_t> Bytes,uint64_t Address,uint64_t & Size,uint32_t & Insn)386479a13c0SDylan McKay static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
387479a13c0SDylan McKay uint64_t &Size, uint32_t &Insn) {
388479a13c0SDylan McKay
389479a13c0SDylan McKay if (Bytes.size() < 4) {
390479a13c0SDylan McKay Size = 0;
391479a13c0SDylan McKay return MCDisassembler::Fail;
392479a13c0SDylan McKay }
393479a13c0SDylan McKay
394479a13c0SDylan McKay Size = 4;
3955449d2daSShivam Gupta Insn =
3965449d2daSShivam Gupta (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
397479a13c0SDylan McKay
398479a13c0SDylan McKay return MCDisassembler::Success;
399479a13c0SDylan McKay }
400479a13c0SDylan McKay
getDecoderTable(uint64_t Size)401479a13c0SDylan McKay static const uint8_t *getDecoderTable(uint64_t Size) {
402479a13c0SDylan McKay
403479a13c0SDylan McKay switch (Size) {
4045449d2daSShivam Gupta case 2:
4055449d2daSShivam Gupta return DecoderTable16;
4065449d2daSShivam Gupta case 4:
4075449d2daSShivam Gupta return DecoderTable32;
4085449d2daSShivam Gupta default:
4095449d2daSShivam Gupta llvm_unreachable("instructions must be 16 or 32-bits");
410479a13c0SDylan McKay }
411479a13c0SDylan McKay }
412479a13c0SDylan McKay
getInstruction(MCInst & Instr,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CStream) const413479a13c0SDylan McKay DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
414479a13c0SDylan McKay ArrayRef<uint8_t> Bytes,
415479a13c0SDylan McKay uint64_t Address,
416479a13c0SDylan McKay raw_ostream &CStream) const {
417479a13c0SDylan McKay uint32_t Insn;
418479a13c0SDylan McKay
419479a13c0SDylan McKay DecodeStatus Result;
420479a13c0SDylan McKay
421479a13c0SDylan McKay // Try decode a 16-bit instruction.
422479a13c0SDylan McKay {
423479a13c0SDylan McKay Result = readInstruction16(Bytes, Address, Size, Insn);
424479a13c0SDylan McKay
4255449d2daSShivam Gupta if (Result == MCDisassembler::Fail)
4265449d2daSShivam Gupta return MCDisassembler::Fail;
427479a13c0SDylan McKay
428479a13c0SDylan McKay // Try to auto-decode a 16-bit instruction.
4295449d2daSShivam Gupta Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
4305449d2daSShivam Gupta this, STI);
431b1dcd6baSBen Shi if (Result != MCDisassembler::Fail)
432b1dcd6baSBen Shi return Result;
433479a13c0SDylan McKay
434b1dcd6baSBen Shi // Try to decode to a load/store instruction. ST/LD need a specified
435b1dcd6baSBen Shi // DecoderMethod, as they already have a specified PostEncoderMethod.
436b1dcd6baSBen Shi Result = decodeLoadStore(Instr, Insn, Address, this);
437479a13c0SDylan McKay if (Result != MCDisassembler::Fail)
438479a13c0SDylan McKay return Result;
439479a13c0SDylan McKay }
440479a13c0SDylan McKay
441479a13c0SDylan McKay // Try decode a 32-bit instruction.
442479a13c0SDylan McKay {
443479a13c0SDylan McKay Result = readInstruction32(Bytes, Address, Size, Insn);
444479a13c0SDylan McKay
4455449d2daSShivam Gupta if (Result == MCDisassembler::Fail)
4465449d2daSShivam Gupta return MCDisassembler::Fail;
447479a13c0SDylan McKay
4485449d2daSShivam Gupta Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,
4495449d2daSShivam Gupta this, STI);
450479a13c0SDylan McKay
451479a13c0SDylan McKay if (Result != MCDisassembler::Fail) {
452479a13c0SDylan McKay return Result;
453479a13c0SDylan McKay }
454479a13c0SDylan McKay
455479a13c0SDylan McKay return MCDisassembler::Fail;
456479a13c0SDylan McKay }
457479a13c0SDylan McKay }
458479a13c0SDylan McKay
459479a13c0SDylan McKay typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,
4604ae9745aSMaksim Panchenko const MCDisassembler *Decoder);
461