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