mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-30 15:18:58 +02:00
C -> O for ppc64; impl NZCV?
Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
parent
c1b028dca4
commit
2e3020c274
5 changed files with 141 additions and 75 deletions
|
|
@ -62,8 +62,53 @@ void EmitIR<IR::Opcode::GetGEFromOp>(powah::Context&, EmitContext&, IR::Inst*) {
|
|||
}
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::GetNZCVFromOp>(powah::Context&, EmitContext& ctx, IR::Inst* inst) {
|
||||
ASSERT(false && "unimp");
|
||||
void EmitIR<IR::Opcode::GetNZCVFromOp>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
if (ctx.reg_alloc.IsValueLive(inst)) {
|
||||
ASSERT(false && "unimp value live");
|
||||
return;
|
||||
}
|
||||
// CR0:
|
||||
// 0 - N/LT, result is negative
|
||||
// 1 - P/GT, result is positive
|
||||
// 2 - Z/EQ, result is zero
|
||||
// 3 - S/SO, summary overflow (carry?)
|
||||
// XER:
|
||||
// 32 - SO
|
||||
// 33 - Overflow
|
||||
// 34 - Carry
|
||||
// NZCV -> (CR0.0, CR0.2, XER.34, XER.33)
|
||||
if (false) {
|
||||
//code.MFSPR(powah::GPR{1}, tmp4, powah::R0); // From XER
|
||||
/*uint64_t nzcv(uint64_t cr0, uint64_t xer) {
|
||||
return ((xer >> 33) & 1)
|
||||
| (((xer >> 34) & 1) << 1)
|
||||
| (((cr0 >> (32 + 2)) & 1) << 2)
|
||||
| (((cr0 >> (32 + 0)) & 1) << 3);
|
||||
}*/
|
||||
// auto const tmp9 = ctx.reg_alloc.ScratchGpr();
|
||||
// auto const tmp10 = ctx.reg_alloc.ScratchGpr();
|
||||
// code.SRDI(tmp9, tmp3, 34);
|
||||
// code.RLDICL(tmp10, tmp4, 31, 63);
|
||||
// code.SRDI(tmp3, tmp3, 32);
|
||||
// code.RLDIC(tmp9, tmp9, 2, 61);
|
||||
// code.OR(tmp9, tmp9, tmp10);
|
||||
// code.RLDIC(tmp3, tmp3, 3, 60);
|
||||
// code.SRDI(tmp4, tmp4, 34);
|
||||
// code.OR(tmp3, tmp9, tmp3);
|
||||
// code.RLDIC(tmp4, tmp4, 1, 62);
|
||||
// code.OR(tmp3, tmp3, tmp4);
|
||||
} else {
|
||||
// MFCR Fills RT 32:63, RT 0:31 left blank
|
||||
auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0));
|
||||
auto const tmp3 = ctx.reg_alloc.ScratchGpr();
|
||||
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
||||
code.LI(tmp, -1);
|
||||
code.RLDICR(tmp, tmp, 0, 0);
|
||||
code.MFCR(powah::R0, tmp3, powah::R0);
|
||||
code.CMPW(tmp, source);
|
||||
code.MFCR(powah::R0, tmp3, powah::R0);
|
||||
ctx.reg_alloc.DefineValue(inst, tmp3);
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
@ -185,6 +230,7 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf
|
|||
for (size_t i = 0; i < gpr_order.size(); ++i)
|
||||
code.LD(powah::GPR{gpr_order[i]}, powah::R1, -(i * 8));
|
||||
code.BLR();
|
||||
code.ApplyRelocs();
|
||||
|
||||
/*
|
||||
llvm-objcopy -I binary -O elf64-powerpc --rename-section=.data=.text,code test.bin test.elf && llvm-objdump -d test.elf
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ void EmitIR<IR::Opcode::A64SetNZCVRaw>(powah::Context& code, EmitContext& ctx, I
|
|||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::A64SetNZCV>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
ASSERT(false && "unimp");
|
||||
auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(0));
|
||||
code.STW(value, PPC64::RJIT, offsetof(A64JitState, pstate));
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
@ -111,8 +112,7 @@ void EmitIR<IR::Opcode::A64SetW>(powah::Context& code, EmitContext& ctx, IR::Ins
|
|||
auto const tmp = ctx.reg_alloc.ScratchGpr();
|
||||
auto const offs = offsetof(A64JitState, regs)
|
||||
+ A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64);
|
||||
code.MR(tmp, value);
|
||||
code.RLDICL(tmp, tmp, 0, 32);
|
||||
code.RLDICL(tmp, value, 0, 32);
|
||||
code.STD(tmp, PPC64::RJIT, offs);
|
||||
} else {
|
||||
ASSERT(false && "unimp");
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <powah_emit.hpp>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
#include "abi.h"
|
||||
#include "dynarmic/common/assert.h"
|
||||
#include "dynarmic/backend/ppc64/a32_core.h"
|
||||
#include "dynarmic/backend/ppc64/abi.h"
|
||||
|
|
@ -436,17 +437,28 @@ void EmitIR<IR::Opcode::Add32>(powah::Context& code, EmitContext& ctx, IR::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.ADD(result, src_a, src_b);
|
||||
code.ADDC_(result, src_a, src_b);
|
||||
code.RLDICL(result, result, 0, 32);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
/*
|
||||
struct jit {
|
||||
uint32_t nzcv;
|
||||
};
|
||||
uint64_t addc(jit *p, uint64_t a, uint64_t b) {
|
||||
long long unsigned int e;
|
||||
uint64_t r = __builtin_addcll(a, b, p->nzcv & 0b0010, &e);
|
||||
p->nzcv = (p->nzcv & 0b1101) | e;
|
||||
return r;
|
||||
}
|
||||
*/
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::Add64>(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.ADD(result, src_a, src_b);
|
||||
code.ADDC_(result, src_a, src_b);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -455,7 +467,7 @@ void EmitIR<IR::Opcode::Sub32>(powah::Context& code, EmitContext& ctx, IR::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.SUBF(result, src_b, src_a);
|
||||
code.SUBFC_(result, src_b, src_a);
|
||||
code.RLDICL(result, result, 0, 32);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
|
@ -465,7 +477,7 @@ void EmitIR<IR::Opcode::Sub64>(powah::Context& code, EmitContext& ctx, IR::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.SUBF(result, src_b, src_a);
|
||||
code.SUBFC_(result, src_b, src_a);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -474,7 +486,7 @@ void EmitIR<IR::Opcode::Mul32>(powah::Context& code, EmitContext& ctx, IR::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.MULLW(result, src_a, src_b);
|
||||
code.MULLWO_(result, src_a, src_b);
|
||||
code.RLDICL(result, result, 0, 32);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
|
@ -484,7 +496,7 @@ void EmitIR<IR::Opcode::Mul64>(powah::Context& code, EmitContext& ctx, IR::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.MULLD(result, src_a, src_b);
|
||||
code.MULLDO_(result, src_a, src_b);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -493,7 +505,7 @@ void EmitIR<IR::Opcode::SignedMultiplyHigh64>(powah::Context& code, EmitContext&
|
|||
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.MULLD(result, src_a, src_b);
|
||||
code.MULLDO_(result, src_a, src_b);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -502,7 +514,7 @@ void EmitIR<IR::Opcode::UnsignedMultiplyHigh64>(powah::Context& code, EmitContex
|
|||
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.MULLD(result, src_a, src_b);
|
||||
code.MULLDO_(result, src_a, src_b);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -511,7 +523,7 @@ void EmitIR<IR::Opcode::UnsignedDiv32>(powah::Context& code, EmitContext& ctx, I
|
|||
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.DIVDU(result, src_a, src_b);
|
||||
code.DIVWU_(result, src_a, src_b);
|
||||
code.RLDICL(result, result, 0, 32);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
|
@ -521,7 +533,7 @@ void EmitIR<IR::Opcode::UnsignedDiv64>(powah::Context& code, EmitContext& ctx, I
|
|||
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.DIVDU(result, src_a, src_b);
|
||||
code.DIVDU_(result, src_a, src_b);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -530,7 +542,7 @@ void EmitIR<IR::Opcode::SignedDiv32>(powah::Context& code, EmitContext& ctx, IR:
|
|||
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.DIVW(result, src_a, src_b);
|
||||
code.DIVW_(result, src_a, src_b);
|
||||
code.EXTSW(result, result);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
|
@ -540,7 +552,7 @@ void EmitIR<IR::Opcode::SignedDiv64>(powah::Context& code, EmitContext& ctx, IR:
|
|||
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.DIVD(result, src_a, src_b);
|
||||
code.DIVD_(result, src_a, src_b);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -549,7 +561,8 @@ void EmitIR<IR::Opcode::And32>(powah::Context& code, EmitContext& ctx, IR::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);
|
||||
code.RLDICL(result, src_a, 0, 32); // Truncate
|
||||
code.AND_(result, result, src_b);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -558,7 +571,8 @@ void EmitIR<IR::Opcode::And64>(powah::Context& code, EmitContext& ctx, IR::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);
|
||||
code.AND_(result, src_a, src_b);
|
||||
code.ADDI(result, result, 0); //update cr0
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -567,7 +581,7 @@ void EmitIR<IR::Opcode::AndNot32>(powah::Context& code, EmitContext& ctx, IR::In
|
|||
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.NAND(result, src_a, src_b);
|
||||
code.NAND_(result, src_a, src_b);
|
||||
code.RLDICL(result, result, 0, 32);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
|
@ -577,7 +591,7 @@ void EmitIR<IR::Opcode::AndNot64>(powah::Context& code, EmitContext& ctx, IR::In
|
|||
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.NAND(result, src_a, src_b);
|
||||
code.NAND_(result, src_a, src_b);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -586,7 +600,7 @@ void EmitIR<IR::Opcode::Eor32>(powah::Context& code, EmitContext& ctx, IR::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.XOR(result, src_a, src_b);
|
||||
code.XOR_(result, src_a, src_b);
|
||||
code.RLDICL(result, result, 0, 32);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
|
@ -596,7 +610,7 @@ void EmitIR<IR::Opcode::Eor64>(powah::Context& code, EmitContext& ctx, IR::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.XOR(result, src_a, src_b);
|
||||
code.XOR_(result, src_a, src_b);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
|
|
@ -605,7 +619,7 @@ void EmitIR<IR::Opcode::Or32>(powah::Context& code, EmitContext& ctx, IR::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.OR(result, src_a, src_b);
|
||||
code.OR_(result, src_a, src_b);
|
||||
code.RLDICL(result, result, 0, 32);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
|
@ -615,10 +629,11 @@ void EmitIR<IR::Opcode::Or64>(powah::Context& code, EmitContext& ctx, IR::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.OR(result, src_a, src_b);
|
||||
code.OR_(result, src_a, src_b);
|
||||
ctx.reg_alloc.DefineValue(inst, result);
|
||||
}
|
||||
|
||||
// TODO(lizzie): NZVC support for NOT
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::Not32>(powah::Context& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto const result = ctx.reg_alloc.ScratchGpr();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue