diff options
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp index 93cc2c0b1..044671943 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp | |||
| @@ -8,40 +8,36 @@ | |||
| 8 | 8 | ||
| 9 | namespace Shader::Maxwell { | 9 | namespace Shader::Maxwell { |
| 10 | namespace { | 10 | namespace { |
| 11 | void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) { | 11 | void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b, bool cc, bool neg_a, bool neg_b, |
| 12 | u64 scale_imm) { | ||
| 12 | union { | 13 | union { |
| 13 | u64 raw; | 14 | u64 raw; |
| 14 | BitField<0, 8, IR::Reg> dest_reg; | 15 | BitField<0, 8, IR::Reg> dest_reg; |
| 15 | BitField<8, 8, IR::Reg> op_a; | 16 | BitField<8, 8, IR::Reg> op_a; |
| 16 | BitField<47, 1, u64> cc; | ||
| 17 | BitField<48, 2, u64> three_for_po; | ||
| 18 | BitField<48, 1, u64> neg_b; | ||
| 19 | BitField<49, 1, u64> neg_a; | ||
| 20 | BitField<39, 5, u64> scale; | ||
| 21 | } const iscadd{insn}; | 17 | } const iscadd{insn}; |
| 22 | 18 | ||
| 23 | const bool po{iscadd.three_for_po == 3}; | 19 | const bool po{neg_a && neg_b}; |
| 24 | IR::U32 op_a{v.X(iscadd.op_a)}; | 20 | IR::U32 op_a{v.X(iscadd.op_a)}; |
| 25 | if (!po) { | 21 | if (po) { |
| 22 | // When PO is present, add one | ||
| 23 | op_b = v.ir.IAdd(op_b, v.ir.Imm32(1)); | ||
| 24 | } else { | ||
| 26 | // When PO is not present, the bits are interpreted as negation | 25 | // When PO is not present, the bits are interpreted as negation |
| 27 | if (iscadd.neg_a != 0) { | 26 | if (neg_a) { |
| 28 | op_a = v.ir.INeg(op_a); | 27 | op_a = v.ir.INeg(op_a); |
| 29 | } | 28 | } |
| 30 | if (iscadd.neg_b != 0) { | 29 | if (neg_b) { |
| 31 | op_b = v.ir.INeg(op_b); | 30 | op_b = v.ir.INeg(op_b); |
| 32 | } | 31 | } |
| 33 | } else { | ||
| 34 | // When PO is present, add one | ||
| 35 | op_b = v.ir.IAdd(op_b, v.ir.Imm32(1)); | ||
| 36 | } | 32 | } |
| 37 | // With the operands already processed, scale A | 33 | // With the operands already processed, scale A |
| 38 | const IR::U32 scale{v.ir.Imm32(static_cast<u32>(iscadd.scale))}; | 34 | const IR::U32 scale{v.ir.Imm32(static_cast<u32>(scale_imm))}; |
| 39 | const IR::U32 scaled_a{v.ir.ShiftLeftLogical(op_a, scale)}; | 35 | const IR::U32 scaled_a{v.ir.ShiftLeftLogical(op_a, scale)}; |
| 40 | 36 | ||
| 41 | const IR::U32 result{v.ir.IAdd(scaled_a, op_b)}; | 37 | const IR::U32 result{v.ir.IAdd(scaled_a, op_b)}; |
| 42 | v.X(iscadd.dest_reg, result); | 38 | v.X(iscadd.dest_reg, result); |
| 43 | 39 | ||
| 44 | if (iscadd.cc != 0) { | 40 | if (cc) { |
| 45 | v.SetZFlag(v.ir.GetZeroFromOp(result)); | 41 | v.SetZFlag(v.ir.GetZeroFromOp(result)); |
| 46 | v.SetSFlag(v.ir.GetSignFromOp(result)); | 42 | v.SetSFlag(v.ir.GetSignFromOp(result)); |
| 47 | const IR::U1 carry{v.ir.GetCarryFromOp(result)}; | 43 | const IR::U1 carry{v.ir.GetCarryFromOp(result)}; |
| @@ -51,6 +47,18 @@ void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) { | |||
| 51 | } | 47 | } |
| 52 | } | 48 | } |
| 53 | 49 | ||
| 50 | void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) { | ||
| 51 | union { | ||
| 52 | u64 raw; | ||
| 53 | BitField<47, 1, u64> cc; | ||
| 54 | BitField<48, 1, u64> neg_b; | ||
| 55 | BitField<49, 1, u64> neg_a; | ||
| 56 | BitField<39, 5, u64> scale; | ||
| 57 | } const iscadd{insn}; | ||
| 58 | |||
| 59 | ISCADD(v, insn, op_b, iscadd.cc != 0, iscadd.neg_a != 0, iscadd.neg_b != 0, iscadd.scale); | ||
| 60 | } | ||
| 61 | |||
| 54 | } // Anonymous namespace | 62 | } // Anonymous namespace |
| 55 | 63 | ||
| 56 | void TranslatorVisitor::ISCADD_reg(u64 insn) { | 64 | void TranslatorVisitor::ISCADD_reg(u64 insn) { |
| @@ -65,8 +73,14 @@ void TranslatorVisitor::ISCADD_imm(u64 insn) { | |||
| 65 | ISCADD(*this, insn, GetImm20(insn)); | 73 | ISCADD(*this, insn, GetImm20(insn)); |
| 66 | } | 74 | } |
| 67 | 75 | ||
| 68 | void TranslatorVisitor::ISCADD32I(u64) { | 76 | void TranslatorVisitor::ISCADD32I(u64 insn) { |
| 69 | throw NotImplementedException("ISCADD32I"); | 77 | union { |
| 78 | u64 raw; | ||
| 79 | BitField<52, 1, u64> cc; | ||
| 80 | BitField<53, 5, u64> scale; | ||
| 81 | } const iscadd{insn}; | ||
| 82 | |||
| 83 | return ISCADD(*this, insn, GetImm32(insn), iscadd.cc != 0, false, false, iscadd.scale); | ||
| 70 | } | 84 | } |
| 71 | 85 | ||
| 72 | } // namespace Shader::Maxwell | 86 | } // namespace Shader::Maxwell |