blob: a885010488fdd12b910ed02f3ca0cbf855191b19 [file] [log] [blame]
Tom Stellarde1818af2016-02-18 03:42:32 +00001//===-- 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
33using namespace llvm;
34
35#define DEBUG_TYPE "amdgpu-disassembler"
36
37typedef llvm::MCDisassembler::DecodeStatus DecodeStatus;
38
39
40static DecodeStatus DecodeVGPR_32RegisterClass(MCInst &Inst, unsigned Imm,
41 uint64_t Addr, const void *Decoder) {
Nikolay Haustov161a1582016-02-25 16:09:14 +000042 const AMDGPUDisassembler *Dis =
Tom Stellarde1818af2016-02-18 03:42:32 +000043 static_cast<const AMDGPUDisassembler *>(Decoder);
44 return Dis->DecodeVGPR_32RegisterClass(Inst, Imm, Addr);
45}
46
47static DecodeStatus DecodeVS_32RegisterClass(MCInst &Inst, unsigned Imm,
48 uint64_t Addr, const void *Decoder) {
Nikolay Haustov161a1582016-02-25 16:09:14 +000049 const AMDGPUDisassembler *Dis =
Tom Stellarde1818af2016-02-18 03:42:32 +000050 static_cast<const AMDGPUDisassembler *>(Decoder);
51 return Dis->DecodeVS_32RegisterClass(Inst, Imm, Addr);
52}
53
Nikolay Haustov161a1582016-02-25 16:09:14 +000054static DecodeStatus DecodeVS_64RegisterClass(MCInst &Inst, unsigned Imm,
Tom Stellarde1818af2016-02-18 03:42:32 +000055 uint64_t Addr, const void *Decoder) {
Nikolay Haustov161a1582016-02-25 16:09:14 +000056 const AMDGPUDisassembler *Dis =
57 static_cast<const AMDGPUDisassembler *>(Decoder);
58 return Dis->DecodeVS_64RegisterClass(Inst, Imm, Addr);
Tom Stellarde1818af2016-02-18 03:42:32 +000059}
60
Nikolay Haustov161a1582016-02-25 16:09:14 +000061static 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
68static DecodeStatus DecodeVReg_96RegisterClass(MCInst &Inst, unsigned Imm,
Tom Stellarde1818af2016-02-18 03:42:32 +000069 uint64_t Addr, const void *Decoder) {
70 // ToDo
71 return MCDisassembler::Fail;
72}
73
Nikolay Haustov161a1582016-02-25 16:09:14 +000074static DecodeStatus DecodeVReg_128RegisterClass(MCInst &Inst, unsigned Imm,
Tom Stellarde1818af2016-02-18 03:42:32 +000075 uint64_t Addr, const void *Decoder) {
76 // ToDo
77 return MCDisassembler::Fail;
78}
79
Nikolay Haustov161a1582016-02-25 16:09:14 +000080static DecodeStatus DecodeSReg_32RegisterClass(MCInst &Inst, unsigned Imm,
Tom Stellarde1818af2016-02-18 03:42:32 +000081 uint64_t Addr, const void *Decoder) {
82 // ToDo
83 return MCDisassembler::Fail;
84}
85
Nikolay Haustov161a1582016-02-25 16:09:14 +000086static DecodeStatus DecodeSReg_64RegisterClass(MCInst &Inst, unsigned Imm,
Tom Stellarde1818af2016-02-18 03:42:32 +000087 uint64_t Addr, const void *Decoder) {
88 // ToDo
89 return MCDisassembler::Fail;
90}
91
Nikolay Haustov161a1582016-02-25 16:09:14 +000092static DecodeStatus DecodeSReg_128RegisterClass(MCInst &Inst, unsigned Imm,
Tom Stellarde1818af2016-02-18 03:42:32 +000093 uint64_t Addr, const void *Decoder) {
94 // ToDo
95 return MCDisassembler::Fail;
96}
97
Nikolay Haustov161a1582016-02-25 16:09:14 +000098static DecodeStatus DecodeSReg_256RegisterClass(MCInst &Inst, unsigned Imm,
Tom Stellarde1818af2016-02-18 03:42:32 +000099 uint64_t Addr, const void *Decoder) {
100 // ToDo
101 return MCDisassembler::Fail;
102}
103
Tom Stellarde1818af2016-02-18 03:42:32 +0000104#define GET_SUBTARGETINFO_ENUM
105#include "AMDGPUGenSubtargetInfo.inc"
106#undef GET_SUBTARGETINFO_ENUM
107
108#include "AMDGPUGenDisassemblerTables.inc"
109
110//===----------------------------------------------------------------------===//
111//
112//===----------------------------------------------------------------------===//
113
114DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
115 ArrayRef<uint8_t> Bytes,
Nikolay Haustov161a1582016-02-25 16:09:14 +0000116 uint64_t Address,
Tom Stellarde1818af2016-02-18 03:42:32 +0000117 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
Nikolay Haustov161a1582016-02-25 16:09:14 +0000124 HasLiteral = false;
125 this->Bytes = Bytes;
126
Tom Stellarde1818af2016-02-18 03:42:32 +0000127 // 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 }
Nikolay Haustov161a1582016-02-25 16:09:14 +0000142 if (HasLiteral == true) {
143 Size = 8;
144 HasLiteral = false;
145 } else {
146 Size = 4;
147 }
Tom Stellarde1818af2016-02-18 03:42:32 +0000148
149 return MCDisassembler::Success;
150}
151
Nikolay Haustov161a1582016-02-25 16:09:14 +0000152DecodeStatus AMDGPUDisassembler::DecodeImmedFloat(unsigned Imm, uint32_t &F) const {
Tom Stellarde1818af2016-02-18 03:42:32 +0000153 // ToDo: case 248: 1/(2*PI) - is allowed only on VI
Nikolay Haustov161a1582016-02-25 16:09:14 +0000154 // ToDo: AMDGPUInstPrinter does not support 1/(2*PI). It consider 1/(2*PI) as
Tom Stellarde1818af2016-02-18 03:42:32 +0000155 // 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
Nikolay Haustov161a1582016-02-25 16:09:14 +0000170DecodeStatus 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
185DecodeStatus AMDGPUDisassembler::DecodeImmedInteger(unsigned Imm,
186 int64_t &I) const {
Tom Stellarde1818af2016-02-18 03:42:32 +0000187 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
Nikolay Haustov161a1582016-02-25 16:09:14 +0000197DecodeStatus AMDGPUDisassembler::DecodeVgprRegister(unsigned Val,
198 unsigned &RegID,
199 unsigned Size) const {
200 if (Val > (256 - Size / 32)) {
Tom Stellarde1818af2016-02-18 03:42:32 +0000201 return MCDisassembler::Fail;
202 }
Nikolay Haustov161a1582016-02-25 16:09:14 +0000203 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);
Tom Stellarde1818af2016-02-18 03:42:32 +0000216 return MCDisassembler::Success;
217}
218
Nikolay Haustov161a1582016-02-25 16:09:14 +0000219DecodeStatus AMDGPUDisassembler::DecodeSgprRegister(unsigned Val,
220 unsigned &RegID,
221 unsigned Size) const {
Tom Stellarde1818af2016-02-18 03:42:32 +0000222 // ToDo: SI/CI have 104 SGPRs, VI - 102
Nikolay Haustov161a1582016-02-25 16:09:14 +0000223 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:
Tom Stellarde1818af2016-02-18 03:42:32 +0000267 return MCDisassembler::Fail;
268 }
Nikolay Haustov161a1582016-02-25 16:09:14 +0000269
270 RegID = AMDGPUMCRegisterClasses[RegClassID].getRegister(Val);
Tom Stellarde1818af2016-02-18 03:42:32 +0000271 return MCDisassembler::Success;
272}
273
Nikolay Haustov161a1582016-02-25 16:09:14 +0000274DecodeStatus AMDGPUDisassembler::DecodeSrc32Register(unsigned Val,
275 unsigned &RegID) const {
276 // ToDo: deal with out-of range registers
Tom Stellarde1818af2016-02-18 03:42:32 +0000277 using namespace AMDGPU;
278 if (Val <= 101) {
Nikolay Haustov161a1582016-02-25 16:09:14 +0000279 return DecodeSgprRegister(Val, RegID, 32);
Tom Stellarde1818af2016-02-18 03:42:32 +0000280 } else if ((Val >= 256) && (Val <= 511)) {
Nikolay Haustov161a1582016-02-25 16:09:14 +0000281 return DecodeVgprRegister(Val - 256, RegID, 32);
Tom Stellarde1818af2016-02-18 03:42:32 +0000282 } 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
Nikolay Haustov161a1582016-02-25 16:09:14 +0000324DecodeStatus 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
343DecodeStatus 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
356DecodeStatus AMDGPUDisassembler::DecodeVGPR_32RegisterClass(llvm::MCInst &Inst,
357 unsigned Imm,
Tom Stellarde1818af2016-02-18 03:42:32 +0000358 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
Nikolay Haustov161a1582016-02-25 16:09:14 +0000367DecodeStatus 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
Tom Stellarde1818af2016-02-18 03:42:32 +0000372 if ((Imm >= 128) && (Imm <= 208)) {
373 // immediate integer
374 int64_t Val;
Nikolay Haustov161a1582016-02-25 16:09:14 +0000375 if (DecodeImmedInteger(Imm, Val) == MCDisassembler::Success) {
Tom Stellarde1818af2016-02-18 03:42:32 +0000376 Inst.addOperand(MCOperand::createImm(Val));
377 return MCDisassembler::Success;
378 }
379 } else if ((Imm >= 240) && (Imm <= 248)) {
Nikolay Haustov161a1582016-02-25 16:09:14 +0000380 // 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) {
Tom Stellarde1818af2016-02-18 03:42:32 +0000391 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
Nikolay Haustov161a1582016-02-25 16:09:14 +0000399 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) ||
Tom Stellarde1818af2016-02-18 03:42:32 +0000410 (Imm >= 512)) {
411 // reserved
412 return MCDisassembler::Fail;
413 } else {
414 // register
415 unsigned RegID;
Nikolay Haustov161a1582016-02-25 16:09:14 +0000416 DecodeStatus status = Is32 ? DecodeSrc32Register(Imm, RegID)
417 : DecodeSrc64Register(Imm, RegID);
418 if (status == MCDisassembler::Success) {
Tom Stellarde1818af2016-02-18 03:42:32 +0000419 Inst.addOperand(MCOperand::createReg(RegID));
420 return MCDisassembler::Success;
421 }
422 }
423 return MCDisassembler::Fail;
424}
425
Nikolay Haustov161a1582016-02-25 16:09:14 +0000426DecodeStatus AMDGPUDisassembler::DecodeVS_32RegisterClass(MCInst &Inst,
427 unsigned Imm,
428 uint64_t Addr) const {
429 return DecodeVSRegisterClass(Inst, Imm, Addr, true);
430}
431
432DecodeStatus AMDGPUDisassembler::DecodeVS_64RegisterClass(MCInst &Inst,
433 unsigned Imm,
434 uint64_t Addr) const {
435 return DecodeVSRegisterClass(Inst, Imm, Addr, false);
436}
437
438DecodeStatus 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
Tom Stellarde1818af2016-02-18 03:42:32 +0000451static MCDisassembler *createAMDGPUDisassembler(const Target &T,
452 const MCSubtargetInfo &STI,
453 MCContext &Ctx) {
454 return new AMDGPUDisassembler(STI, Ctx);
455}
456
457extern "C" void LLVMInitializeAMDGPUDisassembler() {
458 TargetRegistry::RegisterMCDisassembler(TheGCNTarget, createAMDGPUDisassembler);
459}