diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index c090d8ce..9e0d78c4 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -46,40 +46,6 @@ void Translator::S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst) { ir.SetScc(result); } -void Translator::S_ANDN2_B64(const GcnInst& inst) { - // TODO: What if this is used for something other than EXEC masking? - const auto get_src = [&](const InstOperand& operand) { - switch (operand.field) { - case OperandField::VccLo: - return ir.GetVcc(); - case OperandField::ExecLo: - return ir.GetExec(); - case OperandField::ScalarGPR: - return ir.GetThreadBitScalarReg(IR::ScalarReg(operand.code)); - default: - UNREACHABLE(); - } - }; - - const IR::U1 src0{get_src(inst.src[0])}; - const IR::U1 src1{get_src(inst.src[1])}; - const IR::U1 result{ir.LogicalAnd(src0, ir.LogicalNot(src1))}; - ir.SetScc(result); - switch (inst.dst[0].field) { - case OperandField::VccLo: - ir.SetVcc(result); - break; - case OperandField::ExecLo: - ir.SetExec(result); - break; - case OperandField::ScalarGPR: - ir.SetThreadBitScalarReg(IR::ScalarReg(inst.dst[0].code), result); - break; - default: - UNREACHABLE(); - } -} - void Translator::S_AND_SAVEEXEC_B64(const GcnInst& inst) { // 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 @@ -138,7 +104,7 @@ void Translator::S_MOV_B64(const GcnInst& inst) { } } -void Translator::S_OR_B64(bool negate, const GcnInst& inst) { +void Translator::S_OR_B64(NegateMode negate, const GcnInst& inst) { const auto get_src = [&](const InstOperand& operand) { switch (operand.field) { case OperandField::VccLo: @@ -151,9 +117,12 @@ void Translator::S_OR_B64(bool negate, const GcnInst& inst) { }; const IR::U1 src0{get_src(inst.src[0])}; - const IR::U1 src1{get_src(inst.src[1])}; + IR::U1 src1{get_src(inst.src[1])}; + if (negate == NegateMode::Src1) { + src1 = ir.LogicalNot(src1); + } IR::U1 result = ir.LogicalOr(src0, src1); - if (negate) { + if (negate == NegateMode::Result) { result = ir.LogicalNot(result); } ir.SetScc(result); @@ -169,7 +138,7 @@ void Translator::S_OR_B64(bool negate, const GcnInst& inst) { } } -void Translator::S_AND_B64(bool negate, const GcnInst& inst) { +void Translator::S_AND_B64(NegateMode negate, const GcnInst& inst) { const auto get_src = [&](const InstOperand& operand) { switch (operand.field) { case OperandField::VccLo: @@ -183,9 +152,12 @@ void Translator::S_AND_B64(bool negate, const GcnInst& inst) { } }; const IR::U1 src0{get_src(inst.src[0])}; - const IR::U1 src1{get_src(inst.src[1])}; + IR::U1 src1{get_src(inst.src[1])}; + if (negate == NegateMode::Src1) { + src1 = ir.LogicalNot(src1); + } IR::U1 result = ir.LogicalAnd(src0, src1); - if (negate) { + if (negate == NegateMode::Result) { result = ir.LogicalNot(result); } ir.SetScc(result); diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index 6867591a..0b61be9b 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -469,7 +469,10 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) translator.V_RSQ_F32(inst); break; case Opcode::S_ANDN2_B64: - translator.S_ANDN2_B64(inst); + translator.S_AND_B64(NegateMode::Src1, inst); + break; + case Opcode::S_ORN2_B64: + translator.S_OR_B64(NegateMode::Src1, inst); break; case Opcode::V_SIN_F32: translator.V_SIN_F32(inst); @@ -608,19 +611,19 @@ void Translate(IR::Block* block, std::span inst_list, Info& info) translator.V_CMP_U32(ConditionOp::TRU, false, true, inst); break; case Opcode::S_OR_B64: - translator.S_OR_B64(false, inst); + translator.S_OR_B64(NegateMode::None, inst); break; case Opcode::S_NOR_B64: - translator.S_OR_B64(true, inst); + translator.S_OR_B64(NegateMode::Result, inst); break; case Opcode::S_AND_B64: - translator.S_AND_B64(false, inst); + translator.S_AND_B64(NegateMode::None, inst); break; case Opcode::S_NOT_B64: translator.S_NOT_B64(inst); break; case Opcode::S_NAND_B64: - translator.S_AND_B64(true, inst); + translator.S_AND_B64(NegateMode::Result, inst); break; case Opcode::V_LSHRREV_B32: translator.V_LSHRREV_B32(inst); diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index ace9042e..4f10c49a 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -26,6 +26,12 @@ enum class ConditionOp : u32 { TRU, }; +enum class NegateMode : u32 { + None, + Src1, + Result, +}; + class Translator { public: explicit Translator(IR::Block* block_, Info& info); @@ -38,11 +44,10 @@ public: void S_MOV(const GcnInst& inst); void S_MUL_I32(const GcnInst& inst); void S_CMP(ConditionOp cond, bool is_signed, const GcnInst& inst); - void S_ANDN2_B64(const GcnInst& inst); void S_AND_SAVEEXEC_B64(const GcnInst& inst); void S_MOV_B64(const GcnInst& inst); - void S_OR_B64(bool negate, const GcnInst& inst); - void S_AND_B64(bool negate, const GcnInst& inst); + void S_OR_B64(NegateMode negate, const GcnInst& inst); + void S_AND_B64(NegateMode negate, const GcnInst& inst); void S_ADD_I32(const GcnInst& inst); void S_AND_B32(const GcnInst& inst); void S_OR_B32(const GcnInst& inst);