1e1818af8STom Stellard //===-- AMDGPUDisassembler.cpp - Disassembler for AMDGPU ISA --------------===//
2e1818af8STom Stellard //
3e1818af8STom Stellard //                     The LLVM Compiler Infrastructure
4e1818af8STom Stellard //
5e1818af8STom Stellard // This file is distributed under the University of Illinois Open Source
6e1818af8STom Stellard // License. See LICENSE.TXT for details.
7e1818af8STom Stellard //
8e1818af8STom Stellard //===----------------------------------------------------------------------===//
9e1818af8STom Stellard //
10e1818af8STom Stellard //===----------------------------------------------------------------------===//
11e1818af8STom Stellard //
12e1818af8STom Stellard /// \file
13e1818af8STom Stellard ///
14e1818af8STom Stellard /// This file contains definition for AMDGPU ISA disassembler
15e1818af8STom Stellard //
16e1818af8STom Stellard //===----------------------------------------------------------------------===//
17e1818af8STom Stellard 
18e1818af8STom Stellard // ToDo: What to do with instruction suffixes (v_mov_b32 vs v_mov_b32_e32)?
19e1818af8STom Stellard 
20e1818af8STom Stellard #include "AMDGPUDisassembler.h"
21e1818af8STom Stellard #include "AMDGPU.h"
22e1818af8STom Stellard #include "AMDGPURegisterInfo.h"
23212a251cSArtem Tamazov #include "SIDefines.h"
24e1818af8STom Stellard #include "Utils/AMDGPUBaseInfo.h"
25e1818af8STom Stellard 
26ac106addSNikolay Haustov #include "llvm/MC/MCContext.h"
27e1818af8STom Stellard #include "llvm/MC/MCFixedLenDisassembler.h"
28e1818af8STom Stellard #include "llvm/MC/MCInst.h"
29e1818af8STom Stellard #include "llvm/MC/MCInstrDesc.h"
30e1818af8STom Stellard #include "llvm/MC/MCSubtargetInfo.h"
31*3381d7a2SSam Kolton #include "llvm/Support/ELF.h"
32ac106addSNikolay Haustov #include "llvm/Support/Endian.h"
33e1818af8STom Stellard #include "llvm/Support/Debug.h"
34e1818af8STom Stellard #include "llvm/Support/TargetRegistry.h"
35e1818af8STom Stellard 
36e1818af8STom Stellard 
37e1818af8STom Stellard using namespace llvm;
38e1818af8STom Stellard 
39e1818af8STom Stellard #define DEBUG_TYPE "amdgpu-disassembler"
40e1818af8STom Stellard 
41e1818af8STom Stellard typedef llvm::MCDisassembler::DecodeStatus DecodeStatus;
42e1818af8STom Stellard 
43e1818af8STom Stellard 
44ac106addSNikolay Haustov inline static MCDisassembler::DecodeStatus
45ac106addSNikolay Haustov addOperand(MCInst &Inst, const MCOperand& Opnd) {
46ac106addSNikolay Haustov   Inst.addOperand(Opnd);
47ac106addSNikolay Haustov   return Opnd.isValid() ?
48ac106addSNikolay Haustov     MCDisassembler::Success :
49ac106addSNikolay Haustov     MCDisassembler::SoftFail;
50e1818af8STom Stellard }
51e1818af8STom Stellard 
52*3381d7a2SSam Kolton static DecodeStatus decodeSoppBrTarget(MCInst &Inst, unsigned Imm,
53*3381d7a2SSam Kolton                                        uint64_t Addr, const void *Decoder) {
54*3381d7a2SSam Kolton   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
55*3381d7a2SSam Kolton 
56*3381d7a2SSam Kolton   APInt SignedOffset(18, Imm * 4, true);
57*3381d7a2SSam Kolton   int64_t Offset = (SignedOffset.sext(64) + 4 + Addr).getSExtValue();
58*3381d7a2SSam Kolton 
59*3381d7a2SSam Kolton   if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2))
60*3381d7a2SSam Kolton     return MCDisassembler::Success;
61*3381d7a2SSam Kolton   return addOperand(Inst, MCOperand::createImm(Imm));
62*3381d7a2SSam Kolton }
63*3381d7a2SSam Kolton 
64ac106addSNikolay Haustov #define DECODE_OPERAND2(RegClass, DecName) \
65ac106addSNikolay Haustov static DecodeStatus Decode##RegClass##RegisterClass(MCInst &Inst, \
66ac106addSNikolay Haustov                                                     unsigned Imm, \
67ac106addSNikolay Haustov                                                     uint64_t /*Addr*/, \
68ac106addSNikolay Haustov                                                     const void *Decoder) { \
69ac106addSNikolay Haustov   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); \
70ac106addSNikolay Haustov   return addOperand(Inst, DAsm->decodeOperand_##DecName(Imm)); \
71e1818af8STom Stellard }
72e1818af8STom Stellard 
73ac106addSNikolay Haustov #define DECODE_OPERAND(RegClass) DECODE_OPERAND2(RegClass, RegClass)
74e1818af8STom Stellard 
75ac106addSNikolay Haustov DECODE_OPERAND(VGPR_32)
76ac106addSNikolay Haustov DECODE_OPERAND(VS_32)
77ac106addSNikolay Haustov DECODE_OPERAND(VS_64)
78e1818af8STom Stellard 
79ac106addSNikolay Haustov DECODE_OPERAND(VReg_64)
80ac106addSNikolay Haustov DECODE_OPERAND(VReg_96)
81ac106addSNikolay Haustov DECODE_OPERAND(VReg_128)
82e1818af8STom Stellard 
83ac106addSNikolay Haustov DECODE_OPERAND(SReg_32)
8438e496b1SArtem Tamazov DECODE_OPERAND(SReg_32_XM0)
85ac106addSNikolay Haustov DECODE_OPERAND(SReg_64)
86ac106addSNikolay Haustov DECODE_OPERAND(SReg_128)
87ac106addSNikolay Haustov DECODE_OPERAND(SReg_256)
88a4db224dSValery Pykhtin DECODE_OPERAND(SReg_512)
89e1818af8STom Stellard 
90e1818af8STom Stellard #define GET_SUBTARGETINFO_ENUM
91e1818af8STom Stellard #include "AMDGPUGenSubtargetInfo.inc"
92e1818af8STom Stellard #undef GET_SUBTARGETINFO_ENUM
93e1818af8STom Stellard 
94e1818af8STom Stellard #include "AMDGPUGenDisassemblerTables.inc"
95e1818af8STom Stellard 
96e1818af8STom Stellard //===----------------------------------------------------------------------===//
97e1818af8STom Stellard //
98e1818af8STom Stellard //===----------------------------------------------------------------------===//
99e1818af8STom Stellard 
1001048fb18SSam Kolton template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) {
1011048fb18SSam Kolton   assert(Bytes.size() >= sizeof(T));
1021048fb18SSam Kolton   const auto Res = support::endian::read<T, support::endianness::little>(Bytes.data());
1031048fb18SSam Kolton   Bytes = Bytes.slice(sizeof(T));
104ac106addSNikolay Haustov   return Res;
105ac106addSNikolay Haustov }
106ac106addSNikolay Haustov 
107ac106addSNikolay Haustov DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t* Table,
108ac106addSNikolay Haustov                                                MCInst &MI,
109ac106addSNikolay Haustov                                                uint64_t Inst,
110ac106addSNikolay Haustov                                                uint64_t Address) const {
111ac106addSNikolay Haustov   assert(MI.getOpcode() == 0);
112ac106addSNikolay Haustov   assert(MI.getNumOperands() == 0);
113ac106addSNikolay Haustov   MCInst TmpInst;
114ac106addSNikolay Haustov   const auto SavedBytes = Bytes;
115ac106addSNikolay Haustov   if (decodeInstruction(Table, TmpInst, Inst, Address, this, STI)) {
116ac106addSNikolay Haustov     MI = TmpInst;
117ac106addSNikolay Haustov     return MCDisassembler::Success;
118ac106addSNikolay Haustov   }
119ac106addSNikolay Haustov   Bytes = SavedBytes;
120ac106addSNikolay Haustov   return MCDisassembler::Fail;
121ac106addSNikolay Haustov }
122ac106addSNikolay Haustov 
123e1818af8STom Stellard DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
124ac106addSNikolay Haustov                                                 ArrayRef<uint8_t> Bytes_,
125e1818af8STom Stellard                                                 uint64_t Address,
126e1818af8STom Stellard                                                 raw_ostream &WS,
127e1818af8STom Stellard                                                 raw_ostream &CS) const {
128e1818af8STom Stellard   CommentStream = &CS;
129e1818af8STom Stellard 
130e1818af8STom Stellard   // ToDo: AMDGPUDisassembler supports only VI ISA.
131e1818af8STom Stellard   assert(AMDGPU::isVI(STI) && "Can disassemble only VI ISA.");
132e1818af8STom Stellard 
133ac106addSNikolay Haustov   const unsigned MaxInstBytesNum = (std::min)((size_t)8, Bytes_.size());
134ac106addSNikolay Haustov   Bytes = Bytes_.slice(0, MaxInstBytesNum);
135161a158eSNikolay Haustov 
136ac106addSNikolay Haustov   DecodeStatus Res = MCDisassembler::Fail;
137ac106addSNikolay Haustov   do {
138824e804bSValery Pykhtin     // ToDo: better to switch encoding length using some bit predicate
139ac106addSNikolay Haustov     // but it is unknown yet, so try all we can
1401048fb18SSam Kolton 
141c9bdcb75SSam Kolton     // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2
142c9bdcb75SSam Kolton     // encodings
1431048fb18SSam Kolton     if (Bytes.size() >= 8) {
1441048fb18SSam Kolton       const uint64_t QW = eatBytes<uint64_t>(Bytes);
1451048fb18SSam Kolton       Res = tryDecodeInst(DecoderTableDPP64, MI, QW, Address);
1461048fb18SSam Kolton       if (Res) break;
147c9bdcb75SSam Kolton 
148c9bdcb75SSam Kolton       Res = tryDecodeInst(DecoderTableSDWA64, MI, QW, Address);
149c9bdcb75SSam Kolton       if (Res) break;
1501048fb18SSam Kolton     }
1511048fb18SSam Kolton 
1521048fb18SSam Kolton     // Reinitialize Bytes as DPP64 could have eaten too much
1531048fb18SSam Kolton     Bytes = Bytes_.slice(0, MaxInstBytesNum);
1541048fb18SSam Kolton 
1551048fb18SSam Kolton     // Try decode 32-bit instruction
156ac106addSNikolay Haustov     if (Bytes.size() < 4) break;
1571048fb18SSam Kolton     const uint32_t DW = eatBytes<uint32_t>(Bytes);
158ac106addSNikolay Haustov     Res = tryDecodeInst(DecoderTableVI32, MI, DW, Address);
159ac106addSNikolay Haustov     if (Res) break;
160e1818af8STom Stellard 
161ac106addSNikolay Haustov     Res = tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address);
162ac106addSNikolay Haustov     if (Res) break;
163ac106addSNikolay Haustov 
164ac106addSNikolay Haustov     if (Bytes.size() < 4) break;
1651048fb18SSam Kolton     const uint64_t QW = ((uint64_t)eatBytes<uint32_t>(Bytes) << 32) | DW;
166ac106addSNikolay Haustov     Res = tryDecodeInst(DecoderTableVI64, MI, QW, Address);
167ac106addSNikolay Haustov     if (Res) break;
168ac106addSNikolay Haustov 
169ac106addSNikolay Haustov     Res = tryDecodeInst(DecoderTableAMDGPU64, MI, QW, Address);
170ac106addSNikolay Haustov   } while (false);
171ac106addSNikolay Haustov 
172ac106addSNikolay Haustov   Size = Res ? (MaxInstBytesNum - Bytes.size()) : 0;
173ac106addSNikolay Haustov   return Res;
174161a158eSNikolay Haustov }
175e1818af8STom Stellard 
176ac106addSNikolay Haustov const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const {
177ac106addSNikolay Haustov   return getContext().getRegisterInfo()->
178ac106addSNikolay Haustov     getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]);
179e1818af8STom Stellard }
180e1818af8STom Stellard 
181ac106addSNikolay Haustov inline
182ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::errOperand(unsigned V,
183ac106addSNikolay Haustov                                          const Twine& ErrMsg) const {
184ac106addSNikolay Haustov   *CommentStream << "Error: " + ErrMsg;
185ac106addSNikolay Haustov 
186ac106addSNikolay Haustov   // ToDo: add support for error operands to MCInst.h
187ac106addSNikolay Haustov   // return MCOperand::createError(V);
188ac106addSNikolay Haustov   return MCOperand();
189ac106addSNikolay Haustov }
190ac106addSNikolay Haustov 
191ac106addSNikolay Haustov inline
192ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::createRegOperand(unsigned int RegId) const {
193ac106addSNikolay Haustov   return MCOperand::createReg(RegId);
194ac106addSNikolay Haustov }
195ac106addSNikolay Haustov 
196ac106addSNikolay Haustov inline
197ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID,
198ac106addSNikolay Haustov                                                unsigned Val) const {
199ac106addSNikolay Haustov   const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID];
200ac106addSNikolay Haustov   if (Val >= RegCl.getNumRegs())
201ac106addSNikolay Haustov     return errOperand(Val, Twine(getRegClassName(RegClassID)) +
202ac106addSNikolay Haustov                            ": unknown register " + Twine(Val));
203ac106addSNikolay Haustov   return createRegOperand(RegCl.getRegister(Val));
204ac106addSNikolay Haustov }
205ac106addSNikolay Haustov 
206ac106addSNikolay Haustov inline
207ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID,
208ac106addSNikolay Haustov                                                 unsigned Val) const {
209ac106addSNikolay Haustov   // ToDo: SI/CI have 104 SGPRs, VI - 102
210ac106addSNikolay Haustov   // Valery: here we accepting as much as we can, let assembler sort it out
211ac106addSNikolay Haustov   int shift = 0;
212ac106addSNikolay Haustov   switch (SRegClassID) {
213ac106addSNikolay Haustov   case AMDGPU::SGPR_32RegClassID:
214212a251cSArtem Tamazov   case AMDGPU::TTMP_32RegClassID:
215212a251cSArtem Tamazov     break;
216ac106addSNikolay Haustov   case AMDGPU::SGPR_64RegClassID:
217212a251cSArtem Tamazov   case AMDGPU::TTMP_64RegClassID:
218212a251cSArtem Tamazov     shift = 1;
219212a251cSArtem Tamazov     break;
220212a251cSArtem Tamazov   case AMDGPU::SGPR_128RegClassID:
221212a251cSArtem Tamazov   case AMDGPU::TTMP_128RegClassID:
222ac106addSNikolay Haustov   // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in
223ac106addSNikolay Haustov   // this bundle?
224ac106addSNikolay Haustov   case AMDGPU::SReg_256RegClassID:
225ac106addSNikolay Haustov   // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in
226ac106addSNikolay Haustov   // this bundle?
227212a251cSArtem Tamazov   case AMDGPU::SReg_512RegClassID:
228212a251cSArtem Tamazov     shift = 2;
229212a251cSArtem Tamazov     break;
230ac106addSNikolay Haustov   // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in
231ac106addSNikolay Haustov   // this bundle?
232212a251cSArtem Tamazov   default:
233212a251cSArtem Tamazov     assert(false);
234212a251cSArtem Tamazov     break;
235ac106addSNikolay Haustov   }
236ac106addSNikolay Haustov   if (Val % (1 << shift))
237ac106addSNikolay Haustov     *CommentStream << "Warning: " << getRegClassName(SRegClassID)
238ac106addSNikolay Haustov                    << ": scalar reg isn't aligned " << Val;
239ac106addSNikolay Haustov   return createRegOperand(SRegClassID, Val >> shift);
240ac106addSNikolay Haustov }
241ac106addSNikolay Haustov 
242ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VS_32(unsigned Val) const {
243212a251cSArtem Tamazov   return decodeSrcOp(OPW32, Val);
244ac106addSNikolay Haustov }
245ac106addSNikolay Haustov 
246ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VS_64(unsigned Val) const {
247212a251cSArtem Tamazov   return decodeSrcOp(OPW64, Val);
248ac106addSNikolay Haustov }
249ac106addSNikolay Haustov 
250ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VGPR_32(unsigned Val) const {
251cb540bc0SMatt Arsenault   // Some instructions have operand restrictions beyond what the encoding
252cb540bc0SMatt Arsenault   // allows. Some ordinarily VSrc_32 operands are VGPR_32, so clear the extra
253cb540bc0SMatt Arsenault   // high bit.
254cb540bc0SMatt Arsenault   Val &= 255;
255cb540bc0SMatt Arsenault 
256ac106addSNikolay Haustov   return createRegOperand(AMDGPU::VGPR_32RegClassID, Val);
257ac106addSNikolay Haustov }
258ac106addSNikolay Haustov 
259ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VReg_64(unsigned Val) const {
260ac106addSNikolay Haustov   return createRegOperand(AMDGPU::VReg_64RegClassID, Val);
261ac106addSNikolay Haustov }
262ac106addSNikolay Haustov 
263ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VReg_96(unsigned Val) const {
264ac106addSNikolay Haustov   return createRegOperand(AMDGPU::VReg_96RegClassID, Val);
265ac106addSNikolay Haustov }
266ac106addSNikolay Haustov 
267ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VReg_128(unsigned Val) const {
268ac106addSNikolay Haustov   return createRegOperand(AMDGPU::VReg_128RegClassID, Val);
269ac106addSNikolay Haustov }
270ac106addSNikolay Haustov 
271ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_SReg_32(unsigned Val) const {
272ac106addSNikolay Haustov   // table-gen generated disassembler doesn't care about operand types
273ac106addSNikolay Haustov   // leaving only registry class so SSrc_32 operand turns into SReg_32
274ac106addSNikolay Haustov   // and therefore we accept immediates and literals here as well
275212a251cSArtem Tamazov   return decodeSrcOp(OPW32, Val);
276ac106addSNikolay Haustov }
277ac106addSNikolay Haustov 
27838e496b1SArtem Tamazov MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XM0(unsigned Val) const {
27938e496b1SArtem Tamazov   // SReg_32_XM0 is SReg_32 without M0
28038e496b1SArtem Tamazov   return decodeOperand_SReg_32(Val);
28138e496b1SArtem Tamazov }
28238e496b1SArtem Tamazov 
283ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_SReg_64(unsigned Val) const {
284ac106addSNikolay Haustov   // see decodeOperand_SReg_32 comment
285212a251cSArtem Tamazov   return decodeSrcOp(OPW64, Val);
286ac106addSNikolay Haustov }
287ac106addSNikolay Haustov 
288ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_SReg_128(unsigned Val) const {
289212a251cSArtem Tamazov   return decodeSrcOp(OPW128, Val);
290ac106addSNikolay Haustov }
291ac106addSNikolay Haustov 
292ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_SReg_256(unsigned Val) const {
293ac106addSNikolay Haustov   return createSRegOperand(AMDGPU::SReg_256RegClassID, Val);
294ac106addSNikolay Haustov }
295ac106addSNikolay Haustov 
296ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_SReg_512(unsigned Val) const {
297ac106addSNikolay Haustov   return createSRegOperand(AMDGPU::SReg_512RegClassID, Val);
298ac106addSNikolay Haustov }
299ac106addSNikolay Haustov 
300ac106addSNikolay Haustov 
301ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeLiteralConstant() const {
302ac106addSNikolay Haustov   // For now all literal constants are supposed to be unsigned integer
303ac106addSNikolay Haustov   // ToDo: deal with signed/unsigned 64-bit integer constants
304ac106addSNikolay Haustov   // ToDo: deal with float/double constants
305ac106addSNikolay Haustov   if (Bytes.size() < 4)
306ac106addSNikolay Haustov     return errOperand(0, "cannot read literal, inst bytes left " +
307ac106addSNikolay Haustov                          Twine(Bytes.size()));
3081048fb18SSam Kolton   return MCOperand::createImm(eatBytes<uint32_t>(Bytes));
309ac106addSNikolay Haustov }
310ac106addSNikolay Haustov 
311ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) {
312212a251cSArtem Tamazov   using namespace AMDGPU::EncValues;
313212a251cSArtem Tamazov   assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX);
314212a251cSArtem Tamazov   return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ?
315212a251cSArtem Tamazov     (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) :
316212a251cSArtem Tamazov     (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm)));
317212a251cSArtem Tamazov       // Cast prevents negative overflow.
318ac106addSNikolay Haustov }
319ac106addSNikolay Haustov 
320ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeFPImmed(bool Is32, unsigned Imm) {
321212a251cSArtem Tamazov   assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN
322212a251cSArtem Tamazov       && Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX);
323e1818af8STom Stellard   // ToDo: case 248: 1/(2*PI) - is allowed only on VI
324e1818af8STom Stellard   // ToDo: AMDGPUInstPrinter does not support 1/(2*PI). It consider 1/(2*PI) as
325e1818af8STom Stellard   // literal constant.
326ac106addSNikolay Haustov   float V = 0.0f;
327e1818af8STom Stellard   switch (Imm) {
328ac106addSNikolay Haustov   case 240: V =  0.5f; break;
329ac106addSNikolay Haustov   case 241: V = -0.5f; break;
330ac106addSNikolay Haustov   case 242: V =  1.0f; break;
331ac106addSNikolay Haustov   case 243: V = -1.0f; break;
332ac106addSNikolay Haustov   case 244: V =  2.0f; break;
333ac106addSNikolay Haustov   case 245: V = -2.0f; break;
334ac106addSNikolay Haustov   case 246: V =  4.0f; break;
335ac106addSNikolay Haustov   case 247: V = -4.0f; break;
336ac106addSNikolay Haustov   case 248: return MCOperand::createImm(Is32 ?         // 1/(2*PI)
337ac106addSNikolay Haustov                                           0x3e22f983 :
338ac106addSNikolay Haustov                                           0x3fc45f306dc9c882);
339ac106addSNikolay Haustov   default: break;
340e1818af8STom Stellard   }
341ac106addSNikolay Haustov   return MCOperand::createImm(Is32? FloatToBits(V) : DoubleToBits(V));
342e1818af8STom Stellard }
343e1818af8STom Stellard 
344212a251cSArtem Tamazov unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const {
345e1818af8STom Stellard   using namespace AMDGPU;
346212a251cSArtem Tamazov   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
347212a251cSArtem Tamazov   switch (Width) {
348212a251cSArtem Tamazov   default: // fall
349212a251cSArtem Tamazov   case OPW32: return VGPR_32RegClassID;
350212a251cSArtem Tamazov   case OPW64: return VReg_64RegClassID;
351212a251cSArtem Tamazov   case OPW128: return VReg_128RegClassID;
352212a251cSArtem Tamazov   }
353212a251cSArtem Tamazov }
354212a251cSArtem Tamazov 
355212a251cSArtem Tamazov unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const {
356212a251cSArtem Tamazov   using namespace AMDGPU;
357212a251cSArtem Tamazov   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
358212a251cSArtem Tamazov   switch (Width) {
359212a251cSArtem Tamazov   default: // fall
360212a251cSArtem Tamazov   case OPW32: return SGPR_32RegClassID;
361212a251cSArtem Tamazov   case OPW64: return SGPR_64RegClassID;
362212a251cSArtem Tamazov   case OPW128: return SGPR_128RegClassID;
363212a251cSArtem Tamazov   }
364212a251cSArtem Tamazov }
365212a251cSArtem Tamazov 
366212a251cSArtem Tamazov unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const {
367212a251cSArtem Tamazov   using namespace AMDGPU;
368212a251cSArtem Tamazov   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
369212a251cSArtem Tamazov   switch (Width) {
370212a251cSArtem Tamazov   default: // fall
371212a251cSArtem Tamazov   case OPW32: return TTMP_32RegClassID;
372212a251cSArtem Tamazov   case OPW64: return TTMP_64RegClassID;
373212a251cSArtem Tamazov   case OPW128: return TTMP_128RegClassID;
374212a251cSArtem Tamazov   }
375212a251cSArtem Tamazov }
376212a251cSArtem Tamazov 
377212a251cSArtem Tamazov MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val) const {
378212a251cSArtem Tamazov   using namespace AMDGPU::EncValues;
379ac106addSNikolay Haustov   assert(Val < 512); // enum9
380ac106addSNikolay Haustov 
381212a251cSArtem Tamazov   if (VGPR_MIN <= Val && Val <= VGPR_MAX) {
382212a251cSArtem Tamazov     return createRegOperand(getVgprClassId(Width), Val - VGPR_MIN);
383212a251cSArtem Tamazov   }
384b49c3361SArtem Tamazov   if (Val <= SGPR_MAX) {
385b49c3361SArtem Tamazov     assert(SGPR_MIN == 0); // "SGPR_MIN <= Val" is always true and causes compilation warning.
386212a251cSArtem Tamazov     return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN);
387212a251cSArtem Tamazov   }
388212a251cSArtem Tamazov   if (TTMP_MIN <= Val && Val <= TTMP_MAX) {
389212a251cSArtem Tamazov     return createSRegOperand(getTtmpClassId(Width), Val - TTMP_MIN);
390212a251cSArtem Tamazov   }
391ac106addSNikolay Haustov 
392212a251cSArtem Tamazov   assert(Width == OPW32 || Width == OPW64);
393212a251cSArtem Tamazov   const bool Is32 = (Width == OPW32);
394212a251cSArtem Tamazov 
395212a251cSArtem Tamazov   if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX)
396ac106addSNikolay Haustov     return decodeIntImmed(Val);
397ac106addSNikolay Haustov 
398212a251cSArtem Tamazov   if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX)
399ac106addSNikolay Haustov     return decodeFPImmed(Is32, Val);
400ac106addSNikolay Haustov 
401212a251cSArtem Tamazov   if (Val == LITERAL_CONST)
402ac106addSNikolay Haustov     return decodeLiteralConstant();
403ac106addSNikolay Haustov 
404ac106addSNikolay Haustov   return Is32 ? decodeSpecialReg32(Val) : decodeSpecialReg64(Val);
405ac106addSNikolay Haustov }
406ac106addSNikolay Haustov 
407ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const {
408ac106addSNikolay Haustov   using namespace AMDGPU;
409e1818af8STom Stellard   switch (Val) {
410ac106addSNikolay Haustov   case 102: return createRegOperand(getMCReg(FLAT_SCR_LO, STI));
411ac106addSNikolay Haustov   case 103: return createRegOperand(getMCReg(FLAT_SCR_HI, STI));
412e1818af8STom Stellard     // ToDo: no support for xnack_mask_lo/_hi register
413e1818af8STom Stellard   case 104:
414ac106addSNikolay Haustov   case 105: break;
415ac106addSNikolay Haustov   case 106: return createRegOperand(VCC_LO);
416ac106addSNikolay Haustov   case 107: return createRegOperand(VCC_HI);
417212a251cSArtem Tamazov   case 108: return createRegOperand(TBA_LO);
418212a251cSArtem Tamazov   case 109: return createRegOperand(TBA_HI);
419212a251cSArtem Tamazov   case 110: return createRegOperand(TMA_LO);
420212a251cSArtem Tamazov   case 111: return createRegOperand(TMA_HI);
421ac106addSNikolay Haustov   case 124: return createRegOperand(M0);
422ac106addSNikolay Haustov   case 126: return createRegOperand(EXEC_LO);
423ac106addSNikolay Haustov   case 127: return createRegOperand(EXEC_HI);
424e1818af8STom Stellard     // ToDo: no support for vccz register
425ac106addSNikolay Haustov   case 251: break;
426e1818af8STom Stellard     // ToDo: no support for execz register
427ac106addSNikolay Haustov   case 252: break;
428ac106addSNikolay Haustov   case 253: return createRegOperand(SCC);
429ac106addSNikolay Haustov   default: break;
430e1818af8STom Stellard   }
431ac106addSNikolay Haustov   return errOperand(Val, "unknown operand encoding " + Twine(Val));
432e1818af8STom Stellard }
433e1818af8STom Stellard 
434ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {
435161a158eSNikolay Haustov   using namespace AMDGPU;
436161a158eSNikolay Haustov   switch (Val) {
437ac106addSNikolay Haustov   case 102: return createRegOperand(getMCReg(FLAT_SCR, STI));
438ac106addSNikolay Haustov   case 106: return createRegOperand(VCC);
439212a251cSArtem Tamazov   case 108: return createRegOperand(TBA);
440212a251cSArtem Tamazov   case 110: return createRegOperand(TMA);
441ac106addSNikolay Haustov   case 126: return createRegOperand(EXEC);
442ac106addSNikolay Haustov   default: break;
443161a158eSNikolay Haustov   }
444ac106addSNikolay Haustov   return errOperand(Val, "unknown operand encoding " + Twine(Val));
445161a158eSNikolay Haustov }
446161a158eSNikolay Haustov 
447*3381d7a2SSam Kolton //===----------------------------------------------------------------------===//
448*3381d7a2SSam Kolton // AMDGPUSymbolizer
449*3381d7a2SSam Kolton //===----------------------------------------------------------------------===//
450*3381d7a2SSam Kolton 
451*3381d7a2SSam Kolton // Try to find symbol name for specified label
452*3381d7a2SSam Kolton bool AMDGPUSymbolizer::tryAddingSymbolicOperand(MCInst &Inst,
453*3381d7a2SSam Kolton                                 raw_ostream &/*cStream*/, int64_t Value,
454*3381d7a2SSam Kolton                                 uint64_t /*Address*/, bool IsBranch,
455*3381d7a2SSam Kolton                                 uint64_t /*Offset*/, uint64_t /*InstSize*/) {
456*3381d7a2SSam Kolton   typedef std::tuple<uint64_t, StringRef, uint8_t> SymbolInfoTy;
457*3381d7a2SSam Kolton   typedef std::vector<SymbolInfoTy> SectionSymbolsTy;
458*3381d7a2SSam Kolton 
459*3381d7a2SSam Kolton   if (!IsBranch) {
460*3381d7a2SSam Kolton     return false;
461*3381d7a2SSam Kolton   }
462*3381d7a2SSam Kolton 
463*3381d7a2SSam Kolton   auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo);
464*3381d7a2SSam Kolton   auto Result = std::find_if(Symbols->begin(), Symbols->end(),
465*3381d7a2SSam Kolton                              [Value](const SymbolInfoTy& Val) {
466*3381d7a2SSam Kolton                                 return std::get<0>(Val) == static_cast<uint64_t>(Value)
467*3381d7a2SSam Kolton                                     && std::get<2>(Val) == ELF::STT_NOTYPE;
468*3381d7a2SSam Kolton                              });
469*3381d7a2SSam Kolton   if (Result != Symbols->end()) {
470*3381d7a2SSam Kolton     auto *Sym = Ctx.getOrCreateSymbol(std::get<1>(*Result));
471*3381d7a2SSam Kolton     const auto *Add = MCSymbolRefExpr::create(Sym, Ctx);
472*3381d7a2SSam Kolton     Inst.addOperand(MCOperand::createExpr(Add));
473*3381d7a2SSam Kolton     return true;
474*3381d7a2SSam Kolton   }
475*3381d7a2SSam Kolton   return false;
476*3381d7a2SSam Kolton }
477*3381d7a2SSam Kolton 
478*3381d7a2SSam Kolton //===----------------------------------------------------------------------===//
479*3381d7a2SSam Kolton // Initialization
480*3381d7a2SSam Kolton //===----------------------------------------------------------------------===//
481*3381d7a2SSam Kolton 
482*3381d7a2SSam Kolton static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/,
483*3381d7a2SSam Kolton                               LLVMOpInfoCallback /*GetOpInfo*/,
484*3381d7a2SSam Kolton                               LLVMSymbolLookupCallback /*SymbolLookUp*/,
485*3381d7a2SSam Kolton                               void *DisInfo,
486*3381d7a2SSam Kolton                               MCContext *Ctx,
487*3381d7a2SSam Kolton                               std::unique_ptr<MCRelocationInfo> &&RelInfo) {
488*3381d7a2SSam Kolton   return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo);
489*3381d7a2SSam Kolton }
490*3381d7a2SSam Kolton 
491e1818af8STom Stellard static MCDisassembler *createAMDGPUDisassembler(const Target &T,
492e1818af8STom Stellard                                                 const MCSubtargetInfo &STI,
493e1818af8STom Stellard                                                 MCContext &Ctx) {
494e1818af8STom Stellard   return new AMDGPUDisassembler(STI, Ctx);
495e1818af8STom Stellard }
496e1818af8STom Stellard 
497e1818af8STom Stellard extern "C" void LLVMInitializeAMDGPUDisassembler() {
498e1818af8STom Stellard   TargetRegistry::RegisterMCDisassembler(TheGCNTarget, createAMDGPUDisassembler);
499*3381d7a2SSam Kolton   TargetRegistry::RegisterMCSymbolizer(TheGCNTarget, createAMDGPUSymbolizer);
500e1818af8STom Stellard }
501