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