shader/arithmetic_integer: Implement CC for IADD
This commit is contained in:
		| @@ -1870,6 +1870,14 @@ private: | ||||
|         return GenerateBinaryInfix(operation, ">=", Type::Bool, type, type); | ||||
|     } | ||||
|  | ||||
|     Expression LogicalAddCarry(Operation operation) { | ||||
|         const std::string carry = code.GenerateTemporary(); | ||||
|         code.AddLine("uint {};", carry); | ||||
|         code.AddLine("uaddCarry({}, {}, {});", VisitOperand(operation, 0).AsUint(), | ||||
|                      VisitOperand(operation, 1).AsUint(), carry); | ||||
|         return {fmt::format("({} != 0)", carry), Type::Bool}; | ||||
|     } | ||||
|  | ||||
|     Expression LogicalFIsNan(Operation operation) { | ||||
|         return GenerateUnary(operation, "isnan", Type::Bool, Type::Float); | ||||
|     } | ||||
| @@ -2441,6 +2449,8 @@ private: | ||||
|         &GLSLDecompiler::LogicalNotEqual<Type::Uint>, | ||||
|         &GLSLDecompiler::LogicalGreaterEqual<Type::Uint>, | ||||
|  | ||||
|         &GLSLDecompiler::LogicalAddCarry, | ||||
|  | ||||
|         &GLSLDecompiler::Logical2HLessThan<false>, | ||||
|         &GLSLDecompiler::Logical2HEqual<false>, | ||||
|         &GLSLDecompiler::Logical2HLessEqual<false>, | ||||
|   | ||||
| @@ -1584,6 +1584,15 @@ private: | ||||
|         return {OpCompositeConstruct(t_half, low, high), Type::HalfFloat}; | ||||
|     } | ||||
|  | ||||
|     Expression LogicalAddCarry(Operation operation) { | ||||
|         const Id op_a = AsUint(Visit(operation[0])); | ||||
|         const Id op_b = AsUint(Visit(operation[1])); | ||||
|  | ||||
|         const Id result = OpIAddCarry(TypeStruct({t_uint, t_uint}), op_a, op_b); | ||||
|         const Id carry = OpCompositeExtract(t_uint, result, 1); | ||||
|         return {OpINotEqual(t_bool, carry, Constant(t_uint, 0)), Type::Bool}; | ||||
|     } | ||||
|  | ||||
|     Expression LogicalAssign(Operation operation) { | ||||
|         const Node& dest = operation[0]; | ||||
|         const Node& src = operation[1]; | ||||
| @@ -2518,6 +2527,8 @@ private: | ||||
|         &SPIRVDecompiler::Binary<&Module::OpINotEqual, Type::Bool, Type::Uint>, | ||||
|         &SPIRVDecompiler::Binary<&Module::OpUGreaterThanEqual, Type::Bool, Type::Uint>, | ||||
|  | ||||
|         &SPIRVDecompiler::LogicalAddCarry, | ||||
|  | ||||
|         &SPIRVDecompiler::Binary<&Module::OpFOrdLessThan, Type::Bool2, Type::HalfFloat>, | ||||
|         &SPIRVDecompiler::Binary<&Module::OpFOrdEqual, Type::Bool2, Type::HalfFloat>, | ||||
|         &SPIRVDecompiler::Binary<&Module::OpFOrdLessThanEqual, Type::Bool2, Type::HalfFloat>, | ||||
|   | ||||
| @@ -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: | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
					ReinUsesLisp