aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2017-12-13 21:07:51 +0000
committerMatt Arsenault <Matthew.Arsenault@amd.com>2017-12-13 21:07:51 +0000
commitcad7fa857cf6d9949f25dcc5bc1f313f7ec2b0b6 (patch)
treef908e4b0cdd17b3597b031b8b96e823f454695f1 /llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
parenta9f77c6df755841ba1ae2b5c56d0ca4d53907433 (diff)
downloadllvm-cad7fa857cf6d9949f25dcc5bc1f313f7ec2b0b6.zip
llvm-cad7fa857cf6d9949f25dcc5bc1f313f7ec2b0b6.tar.gz
llvm-cad7fa857cf6d9949f25dcc5bc1f313f7ec2b0b6.tar.bz2
AMDGPU: Partially fix disassembly of MIMG instructions
Stores failed to decode at all since they didn't have a DecoderNamespace set. Loads worked, but did not change the register width displayed to match the numbmer of enabled channels. The number of printed registers for vaddr is still wrong, but I don't think that's encoded in the instruction so there's not much we can do about that. Image atomics are still broken. MIMG is the same encoding for SI/VI, but the image atomic classes are split up into encoding specific versions unlike every other MIMG instruction. They have isAsmParserOnly set on them for some reason. dmask is also special for these, so we probably should not have it as an explicit operand as it is now. llvm-svn: 320614
Diffstat (limited to 'llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp')
-rw-r--r--llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp42
1 files changed, 41 insertions, 1 deletions
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
index a33670c..4a3f2c9 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
@@ -234,6 +234,10 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
AMDGPU::OpName::src2_modifiers);
}
+ if (Res && (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::MIMG)) {
+ Res = convertMIMGInst(MI);
+ }
+
if (Res && IsSDWA)
Res = convertSDWAInst(MI);
@@ -260,6 +264,42 @@ DecodeStatus AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const {
return MCDisassembler::Success;
}
+DecodeStatus AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const {
+ int VDataIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
+ AMDGPU::OpName::vdata);
+
+ int DMaskIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
+ AMDGPU::OpName::dmask);
+ unsigned DMask = MI.getOperand(DMaskIdx).getImm() & 0xf;
+ if (DMask == 0)
+ return MCDisassembler::Success;
+
+ unsigned ChannelCount = countPopulation(DMask);
+ if (ChannelCount == 1)
+ return MCDisassembler::Success;
+
+ int NewOpcode = AMDGPU::getMaskedMIMGOp(*MCII, MI.getOpcode(), ChannelCount);
+ assert(NewOpcode != -1 && "could not find matching mimg channel instruction");
+ auto RCID = MCII->get(NewOpcode).OpInfo[VDataIdx].RegClass;
+
+ // Widen the register to the correct number of enabled channels.
+ unsigned Vdata0 = MI.getOperand(VDataIdx).getReg();
+ auto NewVdata = MRI.getMatchingSuperReg(Vdata0, AMDGPU::sub0,
+ &MRI.getRegClass(RCID));
+ if (NewVdata == AMDGPU::NoRegister) {
+ // It's possible to encode this such that the low register + enabled
+ // components exceeds the register count.
+ return MCDisassembler::Success;
+ }
+
+ MI.setOpcode(NewOpcode);
+ // vaddr will be always appear as a single VGPR. This will look different than
+ // how it is usually emitted because the number of register components is not
+ // in the instruction encoding.
+ MI.getOperand(VDataIdx) = MCOperand::createReg(NewVdata);
+ return MCDisassembler::Success;
+}
+
const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const {
return getContext().getRegisterInfo()->
getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]);
@@ -786,7 +826,7 @@ static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/,
static MCDisassembler *createAMDGPUDisassembler(const Target &T,
const MCSubtargetInfo &STI,
MCContext &Ctx) {
- return new AMDGPUDisassembler(STI, Ctx);
+ return new AMDGPUDisassembler(STI, Ctx, T.createMCInstrInfo());
}
extern "C" void LLVMInitializeAMDGPUDisassembler() {