gl_shader_decompiler: Implement BFE_IMM instruction.

This commit is contained in:
bunnei 2018-06-07 00:58:12 -04:00
parent 0cb7ce71e0
commit 92209f905f
2 changed files with 44 additions and 7 deletions

View File

@ -265,6 +265,17 @@ union Instruction {
BitField<49, 1, u64> negate_a; BitField<49, 1, u64> negate_a;
} iscadd; } iscadd;
union {
BitField<20, 8, u64> shift_position;
BitField<28, 8, u64> shift_length;
BitField<48, 1, u64> negate_b;
BitField<49, 1, u64> negate_a;
u64 GetLeftShiftValue() const {
return 32 - (shift_position + shift_length);
}
} bfe;
union { union {
BitField<48, 1, u64> negate_b; BitField<48, 1, u64> negate_b;
BitField<49, 1, u64> negate_c; BitField<49, 1, u64> negate_c;
@ -478,6 +489,7 @@ public:
enum class Type { enum class Type {
Trivial, Trivial,
Arithmetic, Arithmetic,
Bfe,
Logic, Logic,
Shift, Shift,
ScaledAdd, ScaledAdd,
@ -584,9 +596,6 @@ private:
std::vector<Matcher> table = { std::vector<Matcher> table = {
#define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name)
INST("111000110011----", Id::KIL, Type::Flow, "KIL"), INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
INST("0100110000000---", Id::BFE_C, Type::Flow, "BFE_C"),
INST("0101110000000---", Id::BFE_R, Type::Flow, "BFE_R"),
INST("0011100-00000---", Id::BFE_IMM, Type::Flow, "BFE_IMM"),
INST("111000100100----", Id::BRA, Type::Flow, "BRA"), INST("111000100100----", Id::BRA, Type::Flow, "BRA"),
INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"),
INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"),
@ -631,6 +640,9 @@ private:
INST("0100110000100---", Id::IMNMX_C, Type::Arithmetic, "FMNMX_IMM"), INST("0100110000100---", Id::IMNMX_C, Type::Arithmetic, "FMNMX_IMM"),
INST("0101110000100---", Id::IMNMX_R, Type::Arithmetic, "FMNMX_IMM"), INST("0101110000100---", Id::IMNMX_R, Type::Arithmetic, "FMNMX_IMM"),
INST("0011100-00100---", Id::IMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), INST("0011100-00100---", Id::IMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"),
INST("0100110000000---", Id::BFE_C, Type::Bfe, "BFE_C"),
INST("0101110000000---", Id::BFE_R, Type::Bfe, "BFE_R"),
INST("0011100-00000---", Id::BFE_IMM, Type::Bfe, "BFE_IMM"),
INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"), INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"),
INST("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"), INST("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"),
INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"), INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"),

View File

@ -888,8 +888,33 @@ private:
} }
break; break;
} }
case OpCode::Type::Bfe: {
ASSERT_MSG(!instr.bfe.negate_b, "Unimplemented");
std::string op_a = instr.bfe.negate_a ? "-" : "";
op_a += regs.GetRegisterAsInteger(instr.gpr8);
switch (opcode->GetId()) {
case OpCode::Id::BFE_IMM: {
std::string inner_shift =
'(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')';
std::string outer_shift =
'(' + inner_shift + " >> " +
std::to_string(instr.bfe.GetLeftShiftValue() + instr.bfe.shift_position) + ')';
regs.SetRegisterToInteger(instr.gpr0, true, 0, outer_shift, 1, 1);
break;
}
default: {
NGLOG_CRITICAL(HW_GPU, "Unhandled BFE instruction: {}", opcode->GetName());
UNREACHABLE();
}
}
break;
}
case OpCode::Type::Logic: { case OpCode::Type::Logic: {
std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, false); std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, true);
if (instr.alu.lop.invert_a) if (instr.alu.lop.invert_a)
op_a = "~(" + op_a + ')'; op_a = "~(" + op_a + ')';
@ -903,17 +928,17 @@ private:
switch (instr.alu.lop.operation) { switch (instr.alu.lop.operation) {
case Tegra::Shader::LogicOperation::And: { case Tegra::Shader::LogicOperation::And: {
regs.SetRegisterToInteger(instr.gpr0, false, 0, regs.SetRegisterToInteger(instr.gpr0, true, 0,
'(' + op_a + " & " + std::to_string(imm) + ')', 1, 1); '(' + op_a + " & " + std::to_string(imm) + ')', 1, 1);
break; break;
} }
case Tegra::Shader::LogicOperation::Or: { case Tegra::Shader::LogicOperation::Or: {
regs.SetRegisterToInteger(instr.gpr0, false, 0, regs.SetRegisterToInteger(instr.gpr0, true, 0,
'(' + op_a + " | " + std::to_string(imm) + ')', 1, 1); '(' + op_a + " | " + std::to_string(imm) + ')', 1, 1);
break; break;
} }
case Tegra::Shader::LogicOperation::Xor: { case Tegra::Shader::LogicOperation::Xor: {
regs.SetRegisterToInteger(instr.gpr0, false, 0, regs.SetRegisterToInteger(instr.gpr0, true, 0,
'(' + op_a + " ^ " + std::to_string(imm) + ')', 1, 1); '(' + op_a + " ^ " + std::to_string(imm) + ')', 1, 1);
break; break;
} }