xref: /llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp (revision 161a158e5c497a54ea0ba588d242fa98e7c0a3e8)
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