2016-02-18 11:42:32 +08:00
|
|
|
//===-- AMDGPUDisassembler.cpp - Disassembler for AMDGPU ISA --------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
/// \file
|
|
|
|
///
|
|
|
|
/// This file contains definition for AMDGPU ISA disassembler
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
// ToDo: What to do with instruction suffixes (v_mov_b32 vs v_mov_b32_e32)?
|
|
|
|
|
|
|
|
#include "AMDGPUDisassembler.h"
|
|
|
|
#include "AMDGPU.h"
|
|
|
|
#include "AMDGPURegisterInfo.h"
|
|
|
|
#include "Utils/AMDGPUBaseInfo.h"
|
|
|
|
|
|
|
|
#include "llvm/MC/MCFixedLenDisassembler.h"
|
|
|
|
#include "llvm/MC/MCInst.h"
|
|
|
|
#include "llvm/MC/MCInstrDesc.h"
|
|
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
|
|
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "amdgpu-disassembler"
|
|
|
|
|
|
|
|
typedef llvm::MCDisassembler::DecodeStatus DecodeStatus;
|
|
|
|
|
|
|
|
|
|
|
|
static DecodeStatus DecodeVGPR_32RegisterClass(MCInst &Inst, unsigned Imm,
|
|
|
|
uint64_t Addr, const void *Decoder) {
|
2016-02-26 00:09:14 +08:00
|
|
|
const AMDGPUDisassembler *Dis =
|
2016-02-18 11:42:32 +08:00
|
|
|
static_cast<const AMDGPUDisassembler *>(Decoder);
|
|
|
|
return Dis->DecodeVGPR_32RegisterClass(Inst, Imm, Addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static DecodeStatus DecodeVS_32RegisterClass(MCInst &Inst, unsigned Imm,
|
|
|
|
uint64_t Addr, const void *Decoder) {
|
2016-02-26 00:09:14 +08:00
|
|
|
const AMDGPUDisassembler *Dis =
|
2016-02-18 11:42:32 +08:00
|
|
|
static_cast<const AMDGPUDisassembler *>(Decoder);
|
|
|
|
return Dis->DecodeVS_32RegisterClass(Inst, Imm, Addr);
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
static DecodeStatus DecodeVS_64RegisterClass(MCInst &Inst, unsigned Imm,
|
2016-02-18 11:42:32 +08:00
|
|
|
uint64_t Addr, const void *Decoder) {
|
2016-02-26 00:09:14 +08:00
|
|
|
const AMDGPUDisassembler *Dis =
|
|
|
|
static_cast<const AMDGPUDisassembler *>(Decoder);
|
|
|
|
return Dis->DecodeVS_64RegisterClass(Inst, Imm, Addr);
|
2016-02-18 11:42:32 +08:00
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
static DecodeStatus DecodeVReg_64RegisterClass(MCInst &Inst, unsigned Imm,
|
2016-02-18 11:42:32 +08:00
|
|
|
uint64_t Addr, const void *Decoder) {
|
2016-02-26 00:09:14 +08:00
|
|
|
const AMDGPUDisassembler *Dis =
|
|
|
|
static_cast<const AMDGPUDisassembler *>(Decoder);
|
|
|
|
return Dis->DecodeVReg_64RegisterClass(Inst, Imm, Addr);
|
2016-02-18 11:42:32 +08:00
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
static DecodeStatus DecodeVReg_96RegisterClass(MCInst &Inst, unsigned Imm,
|
2016-02-18 11:42:32 +08:00
|
|
|
uint64_t Addr, const void *Decoder) {
|
|
|
|
// ToDo
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
static DecodeStatus DecodeVReg_128RegisterClass(MCInst &Inst, unsigned Imm,
|
2016-02-18 11:42:32 +08:00
|
|
|
uint64_t Addr, const void *Decoder) {
|
|
|
|
// ToDo
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
static DecodeStatus DecodeSReg_32RegisterClass(MCInst &Inst, unsigned Imm,
|
2016-02-18 11:42:32 +08:00
|
|
|
uint64_t Addr, const void *Decoder) {
|
|
|
|
// ToDo
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
static DecodeStatus DecodeSReg_64RegisterClass(MCInst &Inst, unsigned Imm,
|
2016-02-18 11:42:32 +08:00
|
|
|
uint64_t Addr, const void *Decoder) {
|
|
|
|
// ToDo
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
static DecodeStatus DecodeSReg_128RegisterClass(MCInst &Inst, unsigned Imm,
|
2016-02-18 11:42:32 +08:00
|
|
|
uint64_t Addr, const void *Decoder) {
|
|
|
|
// ToDo
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
static DecodeStatus DecodeSReg_256RegisterClass(MCInst &Inst, unsigned Imm,
|
2016-02-18 11:42:32 +08:00
|
|
|
uint64_t Addr, const void *Decoder) {
|
|
|
|
// ToDo
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define GET_SUBTARGETINFO_ENUM
|
|
|
|
#include "AMDGPUGenSubtargetInfo.inc"
|
|
|
|
#undef GET_SUBTARGETINFO_ENUM
|
|
|
|
|
|
|
|
#include "AMDGPUGenDisassemblerTables.inc"
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
|
|
|
|
ArrayRef<uint8_t> Bytes,
|
2016-02-26 00:09:14 +08:00
|
|
|
uint64_t Address,
|
2016-02-18 11:42:32 +08:00
|
|
|
raw_ostream &WS,
|
|
|
|
raw_ostream &CS) const {
|
|
|
|
CommentStream = &CS;
|
|
|
|
|
|
|
|
// ToDo: AMDGPUDisassembler supports only VI ISA.
|
|
|
|
assert(AMDGPU::isVI(STI) && "Can disassemble only VI ISA.");
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
HasLiteral = false;
|
|
|
|
this->Bytes = Bytes;
|
|
|
|
|
2016-02-18 11:42:32 +08:00
|
|
|
// Try decode 32-bit instruction
|
|
|
|
if (Bytes.size() < 4) {
|
|
|
|
Size = 0;
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
uint32_t Insn =
|
|
|
|
(Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0);
|
|
|
|
|
|
|
|
// Calling the auto-generated decoder function.
|
|
|
|
DecodeStatus Result =
|
|
|
|
decodeInstruction(DecoderTableVI32, MI, Insn, Address, this, STI);
|
|
|
|
if (Result != MCDisassembler::Success) {
|
|
|
|
Size = 0;
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
2016-02-26 00:09:14 +08:00
|
|
|
if (HasLiteral == true) {
|
|
|
|
Size = 8;
|
|
|
|
HasLiteral = false;
|
|
|
|
} else {
|
|
|
|
Size = 4;
|
|
|
|
}
|
2016-02-18 11:42:32 +08:00
|
|
|
|
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeImmedFloat(unsigned Imm, uint32_t &F) const {
|
2016-02-18 11:42:32 +08:00
|
|
|
// ToDo: case 248: 1/(2*PI) - is allowed only on VI
|
2016-02-26 00:09:14 +08:00
|
|
|
// ToDo: AMDGPUInstPrinter does not support 1/(2*PI). It consider 1/(2*PI) as
|
2016-02-18 11:42:32 +08:00
|
|
|
// literal constant.
|
|
|
|
switch(Imm) {
|
|
|
|
case 240: F = FloatToBits(0.5f); return MCDisassembler::Success;
|
|
|
|
case 241: F = FloatToBits(-0.5f); return MCDisassembler::Success;
|
|
|
|
case 242: F = FloatToBits(1.0f); return MCDisassembler::Success;
|
|
|
|
case 243: F = FloatToBits(-1.0f); return MCDisassembler::Success;
|
|
|
|
case 244: F = FloatToBits(2.0f); return MCDisassembler::Success;
|
|
|
|
case 245: F = FloatToBits(-2.0f); return MCDisassembler::Success;
|
|
|
|
case 246: F = FloatToBits(4.0f); return MCDisassembler::Success;
|
|
|
|
case 247: F = FloatToBits(-4.0f); return MCDisassembler::Success;
|
|
|
|
case 248: F = 0x3e22f983; return MCDisassembler::Success; // 1/(2*PI)
|
|
|
|
default: return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeImmedDouble(unsigned Imm, uint64_t &D) const {
|
|
|
|
switch(Imm) {
|
|
|
|
case 240: D = DoubleToBits(0.5); return MCDisassembler::Success;
|
|
|
|
case 241: D = DoubleToBits(-0.5); return MCDisassembler::Success;
|
|
|
|
case 242: D = DoubleToBits(1.0); return MCDisassembler::Success;
|
|
|
|
case 243: D = DoubleToBits(-1.0); return MCDisassembler::Success;
|
|
|
|
case 244: D = DoubleToBits(2.0); return MCDisassembler::Success;
|
|
|
|
case 245: D = DoubleToBits(-2.0); return MCDisassembler::Success;
|
|
|
|
case 246: D = DoubleToBits(4.0); return MCDisassembler::Success;
|
|
|
|
case 247: D = DoubleToBits(-4.0); return MCDisassembler::Success;
|
|
|
|
case 248: D = 0x3fc45f306dc9c882; return MCDisassembler::Success; // 1/(2*PI)
|
|
|
|
default: return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeImmedInteger(unsigned Imm,
|
|
|
|
int64_t &I) const {
|
2016-02-18 11:42:32 +08:00
|
|
|
if ((Imm >= 128) && (Imm <= 192)) {
|
|
|
|
I = Imm - 128;
|
|
|
|
return MCDisassembler::Success;
|
|
|
|
} else if ((Imm >= 193) && (Imm <= 208)) {
|
|
|
|
I = 192 - Imm;
|
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeVgprRegister(unsigned Val,
|
|
|
|
unsigned &RegID,
|
|
|
|
unsigned Size) const {
|
|
|
|
if (Val > (256 - Size / 32)) {
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
unsigned RegClassID;
|
|
|
|
switch (Size) {
|
|
|
|
case 32: RegClassID = AMDGPU::VGPR_32RegClassID; break;
|
|
|
|
case 64: RegClassID = AMDGPU::VReg_64RegClassID; break;
|
|
|
|
case 96: RegClassID = AMDGPU::VReg_96RegClassID; break;
|
|
|
|
case 128: RegClassID = AMDGPU::VReg_128RegClassID; break;
|
|
|
|
case 256: RegClassID = AMDGPU::VReg_256RegClassID; break;
|
|
|
|
case 512: RegClassID = AMDGPU::VReg_512RegClassID; break;
|
|
|
|
default:
|
2016-02-18 11:42:32 +08:00
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
2016-02-26 00:09:14 +08:00
|
|
|
|
|
|
|
RegID = AMDGPUMCRegisterClasses[RegClassID].getRegister(Val);
|
2016-02-18 11:42:32 +08:00
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeSgprRegister(unsigned Val,
|
|
|
|
unsigned &RegID,
|
|
|
|
unsigned Size) const {
|
2016-02-18 11:42:32 +08:00
|
|
|
// ToDo: SI/CI have 104 SGPRs, VI - 102
|
2016-02-26 00:09:14 +08:00
|
|
|
unsigned RegClassID;
|
|
|
|
|
|
|
|
switch (Size) {
|
|
|
|
case 32:
|
|
|
|
if (Val > 101) {
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
RegClassID = AMDGPU::SGPR_32RegClassID;
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
if ((Val % 2 != 0) || (Val > 100)) {
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
Val /= 2;
|
|
|
|
RegClassID = AMDGPU::SGPR_64RegClassID;
|
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
// ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in
|
|
|
|
// this bundle?
|
|
|
|
if ((Val % 4 != 0) || (Val > 96)) {
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
Val /= 4;
|
|
|
|
RegClassID = AMDGPU::SReg_128RegClassID;
|
|
|
|
break;
|
|
|
|
case 256:
|
|
|
|
// ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in
|
|
|
|
// this bundle?
|
|
|
|
if ((Val % 4 != 0) || (Val > 92)) {
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
Val /= 4;
|
|
|
|
RegClassID = AMDGPU::SReg_256RegClassID;
|
|
|
|
break;
|
|
|
|
case 512:
|
|
|
|
// ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in
|
|
|
|
// this bundle?
|
|
|
|
if ((Val % 4 != 0) || (Val > 84)) {
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
Val /= 4;
|
|
|
|
RegClassID = AMDGPU::SReg_512RegClassID;
|
|
|
|
break;
|
|
|
|
default:
|
2016-02-18 11:42:32 +08:00
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
2016-02-26 00:09:14 +08:00
|
|
|
|
|
|
|
RegID = AMDGPUMCRegisterClasses[RegClassID].getRegister(Val);
|
2016-02-18 11:42:32 +08:00
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeSrc32Register(unsigned Val,
|
|
|
|
unsigned &RegID) const {
|
|
|
|
// ToDo: deal with out-of range registers
|
2016-02-18 11:42:32 +08:00
|
|
|
using namespace AMDGPU;
|
|
|
|
if (Val <= 101) {
|
2016-02-26 00:09:14 +08:00
|
|
|
return DecodeSgprRegister(Val, RegID, 32);
|
2016-02-18 11:42:32 +08:00
|
|
|
} else if ((Val >= 256) && (Val <= 511)) {
|
2016-02-26 00:09:14 +08:00
|
|
|
return DecodeVgprRegister(Val - 256, RegID, 32);
|
2016-02-18 11:42:32 +08:00
|
|
|
} else {
|
|
|
|
switch(Val) {
|
|
|
|
case 102: RegID = getMCReg(FLAT_SCR_LO, STI); return MCDisassembler::Success;
|
|
|
|
case 103: RegID = getMCReg(FLAT_SCR_HI, STI); return MCDisassembler::Success;
|
|
|
|
// ToDo: no support for xnack_mask_lo/_hi register
|
|
|
|
case 104:
|
|
|
|
case 105: return MCDisassembler::Fail;
|
|
|
|
case 106: RegID = getMCReg(VCC_LO, STI); return MCDisassembler::Success;
|
|
|
|
case 107: RegID = getMCReg(VCC_HI, STI); return MCDisassembler::Success;
|
|
|
|
// ToDo: no support for tba_lo/_hi register
|
|
|
|
case 108:
|
|
|
|
case 109: return MCDisassembler::Fail;
|
|
|
|
// ToDo: no support for tma_lo/_hi register
|
|
|
|
case 110:
|
|
|
|
case 111: return MCDisassembler::Fail;
|
|
|
|
// ToDo: no support for ttmp[0:11] register
|
|
|
|
case 112:
|
|
|
|
case 113:
|
|
|
|
case 114:
|
|
|
|
case 115:
|
|
|
|
case 116:
|
|
|
|
case 117:
|
|
|
|
case 118:
|
|
|
|
case 119:
|
|
|
|
case 120:
|
|
|
|
case 121:
|
|
|
|
case 122:
|
|
|
|
case 123: return MCDisassembler::Fail;
|
|
|
|
case 124: RegID = getMCReg(M0, STI); return MCDisassembler::Success;
|
|
|
|
case 126: RegID = getMCReg(EXEC_LO, STI); return MCDisassembler::Success;
|
|
|
|
case 127: RegID = getMCReg(EXEC_HI, STI); return MCDisassembler::Success;
|
|
|
|
// ToDo: no support for vccz register
|
|
|
|
case 251: return MCDisassembler::Fail;
|
|
|
|
// ToDo: no support for execz register
|
|
|
|
case 252: return MCDisassembler::Fail;
|
|
|
|
case 253: RegID = getMCReg(SCC, STI); return MCDisassembler::Success;
|
|
|
|
default: return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeSrc64Register(unsigned Val,
|
|
|
|
unsigned &RegID) const {
|
|
|
|
// ToDo: deal with out-of range registers
|
|
|
|
using namespace AMDGPU;
|
|
|
|
if (Val <= 101) {
|
|
|
|
return DecodeSgprRegister(Val, RegID, 64);
|
|
|
|
} else if ((Val >= 256) && (Val <= 511)) {
|
|
|
|
return DecodeVgprRegister(Val - 256, RegID, 64);
|
|
|
|
} else {
|
|
|
|
switch(Val) {
|
|
|
|
case 102: RegID = getMCReg(FLAT_SCR, STI); return MCDisassembler::Success;
|
|
|
|
case 106: RegID = getMCReg(VCC, STI); return MCDisassembler::Success;
|
|
|
|
case 126: RegID = getMCReg(EXEC, STI); return MCDisassembler::Success;
|
|
|
|
default: return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeLiteralConstant(MCInst &Inst,
|
|
|
|
uint64_t &Literal) const {
|
|
|
|
// For now all literal constants are supposed to be unsigned integer
|
|
|
|
// ToDo: deal with signed/unsigned 64-bit integer constants
|
|
|
|
// ToDo: deal with float/double constants
|
|
|
|
if (Bytes.size() < 8) {
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
Literal =
|
|
|
|
0 | (Bytes[7] << 24) | (Bytes[6] << 16) | (Bytes[5] << 8) | (Bytes[4] << 0);
|
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeVGPR_32RegisterClass(llvm::MCInst &Inst,
|
|
|
|
unsigned Imm,
|
2016-02-18 11:42:32 +08:00
|
|
|
uint64_t Addr) const {
|
|
|
|
unsigned RegID;
|
|
|
|
if (DecodeVgprRegister(Imm, RegID) == MCDisassembler::Success) {
|
|
|
|
Inst.addOperand(MCOperand::createReg(RegID));
|
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeVSRegisterClass(MCInst &Inst,
|
|
|
|
unsigned Imm,
|
|
|
|
uint64_t Addr,
|
|
|
|
bool Is32) const {
|
|
|
|
// ToDo: different opcodes allow different formats of this operands
|
2016-02-18 11:42:32 +08:00
|
|
|
if ((Imm >= 128) && (Imm <= 208)) {
|
|
|
|
// immediate integer
|
|
|
|
int64_t Val;
|
2016-02-26 00:09:14 +08:00
|
|
|
if (DecodeImmedInteger(Imm, Val) == MCDisassembler::Success) {
|
2016-02-18 11:42:32 +08:00
|
|
|
Inst.addOperand(MCOperand::createImm(Val));
|
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
} else if ((Imm >= 240) && (Imm <= 248)) {
|
2016-02-26 00:09:14 +08:00
|
|
|
// immediate float/double
|
|
|
|
uint64_t Val;
|
|
|
|
DecodeStatus status;
|
|
|
|
if (Is32) {
|
|
|
|
uint32_t Val32;
|
|
|
|
status = DecodeImmedFloat(Imm, Val32);
|
|
|
|
Val = static_cast<uint64_t>(Val32);
|
|
|
|
} else {
|
|
|
|
status = DecodeImmedDouble(Imm, Val);
|
|
|
|
}
|
|
|
|
if (status == MCDisassembler::Success) {
|
2016-02-18 11:42:32 +08:00
|
|
|
Inst.addOperand(MCOperand::createImm(Val));
|
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
} else if (Imm == 254) {
|
|
|
|
// LDS direct
|
|
|
|
// ToDo: implement LDS direct read
|
|
|
|
} else if (Imm == 255) {
|
|
|
|
// literal constant
|
2016-02-26 00:09:14 +08:00
|
|
|
HasLiteral = true;
|
|
|
|
uint64_t Literal;
|
|
|
|
if (DecodeLiteralConstant(Inst, Literal) == MCDisassembler::Success) {
|
|
|
|
Inst.addOperand(MCOperand::createImm(Literal));
|
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
} else if ((Imm == 125) ||
|
|
|
|
((Imm >= 209) && (Imm <= 239)) ||
|
|
|
|
(Imm == 249) ||
|
|
|
|
(Imm == 250) ||
|
2016-02-18 11:42:32 +08:00
|
|
|
(Imm >= 512)) {
|
|
|
|
// reserved
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
} else {
|
|
|
|
// register
|
|
|
|
unsigned RegID;
|
2016-02-26 00:09:14 +08:00
|
|
|
DecodeStatus status = Is32 ? DecodeSrc32Register(Imm, RegID)
|
|
|
|
: DecodeSrc64Register(Imm, RegID);
|
|
|
|
if (status == MCDisassembler::Success) {
|
2016-02-18 11:42:32 +08:00
|
|
|
Inst.addOperand(MCOperand::createReg(RegID));
|
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
2016-02-26 00:09:14 +08:00
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeVS_32RegisterClass(MCInst &Inst,
|
|
|
|
unsigned Imm,
|
|
|
|
uint64_t Addr) const {
|
|
|
|
return DecodeVSRegisterClass(Inst, Imm, Addr, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeVS_64RegisterClass(MCInst &Inst,
|
|
|
|
unsigned Imm,
|
|
|
|
uint64_t Addr) const {
|
|
|
|
return DecodeVSRegisterClass(Inst, Imm, Addr, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
DecodeStatus AMDGPUDisassembler::DecodeVReg_64RegisterClass(llvm::MCInst &Inst,
|
|
|
|
unsigned Imm,
|
|
|
|
uint64_t Addr) const {
|
|
|
|
unsigned RegID;
|
|
|
|
if (DecodeVgprRegister(Imm, RegID, 64) == MCDisassembler::Success) {
|
|
|
|
Inst.addOperand(MCOperand::createReg(RegID));
|
|
|
|
return MCDisassembler::Success;
|
|
|
|
}
|
|
|
|
return MCDisassembler::Fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-02-18 11:42:32 +08:00
|
|
|
static MCDisassembler *createAMDGPUDisassembler(const Target &T,
|
|
|
|
const MCSubtargetInfo &STI,
|
|
|
|
MCContext &Ctx) {
|
|
|
|
return new AMDGPUDisassembler(STI, Ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void LLVMInitializeAMDGPUDisassembler() {
|
|
|
|
TargetRegistry::RegisterMCDisassembler(TheGCNTarget, createAMDGPUDisassembler);
|
|
|
|
}
|