summaryrefslogtreecommitdiffstats
path: root/src/video_core/shader/decode/arithmetic_integer.cpp
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2020-04-30 18:56:36 +0200
committerGitHub <noreply@github.com>2020-04-30 18:56:36 +0200
commitc7b5a87c9038f37e5fec07336de575498a84b534 (patch)
treeaaefec229f8ddcb6744b405757d2559c1dcf0b92 /src/video_core/shader/decode/arithmetic_integer.cpp
parentMerge pull request #3805 from ReinUsesLisp/preserve-contents (diff)
parentshader/arithmetic_integer: Fix tracking issue in temporary (diff)
downloadyuzu-c7b5a87c9038f37e5fec07336de575498a84b534.tar
yuzu-c7b5a87c9038f37e5fec07336de575498a84b534.tar.gz
yuzu-c7b5a87c9038f37e5fec07336de575498a84b534.tar.bz2
yuzu-c7b5a87c9038f37e5fec07336de575498a84b534.tar.lz
yuzu-c7b5a87c9038f37e5fec07336de575498a84b534.tar.xz
yuzu-c7b5a87c9038f37e5fec07336de575498a84b534.tar.zst
yuzu-c7b5a87c9038f37e5fec07336de575498a84b534.zip
Diffstat (limited to 'src/video_core/shader/decode/arithmetic_integer.cpp')
-rw-r--r--src/video_core/shader/decode/arithmetic_integer.cpp31
1 files changed, 27 insertions, 4 deletions
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp
index 9af8c606d..a041519b7 100644
--- a/src/video_core/shader/decode/arithmetic_integer.cpp
+++ b/src/video_core/shader/decode/arithmetic_integer.cpp
@@ -35,15 +35,38 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
case OpCode::Id::IADD_C:
case OpCode::Id::IADD_R:
case OpCode::Id::IADD_IMM: {
- UNIMPLEMENTED_IF_MSG(instr.alu.saturate_d, "IADD saturation not implemented");
+ UNIMPLEMENTED_IF_MSG(instr.alu.saturate_d, "IADD.SAT");
+ UNIMPLEMENTED_IF_MSG(instr.iadd.x && instr.generates_cc, "IADD.X Rd.CC");
op_a = GetOperandAbsNegInteger(op_a, false, instr.alu_integer.negate_a, true);
op_b = GetOperandAbsNegInteger(op_b, false, instr.alu_integer.negate_b, true);
- const Node value = Operation(OperationCode::IAdd, PRECISE, op_a, op_b);
+ Node value = Operation(OperationCode::UAdd, op_a, op_b);
- SetInternalFlagsFromInteger(bb, value, instr.generates_cc);
- SetRegister(bb, instr.gpr0, value);
+ if (instr.iadd.x) {
+ Node carry = GetInternalFlag(InternalFlag::Carry);
+ Node x = Operation(OperationCode::Select, std::move(carry), Immediate(1), Immediate(0));
+ value = Operation(OperationCode::UAdd, std::move(value), std::move(x));
+ }
+
+ if (instr.generates_cc) {
+ const Node i0 = Immediate(0);
+
+ Node zero = Operation(OperationCode::LogicalIEqual, value, i0);
+ Node sign = Operation(OperationCode::LogicalILessThan, value, i0);
+ Node carry = Operation(OperationCode::LogicalAddCarry, op_a, op_b);
+
+ Node pos_a = Operation(OperationCode::LogicalIGreaterThan, op_a, i0);
+ Node pos_b = Operation(OperationCode::LogicalIGreaterThan, op_b, i0);
+ Node pos = Operation(OperationCode::LogicalAnd, std::move(pos_a), std::move(pos_b));
+ Node overflow = Operation(OperationCode::LogicalAnd, pos, sign);
+
+ SetInternalFlag(bb, InternalFlag::Zero, std::move(zero));
+ SetInternalFlag(bb, InternalFlag::Sign, std::move(sign));
+ SetInternalFlag(bb, InternalFlag::Carry, std::move(carry));
+ SetInternalFlag(bb, InternalFlag::Overflow, std::move(overflow));
+ }
+ SetRegister(bb, instr.gpr0, std::move(value));
break;
}
case OpCode::Id::IADD3_C: