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/MCFixedLenDisassembler.h" 26 #include "llvm/MC/MCInst.h" 27 #include "llvm/MC/MCInstrDesc.h" 28 #include "llvm/MC/MCSubtargetInfo.h" 29 #include "llvm/Support/Debug.h" 30 #include "llvm/Support/TargetRegistry.h" 31 32 33 using namespace llvm; 34 35 #define DEBUG_TYPE "amdgpu-disassembler" 36 37 typedef llvm::MCDisassembler::DecodeStatus DecodeStatus; 38 39 40 static DecodeStatus DecodeVGPR_32RegisterClass(MCInst &Inst, unsigned Imm, 41 uint64_t Addr, const void *Decoder) { 42 const AMDGPUDisassembler *Dis = 43 static_cast<const AMDGPUDisassembler *>(Decoder); 44 return Dis->DecodeVGPR_32RegisterClass(Inst, Imm, Addr); 45 } 46 47 static DecodeStatus DecodeVS_32RegisterClass(MCInst &Inst, unsigned Imm, 48 uint64_t Addr, const void *Decoder) { 49 const AMDGPUDisassembler *Dis = 50 static_cast<const AMDGPUDisassembler *>(Decoder); 51 return Dis->DecodeVS_32RegisterClass(Inst, Imm, Addr); 52 } 53 54 static DecodeStatus DecodeVS_64RegisterClass(MCInst &Inst, unsigned Imm, 55 uint64_t Addr, const void *Decoder) { 56 const AMDGPUDisassembler *Dis = 57 static_cast<const AMDGPUDisassembler *>(Decoder); 58 return Dis->DecodeVS_64RegisterClass(Inst, Imm, Addr); 59 } 60 61 static DecodeStatus DecodeVReg_64RegisterClass(MCInst &Inst, unsigned Imm, 62 uint64_t Addr, const void *Decoder) { 63 const AMDGPUDisassembler *Dis = 64 static_cast<const AMDGPUDisassembler *>(Decoder); 65 return Dis->DecodeVReg_64RegisterClass(Inst, Imm, Addr); 66 } 67 68 static DecodeStatus DecodeVReg_96RegisterClass(MCInst &Inst, unsigned Imm, 69 uint64_t Addr, const void *Decoder) { 70 // ToDo 71 return MCDisassembler::Fail; 72 } 73 74 static DecodeStatus DecodeVReg_128RegisterClass(MCInst &Inst, unsigned Imm, 75 uint64_t Addr, const void *Decoder) { 76 // ToDo 77 return MCDisassembler::Fail; 78 } 79 80 static DecodeStatus DecodeSReg_32RegisterClass(MCInst &Inst, unsigned Imm, 81 uint64_t Addr, const void *Decoder) { 82 // ToDo 83 return MCDisassembler::Fail; 84 } 85 86 static DecodeStatus DecodeSReg_64RegisterClass(MCInst &Inst, unsigned Imm, 87 uint64_t Addr, const void *Decoder) { 88 // ToDo 89 return MCDisassembler::Fail; 90 } 91 92 static DecodeStatus DecodeSReg_128RegisterClass(MCInst &Inst, unsigned Imm, 93 uint64_t Addr, const void *Decoder) { 94 // ToDo 95 return MCDisassembler::Fail; 96 } 97 98 static DecodeStatus DecodeSReg_256RegisterClass(MCInst &Inst, unsigned Imm, 99 uint64_t Addr, const void *Decoder) { 100 // ToDo 101 return MCDisassembler::Fail; 102 } 103 104 #define GET_SUBTARGETINFO_ENUM 105 #include "AMDGPUGenSubtargetInfo.inc" 106 #undef GET_SUBTARGETINFO_ENUM 107 108 #include "AMDGPUGenDisassemblerTables.inc" 109 110 //===----------------------------------------------------------------------===// 111 // 112 //===----------------------------------------------------------------------===// 113 114 DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, 115 ArrayRef<uint8_t> Bytes, 116 uint64_t Address, 117 raw_ostream &WS, 118 raw_ostream &CS) const { 119 CommentStream = &CS; 120 121 // ToDo: AMDGPUDisassembler supports only VI ISA. 122 assert(AMDGPU::isVI(STI) && "Can disassemble only VI ISA."); 123 124 HasLiteral = false; 125 this->Bytes = Bytes; 126 127 // Try decode 32-bit instruction 128 if (Bytes.size() < 4) { 129 Size = 0; 130 return MCDisassembler::Fail; 131 } 132 uint32_t Insn = 133 (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0); 134 135 // Calling the auto-generated decoder function. 136 DecodeStatus Result = 137 decodeInstruction(DecoderTableVI32, MI, Insn, Address, this, STI); 138 if (Result != MCDisassembler::Success) { 139 Size = 0; 140 return MCDisassembler::Fail; 141 } 142 if (HasLiteral == true) { 143 Size = 8; 144 HasLiteral = false; 145 } else { 146 Size = 4; 147 } 148 149 return MCDisassembler::Success; 150 } 151 152 DecodeStatus AMDGPUDisassembler::DecodeImmedFloat(unsigned Imm, uint32_t &F) const { 153 // ToDo: case 248: 1/(2*PI) - is allowed only on VI 154 // ToDo: AMDGPUInstPrinter does not support 1/(2*PI). It consider 1/(2*PI) as 155 // literal constant. 156 switch(Imm) { 157 case 240: F = FloatToBits(0.5f); return MCDisassembler::Success; 158 case 241: F = FloatToBits(-0.5f); return MCDisassembler::Success; 159 case 242: F = FloatToBits(1.0f); return MCDisassembler::Success; 160 case 243: F = FloatToBits(-1.0f); return MCDisassembler::Success; 161 case 244: F = FloatToBits(2.0f); return MCDisassembler::Success; 162 case 245: F = FloatToBits(-2.0f); return MCDisassembler::Success; 163 case 246: F = FloatToBits(4.0f); return MCDisassembler::Success; 164 case 247: F = FloatToBits(-4.0f); return MCDisassembler::Success; 165 case 248: F = 0x3e22f983; return MCDisassembler::Success; // 1/(2*PI) 166 default: return MCDisassembler::Fail; 167 } 168 } 169 170 DecodeStatus AMDGPUDisassembler::DecodeImmedDouble(unsigned Imm, uint64_t &D) const { 171 switch(Imm) { 172 case 240: D = DoubleToBits(0.5); return MCDisassembler::Success; 173 case 241: D = DoubleToBits(-0.5); return MCDisassembler::Success; 174 case 242: D = DoubleToBits(1.0); return MCDisassembler::Success; 175 case 243: D = DoubleToBits(-1.0); return MCDisassembler::Success; 176 case 244: D = DoubleToBits(2.0); return MCDisassembler::Success; 177 case 245: D = DoubleToBits(-2.0); return MCDisassembler::Success; 178 case 246: D = DoubleToBits(4.0); return MCDisassembler::Success; 179 case 247: D = DoubleToBits(-4.0); return MCDisassembler::Success; 180 case 248: D = 0x3fc45f306dc9c882; return MCDisassembler::Success; // 1/(2*PI) 181 default: return MCDisassembler::Fail; 182 } 183 } 184 185 DecodeStatus AMDGPUDisassembler::DecodeImmedInteger(unsigned Imm, 186 int64_t &I) const { 187 if ((Imm >= 128) && (Imm <= 192)) { 188 I = Imm - 128; 189 return MCDisassembler::Success; 190 } else if ((Imm >= 193) && (Imm <= 208)) { 191 I = 192 - Imm; 192 return MCDisassembler::Success; 193 } 194 return MCDisassembler::Fail; 195 } 196 197 DecodeStatus AMDGPUDisassembler::DecodeVgprRegister(unsigned Val, 198 unsigned &RegID, 199 unsigned Size) const { 200 if (Val > (256 - Size / 32)) { 201 return MCDisassembler::Fail; 202 } 203 unsigned RegClassID; 204 switch (Size) { 205 case 32: RegClassID = AMDGPU::VGPR_32RegClassID; break; 206 case 64: RegClassID = AMDGPU::VReg_64RegClassID; break; 207 case 96: RegClassID = AMDGPU::VReg_96RegClassID; break; 208 case 128: RegClassID = AMDGPU::VReg_128RegClassID; break; 209 case 256: RegClassID = AMDGPU::VReg_256RegClassID; break; 210 case 512: RegClassID = AMDGPU::VReg_512RegClassID; break; 211 default: 212 return MCDisassembler::Fail; 213 } 214 215 RegID = AMDGPUMCRegisterClasses[RegClassID].getRegister(Val); 216 return MCDisassembler::Success; 217 } 218 219 DecodeStatus AMDGPUDisassembler::DecodeSgprRegister(unsigned Val, 220 unsigned &RegID, 221 unsigned Size) const { 222 // ToDo: SI/CI have 104 SGPRs, VI - 102 223 unsigned RegClassID; 224 225 switch (Size) { 226 case 32: 227 if (Val > 101) { 228 return MCDisassembler::Fail; 229 } 230 RegClassID = AMDGPU::SGPR_32RegClassID; 231 break; 232 case 64: 233 if ((Val % 2 != 0) || (Val > 100)) { 234 return MCDisassembler::Fail; 235 } 236 Val /= 2; 237 RegClassID = AMDGPU::SGPR_64RegClassID; 238 break; 239 case 128: 240 // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in 241 // this bundle? 242 if ((Val % 4 != 0) || (Val > 96)) { 243 return MCDisassembler::Fail; 244 } 245 Val /= 4; 246 RegClassID = AMDGPU::SReg_128RegClassID; 247 break; 248 case 256: 249 // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in 250 // this bundle? 251 if ((Val % 4 != 0) || (Val > 92)) { 252 return MCDisassembler::Fail; 253 } 254 Val /= 4; 255 RegClassID = AMDGPU::SReg_256RegClassID; 256 break; 257 case 512: 258 // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in 259 // this bundle? 260 if ((Val % 4 != 0) || (Val > 84)) { 261 return MCDisassembler::Fail; 262 } 263 Val /= 4; 264 RegClassID = AMDGPU::SReg_512RegClassID; 265 break; 266 default: 267 return MCDisassembler::Fail; 268 } 269 270 RegID = AMDGPUMCRegisterClasses[RegClassID].getRegister(Val); 271 return MCDisassembler::Success; 272 } 273 274 DecodeStatus AMDGPUDisassembler::DecodeSrc32Register(unsigned Val, 275 unsigned &RegID) const { 276 // ToDo: deal with out-of range registers 277 using namespace AMDGPU; 278 if (Val <= 101) { 279 return DecodeSgprRegister(Val, RegID, 32); 280 } else if ((Val >= 256) && (Val <= 511)) { 281 return DecodeVgprRegister(Val - 256, RegID, 32); 282 } else { 283 switch(Val) { 284 case 102: RegID = getMCReg(FLAT_SCR_LO, STI); return MCDisassembler::Success; 285 case 103: RegID = getMCReg(FLAT_SCR_HI, STI); return MCDisassembler::Success; 286 // ToDo: no support for xnack_mask_lo/_hi register 287 case 104: 288 case 105: return MCDisassembler::Fail; 289 case 106: RegID = getMCReg(VCC_LO, STI); return MCDisassembler::Success; 290 case 107: RegID = getMCReg(VCC_HI, STI); return MCDisassembler::Success; 291 // ToDo: no support for tba_lo/_hi register 292 case 108: 293 case 109: return MCDisassembler::Fail; 294 // ToDo: no support for tma_lo/_hi register 295 case 110: 296 case 111: return MCDisassembler::Fail; 297 // ToDo: no support for ttmp[0:11] register 298 case 112: 299 case 113: 300 case 114: 301 case 115: 302 case 116: 303 case 117: 304 case 118: 305 case 119: 306 case 120: 307 case 121: 308 case 122: 309 case 123: return MCDisassembler::Fail; 310 case 124: RegID = getMCReg(M0, STI); return MCDisassembler::Success; 311 case 126: RegID = getMCReg(EXEC_LO, STI); return MCDisassembler::Success; 312 case 127: RegID = getMCReg(EXEC_HI, STI); return MCDisassembler::Success; 313 // ToDo: no support for vccz register 314 case 251: return MCDisassembler::Fail; 315 // ToDo: no support for execz register 316 case 252: return MCDisassembler::Fail; 317 case 253: RegID = getMCReg(SCC, STI); return MCDisassembler::Success; 318 default: return MCDisassembler::Fail; 319 } 320 } 321 return MCDisassembler::Fail; 322 } 323 324 DecodeStatus AMDGPUDisassembler::DecodeSrc64Register(unsigned Val, 325 unsigned &RegID) const { 326 // ToDo: deal with out-of range registers 327 using namespace AMDGPU; 328 if (Val <= 101) { 329 return DecodeSgprRegister(Val, RegID, 64); 330 } else if ((Val >= 256) && (Val <= 511)) { 331 return DecodeVgprRegister(Val - 256, RegID, 64); 332 } else { 333 switch(Val) { 334 case 102: RegID = getMCReg(FLAT_SCR, STI); return MCDisassembler::Success; 335 case 106: RegID = getMCReg(VCC, STI); return MCDisassembler::Success; 336 case 126: RegID = getMCReg(EXEC, STI); return MCDisassembler::Success; 337 default: return MCDisassembler::Fail; 338 } 339 } 340 return MCDisassembler::Fail; 341 } 342 343 DecodeStatus AMDGPUDisassembler::DecodeLiteralConstant(MCInst &Inst, 344 uint64_t &Literal) const { 345 // For now all literal constants are supposed to be unsigned integer 346 // ToDo: deal with signed/unsigned 64-bit integer constants 347 // ToDo: deal with float/double constants 348 if (Bytes.size() < 8) { 349 return MCDisassembler::Fail; 350 } 351 Literal = 352 0 | (Bytes[7] << 24) | (Bytes[6] << 16) | (Bytes[5] << 8) | (Bytes[4] << 0); 353 return MCDisassembler::Success; 354 } 355 356 DecodeStatus AMDGPUDisassembler::DecodeVGPR_32RegisterClass(llvm::MCInst &Inst, 357 unsigned Imm, 358 uint64_t Addr) const { 359 unsigned RegID; 360 if (DecodeVgprRegister(Imm, RegID) == MCDisassembler::Success) { 361 Inst.addOperand(MCOperand::createReg(RegID)); 362 return MCDisassembler::Success; 363 } 364 return MCDisassembler::Fail; 365 } 366 367 DecodeStatus AMDGPUDisassembler::DecodeVSRegisterClass(MCInst &Inst, 368 unsigned Imm, 369 uint64_t Addr, 370 bool Is32) const { 371 // ToDo: different opcodes allow different formats of this operands 372 if ((Imm >= 128) && (Imm <= 208)) { 373 // immediate integer 374 int64_t Val; 375 if (DecodeImmedInteger(Imm, Val) == MCDisassembler::Success) { 376 Inst.addOperand(MCOperand::createImm(Val)); 377 return MCDisassembler::Success; 378 } 379 } else if ((Imm >= 240) && (Imm <= 248)) { 380 // immediate float/double 381 uint64_t Val; 382 DecodeStatus status; 383 if (Is32) { 384 uint32_t Val32; 385 status = DecodeImmedFloat(Imm, Val32); 386 Val = static_cast<uint64_t>(Val32); 387 } else { 388 status = DecodeImmedDouble(Imm, Val); 389 } 390 if (status == MCDisassembler::Success) { 391 Inst.addOperand(MCOperand::createImm(Val)); 392 return MCDisassembler::Success; 393 } 394 } else if (Imm == 254) { 395 // LDS direct 396 // ToDo: implement LDS direct read 397 } else if (Imm == 255) { 398 // literal constant 399 HasLiteral = true; 400 uint64_t Literal; 401 if (DecodeLiteralConstant(Inst, Literal) == MCDisassembler::Success) { 402 Inst.addOperand(MCOperand::createImm(Literal)); 403 return MCDisassembler::Success; 404 } 405 return MCDisassembler::Fail; 406 } else if ((Imm == 125) || 407 ((Imm >= 209) && (Imm <= 239)) || 408 (Imm == 249) || 409 (Imm == 250) || 410 (Imm >= 512)) { 411 // reserved 412 return MCDisassembler::Fail; 413 } else { 414 // register 415 unsigned RegID; 416 DecodeStatus status = Is32 ? DecodeSrc32Register(Imm, RegID) 417 : DecodeSrc64Register(Imm, RegID); 418 if (status == MCDisassembler::Success) { 419 Inst.addOperand(MCOperand::createReg(RegID)); 420 return MCDisassembler::Success; 421 } 422 } 423 return MCDisassembler::Fail; 424 } 425 426 DecodeStatus AMDGPUDisassembler::DecodeVS_32RegisterClass(MCInst &Inst, 427 unsigned Imm, 428 uint64_t Addr) const { 429 return DecodeVSRegisterClass(Inst, Imm, Addr, true); 430 } 431 432 DecodeStatus AMDGPUDisassembler::DecodeVS_64RegisterClass(MCInst &Inst, 433 unsigned Imm, 434 uint64_t Addr) const { 435 return DecodeVSRegisterClass(Inst, Imm, Addr, false); 436 } 437 438 DecodeStatus AMDGPUDisassembler::DecodeVReg_64RegisterClass(llvm::MCInst &Inst, 439 unsigned Imm, 440 uint64_t Addr) const { 441 unsigned RegID; 442 if (DecodeVgprRegister(Imm, RegID, 64) == MCDisassembler::Success) { 443 Inst.addOperand(MCOperand::createReg(RegID)); 444 return MCDisassembler::Success; 445 } 446 return MCDisassembler::Fail; 447 } 448 449 450 451 static MCDisassembler *createAMDGPUDisassembler(const Target &T, 452 const MCSubtargetInfo &STI, 453 MCContext &Ctx) { 454 return new AMDGPUDisassembler(STI, Ctx); 455 } 456 457 extern "C" void LLVMInitializeAMDGPUDisassembler() { 458 TargetRegistry::RegisterMCDisassembler(TheGCNTarget, createAMDGPUDisassembler); 459 } 460