1 //===-- AMDGPUDisassembler.cpp - Disassembler for AMDGPU ISA --------------===// 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 //===----------------------------------------------------------------------===// 11 // 12 /// \file 13 /// 14 /// This file contains definition for AMDGPU ISA disassembler 15 // 16 //===----------------------------------------------------------------------===// 17 18 // ToDo: What to do with instruction suffixes (v_mov_b32 vs v_mov_b32_e32)? 19 20 #include "AMDGPUDisassembler.h" 21 #include "AMDGPU.h" 22 #include "AMDGPURegisterInfo.h" 23 #include "Utils/AMDGPUBaseInfo.h" 24 25 #include "llvm/MC/MCContext.h" 26 #include "llvm/MC/MCFixedLenDisassembler.h" 27 #include "llvm/MC/MCInst.h" 28 #include "llvm/MC/MCInstrDesc.h" 29 #include "llvm/MC/MCSubtargetInfo.h" 30 #include "llvm/Support/Endian.h" 31 #include "llvm/Support/Debug.h" 32 #include "llvm/Support/TargetRegistry.h" 33 34 35 using namespace llvm; 36 37 #define DEBUG_TYPE "amdgpu-disassembler" 38 39 typedef llvm::MCDisassembler::DecodeStatus DecodeStatus; 40 41 42 inline static MCDisassembler::DecodeStatus 43 addOperand(MCInst &Inst, const MCOperand& Opnd) { 44 Inst.addOperand(Opnd); 45 return Opnd.isValid() ? 46 MCDisassembler::Success : 47 MCDisassembler::SoftFail; 48 } 49 50 #define DECODE_OPERAND2(RegClass, DecName) \ 51 static DecodeStatus Decode##RegClass##RegisterClass(MCInst &Inst, \ 52 unsigned Imm, \ 53 uint64_t /*Addr*/, \ 54 const void *Decoder) { \ 55 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); \ 56 return addOperand(Inst, DAsm->decodeOperand_##DecName(Imm)); \ 57 } 58 59 #define DECODE_OPERAND(RegClass) DECODE_OPERAND2(RegClass, RegClass) 60 61 DECODE_OPERAND(VGPR_32) 62 DECODE_OPERAND(VS_32) 63 DECODE_OPERAND(VS_64) 64 65 DECODE_OPERAND(VReg_64) 66 DECODE_OPERAND(VReg_96) 67 DECODE_OPERAND(VReg_128) 68 69 DECODE_OPERAND(SGPR_32) 70 DECODE_OPERAND(SReg_32) 71 DECODE_OPERAND(SReg_32_XM0) 72 DECODE_OPERAND(SReg_64) 73 DECODE_OPERAND(SReg_128) 74 DECODE_OPERAND(SReg_256) 75 DECODE_OPERAND(SReg_512) 76 77 #define GET_SUBTARGETINFO_ENUM 78 #include "AMDGPUGenSubtargetInfo.inc" 79 #undef GET_SUBTARGETINFO_ENUM 80 81 #include "AMDGPUGenDisassemblerTables.inc" 82 83 //===----------------------------------------------------------------------===// 84 // 85 //===----------------------------------------------------------------------===// 86 87 template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) { 88 assert(Bytes.size() >= sizeof(T)); 89 const auto Res = support::endian::read<T, support::endianness::little>(Bytes.data()); 90 Bytes = Bytes.slice(sizeof(T)); 91 return Res; 92 } 93 94 DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t* Table, 95 MCInst &MI, 96 uint64_t Inst, 97 uint64_t Address) const { 98 assert(MI.getOpcode() == 0); 99 assert(MI.getNumOperands() == 0); 100 MCInst TmpInst; 101 const auto SavedBytes = Bytes; 102 if (decodeInstruction(Table, TmpInst, Inst, Address, this, STI)) { 103 MI = TmpInst; 104 return MCDisassembler::Success; 105 } 106 Bytes = SavedBytes; 107 return MCDisassembler::Fail; 108 } 109 110 DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, 111 ArrayRef<uint8_t> Bytes_, 112 uint64_t Address, 113 raw_ostream &WS, 114 raw_ostream &CS) const { 115 CommentStream = &CS; 116 117 // ToDo: AMDGPUDisassembler supports only VI ISA. 118 assert(AMDGPU::isVI(STI) && "Can disassemble only VI ISA."); 119 120 const unsigned MaxInstBytesNum = (std::min)((size_t)8, Bytes_.size()); 121 Bytes = Bytes_.slice(0, MaxInstBytesNum); 122 123 DecodeStatus Res = MCDisassembler::Fail; 124 do { 125 // ToDo: better to switch encoding length using some bit predicate 126 // but it is unknown yet, so try all we can 127 128 // Try to decode DPP first to solve conflict with VOP1 and VOP2 encodings 129 if (Bytes.size() >= 8) { 130 const uint64_t QW = eatBytes<uint64_t>(Bytes); 131 Res = tryDecodeInst(DecoderTableDPP64, MI, QW, Address); 132 if (Res) break; 133 } 134 135 // Reinitialize Bytes as DPP64 could have eaten too much 136 Bytes = Bytes_.slice(0, MaxInstBytesNum); 137 138 // Try decode 32-bit instruction 139 if (Bytes.size() < 4) break; 140 const uint32_t DW = eatBytes<uint32_t>(Bytes); 141 Res = tryDecodeInst(DecoderTableVI32, MI, DW, Address); 142 if (Res) break; 143 144 Res = tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address); 145 if (Res) break; 146 147 if (Bytes.size() < 4) break; 148 const uint64_t QW = ((uint64_t)eatBytes<uint32_t>(Bytes) << 32) | DW; 149 Res = tryDecodeInst(DecoderTableVI64, MI, QW, Address); 150 if (Res) break; 151 152 Res = tryDecodeInst(DecoderTableAMDGPU64, MI, QW, Address); 153 } while (false); 154 155 Size = Res ? (MaxInstBytesNum - Bytes.size()) : 0; 156 return Res; 157 } 158 159 const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const { 160 return getContext().getRegisterInfo()-> 161 getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]); 162 } 163 164 inline 165 MCOperand AMDGPUDisassembler::errOperand(unsigned V, 166 const Twine& ErrMsg) const { 167 *CommentStream << "Error: " + ErrMsg; 168 169 // ToDo: add support for error operands to MCInst.h 170 // return MCOperand::createError(V); 171 return MCOperand(); 172 } 173 174 inline 175 MCOperand AMDGPUDisassembler::createRegOperand(unsigned int RegId) const { 176 return MCOperand::createReg(RegId); 177 } 178 179 inline 180 MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID, 181 unsigned Val) const { 182 const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID]; 183 if (Val >= RegCl.getNumRegs()) 184 return errOperand(Val, Twine(getRegClassName(RegClassID)) + 185 ": unknown register " + Twine(Val)); 186 return createRegOperand(RegCl.getRegister(Val)); 187 } 188 189 inline 190 MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID, 191 unsigned Val) const { 192 // ToDo: SI/CI have 104 SGPRs, VI - 102 193 // Valery: here we accepting as much as we can, let assembler sort it out 194 int shift = 0; 195 switch (SRegClassID) { 196 case AMDGPU::SGPR_32RegClassID: 197 case AMDGPU::SReg_32RegClassID: break; 198 case AMDGPU::SGPR_64RegClassID: 199 case AMDGPU::SReg_64RegClassID: shift = 1; break; 200 case AMDGPU::SReg_128RegClassID: 201 // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in 202 // this bundle? 203 case AMDGPU::SReg_256RegClassID: 204 // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in 205 // this bundle? 206 case AMDGPU::SReg_512RegClassID: shift = 2; break; 207 // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in 208 // this bundle? 209 default: assert(false); break; 210 } 211 if (Val % (1 << shift)) 212 *CommentStream << "Warning: " << getRegClassName(SRegClassID) 213 << ": scalar reg isn't aligned " << Val; 214 return createRegOperand(SRegClassID, Val >> shift); 215 } 216 217 MCOperand AMDGPUDisassembler::decodeOperand_VS_32(unsigned Val) const { 218 return decodeSrcOp(OP32, Val); 219 } 220 221 MCOperand AMDGPUDisassembler::decodeOperand_VS_64(unsigned Val) const { 222 return decodeSrcOp(OP64, Val); 223 } 224 225 MCOperand AMDGPUDisassembler::decodeOperand_VGPR_32(unsigned Val) const { 226 return createRegOperand(AMDGPU::VGPR_32RegClassID, Val); 227 } 228 229 MCOperand AMDGPUDisassembler::decodeOperand_VReg_64(unsigned Val) const { 230 return createRegOperand(AMDGPU::VReg_64RegClassID, Val); 231 } 232 233 MCOperand AMDGPUDisassembler::decodeOperand_VReg_96(unsigned Val) const { 234 return createRegOperand(AMDGPU::VReg_96RegClassID, Val); 235 } 236 237 MCOperand AMDGPUDisassembler::decodeOperand_VReg_128(unsigned Val) const { 238 return createRegOperand(AMDGPU::VReg_128RegClassID, Val); 239 } 240 241 MCOperand AMDGPUDisassembler::decodeOperand_SGPR_32(unsigned Val) const { 242 return createSRegOperand(AMDGPU::SGPR_32RegClassID, Val); 243 } 244 245 MCOperand AMDGPUDisassembler::decodeOperand_SReg_32(unsigned Val) const { 246 // table-gen generated disassembler doesn't care about operand types 247 // leaving only registry class so SSrc_32 operand turns into SReg_32 248 // and therefore we accept immediates and literals here as well 249 return decodeSrcOp(OP32, Val); 250 } 251 252 MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XM0(unsigned Val) const { 253 // SReg_32_XM0 is SReg_32 without M0 254 return decodeOperand_SReg_32(Val); 255 } 256 257 MCOperand AMDGPUDisassembler::decodeOperand_SReg_64(unsigned Val) const { 258 // see decodeOperand_SReg_32 comment 259 return decodeSrcOp(OP64, Val); 260 } 261 262 MCOperand AMDGPUDisassembler::decodeOperand_SReg_128(unsigned Val) const { 263 return createSRegOperand(AMDGPU::SReg_128RegClassID, Val); 264 } 265 266 MCOperand AMDGPUDisassembler::decodeOperand_SReg_256(unsigned Val) const { 267 return createSRegOperand(AMDGPU::SReg_256RegClassID, Val); 268 } 269 270 MCOperand AMDGPUDisassembler::decodeOperand_SReg_512(unsigned Val) const { 271 return createSRegOperand(AMDGPU::SReg_512RegClassID, Val); 272 } 273 274 275 MCOperand AMDGPUDisassembler::decodeLiteralConstant() const { 276 // For now all literal constants are supposed to be unsigned integer 277 // ToDo: deal with signed/unsigned 64-bit integer constants 278 // ToDo: deal with float/double constants 279 if (Bytes.size() < 4) 280 return errOperand(0, "cannot read literal, inst bytes left " + 281 Twine(Bytes.size())); 282 return MCOperand::createImm(eatBytes<uint32_t>(Bytes)); 283 } 284 285 MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) { 286 assert(Imm >= 128 && Imm <= 208); 287 return MCOperand::createImm((Imm <= 192) ? (Imm - 128) : (192 - Imm)); 288 } 289 290 MCOperand AMDGPUDisassembler::decodeFPImmed(bool Is32, unsigned Imm) { 291 assert(Imm >= 240 && Imm <= 248); 292 // ToDo: case 248: 1/(2*PI) - is allowed only on VI 293 // ToDo: AMDGPUInstPrinter does not support 1/(2*PI). It consider 1/(2*PI) as 294 // literal constant. 295 float V = 0.0f; 296 switch (Imm) { 297 case 240: V = 0.5f; break; 298 case 241: V = -0.5f; break; 299 case 242: V = 1.0f; break; 300 case 243: V = -1.0f; break; 301 case 244: V = 2.0f; break; 302 case 245: V = -2.0f; break; 303 case 246: V = 4.0f; break; 304 case 247: V = -4.0f; break; 305 case 248: return MCOperand::createImm(Is32 ? // 1/(2*PI) 306 0x3e22f983 : 307 0x3fc45f306dc9c882); 308 default: break; 309 } 310 return MCOperand::createImm(Is32? FloatToBits(V) : DoubleToBits(V)); 311 } 312 313 MCOperand AMDGPUDisassembler::decodeSrcOp(bool Is32, unsigned Val) const { 314 using namespace AMDGPU; 315 assert(Val < 512); // enum9 316 317 if (Val >= 256) 318 return createRegOperand(Is32 ? VGPR_32RegClassID : VReg_64RegClassID, 319 Val - 256); 320 if (Val <= 101) 321 return createSRegOperand(Is32 ? SGPR_32RegClassID : SGPR_64RegClassID, 322 Val); 323 324 if (Val >= 128 && Val <= 208) 325 return decodeIntImmed(Val); 326 327 if (Val >= 240 && Val <= 248) 328 return decodeFPImmed(Is32, Val); 329 330 if (Val == 255) 331 return decodeLiteralConstant(); 332 333 return Is32 ? decodeSpecialReg32(Val) : decodeSpecialReg64(Val); 334 } 335 336 MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const { 337 using namespace AMDGPU; 338 switch (Val) { 339 case 102: return createRegOperand(getMCReg(FLAT_SCR_LO, STI)); 340 case 103: return createRegOperand(getMCReg(FLAT_SCR_HI, STI)); 341 // ToDo: no support for xnack_mask_lo/_hi register 342 case 104: 343 case 105: break; 344 case 106: return createRegOperand(VCC_LO); 345 case 107: return createRegOperand(VCC_HI); 346 // ToDo: no support for tba_lo/_hi register 347 case 108: 348 case 109: break; 349 // ToDo: no support for tma_lo/_hi register 350 case 110: 351 case 111: break; 352 // ToDo: no support for ttmp[0:11] register 353 case 112: 354 case 113: 355 case 114: 356 case 115: 357 case 116: 358 case 117: 359 case 118: 360 case 119: 361 case 120: 362 case 121: 363 case 122: 364 case 123: break; 365 case 124: return createRegOperand(M0); 366 case 126: return createRegOperand(EXEC_LO); 367 case 127: return createRegOperand(EXEC_HI); 368 // ToDo: no support for vccz register 369 case 251: break; 370 // ToDo: no support for execz register 371 case 252: break; 372 case 253: return createRegOperand(SCC); 373 default: break; 374 } 375 return errOperand(Val, "unknown operand encoding " + Twine(Val)); 376 } 377 378 MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const { 379 using namespace AMDGPU; 380 switch (Val) { 381 case 102: return createRegOperand(getMCReg(FLAT_SCR, STI)); 382 case 106: return createRegOperand(VCC); 383 case 126: return createRegOperand(EXEC); 384 default: break; 385 } 386 return errOperand(Val, "unknown operand encoding " + Twine(Val)); 387 } 388 389 static MCDisassembler *createAMDGPUDisassembler(const Target &T, 390 const MCSubtargetInfo &STI, 391 MCContext &Ctx) { 392 return new AMDGPUDisassembler(STI, Ctx); 393 } 394 395 extern "C" void LLVMInitializeAMDGPUDisassembler() { 396 TargetRegistry::RegisterMCDisassembler(TheGCNTarget, createAMDGPUDisassembler); 397 } 398