shader_recompiler: frontend: `SOPC` and `SOPK` handling separated; more cmp opcodes (#634)
This commit is contained in:
parent
d2e4a200fb
commit
3fbb68048e
|
@ -6,98 +6,150 @@
|
||||||
namespace Shader::Gcn {
|
namespace Shader::Gcn {
|
||||||
|
|
||||||
void Translator::EmitScalarAlu(const GcnInst& inst) {
|
void Translator::EmitScalarAlu(const GcnInst& inst) {
|
||||||
|
switch (inst.encoding) {
|
||||||
|
case InstEncoding::SOPC: {
|
||||||
|
EmitSOPC(inst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case InstEncoding::SOPK: {
|
||||||
|
EmitSOPK(inst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
switch (inst.opcode) {
|
||||||
|
case Opcode::S_MOV_B32:
|
||||||
|
return S_MOV(inst);
|
||||||
|
case Opcode::S_MUL_I32:
|
||||||
|
return S_MUL_I32(inst);
|
||||||
|
case Opcode::S_AND_SAVEEXEC_B64:
|
||||||
|
return S_AND_SAVEEXEC_B64(inst);
|
||||||
|
case Opcode::S_MOV_B64:
|
||||||
|
return S_MOV_B64(inst);
|
||||||
|
case Opcode::S_OR_B64:
|
||||||
|
return S_OR_B64(NegateMode::None, false, inst);
|
||||||
|
case Opcode::S_NOR_B64:
|
||||||
|
return S_OR_B64(NegateMode::Result, false, inst);
|
||||||
|
case Opcode::S_XOR_B64:
|
||||||
|
return S_OR_B64(NegateMode::None, true, inst);
|
||||||
|
case Opcode::S_ORN2_B64:
|
||||||
|
return S_OR_B64(NegateMode::Src1, false, inst);
|
||||||
|
case Opcode::S_AND_B64:
|
||||||
|
return S_AND_B64(NegateMode::None, inst);
|
||||||
|
case Opcode::S_NAND_B64:
|
||||||
|
return S_AND_B64(NegateMode::Result, inst);
|
||||||
|
case Opcode::S_ANDN2_B64:
|
||||||
|
return S_AND_B64(NegateMode::Src1, inst);
|
||||||
|
case Opcode::S_NOT_B64:
|
||||||
|
return S_NOT_B64(inst);
|
||||||
|
case Opcode::S_ADD_I32:
|
||||||
|
return S_ADD_I32(inst);
|
||||||
|
case Opcode::S_AND_B32:
|
||||||
|
return S_AND_B32(inst);
|
||||||
|
case Opcode::S_ASHR_I32:
|
||||||
|
return S_ASHR_I32(inst);
|
||||||
|
case Opcode::S_OR_B32:
|
||||||
|
return S_OR_B32(inst);
|
||||||
|
case Opcode::S_LSHL_B32:
|
||||||
|
return S_LSHL_B32(inst);
|
||||||
|
case Opcode::S_LSHR_B32:
|
||||||
|
return S_LSHR_B32(inst);
|
||||||
|
case Opcode::S_CSELECT_B32:
|
||||||
|
return S_CSELECT_B32(inst);
|
||||||
|
case Opcode::S_CSELECT_B64:
|
||||||
|
return S_CSELECT_B64(inst);
|
||||||
|
case Opcode::S_BFE_U32:
|
||||||
|
return S_BFE_U32(inst);
|
||||||
|
case Opcode::S_BFM_B32:
|
||||||
|
return S_BFM_B32(inst);
|
||||||
|
case Opcode::S_BREV_B32:
|
||||||
|
return S_BREV_B32(inst);
|
||||||
|
case Opcode::S_ADD_U32:
|
||||||
|
return S_ADD_U32(inst);
|
||||||
|
case Opcode::S_ADDC_U32:
|
||||||
|
return S_ADDC_U32(inst);
|
||||||
|
case Opcode::S_SUB_U32:
|
||||||
|
case Opcode::S_SUB_I32:
|
||||||
|
return S_SUB_U32(inst);
|
||||||
|
case Opcode::S_MIN_U32:
|
||||||
|
return S_MIN_U32(inst);
|
||||||
|
case Opcode::S_MAX_U32:
|
||||||
|
return S_MAX_U32(inst);
|
||||||
|
case Opcode::S_WQM_B64:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LogMissingOpcode(inst);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Translator::EmitSOPC(const GcnInst& inst) {
|
||||||
switch (inst.opcode) {
|
switch (inst.opcode) {
|
||||||
case Opcode::S_MOVK_I32:
|
case Opcode::S_CMP_EQ_I32:
|
||||||
return S_MOVK(inst);
|
return S_CMP(ConditionOp::EQ, true, inst);
|
||||||
case Opcode::S_MOV_B32:
|
|
||||||
return S_MOV(inst);
|
|
||||||
case Opcode::S_MUL_I32:
|
|
||||||
return S_MUL_I32(inst);
|
|
||||||
case Opcode::S_AND_SAVEEXEC_B64:
|
|
||||||
return S_AND_SAVEEXEC_B64(inst);
|
|
||||||
case Opcode::S_MOV_B64:
|
|
||||||
return S_MOV_B64(inst);
|
|
||||||
case Opcode::S_CMP_LT_U32:
|
|
||||||
return S_CMP(ConditionOp::LT, false, inst);
|
|
||||||
case Opcode::S_CMP_LE_U32:
|
|
||||||
return S_CMP(ConditionOp::LE, false, inst);
|
|
||||||
case Opcode::S_CMP_LG_U32:
|
|
||||||
return S_CMP(ConditionOp::LG, false, inst);
|
|
||||||
case Opcode::S_CMP_LT_I32:
|
|
||||||
return S_CMP(ConditionOp::LT, true, inst);
|
|
||||||
case Opcode::S_CMP_LG_I32:
|
case Opcode::S_CMP_LG_I32:
|
||||||
return S_CMP(ConditionOp::LG, true, inst);
|
return S_CMP(ConditionOp::LG, true, inst);
|
||||||
case Opcode::S_CMP_GT_I32:
|
case Opcode::S_CMP_GT_I32:
|
||||||
return S_CMP(ConditionOp::GT, true, inst);
|
return S_CMP(ConditionOp::GT, true, inst);
|
||||||
case Opcode::S_CMP_LE_I32:
|
|
||||||
return S_CMP(ConditionOp::LE, true, inst);
|
|
||||||
case Opcode::S_CMP_GE_I32:
|
case Opcode::S_CMP_GE_I32:
|
||||||
return S_CMP(ConditionOp::GE, true, inst);
|
return S_CMP(ConditionOp::GE, true, inst);
|
||||||
case Opcode::S_CMP_EQ_I32:
|
case Opcode::S_CMP_LT_I32:
|
||||||
return S_CMP(ConditionOp::EQ, true, inst);
|
return S_CMP(ConditionOp::LT, true, inst);
|
||||||
|
case Opcode::S_CMP_LE_I32:
|
||||||
|
return S_CMP(ConditionOp::LE, true, inst);
|
||||||
|
|
||||||
case Opcode::S_CMP_EQ_U32:
|
case Opcode::S_CMP_EQ_U32:
|
||||||
return S_CMP(ConditionOp::EQ, false, inst);
|
return S_CMP(ConditionOp::EQ, false, inst);
|
||||||
case Opcode::S_CMP_GE_U32:
|
case Opcode::S_CMP_LG_U32:
|
||||||
return S_CMP(ConditionOp::GE, false, inst);
|
return S_CMP(ConditionOp::LG, false, inst);
|
||||||
case Opcode::S_CMP_GT_U32:
|
case Opcode::S_CMP_GT_U32:
|
||||||
return S_CMP(ConditionOp::GT, false, inst);
|
return S_CMP(ConditionOp::GT, false, inst);
|
||||||
case Opcode::S_OR_B64:
|
case Opcode::S_CMP_GE_U32:
|
||||||
return S_OR_B64(NegateMode::None, false, inst);
|
return S_CMP(ConditionOp::GE, false, inst);
|
||||||
case Opcode::S_NOR_B64:
|
case Opcode::S_CMP_LT_U32:
|
||||||
return S_OR_B64(NegateMode::Result, false, inst);
|
return S_CMP(ConditionOp::LT, false, inst);
|
||||||
case Opcode::S_XOR_B64:
|
case Opcode::S_CMP_LE_U32:
|
||||||
return S_OR_B64(NegateMode::None, true, inst);
|
return S_CMP(ConditionOp::LE, false, inst);
|
||||||
case Opcode::S_ORN2_B64:
|
default:
|
||||||
return S_OR_B64(NegateMode::Src1, false, inst);
|
LogMissingOpcode(inst);
|
||||||
case Opcode::S_AND_B64:
|
}
|
||||||
return S_AND_B64(NegateMode::None, inst);
|
}
|
||||||
case Opcode::S_NAND_B64:
|
|
||||||
return S_AND_B64(NegateMode::Result, inst);
|
void Translator::EmitSOPK(const GcnInst& inst) {
|
||||||
case Opcode::S_ANDN2_B64:
|
switch (inst.opcode) {
|
||||||
return S_AND_B64(NegateMode::Src1, inst);
|
case Opcode::S_MOVK_I32:
|
||||||
case Opcode::S_NOT_B64:
|
return S_MOVK(inst);
|
||||||
return S_NOT_B64(inst);
|
|
||||||
case Opcode::S_ADD_I32:
|
case Opcode::S_CMPK_EQ_I32:
|
||||||
return S_ADD_I32(inst);
|
return S_CMPK(ConditionOp::EQ, true, inst);
|
||||||
case Opcode::S_AND_B32:
|
case Opcode::S_CMPK_LG_I32:
|
||||||
return S_AND_B32(inst);
|
return S_CMPK(ConditionOp::LG, true, inst);
|
||||||
case Opcode::S_ASHR_I32:
|
case Opcode::S_CMPK_GT_I32:
|
||||||
return S_ASHR_I32(inst);
|
return S_CMPK(ConditionOp::GT, true, inst);
|
||||||
case Opcode::S_OR_B32:
|
case Opcode::S_CMPK_GE_I32:
|
||||||
return S_OR_B32(inst);
|
return S_CMPK(ConditionOp::GE, true, inst);
|
||||||
case Opcode::S_LSHL_B32:
|
case Opcode::S_CMPK_LT_I32:
|
||||||
return S_LSHL_B32(inst);
|
return S_CMPK(ConditionOp::LT, true, inst);
|
||||||
case Opcode::S_LSHR_B32:
|
case Opcode::S_CMPK_LE_I32:
|
||||||
return S_LSHR_B32(inst);
|
return S_CMPK(ConditionOp::LE, true, inst);
|
||||||
case Opcode::S_CSELECT_B32:
|
|
||||||
return S_CSELECT_B32(inst);
|
case Opcode::S_CMPK_EQ_U32:
|
||||||
case Opcode::S_CSELECT_B64:
|
return S_CMPK(ConditionOp::EQ, false, inst);
|
||||||
return S_CSELECT_B64(inst);
|
case Opcode::S_CMPK_LG_U32:
|
||||||
case Opcode::S_BFE_U32:
|
return S_CMPK(ConditionOp::LG, false, inst);
|
||||||
return S_BFE_U32(inst);
|
case Opcode::S_CMPK_GT_U32:
|
||||||
case Opcode::S_BFM_B32:
|
return S_CMPK(ConditionOp::GT, false, inst);
|
||||||
return S_BFM_B32(inst);
|
case Opcode::S_CMPK_GE_U32:
|
||||||
case Opcode::S_BREV_B32:
|
return S_CMPK(ConditionOp::GE, false, inst);
|
||||||
return S_BREV_B32(inst);
|
case Opcode::S_CMPK_LT_U32:
|
||||||
case Opcode::S_ADD_U32:
|
return S_CMPK(ConditionOp::LT, false, inst);
|
||||||
return S_ADD_U32(inst);
|
case Opcode::S_CMPK_LE_U32:
|
||||||
case Opcode::S_ADDC_U32:
|
return S_CMPK(ConditionOp::LE, false, inst);
|
||||||
return S_ADDC_U32(inst);
|
|
||||||
case Opcode::S_ADDK_I32:
|
case Opcode::S_ADDK_I32:
|
||||||
return S_ADDK_I32(inst);
|
return S_ADDK_I32(inst);
|
||||||
case Opcode::S_MULK_I32:
|
case Opcode::S_MULK_I32:
|
||||||
return S_MULK_I32(inst);
|
return S_MULK_I32(inst);
|
||||||
case Opcode::S_SUB_U32:
|
|
||||||
case Opcode::S_SUB_I32:
|
|
||||||
return S_SUB_U32(inst);
|
|
||||||
case Opcode::S_MIN_U32:
|
|
||||||
return S_MIN_U32(inst);
|
|
||||||
case Opcode::S_MAX_U32:
|
|
||||||
return S_MAX_U32(inst);
|
|
||||||
case Opcode::S_WQM_B64:
|
|
||||||
break;
|
|
||||||
case Opcode::S_CMPK_EQ_U32:
|
|
||||||
return S_CMPK_EQ_U32(inst);
|
|
||||||
default:
|
default:
|
||||||
LogMissingOpcode(inst);
|
LogMissingOpcode(inst);
|
||||||
}
|
}
|
||||||
|
@ -154,6 +206,31 @@ void Translator::S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst) {
|
||||||
ir.SetScc(result);
|
ir.SetScc(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Translator::S_CMPK(ConditionOp cond, bool is_signed, const GcnInst& inst) {
|
||||||
|
const s32 simm16 = inst.control.sopk.simm;
|
||||||
|
const IR::U32 lhs = GetSrc(inst.dst[0]);
|
||||||
|
const IR::U32 rhs = ir.Imm32(simm16);
|
||||||
|
const IR::U1 result = [&] {
|
||||||
|
switch (cond) {
|
||||||
|
case ConditionOp::EQ:
|
||||||
|
return ir.IEqual(lhs, rhs);
|
||||||
|
case ConditionOp::LG:
|
||||||
|
return ir.INotEqual(lhs, rhs);
|
||||||
|
case ConditionOp::GT:
|
||||||
|
return ir.IGreaterThan(lhs, rhs, is_signed);
|
||||||
|
case ConditionOp::GE:
|
||||||
|
return ir.IGreaterThanEqual(lhs, rhs, is_signed);
|
||||||
|
case ConditionOp::LT:
|
||||||
|
return ir.ILessThan(lhs, rhs, is_signed);
|
||||||
|
case ConditionOp::LE:
|
||||||
|
return ir.ILessThanEqual(lhs, rhs, is_signed);
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
ir.SetScc(result);
|
||||||
|
}
|
||||||
|
|
||||||
void Translator::S_AND_SAVEEXEC_B64(const GcnInst& inst) {
|
void Translator::S_AND_SAVEEXEC_B64(const GcnInst& inst) {
|
||||||
// This instruction normally operates on 64-bit data (EXEC, VCC, SGPRs)
|
// This instruction normally operates on 64-bit data (EXEC, VCC, SGPRs)
|
||||||
// However here we flatten it to 1-bit EXEC and 1-bit VCC. For the destination
|
// However here we flatten it to 1-bit EXEC and 1-bit VCC. For the destination
|
||||||
|
@ -470,11 +547,4 @@ void Translator::S_MIN_U32(const GcnInst& inst) {
|
||||||
ir.SetScc(ir.IEqual(result, src0));
|
ir.SetScc(ir.IEqual(result, src0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::S_CMPK_EQ_U32(const GcnInst& inst) {
|
|
||||||
const s32 simm16 = inst.control.sopk.simm;
|
|
||||||
const IR::U32 src0{GetSrc(inst.dst[0])};
|
|
||||||
const IR::U32 src1{ir.Imm32(simm16)};
|
|
||||||
ir.SetScc(ir.IEqual(src0, src1));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Shader::Gcn
|
} // namespace Shader::Gcn
|
||||||
|
|
|
@ -69,6 +69,10 @@ public:
|
||||||
void EmitScalarAlu(const GcnInst& inst);
|
void EmitScalarAlu(const GcnInst& inst);
|
||||||
void EmitVectorAlu(const GcnInst& inst);
|
void EmitVectorAlu(const GcnInst& inst);
|
||||||
|
|
||||||
|
// Instruction encodings
|
||||||
|
void EmitSOPC(const GcnInst& inst);
|
||||||
|
void EmitSOPK(const GcnInst& inst);
|
||||||
|
|
||||||
// Scalar ALU
|
// Scalar ALU
|
||||||
void S_MOVK(const GcnInst& inst);
|
void S_MOVK(const GcnInst& inst);
|
||||||
void S_MOV(const GcnInst& inst);
|
void S_MOV(const GcnInst& inst);
|
||||||
|
@ -98,7 +102,7 @@ public:
|
||||||
void S_ADDK_I32(const GcnInst& inst);
|
void S_ADDK_I32(const GcnInst& inst);
|
||||||
void S_MAX_U32(const GcnInst& inst);
|
void S_MAX_U32(const GcnInst& inst);
|
||||||
void S_MIN_U32(const GcnInst& inst);
|
void S_MIN_U32(const GcnInst& inst);
|
||||||
void S_CMPK_EQ_U32(const GcnInst& inst);
|
void S_CMPK(ConditionOp cond, bool is_signed, const GcnInst& inst);
|
||||||
|
|
||||||
// Scalar Memory
|
// Scalar Memory
|
||||||
void S_LOAD_DWORD(int num_dwords, const GcnInst& inst);
|
void S_LOAD_DWORD(int num_dwords, const GcnInst& inst);
|
||||||
|
|
Loading…
Reference in New Issue