diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 858f846574..c3f110b103 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -364,6 +364,7 @@ struct Context { void CMPD(GPR const rx, GPR const ry) { CMP(0, 1, rx, ry); } void LI(GPR const rx, uint32_t value) { ADDI(rx, R0, value); } + void LIS(GPR const rx, uint32_t value) { ADDIS(rx, R0, value); } void BLR() { base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 5943072413..5d79a47036 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -24,7 +24,6 @@ struct A64JitState { u64 sp = 0; u32 upper_location_descriptor; u32 exclusive_state = 0; - u32 cpsr_nzcv = 0; u32 pstate = 0; u32 fpcr = 0; u32 fpsr = 0; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index c5a536f1e5..3e8bbbacf2 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -9,6 +9,7 @@ namespace Dynarmic::Backend::PPC64 { constexpr powah::GPR RJIT = powah::R3; //yeah it's param, so what? +constexpr powah::GPR RNZCV = powah::R31; constexpr powah::GPR ABI_PARAM1 = powah::R3; constexpr powah::GPR ABI_PARAM2 = powah::R4; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp index 44323a4721..98a73f2028 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp @@ -81,26 +81,26 @@ void EmitIR(powah::Context& code, EmitContext& c } /* -uint64_t f(uint64_t a) { return a == 0; } +uint64_t f(uint64_t a) { return (uint32_t)a == 0; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const result = ctx.reg_alloc.ScratchGpr(); auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - code.CNTLZD(result, source); - code.SRDI(result, result, 6); + code.CNTLZW(result, source); + code.SRWI(result, result, 5); ctx.reg_alloc.DefineValue(inst, result); } /* -uint64_t f(uint64_t a) { return (uint32_t)a == 0; } +uint64_t f(uint64_t a) { return a == 0; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const result = ctx.reg_alloc.ScratchGpr(); auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - code.CNTLZW(result, source); - code.SRWI(result, result, 5); + code.CNTLZD(result, source); + code.SRDI(result, result, 6); ctx.reg_alloc.DefineValue(inst, result); } @@ -561,39 +561,33 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* auto const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); auto const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); auto const tmp3 = ctx.reg_alloc.ScratchGpr(); - auto const tmp10 = ctx.reg_alloc.ScratchGpr(); + auto const tmp8 = ctx.reg_alloc.ScratchGpr(); auto const tmp9 = PPC64::RNZCV; code.RLDICL(tmp3, src_a, 0, 32); // Truncate code.AND(tmp3, tmp3, src_b); - code.CNTLZD(tmp10, tmp3); - code.SRADI(tmp9, tmp3, 32); - code.SRDI(tmp10, tmp10, 6); - code.RLWINM(tmp9, tmp9, 0, 0, 0); - code.SLDI(tmp10, tmp10, 30); - code.OR(tmp9, tmp9, tmp10); - -/* - and 3,4,5 - cntlzd 10,3 - sradi 9,3,32 - srdi 10,10,6 - rlwinm 9,9,0,0,0 - sldi 10,10,30 - or 9,9,10 - std 9,0(8) - blr -*/ - + code.CNTLZD(tmp9, tmp3); + code.RLWINM(tmp8, tmp3, 0, 0, 0); + code.SRDI(tmp9, tmp9, 6); + code.SLDI(tmp9, tmp9, 30); + code.OR(tmp9, tmp9, tmp8); ctx.reg_alloc.DefineValue(inst, tmp3); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto const result = ctx.reg_alloc.ScratchGpr(); auto const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); auto const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); - code.AND_(result, src_a, src_b); - ctx.reg_alloc.DefineValue(inst, result); + auto const tmp3 = ctx.reg_alloc.ScratchGpr(); + auto const tmp10 = ctx.reg_alloc.ScratchGpr(); + auto const tmp9 = PPC64::RNZCV; + code.AND(tmp3, src_a, src_b); + code.CNTLZD(tmp10, tmp3); + code.SRADI(tmp9, tmp3, 32); + code.SRDI(tmp10, tmp10, 6); + code.RLWINM(tmp9, tmp9, 0, 0, 0); + code.SLDI(tmp10, tmp10, 30); + code.OR(tmp9, tmp9, tmp10); + ctx.reg_alloc.DefineValue(inst, tmp3); } template<> diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp index 5cd113789e..3e524571b0 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -163,9 +163,19 @@ RegLock RegAlloc::UseGpr(IR::Value arg) { // HOLY SHIT EVIL HAXX auto const reg = ScratchGpr(); auto const imm = arg.GetImmediateAsU64(); - if (imm >= 0xffff) { - ASSERT(false && "big imms"); - } else { + if (imm >= 0xffffffff) { + auto const lo = uint32_t(imm >> 0), hi = uint32_t(imm >> 32); + if (lo == hi) { + code.LIS(reg, imm >> 16); + code.ORI(reg, reg, imm & 0xffff); + code.RLDIMI(reg, reg, 32, 0); + } else { + ASSERT(false && "larger >32bit imms"); + } + } else if (imm > 0xffff && imm <= 0xffffffff) { + code.LIS(reg, imm >> 16); + code.ORI(reg, reg, imm & 0xffff); + } else if (imm <= 0xffff) { code.LI(reg, imm); } return reg;