summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2018-12-19 00:31:58 -0300
committerGravatar ReinUsesLisp2019-01-15 17:54:52 -0300
commit4fd06efeb94ff5fc5af4c5e4b9e8a4fa95d3b383 (patch)
tree85161efb42877cfa211d6c19b3aad3d0dd7af1cc
parentshader_decode: Implement LOP3 (diff)
downloadyuzu-4fd06efeb94ff5fc5af4c5e4b9e8a4fa95d3b383.tar.gz
yuzu-4fd06efeb94ff5fc5af4c5e4b9e8a4fa95d3b383.tar.xz
yuzu-4fd06efeb94ff5fc5af4c5e4b9e8a4fa95d3b383.zip
shader_decode: Implement IADD3
-rw-r--r--src/video_core/shader/decode/arithmetic_integer.cpp61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp
index 145bbcfc8..3b9b9d6d9 100644
--- a/src/video_core/shader/decode/arithmetic_integer.cpp
+++ b/src/video_core/shader/decode/arithmetic_integer.cpp
@@ -9,6 +9,7 @@
9 9
10namespace VideoCommon::Shader { 10namespace VideoCommon::Shader {
11 11
12using Tegra::Shader::IAdd3Height;
12using Tegra::Shader::Instruction; 13using Tegra::Shader::Instruction;
13using Tegra::Shader::OpCode; 14using Tegra::Shader::OpCode;
14using Tegra::Shader::Register; 15using Tegra::Shader::Register;
@@ -42,6 +43,66 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) {
42 SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b)); 43 SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b));
43 break; 44 break;
44 } 45 }
46 case OpCode::Id::IADD3_C:
47 case OpCode::Id::IADD3_R:
48 case OpCode::Id::IADD3_IMM: {
49 UNIMPLEMENTED_IF_MSG(instr.generates_cc,
50 "Condition codes generation in IADD3 is not implemented");
51
52 Node op_c = GetRegister(instr.gpr39);
53
54 const auto ApplyHeight = [&](IAdd3Height height, Node value) {
55 switch (height) {
56 case IAdd3Height::None:
57 return value;
58 case IAdd3Height::LowerHalfWord:
59 return Operation(OperationCode::IBitwiseAnd, NO_PRECISE, value, Immediate(0xffff));
60 case IAdd3Height::UpperHalfWord:
61 return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, value,
62 Immediate(16));
63 default:
64 UNIMPLEMENTED_MSG("Unhandled IADD3 height: {}", static_cast<u32>(height));
65 return Immediate(0);
66 }
67 };
68
69 if (opcode->get().GetId() == OpCode::Id::IADD3_R) {
70 op_a = ApplyHeight(instr.iadd3.height_a, op_a);
71 op_b = ApplyHeight(instr.iadd3.height_b, op_b);
72 op_c = ApplyHeight(instr.iadd3.height_c, op_c);
73 }
74
75 op_a = GetOperandAbsNegInteger(op_a, false, instr.iadd3.neg_a, true);
76 op_b = GetOperandAbsNegInteger(op_b, false, instr.iadd3.neg_b, true);
77 op_c = GetOperandAbsNegInteger(op_c, false, instr.iadd3.neg_c, true);
78
79 const Node value = [&]() {
80 const Node add_ab = Operation(OperationCode::IAdd, NO_PRECISE, op_a, op_b);
81 if (opcode->get().GetId() != OpCode::Id::IADD3_R) {
82 return Operation(OperationCode::IAdd, NO_PRECISE, add_ab, op_c);
83 }
84 const Node shifted = [&]() {
85 switch (instr.iadd3.mode) {
86 case Tegra::Shader::IAdd3Mode::RightShift:
87 // TODO(tech4me): According to
88 // https://envytools.readthedocs.io/en/latest/hw/graph/maxwell/cuda/int.html?highlight=iadd3
89 // The addition between op_a and op_b should be done in uint33, more
90 // investigation required
91 return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, add_ab,
92 Immediate(16));
93 case Tegra::Shader::IAdd3Mode::LeftShift:
94 return Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, add_ab,
95 Immediate(16));
96 default:
97 return add_ab;
98 }
99 }();
100 return Operation(OperationCode::IAdd, NO_PRECISE, shifted, op_c);
101 }();
102
103 SetRegister(bb, instr.gpr0, value);
104 break;
105 }
45 case OpCode::Id::ISCADD_C: 106 case OpCode::Id::ISCADD_C:
46 case OpCode::Id::ISCADD_R: 107 case OpCode::Id::ISCADD_R:
47 case OpCode::Id::ISCADD_IMM: { 108 case OpCode::Id::ISCADD_IMM: {