From 92209f905fff33eaf4812c3d4a153ff9fffb1ed0 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 7 Jun 2018 00:58:12 -0400 Subject: [PATCH] gl_shader_decompiler: Implement BFE_IMM instruction. --- src/video_core/engines/shader_bytecode.h | 18 ++++++++-- .../renderer_opengl/gl_shader_decompiler.cpp | 33 ++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 2cda1e63e..32800392b 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -265,6 +265,17 @@ union Instruction { BitField<49, 1, u64> negate_a; } 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 { BitField<48, 1, u64> negate_b; BitField<49, 1, u64> negate_c; @@ -478,6 +489,7 @@ public: enum class Type { Trivial, Arithmetic, + Bfe, Logic, Shift, ScaledAdd, @@ -584,9 +596,6 @@ private: std::vector table = { #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) 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("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), @@ -631,6 +640,9 @@ private: INST("0100110000100---", Id::IMNMX_C, Type::Arithmetic, "FMNMX_IMM"), INST("0101110000100---", Id::IMNMX_R, 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("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"), INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"), diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 8e249584f..94c6bc4b2 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -888,8 +888,33 @@ private: } 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: { - 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) op_a = "~(" + op_a + ')'; @@ -903,17 +928,17 @@ private: switch (instr.alu.lop.operation) { 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); break; } 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); break; } 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); break; }