1 //===- SparcDisassembler.cpp - Disassembler for Sparc -----------*- 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 // This file is part of the Sparc Disassembler. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MCTargetDesc/SparcMCTargetDesc.h" 14 #include "TargetInfo/SparcTargetInfo.h" 15 #include "llvm/MC/MCAsmInfo.h" 16 #include "llvm/MC/MCContext.h" 17 #include "llvm/MC/MCDecoderOps.h" 18 #include "llvm/MC/MCDisassembler/MCDisassembler.h" 19 #include "llvm/MC/MCInst.h" 20 #include "llvm/MC/TargetRegistry.h" 21 #include "llvm/Support/Compiler.h" 22 23 using namespace llvm; 24 25 #define DEBUG_TYPE "sparc-disassembler" 26 27 typedef MCDisassembler::DecodeStatus DecodeStatus; 28 29 namespace { 30 31 /// A disassembler class for Sparc. 32 class SparcDisassembler : public MCDisassembler { 33 public: 34 SparcDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) 35 : MCDisassembler(STI, Ctx) {} 36 virtual ~SparcDisassembler() = default; 37 38 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, 39 ArrayRef<uint8_t> Bytes, uint64_t Address, 40 raw_ostream &CStream) const override; 41 }; 42 } 43 44 static MCDisassembler *createSparcDisassembler(const Target &T, 45 const MCSubtargetInfo &STI, 46 MCContext &Ctx) { 47 return new SparcDisassembler(STI, Ctx); 48 } 49 50 extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void 51 LLVMInitializeSparcDisassembler() { 52 // Register the disassembler. 53 TargetRegistry::RegisterMCDisassembler(getTheSparcTarget(), 54 createSparcDisassembler); 55 TargetRegistry::RegisterMCDisassembler(getTheSparcV9Target(), 56 createSparcDisassembler); 57 TargetRegistry::RegisterMCDisassembler(getTheSparcelTarget(), 58 createSparcDisassembler); 59 } 60 61 static const unsigned IntRegDecoderTable[] = { 62 SP::G0, SP::G1, SP::G2, SP::G3, 63 SP::G4, SP::G5, SP::G6, SP::G7, 64 SP::O0, SP::O1, SP::O2, SP::O3, 65 SP::O4, SP::O5, SP::O6, SP::O7, 66 SP::L0, SP::L1, SP::L2, SP::L3, 67 SP::L4, SP::L5, SP::L6, SP::L7, 68 SP::I0, SP::I1, SP::I2, SP::I3, 69 SP::I4, SP::I5, SP::I6, SP::I7 }; 70 71 static const unsigned FPRegDecoderTable[] = { 72 SP::F0, SP::F1, SP::F2, SP::F3, 73 SP::F4, SP::F5, SP::F6, SP::F7, 74 SP::F8, SP::F9, SP::F10, SP::F11, 75 SP::F12, SP::F13, SP::F14, SP::F15, 76 SP::F16, SP::F17, SP::F18, SP::F19, 77 SP::F20, SP::F21, SP::F22, SP::F23, 78 SP::F24, SP::F25, SP::F26, SP::F27, 79 SP::F28, SP::F29, SP::F30, SP::F31 }; 80 81 static const unsigned DFPRegDecoderTable[] = { 82 SP::D0, SP::D16, SP::D1, SP::D17, 83 SP::D2, SP::D18, SP::D3, SP::D19, 84 SP::D4, SP::D20, SP::D5, SP::D21, 85 SP::D6, SP::D22, SP::D7, SP::D23, 86 SP::D8, SP::D24, SP::D9, SP::D25, 87 SP::D10, SP::D26, SP::D11, SP::D27, 88 SP::D12, SP::D28, SP::D13, SP::D29, 89 SP::D14, SP::D30, SP::D15, SP::D31 }; 90 91 static const unsigned QFPRegDecoderTable[] = { 92 SP::Q0, SP::Q8, ~0U, ~0U, 93 SP::Q1, SP::Q9, ~0U, ~0U, 94 SP::Q2, SP::Q10, ~0U, ~0U, 95 SP::Q3, SP::Q11, ~0U, ~0U, 96 SP::Q4, SP::Q12, ~0U, ~0U, 97 SP::Q5, SP::Q13, ~0U, ~0U, 98 SP::Q6, SP::Q14, ~0U, ~0U, 99 SP::Q7, SP::Q15, ~0U, ~0U } ; 100 101 static const unsigned FCCRegDecoderTable[] = { 102 SP::FCC0, SP::FCC1, SP::FCC2, SP::FCC3 }; 103 104 static const unsigned ASRRegDecoderTable[] = { 105 SP::Y, SP::ASR1, SP::ASR2, SP::ASR3, SP::ASR4, SP::ASR5, SP::ASR6, 106 SP::ASR7, SP::ASR8, SP::ASR9, SP::ASR10, SP::ASR11, SP::ASR12, SP::ASR13, 107 SP::ASR14, SP::ASR15, SP::ASR16, SP::ASR17, SP::ASR18, SP::ASR19, SP::ASR20, 108 SP::ASR21, SP::ASR22, SP::ASR23, SP::ASR24, SP::ASR25, SP::ASR26, SP::ASR27, 109 SP::ASR28, SP::ASR29, SP::ASR30, SP::ASR31}; 110 111 static const unsigned PRRegDecoderTable[] = { 112 SP::TPC, SP::TNPC, SP::TSTATE, SP::TT, SP::TICK, 113 SP::TBA, SP::PSTATE, SP::TL, SP::PIL, SP::CWP, 114 SP::CANSAVE, SP::CANRESTORE, SP::CLEANWIN, SP::OTHERWIN, SP::WSTATE}; 115 116 static const uint16_t IntPairDecoderTable[] = { 117 SP::G0_G1, SP::G2_G3, SP::G4_G5, SP::G6_G7, 118 SP::O0_O1, SP::O2_O3, SP::O4_O5, SP::O6_O7, 119 SP::L0_L1, SP::L2_L3, SP::L4_L5, SP::L6_L7, 120 SP::I0_I1, SP::I2_I3, SP::I4_I5, SP::I6_I7, 121 }; 122 123 static const unsigned CPRegDecoderTable[] = { 124 SP::C0, SP::C1, SP::C2, SP::C3, 125 SP::C4, SP::C5, SP::C6, SP::C7, 126 SP::C8, SP::C9, SP::C10, SP::C11, 127 SP::C12, SP::C13, SP::C14, SP::C15, 128 SP::C16, SP::C17, SP::C18, SP::C19, 129 SP::C20, SP::C21, SP::C22, SP::C23, 130 SP::C24, SP::C25, SP::C26, SP::C27, 131 SP::C28, SP::C29, SP::C30, SP::C31 132 }; 133 134 135 static const uint16_t CPPairDecoderTable[] = { 136 SP::C0_C1, SP::C2_C3, SP::C4_C5, SP::C6_C7, 137 SP::C8_C9, SP::C10_C11, SP::C12_C13, SP::C14_C15, 138 SP::C16_C17, SP::C18_C19, SP::C20_C21, SP::C22_C23, 139 SP::C24_C25, SP::C26_C27, SP::C28_C29, SP::C30_C31 140 }; 141 142 static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, unsigned RegNo, 143 uint64_t Address, 144 const MCDisassembler *Decoder) { 145 if (RegNo > 31) 146 return MCDisassembler::Fail; 147 unsigned Reg = IntRegDecoderTable[RegNo]; 148 Inst.addOperand(MCOperand::createReg(Reg)); 149 return MCDisassembler::Success; 150 } 151 152 static DecodeStatus DecodeI64RegsRegisterClass(MCInst &Inst, unsigned RegNo, 153 uint64_t Address, 154 const MCDisassembler *Decoder) { 155 return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder); 156 } 157 158 // This is used for the type "ptr_rc", which is either IntRegs or I64Regs 159 // depending on SparcRegisterInfo::getPointerRegClass. 160 static DecodeStatus DecodePointerLikeRegClass0(MCInst &Inst, unsigned RegNo, 161 uint64_t Address, 162 const MCDisassembler *Decoder) { 163 return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder); 164 } 165 166 static DecodeStatus DecodeFPRegsRegisterClass(MCInst &Inst, unsigned RegNo, 167 uint64_t Address, 168 const MCDisassembler *Decoder) { 169 if (RegNo > 31) 170 return MCDisassembler::Fail; 171 unsigned Reg = FPRegDecoderTable[RegNo]; 172 Inst.addOperand(MCOperand::createReg(Reg)); 173 return MCDisassembler::Success; 174 } 175 176 static DecodeStatus DecodeDFPRegsRegisterClass(MCInst &Inst, unsigned RegNo, 177 uint64_t Address, 178 const MCDisassembler *Decoder) { 179 if (RegNo > 31) 180 return MCDisassembler::Fail; 181 unsigned Reg = DFPRegDecoderTable[RegNo]; 182 Inst.addOperand(MCOperand::createReg(Reg)); 183 return MCDisassembler::Success; 184 } 185 186 static DecodeStatus DecodeQFPRegsRegisterClass(MCInst &Inst, unsigned RegNo, 187 uint64_t Address, 188 const MCDisassembler *Decoder) { 189 if (RegNo > 31) 190 return MCDisassembler::Fail; 191 192 unsigned Reg = QFPRegDecoderTable[RegNo]; 193 if (Reg == ~0U) 194 return MCDisassembler::Fail; 195 Inst.addOperand(MCOperand::createReg(Reg)); 196 return MCDisassembler::Success; 197 } 198 199 static DecodeStatus 200 DecodeCoprocRegsRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, 201 const MCDisassembler *Decoder) { 202 if (RegNo > 31) 203 return MCDisassembler::Fail; 204 unsigned Reg = CPRegDecoderTable[RegNo]; 205 Inst.addOperand(MCOperand::createReg(Reg)); 206 return MCDisassembler::Success; 207 } 208 209 static DecodeStatus DecodeFCCRegsRegisterClass(MCInst &Inst, unsigned RegNo, 210 uint64_t Address, 211 const MCDisassembler *Decoder) { 212 if (RegNo > 3) 213 return MCDisassembler::Fail; 214 Inst.addOperand(MCOperand::createReg(FCCRegDecoderTable[RegNo])); 215 return MCDisassembler::Success; 216 } 217 218 static DecodeStatus DecodeASRRegsRegisterClass(MCInst &Inst, unsigned RegNo, 219 uint64_t Address, 220 const MCDisassembler *Decoder) { 221 if (RegNo > 31) 222 return MCDisassembler::Fail; 223 Inst.addOperand(MCOperand::createReg(ASRRegDecoderTable[RegNo])); 224 return MCDisassembler::Success; 225 } 226 227 static DecodeStatus DecodePRRegsRegisterClass(MCInst &Inst, unsigned RegNo, 228 uint64_t Address, 229 const MCDisassembler *Decoder) { 230 if (RegNo >= std::size(PRRegDecoderTable)) 231 return MCDisassembler::Fail; 232 Inst.addOperand(MCOperand::createReg(PRRegDecoderTable[RegNo])); 233 return MCDisassembler::Success; 234 } 235 236 static DecodeStatus DecodeIntPairRegisterClass(MCInst &Inst, unsigned RegNo, 237 uint64_t Address, 238 const MCDisassembler *Decoder) { 239 DecodeStatus S = MCDisassembler::Success; 240 241 if (RegNo > 31) 242 return MCDisassembler::Fail; 243 244 if ((RegNo & 1)) 245 S = MCDisassembler::SoftFail; 246 247 unsigned RegisterPair = IntPairDecoderTable[RegNo/2]; 248 Inst.addOperand(MCOperand::createReg(RegisterPair)); 249 return S; 250 } 251 252 static DecodeStatus 253 DecodeCoprocPairRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, 254 const MCDisassembler *Decoder) { 255 if (RegNo > 31) 256 return MCDisassembler::Fail; 257 258 unsigned RegisterPair = CPPairDecoderTable[RegNo/2]; 259 Inst.addOperand(MCOperand::createReg(RegisterPair)); 260 return MCDisassembler::Success; 261 } 262 263 static DecodeStatus DecodeCall(MCInst &Inst, unsigned insn, uint64_t Address, 264 const MCDisassembler *Decoder); 265 static DecodeStatus DecodeSIMM5(MCInst &Inst, unsigned insn, uint64_t Address, 266 const MCDisassembler *Decoder); 267 static DecodeStatus DecodeSIMM13(MCInst &Inst, unsigned insn, uint64_t Address, 268 const MCDisassembler *Decoder); 269 template <unsigned N> 270 constexpr static DecodeStatus DecodeDisp(MCInst &MI, uint32_t ImmVal, 271 uint64_t Address, 272 const MCDisassembler *Decoder); 273 #include "SparcGenDisassemblerTables.inc" 274 275 /// Read four bytes from the ArrayRef and return 32 bit word. 276 static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address, 277 uint64_t &Size, uint32_t &Insn, 278 bool IsLittleEndian) { 279 // We want to read exactly 4 Bytes of data. 280 if (Bytes.size() < 4) { 281 Size = 0; 282 return MCDisassembler::Fail; 283 } 284 285 Size = 4; 286 Insn = IsLittleEndian 287 ? (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) | 288 (Bytes[3] << 24) 289 : (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | 290 (Bytes[0] << 24); 291 292 return MCDisassembler::Success; 293 } 294 295 DecodeStatus SparcDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, 296 ArrayRef<uint8_t> Bytes, 297 uint64_t Address, 298 raw_ostream &CStream) const { 299 uint32_t Insn; 300 bool isLittleEndian = getContext().getAsmInfo()->isLittleEndian(); 301 DecodeStatus Result = 302 readInstruction32(Bytes, Address, Size, Insn, isLittleEndian); 303 if (Result == MCDisassembler::Fail) 304 return MCDisassembler::Fail; 305 306 // Calling the auto-generated decoder function. 307 308 if (STI.hasFeature(Sparc::FeatureV9)) 309 { 310 Result = decodeInstruction(DecoderTableSparcV932, Instr, Insn, Address, this, STI); 311 } 312 else 313 { 314 Result = decodeInstruction(DecoderTableSparcV832, Instr, Insn, Address, this, STI); 315 } 316 if (Result != MCDisassembler::Fail) 317 return Result; 318 319 Result = 320 decodeInstruction(DecoderTableSparc32, Instr, Insn, Address, this, STI); 321 322 return Result; 323 } 324 325 static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, 326 uint64_t Address, uint64_t Offset, 327 uint64_t Width, MCInst &MI, 328 const MCDisassembler *Decoder) { 329 return Decoder->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset, 330 Width, /*InstSize=*/4); 331 } 332 333 static DecodeStatus DecodeCall(MCInst &MI, unsigned insn, uint64_t Address, 334 const MCDisassembler *Decoder) { 335 int64_t CallOffset = SignExtend64(fieldFromInstruction(insn, 0, 30), 30) * 4; 336 if (!tryAddingSymbolicOperand(Address + CallOffset, false, Address, 0, 30, MI, 337 Decoder)) 338 MI.addOperand(MCOperand::createImm(CallOffset)); 339 return MCDisassembler::Success; 340 } 341 342 static DecodeStatus DecodeSIMM5(MCInst &MI, unsigned insn, uint64_t Address, 343 const MCDisassembler *Decoder) { 344 assert(isUInt<5>(insn)); 345 MI.addOperand(MCOperand::createImm(SignExtend64<5>(insn))); 346 return MCDisassembler::Success; 347 } 348 349 static DecodeStatus DecodeSIMM13(MCInst &MI, unsigned insn, uint64_t Address, 350 const MCDisassembler *Decoder) { 351 assert(isUInt<13>(insn)); 352 MI.addOperand(MCOperand::createImm(SignExtend64<13>(insn))); 353 return MCDisassembler::Success; 354 } 355 356 template <unsigned N> 357 constexpr static DecodeStatus DecodeDisp(MCInst &MI, uint32_t ImmVal, 358 uint64_t Address, 359 const MCDisassembler *Decoder) { 360 int64_t BranchOffset = SignExtend64(ImmVal, N) * 4; 361 if (!tryAddingSymbolicOperand(Address + BranchOffset, true, Address, 0, N, MI, 362 Decoder)) 363 MI.addOperand(MCOperand::createImm(BranchOffset)); 364 return MCDisassembler::Success; 365 } 366