Просмотр исходного кода

shader: Fix ISCADD logic for PO/CC

ameerj 5 лет назад
Родитель
Сommit
cd9f75e223

+ 8 - 7
src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp

@@ -30,23 +30,24 @@ void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) {
         if (iscadd.neg_b != 0) {
             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 scaled_a{v.ir.ShiftLeftLogical(op_a, scale)};
 
-    IR::U32 result{v.ir.IAdd(scaled_a, op_b)};
-    if (po) {
-        // .PO adds one to the final result
-        result = v.ir.IAdd(result, v.ir.Imm32(1));
-    }
+    const IR::U32 result{v.ir.IAdd(scaled_a, op_b)};
     v.X(iscadd.dest_reg, result);
 
     if (iscadd.cc != 0) {
         v.SetZFlag(v.ir.GetZeroFromOp(result));
         v.SetSFlag(v.ir.GetSignFromOp(result));
-        v.SetCFlag(v.ir.GetCarryFromOp(result));
-        v.SetOFlag(v.ir.GetOverflowFromOp(result));
+        const IR::U1 carry{v.ir.GetCarryFromOp(result)};
+        const IR::U1 overflow{v.ir.GetOverflowFromOp(result)};
+        v.SetCFlag(po ? v.ir.LogicalOr(carry, v.ir.GetCarryFromOp(op_b)) : carry);
+        v.SetOFlag(po ? v.ir.LogicalOr(overflow, v.ir.GetOverflowFromOp(op_b)) : overflow);
     }
 }