diff options
author | bunnei <bunneidev@gmail.com> | 2018-06-05 02:48:15 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-05 02:48:15 +0200 |
commit | e8bfff7b4bee1472ae618cecb52343a41be39b8b (patch) | |
tree | 69b5926ccdfbc50eeb46737488ae8fe696fa090c | |
parent | Merge pull request #510 from Subv/isetp (diff) | |
parent | GPU: Implemented the LOP32I instruction. (diff) | |
download | yuzu-e8bfff7b4bee1472ae618cecb52343a41be39b8b.tar yuzu-e8bfff7b4bee1472ae618cecb52343a41be39b8b.tar.gz yuzu-e8bfff7b4bee1472ae618cecb52343a41be39b8b.tar.bz2 yuzu-e8bfff7b4bee1472ae618cecb52343a41be39b8b.tar.lz yuzu-e8bfff7b4bee1472ae618cecb52343a41be39b8b.tar.xz yuzu-e8bfff7b4bee1472ae618cecb52343a41be39b8b.tar.zst yuzu-e8bfff7b4bee1472ae618cecb52343a41be39b8b.zip |
-rw-r--r-- | src/video_core/engines/shader_bytecode.h | 16 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 43 |
2 files changed, 58 insertions, 1 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 3add56155..22c122fcc 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -156,6 +156,13 @@ enum class PredOperation : u64 { Xor = 2, }; +enum class LogicOperation : u64 { + And = 0, + Or = 1, + Xor = 2, + PassB = 3, +}; + enum class SubOp : u64 { Cos = 0x0, Sin = 0x1, @@ -202,6 +209,12 @@ union Instruction { BitField<42, 1, u64> negate_pred; } fmnmx; + union { + BitField<53, 2, LogicOperation> operation; + BitField<55, 1, u64> invert_a; + BitField<56, 1, u64> invert_b; + } lop; + float GetImm20_19() const { float result{}; u32 imm{static_cast<u32>(imm20_19)}; @@ -391,6 +404,7 @@ public: enum class Type { Trivial, Arithmetic, + Logic, Ffma, Flow, Memory, @@ -524,7 +538,6 @@ private: INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), - INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"), INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), @@ -535,6 +548,7 @@ private: INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"), INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"), INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), + INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"), INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 8c263f15f..9943394c6 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -841,6 +841,49 @@ private: } break; } + case OpCode::Type::Logic: { + std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, false); + + if (instr.alu.lop.invert_a) + op_a = "~(" + op_a + ')'; + + switch (opcode->GetId()) { + case OpCode::Id::LOP32I: { + u32 imm = static_cast<u32>(instr.alu.imm20_32.Value()); + + if (instr.alu.lop.invert_b) + imm = ~imm; + + switch (instr.alu.lop.operation) { + case Tegra::Shader::LogicOperation::And: { + regs.SetRegisterToInteger(instr.gpr0, false, 0, + '(' + op_a + " & " + std::to_string(imm) + ')', 1, 1); + break; + } + case Tegra::Shader::LogicOperation::Or: { + regs.SetRegisterToInteger(instr.gpr0, false, 0, + '(' + op_a + " | " + std::to_string(imm) + ')', 1, 1); + break; + } + case Tegra::Shader::LogicOperation::Xor: { + regs.SetRegisterToInteger(instr.gpr0, false, 0, + '(' + op_a + " ^ " + std::to_string(imm) + ')', 1, 1); + break; + } + default: + NGLOG_CRITICAL(HW_GPU, "Unimplemented lop32i operation: {}", + static_cast<u32>(instr.alu.lop.operation.Value())); + UNREACHABLE(); + } + break; + } + default: { + NGLOG_CRITICAL(HW_GPU, "Unhandled logic instruction: {}", opcode->GetName()); + UNREACHABLE(); + } + } + break; + } case OpCode::Type::Ffma: { std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); std::string op_b = instr.ffma.negate_b ? "-" : ""; |