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