From b97147e1872b9591d5e694c2df71961a24d14090 Mon Sep 17 00:00:00 2001 From: Merry Date: Wed, 20 Jul 2022 14:33:28 +0100 Subject: [PATCH] a32_get_set_elimination_pass: Reduce NZC to 00C --- src/dynarmic/backend/x64/a32_emit_x64.cpp | 32 +++++++++++++------ .../ir/opt/a32_get_set_elimination_pass.cpp | 6 +++- src/dynarmic/ir/value.cpp | 6 ++++ src/dynarmic/ir/value.h | 2 ++ 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/dynarmic/backend/x64/a32_emit_x64.cpp b/src/dynarmic/backend/x64/a32_emit_x64.cpp index f579865e..5e68478f 100644 --- a/src/dynarmic/backend/x64/a32_emit_x64.cpp +++ b/src/dynarmic/backend/x64/a32_emit_x64.cpp @@ -555,20 +555,32 @@ void A32EmitX64::EmitA32SetCpsrNZ(A32EmitContext& ctx, IR::Inst* inst) { void A32EmitX64::EmitA32SetCpsrNZC(A32EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); - ctx.reg_alloc.Use(args[0], HostLoc::RAX); + if (args[0].IsImmediate()) { + if (args[1].IsImmediate()) { + const bool c = args[1].GetImmediateU1(); - if (args[1].IsImmediate()) { - const bool c = args[1].GetImmediateU1(); + code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], c); + } else { + const Xbyak::Reg8 c = ctx.reg_alloc.UseGpr(args[1]).cvt8(); - code.mov(al, ah); - code.or_(al, c); - code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], al); + code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], c); + } } else { - const Xbyak::Reg8 c = ctx.reg_alloc.UseGpr(args[1]).cvt8(); + ctx.reg_alloc.Use(args[0], HostLoc::RAX); - code.mov(al, ah); - code.or_(al, c); - code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], al); + if (args[1].IsImmediate()) { + const bool c = args[1].GetImmediateU1(); + + code.mov(al, ah); + code.or_(al, c); + code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], al); + } else { + const Xbyak::Reg8 c = ctx.reg_alloc.UseGpr(args[1]).cvt8(); + + code.mov(al, ah); + code.or_(al, c); + code.mov(code.byte[r15 + offsetof(A32JitState, cpsr_nzcv) + 1], al); + } } } diff --git a/src/dynarmic/ir/opt/a32_get_set_elimination_pass.cpp b/src/dynarmic/ir/opt/a32_get_set_elimination_pass.cpp index 7c14b7b3..6faa7997 100644 --- a/src/dynarmic/ir/opt/a32_get_set_elimination_pass.cpp +++ b/src/dynarmic/ir/opt/a32_get_set_elimination_pass.cpp @@ -204,8 +204,12 @@ void A32GetSetElimination(IR::Block& block) { break; } case IR::Opcode::A32SetCpsrNZ: { + if (cpsr_info.nzc.set_instruction_present) { + cpsr_info.nzc.last_set_instruction->SetArg(0, IR::Value::EmptyNZCVImmediateMarker()); + } + // cpsr_info.c remains valid - cpsr_info.nzc = {}; // TODO: Consider reduction of previous to a SetCFlag operation + cpsr_info.nzc = {}; cpsr_info.nzcv = {}; do_set(cpsr_info.nz, inst->GetArg(0), inst); break; diff --git a/src/dynarmic/ir/value.cpp b/src/dynarmic/ir/value.cpp index 5b86f731..20f94cb5 100644 --- a/src/dynarmic/ir/value.cpp +++ b/src/dynarmic/ir/value.cpp @@ -79,6 +79,12 @@ Value::Value(AccType value) inner.imm_acctype = value; } +Value Value::EmptyNZCVImmediateMarker() { + Value result{}; + result.type = Type::NZCVFlags; + return result; +} + bool Value::IsIdentity() const { if (type == Type::Opaque) return inner.inst->GetOpcode() == Opcode::Identity; diff --git a/src/dynarmic/ir/value.h b/src/dynarmic/ir/value.h index 122d86e5..8f70110a 100644 --- a/src/dynarmic/ir/value.h +++ b/src/dynarmic/ir/value.h @@ -53,6 +53,8 @@ public: explicit Value(Cond value); explicit Value(AccType value); + static Value EmptyNZCVImmediateMarker(); + bool IsIdentity() const; bool IsEmpty() const; bool IsImmediate() const;