From e99f7da24e1c60300bb8a19628fc16b528c571d9 Mon Sep 17 00:00:00 2001
From: Wunkolo <Wunkolo@gmail.com>
Date: Sat, 17 Aug 2024 11:48:17 -0700
Subject: [PATCH] shader_jit_a64: Fix/optimize conditional evaluation

Fix some of the regressions introduced by the previous optimization.
EOR does not support a constant of `0` in its immediate. In these cases
the COND{0,1} registers can be utilized immediately.
---
 .../shader/shader_jit_a64_compiler.cpp        | 46 ++++++++++++++-----
 1 file changed, 34 insertions(+), 12 deletions(-)

diff --git a/src/video_core/shader/shader_jit_a64_compiler.cpp b/src/video_core/shader/shader_jit_a64_compiler.cpp
index 4e55b7b86..2927a28c5 100644
--- a/src/video_core/shader/shader_jit_a64_compiler.cpp
+++ b/src/video_core/shader/shader_jit_a64_compiler.cpp
@@ -386,28 +386,50 @@ void JitShader::Compile_SanitizedMul(QReg src1, QReg src2, QReg scratch0) {
 }
 
 void JitShader::Compile_EvaluateCondition(Instruction instr) {
-    const u8 refx = instr.flow_control.refx.Value();
-    const u8 refy = instr.flow_control.refy.Value();
+    const bool refx = instr.flow_control.refx.Value();
+    const bool refy = instr.flow_control.refy.Value();
 
     switch (instr.flow_control.op) {
     // Note: NXOR is used below to check for equality
-    case Instruction::FlowControlType::Or:
-        EOR(XSCRATCH0, COND0, refx ^ 1);
-        EOR(XSCRATCH1, COND1, refy ^ 1);
-        ORR(XSCRATCH0, XSCRATCH0, XSCRATCH1);
+    case Instruction::FlowControlType::Or: {
+        XReg OpX = XSCRATCH0;
+        if (!refx) {
+            EOR(OpX, COND0, u8(refx) ^ 1);
+        } else {
+            OpX = COND0;
+        }
+        XReg OpY = XSCRATCH1;
+        if (!refy) {
+            EOR(OpY, COND1, u8(refy) ^ 1);
+        } else {
+            OpY = COND1;
+        }
+        ORR(XSCRATCH0, OpX, OpY);
         CMP(XSCRATCH0, 0);
         break;
+    }
     // Note: TST will AND two registers and set the EQ/NE flags on the result
-    case Instruction::FlowControlType::And:
-        EOR(XSCRATCH0, COND0, refx ^ 1);
-        EOR(XSCRATCH1, COND1, refy ^ 1);
-        TST(XSCRATCH0, XSCRATCH1);
+    case Instruction::FlowControlType::And: {
+        XReg OpX = XSCRATCH0;
+        if (!refx) {
+            EOR(OpX, COND0, u8(refx) ^ 1);
+        } else {
+            OpX = COND0;
+        }
+        XReg OpY = XSCRATCH1;
+        if (!refy) {
+            EOR(OpY, COND1, u8(refy) ^ 1);
+        } else {
+            OpY = COND1;
+        }
+        TST(OpX, OpY);
         break;
+    }
     case Instruction::FlowControlType::JustX:
-        CMP(COND0, refx);
+        CMP(COND0, u8(refx) ^ 1);
         break;
     case Instruction::FlowControlType::JustY:
-        CMP(COND1, refy);
+        CMP(COND1, u8(refy) ^ 1);
         break;
     default:
         UNREACHABLE();