summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp')
-rw-r--r--llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp302
1 files changed, 302 insertions, 0 deletions
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
new file mode 100644
index 00000000000..08c759948f6
--- /dev/null
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
@@ -0,0 +1,302 @@
+//===-- 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) {
+ const AMDGPUDisassembler *Dis =
+ 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) {
+ const AMDGPUDisassembler *Dis =
+ static_cast<const AMDGPUDisassembler *>(Decoder);
+ return Dis->DecodeVS_32RegisterClass(Inst, Imm, Addr);
+}
+
+static DecodeStatus DecodeVS_64RegisterClass(MCInst &Inst, unsigned Imm,
+ uint64_t Addr, const void *Decoder) {
+ // ToDo
+ return MCDisassembler::Fail;
+}
+
+static DecodeStatus DecodeVReg_64RegisterClass(MCInst &Inst, unsigned Imm,
+ uint64_t Addr, const void *Decoder) {
+ // ToDo
+ return MCDisassembler::Fail;
+}
+
+static DecodeStatus DecodeVReg_96RegisterClass(MCInst &Inst, unsigned Imm,
+ uint64_t Addr, const void *Decoder) {
+ // ToDo
+ return MCDisassembler::Fail;
+}
+
+static DecodeStatus DecodeVReg_128RegisterClass(MCInst &Inst, unsigned Imm,
+ uint64_t Addr, const void *Decoder) {
+ // ToDo
+ return MCDisassembler::Fail;
+}
+
+static DecodeStatus DecodeSReg_32RegisterClass(MCInst &Inst, unsigned Imm,
+ uint64_t Addr, const void *Decoder) {
+ // ToDo
+ return MCDisassembler::Fail;
+}
+
+static DecodeStatus DecodeSReg_64RegisterClass(MCInst &Inst, unsigned Imm,
+ uint64_t Addr, const void *Decoder) {
+ // ToDo
+ return MCDisassembler::Fail;
+}
+
+static DecodeStatus DecodeSReg_128RegisterClass(MCInst &Inst, unsigned Imm,
+ uint64_t Addr, const void *Decoder) {
+ // ToDo
+ return MCDisassembler::Fail;
+}
+
+static DecodeStatus DecodeSReg_256RegisterClass(MCInst &Inst, unsigned Imm,
+ 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,
+ uint64_t Address,
+ raw_ostream &WS,
+ raw_ostream &CS) const {
+ CommentStream = &CS;
+
+ // ToDo: AMDGPUDisassembler supports only VI ISA.
+ assert(AMDGPU::isVI(STI) && "Can disassemble only VI ISA.");
+
+ // 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;
+ }
+ Size = 4;
+
+ return MCDisassembler::Success;
+}
+
+DecodeStatus AMDGPUDisassembler::DecodeLitFloat(unsigned Imm, uint32_t& F) const {
+ // ToDo: case 248: 1/(2*PI) - is allowed only on VI
+ // ToDo: AMDGPUInstPrinter does not support 1/(2*PI). It consider 1/(2*PI) as
+ // 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;
+ }
+}
+
+DecodeStatus AMDGPUDisassembler::DecodeLitInteger(unsigned Imm,
+ int64_t& I) const {
+ 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;
+}
+
+DecodeStatus AMDGPUDisassembler::DecodeVgprRegister(unsigned Val,
+ unsigned& RegID) const {
+ if (Val > 255) {
+ return MCDisassembler::Fail;
+ }
+ RegID = AMDGPUMCRegisterClasses[AMDGPU::VGPR_32RegClassID].getRegister(Val);
+ return MCDisassembler::Success;
+}
+
+DecodeStatus AMDGPUDisassembler::DecodeSgprRegister(unsigned Val,
+ unsigned& RegID) const {
+ // ToDo: SI/CI have 104 SGPRs, VI - 102
+ if (Val > 101) {
+ return MCDisassembler::Fail;
+ }
+ RegID = AMDGPUMCRegisterClasses[AMDGPU::SGPR_32RegClassID].getRegister(Val);
+ return MCDisassembler::Success;
+}
+
+DecodeStatus AMDGPUDisassembler::DecodeSrcRegister(unsigned Val,
+ unsigned& RegID) const {
+ // ToDo: deal with out-of range registers
+ using namespace AMDGPU;
+ if (Val <= 101) {
+ return DecodeSgprRegister(Val, RegID);
+ } else if ((Val >= 256) && (Val <= 511)) {
+ return DecodeVgprRegister(Val - 256, RegID);
+ } 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;
+}
+
+DecodeStatus AMDGPUDisassembler::DecodeVGPR_32RegisterClass(llvm::MCInst &Inst,
+ unsigned Imm,
+ uint64_t Addr) const {
+ unsigned RegID;
+ if (DecodeVgprRegister(Imm, RegID) == MCDisassembler::Success) {
+ Inst.addOperand(MCOperand::createReg(RegID));
+ return MCDisassembler::Success;
+ }
+ return MCDisassembler::Fail;
+}
+
+DecodeStatus AMDGPUDisassembler::DecodeVS_32RegisterClass(MCInst &Inst,
+ unsigned Imm,
+ uint64_t Addr) const {
+ // ToDo: different opcodes allow different formats og this operands
+ if ((Imm >= 128) && (Imm <= 208)) {
+ // immediate integer
+ int64_t Val;
+ if (DecodeLitInteger(Imm, Val) == MCDisassembler::Success) {
+ Inst.addOperand(MCOperand::createImm(Val));
+ return MCDisassembler::Success;
+ }
+ } else if ((Imm >= 240) && (Imm <= 248)) {
+ // immediate float
+ uint32_t Val;
+ if (DecodeLitFloat(Imm, Val) == MCDisassembler::Success) {
+ 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
+ } else if ((Imm == 125) ||
+ ((Imm >= 209) && (Imm <= 239)) ||
+ (Imm == 249) ||
+ (Imm == 250) ||
+ (Imm >= 512)) {
+ // reserved
+ return MCDisassembler::Fail;
+ } else {
+ // register
+ unsigned RegID;
+ if (DecodeSrcRegister(Imm, RegID) == MCDisassembler::Success) {
+ Inst.addOperand(MCOperand::createReg(RegID));
+ return MCDisassembler::Success;
+ }
+ }
+ return MCDisassembler::Fail;
+}
+
+static MCDisassembler *createAMDGPUDisassembler(const Target &T,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new AMDGPUDisassembler(STI, Ctx);
+}
+
+extern "C" void LLVMInitializeAMDGPUDisassembler() {
+ TargetRegistry::RegisterMCDisassembler(TheGCNTarget, createAMDGPUDisassembler);
+}
OpenPOWER on IntegriCloud