diff options
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/translate/impl/integer_add_three_input.cpp | 29 |
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 | ||