From c788f9c0bd9cb0b0cb66f7424a65032cca3731cc Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sat, 25 Apr 2020 22:41:20 -0300
Subject: [PATCH] shader/arithmetic_integer: Implement IADD.X

IADD.X takes the carry flag and adds it to the result. This is generally
used to emulate 64-bit operations with 32-bit registers.
---
 src/video_core/engines/shader_bytecode.h            | 4 ++++
 src/video_core/shader/decode/arithmetic_integer.cpp | 6 ++++++
 2 files changed, 10 insertions(+)

diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index cde3a26b9d..8dae754d49 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -813,6 +813,10 @@ union Instruction {
         BitField<49, 1, u64> negate_a;
     } alu_integer;
 
+    union {
+        BitField<43, 1, u64> x;
+    } iadd;
+
     union {
         BitField<39, 1, u64> ftz;
         BitField<32, 1, u64> saturate;
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp
index 99b4b6342f..2a3311cb8e 100644
--- a/src/video_core/shader/decode/arithmetic_integer.cpp
+++ b/src/video_core/shader/decode/arithmetic_integer.cpp
@@ -42,6 +42,12 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
 
         Node value = Operation(OperationCode::IAdd, op_a, op_b);
 
+        if (instr.iadd.x) {
+            Node carry = GetInternalFlag(InternalFlag::Carry);
+            Node x = Operation(OperationCode::Select, std::move(carry), Immediate(1), Immediate(0));
+            value = Operation(OperationCode::IAdd, std::move(value), std::move(x));
+        }
+
         if (instr.generates_cc) {
             const Node i0 = Immediate(0);