diff options
| author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2020-04-25 21:56:11 -0300 | 
|---|---|---|
| committer | ReinUsesLisp <reinuseslisp@airmail.cc> | 2020-04-25 22:55:26 -0300 | 
| commit | 255197e64363f9286ed145cafdeb129c85c16621 (patch) | |
| tree | 976cb93129b86277b8136f21f3c7c2492bb8694d /src/video_core/shader | |
| parent | ffc5ec6fa816b1bf56044b9d8cf5f1935abe77ee (diff) | |
shader/arithmetic_integer: Implement CC for IADD
Diffstat (limited to 'src/video_core/shader')
| -rw-r--r-- | src/video_core/shader/decode/arithmetic_integer.cpp | 22 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 2 | 
2 files changed, 21 insertions, 3 deletions
| diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index 9af8c606d..99b4b6342 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp @@ -40,10 +40,26 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {          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::IAdd, op_a, op_b); -        SetInternalFlagsFromInteger(bb, value, instr.generates_cc); -        SetRegister(bb, instr.gpr0, value); +        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: diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 3eee961f5..3f5a7bc7a 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h @@ -132,6 +132,8 @@ enum class OperationCode {      LogicalUNotEqual,     /// (uint a, uint b) -> bool      LogicalUGreaterEqual, /// (uint a, uint b) -> bool +    LogicalAddCarry, /// (uint a, uint b) -> bool +      Logical2HLessThan,            /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2      Logical2HEqual,               /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2      Logical2HLessEqual,           /// (MetaHalfArithmetic, f16vec2 a, f16vec2) -> bool2 | 
