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 /// \brief 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 /// \brief 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 readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address, 71 uint64_t &Size, uint32_t &Insn) { 72 Size = 2; 73 Insn = (Bytes[0] << 0) | (Bytes[1] << 8); 74 return true; 75 } 76 77 static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &, unsigned, 78 uint64_t, const void *); 79 80 static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &, unsigned, 81 uint64_t, const void *); 82 83 static MCDisassembler::DecodeStatus 84 DecodeBranchTargetS9(MCInst &, unsigned, uint64_t, const void *); 85 86 static MCDisassembler::DecodeStatus 87 DecodeBranchTargetS21(MCInst &, unsigned, uint64_t, const void *); 88 89 static MCDisassembler::DecodeStatus 90 DecodeBranchTargetS25(MCInst &, unsigned, uint64_t, const void *); 91 92 static MCDisassembler::DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, 93 const void *); 94 95 static MCDisassembler::DecodeStatus 96 DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t, const void *); 97 98 static MCDisassembler::DecodeStatus 99 DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t, const void *); 100 101 static MCDisassembler::DecodeStatus 102 DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t, const void *); 103 104 static const uint16_t GPR32DecoderTable[] = { 105 ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6, 106 ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13, 107 ARC::R14, ARC::R15, ARC::R16, ARC::R17, ARC::R18, ARC::R19, ARC::R20, 108 ARC::R21, ARC::R22, ARC::R23, ARC::R24, ARC::R25, ARC::GP, ARC::FP, 109 ARC::SP, ARC::ILINK, ARC::R30, ARC::BLINK}; 110 111 static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo, 112 uint64_t Address, 113 const void *Decoder) { 114 if (RegNo >= 32) { 115 DEBUG(dbgs() << "Not a GPR32 register."); 116 return MCDisassembler::Fail; 117 } 118 unsigned Reg = GPR32DecoderTable[RegNo]; 119 Inst.addOperand(MCOperand::createReg(Reg)); 120 return MCDisassembler::Success; 121 } 122 123 #include "ARCGenDisassemblerTables.inc" 124 125 static unsigned decodeCField(unsigned Insn) { 126 return fieldFromInstruction(Insn, 6, 6); 127 } 128 129 static unsigned decodeBField(unsigned Insn) { 130 return (fieldFromInstruction(Insn, 12, 3) << 3) | 131 fieldFromInstruction(Insn, 24, 3); 132 } 133 134 static unsigned decodeAField(unsigned Insn) { 135 return fieldFromInstruction(Insn, 0, 6); 136 } 137 138 static MCDisassembler::DecodeStatus 139 DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Dec) { 140 // We have the 9-bit immediate in the low bits, 6-bit register in high bits. 141 unsigned S9 = Insn & 0x1ff; 142 unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9; 143 DecodeGPR32RegisterClass(Inst, R, Address, Dec); 144 Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9))); 145 return MCDisassembler::Success; 146 } 147 148 static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &Inst, 149 unsigned InsnS9, 150 uint64_t Address, 151 const void *Decoder) { 152 Inst.addOperand(MCOperand::createImm(SignExtend32<9>(0x1ff & InsnS9))); 153 return MCDisassembler::Success; 154 } 155 156 static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &Inst, 157 unsigned InsnS12, 158 uint64_t Address, 159 const void *Decoder) { 160 Inst.addOperand(MCOperand::createImm(SignExtend32<12>(0xfff & InsnS12))); 161 return MCDisassembler::Success; 162 } 163 164 static MCDisassembler::DecodeStatus DecodeBranchTargetS9(MCInst &Inst, 165 unsigned S, 166 uint64_t Address, 167 const void *Decoder) { 168 Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S))); 169 return MCDisassembler::Success; 170 } 171 172 static MCDisassembler::DecodeStatus DecodeBranchTargetS21(MCInst &Inst, 173 unsigned S, 174 uint64_t Address, 175 const void *Decoder) { 176 Inst.addOperand(MCOperand::createImm(SignExtend32<21>(S))); 177 return MCDisassembler::Success; 178 } 179 180 static MCDisassembler::DecodeStatus DecodeBranchTargetS25(MCInst &Inst, 181 unsigned S, 182 uint64_t Address, 183 const void *Decoder) { 184 Inst.addOperand(MCOperand::createImm(SignExtend32<25>(S))); 185 return MCDisassembler::Success; 186 } 187 188 static MCDisassembler::DecodeStatus 189 DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address, 190 const void *Decoder) { 191 unsigned SrcC, DstB, LImm; 192 DstB = decodeBField(Insn); 193 if (DstB != 62) { 194 DEBUG(dbgs() << "Decoding StLImm found non-limm register."); 195 return MCDisassembler::Fail; 196 } 197 SrcC = decodeCField(Insn); 198 DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder); 199 LImm = (Insn >> 32); 200 Inst.addOperand(MCOperand::createImm(LImm)); 201 Inst.addOperand(MCOperand::createImm(0)); 202 return MCDisassembler::Success; 203 } 204 205 static MCDisassembler::DecodeStatus 206 DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address, 207 const void *Decoder) { 208 unsigned DstA, SrcB, LImm; 209 DEBUG(dbgs() << "Decoding LdLImm:\n"); 210 SrcB = decodeBField(Insn); 211 if (SrcB != 62) { 212 DEBUG(dbgs() << "Decoding LdLImm found non-limm register."); 213 return MCDisassembler::Fail; 214 } 215 DstA = decodeAField(Insn); 216 DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder); 217 LImm = (Insn >> 32); 218 Inst.addOperand(MCOperand::createImm(LImm)); 219 Inst.addOperand(MCOperand::createImm(0)); 220 return MCDisassembler::Success; 221 } 222 223 static MCDisassembler::DecodeStatus 224 DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address, 225 const void *Decoder) { 226 unsigned DstA, SrcB; 227 DEBUG(dbgs() << "Decoding LdRLimm\n"); 228 DstA = decodeAField(Insn); 229 DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder); 230 SrcB = decodeBField(Insn); 231 DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder); 232 if (decodeCField(Insn) != 62) { 233 DEBUG(dbgs() << "Decoding LdRLimm found non-limm register."); 234 return MCDisassembler::Fail; 235 } 236 Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32))); 237 return MCDisassembler::Success; 238 } 239 240 MCDisassembler::DecodeStatus ARCDisassembler::getInstruction( 241 MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address, 242 raw_ostream &vStream, raw_ostream &cStream) const { 243 MCDisassembler::DecodeStatus Result; 244 if (Bytes.size() < 2) { 245 Size = 0; 246 return Fail; 247 } 248 uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3; 249 // 0x00 -> 0x07 are 32-bit instructions. 250 // 0x08 -> 0x1F are 16-bit instructions. 251 if (DecodeByte < 0x08) { 252 // 32-bit instruction. 253 if (Bytes.size() < 4) { 254 // Did we decode garbage? 255 Size = 0; 256 return Fail; 257 } 258 if (Bytes.size() >= 8) { 259 // Attempt to decode 64-bit instruction. 260 uint64_t Insn64; 261 if (!readInstruction64(Bytes, Address, Size, Insn64)) 262 return Fail; 263 Result = 264 decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI); 265 if (Result == MCDisassembler::Success) { 266 DEBUG(dbgs() << "Successfully decoded 64-bit instruction."); 267 return MCDisassembler::Success; 268 } 269 DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit."); 270 } 271 uint32_t Insn32; 272 if (!readInstruction32(Bytes, Address, Size, Insn32)) { 273 return Fail; 274 } 275 // Calling the auto-generated decoder function. 276 return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI); 277 } 278 279 // 16-bit instruction. 280 uint32_t Insn16; 281 if (!readInstruction16(Bytes, Address, Size, Insn16)) { 282 return Fail; 283 } 284 // Calling the auto-generated decoder function. 285 return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI); 286 } 287 288 static MCDisassembler *createARCDisassembler(const Target &T, 289 const MCSubtargetInfo &STI, 290 MCContext &Ctx) { 291 return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo()); 292 } 293 294 extern "C" void LLVMInitializeARCDisassembler() { 295 // Register the disassembler. 296 TargetRegistry::RegisterMCDisassembler(getTheARCTarget(), 297 createARCDisassembler); 298 } 299