From 510072b4f48801df4b0b29dfad19eafae03eba4f Mon Sep 17 00:00:00 2001 From: Vinicius Rangel Date: Tue, 23 Jul 2024 14:03:18 -0300 Subject: [PATCH] shader recompiler: add 64 bits version to get register / GetSrc --- src/shader_recompiler/frontend/opcodes.h | 8 +- .../frontend/translate/translate.cpp | 122 ++++++++++++++++++ .../frontend/translate/translate.h | 5 +- .../frontend/translate/vector_alu.cpp | 61 +-------- src/shader_recompiler/ir/ir_emitter.cpp | 20 +++ 5 files changed, 157 insertions(+), 59 deletions(-) diff --git a/src/shader_recompiler/frontend/opcodes.h b/src/shader_recompiler/frontend/opcodes.h index d38140d8f..cdc1e4746 100644 --- a/src/shader_recompiler/frontend/opcodes.h +++ b/src/shader_recompiler/frontend/opcodes.h @@ -2392,10 +2392,10 @@ enum class OperandField : u32 { ConstFloatPos_4_0, ConstFloatNeg_4_0, VccZ = 251, - ExecZ, - Scc, - LdsDirect, - LiteralConst, + ExecZ = 252, + Scc = 253, + LdsDirect = 254, + LiteralConst = 255, VectorGPR, Undefined = 0xFFFFFFFF, diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index abde32bef..912bd8c73 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -75,6 +75,7 @@ void Translator::EmitPrologue() { } } +template <> IR::U32F32 Translator::GetSrc(const InstOperand& operand, bool force_flt) { // Input modifiers work on float values. force_flt |= operand.input_modifier.abs | operand.input_modifier.neg; @@ -172,6 +173,127 @@ IR::U32F32 Translator::GetSrc(const InstOperand& operand, bool force_flt) { return value; } +template <> +IR::U32 Translator::GetSrc(const InstOperand& operand, bool force_flt) { + return GetSrc(operand, force_flt); +} + +template <> +IR::F32 Translator::GetSrc(const InstOperand& operand, bool) { + return GetSrc(operand, true); +} + +template <> +IR::U64F64 Translator::GetSrc64(const InstOperand& operand, bool force_flt) { + // Input modifiers work on float values. + force_flt |= operand.input_modifier.abs | operand.input_modifier.neg; + + IR::U64F64 value{}; + switch (operand.field) { + case OperandField::ScalarGPR: + if (operand.type == ScalarType::Float64 || force_flt) { + value = ir.GetScalarReg(IR::ScalarReg(operand.code)); + } else if (operand.type == ScalarType::Uint64 || operand.type == ScalarType::Sint64) { + value = ir.GetScalarReg(IR::ScalarReg(operand.code)); + } else { + UNREACHABLE(); + } + break; + case OperandField::VectorGPR: + if (operand.type == ScalarType::Float64 || force_flt) { + value = ir.GetVectorReg(IR::VectorReg(operand.code)); + } else if (operand.type == ScalarType::Uint64 || operand.type == ScalarType::Sint64) { + value = ir.GetVectorReg(IR::VectorReg(operand.code)); + } else { + UNREACHABLE(); + } + break; + case OperandField::ConstZero: + if (force_flt) { + value = ir.Imm64(0.0); + } else { + value = ir.Imm64(u64(0U)); + } + break; + case OperandField::SignedConstIntPos: + ASSERT(!force_flt); + value = ir.Imm64(s64(operand.code) - SignedConstIntPosMin + 1); + break; + case OperandField::SignedConstIntNeg: + ASSERT(!force_flt); + value = ir.Imm64(-s64(operand.code) + SignedConstIntNegMin - 1); + break; + case OperandField::LiteralConst: + if (force_flt) { + UNREACHABLE(); // There is a literal double? + } else { + value = ir.Imm64(u64(operand.code)); + } + break; + case OperandField::ConstFloatPos_1_0: + if (force_flt) { + value = ir.Imm64(1.0); + } else { + value = ir.Imm64(std::bit_cast(double(1.0))); + } + break; + case OperandField::ConstFloatPos_0_5: + value = ir.Imm64(0.5); + break; + case OperandField::ConstFloatPos_2_0: + value = ir.Imm64(2.0); + break; + case OperandField::ConstFloatPos_4_0: + value = ir.Imm64(4.0); + break; + case OperandField::ConstFloatNeg_0_5: + value = ir.Imm64(-0.5); + break; + case OperandField::ConstFloatNeg_1_0: + value = ir.Imm64(-1.0); + break; + case OperandField::ConstFloatNeg_2_0: + value = ir.Imm64(-2.0); + break; + case OperandField::ConstFloatNeg_4_0: + value = ir.Imm64(-4.0); + break; + case OperandField::VccLo: + if (force_flt) { + value = ir.BitCast(IR::U64(ir.UConvert(64, ir.GetVccLo()))); + } else { + value = ir.UConvert(64, ir.GetVccLo()); + } + break; + case OperandField::VccHi: + if (force_flt) { + value = ir.BitCast(IR::U64(ir.UConvert(64, ir.GetVccHi()))); + } else { + value = ir.UConvert(64, ir.GetVccHi()); + } + break; + default: + UNREACHABLE(); + } + + if (operand.input_modifier.abs) { + value = ir.FPAbs(value); + } + if (operand.input_modifier.neg) { + value = ir.FPNeg(value); + } + return value; +} + +template <> +IR::U64 Translator::GetSrc64(const InstOperand& operand, bool force_flt) { + return GetSrc64(operand, force_flt); +} +template <> +IR::F64 Translator::GetSrc64(const InstOperand& operand, bool) { + return GetSrc64(operand, true); +} + void Translator::SetDst(const InstOperand& operand, const IR::U32F32& value) { IR::U32F32 result = value; if (operand.output_modifier.multiplier != 0.f) { diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 287d7943e..5feec8f71 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -188,7 +188,10 @@ public: void EXP(const GcnInst& inst); private: - IR::U32F32 GetSrc(const InstOperand& operand, bool flt_zero = false); + template + [[nodiscard]] T GetSrc(const InstOperand& operand, bool flt_zero = false); + template + [[nodiscard]] T GetSrc64(const InstOperand& operand, bool flt_zero = false); void SetDst(const InstOperand& operand, const IR::U32F32& value); private: diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index 036640364..650b8907c 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -93,31 +93,15 @@ void Translator::V_ADD_I32(const GcnInst& inst) { } void Translator::V_ADDC_U32(const GcnInst& inst) { - IR::U32 src0; - const IR::Value src0_0{GetSrc(inst.src[0])}; - if (src0_0.Type() == IR::Type::F32 || src0_0.Type() == IR::Type::F64) { - src0 = ir.ConvertFToU(32, IR::F32F64(src0_0)); - } else if (src0_0.Type() == IR::Type::U32) { - src0 = IR::U32U64(src0_0); - } else { - UNREACHABLE(); - } - IR::U32 src1; - const IR::Value src1_0{GetSrc(inst.src[1])}; - if (src1_0.Type() == IR::Type::F32 || src1_0.Type() == IR::Type::F64) { - src1 = ir.ConvertFToU(32, IR::F32F64(src1_0)); - } else if (src1_0.Type() == IR::Type::U32) { - src1 = IR::U32U64(src1_0); - } else { - UNREACHABLE(); - } + const auto src0 = GetSrc(inst.src[0]); + const auto src1 = GetSrc(inst.src[1]); IR::U32 scarry; if (inst.src_count == 3) { // VOP3 - scarry = {GetSrc(inst.src[2])}; + scarry = GetSrc(inst.src[2]); } else { // VOP2 - scarry = {ir.GetVccLo()}; + scarry = ir.GetVccLo(); } IR::U32 result = ir.IAdd(ir.IAdd(src0, src1), scarry); @@ -330,41 +314,10 @@ void Translator::V_SUBREV_I32(const GcnInst& inst) { } void Translator::V_MAD_U64_U32(const GcnInst& inst) { - IR::U32 src0; - const IR::Value src0_0{GetSrc(inst.src[0])}; - if (src0_0.Type() == IR::Type::F32 || src0_0.Type() == IR::Type::F64) { - src0 = ir.ConvertFToU(32, IR::F32F64(src0_0)); - } else if (src0_0.Type() == IR::Type::U64) { - src0 = ir.UConvert(32, IR::U64(src0_0)); - } else if (src0_0.Type() == IR::Type::U32) { - src0 = IR::U32(src0_0); - } else { - UNREACHABLE(); - } - IR::U32 src1; - const IR::Value src1_0{GetSrc(inst.src[1])}; - if (src1_0.Type() == IR::Type::F32 || src1_0.Type() == IR::Type::F64) { - src1 = ir.ConvertFToU(32, IR::F32F64(src1_0)); - } else if (src1_0.Type() == IR::Type::U64) { - src1 = ir.UConvert(32, IR::U64(src1_0)); - } else if (src1_0.Type() == IR::Type::U32) { - src1 = IR::U32(src1_0); - } else { - UNREACHABLE(); - } - - IR::U64 src2; - const IR::Value src2_0{GetSrc(inst.src[2])}; - if (src2_0.Type() == IR::Type::F32 || src2_0.Type() == IR::Type::F64) { - src2 = ir.ConvertFToU(64, IR::F32F64(src2_0)); - } else if (src2_0.Type() == IR::Type::U64) { - src2 = IR::U64(src2_0); - } else if (src2_0.Type() == IR::Type::U32) { - src2 = ir.UConvert(64, IR::U32(src2_0)); - } else { - UNREACHABLE(); - } + const auto src0 = GetSrc(inst.src[0]); + const auto src1 = GetSrc(inst.src[1]); + const auto src2 = GetSrc64(inst.src[2]); IR::U64 result; result = ir.IMul(src0, src1); diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 6b0be5631..6df407e88 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -153,6 +153,16 @@ F32 IREmitter::GetScalarReg(IR::ScalarReg reg) { return BitCast(GetScalarReg(reg)); } +template <> +U64 IREmitter::GetScalarReg(IR::ScalarReg reg) { + return Inst(Opcode::GetScalarRegister, reg); +} + +template <> +F64 IREmitter::GetScalarReg(IR::ScalarReg reg) { + return BitCast(GetScalarReg(reg)); +} + template <> U32 IREmitter::GetVectorReg(IR::VectorReg reg) { return Inst(Opcode::GetVectorRegister, reg); @@ -163,6 +173,16 @@ F32 IREmitter::GetVectorReg(IR::VectorReg reg) { return BitCast(GetVectorReg(reg)); } +template <> +U64 IREmitter::GetVectorReg(IR::VectorReg reg) { + return Inst(Opcode::GetVectorRegister, reg); +} + +template <> +F64 IREmitter::GetVectorReg(IR::VectorReg reg) { + return BitCast(GetVectorReg(reg)); +} + void IREmitter::SetScalarReg(IR::ScalarReg reg, const U32F32& value) { const U32 value_typed = value.Type() == Type::F32 ? BitCast(F32{value}) : U32{value}; Inst(Opcode::SetScalarRegister, reg, value_typed);