xref: /llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp (revision e1818af8c5330bb8d28d5f72de30bae95d6f1c91)
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   // ToDo
57   return MCDisassembler::Fail;
58 }
59 
60 static DecodeStatus DecodeVReg_64RegisterClass(MCInst &Inst, unsigned Imm,
61                                                uint64_t Addr, const void *Decoder) {
62   // ToDo
63   return MCDisassembler::Fail;
64 }
65 
66 static DecodeStatus DecodeVReg_96RegisterClass(MCInst &Inst, unsigned Imm,
67                                                uint64_t Addr, const void *Decoder) {
68   // ToDo
69   return MCDisassembler::Fail;
70 }
71 
72 static DecodeStatus DecodeVReg_128RegisterClass(MCInst &Inst, unsigned Imm,
73                                                 uint64_t Addr, const void *Decoder) {
74   // ToDo
75   return MCDisassembler::Fail;
76 }
77 
78 static DecodeStatus DecodeSReg_32RegisterClass(MCInst &Inst, unsigned Imm,
79                                                uint64_t Addr, const void *Decoder) {
80   // ToDo
81   return MCDisassembler::Fail;
82 }
83 
84 static DecodeStatus DecodeSReg_64RegisterClass(MCInst &Inst, unsigned Imm,
85                                                uint64_t Addr, const void *Decoder) {
86   // ToDo
87   return MCDisassembler::Fail;
88 }
89 
90 static DecodeStatus DecodeSReg_128RegisterClass(MCInst &Inst, unsigned Imm,
91                                                 uint64_t Addr, const void *Decoder) {
92   // ToDo
93   return MCDisassembler::Fail;
94 }
95 
96 static DecodeStatus DecodeSReg_256RegisterClass(MCInst &Inst, unsigned Imm,
97                                                 uint64_t Addr, const void *Decoder) {
98   // ToDo
99   return MCDisassembler::Fail;
100 }
101 
102 
103 #define GET_SUBTARGETINFO_ENUM
104 #include "AMDGPUGenSubtargetInfo.inc"
105 #undef GET_SUBTARGETINFO_ENUM
106 
107 #include "AMDGPUGenDisassemblerTables.inc"
108 
109 //===----------------------------------------------------------------------===//
110 //
111 //===----------------------------------------------------------------------===//
112 
113 DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
114                                                 ArrayRef<uint8_t> Bytes,
115                                                 uint64_t Address,
116                                                 raw_ostream &WS,
117                                                 raw_ostream &CS) const {
118   CommentStream = &CS;
119 
120   // ToDo: AMDGPUDisassembler supports only VI ISA.
121   assert(AMDGPU::isVI(STI) && "Can disassemble only VI ISA.");
122 
123   // Try decode 32-bit instruction
124   if (Bytes.size() < 4) {
125     Size = 0;
126     return MCDisassembler::Fail;
127   }
128   uint32_t Insn =
129       (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);
130 
131   // Calling the auto-generated decoder function.
132   DecodeStatus Result =
133       decodeInstruction(DecoderTableVI32, MI, Insn, Address, this, STI);
134   if (Result != MCDisassembler::Success) {
135       Size = 0;
136       return MCDisassembler::Fail;
137   }
138   Size = 4;
139 
140   return MCDisassembler::Success;
141 }
142 
143 DecodeStatus AMDGPUDisassembler::DecodeLitFloat(unsigned Imm, uint32_t& F) const {
144   // ToDo: case 248: 1/(2*PI) - is allowed only on VI
145   // ToDo: AMDGPUInstPrinter does not support 1/(2*PI). It consider 1/(2*PI) as
146   // literal constant.
147   switch(Imm) {
148   case 240: F = FloatToBits(0.5f); return MCDisassembler::Success;
149   case 241: F = FloatToBits(-0.5f); return MCDisassembler::Success;
150   case 242: F = FloatToBits(1.0f); return MCDisassembler::Success;
151   case 243: F = FloatToBits(-1.0f); return MCDisassembler::Success;
152   case 244: F = FloatToBits(2.0f); return MCDisassembler::Success;
153   case 245: F = FloatToBits(-2.0f); return MCDisassembler::Success;
154   case 246: F = FloatToBits(4.0f); return MCDisassembler::Success;
155   case 247: F = FloatToBits(-4.0f); return MCDisassembler::Success;
156   case 248: F = 0x3e22f983; return MCDisassembler::Success; // 1/(2*PI)
157   default: return MCDisassembler::Fail;
158   }
159 }
160 
161 DecodeStatus AMDGPUDisassembler::DecodeLitInteger(unsigned Imm,
162                                                   int64_t& I) const {
163   if ((Imm >= 128) && (Imm <= 192)) {
164     I = Imm - 128;
165     return MCDisassembler::Success;
166   } else if ((Imm >= 193) && (Imm <= 208)) {
167     I = 192 - Imm;
168     return MCDisassembler::Success;
169   }
170   return MCDisassembler::Fail;
171 }
172 
173 DecodeStatus AMDGPUDisassembler::DecodeVgprRegister(unsigned Val,
174                                                     unsigned& RegID) const {
175   if (Val > 255) {
176     return MCDisassembler::Fail;
177   }
178   RegID = AMDGPUMCRegisterClasses[AMDGPU::VGPR_32RegClassID].getRegister(Val);
179   return MCDisassembler::Success;
180 }
181 
182 DecodeStatus AMDGPUDisassembler::DecodeSgprRegister(unsigned Val,
183                                                     unsigned& RegID) const {
184   // ToDo: SI/CI have 104 SGPRs, VI - 102
185   if (Val > 101) {
186     return MCDisassembler::Fail;
187   }
188   RegID = AMDGPUMCRegisterClasses[AMDGPU::SGPR_32RegClassID].getRegister(Val);
189   return MCDisassembler::Success;
190 }
191 
192 DecodeStatus AMDGPUDisassembler::DecodeSrcRegister(unsigned Val,
193                                                    unsigned& RegID) const {
194   // ToDo: deal with out-of range registers
195   using namespace AMDGPU;
196   if (Val <= 101) {
197     return DecodeSgprRegister(Val, RegID);
198   } else if ((Val >= 256) && (Val <= 511)) {
199     return DecodeVgprRegister(Val - 256, RegID);
200   } else {
201     switch(Val) {
202     case 102: RegID = getMCReg(FLAT_SCR_LO, STI); return MCDisassembler::Success;
203     case 103: RegID = getMCReg(FLAT_SCR_HI, STI); return MCDisassembler::Success;
204     // ToDo: no support for xnack_mask_lo/_hi register
205     case 104:
206     case 105: return MCDisassembler::Fail;
207     case 106: RegID = getMCReg(VCC_LO, STI); return MCDisassembler::Success;
208     case 107: RegID = getMCReg(VCC_HI, STI); return MCDisassembler::Success;
209     // ToDo: no support for tba_lo/_hi register
210     case 108:
211     case 109: return MCDisassembler::Fail;
212     // ToDo: no support for tma_lo/_hi register
213     case 110:
214     case 111: return MCDisassembler::Fail;
215     // ToDo: no support for ttmp[0:11] register
216     case 112:
217     case 113:
218     case 114:
219     case 115:
220     case 116:
221     case 117:
222     case 118:
223     case 119:
224     case 120:
225     case 121:
226     case 122:
227     case 123: return MCDisassembler::Fail;
228     case 124: RegID = getMCReg(M0, STI); return MCDisassembler::Success;
229     case 126: RegID = getMCReg(EXEC_LO, STI); return MCDisassembler::Success;
230     case 127: RegID = getMCReg(EXEC_HI, STI); return MCDisassembler::Success;
231     // ToDo: no support for vccz register
232     case 251: return MCDisassembler::Fail;
233     // ToDo: no support for execz register
234     case 252: return MCDisassembler::Fail;
235     case 253: RegID = getMCReg(SCC, STI); return MCDisassembler::Success;
236     default: return MCDisassembler::Fail;
237     }
238   }
239   return MCDisassembler::Fail;
240 }
241 
242 DecodeStatus AMDGPUDisassembler::DecodeVGPR_32RegisterClass(llvm::MCInst &Inst,
243                                                             unsigned Imm,
244                                                             uint64_t Addr) const {
245   unsigned RegID;
246   if (DecodeVgprRegister(Imm, RegID) == MCDisassembler::Success) {
247     Inst.addOperand(MCOperand::createReg(RegID));
248     return MCDisassembler::Success;
249   }
250   return MCDisassembler::Fail;
251 }
252 
253 DecodeStatus AMDGPUDisassembler::DecodeVS_32RegisterClass(MCInst &Inst,
254                                                           unsigned Imm,
255                                                           uint64_t Addr) const {
256   // ToDo: different opcodes allow different formats og this operands
257   if ((Imm >= 128) && (Imm <= 208)) {
258     // immediate integer
259     int64_t Val;
260     if (DecodeLitInteger(Imm, Val) == MCDisassembler::Success) {
261       Inst.addOperand(MCOperand::createImm(Val));
262       return MCDisassembler::Success;
263     }
264   } else if ((Imm >= 240) && (Imm <= 248)) {
265     // immediate float
266     uint32_t Val;
267     if (DecodeLitFloat(Imm, Val) == MCDisassembler::Success) {
268       Inst.addOperand(MCOperand::createImm(Val));
269       return MCDisassembler::Success;
270     }
271   } else if (Imm == 254) {
272     // LDS direct
273     // ToDo: implement LDS direct read
274   } else if (Imm == 255) {
275     // literal constant
276   } else if ((Imm == 125) ||
277              ((Imm >= 209) && (Imm <= 239)) ||
278              (Imm == 249) ||
279              (Imm == 250) ||
280              (Imm >= 512)) {
281     // reserved
282     return MCDisassembler::Fail;
283   } else {
284     // register
285     unsigned RegID;
286     if (DecodeSrcRegister(Imm, RegID) == MCDisassembler::Success) {
287       Inst.addOperand(MCOperand::createReg(RegID));
288       return MCDisassembler::Success;
289     }
290   }
291   return MCDisassembler::Fail;
292 }
293 
294 static MCDisassembler *createAMDGPUDisassembler(const Target &T,
295                                                 const MCSubtargetInfo &STI,
296                                                 MCContext &Ctx) {
297   return new AMDGPUDisassembler(STI, Ctx);
298 }
299 
300 extern "C" void LLVMInitializeAMDGPUDisassembler() {
301   TargetRegistry::RegisterMCDisassembler(TheGCNTarget, createAMDGPUDisassembler);
302 }
303