summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2018-06-07 06:58:12 +0200
committerbunnei <bunneidev@gmail.com>2018-06-07 06:58:12 +0200
commit92209f905fff33eaf4812c3d4a153ff9fffb1ed0 (patch)
tree53ef881e880ba5d728c31094f00ccd56e5d7e9c5
parentMerge pull request #539 from bunnei/f2f-rounding (diff)
downloadyuzu-92209f905fff33eaf4812c3d4a153ff9fffb1ed0.tar
yuzu-92209f905fff33eaf4812c3d4a153ff9fffb1ed0.tar.gz
yuzu-92209f905fff33eaf4812c3d4a153ff9fffb1ed0.tar.bz2
yuzu-92209f905fff33eaf4812c3d4a153ff9fffb1ed0.tar.lz
yuzu-92209f905fff33eaf4812c3d4a153ff9fffb1ed0.tar.xz
yuzu-92209f905fff33eaf4812c3d4a153ff9fffb1ed0.tar.zst
yuzu-92209f905fff33eaf4812c3d4a153ff9fffb1ed0.zip
-rw-r--r--src/video_core/engines/shader_bytecode.h18
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp33
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
@@ -266,6 +266,17 @@ union Instruction {
} 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;
} ffma;
@@ -478,6 +489,7 @@ public:
enum class Type {
Trivial,
Arithmetic,
+ Bfe,
Logic,
Shift,
ScaledAdd,
@@ -584,9 +596,6 @@ private:
std::vector<Matcher> 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;
}