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