blob: 20db4e513978eff90457a1ef8f84cb307a92b72f [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)
Nikolay Haustov161a1582016-02-25 16:09:14 +000090
Sam Kolton363f47a2017-05-26 15:52:00 +000091DECODE_OPERAND_REG(VReg_64)
92DECODE_OPERAND_REG(VReg_96)
93DECODE_OPERAND_REG(VReg_128)
Tom Stellarde1818af2016-02-18 03:42:32 +000094
Sam Kolton363f47a2017-05-26 15:52:00 +000095DECODE_OPERAND_REG(SReg_32)
96DECODE_OPERAND_REG(SReg_32_XM0_XEXEC)
97DECODE_OPERAND_REG(SReg_64)
98DECODE_OPERAND_REG(SReg_64_XEXEC)
99DECODE_OPERAND_REG(SReg_128)
100DECODE_OPERAND_REG(SReg_256)
101DECODE_OPERAND_REG(SReg_512)
Tom Stellarde1818af2016-02-18 03:42:32 +0000102
Matt Arsenault4bd72362016-12-10 00:39:12 +0000103
104static DecodeStatus decodeOperand_VSrc16(MCInst &Inst,
105 unsigned Imm,
106 uint64_t Addr,
107 const void *Decoder) {
108 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
109 return addOperand(Inst, DAsm->decodeOperand_VSrc16(Imm));
110}
111
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000112static DecodeStatus decodeOperand_VSrcV216(MCInst &Inst,
113 unsigned Imm,
114 uint64_t Addr,
115 const void *Decoder) {
116 auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
117 return addOperand(Inst, DAsm->decodeOperand_VSrcV216(Imm));
118}
119
Sam Kolton549c89d2017-06-21 08:53:38 +0000120#define DECODE_SDWA(DecName) \
121DECODE_OPERAND(decodeSDWA##DecName, decodeSDWA##DecName)
Sam Kolton363f47a2017-05-26 15:52:00 +0000122
Sam Kolton549c89d2017-06-21 08:53:38 +0000123DECODE_SDWA(Src32)
124DECODE_SDWA(Src16)
125DECODE_SDWA(VopcDst)
Sam Kolton363f47a2017-05-26 15:52:00 +0000126
Tom Stellarde1818af2016-02-18 03:42:32 +0000127#include "AMDGPUGenDisassemblerTables.inc"
128
129//===----------------------------------------------------------------------===//
130//
131//===----------------------------------------------------------------------===//
132
Sam Kolton1048fb12016-03-31 14:15:04 +0000133template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) {
134 assert(Bytes.size() >= sizeof(T));
135 const auto Res = support::endian::read<T, support::endianness::little>(Bytes.data());
136 Bytes = Bytes.slice(sizeof(T));
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000137 return Res;
138}
139
140DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t* Table,
141 MCInst &MI,
142 uint64_t Inst,
143 uint64_t Address) const {
144 assert(MI.getOpcode() == 0);
145 assert(MI.getNumOperands() == 0);
146 MCInst TmpInst;
Dmitry Preobrazhenskyce941c92017-05-19 14:27:52 +0000147 HasLiteral = false;
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000148 const auto SavedBytes = Bytes;
149 if (decodeInstruction(Table, TmpInst, Inst, Address, this, STI)) {
150 MI = TmpInst;
151 return MCDisassembler::Success;
152 }
153 Bytes = SavedBytes;
154 return MCDisassembler::Fail;
155}
156
Tom Stellarde1818af2016-02-18 03:42:32 +0000157DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000158 ArrayRef<uint8_t> Bytes_,
Nikolay Haustov161a1582016-02-25 16:09:14 +0000159 uint64_t Address,
Tom Stellarde1818af2016-02-18 03:42:32 +0000160 raw_ostream &WS,
161 raw_ostream &CS) const {
162 CommentStream = &CS;
Sam Kolton549c89d2017-06-21 08:53:38 +0000163 bool IsSDWA = false;
Tom Stellarde1818af2016-02-18 03:42:32 +0000164
165 // ToDo: AMDGPUDisassembler supports only VI ISA.
Matt Arsenaultd122abe2017-02-15 21:50:34 +0000166 if (!STI.getFeatureBits()[AMDGPU::FeatureGCN3Encoding])
167 report_fatal_error("Disassembly not yet supported for subtarget");
Tom Stellarde1818af2016-02-18 03:42:32 +0000168
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000169 const unsigned MaxInstBytesNum = (std::min)((size_t)8, Bytes_.size());
170 Bytes = Bytes_.slice(0, MaxInstBytesNum);
Nikolay Haustov161a1582016-02-25 16:09:14 +0000171
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000172 DecodeStatus Res = MCDisassembler::Fail;
173 do {
Valery Pykhtin824e8042016-03-04 10:59:50 +0000174 // ToDo: better to switch encoding length using some bit predicate
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000175 // but it is unknown yet, so try all we can
Matt Arsenault37fefd62016-06-10 02:18:02 +0000176
Sam Koltonc9bdcb72016-06-09 11:04:45 +0000177 // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2
178 // encodings
Sam Kolton1048fb12016-03-31 14:15:04 +0000179 if (Bytes.size() >= 8) {
180 const uint64_t QW = eatBytes<uint64_t>(Bytes);
181 Res = tryDecodeInst(DecoderTableDPP64, MI, QW, Address);
182 if (Res) break;
Sam Koltonc9bdcb72016-06-09 11:04:45 +0000183
184 Res = tryDecodeInst(DecoderTableSDWA64, MI, QW, Address);
Sam Kolton549c89d2017-06-21 08:53:38 +0000185 if (Res) { IsSDWA = true; break; }
Sam Kolton363f47a2017-05-26 15:52:00 +0000186
187 Res = tryDecodeInst(DecoderTableSDWA964, MI, QW, Address);
Sam Kolton549c89d2017-06-21 08:53:38 +0000188 if (Res) { IsSDWA = true; break; }
Sam Kolton1048fb12016-03-31 14:15:04 +0000189 }
190
191 // Reinitialize Bytes as DPP64 could have eaten too much
192 Bytes = Bytes_.slice(0, MaxInstBytesNum);
193
194 // Try decode 32-bit instruction
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000195 if (Bytes.size() < 4) break;
Sam Kolton1048fb12016-03-31 14:15:04 +0000196 const uint32_t DW = eatBytes<uint32_t>(Bytes);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000197 Res = tryDecodeInst(DecoderTableVI32, MI, DW, Address);
198 if (Res) break;
Tom Stellarde1818af2016-02-18 03:42:32 +0000199
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000200 Res = tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address);
201 if (Res) break;
Tom Stellarde1818af2016-02-18 03:42:32 +0000202
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000203 if (Bytes.size() < 4) break;
Sam Kolton1048fb12016-03-31 14:15:04 +0000204 const uint64_t QW = ((uint64_t)eatBytes<uint32_t>(Bytes) << 32) | DW;
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000205 Res = tryDecodeInst(DecoderTableVI64, MI, QW, Address);
206 if (Res) break;
207
208 Res = tryDecodeInst(DecoderTableAMDGPU64, MI, QW, Address);
209 } while (false);
210
Matt Arsenault678e1112017-04-10 17:58:06 +0000211 if (Res && (MI.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||
212 MI.getOpcode() == AMDGPU::V_MAC_F32_e64_si ||
213 MI.getOpcode() == AMDGPU::V_MAC_F16_e64_vi)) {
214 // Insert dummy unused src2_modifiers.
Sam Kolton549c89d2017-06-21 08:53:38 +0000215 insertNamedMCOperand(MI, MCOperand::createImm(0),
216 AMDGPU::OpName::src2_modifiers);
Matt Arsenault678e1112017-04-10 17:58:06 +0000217 }
218
Sam Kolton549c89d2017-06-21 08:53:38 +0000219 if (Res && IsSDWA)
220 Res = convertSDWAInst(MI);
221
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000222 Size = Res ? (MaxInstBytesNum - Bytes.size()) : 0;
223 return Res;
Tom Stellarde1818af2016-02-18 03:42:32 +0000224}
225
Sam Kolton549c89d2017-06-21 08:53:38 +0000226DecodeStatus AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const {
227 if (STI.getFeatureBits()[AMDGPU::FeatureGFX9]) {
228 if (AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sdst) != -1)
229 // VOPC - insert clamp
230 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::clamp);
231 } else if (STI.getFeatureBits()[AMDGPU::FeatureVolcanicIslands]) {
232 int SDst = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sdst);
233 if (SDst != -1) {
234 // VOPC - insert VCC register as sdst
235 insertNamedMCOperand(MI, MCOperand::createReg(AMDGPU::VCC),
236 AMDGPU::OpName::sdst);
237 } else {
238 // VOP1/2 - insert omod if present in instruction
239 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::omod);
240 }
241 }
242 return MCDisassembler::Success;
243}
244
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000245const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const {
246 return getContext().getRegisterInfo()->
247 getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]);
Tom Stellarde1818af2016-02-18 03:42:32 +0000248}
249
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000250inline
251MCOperand AMDGPUDisassembler::errOperand(unsigned V,
252 const Twine& ErrMsg) const {
253 *CommentStream << "Error: " + ErrMsg;
254
255 // ToDo: add support for error operands to MCInst.h
256 // return MCOperand::createError(V);
257 return MCOperand();
Nikolay Haustov161a1582016-02-25 16:09:14 +0000258}
259
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000260inline
261MCOperand AMDGPUDisassembler::createRegOperand(unsigned int RegId) const {
262 return MCOperand::createReg(RegId);
Tom Stellarde1818af2016-02-18 03:42:32 +0000263}
264
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000265inline
266MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID,
267 unsigned Val) const {
268 const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID];
269 if (Val >= RegCl.getNumRegs())
270 return errOperand(Val, Twine(getRegClassName(RegClassID)) +
271 ": unknown register " + Twine(Val));
272 return createRegOperand(RegCl.getRegister(Val));
Tom Stellarde1818af2016-02-18 03:42:32 +0000273}
274
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000275inline
276MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID,
277 unsigned Val) const {
Tom Stellarde1818af2016-02-18 03:42:32 +0000278 // ToDo: SI/CI have 104 SGPRs, VI - 102
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000279 // Valery: here we accepting as much as we can, let assembler sort it out
280 int shift = 0;
281 switch (SRegClassID) {
282 case AMDGPU::SGPR_32RegClassID:
Artem Tamazov212a2512016-05-24 12:05:16 +0000283 case AMDGPU::TTMP_32RegClassID:
284 break;
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000285 case AMDGPU::SGPR_64RegClassID:
Artem Tamazov212a2512016-05-24 12:05:16 +0000286 case AMDGPU::TTMP_64RegClassID:
287 shift = 1;
288 break;
289 case AMDGPU::SGPR_128RegClassID:
290 case AMDGPU::TTMP_128RegClassID:
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000291 // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in
292 // this bundle?
293 case AMDGPU::SReg_256RegClassID:
294 // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in
295 // this bundle?
Artem Tamazov212a2512016-05-24 12:05:16 +0000296 case AMDGPU::SReg_512RegClassID:
297 shift = 2;
298 break;
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000299 // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in
300 // this bundle?
Artem Tamazov212a2512016-05-24 12:05:16 +0000301 default:
Matt Arsenault92b355b2016-11-15 19:34:37 +0000302 llvm_unreachable("unhandled register class");
Tom Stellarde1818af2016-02-18 03:42:32 +0000303 }
Matt Arsenault92b355b2016-11-15 19:34:37 +0000304
305 if (Val % (1 << shift)) {
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000306 *CommentStream << "Warning: " << getRegClassName(SRegClassID)
307 << ": scalar reg isn't aligned " << Val;
Matt Arsenault92b355b2016-11-15 19:34:37 +0000308 }
309
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000310 return createRegOperand(SRegClassID, Val >> shift);
Tom Stellarde1818af2016-02-18 03:42:32 +0000311}
312
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000313MCOperand AMDGPUDisassembler::decodeOperand_VS_32(unsigned Val) const {
Artem Tamazov212a2512016-05-24 12:05:16 +0000314 return decodeSrcOp(OPW32, Val);
Tom Stellarde1818af2016-02-18 03:42:32 +0000315}
316
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000317MCOperand AMDGPUDisassembler::decodeOperand_VS_64(unsigned Val) const {
Artem Tamazov212a2512016-05-24 12:05:16 +0000318 return decodeSrcOp(OPW64, Val);
Nikolay Haustov161a1582016-02-25 16:09:14 +0000319}
320
Matt Arsenault4bd72362016-12-10 00:39:12 +0000321MCOperand AMDGPUDisassembler::decodeOperand_VSrc16(unsigned Val) const {
322 return decodeSrcOp(OPW16, Val);
323}
324
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000325MCOperand AMDGPUDisassembler::decodeOperand_VSrcV216(unsigned Val) const {
326 return decodeSrcOp(OPWV216, Val);
327}
328
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000329MCOperand AMDGPUDisassembler::decodeOperand_VGPR_32(unsigned Val) const {
Matt Arsenaultcb540bc2016-07-19 00:35:03 +0000330 // Some instructions have operand restrictions beyond what the encoding
331 // allows. Some ordinarily VSrc_32 operands are VGPR_32, so clear the extra
332 // high bit.
333 Val &= 255;
334
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000335 return createRegOperand(AMDGPU::VGPR_32RegClassID, Val);
336}
337
338MCOperand AMDGPUDisassembler::decodeOperand_VReg_64(unsigned Val) const {
339 return createRegOperand(AMDGPU::VReg_64RegClassID, Val);
340}
341
342MCOperand AMDGPUDisassembler::decodeOperand_VReg_96(unsigned Val) const {
343 return createRegOperand(AMDGPU::VReg_96RegClassID, Val);
344}
345
346MCOperand AMDGPUDisassembler::decodeOperand_VReg_128(unsigned Val) const {
347 return createRegOperand(AMDGPU::VReg_128RegClassID, Val);
348}
349
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000350MCOperand AMDGPUDisassembler::decodeOperand_SReg_32(unsigned Val) const {
351 // table-gen generated disassembler doesn't care about operand types
352 // leaving only registry class so SSrc_32 operand turns into SReg_32
353 // and therefore we accept immediates and literals here as well
Artem Tamazov212a2512016-05-24 12:05:16 +0000354 return decodeSrcOp(OPW32, Val);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000355}
356
Matt Arsenault640c44b2016-11-29 19:39:53 +0000357MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XM0_XEXEC(
358 unsigned Val) const {
359 // SReg_32_XM0 is SReg_32 without M0 or EXEC_LO/EXEC_HI
Artem Tamazov38e496b2016-04-29 17:04:50 +0000360 return decodeOperand_SReg_32(Val);
361}
362
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000363MCOperand AMDGPUDisassembler::decodeOperand_SReg_64(unsigned Val) const {
Matt Arsenault640c44b2016-11-29 19:39:53 +0000364 return decodeSrcOp(OPW64, Val);
365}
366
367MCOperand AMDGPUDisassembler::decodeOperand_SReg_64_XEXEC(unsigned Val) const {
Artem Tamazov212a2512016-05-24 12:05:16 +0000368 return decodeSrcOp(OPW64, Val);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000369}
370
371MCOperand AMDGPUDisassembler::decodeOperand_SReg_128(unsigned Val) const {
Artem Tamazov212a2512016-05-24 12:05:16 +0000372 return decodeSrcOp(OPW128, Val);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000373}
374
375MCOperand AMDGPUDisassembler::decodeOperand_SReg_256(unsigned Val) const {
376 return createSRegOperand(AMDGPU::SReg_256RegClassID, Val);
377}
378
379MCOperand AMDGPUDisassembler::decodeOperand_SReg_512(unsigned Val) const {
380 return createSRegOperand(AMDGPU::SReg_512RegClassID, Val);
381}
382
383
384MCOperand AMDGPUDisassembler::decodeLiteralConstant() const {
Nikolay Haustov161a1582016-02-25 16:09:14 +0000385 // For now all literal constants are supposed to be unsigned integer
386 // ToDo: deal with signed/unsigned 64-bit integer constants
387 // ToDo: deal with float/double constants
Dmitry Preobrazhenskyce941c92017-05-19 14:27:52 +0000388 if (!HasLiteral) {
389 if (Bytes.size() < 4) {
390 return errOperand(0, "cannot read literal, inst bytes left " +
391 Twine(Bytes.size()));
392 }
393 HasLiteral = true;
394 Literal = eatBytes<uint32_t>(Bytes);
395 }
396 return MCOperand::createImm(Literal);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000397}
398
399MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) {
Artem Tamazov212a2512016-05-24 12:05:16 +0000400 using namespace AMDGPU::EncValues;
401 assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX);
402 return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ?
403 (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) :
404 (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm)));
405 // Cast prevents negative overflow.
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000406}
407
Matt Arsenault4bd72362016-12-10 00:39:12 +0000408static int64_t getInlineImmVal32(unsigned Imm) {
409 switch (Imm) {
410 case 240:
411 return FloatToBits(0.5f);
412 case 241:
413 return FloatToBits(-0.5f);
414 case 242:
415 return FloatToBits(1.0f);
416 case 243:
417 return FloatToBits(-1.0f);
418 case 244:
419 return FloatToBits(2.0f);
420 case 245:
421 return FloatToBits(-2.0f);
422 case 246:
423 return FloatToBits(4.0f);
424 case 247:
425 return FloatToBits(-4.0f);
426 case 248: // 1 / (2 * PI)
427 return 0x3e22f983;
428 default:
429 llvm_unreachable("invalid fp inline imm");
430 }
431}
432
433static int64_t getInlineImmVal64(unsigned Imm) {
434 switch (Imm) {
435 case 240:
436 return DoubleToBits(0.5);
437 case 241:
438 return DoubleToBits(-0.5);
439 case 242:
440 return DoubleToBits(1.0);
441 case 243:
442 return DoubleToBits(-1.0);
443 case 244:
444 return DoubleToBits(2.0);
445 case 245:
446 return DoubleToBits(-2.0);
447 case 246:
448 return DoubleToBits(4.0);
449 case 247:
450 return DoubleToBits(-4.0);
451 case 248: // 1 / (2 * PI)
452 return 0x3fc45f306dc9c882;
453 default:
454 llvm_unreachable("invalid fp inline imm");
455 }
456}
457
458static int64_t getInlineImmVal16(unsigned Imm) {
459 switch (Imm) {
460 case 240:
461 return 0x3800;
462 case 241:
463 return 0xB800;
464 case 242:
465 return 0x3C00;
466 case 243:
467 return 0xBC00;
468 case 244:
469 return 0x4000;
470 case 245:
471 return 0xC000;
472 case 246:
473 return 0x4400;
474 case 247:
475 return 0xC400;
476 case 248: // 1 / (2 * PI)
477 return 0x3118;
478 default:
479 llvm_unreachable("invalid fp inline imm");
480 }
481}
482
483MCOperand AMDGPUDisassembler::decodeFPImmed(OpWidthTy Width, unsigned Imm) {
Artem Tamazov212a2512016-05-24 12:05:16 +0000484 assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN
485 && Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX);
Matt Arsenault4bd72362016-12-10 00:39:12 +0000486
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000487 // ToDo: case 248: 1/(2*PI) - is allowed only on VI
Matt Arsenault4bd72362016-12-10 00:39:12 +0000488 switch (Width) {
489 case OPW32:
490 return MCOperand::createImm(getInlineImmVal32(Imm));
491 case OPW64:
492 return MCOperand::createImm(getInlineImmVal64(Imm));
493 case OPW16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000494 case OPWV216:
Matt Arsenault4bd72362016-12-10 00:39:12 +0000495 return MCOperand::createImm(getInlineImmVal16(Imm));
496 default:
497 llvm_unreachable("implement me");
Nikolay Haustov161a1582016-02-25 16:09:14 +0000498 }
Nikolay Haustov161a1582016-02-25 16:09:14 +0000499}
500
Artem Tamazov212a2512016-05-24 12:05:16 +0000501unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const {
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000502 using namespace AMDGPU;
Artem Tamazov212a2512016-05-24 12:05:16 +0000503 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
504 switch (Width) {
505 default: // fall
Matt Arsenault4bd72362016-12-10 00:39:12 +0000506 case OPW32:
507 case OPW16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000508 case OPWV216:
Matt Arsenault4bd72362016-12-10 00:39:12 +0000509 return VGPR_32RegClassID;
Artem Tamazov212a2512016-05-24 12:05:16 +0000510 case OPW64: return VReg_64RegClassID;
511 case OPW128: return VReg_128RegClassID;
512 }
513}
514
515unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const {
516 using namespace AMDGPU;
517 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
518 switch (Width) {
519 default: // fall
Matt Arsenault4bd72362016-12-10 00:39:12 +0000520 case OPW32:
521 case OPW16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000522 case OPWV216:
Matt Arsenault4bd72362016-12-10 00:39:12 +0000523 return SGPR_32RegClassID;
Artem Tamazov212a2512016-05-24 12:05:16 +0000524 case OPW64: return SGPR_64RegClassID;
525 case OPW128: return SGPR_128RegClassID;
526 }
527}
528
529unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const {
530 using namespace AMDGPU;
531 assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
532 switch (Width) {
533 default: // fall
Matt Arsenault4bd72362016-12-10 00:39:12 +0000534 case OPW32:
535 case OPW16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000536 case OPWV216:
Matt Arsenault4bd72362016-12-10 00:39:12 +0000537 return TTMP_32RegClassID;
Artem Tamazov212a2512016-05-24 12:05:16 +0000538 case OPW64: return TTMP_64RegClassID;
539 case OPW128: return TTMP_128RegClassID;
540 }
541}
542
543MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val) const {
544 using namespace AMDGPU::EncValues;
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000545 assert(Val < 512); // enum9
546
Artem Tamazov212a2512016-05-24 12:05:16 +0000547 if (VGPR_MIN <= Val && Val <= VGPR_MAX) {
548 return createRegOperand(getVgprClassId(Width), Val - VGPR_MIN);
549 }
Artem Tamazovb49c3362016-05-26 15:52:16 +0000550 if (Val <= SGPR_MAX) {
551 assert(SGPR_MIN == 0); // "SGPR_MIN <= Val" is always true and causes compilation warning.
Artem Tamazov212a2512016-05-24 12:05:16 +0000552 return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN);
553 }
554 if (TTMP_MIN <= Val && Val <= TTMP_MAX) {
555 return createSRegOperand(getTtmpClassId(Width), Val - TTMP_MIN);
556 }
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000557
Matt Arsenault4bd72362016-12-10 00:39:12 +0000558 assert(Width == OPW16 || Width == OPW32 || Width == OPW64);
Artem Tamazov212a2512016-05-24 12:05:16 +0000559
560 if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX)
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000561 return decodeIntImmed(Val);
562
Artem Tamazov212a2512016-05-24 12:05:16 +0000563 if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX)
Matt Arsenault4bd72362016-12-10 00:39:12 +0000564 return decodeFPImmed(Width, Val);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000565
Artem Tamazov212a2512016-05-24 12:05:16 +0000566 if (Val == LITERAL_CONST)
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000567 return decodeLiteralConstant();
568
Matt Arsenault4bd72362016-12-10 00:39:12 +0000569 switch (Width) {
570 case OPW32:
571 case OPW16:
Matt Arsenault9be7b0d2017-02-27 18:49:11 +0000572 case OPWV216:
Matt Arsenault4bd72362016-12-10 00:39:12 +0000573 return decodeSpecialReg32(Val);
574 case OPW64:
575 return decodeSpecialReg64(Val);
576 default:
577 llvm_unreachable("unexpected immediate type");
578 }
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000579}
580
581MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const {
582 using namespace AMDGPU;
583 switch (Val) {
584 case 102: return createRegOperand(getMCReg(FLAT_SCR_LO, STI));
585 case 103: return createRegOperand(getMCReg(FLAT_SCR_HI, STI));
586 // ToDo: no support for xnack_mask_lo/_hi register
587 case 104:
588 case 105: break;
589 case 106: return createRegOperand(VCC_LO);
590 case 107: return createRegOperand(VCC_HI);
Artem Tamazov212a2512016-05-24 12:05:16 +0000591 case 108: return createRegOperand(TBA_LO);
592 case 109: return createRegOperand(TBA_HI);
593 case 110: return createRegOperand(TMA_LO);
594 case 111: return createRegOperand(TMA_HI);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000595 case 124: return createRegOperand(M0);
596 case 126: return createRegOperand(EXEC_LO);
597 case 127: return createRegOperand(EXEC_HI);
Matt Arsenaulta3b3b482017-02-18 18:41:41 +0000598 case 235: return createRegOperand(SRC_SHARED_BASE);
599 case 236: return createRegOperand(SRC_SHARED_LIMIT);
600 case 237: return createRegOperand(SRC_PRIVATE_BASE);
601 case 238: return createRegOperand(SRC_PRIVATE_LIMIT);
602 // TODO: SRC_POPS_EXITING_WAVE_ID
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000603 // ToDo: no support for vccz register
604 case 251: break;
605 // ToDo: no support for execz register
606 case 252: break;
607 case 253: return createRegOperand(SCC);
608 default: break;
Tom Stellarde1818af2016-02-18 03:42:32 +0000609 }
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000610 return errOperand(Val, "unknown operand encoding " + Twine(Val));
Tom Stellarde1818af2016-02-18 03:42:32 +0000611}
612
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000613MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {
614 using namespace AMDGPU;
615 switch (Val) {
616 case 102: return createRegOperand(getMCReg(FLAT_SCR, STI));
617 case 106: return createRegOperand(VCC);
Artem Tamazov212a2512016-05-24 12:05:16 +0000618 case 108: return createRegOperand(TBA);
619 case 110: return createRegOperand(TMA);
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000620 case 126: return createRegOperand(EXEC);
621 default: break;
Tom Stellarde1818af2016-02-18 03:42:32 +0000622 }
Nikolay Haustovac106ad2016-03-01 13:57:29 +0000623 return errOperand(Val, "unknown operand encoding " + Twine(Val));
Tom Stellarde1818af2016-02-18 03:42:32 +0000624}
625
Sam Kolton549c89d2017-06-21 08:53:38 +0000626MCOperand AMDGPUDisassembler::decodeSDWASrc(const OpWidthTy Width,
627 unsigned Val) const {
Sam Kolton363f47a2017-05-26 15:52:00 +0000628 using namespace AMDGPU::SDWA;
629
Sam Kolton549c89d2017-06-21 08:53:38 +0000630 if (STI.getFeatureBits()[AMDGPU::FeatureGFX9]) {
631 if (SDWA9EncValues::SRC_VGPR_MIN <= Val &&
632 Val <= SDWA9EncValues::SRC_VGPR_MAX) {
633 return createRegOperand(getVgprClassId(Width),
634 Val - SDWA9EncValues::SRC_VGPR_MIN);
635 }
636 if (SDWA9EncValues::SRC_SGPR_MIN <= Val &&
637 Val <= SDWA9EncValues::SRC_SGPR_MAX) {
638 return createSRegOperand(getSgprClassId(Width),
639 Val - SDWA9EncValues::SRC_SGPR_MIN);
640 }
641
642 return decodeSpecialReg32(Val - SDWA9EncValues::SRC_SGPR_MIN);
643 } else if (STI.getFeatureBits()[AMDGPU::FeatureVolcanicIslands]) {
644 return createRegOperand(getVgprClassId(Width), Val);
Sam Kolton363f47a2017-05-26 15:52:00 +0000645 }
Sam Kolton549c89d2017-06-21 08:53:38 +0000646 llvm_unreachable("unsupported target");
Sam Kolton363f47a2017-05-26 15:52:00 +0000647}
648
Sam Kolton549c89d2017-06-21 08:53:38 +0000649MCOperand AMDGPUDisassembler::decodeSDWASrc16(unsigned Val) const {
650 return decodeSDWASrc(OPW16, Val);
Sam Kolton363f47a2017-05-26 15:52:00 +0000651}
652
Sam Kolton549c89d2017-06-21 08:53:38 +0000653MCOperand AMDGPUDisassembler::decodeSDWASrc32(unsigned Val) const {
654 return decodeSDWASrc(OPW32, Val);
Sam Kolton363f47a2017-05-26 15:52:00 +0000655}
656
657
Sam Kolton549c89d2017-06-21 08:53:38 +0000658MCOperand AMDGPUDisassembler::decodeSDWAVopcDst(unsigned Val) const {
Sam Kolton363f47a2017-05-26 15:52:00 +0000659 using namespace AMDGPU::SDWA;
660
Sam Kolton549c89d2017-06-21 08:53:38 +0000661 assert(STI.getFeatureBits()[AMDGPU::FeatureGFX9] &&
662 "SDWAVopcDst should be present only on GFX9");
Sam Kolton363f47a2017-05-26 15:52:00 +0000663 if (Val & SDWA9EncValues::VOPC_DST_VCC_MASK) {
664 Val &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
665 if (Val > AMDGPU::EncValues::SGPR_MAX) {
666 return decodeSpecialReg64(Val);
667 } else {
668 return createSRegOperand(getSgprClassId(OPW64), Val);
669 }
670 } else {
671 return createRegOperand(AMDGPU::VCC);
672 }
673}
674
Sam Kolton3381d7a2016-10-06 13:46:08 +0000675//===----------------------------------------------------------------------===//
676// AMDGPUSymbolizer
677//===----------------------------------------------------------------------===//
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000678
Sam Kolton3381d7a2016-10-06 13:46:08 +0000679// Try to find symbol name for specified label
680bool AMDGPUSymbolizer::tryAddingSymbolicOperand(MCInst &Inst,
681 raw_ostream &/*cStream*/, int64_t Value,
682 uint64_t /*Address*/, bool IsBranch,
683 uint64_t /*Offset*/, uint64_t /*InstSize*/) {
684 typedef std::tuple<uint64_t, StringRef, uint8_t> SymbolInfoTy;
685 typedef std::vector<SymbolInfoTy> SectionSymbolsTy;
686
687 if (!IsBranch) {
688 return false;
689 }
690
691 auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo);
692 auto Result = std::find_if(Symbols->begin(), Symbols->end(),
693 [Value](const SymbolInfoTy& Val) {
694 return std::get<0>(Val) == static_cast<uint64_t>(Value)
695 && std::get<2>(Val) == ELF::STT_NOTYPE;
696 });
697 if (Result != Symbols->end()) {
698 auto *Sym = Ctx.getOrCreateSymbol(std::get<1>(*Result));
699 const auto *Add = MCSymbolRefExpr::create(Sym, Ctx);
700 Inst.addOperand(MCOperand::createExpr(Add));
701 return true;
702 }
703 return false;
704}
705
Matt Arsenault92b355b2016-11-15 19:34:37 +0000706void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
707 int64_t Value,
708 uint64_t Address) {
709 llvm_unreachable("unimplemented");
710}
711
Sam Kolton3381d7a2016-10-06 13:46:08 +0000712//===----------------------------------------------------------------------===//
713// Initialization
714//===----------------------------------------------------------------------===//
715
716static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/,
717 LLVMOpInfoCallback /*GetOpInfo*/,
718 LLVMSymbolLookupCallback /*SymbolLookUp*/,
Matt Arsenaultf3dd8632016-11-01 00:55:14 +0000719 void *DisInfo,
Sam Kolton3381d7a2016-10-06 13:46:08 +0000720 MCContext *Ctx,
721 std::unique_ptr<MCRelocationInfo> &&RelInfo) {
722 return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo);
723}
724
Tom Stellarde1818af2016-02-18 03:42:32 +0000725static MCDisassembler *createAMDGPUDisassembler(const Target &T,
726 const MCSubtargetInfo &STI,
727 MCContext &Ctx) {
728 return new AMDGPUDisassembler(STI, Ctx);
729}
730
731extern "C" void LLVMInitializeAMDGPUDisassembler() {
Mehdi Aminif42454b2016-10-09 23:00:34 +0000732 TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(),
733 createAMDGPUDisassembler);
734 TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(),
735 createAMDGPUSymbolizer);
Tom Stellarde1818af2016-02-18 03:42:32 +0000736}