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"
313381d7a2SSam 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 
523381d7a2SSam Kolton static DecodeStatus decodeSoppBrTarget(MCInst &Inst, unsigned Imm,
533381d7a2SSam Kolton                                        uint64_t Addr, const void *Decoder) {
543381d7a2SSam Kolton   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
553381d7a2SSam Kolton 
563381d7a2SSam Kolton   APInt SignedOffset(18, Imm * 4, true);
573381d7a2SSam Kolton   int64_t Offset = (SignedOffset.sext(64) + 4 + Addr).getSExtValue();
583381d7a2SSam Kolton 
593381d7a2SSam Kolton   if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2))
603381d7a2SSam Kolton     return MCDisassembler::Success;
613381d7a2SSam Kolton   return addOperand(Inst, MCOperand::createImm(Imm));
623381d7a2SSam Kolton }
633381d7a2SSam 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:
233*92b355b1SMatt Arsenault     llvm_unreachable("unhandled register class");
234ac106addSNikolay Haustov   }
235*92b355b1SMatt Arsenault 
236*92b355b1SMatt Arsenault   if (Val % (1 << shift)) {
237ac106addSNikolay Haustov     *CommentStream << "Warning: " << getRegClassName(SRegClassID)
238ac106addSNikolay Haustov                    << ": scalar reg isn't aligned " << Val;
239*92b355b1SMatt Arsenault   }
240*92b355b1SMatt Arsenault 
241ac106addSNikolay Haustov   return createRegOperand(SRegClassID, Val >> shift);
242ac106addSNikolay Haustov }
243ac106addSNikolay Haustov 
244ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VS_32(unsigned Val) const {
245212a251cSArtem Tamazov   return decodeSrcOp(OPW32, Val);
246ac106addSNikolay Haustov }
247ac106addSNikolay Haustov 
248ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VS_64(unsigned Val) const {
249212a251cSArtem Tamazov   return decodeSrcOp(OPW64, Val);
250ac106addSNikolay Haustov }
251ac106addSNikolay Haustov 
252ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VGPR_32(unsigned Val) const {
253cb540bc0SMatt Arsenault   // Some instructions have operand restrictions beyond what the encoding
254cb540bc0SMatt Arsenault   // allows. Some ordinarily VSrc_32 operands are VGPR_32, so clear the extra
255cb540bc0SMatt Arsenault   // high bit.
256cb540bc0SMatt Arsenault   Val &= 255;
257cb540bc0SMatt Arsenault 
258ac106addSNikolay Haustov   return createRegOperand(AMDGPU::VGPR_32RegClassID, Val);
259ac106addSNikolay Haustov }
260ac106addSNikolay Haustov 
261ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VReg_64(unsigned Val) const {
262ac106addSNikolay Haustov   return createRegOperand(AMDGPU::VReg_64RegClassID, Val);
263ac106addSNikolay Haustov }
264ac106addSNikolay Haustov 
265ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VReg_96(unsigned Val) const {
266ac106addSNikolay Haustov   return createRegOperand(AMDGPU::VReg_96RegClassID, Val);
267ac106addSNikolay Haustov }
268ac106addSNikolay Haustov 
269ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_VReg_128(unsigned Val) const {
270ac106addSNikolay Haustov   return createRegOperand(AMDGPU::VReg_128RegClassID, Val);
271ac106addSNikolay Haustov }
272ac106addSNikolay Haustov 
273ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_SReg_32(unsigned Val) const {
274ac106addSNikolay Haustov   // table-gen generated disassembler doesn't care about operand types
275ac106addSNikolay Haustov   // leaving only registry class so SSrc_32 operand turns into SReg_32
276ac106addSNikolay Haustov   // and therefore we accept immediates and literals here as well
277212a251cSArtem Tamazov   return decodeSrcOp(OPW32, Val);
278ac106addSNikolay Haustov }
279ac106addSNikolay Haustov 
28038e496b1SArtem Tamazov MCOperand AMDGPUDisassembler::decodeOperand_SReg_32_XM0(unsigned Val) const {
28138e496b1SArtem Tamazov   // SReg_32_XM0 is SReg_32 without M0
28238e496b1SArtem Tamazov   return decodeOperand_SReg_32(Val);
28338e496b1SArtem Tamazov }
28438e496b1SArtem Tamazov 
285ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_SReg_64(unsigned Val) const {
286ac106addSNikolay Haustov   // see decodeOperand_SReg_32 comment
287212a251cSArtem Tamazov   return decodeSrcOp(OPW64, Val);
288ac106addSNikolay Haustov }
289ac106addSNikolay Haustov 
290ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_SReg_128(unsigned Val) const {
291212a251cSArtem Tamazov   return decodeSrcOp(OPW128, Val);
292ac106addSNikolay Haustov }
293ac106addSNikolay Haustov 
294ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_SReg_256(unsigned Val) const {
295ac106addSNikolay Haustov   return createSRegOperand(AMDGPU::SReg_256RegClassID, Val);
296ac106addSNikolay Haustov }
297ac106addSNikolay Haustov 
298ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeOperand_SReg_512(unsigned Val) const {
299ac106addSNikolay Haustov   return createSRegOperand(AMDGPU::SReg_512RegClassID, Val);
300ac106addSNikolay Haustov }
301ac106addSNikolay Haustov 
302ac106addSNikolay Haustov 
303ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeLiteralConstant() const {
304ac106addSNikolay Haustov   // For now all literal constants are supposed to be unsigned integer
305ac106addSNikolay Haustov   // ToDo: deal with signed/unsigned 64-bit integer constants
306ac106addSNikolay Haustov   // ToDo: deal with float/double constants
307ac106addSNikolay Haustov   if (Bytes.size() < 4)
308ac106addSNikolay Haustov     return errOperand(0, "cannot read literal, inst bytes left " +
309ac106addSNikolay Haustov                          Twine(Bytes.size()));
3101048fb18SSam Kolton   return MCOperand::createImm(eatBytes<uint32_t>(Bytes));
311ac106addSNikolay Haustov }
312ac106addSNikolay Haustov 
313ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) {
314212a251cSArtem Tamazov   using namespace AMDGPU::EncValues;
315212a251cSArtem Tamazov   assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX);
316212a251cSArtem Tamazov   return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ?
317212a251cSArtem Tamazov     (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) :
318212a251cSArtem Tamazov     (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm)));
319212a251cSArtem Tamazov       // Cast prevents negative overflow.
320ac106addSNikolay Haustov }
321ac106addSNikolay Haustov 
322ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeFPImmed(bool Is32, unsigned Imm) {
323212a251cSArtem Tamazov   assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN
324212a251cSArtem Tamazov       && Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX);
325e1818af8STom Stellard   // ToDo: case 248: 1/(2*PI) - is allowed only on VI
326e1818af8STom Stellard   // ToDo: AMDGPUInstPrinter does not support 1/(2*PI). It consider 1/(2*PI) as
327e1818af8STom Stellard   // literal constant.
328ac106addSNikolay Haustov   float V = 0.0f;
329e1818af8STom Stellard   switch (Imm) {
330ac106addSNikolay Haustov   case 240: V =  0.5f; break;
331ac106addSNikolay Haustov   case 241: V = -0.5f; break;
332ac106addSNikolay Haustov   case 242: V =  1.0f; break;
333ac106addSNikolay Haustov   case 243: V = -1.0f; break;
334ac106addSNikolay Haustov   case 244: V =  2.0f; break;
335ac106addSNikolay Haustov   case 245: V = -2.0f; break;
336ac106addSNikolay Haustov   case 246: V =  4.0f; break;
337ac106addSNikolay Haustov   case 247: V = -4.0f; break;
338ac106addSNikolay Haustov   case 248: return MCOperand::createImm(Is32 ?         // 1/(2*PI)
339ac106addSNikolay Haustov                                           0x3e22f983 :
340ac106addSNikolay Haustov                                           0x3fc45f306dc9c882);
341ac106addSNikolay Haustov   default: break;
342e1818af8STom Stellard   }
343ac106addSNikolay Haustov   return MCOperand::createImm(Is32? FloatToBits(V) : DoubleToBits(V));
344e1818af8STom Stellard }
345e1818af8STom Stellard 
346212a251cSArtem Tamazov unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const {
347e1818af8STom Stellard   using namespace AMDGPU;
348212a251cSArtem Tamazov   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
349212a251cSArtem Tamazov   switch (Width) {
350212a251cSArtem Tamazov   default: // fall
351212a251cSArtem Tamazov   case OPW32: return VGPR_32RegClassID;
352212a251cSArtem Tamazov   case OPW64: return VReg_64RegClassID;
353212a251cSArtem Tamazov   case OPW128: return VReg_128RegClassID;
354212a251cSArtem Tamazov   }
355212a251cSArtem Tamazov }
356212a251cSArtem Tamazov 
357212a251cSArtem Tamazov unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const {
358212a251cSArtem Tamazov   using namespace AMDGPU;
359212a251cSArtem Tamazov   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
360212a251cSArtem Tamazov   switch (Width) {
361212a251cSArtem Tamazov   default: // fall
362212a251cSArtem Tamazov   case OPW32: return SGPR_32RegClassID;
363212a251cSArtem Tamazov   case OPW64: return SGPR_64RegClassID;
364212a251cSArtem Tamazov   case OPW128: return SGPR_128RegClassID;
365212a251cSArtem Tamazov   }
366212a251cSArtem Tamazov }
367212a251cSArtem Tamazov 
368212a251cSArtem Tamazov unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const {
369212a251cSArtem Tamazov   using namespace AMDGPU;
370212a251cSArtem Tamazov   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
371212a251cSArtem Tamazov   switch (Width) {
372212a251cSArtem Tamazov   default: // fall
373212a251cSArtem Tamazov   case OPW32: return TTMP_32RegClassID;
374212a251cSArtem Tamazov   case OPW64: return TTMP_64RegClassID;
375212a251cSArtem Tamazov   case OPW128: return TTMP_128RegClassID;
376212a251cSArtem Tamazov   }
377212a251cSArtem Tamazov }
378212a251cSArtem Tamazov 
379212a251cSArtem Tamazov MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val) const {
380212a251cSArtem Tamazov   using namespace AMDGPU::EncValues;
381ac106addSNikolay Haustov   assert(Val < 512); // enum9
382ac106addSNikolay Haustov 
383212a251cSArtem Tamazov   if (VGPR_MIN <= Val && Val <= VGPR_MAX) {
384212a251cSArtem Tamazov     return createRegOperand(getVgprClassId(Width), Val - VGPR_MIN);
385212a251cSArtem Tamazov   }
386b49c3361SArtem Tamazov   if (Val <= SGPR_MAX) {
387b49c3361SArtem Tamazov     assert(SGPR_MIN == 0); // "SGPR_MIN <= Val" is always true and causes compilation warning.
388212a251cSArtem Tamazov     return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN);
389212a251cSArtem Tamazov   }
390212a251cSArtem Tamazov   if (TTMP_MIN <= Val && Val <= TTMP_MAX) {
391212a251cSArtem Tamazov     return createSRegOperand(getTtmpClassId(Width), Val - TTMP_MIN);
392212a251cSArtem Tamazov   }
393ac106addSNikolay Haustov 
394212a251cSArtem Tamazov   assert(Width == OPW32 || Width == OPW64);
395212a251cSArtem Tamazov   const bool Is32 = (Width == OPW32);
396212a251cSArtem Tamazov 
397212a251cSArtem Tamazov   if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX)
398ac106addSNikolay Haustov     return decodeIntImmed(Val);
399ac106addSNikolay Haustov 
400212a251cSArtem Tamazov   if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX)
401ac106addSNikolay Haustov     return decodeFPImmed(Is32, Val);
402ac106addSNikolay Haustov 
403212a251cSArtem Tamazov   if (Val == LITERAL_CONST)
404ac106addSNikolay Haustov     return decodeLiteralConstant();
405ac106addSNikolay Haustov 
406ac106addSNikolay Haustov   return Is32 ? decodeSpecialReg32(Val) : decodeSpecialReg64(Val);
407ac106addSNikolay Haustov }
408ac106addSNikolay Haustov 
409ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const {
410ac106addSNikolay Haustov   using namespace AMDGPU;
411e1818af8STom Stellard   switch (Val) {
412ac106addSNikolay Haustov   case 102: return createRegOperand(getMCReg(FLAT_SCR_LO, STI));
413ac106addSNikolay Haustov   case 103: return createRegOperand(getMCReg(FLAT_SCR_HI, STI));
414e1818af8STom Stellard     // ToDo: no support for xnack_mask_lo/_hi register
415e1818af8STom Stellard   case 104:
416ac106addSNikolay Haustov   case 105: break;
417ac106addSNikolay Haustov   case 106: return createRegOperand(VCC_LO);
418ac106addSNikolay Haustov   case 107: return createRegOperand(VCC_HI);
419212a251cSArtem Tamazov   case 108: return createRegOperand(TBA_LO);
420212a251cSArtem Tamazov   case 109: return createRegOperand(TBA_HI);
421212a251cSArtem Tamazov   case 110: return createRegOperand(TMA_LO);
422212a251cSArtem Tamazov   case 111: return createRegOperand(TMA_HI);
423ac106addSNikolay Haustov   case 124: return createRegOperand(M0);
424ac106addSNikolay Haustov   case 126: return createRegOperand(EXEC_LO);
425ac106addSNikolay Haustov   case 127: return createRegOperand(EXEC_HI);
426e1818af8STom Stellard     // ToDo: no support for vccz register
427ac106addSNikolay Haustov   case 251: break;
428e1818af8STom Stellard     // ToDo: no support for execz register
429ac106addSNikolay Haustov   case 252: break;
430ac106addSNikolay Haustov   case 253: return createRegOperand(SCC);
431ac106addSNikolay Haustov   default: break;
432e1818af8STom Stellard   }
433ac106addSNikolay Haustov   return errOperand(Val, "unknown operand encoding " + Twine(Val));
434e1818af8STom Stellard }
435e1818af8STom Stellard 
436ac106addSNikolay Haustov MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {
437161a158eSNikolay Haustov   using namespace AMDGPU;
438161a158eSNikolay Haustov   switch (Val) {
439ac106addSNikolay Haustov   case 102: return createRegOperand(getMCReg(FLAT_SCR, STI));
440ac106addSNikolay Haustov   case 106: return createRegOperand(VCC);
441212a251cSArtem Tamazov   case 108: return createRegOperand(TBA);
442212a251cSArtem Tamazov   case 110: return createRegOperand(TMA);
443ac106addSNikolay Haustov   case 126: return createRegOperand(EXEC);
444ac106addSNikolay Haustov   default: break;
445161a158eSNikolay Haustov   }
446ac106addSNikolay Haustov   return errOperand(Val, "unknown operand encoding " + Twine(Val));
447161a158eSNikolay Haustov }
448161a158eSNikolay Haustov 
4493381d7a2SSam Kolton //===----------------------------------------------------------------------===//
4503381d7a2SSam Kolton // AMDGPUSymbolizer
4513381d7a2SSam Kolton //===----------------------------------------------------------------------===//
4523381d7a2SSam Kolton 
4533381d7a2SSam Kolton // Try to find symbol name for specified label
4543381d7a2SSam Kolton bool AMDGPUSymbolizer::tryAddingSymbolicOperand(MCInst &Inst,
4553381d7a2SSam Kolton                                 raw_ostream &/*cStream*/, int64_t Value,
4563381d7a2SSam Kolton                                 uint64_t /*Address*/, bool IsBranch,
4573381d7a2SSam Kolton                                 uint64_t /*Offset*/, uint64_t /*InstSize*/) {
4583381d7a2SSam Kolton   typedef std::tuple<uint64_t, StringRef, uint8_t> SymbolInfoTy;
4593381d7a2SSam Kolton   typedef std::vector<SymbolInfoTy> SectionSymbolsTy;
4603381d7a2SSam Kolton 
4613381d7a2SSam Kolton   if (!IsBranch) {
4623381d7a2SSam Kolton     return false;
4633381d7a2SSam Kolton   }
4643381d7a2SSam Kolton 
4653381d7a2SSam Kolton   auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo);
4663381d7a2SSam Kolton   auto Result = std::find_if(Symbols->begin(), Symbols->end(),
4673381d7a2SSam Kolton                              [Value](const SymbolInfoTy& Val) {
4683381d7a2SSam Kolton                                 return std::get<0>(Val) == static_cast<uint64_t>(Value)
4693381d7a2SSam Kolton                                     && std::get<2>(Val) == ELF::STT_NOTYPE;
4703381d7a2SSam Kolton                              });
4713381d7a2SSam Kolton   if (Result != Symbols->end()) {
4723381d7a2SSam Kolton     auto *Sym = Ctx.getOrCreateSymbol(std::get<1>(*Result));
4733381d7a2SSam Kolton     const auto *Add = MCSymbolRefExpr::create(Sym, Ctx);
4743381d7a2SSam Kolton     Inst.addOperand(MCOperand::createExpr(Add));
4753381d7a2SSam Kolton     return true;
4763381d7a2SSam Kolton   }
4773381d7a2SSam Kolton   return false;
4783381d7a2SSam Kolton }
4793381d7a2SSam Kolton 
480*92b355b1SMatt Arsenault void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
481*92b355b1SMatt Arsenault                                                        int64_t Value,
482*92b355b1SMatt Arsenault                                                        uint64_t Address) {
483*92b355b1SMatt Arsenault   llvm_unreachable("unimplemented");
484*92b355b1SMatt Arsenault }
485*92b355b1SMatt Arsenault 
4863381d7a2SSam Kolton //===----------------------------------------------------------------------===//
4873381d7a2SSam Kolton // Initialization
4883381d7a2SSam Kolton //===----------------------------------------------------------------------===//
4893381d7a2SSam Kolton 
4903381d7a2SSam Kolton static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/,
4913381d7a2SSam Kolton                               LLVMOpInfoCallback /*GetOpInfo*/,
4923381d7a2SSam Kolton                               LLVMSymbolLookupCallback /*SymbolLookUp*/,
4933381d7a2SSam Kolton                               void *DisInfo,
4943381d7a2SSam Kolton                               MCContext *Ctx,
4953381d7a2SSam Kolton                               std::unique_ptr<MCRelocationInfo> &&RelInfo) {
4963381d7a2SSam Kolton   return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo);
4973381d7a2SSam Kolton }
4983381d7a2SSam Kolton 
499e1818af8STom Stellard static MCDisassembler *createAMDGPUDisassembler(const Target &T,
500e1818af8STom Stellard                                                 const MCSubtargetInfo &STI,
501e1818af8STom Stellard                                                 MCContext &Ctx) {
502e1818af8STom Stellard   return new AMDGPUDisassembler(STI, Ctx);
503e1818af8STom Stellard }
504e1818af8STom Stellard 
505e1818af8STom Stellard extern "C" void LLVMInitializeAMDGPUDisassembler() {
506f42454b9SMehdi Amini   TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(),
507f42454b9SMehdi Amini                                          createAMDGPUDisassembler);
508f42454b9SMehdi Amini   TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(),
509f42454b9SMehdi Amini                                        createAMDGPUSymbolizer);
510e1818af8STom Stellard }
511