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