mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-02 15:32:52 +00:00
Better conditions
This commit is contained in:
parent
4224a95583
commit
2e6f3aae32
@ -12,14 +12,27 @@ namespace Shader::Backend::X64 {
|
|||||||
using namespace Xbyak;
|
using namespace Xbyak;
|
||||||
using namespace Xbyak::util;
|
using namespace Xbyak::util;
|
||||||
|
|
||||||
static void TestCondition(EmitContext& ctx, const IR::Inst* ref) {
|
static void EmitCondition(EmitContext& ctx, const IR::Inst* ref, Label& label, bool invert) {
|
||||||
IR::Value cond = ref->Arg(0);
|
IR::Value cond = ref->Arg(0);
|
||||||
Operand& op = ctx.Def(cond)[0];
|
if (cond.IsImmediate()) {
|
||||||
Reg8 tmp = op.isREG() ? op.getReg().cvt8() : ctx.TempGPReg(false).cvt8();
|
// If imediate, we evaluate at compile time
|
||||||
if (!op.isREG()) {
|
if (cond.U1() != invert) {
|
||||||
ctx.Code().mov(tmp, op);
|
ctx.Code().jmp(label);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Operand& op = ctx.Def(cond)[0];
|
||||||
|
if (op.isREG()) {
|
||||||
|
Reg8 reg = op.getReg().cvt8();
|
||||||
|
ctx.Code().test(reg, reg);
|
||||||
|
} else {
|
||||||
|
ctx.Code().test(op, 0xff);
|
||||||
|
}
|
||||||
|
if (invert) {
|
||||||
|
ctx.Code().jz(label);
|
||||||
|
} else {
|
||||||
|
ctx.Code().jnz(label);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ctx.Code().test(tmp, tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ArgType>
|
template <typename ArgType>
|
||||||
@ -120,22 +133,20 @@ static void Traverse(EmitContext& ctx, const IR::Program& program) {
|
|||||||
case IR::AbstractSyntaxNode::Type::If: {
|
case IR::AbstractSyntaxNode::Type::If: {
|
||||||
IR::Inst* ref = node.data.if_node.cond.InstRecursive();
|
IR::Inst* ref = node.data.if_node.cond.InstRecursive();
|
||||||
Label& merge = ctx.BlockLabel(node.data.if_node.merge);
|
Label& merge = ctx.BlockLabel(node.data.if_node.merge);
|
||||||
TestCondition(ctx, ref);
|
EmitCondition(ctx, ref, merge, true);
|
||||||
c.jz(merge);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::AbstractSyntaxNode::Type::Repeat: {
|
case IR::AbstractSyntaxNode::Type::Repeat: {
|
||||||
IR::Inst* ref = node.data.repeat.cond.InstRecursive();
|
IR::Inst* ref = node.data.repeat.cond.InstRecursive();
|
||||||
Label& loop_header = ctx.BlockLabel(node.data.repeat.loop_header);
|
Label& loop_header = ctx.BlockLabel(node.data.repeat.loop_header);
|
||||||
TestCondition(ctx, ref);
|
EmitCondition(ctx, ref, loop_header, false);
|
||||||
c.jnz(loop_header);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::AbstractSyntaxNode::Type::Break: {
|
case IR::AbstractSyntaxNode::Type::Break: {
|
||||||
IR::Inst* ref = node.data.break_node.cond.InstRecursive();
|
IR::Inst* ref = node.data.break_node.cond.InstRecursive();
|
||||||
Label& merge = ctx.BlockLabel(node.data.break_node.merge);
|
Label& merge = ctx.BlockLabel(node.data.break_node.merge);
|
||||||
TestCondition(ctx, ref);
|
EmitCondition(ctx, ref, merge, true);
|
||||||
c.jz(merge);
|
+c.jz(merge);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR::AbstractSyntaxNode::Type::Return: {
|
case IR::AbstractSyntaxNode::Type::Return: {
|
||||||
|
Loading…
Reference in New Issue
Block a user