mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-21 03:54:45 +00:00
shader recompiler: add 64 bits version to get register / GetSrc
This commit is contained in:
parent
e23749bf0e
commit
510072b4f4
5 changed files with 157 additions and 59 deletions
|
@ -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,
|
||||
|
|
|
@ -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<IR::U32F32>(operand, force_flt);
|
||||
}
|
||||
|
||||
template <>
|
||||
IR::F32 Translator::GetSrc(const InstOperand& operand, bool) {
|
||||
return GetSrc<IR::U32F32>(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::F64>(IR::ScalarReg(operand.code));
|
||||
} else if (operand.type == ScalarType::Uint64 || operand.type == ScalarType::Sint64) {
|
||||
value = ir.GetScalarReg<IR::U64>(IR::ScalarReg(operand.code));
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
case OperandField::VectorGPR:
|
||||
if (operand.type == ScalarType::Float64 || force_flt) {
|
||||
value = ir.GetVectorReg<IR::F64>(IR::VectorReg(operand.code));
|
||||
} else if (operand.type == ScalarType::Uint64 || operand.type == ScalarType::Sint64) {
|
||||
value = ir.GetVectorReg<IR::U64>(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<u64>(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::F64>(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::F64>(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<IR::U64F64>(operand, force_flt);
|
||||
}
|
||||
template <>
|
||||
IR::F64 Translator::GetSrc64(const InstOperand& operand, bool) {
|
||||
return GetSrc64<IR::U64F64>(operand, true);
|
||||
}
|
||||
|
||||
void Translator::SetDst(const InstOperand& operand, const IR::U32F32& value) {
|
||||
IR::U32F32 result = value;
|
||||
if (operand.output_modifier.multiplier != 0.f) {
|
||||
|
|
|
@ -188,7 +188,10 @@ public:
|
|||
void EXP(const GcnInst& inst);
|
||||
|
||||
private:
|
||||
IR::U32F32 GetSrc(const InstOperand& operand, bool flt_zero = false);
|
||||
template <typename T = IR::U32F32>
|
||||
[[nodiscard]] T GetSrc(const InstOperand& operand, bool flt_zero = false);
|
||||
template <typename T = IR::U64F64>
|
||||
[[nodiscard]] T GetSrc64(const InstOperand& operand, bool flt_zero = false);
|
||||
void SetDst(const InstOperand& operand, const IR::U32F32& value);
|
||||
|
||||
private:
|
||||
|
|
|
@ -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<IR::U32>(inst.src[0]);
|
||||
const auto src1 = GetSrc<IR::U32>(inst.src[1]);
|
||||
|
||||
IR::U32 scarry;
|
||||
if (inst.src_count == 3) { // VOP3
|
||||
scarry = {GetSrc(inst.src[2])};
|
||||
scarry = GetSrc<IR::U32>(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<IR::U32>(inst.src[0]);
|
||||
const auto src1 = GetSrc<IR::U32>(inst.src[1]);
|
||||
const auto src2 = GetSrc64<IR::U64>(inst.src[2]);
|
||||
|
||||
IR::U64 result;
|
||||
result = ir.IMul(src0, src1);
|
||||
|
|
|
@ -153,6 +153,16 @@ F32 IREmitter::GetScalarReg(IR::ScalarReg reg) {
|
|||
return BitCast<F32>(GetScalarReg<U32>(reg));
|
||||
}
|
||||
|
||||
template <>
|
||||
U64 IREmitter::GetScalarReg(IR::ScalarReg reg) {
|
||||
return Inst<U64>(Opcode::GetScalarRegister, reg);
|
||||
}
|
||||
|
||||
template <>
|
||||
F64 IREmitter::GetScalarReg(IR::ScalarReg reg) {
|
||||
return BitCast<F64>(GetScalarReg<U64>(reg));
|
||||
}
|
||||
|
||||
template <>
|
||||
U32 IREmitter::GetVectorReg(IR::VectorReg reg) {
|
||||
return Inst<U32>(Opcode::GetVectorRegister, reg);
|
||||
|
@ -163,6 +173,16 @@ F32 IREmitter::GetVectorReg(IR::VectorReg reg) {
|
|||
return BitCast<F32>(GetVectorReg<U32>(reg));
|
||||
}
|
||||
|
||||
template <>
|
||||
U64 IREmitter::GetVectorReg(IR::VectorReg reg) {
|
||||
return Inst<U64>(Opcode::GetVectorRegister, reg);
|
||||
}
|
||||
|
||||
template <>
|
||||
F64 IREmitter::GetVectorReg(IR::VectorReg reg) {
|
||||
return BitCast<F64>(GetVectorReg<U64>(reg));
|
||||
}
|
||||
|
||||
void IREmitter::SetScalarReg(IR::ScalarReg reg, const U32F32& value) {
|
||||
const U32 value_typed = value.Type() == Type::F32 ? BitCast<U32>(F32{value}) : U32{value};
|
||||
Inst(Opcode::SetScalarRegister, reg, value_typed);
|
||||
|
|
Loading…
Add table
Reference in a new issue