Browse Source

A64: addition fixes extra

Signed-off-by: lizzie <lizzie@eden-emu.dev>
dynarmic-ppc64
lizzie 2 months ago
parent
commit
3e66f9bd8e
No known key found for this signature in database GPG Key ID: 287378CADCAB13
  1. 1
      externals/powah/powah_emit.hpp
  2. 1
      src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h
  3. 1
      src/dynarmic/src/dynarmic/backend/ppc64/abi.h
  4. 52
      src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp
  5. 14
      src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp

1
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 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 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() { void BLR() {
base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0); base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0);

1
src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h

@ -24,7 +24,6 @@ struct A64JitState {
u64 sp = 0; u64 sp = 0;
u32 upper_location_descriptor; u32 upper_location_descriptor;
u32 exclusive_state = 0; u32 exclusive_state = 0;
u32 cpsr_nzcv = 0;
u32 pstate = 0; u32 pstate = 0;
u32 fpcr = 0; u32 fpcr = 0;
u32 fpsr = 0; u32 fpsr = 0;

1
src/dynarmic/src/dynarmic/backend/ppc64/abi.h

@ -9,6 +9,7 @@
namespace Dynarmic::Backend::PPC64 { namespace Dynarmic::Backend::PPC64 {
constexpr powah::GPR RJIT = powah::R3; //yeah it's param, so what? 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_PARAM1 = powah::R3;
constexpr powah::GPR ABI_PARAM2 = powah::R4; constexpr powah::GPR ABI_PARAM2 = powah::R4;

52
src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp

@ -81,26 +81,26 @@ void EmitIR<IR::Opcode::MostSignificantBit>(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<> template<>
void EmitIR<IR::Opcode::IsZero32>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::IsZero32>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
auto const result = ctx.reg_alloc.ScratchGpr(); auto const result = ctx.reg_alloc.ScratchGpr();
auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); 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); 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<> template<>
void EmitIR<IR::Opcode::IsZero64>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::IsZero64>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
auto const result = ctx.reg_alloc.ScratchGpr(); auto const result = ctx.reg_alloc.ScratchGpr();
auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); 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); ctx.reg_alloc.DefineValue(inst, result);
} }
@ -561,39 +561,33 @@ void EmitIR<IR::Opcode::And32>(powah::Context& code, EmitContext& ctx, IR::Inst*
auto const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); auto const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0));
auto const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); auto const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1));
auto const tmp3 = ctx.reg_alloc.ScratchGpr(); 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; auto const tmp9 = PPC64::RNZCV;
code.RLDICL(tmp3, src_a, 0, 32); // Truncate code.RLDICL(tmp3, src_a, 0, 32); // Truncate
code.AND(tmp3, tmp3, src_b); 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); ctx.reg_alloc.DefineValue(inst, tmp3);
} }
template<> template<>
void EmitIR<IR::Opcode::And64>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::And64>(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_a = ctx.reg_alloc.UseGpr(inst->GetArg(0));
auto const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); 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<> template<>

14
src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp

@ -163,9 +163,19 @@ RegLock<powah::GPR> RegAlloc::UseGpr(IR::Value arg) {
// HOLY SHIT EVIL HAXX // HOLY SHIT EVIL HAXX
auto const reg = ScratchGpr(); auto const reg = ScratchGpr();
auto const imm = arg.GetImmediateAsU64(); auto const imm = arg.GetImmediateAsU64();
if (imm >= 0xffff) {
ASSERT(false && "big imms");
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 { } 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); code.LI(reg, imm);
} }
return reg; return reg;

Loading…
Cancel
Save