From 5d170de0b5c57afdfc7c633c0b3b36d7ea9299c2 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 30 May 2021 20:46:07 -0300
Subject: shader: Implement ISCADD32I

---
 .../maxwell/translate/impl/integer_scaled_add.cpp  | 48 ++++++++++++++--------
 1 file changed, 31 insertions(+), 17 deletions(-)

(limited to 'src/shader_recompiler/frontend')

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 93cc2c0b1c..044671943e 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 @@
 
 namespace Shader::Maxwell {
 namespace {
-void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) {
+void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b, bool cc, bool neg_a, bool neg_b,
+            u64 scale_imm) {
     union {
         u64 raw;
         BitField<0, 8, IR::Reg> dest_reg;
         BitField<8, 8, IR::Reg> op_a;
-        BitField<47, 1, u64> cc;
-        BitField<48, 2, u64> three_for_po;
-        BitField<48, 1, u64> neg_b;
-        BitField<49, 1, u64> neg_a;
-        BitField<39, 5, u64> scale;
     } const iscadd{insn};
 
-    const bool po{iscadd.three_for_po == 3};
+    const bool po{neg_a && neg_b};
     IR::U32 op_a{v.X(iscadd.op_a)};
-    if (!po) {
+    if (po) {
+        // When PO is present, add one
+        op_b = v.ir.IAdd(op_b, v.ir.Imm32(1));
+    } else {
         // When PO is not present, the bits are interpreted as negation
-        if (iscadd.neg_a != 0) {
+        if (neg_a) {
             op_a = v.ir.INeg(op_a);
         }
-        if (iscadd.neg_b != 0) {
+        if (neg_b) {
             op_b = v.ir.INeg(op_b);
         }
-    } else {
-        // When PO is present, add one
-        op_b = v.ir.IAdd(op_b, v.ir.Imm32(1));
     }
     // With the operands already processed, scale A
-    const IR::U32 scale{v.ir.Imm32(static_cast<u32>(iscadd.scale))};
+    const IR::U32 scale{v.ir.Imm32(static_cast<u32>(scale_imm))};
     const IR::U32 scaled_a{v.ir.ShiftLeftLogical(op_a, scale)};
 
     const IR::U32 result{v.ir.IAdd(scaled_a, op_b)};
     v.X(iscadd.dest_reg, result);
 
-    if (iscadd.cc != 0) {
+    if (cc) {
         v.SetZFlag(v.ir.GetZeroFromOp(result));
         v.SetSFlag(v.ir.GetSignFromOp(result));
         const IR::U1 carry{v.ir.GetCarryFromOp(result)};
@@ -51,6 +47,18 @@ void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) {
     }
 }
 
+void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) {
+    union {
+        u64 raw;
+        BitField<47, 1, u64> cc;
+        BitField<48, 1, u64> neg_b;
+        BitField<49, 1, u64> neg_a;
+        BitField<39, 5, u64> scale;
+    } const iscadd{insn};
+
+    ISCADD(v, insn, op_b, iscadd.cc != 0, iscadd.neg_a != 0, iscadd.neg_b != 0, iscadd.scale);
+}
+
 } // Anonymous namespace
 
 void TranslatorVisitor::ISCADD_reg(u64 insn) {
@@ -65,8 +73,14 @@ void TranslatorVisitor::ISCADD_imm(u64 insn) {
     ISCADD(*this, insn, GetImm20(insn));
 }
 
-void TranslatorVisitor::ISCADD32I(u64) {
-    throw NotImplementedException("ISCADD32I");
+void TranslatorVisitor::ISCADD32I(u64 insn) {
+    union {
+        u64 raw;
+        BitField<52, 1, u64> cc;
+        BitField<53, 5, u64> scale;
+    } const iscadd{insn};
+
+    return ISCADD(*this, insn, GetImm32(insn), iscadd.cc != 0, false, false, iscadd.scale);
 }
 
 } // namespace Shader::Maxwell
-- 
cgit v1.2.3-70-g09d2