summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/integer_add_three_input.cpp29
1 files changed, 22 insertions, 7 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add_three_input.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add_three_input.cpp
index c2dbd7998..e88c0ffb6 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add_three_input.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_add_three_input.cpp
@@ -58,13 +58,6 @@ void IADD3(TranslatorVisitor& v, u64 insn, IR::U32 op_b, IR::U32 op_c) {
58 BitField<51, 1, u64> neg_a; 58 BitField<51, 1, u64> neg_a;
59 } iadd3{insn}; 59 } iadd3{insn};
60 60
61 if (iadd3.x != 0) {
62 throw NotImplementedException("IADD3 X");
63 }
64 if (iadd3.cc != 0) {
65 throw NotImplementedException("IADD3 CC");
66 }
67
68 IR::U32 op_a{v.X(iadd3.src_a)}; 61 IR::U32 op_a{v.X(iadd3.src_a)};
69 op_a = IntegerHalf(v.ir, op_a, iadd3.half_a); 62 op_a = IntegerHalf(v.ir, op_a, iadd3.half_a);
70 op_b = IntegerHalf(v.ir, op_b, iadd3.half_b); 63 op_b = IntegerHalf(v.ir, op_b, iadd3.half_b);
@@ -81,10 +74,32 @@ void IADD3(TranslatorVisitor& v, u64 insn, IR::U32 op_b, IR::U32 op_c) {
81 } 74 }
82 75
83 IR::U32 lhs{v.ir.IAdd(op_a, op_b)}; 76 IR::U32 lhs{v.ir.IAdd(op_a, op_b)};
77 IR::U1 of_1;
78 if (iadd3.cc != 0) {
79 of_1 = v.ir.GetOverflowFromOp(lhs);
80 }
81 if (iadd3.x != 0) {
82 const IR::U32 carry{v.ir.Select(v.ir.GetCFlag(), v.ir.Imm32(1), v.ir.Imm32(0))};
83 lhs = v.ir.IAdd(lhs, carry);
84 }
85 if (iadd3.cc != 0 && iadd3.shift == Shift::Left) {
86 IR::U32 high_bits{v.ir.ShiftRightLogical(lhs, v.ir.Imm32(16))};
87 of_1 = v.ir.LogicalOr(of_1, v.ir.INotEqual(v.ir.Imm32(0), high_bits));
88 }
84 lhs = IntegerShift(v.ir, lhs, iadd3.shift); 89 lhs = IntegerShift(v.ir, lhs, iadd3.shift);
85 const IR::U32 result{v.ir.IAdd(lhs, op_c)}; 90 const IR::U32 result{v.ir.IAdd(lhs, op_c)};
86 91
87 v.X(iadd3.dest_reg, result); 92 v.X(iadd3.dest_reg, result);
93 if (iadd3.cc != 0) {
94 // TODO: How does CC behave when X is set?
95 if (iadd3.x != 0) {
96 throw NotImplementedException("IADD3 X+CC");
97 }
98 v.SetZFlag(v.ir.GetZeroFromOp(result));
99 v.SetSFlag(v.ir.GetSignFromOp(result));
100 v.SetCFlag(v.ir.GetCarryFromOp(result));
101 v.SetOFlag(v.ir.LogicalOr(v.ir.GetOverflowFromOp(result), of_1));
102 }
88} 103}
89} // Anonymous namespace 104} // Anonymous namespace
90 105