Path: blob/main/contrib/llvm-project/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp
35293 views
//===- AVRDisassembler.cpp - Disassembler for AVR ---------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file is part of the AVR Disassembler.9//10//===----------------------------------------------------------------------===//1112#include "AVR.h"13#include "AVRRegisterInfo.h"14#include "AVRSubtarget.h"15#include "MCTargetDesc/AVRMCTargetDesc.h"16#include "TargetInfo/AVRTargetInfo.h"1718#include "llvm/ADT/DenseMap.h"19#include "llvm/ADT/STLExtras.h"2021#include "llvm/MC/MCAsmInfo.h"22#include "llvm/MC/MCContext.h"23#include "llvm/MC/MCDecoderOps.h"24#include "llvm/MC/MCDisassembler/MCDisassembler.h"25#include "llvm/MC/MCInst.h"26#include "llvm/MC/TargetRegistry.h"2728using namespace llvm;2930#define DEBUG_TYPE "avr-disassembler"3132typedef MCDisassembler::DecodeStatus DecodeStatus;3334namespace {3536/// A disassembler class for AVR.37class AVRDisassembler : public MCDisassembler {38public:39AVRDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)40: MCDisassembler(STI, Ctx) {}41virtual ~AVRDisassembler() = default;4243DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,44ArrayRef<uint8_t> Bytes, uint64_t Address,45raw_ostream &CStream) const override;46};47} // namespace4849static MCDisassembler *createAVRDisassembler(const Target &T,50const MCSubtargetInfo &STI,51MCContext &Ctx) {52return new AVRDisassembler(STI, Ctx);53}5455extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRDisassembler() {56// Register the disassembler.57TargetRegistry::RegisterMCDisassembler(getTheAVRTarget(),58createAVRDisassembler);59}6061static const uint16_t GPRDecoderTable[] = {62AVR::R0, AVR::R1, AVR::R2, AVR::R3, AVR::R4, AVR::R5, AVR::R6,63AVR::R7, AVR::R8, AVR::R9, AVR::R10, AVR::R11, AVR::R12, AVR::R13,64AVR::R14, AVR::R15, AVR::R16, AVR::R17, AVR::R18, AVR::R19, AVR::R20,65AVR::R21, AVR::R22, AVR::R23, AVR::R24, AVR::R25, AVR::R26, AVR::R27,66AVR::R28, AVR::R29, AVR::R30, AVR::R31,67};6869static DecodeStatus DecodeGPR8RegisterClass(MCInst &Inst, unsigned RegNo,70uint64_t Address,71const MCDisassembler *Decoder) {72if (RegNo > 31)73return MCDisassembler::Fail;7475unsigned Register = GPRDecoderTable[RegNo];76Inst.addOperand(MCOperand::createReg(Register));77return MCDisassembler::Success;78}7980static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo,81uint64_t Address,82const MCDisassembler *Decoder) {83if (RegNo > 15)84return MCDisassembler::Fail;8586unsigned Register = GPRDecoderTable[RegNo + 16];87Inst.addOperand(MCOperand::createReg(Register));88return MCDisassembler::Success;89}9091static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,92const MCDisassembler *Decoder);9394static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,95const MCDisassembler *Decoder);9697static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,98const MCDisassembler *Decoder);99100static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Insn,101uint64_t Address,102const MCDisassembler *Decoder);103104static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,105const MCDisassembler *Decoder);106107static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,108const MCDisassembler *Decoder);109110static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,111uint64_t Address,112const MCDisassembler *Decoder);113114static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,115uint64_t Address,116const MCDisassembler *Decoder);117118static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,119const MCDisassembler *Decoder);120121static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,122uint64_t Address,123const MCDisassembler *Decoder);124125static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,126const MCDisassembler *Decoder);127128static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address,129const MCDisassembler *Decoder);130131static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,132uint64_t Address,133const MCDisassembler *Decoder);134135static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,136uint64_t Address,137const MCDisassembler *Decoder);138139#include "AVRGenDisassemblerTables.inc"140141static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address,142const MCDisassembler *Decoder) {143unsigned addr = 0;144addr |= fieldFromInstruction(Insn, 0, 4);145addr |= fieldFromInstruction(Insn, 9, 2) << 4;146unsigned reg = fieldFromInstruction(Insn, 4, 5);147Inst.addOperand(MCOperand::createImm(addr));148if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==149MCDisassembler::Fail)150return MCDisassembler::Fail;151return MCDisassembler::Success;152}153154static DecodeStatus decodeFIORdA(MCInst &Inst, unsigned Insn, uint64_t Address,155const MCDisassembler *Decoder) {156unsigned addr = 0;157addr |= fieldFromInstruction(Insn, 0, 4);158addr |= fieldFromInstruction(Insn, 9, 2) << 4;159unsigned reg = fieldFromInstruction(Insn, 4, 5);160if (DecodeGPR8RegisterClass(Inst, reg, Address, Decoder) ==161MCDisassembler::Fail)162return MCDisassembler::Fail;163Inst.addOperand(MCOperand::createImm(addr));164return MCDisassembler::Success;165}166167static DecodeStatus decodeFIOBIT(MCInst &Inst, unsigned Insn, uint64_t Address,168const MCDisassembler *Decoder) {169unsigned addr = fieldFromInstruction(Insn, 3, 5);170unsigned b = fieldFromInstruction(Insn, 0, 3);171Inst.addOperand(MCOperand::createImm(addr));172Inst.addOperand(MCOperand::createImm(b));173return MCDisassembler::Success;174}175176static DecodeStatus decodeCallTarget(MCInst &Inst, unsigned Field,177uint64_t Address,178const MCDisassembler *Decoder) {179// Call targets need to be shifted left by one so this needs a custom180// decoder.181Inst.addOperand(MCOperand::createImm(Field << 1));182return MCDisassembler::Success;183}184185static DecodeStatus decodeFRd(MCInst &Inst, unsigned Insn, uint64_t Address,186const MCDisassembler *Decoder) {187unsigned d = fieldFromInstruction(Insn, 4, 5);188if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==189MCDisassembler::Fail)190return MCDisassembler::Fail;191return MCDisassembler::Success;192}193194static DecodeStatus decodeFLPMX(MCInst &Inst, unsigned Insn, uint64_t Address,195const MCDisassembler *Decoder) {196if (decodeFRd(Inst, Insn, Address, Decoder) == MCDisassembler::Fail)197return MCDisassembler::Fail;198Inst.addOperand(MCOperand::createReg(AVR::R31R30));199return MCDisassembler::Success;200}201202static DecodeStatus decodeFFMULRdRr(MCInst &Inst, unsigned Insn,203uint64_t Address,204const MCDisassembler *Decoder) {205unsigned d = fieldFromInstruction(Insn, 4, 3) + 16;206unsigned r = fieldFromInstruction(Insn, 0, 3) + 16;207if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==208MCDisassembler::Fail)209return MCDisassembler::Fail;210if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==211MCDisassembler::Fail)212return MCDisassembler::Fail;213return MCDisassembler::Success;214}215216static DecodeStatus decodeFMOVWRdRr(MCInst &Inst, unsigned Insn,217uint64_t Address,218const MCDisassembler *Decoder) {219unsigned r = fieldFromInstruction(Insn, 4, 4) * 2;220unsigned d = fieldFromInstruction(Insn, 0, 4) * 2;221if (DecodeGPR8RegisterClass(Inst, r, Address, Decoder) ==222MCDisassembler::Fail)223return MCDisassembler::Fail;224if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==225MCDisassembler::Fail)226return MCDisassembler::Fail;227return MCDisassembler::Success;228}229230static DecodeStatus decodeFWRdK(MCInst &Inst, unsigned Insn, uint64_t Address,231const MCDisassembler *Decoder) {232unsigned d = fieldFromInstruction(Insn, 4, 2) * 2 + 24; // starts at r24:r25233unsigned k = 0;234k |= fieldFromInstruction(Insn, 0, 4);235k |= fieldFromInstruction(Insn, 6, 2) << 4;236if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==237MCDisassembler::Fail)238return MCDisassembler::Fail;239if (DecodeGPR8RegisterClass(Inst, d, Address, Decoder) ==240MCDisassembler::Fail)241return MCDisassembler::Fail;242Inst.addOperand(MCOperand::createImm(k));243return MCDisassembler::Success;244}245246static DecodeStatus decodeFMUL2RdRr(MCInst &Inst, unsigned Insn,247uint64_t Address,248const MCDisassembler *Decoder) {249unsigned rd = fieldFromInstruction(Insn, 4, 4) + 16;250unsigned rr = fieldFromInstruction(Insn, 0, 4) + 16;251if (DecodeGPR8RegisterClass(Inst, rd, Address, Decoder) ==252MCDisassembler::Fail)253return MCDisassembler::Fail;254if (DecodeGPR8RegisterClass(Inst, rr, Address, Decoder) ==255MCDisassembler::Fail)256return MCDisassembler::Fail;257return MCDisassembler::Success;258}259260static DecodeStatus decodeMemri(MCInst &Inst, unsigned Insn, uint64_t Address,261const MCDisassembler *Decoder) {262// As in the EncoderMethod `AVRMCCodeEmitter::encodeMemri`, the memory263// address is encoded into 7-bit, in which bits 0-5 are the immediate offset,264// and the bit-6 is the pointer register bit (Z=0, Y=1).265if (Insn > 127)266return MCDisassembler::Fail;267268// Append the base register operand.269Inst.addOperand(270MCOperand::createReg((Insn & 0x40) ? AVR::R29R28 : AVR::R31R30));271// Append the immediate offset operand.272Inst.addOperand(MCOperand::createImm(Insn & 0x3f));273274return MCDisassembler::Success;275}276277static DecodeStatus decodeFBRk(MCInst &Inst, unsigned Insn, uint64_t Address,278const MCDisassembler *Decoder) {279// Decode the opcode.280switch (Insn & 0xf000) {281case 0xc000:282Inst.setOpcode(AVR::RJMPk);283break;284case 0xd000:285Inst.setOpcode(AVR::RCALLk);286break;287default: // Unknown relative branch instruction.288return MCDisassembler::Fail;289}290// Decode the relative offset.291int16_t Offset = ((int16_t)((Insn & 0xfff) << 4)) >> 3;292Inst.addOperand(MCOperand::createImm(Offset));293return MCDisassembler::Success;294}295296static DecodeStatus decodeCondBranch(MCInst &Inst, unsigned Insn,297uint64_t Address,298const MCDisassembler *Decoder) {299// These 8 instructions are not defined as aliases of BRBS/BRBC.300DenseMap<unsigned, unsigned> brInsts = {301{0x000, AVR::BRLOk}, {0x400, AVR::BRSHk}, {0x001, AVR::BREQk},302{0x401, AVR::BRNEk}, {0x002, AVR::BRMIk}, {0x402, AVR::BRPLk},303{0x004, AVR::BRLTk}, {0x404, AVR::BRGEk}};304305// Get the relative offset.306int16_t Offset = ((int16_t)((Insn & 0x3f8) << 6)) >> 8;307308// Search the instruction pattern.309auto NotAlias = [&Insn](const std::pair<unsigned, unsigned> &I) {310return (Insn & 0x407) != I.first;311};312llvm::partition(brInsts, NotAlias);313auto It = llvm::partition_point(brInsts, NotAlias);314315// Decode the instruction.316if (It != brInsts.end()) {317// This instruction is not an alias of BRBC/BRBS.318Inst.setOpcode(It->second);319Inst.addOperand(MCOperand::createImm(Offset));320} else {321// Fall back to an ordinary BRBS/BRBC.322Inst.setOpcode(Insn & 0x400 ? AVR::BRBCsk : AVR::BRBSsk);323Inst.addOperand(MCOperand::createImm(Insn & 7));324Inst.addOperand(MCOperand::createImm(Offset));325}326327return MCDisassembler::Success;328}329330static DecodeStatus decodeLoadStore(MCInst &Inst, unsigned Insn,331uint64_t Address,332const MCDisassembler *Decoder) {333// Get the register will be loaded or stored.334unsigned RegVal = GPRDecoderTable[(Insn >> 4) & 0x1f];335336// Decode LDD/STD with offset less than 8.337if ((Insn & 0xf000) == 0x8000) {338unsigned RegBase = (Insn & 0x8) ? AVR::R29R28 : AVR::R31R30;339unsigned Offset = Insn & 7; // We need not consider offset > 7.340if ((Insn & 0x200) == 0) { // Decode LDD.341Inst.setOpcode(AVR::LDDRdPtrQ);342Inst.addOperand(MCOperand::createReg(RegVal));343Inst.addOperand(MCOperand::createReg(RegBase));344Inst.addOperand(MCOperand::createImm(Offset));345} else { // Decode STD.346Inst.setOpcode(AVR::STDPtrQRr);347Inst.addOperand(MCOperand::createReg(RegBase));348Inst.addOperand(MCOperand::createImm(Offset));349Inst.addOperand(MCOperand::createReg(RegVal));350}351return MCDisassembler::Success;352}353354// Decode the following 14 instructions. Bit 9 indicates load(0) or store(1),355// bits 8~4 indicate the value register, bits 3-2 indicate the base address356// register (11-X, 10-Y, 00-Z), bits 1~0 indicate the mode (00-basic,357// 01-postinc, 10-predec).358// ST X, Rr : 1001 001r rrrr 1100359// ST X+, Rr : 1001 001r rrrr 1101360// ST -X, Rr : 1001 001r rrrr 1110361// ST Y+, Rr : 1001 001r rrrr 1001362// ST -Y, Rr : 1001 001r rrrr 1010363// ST Z+, Rr : 1001 001r rrrr 0001364// ST -Z, Rr : 1001 001r rrrr 0010365// LD Rd, X : 1001 000d dddd 1100366// LD Rd, X+ : 1001 000d dddd 1101367// LD Rd, -X : 1001 000d dddd 1110368// LD Rd, Y+ : 1001 000d dddd 1001369// LD Rd, -Y : 1001 000d dddd 1010370// LD Rd, Z+ : 1001 000d dddd 0001371// LD Rd, -Z : 1001 000d dddd 0010372if ((Insn & 0xfc00) != 0x9000 || (Insn & 0xf) == 0)373return MCDisassembler::Fail;374375// Get the base address register.376unsigned RegBase;377switch (Insn & 0xc) {378case 0xc:379RegBase = AVR::R27R26;380break;381case 0x8:382RegBase = AVR::R29R28;383break;384case 0x0:385RegBase = AVR::R31R30;386break;387default:388return MCDisassembler::Fail;389}390391// Set the opcode.392switch (Insn & 0x203) {393case 0x200:394Inst.setOpcode(AVR::STPtrRr);395Inst.addOperand(MCOperand::createReg(RegBase));396Inst.addOperand(MCOperand::createReg(RegVal));397return MCDisassembler::Success;398case 0x201:399Inst.setOpcode(AVR::STPtrPiRr);400break;401case 0x202:402Inst.setOpcode(AVR::STPtrPdRr);403break;404case 0:405Inst.setOpcode(AVR::LDRdPtr);406Inst.addOperand(MCOperand::createReg(RegVal));407Inst.addOperand(MCOperand::createReg(RegBase));408return MCDisassembler::Success;409case 1:410Inst.setOpcode(AVR::LDRdPtrPi);411break;412case 2:413Inst.setOpcode(AVR::LDRdPtrPd);414break;415default:416return MCDisassembler::Fail;417}418419// Build postinc/predec machine instructions.420if ((Insn & 0x200) == 0) { // This is a load instruction.421Inst.addOperand(MCOperand::createReg(RegVal));422Inst.addOperand(MCOperand::createReg(RegBase));423Inst.addOperand(MCOperand::createReg(RegBase));424} else { // This is a store instruction.425Inst.addOperand(MCOperand::createReg(RegBase));426Inst.addOperand(MCOperand::createReg(RegBase));427Inst.addOperand(MCOperand::createReg(RegVal));428// STPtrPiRr and STPtrPdRr have an extra immediate operand.429Inst.addOperand(MCOperand::createImm(1));430}431432return MCDisassembler::Success;433}434435static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,436uint64_t &Size, uint32_t &Insn) {437if (Bytes.size() < 2) {438Size = 0;439return MCDisassembler::Fail;440}441442Size = 2;443Insn = (Bytes[0] << 0) | (Bytes[1] << 8);444445return MCDisassembler::Success;446}447448static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,449uint64_t &Size, uint32_t &Insn) {450451if (Bytes.size() < 4) {452Size = 0;453return MCDisassembler::Fail;454}455456Size = 4;457Insn =458(Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);459460return MCDisassembler::Success;461}462463static const uint8_t *getDecoderTable(uint64_t Size) {464465switch (Size) {466case 2:467return DecoderTable16;468case 4:469return DecoderTable32;470default:471llvm_unreachable("instructions must be 16 or 32-bits");472}473}474475DecodeStatus AVRDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,476ArrayRef<uint8_t> Bytes,477uint64_t Address,478raw_ostream &CStream) const {479uint32_t Insn;480481DecodeStatus Result;482483// Try decode a 16-bit instruction.484{485Result = readInstruction16(Bytes, Address, Size, Insn);486487if (Result == MCDisassembler::Fail)488return MCDisassembler::Fail;489490// Try to decode AVRTiny instructions.491if (STI.hasFeature(AVR::FeatureTinyEncoding)) {492Result = decodeInstruction(DecoderTableAVRTiny16, Instr, Insn, Address,493this, STI);494if (Result != MCDisassembler::Fail)495return Result;496}497498// Try to auto-decode a 16-bit instruction.499Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,500this, STI);501if (Result != MCDisassembler::Fail)502return Result;503504// Try to decode to a load/store instruction. ST/LD need a specified505// DecoderMethod, as they already have a specified PostEncoderMethod.506Result = decodeLoadStore(Instr, Insn, Address, this);507if (Result != MCDisassembler::Fail)508return Result;509}510511// Try decode a 32-bit instruction.512{513Result = readInstruction32(Bytes, Address, Size, Insn);514515if (Result == MCDisassembler::Fail)516return MCDisassembler::Fail;517518Result = decodeInstruction(getDecoderTable(Size), Instr, Insn, Address,519this, STI);520521if (Result != MCDisassembler::Fail) {522return Result;523}524525return MCDisassembler::Fail;526}527}528529typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned insn, uint64_t Address,530const MCDisassembler *Decoder);531532533