blob: ca4e501559be08455e5b4de5ece434dbee0985d0 [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"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000023#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
Artem Tamazov212a2512016-05-24 12:05:16 +000024#include "SIDefines.h"
Tom Stellarde1818af2016-02-18 03:42:32 +000025#include "Utils/AMDGPUBaseInfo.h"
26
Zachary Turner264b5d92017-06-07 03:48:56 +000027#include "llvm/BinaryFormat/ELF.h"
Nikolay Haustovac106ad2016-03-01 13:57:29 +000028#include "llvm/MC/MCContext.h"
Tom Stellarde1818af2016-02-18 03:42:32 +000029#include "llvm/MC/MCFixedLenDisassembler.h"
30#include "llvm/MC/MCInst.h"
31#include "llvm/MC/MCInstrDesc.h"
32#include "llvm/MC/MCSubtargetInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000033#include "llvm/Support/Debug.h"
Nikolay Haustovac106ad2016-03-01 13:57:29 +000034#include "llvm/Support/Endian.h"
Tom Stellarde1818af2016-02-18 03:42:32 +000035#include "llvm/Support/TargetRegistry.h"
36
Tom Stellarde1818af2016-02-18 03:42:32 +000037using namespace llvm;
38
39#define DEBUG_TYPE "amdgpu-disassembler"
40
41typedef llvm::MCDisassembler::DecodeStatus DecodeStatus;
42
43
Nikolay Haustovac106ad2016-03-01 13:57:29 +000044inline static MCDisassembler::DecodeStatus
45addOperand(MCInst &Inst, const MCOperand& Opnd) {
46 Inst.addOperand(Opnd);
47 return Opnd.isValid() ?
48 MCDisassembler::Success :
49 MCDisassembler::SoftFail;
Tom Stellarde1818af2016-02-18 03:42:32 +000050}
51
Sam Kolton549c89d2017-06-21 08:53:38 +000052static int insertNamedMCOperand(MCInst &MI, const MCOperand &Op,
53 uint16_t NameIdx) {
54 int OpIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), NameIdx);
55 if (OpIdx != -1) {
56 auto I = MI.begin();
57 std::advance(I, OpIdx);
58 MI.insert(I, Op);
59 }
60 return OpIdx;
61}
62
Sam Kolton3381d7a2016-10-06 13:46:08 +000063static DecodeStatus decodeSoppBrTarget(MCInst &Inst, unsigned Imm,
64 uint64_t Addr, const void *Decoder) {
65 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
66
67 APInt SignedOffset(18, Imm * 4, true);
68 int64_t Offset = (SignedOffset.sext(64) + 4 + Addr).getSExtValue();
69
70 if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2))
71 return MCDisassembler::Success;
Matt Arsenaultf3dd8632016-11-01 00:55:14 +000072 return addOperand(Inst, MCOperand::createImm(Imm));
Sam Kolton3381d7a2016-10-06 13:46:08 +000073}
74
Sam Kolton363f47a2017-05-26 15:52:00 +000075#define DECODE_OPERAND(StaticDecoderName, DecoderName) \
76static DecodeStatus StaticDecoderName(MCInst &Inst, \
77 unsigned Imm, \
78 uint64_t /*Addr*/, \
79 const void *Decoder) { \
Nikolay Haustovac106ad2016-03-01 13:57:29 +000080 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); \
Sam Kolton363f47a2017-05-26 15:52:00 +000081 return addOperand(Inst, DAsm->DecoderName(Imm)); \
Tom Stellarde1818af2016-02-18 03:42:32 +000082}
83
Sam Kolton363f47a2017-05-26 15:52:00 +000084#define DECODE_OPERAND_REG(RegClass) \
85DECODE_OPERAND(Decode##RegClass##RegisterClass, decodeOperand_##RegClass)
Tom Stellarde1818af2016-02-18 03:42:32 +000086
Sam Kolton363f47a2017-05-26 15:52:00 +000087DECODE_OPERAND_REG(VGPR_32)
88DECODE_OPERAND_REG(VS_32)
89DECODE_OPERAND_REG(VS_64)
Dmitry Preobrazhensky30fc5232017-07-18 13:12:48 +000090DECODE_OPERAND_REG(VS_128)
Nikolay Haustov161a1582016-02-25 16:09:14 +000091
Sam Kolton363f47a2017-05-26 15:52:00 +000092DECODE_OPERAND_REG(VReg_64)
93DECODE_OPERAND_REG(VReg_96)
94DECODE_OPERAND_REG(VReg_128)
Tom Stellarde1818af2016-02-18 03:42:32 +000095
Sam Kolton363f47a2017-05-26 15:52:00 +000096DECODE_OPERAND_REG(SReg_32)
97DECODE_OPERAND_REG(SReg_32_XM0_XEXEC)
Matt Arsenaultca7b0a12017-07-21 15:36:16 +000098DECODE_OPERAND_REG(SReg_32_XEXEC_HI)
Sam Kolton363f47a2017-05-26 15:52:00 +000099DECODE_OPERAND_REG(SReg_64)
100DECODE_OPERAND_REG(SReg_64_XEXEC)
101DECODE_OPERAND_REG(SReg_128)
102DECODE_OPERAND_REG(SReg_256)
103DECODE_OPERAND_REG(SReg_512)
Tom Stellarde1818af2016-02-18 03:42:32 +0000104
Matt Arsenault4bd72362016-12-10 00:39:12 +0000105
106static DecodeStatus decodeOperand_VSrc16(MCInst &Inst,
107 unsigned Imm,
108 uint64_t Addr,
109 const void *Decoder) {
110 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
111 return addOperand(Inst, DAsm->decodeOperand_VSrc16(Imm));
112}
113
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000114static DecodeStatus decodeOperand_VSrcV216(MCInst &Inst,
115 unsigned Imm,
116 uint64_t Addr,
117 const void *Decoder) {
118 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
119 return addOperand(Inst, DAsm->decodeOperand_VSrcV216(Imm));
120}
121
Sam Kolton549c89d2017-06-21 08:53:38 +0000122#define DECODE_SDWA(DecName) \
123DECODE_OPERAND(decodeSDWA##DecName, decodeSDWA##DecName)
Sam Kolton363f47a2017-05-26 15:52:00 +0000124
Sam Kolton549c89d2017-06-21 08:53:38 +0000125DECODE_SDWA(Src32)
126DECODE_SDWA(Src16)
127DECODE_SDWA(VopcDst)
Sam Kolton363f47a2017-05-26 15:52:00 +0000128
Tom Stellarde1818af2016-02-18 03:42:32 +0000129#include "AMDGPUGenDisassemblerTables.inc"
130
131//===----------------------------------------------------------------------===//
132//
133//===----------------------------------------------------------------------===//
134
Sam Kolton1048fb12016-03-31 14:15:04 +0000135template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) {
136 assert(Bytes.size() >= sizeof(T));
137 const auto Res = support::endian::read<T, support::endianness::little>(Bytes.data());
138 Bytes = Bytes.slice(sizeof(T));
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000139 return Res;
140}
141
142DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t* Table,
143 MCInst &MI,
144 uint64_t Inst,
145 uint64_t Address) const {
146 assert(MI.getOpcode() == 0);
147 assert(MI.getNumOperands() == 0);
148 MCInst TmpInst;
Dmitry Preobrazhenskyce941c92017-05-19 14:27:52 +0000149 HasLiteral = false;
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000150 const auto SavedBytes = Bytes;
151 if (decodeInstruction(Table, TmpInst, Inst, Address, this, STI)) {
152 MI = TmpInst;
153 return MCDisassembler::Success;
154 }
155 Bytes = SavedBytes;
156 return MCDisassembler::Fail;
157}
158
Tom Stellarde1818af2016-02-18 03:42:32 +0000159DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000160 ArrayRef<uint8_t> Bytes_,
Nikolay Haustov161a1582016-02-25 16:09:14 +0000161 uint64_t Address,
Tom Stellarde1818af2016-02-18 03:42:32 +0000162 raw_ostream &WS,
163 raw_ostream &CS) const {
164 CommentStream = &CS;
Sam Kolton549c89d2017-06-21 08:53:38 +0000165 bool IsSDWA = false;
Tom Stellarde1818af2016-02-18 03:42:32 +0000166
167 // ToDo: AMDGPUDisassembler supports only VI ISA.
Matt Arsenaultd122abe2017-02-15 21:50:34 +0000168 if (!STI.getFeatureBits()[AMDGPU::FeatureGCN3Encoding])
169 report_fatal_error("Disassembly not yet supported for subtarget");
Tom Stellarde1818af2016-02-18 03:42:32 +0000170
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000171 const unsigned MaxInstBytesNum = (std::min)((size_t)8, Bytes_.size());
172 Bytes = Bytes_.slice(0, MaxInstBytesNum);
Nikolay Haustov161a1582016-02-25 16:09:14 +0000173
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000174 DecodeStatus Res = MCDisassembler::Fail;
175 do {
Valery Pykhtin824e8042016-03-04 10:59:50 +0000176 // ToDo: better to switch encoding length using some bit predicate
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000177 // but it is unknown yet, so try all we can
Matt Arsenault37fefd62016-06-10 02:18:02 +0000178
Sam Koltonc9bdcb72016-06-09 11:04:45 +0000179 // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2
180 // encodings
Sam Kolton1048fb12016-03-31 14:15:04 +0000181 if (Bytes.size() >= 8) {
182 const uint64_t QW = eatBytes<uint64_t>(Bytes);
183 Res = tryDecodeInst(DecoderTableDPP64, MI, QW, Address);
184 if (Res) break;
Sam Koltonc9bdcb72016-06-09 11:04:45 +0000185
186 Res = tryDecodeInst(DecoderTableSDWA64, MI, QW, Address);
Sam Kolton549c89d2017-06-21 08:53:38 +0000187 if (Res) { IsSDWA = true; break; }
Sam Kolton363f47a2017-05-26 15:52:00 +0000188
189 Res = tryDecodeInst(DecoderTableSDWA964, MI, QW, Address);
Sam Kolton549c89d2017-06-21 08:53:38 +0000190 if (Res) { IsSDWA = true; break; }
Sam Kolton1048fb12016-03-31 14:15:04 +0000191 }
192
193 // Reinitialize Bytes as DPP64 could have eaten too much
194 Bytes = Bytes_.slice(0, MaxInstBytesNum);
195
196 // Try decode 32-bit instruction
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000197 if (Bytes.size() < 4) break;
Sam Kolton1048fb12016-03-31 14:15:04 +0000198 const uint32_t DW = eatBytes<uint32_t>(Bytes);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000199 Res = tryDecodeInst(DecoderTableVI32, MI, DW, Address);
200 if (Res) break;
Tom Stellarde1818af2016-02-18 03:42:32 +0000201
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000202 Res = tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address);
203 if (Res) break;
Tom Stellarde1818af2016-02-18 03:42:32 +0000204
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000205 if (Bytes.size() < 4) break;
Sam Kolton1048fb12016-03-31 14:15:04 +0000206 const uint64_t QW = ((uint64_t)eatBytes<uint32_t>(Bytes) << 32) | DW;
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000207 Res = tryDecodeInst(DecoderTableVI64, MI, QW, Address);
208 if (Res) break;
209
210 Res = tryDecodeInst(DecoderTableAMDGPU64, MI, QW, Address);
211 } while (false);
212
Matt Arsenault678e1112017-04-10 17:58:06 +0000213 if (Res && (MI.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||
214 MI.getOpcode() == AMDGPU::V_MAC_F32_e64_si ||
215 MI.getOpcode() == AMDGPU::V_MAC_F16_e64_vi)) {
216 // Insert dummy unused src2_modifiers.
Sam Kolton549c89d2017-06-21 08:53:38 +0000217 insertNamedMCOperand(MI, MCOperand::createImm(0),
218 AMDGPU::OpName::src2_modifiers);
Matt Arsenault678e1112017-04-10 17:58:06 +0000219 }
220
Sam Kolton549c89d2017-06-21 08:53:38 +0000221 if (Res && IsSDWA)
222 Res = convertSDWAInst(MI);
223
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000224 Size = Res ? (MaxInstBytesNum - Bytes.size()) : 0;
225 return Res;
Tom Stellarde1818af2016-02-18 03:42:32 +0000226}
227
Sam Kolton549c89d2017-06-21 08:53:38 +0000228DecodeStatus AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const {
229 if (STI.getFeatureBits()[AMDGPU::FeatureGFX9]) {
230 if (AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sdst) != -1)
231 // VOPC - insert clamp
232 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::clamp);
233 } else if (STI.getFeatureBits()[AMDGPU::FeatureVolcanicIslands]) {
234 int SDst = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sdst);
235 if (SDst != -1) {
236 // VOPC - insert VCC register as sdst
237 insertNamedMCOperand(MI, MCOperand::createReg(AMDGPU::VCC),
238 AMDGPU::OpName::sdst);
239 } else {
240 // VOP1/2 - insert omod if present in instruction
241 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::omod);
242 }
243 }
244 return MCDisassembler::Success;
245}
246
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000247const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const {
248 return getContext().getRegisterInfo()->
249 getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]);
Tom Stellarde1818af2016-02-18 03:42:32 +0000250}
251
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000252inline
253MCOperand AMDGPUDisassembler::errOperand(unsigned V,
254 const Twine& ErrMsg) const {
255 *CommentStream << "Error: " + ErrMsg;
256
257 // ToDo: add support for error operands to MCInst.h
258 // return MCOperand::createError(V);
259 return MCOperand();
Nikolay Haustov161a1582016-02-25 16:09:14 +0000260}
261
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000262inline
263MCOperand AMDGPUDisassembler::createRegOperand(unsigned int RegId) const {
264 return MCOperand::createReg(RegId);
Tom Stellarde1818af2016-02-18 03:42:32 +0000265}
266
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000267inline
268MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID,
269 unsigned Val) const {
270 const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID];
271 if (Val >= RegCl.getNumRegs())
272 return errOperand(Val, Twine(getRegClassName(RegClassID)) +
273 ": unknown register " + Twine(Val));
274 return createRegOperand(RegCl.getRegister(Val));
Tom Stellarde1818af2016-02-18 03:42:32 +0000275}
276
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000277inline
278MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID,
279 unsigned Val) const {
Tom Stellarde1818af2016-02-18 03:42:32 +0000280 // ToDo: SI/CI have 104 SGPRs, VI - 102
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000281 // Valery: here we accepting as much as we can, let assembler sort it out
282 int shift = 0;
283 switch (SRegClassID) {
284 case AMDGPU::SGPR_32RegClassID:
Artem Tamazov212a2512016-05-24 12:05:16 +0000285 case AMDGPU::TTMP_32RegClassID:
286 break;
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000287 case AMDGPU::SGPR_64RegClassID:
Artem Tamazov212a2512016-05-24 12:05:16 +0000288 case AMDGPU::TTMP_64RegClassID:
289 shift = 1;
290 break;
291 case AMDGPU::SGPR_128RegClassID:
292 case AMDGPU::TTMP_128RegClassID:
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000293 // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in
294 // this bundle?
295 case AMDGPU::SReg_256RegClassID:
296 // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in
297 // this bundle?
Artem Tamazov212a2512016-05-24 12:05:16 +0000298 case AMDGPU::SReg_512RegClassID:
299 shift = 2;
300 break;
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000301 // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in
302 // this bundle?
Artem Tamazov212a2512016-05-24 12:05:16 +0000303 default:
Matt Arsenault92b355b2016-11-15 19:34:37 +0000304 llvm_unreachable("unhandled register class");
Tom Stellarde1818af2016-02-18 03:42:32 +0000305 }
Matt Arsenault92b355b2016-11-15 19:34:37 +0000306
307 if (Val % (1 << shift)) {
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000308 *CommentStream << "Warning: " << getRegClassName(SRegClassID)
309 << ": scalar reg isn't aligned " << Val;
Matt Arsenault92b355b2016-11-15 19:34:37 +0000310 }
311
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000312 return createRegOperand(SRegClassID, Val >> shift);
Tom Stellarde1818af2016-02-18 03:42:32 +0000313}
314
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000315MCOperand AMDGPUDisassembler::decodeOperand_VS_32(unsigned Val) const {
Artem Tamazov212a2512016-05-24 12:05:16 +0000316 return decodeSrcOp(OPW32, Val);
Tom Stellarde1818af2016-02-18 03:42:32 +0000317}
318
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000319MCOperand AMDGPUDisassembler::decodeOperand_VS_64(unsigned Val) const {
Artem Tamazov212a2512016-05-24 12:05:16 +0000320 return decodeSrcOp(OPW64, Val);
Nikolay Haustov161a1582016-02-25 16:09:14 +0000321}
322
Dmitry Preobrazhensky30fc5232017-07-18 13:12:48 +0000323MCOperand AMDGPUDisassembler::decodeOperand_VS_128(unsigned Val) const {
324 return decodeSrcOp(OPW128, Val);
325}
326
Matt Arsenault4bd72362016-12-10 00:39:12 +0000327MCOperand AMDGPUDisassembler::decodeOperand_VSrc16(unsigned Val) const {
328 return decodeSrcOp(OPW16, Val);
329}
330
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000331MCOperand AMDGPUDisassembler::decodeOperand_VSrcV216(unsigned Val) const {
332 return decodeSrcOp(OPWV216, Val);
333}
334
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000335MCOperand AMDGPUDisassembler::decodeOperand_VGPR_32(unsigned Val) const {
Matt Arsenaultcb540bc2016-07-19 00:35:03 +0000336 // Some instructions have operand restrictions beyond what the encoding
337 // allows. Some ordinarily VSrc_32 operands are VGPR_32, so clear the extra
338 // high bit.
339 Val &= 255;
340
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000341 return createRegOperand(AMDGPU::VGPR_32RegClassID, Val);
342}
343
344MCOperand AMDGPUDisassembler::decodeOperand_VReg_64(unsigned Val) const {
345 return createRegOperand(AMDGPU::VReg_64RegClassID, Val);
346}
347
348MCOperand AMDGPUDisassembler::decodeOperand_VReg_96(unsigned Val) const {
349 return createRegOperand(AMDGPU::VReg_96RegClassID, Val);
350}
351
352MCOperand AMDGPUDisassembler::decodeOperand_VReg_128(unsigned Val) const {
353 return createRegOperand(AMDGPU::VReg_128RegClassID, Val);
354}
355
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000356MCOperand AMDGPUDisassembler::decodeOperand_SReg_32(unsigned Val) const {
357 // table-gen generated disassembler doesn't care about operand types
358 // leaving only registry class so SSrc_32 operand turns into SReg_32
359 // and therefore we accept immediates and literals here as well
Artem Tamazov212a2512016-05-24 12:05:16 +0000360 return decodeSrcOp(OPW32, Val);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000361}
362
Matt Arsenault640c44b2016-11-29 19:39:53 +0000363MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XM0_XEXEC(
364 unsigned Val) const {
365 // SReg_32_XM0 is SReg_32 without M0 or EXEC_LO/EXEC_HI
Artem Tamazov38e496b2016-04-29 17:04:50 +0000366 return decodeOperand_SReg_32(Val);
367}
368
Matt Arsenaultca7b0a12017-07-21 15:36:16 +0000369MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XEXEC_HI(
370 unsigned Val) const {
371 // SReg_32_XM0 is SReg_32 without EXEC_HI
372 return decodeOperand_SReg_32(Val);
373}
374
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000375MCOperand AMDGPUDisassembler::decodeOperand_SReg_64(unsigned Val) const {
Matt Arsenault640c44b2016-11-29 19:39:53 +0000376 return decodeSrcOp(OPW64, Val);
377}
378
379MCOperand AMDGPUDisassembler::decodeOperand_SReg_64_XEXEC(unsigned Val) const {
Artem Tamazov212a2512016-05-24 12:05:16 +0000380 return decodeSrcOp(OPW64, Val);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000381}
382
383MCOperand AMDGPUDisassembler::decodeOperand_SReg_128(unsigned Val) const {
Artem Tamazov212a2512016-05-24 12:05:16 +0000384 return decodeSrcOp(OPW128, Val);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000385}
386
387MCOperand AMDGPUDisassembler::decodeOperand_SReg_256(unsigned Val) const {
388 return createSRegOperand(AMDGPU::SReg_256RegClassID, Val);
389}
390
391MCOperand AMDGPUDisassembler::decodeOperand_SReg_512(unsigned Val) const {
392 return createSRegOperand(AMDGPU::SReg_512RegClassID, Val);
393}
394
395
396MCOperand AMDGPUDisassembler::decodeLiteralConstant() const {
Nikolay Haustov161a1582016-02-25 16:09:14 +0000397 // For now all literal constants are supposed to be unsigned integer
398 // ToDo: deal with signed/unsigned 64-bit integer constants
399 // ToDo: deal with float/double constants
Dmitry Preobrazhenskyce941c92017-05-19 14:27:52 +0000400 if (!HasLiteral) {
401 if (Bytes.size() < 4) {
402 return errOperand(0, "cannot read literal, inst bytes left " +
403 Twine(Bytes.size()));
404 }
405 HasLiteral = true;
406 Literal = eatBytes<uint32_t>(Bytes);
407 }
408 return MCOperand::createImm(Literal);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000409}
410
411MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) {
Artem Tamazov212a2512016-05-24 12:05:16 +0000412 using namespace AMDGPU::EncValues;
413 assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX);
414 return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ?
415 (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) :
416 (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm)));
417 // Cast prevents negative overflow.
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000418}
419
Matt Arsenault4bd72362016-12-10 00:39:12 +0000420static int64_t getInlineImmVal32(unsigned Imm) {
421 switch (Imm) {
422 case 240:
423 return FloatToBits(0.5f);
424 case 241:
425 return FloatToBits(-0.5f);
426 case 242:
427 return FloatToBits(1.0f);
428 case 243:
429 return FloatToBits(-1.0f);
430 case 244:
431 return FloatToBits(2.0f);
432 case 245:
433 return FloatToBits(-2.0f);
434 case 246:
435 return FloatToBits(4.0f);
436 case 247:
437 return FloatToBits(-4.0f);
438 case 248: // 1 / (2 * PI)
439 return 0x3e22f983;
440 default:
441 llvm_unreachable("invalid fp inline imm");
442 }
443}
444
445static int64_t getInlineImmVal64(unsigned Imm) {
446 switch (Imm) {
447 case 240:
448 return DoubleToBits(0.5);
449 case 241:
450 return DoubleToBits(-0.5);
451 case 242:
452 return DoubleToBits(1.0);
453 case 243:
454 return DoubleToBits(-1.0);
455 case 244:
456 return DoubleToBits(2.0);
457 case 245:
458 return DoubleToBits(-2.0);
459 case 246:
460 return DoubleToBits(4.0);
461 case 247:
462 return DoubleToBits(-4.0);
463 case 248: // 1 / (2 * PI)
464 return 0x3fc45f306dc9c882;
465 default:
466 llvm_unreachable("invalid fp inline imm");
467 }
468}
469
470static int64_t getInlineImmVal16(unsigned Imm) {
471 switch (Imm) {
472 case 240:
473 return 0x3800;
474 case 241:
475 return 0xB800;
476 case 242:
477 return 0x3C00;
478 case 243:
479 return 0xBC00;
480 case 244:
481 return 0x4000;
482 case 245:
483 return 0xC000;
484 case 246:
485 return 0x4400;
486 case 247:
487 return 0xC400;
488 case 248: // 1 / (2 * PI)
489 return 0x3118;
490 default:
491 llvm_unreachable("invalid fp inline imm");
492 }
493}
494
495MCOperand AMDGPUDisassembler::decodeFPImmed(OpWidthTy Width, unsigned Imm) {
Artem Tamazov212a2512016-05-24 12:05:16 +0000496 assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN
497 && Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000498
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000499 // ToDo: case 248: 1/(2*PI) - is allowed only on VI
Matt Arsenault4bd72362016-12-10 00:39:12 +0000500 switch (Width) {
501 case OPW32:
502 return MCOperand::createImm(getInlineImmVal32(Imm));
503 case OPW64:
504 return MCOperand::createImm(getInlineImmVal64(Imm));
505 case OPW16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000506 case OPWV216:
Matt Arsenault4bd72362016-12-10 00:39:12 +0000507 return MCOperand::createImm(getInlineImmVal16(Imm));
508 default:
509 llvm_unreachable("implement me");
Nikolay Haustov161a1582016-02-25 16:09:14 +0000510 }
Nikolay Haustov161a1582016-02-25 16:09:14 +0000511}
512
Artem Tamazov212a2512016-05-24 12:05:16 +0000513unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const {
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000514 using namespace AMDGPU;
Artem Tamazov212a2512016-05-24 12:05:16 +0000515 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
516 switch (Width) {
517 default: // fall
Matt Arsenault4bd72362016-12-10 00:39:12 +0000518 case OPW32:
519 case OPW16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000520 case OPWV216:
Matt Arsenault4bd72362016-12-10 00:39:12 +0000521 return VGPR_32RegClassID;
Artem Tamazov212a2512016-05-24 12:05:16 +0000522 case OPW64: return VReg_64RegClassID;
523 case OPW128: return VReg_128RegClassID;
524 }
525}
526
527unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const {
528 using namespace AMDGPU;
529 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
530 switch (Width) {
531 default: // fall
Matt Arsenault4bd72362016-12-10 00:39:12 +0000532 case OPW32:
533 case OPW16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000534 case OPWV216:
Matt Arsenault4bd72362016-12-10 00:39:12 +0000535 return SGPR_32RegClassID;
Artem Tamazov212a2512016-05-24 12:05:16 +0000536 case OPW64: return SGPR_64RegClassID;
537 case OPW128: return SGPR_128RegClassID;
538 }
539}
540
541unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const {
542 using namespace AMDGPU;
543 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
544 switch (Width) {
545 default: // fall
Matt Arsenault4bd72362016-12-10 00:39:12 +0000546 case OPW32:
547 case OPW16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000548 case OPWV216:
Matt Arsenault4bd72362016-12-10 00:39:12 +0000549 return TTMP_32RegClassID;
Artem Tamazov212a2512016-05-24 12:05:16 +0000550 case OPW64: return TTMP_64RegClassID;
551 case OPW128: return TTMP_128RegClassID;
552 }
553}
554
555MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val) const {
556 using namespace AMDGPU::EncValues;
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000557 assert(Val < 512); // enum9
558
Artem Tamazov212a2512016-05-24 12:05:16 +0000559 if (VGPR_MIN <= Val && Val <= VGPR_MAX) {
560 return createRegOperand(getVgprClassId(Width), Val - VGPR_MIN);
561 }
Artem Tamazovb49c3362016-05-26 15:52:16 +0000562 if (Val <= SGPR_MAX) {
563 assert(SGPR_MIN == 0); // "SGPR_MIN <= Val" is always true and causes compilation warning.
Artem Tamazov212a2512016-05-24 12:05:16 +0000564 return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN);
565 }
566 if (TTMP_MIN <= Val && Val <= TTMP_MAX) {
567 return createSRegOperand(getTtmpClassId(Width), Val - TTMP_MIN);
568 }
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000569
Artem Tamazov212a2512016-05-24 12:05:16 +0000570 if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX)
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000571 return decodeIntImmed(Val);
572
Artem Tamazov212a2512016-05-24 12:05:16 +0000573 if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX)
Matt Arsenault4bd72362016-12-10 00:39:12 +0000574 return decodeFPImmed(Width, Val);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000575
Artem Tamazov212a2512016-05-24 12:05:16 +0000576 if (Val == LITERAL_CONST)
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000577 return decodeLiteralConstant();
578
Matt Arsenault4bd72362016-12-10 00:39:12 +0000579 switch (Width) {
580 case OPW32:
581 case OPW16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000582 case OPWV216:
Matt Arsenault4bd72362016-12-10 00:39:12 +0000583 return decodeSpecialReg32(Val);
584 case OPW64:
585 return decodeSpecialReg64(Val);
586 default:
587 llvm_unreachable("unexpected immediate type");
588 }
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000589}
590
591MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const {
592 using namespace AMDGPU;
593 switch (Val) {
594 case 102: return createRegOperand(getMCReg(FLAT_SCR_LO, STI));
595 case 103: return createRegOperand(getMCReg(FLAT_SCR_HI, STI));
596 // ToDo: no support for xnack_mask_lo/_hi register
597 case 104:
598 case 105: break;
599 case 106: return createRegOperand(VCC_LO);
600 case 107: return createRegOperand(VCC_HI);
Artem Tamazov212a2512016-05-24 12:05:16 +0000601 case 108: return createRegOperand(TBA_LO);
602 case 109: return createRegOperand(TBA_HI);
603 case 110: return createRegOperand(TMA_LO);
604 case 111: return createRegOperand(TMA_HI);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000605 case 124: return createRegOperand(M0);
606 case 126: return createRegOperand(EXEC_LO);
607 case 127: return createRegOperand(EXEC_HI);
Matt Arsenaulta3b3b482017-02-18 18:41:41 +0000608 case 235: return createRegOperand(SRC_SHARED_BASE);
609 case 236: return createRegOperand(SRC_SHARED_LIMIT);
610 case 237: return createRegOperand(SRC_PRIVATE_BASE);
611 case 238: return createRegOperand(SRC_PRIVATE_LIMIT);
612 // TODO: SRC_POPS_EXITING_WAVE_ID
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000613 // ToDo: no support for vccz register
614 case 251: break;
615 // ToDo: no support for execz register
616 case 252: break;
617 case 253: return createRegOperand(SCC);
618 default: break;
Tom Stellarde1818af2016-02-18 03:42:32 +0000619 }
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000620 return errOperand(Val, "unknown operand encoding " + Twine(Val));
Tom Stellarde1818af2016-02-18 03:42:32 +0000621}
622
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000623MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {
624 using namespace AMDGPU;
625 switch (Val) {
626 case 102: return createRegOperand(getMCReg(FLAT_SCR, STI));
627 case 106: return createRegOperand(VCC);
Artem Tamazov212a2512016-05-24 12:05:16 +0000628 case 108: return createRegOperand(TBA);
629 case 110: return createRegOperand(TMA);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000630 case 126: return createRegOperand(EXEC);
631 default: break;
Tom Stellarde1818af2016-02-18 03:42:32 +0000632 }
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000633 return errOperand(Val, "unknown operand encoding " + Twine(Val));
Tom Stellarde1818af2016-02-18 03:42:32 +0000634}
635
Sam Kolton549c89d2017-06-21 08:53:38 +0000636MCOperand AMDGPUDisassembler::decodeSDWASrc(const OpWidthTy Width,
637 unsigned Val) const {
Sam Kolton363f47a2017-05-26 15:52:00 +0000638 using namespace AMDGPU::SDWA;
639
Sam Kolton549c89d2017-06-21 08:53:38 +0000640 if (STI.getFeatureBits()[AMDGPU::FeatureGFX9]) {
Sam Koltona179d252017-06-27 15:02:23 +0000641 // XXX: static_cast<int> is needed to avoid stupid warning:
642 // compare with unsigned is always true
643 if (SDWA9EncValues::SRC_VGPR_MIN <= static_cast<int>(Val) &&
Sam Kolton549c89d2017-06-21 08:53:38 +0000644 Val <= SDWA9EncValues::SRC_VGPR_MAX) {
645 return createRegOperand(getVgprClassId(Width),
646 Val - SDWA9EncValues::SRC_VGPR_MIN);
647 }
648 if (SDWA9EncValues::SRC_SGPR_MIN <= Val &&
649 Val <= SDWA9EncValues::SRC_SGPR_MAX) {
650 return createSRegOperand(getSgprClassId(Width),
651 Val - SDWA9EncValues::SRC_SGPR_MIN);
652 }
653
654 return decodeSpecialReg32(Val - SDWA9EncValues::SRC_SGPR_MIN);
655 } else if (STI.getFeatureBits()[AMDGPU::FeatureVolcanicIslands]) {
656 return createRegOperand(getVgprClassId(Width), Val);
Sam Kolton363f47a2017-05-26 15:52:00 +0000657 }
Sam Kolton549c89d2017-06-21 08:53:38 +0000658 llvm_unreachable("unsupported target");
Sam Kolton363f47a2017-05-26 15:52:00 +0000659}
660
Sam Kolton549c89d2017-06-21 08:53:38 +0000661MCOperand AMDGPUDisassembler::decodeSDWASrc16(unsigned Val) const {
662 return decodeSDWASrc(OPW16, Val);
Sam Kolton363f47a2017-05-26 15:52:00 +0000663}
664
Sam Kolton549c89d2017-06-21 08:53:38 +0000665MCOperand AMDGPUDisassembler::decodeSDWASrc32(unsigned Val) const {
666 return decodeSDWASrc(OPW32, Val);
Sam Kolton363f47a2017-05-26 15:52:00 +0000667}
668
669
Sam Kolton549c89d2017-06-21 08:53:38 +0000670MCOperand AMDGPUDisassembler::decodeSDWAVopcDst(unsigned Val) const {
Sam Kolton363f47a2017-05-26 15:52:00 +0000671 using namespace AMDGPU::SDWA;
672
Sam Kolton549c89d2017-06-21 08:53:38 +0000673 assert(STI.getFeatureBits()[AMDGPU::FeatureGFX9] &&
674 "SDWAVopcDst should be present only on GFX9");
Sam Kolton363f47a2017-05-26 15:52:00 +0000675 if (Val & SDWA9EncValues::VOPC_DST_VCC_MASK) {
676 Val &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
677 if (Val > AMDGPU::EncValues::SGPR_MAX) {
678 return decodeSpecialReg64(Val);
679 } else {
680 return createSRegOperand(getSgprClassId(OPW64), Val);
681 }
682 } else {
683 return createRegOperand(AMDGPU::VCC);
684 }
685}
686
Sam Kolton3381d7a2016-10-06 13:46:08 +0000687//===----------------------------------------------------------------------===//
688// AMDGPUSymbolizer
689//===----------------------------------------------------------------------===//
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000690
Sam Kolton3381d7a2016-10-06 13:46:08 +0000691// Try to find symbol name for specified label
692bool AMDGPUSymbolizer::tryAddingSymbolicOperand(MCInst &Inst,
693 raw_ostream &/*cStream*/, int64_t Value,
694 uint64_t /*Address*/, bool IsBranch,
695 uint64_t /*Offset*/, uint64_t /*InstSize*/) {
696 typedef std::tuple<uint64_t, StringRef, uint8_t> SymbolInfoTy;
697 typedef std::vector<SymbolInfoTy> SectionSymbolsTy;
698
699 if (!IsBranch) {
700 return false;
701 }
702
703 auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo);
704 auto Result = std::find_if(Symbols->begin(), Symbols->end(),
705 [Value](const SymbolInfoTy& Val) {
706 return std::get<0>(Val) == static_cast<uint64_t>(Value)
707 && std::get<2>(Val) == ELF::STT_NOTYPE;
708 });
709 if (Result != Symbols->end()) {
710 auto *Sym = Ctx.getOrCreateSymbol(std::get<1>(*Result));
711 const auto *Add = MCSymbolRefExpr::create(Sym, Ctx);
712 Inst.addOperand(MCOperand::createExpr(Add));
713 return true;
714 }
715 return false;
716}
717
Matt Arsenault92b355b2016-11-15 19:34:37 +0000718void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
719 int64_t Value,
720 uint64_t Address) {
721 llvm_unreachable("unimplemented");
722}
723
Sam Kolton3381d7a2016-10-06 13:46:08 +0000724//===----------------------------------------------------------------------===//
725// Initialization
726//===----------------------------------------------------------------------===//
727
728static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/,
729 LLVMOpInfoCallback /*GetOpInfo*/,
730 LLVMSymbolLookupCallback /*SymbolLookUp*/,
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000731 void *DisInfo,
Sam Kolton3381d7a2016-10-06 13:46:08 +0000732 MCContext *Ctx,
733 std::unique_ptr<MCRelocationInfo> &&RelInfo) {
734 return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo);
735}
736
Tom Stellarde1818af2016-02-18 03:42:32 +0000737static MCDisassembler *createAMDGPUDisassembler(const Target &T,
738 const MCSubtargetInfo &STI,
739 MCContext &Ctx) {
740 return new AMDGPUDisassembler(STI, Ctx);
741}
742
743extern "C" void LLVMInitializeAMDGPUDisassembler() {
Mehdi Aminif42454b2016-10-09 23:00:34 +0000744 TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(),
745 createAMDGPUDisassembler);
746 TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(),
747 createAMDGPUSymbolizer);
Tom Stellarde1818af2016-02-18 03:42:32 +0000748}