From 57ebe48cf783fe8eca3097c34f9e603514d305f6 Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Tue, 10 Sep 2024 19:26:53 +0300 Subject: [PATCH 1/2] Add a huge switch case with all instructions. --- PowerRecomp/main.cpp | 394 ++++++++++++++++++++++++++++++++++++--- PowerUtils/ppc_context.h | 271 ++++++++++++++++++++++++++- 2 files changed, 628 insertions(+), 37 deletions(-) diff --git a/PowerRecomp/main.cpp b/PowerRecomp/main.cpp index 22727b4..cac282e 100644 --- a/PowerRecomp/main.cpp +++ b/PowerRecomp/main.cpp @@ -44,6 +44,8 @@ int main() std::filesystem::create_directory("out"); FILE* f = fopen("out/" TEST_FILE ".cpp", "w"); + std::println(f, "#include \n"); + for (const auto& fn : functions) { auto base = fn.base; @@ -61,7 +63,8 @@ int main() name = std::format("sub_{:X}", base); } - std::println(f, "void {}() {{", name); + std::println(f, "void {}(PPCContext& __restrict ctx, uint8_t* __restrict base) {{", name); + std::println(f, "\tuint32_t ea;\n"); ppc_insn insn; while (base < end) @@ -80,37 +83,35 @@ int main() switch (insn.opcode->id) { case PPC_INST_ADD: - std::println(f, "\tr{} = r{} + r{};", insn.operands[0], insn.operands[1], insn.operands[2]); + // TODO: . variant + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 + ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]); break; + case PPC_INST_ADDI: - std::println(f, "\tr{} = r{} + {};", insn.operands[0], insn.operands[1], insn.operands[2]); + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 + {};", insn.operands[0], insn.operands[1], insn.operands[2]); break; - case PPC_INST_STWU: - std::println(f, "\tea = r{} + {};", insn.operands[2], static_cast(insn.operands[1])); - std::println(f, "\t*ea = byteswap(r{});", insn.operands[0]); - std::println(f, "\tr{} = ea;", insn.operands[2]); - break; - case PPC_INST_STW: - std::println(f, "\t*(r{} + {}) = byteswap(r{});", insn.operands[2], static_cast(insn.operands[1]), insn.operands[0]); - break; - case PPC_INST_MR: - std::println(f, "\tr{} = r{};", insn.operands[0], insn.operands[1]); - break; - case PPC_INST_LWZ: - std::println(f, "\tr{} = *(r{} + {});", insn.operands[0], insn.operands[2], insn.operands[1]); - break; - case PPC_INST_LI: - std::println(f, "\tr{} = {};", insn.operands[0], insn.operands[1]); - break; - case PPC_INST_MFLR: - std::println(f, "\tr{} = lr;", insn.operands[0]); - break; - case PPC_INST_MTLR: - std::println(f, "\tlr = r{};", insn.operands[0]); - break; - case PPC_INST_BLR: - std::println(f, "\treturn;"); + + case PPC_INST_ADDIC: + case PPC_INST_ADDIS: + case PPC_INST_ADDZE: + case PPC_INST_AND: + case PPC_INST_ANDC: + case PPC_INST_ANDI: + case PPC_INST_ANDIS: + case PPC_INST_ATTN: + case PPC_INST_B: + case PPC_INST_BCTR: + case PPC_INST_BCTRL: + case PPC_INST_BDNZ: + case PPC_INST_BDNZF: + case PPC_INST_BEQ: + case PPC_INST_BEQLR: + case PPC_INST_BGE: + case PPC_INST_BGELR: + case PPC_INST_BGT: + case PPC_INST_BGTLR: break; + case PPC_INST_BL: { std::string targetName = ""; @@ -123,10 +124,343 @@ int main() { targetName = std::format("sub_{:X}", insn.operands[0]); } - std::println(f, "\tlr = 0x{:x};", base); - std::println(f, "\t{}();", targetName); + std::println(f, "\tctx.lr = 0x{:X};", base); + std::println(f, "\t{}(ctx, base);", targetName); break; } + + case PPC_INST_BLE: + case PPC_INST_BLELR: + break; + + case PPC_INST_BLR: + // TODO: do they use this for anything other than a return? + std::println(f, "\treturn;"); + break; + + case PPC_INST_BLRL: + case PPC_INST_BLT: + case PPC_INST_BLTLR: + case PPC_INST_BNE: + case PPC_INST_BNECTR: + case PPC_INST_BNELR: + case PPC_INST_CCTPL: + case PPC_INST_CCTPM: + case PPC_INST_CLRLDI: + case PPC_INST_CLRLWI: + case PPC_INST_CMPD: + case PPC_INST_CMPDI: + case PPC_INST_CMPLD: + case PPC_INST_CMPLDI: + case PPC_INST_CMPLW: + case PPC_INST_CMPLWI: + case PPC_INST_CMPW: + case PPC_INST_CMPWI: + case PPC_INST_CNTLZD: + case PPC_INST_CNTLZW: + case PPC_INST_DB16CYC: + case PPC_INST_DCBF: + case PPC_INST_DCBT: + case PPC_INST_DCBTST: + case PPC_INST_DCBZ: + case PPC_INST_DCBZL: + case PPC_INST_DIVD: + case PPC_INST_DIVDU: + case PPC_INST_DIVW: + case PPC_INST_DIVWU: + case PPC_INST_EIEIO: + case PPC_INST_EXTSB: + case PPC_INST_EXTSH: + case PPC_INST_EXTSW: + case PPC_INST_FABS: + case PPC_INST_FADD: + case PPC_INST_FADDS: + case PPC_INST_FCFID: + case PPC_INST_FCMPU: + case PPC_INST_FCTID: + case PPC_INST_FCTIDZ: + case PPC_INST_FCTIWZ: + case PPC_INST_FDIV: + case PPC_INST_FDIVS: + case PPC_INST_FMADD: + case PPC_INST_FMADDS: + case PPC_INST_FMR: + case PPC_INST_FMSUB: + case PPC_INST_FMSUBS: + case PPC_INST_FMUL: + case PPC_INST_FMULS: + case PPC_INST_FNABS: + case PPC_INST_FNEG: + case PPC_INST_FNMADDS: + case PPC_INST_FNMSUB: + case PPC_INST_FNMSUBS: + case PPC_INST_FRES: + case PPC_INST_FRSP: + case PPC_INST_FSEL: + case PPC_INST_FSQRT: + case PPC_INST_FSQRTS: + case PPC_INST_FSUB: + case PPC_INST_FSUBS: + case PPC_INST_LBZ: + case PPC_INST_LBZU: + case PPC_INST_LBZX: + case PPC_INST_LD: + case PPC_INST_LDARX: + case PPC_INST_LDU: + case PPC_INST_LDX: + case PPC_INST_LFD: + case PPC_INST_LFDX: + case PPC_INST_LFS: + case PPC_INST_LFSX: + case PPC_INST_LHA: + case PPC_INST_LHAX: + case PPC_INST_LHZ: + case PPC_INST_LHZX: + break; + + case PPC_INST_LI: + std::println(f, "\tctx.r{}.u64 = {};", insn.operands[0], insn.operands[1]); + break; + + case PPC_INST_LIS: + case PPC_INST_LVEWX: + case PPC_INST_LVEWX128: + case PPC_INST_LVLX: + case PPC_INST_LVLX128: + case PPC_INST_LVRX: + case PPC_INST_LVRX128: + case PPC_INST_LVSL: + case PPC_INST_LVSR: + case PPC_INST_LVX: + case PPC_INST_LVX128: + case PPC_INST_LWA: + case PPC_INST_LWARX: + case PPC_INST_LWAX: + case PPC_INST_LWBRX: + case PPC_INST_LWSYNC: + break; + + case PPC_INST_LWZ: + std::println(f, "\tctx.r{}.u64 = PPC_LOAD_U32({} + ctx.r{}.u32);", insn.operands[0], int32_t(insn.operands[1]), insn.operands[2]); + break; + + case PPC_INST_LWZU: + case PPC_INST_LWZX: + case PPC_INST_MFCR: + case PPC_INST_MFFS: + break; + + case PPC_INST_MFLR: + std::println(f, "\tctx.lr = ctx.r{}.u64;", insn.operands[0]); + break; + + case PPC_INST_MFMSR: + case PPC_INST_MFOCRF: + case PPC_INST_MFTB: + break; + + case PPC_INST_MR: + // TODO: . variant + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64;", insn.operands[0], insn.operands[1]); + break; + + case PPC_INST_MTCR: + case PPC_INST_MTCTR: + case PPC_INST_MTFSF: + break; + + case PPC_INST_MTLR: + std::println(f, "\tctx.r{}.u64 = ctx.lr;", insn.operands[0]); + break; + + case PPC_INST_MTMSRD: + case PPC_INST_MTXER: + case PPC_INST_MULCHWU: + case PPC_INST_MULHHW: + case PPC_INST_MULHW: + case PPC_INST_MULHWU: + case PPC_INST_MULLD: + case PPC_INST_MULLI: + case PPC_INST_MULLW: + case PPC_INST_NAND: + case PPC_INST_NEG: + case PPC_INST_NOP: + case PPC_INST_NOR: + case PPC_INST_NOT: + case PPC_INST_OR: + case PPC_INST_ORC: + case PPC_INST_ORI: + case PPC_INST_ORIS: + case PPC_INST_RLDICL: + case PPC_INST_RLDICR: + case PPC_INST_RLDIMI: + case PPC_INST_RLWIMI: + case PPC_INST_RLWINM: + case PPC_INST_ROTLDI: + case PPC_INST_ROTLW: + case PPC_INST_ROTLWI: + case PPC_INST_SLD: + case PPC_INST_SLW: + case PPC_INST_SRAD: + case PPC_INST_SRADI: + case PPC_INST_SRAW: + case PPC_INST_SRAWI: + case PPC_INST_SRD: + case PPC_INST_SRW: + case PPC_INST_STB: + case PPC_INST_STBU: + case PPC_INST_STBX: + case PPC_INST_STD: + case PPC_INST_STDCX: + case PPC_INST_STDU: + case PPC_INST_STDX: + case PPC_INST_STFD: + case PPC_INST_STFDX: + case PPC_INST_STFIWX: + case PPC_INST_STFS: + case PPC_INST_STFSX: + case PPC_INST_STH: + case PPC_INST_STHBRX: + case PPC_INST_STHX: + case PPC_INST_STVEHX: + case PPC_INST_STVEWX: + case PPC_INST_STVEWX128: + case PPC_INST_STVLX: + case PPC_INST_STVLX128: + case PPC_INST_STVRX: + case PPC_INST_STVRX128: + case PPC_INST_STVX: + case PPC_INST_STVX128: + break; + + case PPC_INST_STW: + std::println(f, "\tPPC_STORE_U32({} + ctx.r{}.u32, ctx.r{}.u32);", int32_t(insn.operands[1]), insn.operands[2], insn.operands[0]); + break; + + case PPC_INST_STWBRX: + case PPC_INST_STWCX: + break; + + case PPC_INST_STWU: + std::println(f, "\tea = {} + ctx.r{}.u32;", int32_t(insn.operands[1]), insn.operands[2]); + std::println(f, "\tPPC_STORE_U32(ea, ctx.r{}.u32);", insn.operands[0]); + std::println(f, "\tctx.r{}.u64 = ea;", insn.operands[0]); + break; + + case PPC_INST_STWUX: + case PPC_INST_STWX: + case PPC_INST_SUBF: + case PPC_INST_SUBFC: + case PPC_INST_SUBFE: + case PPC_INST_SUBFIC: + case PPC_INST_SYNC: + case PPC_INST_TDLGEI: + case PPC_INST_TDLLEI: + case PPC_INST_TWI: + case PPC_INST_TWLGEI: + case PPC_INST_TWLLEI: + case PPC_INST_VADDFP: + case PPC_INST_VADDFP128: + case PPC_INST_VADDSHS: + case PPC_INST_VADDUBM: + case PPC_INST_VADDUBS: + case PPC_INST_VADDUHM: + case PPC_INST_VADDUWM: + case PPC_INST_VADDUWS: + case PPC_INST_VAND: + case PPC_INST_VAND128: + case PPC_INST_VANDC128: + case PPC_INST_VAVGSB: + case PPC_INST_VAVGSH: + case PPC_INST_VAVGUB: + case PPC_INST_VCFPSXWS128: + case PPC_INST_VCFSX: + case PPC_INST_VCFUX: + case PPC_INST_VCMPBFP128: + case PPC_INST_VCMPEQFP: + case PPC_INST_VCMPEQFP128: + case PPC_INST_VCMPEQUB: + case PPC_INST_VCMPEQUW: + case PPC_INST_VCMPEQUW128: + case PPC_INST_VCMPGEFP: + case PPC_INST_VCMPGEFP128: + case PPC_INST_VCMPGTFP: + case PPC_INST_VCMPGTFP128: + case PPC_INST_VCMPGTUB: + case PPC_INST_VCMPGTUH: + case PPC_INST_VCSXWFP128: + case PPC_INST_VCTSXS: + case PPC_INST_VCUXWFP128: + case PPC_INST_VEXPTEFP128: + case PPC_INST_VLOGEFP128: + case PPC_INST_VMADDCFP128: + case PPC_INST_VMADDFP: + case PPC_INST_VMADDFP128: + case PPC_INST_VMAXFP: + case PPC_INST_VMAXFP128: + case PPC_INST_VMAXSW: + case PPC_INST_VMINFP: + case PPC_INST_VMINFP128: + case PPC_INST_VMRGHB: + case PPC_INST_VMRGHH: + case PPC_INST_VMRGHW: + case PPC_INST_VMRGHW128: + case PPC_INST_VMRGLB: + case PPC_INST_VMRGLH: + case PPC_INST_VMRGLW: + case PPC_INST_VMRGLW128: + case PPC_INST_VMSUM3FP128: + case PPC_INST_VMSUM4FP128: + case PPC_INST_VMULFP128: + case PPC_INST_VNMSUBFP: + case PPC_INST_VNMSUBFP128: + case PPC_INST_VOR: + case PPC_INST_VOR128: + case PPC_INST_VPERM: + case PPC_INST_VPERM128: + case PPC_INST_VPERMWI128: + case PPC_INST_VPKD3D128: + case PPC_INST_VPKSHUS: + case PPC_INST_VREFP: + case PPC_INST_VREFP128: + case PPC_INST_VRFIM128: + case PPC_INST_VRFIN: + case PPC_INST_VRFIN128: + case PPC_INST_VRFIZ128: + case PPC_INST_VRLIMI128: + case PPC_INST_VRSQRTEFP: + case PPC_INST_VRSQRTEFP128: + case PPC_INST_VSEL: + case PPC_INST_VSLB: + case PPC_INST_VSLDOI: + case PPC_INST_VSLDOI128: + case PPC_INST_VSLW128: + case PPC_INST_VSPLTH: + case PPC_INST_VSPLTISB: + case PPC_INST_VSPLTISW: + case PPC_INST_VSPLTISW128: + case PPC_INST_VSPLTW: + case PPC_INST_VSPLTW128: + case PPC_INST_VSR: + case PPC_INST_VSRAW128: + case PPC_INST_VSRW: + case PPC_INST_VSRW128: + case PPC_INST_VSUBFP: + case PPC_INST_VSUBFP128: + case PPC_INST_VSUBSWS: + case PPC_INST_VSUBUBS: + case PPC_INST_VSUBUHM: + case PPC_INST_VUPKD3D128: + case PPC_INST_VUPKHSB128: + case PPC_INST_VUPKHSH: + case PPC_INST_VUPKLSB128: + case PPC_INST_VUPKLSH: + case PPC_INST_VXOR: + case PPC_INST_VXOR128: + case PPC_INST_XOR: + case PPC_INST_XORI: + case PPC_INST_XORIS: + break; } } } diff --git a/PowerUtils/ppc_context.h b/PowerUtils/ppc_context.h index 793dcdf..538f38b 100644 --- a/PowerUtils/ppc_context.h +++ b/PowerUtils/ppc_context.h @@ -1,18 +1,275 @@ #pragma once #include +#include + +#ifdef __clang__ +#define __restrict __restrict__ +#define _byteswap_ushort __builtin_bswap16 +#define _byteswap_ulong __builtin_bswap32 +#define _byteswap_uint64 __builtin_bswap64 +#endif + +#define PPC_LOAD_U16(x) _byteswap_ushort(*(uint16_t*)(base + (x))) +#define PPC_LOAD_U32(x) _byteswap_ulong(*(uint32_t*)(base + (x))) +#define PPC_LOAD_U64(x) _byteswap_uint64(*(uint64_t*)(base + (x))) + +#define PPC_STORE_U16(x, y) *(uint16_t*)(base + (x)) = _byteswap_ushort(y) +#define PPC_STORE_U32(x, y) *(uint32_t*)(base + (x)) = _byteswap_ulong(y) +#define PPC_STORE_U64(x, y) *(uint64_t*)(base + (x)) = _byteswap_uint64(y) + +struct PPCRegister +{ + union + { + int8_t s8; + uint8_t u8; + int16_t s16; + uint16_t u16; + int32_t s32; + uint32_t u32; + int64_t s64; + uint64_t u64; + float f32; + double f64; + }; +}; typedef float float128[4]; struct PPCContext { - uint64_t iar; uint64_t lr; uint64_t ctr; - uint32_t xer; - uint32_t cr[8]; - uint32_t fpcsr; - uint64_t gpr[32]; - double fpr[32]; - float128 vpr[128]; + union + { + struct + { + uint32_t cr0; + uint32_t cr1; + uint32_t cr2; + uint32_t cr3; + uint32_t cr4; + uint32_t cr5; + uint32_t cr6; + uint32_t cr7; + }; + uint32_t cr[8]; + }; + + union + { + struct + { + PPCRegister r0; + PPCRegister r1; + PPCRegister r2; + PPCRegister r3; + PPCRegister r4; + PPCRegister r5; + PPCRegister r6; + PPCRegister r7; + PPCRegister r8; + PPCRegister r9; + PPCRegister r10; + PPCRegister r11; + PPCRegister r12; + PPCRegister r13; + PPCRegister r14; + PPCRegister r15; + PPCRegister r16; + PPCRegister r17; + PPCRegister r18; + PPCRegister r19; + PPCRegister r20; + PPCRegister r21; + PPCRegister r22; + PPCRegister r23; + PPCRegister r24; + PPCRegister r25; + PPCRegister r26; + PPCRegister r27; + PPCRegister r28; + PPCRegister r29; + PPCRegister r30; + PPCRegister r31; + }; + PPCRegister r[32]; + }; + + union + { + struct + { + PPCRegister f0; + PPCRegister f1; + PPCRegister f2; + PPCRegister f3; + PPCRegister f4; + PPCRegister f5; + PPCRegister f6; + PPCRegister f7; + PPCRegister f8; + PPCRegister f9; + PPCRegister f10; + PPCRegister f11; + PPCRegister f12; + PPCRegister f13; + PPCRegister f14; + PPCRegister f15; + PPCRegister f16; + PPCRegister f17; + PPCRegister f18; + PPCRegister f19; + PPCRegister f20; + PPCRegister f21; + PPCRegister f22; + PPCRegister f23; + PPCRegister f24; + PPCRegister f25; + PPCRegister f26; + PPCRegister f27; + PPCRegister f28; + PPCRegister f29; + PPCRegister f30; + PPCRegister f31; + }; + PPCRegister f[32]; + }; + + union + { + struct + { + float128 v0; + float128 v1; + float128 v2; + float128 v3; + float128 v4; + float128 v5; + float128 v6; + float128 v7; + float128 v8; + float128 v9; + float128 v10; + float128 v11; + float128 v12; + float128 v13; + float128 v14; + float128 v15; + float128 v16; + float128 v17; + float128 v18; + float128 v19; + float128 v20; + float128 v21; + float128 v22; + float128 v23; + float128 v24; + float128 v25; + float128 v26; + float128 v27; + float128 v28; + float128 v29; + float128 v30; + float128 v31; + float128 v32; + float128 v33; + float128 v34; + float128 v35; + float128 v36; + float128 v37; + float128 v38; + float128 v39; + float128 v40; + float128 v41; + float128 v42; + float128 v43; + float128 v44; + float128 v45; + float128 v46; + float128 v47; + float128 v48; + float128 v49; + float128 v50; + float128 v51; + float128 v52; + float128 v53; + float128 v54; + float128 v55; + float128 v56; + float128 v57; + float128 v58; + float128 v59; + float128 v60; + float128 v61; + float128 v62; + float128 v63; + float128 v64; + float128 v65; + float128 v66; + float128 v67; + float128 v68; + float128 v69; + float128 v70; + float128 v71; + float128 v72; + float128 v73; + float128 v74; + float128 v75; + float128 v76; + float128 v77; + float128 v78; + float128 v79; + float128 v80; + float128 v81; + float128 v82; + float128 v83; + float128 v84; + float128 v85; + float128 v86; + float128 v87; + float128 v88; + float128 v89; + float128 v90; + float128 v91; + float128 v92; + float128 v93; + float128 v94; + float128 v95; + float128 v96; + float128 v97; + float128 v98; + float128 v99; + float128 v100; + float128 v101; + float128 v102; + float128 v103; + float128 v104; + float128 v105; + float128 v106; + float128 v107; + float128 v108; + float128 v109; + float128 v110; + float128 v111; + float128 v112; + float128 v113; + float128 v114; + float128 v115; + float128 v116; + float128 v117; + float128 v118; + float128 v119; + float128 v120; + float128 v121; + float128 v122; + float128 v123; + float128 v124; + float128 v125; + float128 v126; + float128 v127; + }; + float128 v[128]; + }; }; From 28e6ba92f8a1d810313359d964d9531e013cfbe1 Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Tue, 10 Sep 2024 23:16:21 +0300 Subject: [PATCH 2/2] Implement some instructions. --- PowerRecomp/main.cpp | 122 ++++++++++++++++++++++++++++++++++++++- PowerUtils/ppc_context.h | 28 ++++++--- 2 files changed, 138 insertions(+), 12 deletions(-) diff --git a/PowerRecomp/main.cpp b/PowerRecomp/main.cpp index cac282e..f7aaafe 100644 --- a/PowerRecomp/main.cpp +++ b/PowerRecomp/main.cpp @@ -6,7 +6,7 @@ #include #include -#define TEST_FILE "add.elf" +#define TEST_FILE "cond.elf" int main() { @@ -69,6 +69,10 @@ int main() ppc_insn insn; while (base < end) { + auto block = fn.SearchBlock(base); + if (block != -1 && (fn.base + fn.blocks[block].base) == base) + std::println(f, "loc_{:X}:", base); + ppc::Disassemble(data, 4, base, insn); base += 4; @@ -79,6 +83,8 @@ int main() } else { + // TODO: need to handle instructions that treat r0 as 0 + std::println(f, "\t// {:x} {} {}", base - 4, insn.opcode->name, insn.op_str); switch (insn.opcode->id) { @@ -88,17 +94,44 @@ int main() break; case PPC_INST_ADDI: - std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 + {};", insn.operands[0], insn.operands[1], insn.operands[2]); + std::println(f, "\tctx.r{}.s64 = ctx.r{}.s64 + {};", insn.operands[0], insn.operands[1], static_cast(insn.operands[2])); break; case PPC_INST_ADDIC: + break; + case PPC_INST_ADDIS: + // TODO: validate the sign extend + std::println(f, "\tctx.r{}.s64 = ctx.r{}.s64 + {};", insn.operands[0], insn.operands[1], static_cast(insn.operands[2] << 16)); + break; + case PPC_INST_ADDZE: + break; + case PPC_INST_AND: + // TODO: . variant + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_ANDC: + // TODO: . variant + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & ~ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_ANDI: + // TODO: . variant + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & {};", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_ANDIS: + // TODO: . variant + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & {};", insn.operands[0], insn.operands[1], insn.operands[2] << 16); + break; + case PPC_INST_ATTN: + // undefined instruction + break; + case PPC_INST_B: case PPC_INST_BCTR: case PPC_INST_BCTRL: @@ -159,8 +192,15 @@ int main() case PPC_INST_CNTLZD: case PPC_INST_CNTLZW: case PPC_INST_DB16CYC: + case PPC_INST_DCBF: + // no op + break; + case PPC_INST_DCBT: + // no op + break; + case PPC_INST_DCBTST: case PPC_INST_DCBZ: case PPC_INST_DCBZL: @@ -168,7 +208,12 @@ int main() case PPC_INST_DIVDU: case PPC_INST_DIVW: case PPC_INST_DIVWU: + break; + case PPC_INST_EIEIO: + // no op + break; + case PPC_INST_EXTSB: case PPC_INST_EXTSH: case PPC_INST_EXTSW: @@ -201,10 +246,26 @@ int main() case PPC_INST_FSQRTS: case PPC_INST_FSUB: case PPC_INST_FSUBS: + break; + case PPC_INST_LBZ: + std::println(f, "\tctx.r{}.u64 = PPC_LOAD_U8({} + ctx.r{}.u32);", insn.operands[0], int32_t(insn.operands[1]), insn.operands[2]); + break; + case PPC_INST_LBZU: + std::println(f, "\tea = {} + ctx.r{}.u32;", int32_t(insn.operands[1]), insn.operands[2]); + std::println(f, "\tctx.r{}.u64 = PPC_LOAD_U8(ea);", insn.operands[0]); + std::println(f, "\tctx.r{}.u64 = ea;", insn.operands[2]); + break; + case PPC_INST_LBZX: + std::println(f, "\tctx.r{}.u64 = PPC_LOAD_U8(ctx.r{}.u32 + ctx.r{}.u32);", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_LD: + std::println(f, "\tctx.r{}.u64 = PPC_LOAD_U64({} + ctx.r{}.u32);", insn.operands[0], int32_t(insn.operands[1]), insn.operands[2]); + break; + case PPC_INST_LDARX: case PPC_INST_LDU: case PPC_INST_LDX: @@ -219,10 +280,15 @@ int main() break; case PPC_INST_LI: - std::println(f, "\tctx.r{}.u64 = {};", insn.operands[0], insn.operands[1]); + // TODO: validate the sign extend + std::println(f, "\tctx.r{}.s64 = {};", insn.operands[0], int32_t(insn.operands[1])); break; case PPC_INST_LIS: + // TODO: validate the sign extend + std::println(f, "\tctx.r{}.s64 = {};", insn.operands[0], int32_t(insn.operands[1] << 16)); + break; + case PPC_INST_LVEWX: case PPC_INST_LVEWX128: case PPC_INST_LVLX: @@ -237,7 +303,10 @@ int main() case PPC_INST_LWARX: case PPC_INST_LWAX: case PPC_INST_LWBRX: + break; + case PPC_INST_LWSYNC: + // no op break; case PPC_INST_LWZ: @@ -280,17 +349,54 @@ int main() case PPC_INST_MULHW: case PPC_INST_MULHWU: case PPC_INST_MULLD: + break; + case PPC_INST_MULLI: + std::println(f, "\tctx.r{}.s64 = ctx.r{}.s64 * {};", insn.operands[0], insn.operands[1], static_cast(insn.operands[2])); + break; + case PPC_INST_MULLW: + break; + case PPC_INST_NAND: + std::println(f, "\tctx.r{}.u64 = ~(ctx.r{}.u64 & ctx.r{}.u64);", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_NEG: + // TODO: . variant + std::println(f, "\tctx.r{}.s64 = -ctx.r{}.s64;", insn.operands[0], insn.operands[1]); + break; + case PPC_INST_NOP: + // no op + break; + case PPC_INST_NOR: + std::println(f, "\tctx.r{}.u64 = ~(ctx.r{}.u64 | ctx.r{}.u64);", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_NOT: + // TODO: . variant + std::println(f, "\tctx.r{}.u64 = ~ctx.r{}.u64;", insn.operands[0], insn.operands[1]); + break; + case PPC_INST_OR: + // TODO: . variant + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 | ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_ORC: + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 | ~ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_ORI: + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 | {}", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_ORIS: + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 | {}", insn.operands[0], insn.operands[1], insn.operands[2] << 16); + break; + case PPC_INST_RLDICL: case PPC_INST_RLDICR: case PPC_INST_RLDIMI: @@ -457,9 +563,19 @@ int main() case PPC_INST_VUPKLSH: case PPC_INST_VXOR: case PPC_INST_VXOR128: + break; + case PPC_INST_XOR: + // TODO: . variant + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 ^ ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_XORI: + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 ^ {};", insn.operands[0], insn.operands[1], insn.operands[2]); + break; + case PPC_INST_XORIS: + std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 ^ {};", insn.operands[0], insn.operands[1], insn.operands[2] << 16); break; } } diff --git a/PowerUtils/ppc_context.h b/PowerUtils/ppc_context.h index 538f38b..ca1aceb 100644 --- a/PowerUtils/ppc_context.h +++ b/PowerUtils/ppc_context.h @@ -9,10 +9,12 @@ #define _byteswap_uint64 __builtin_bswap64 #endif +#define PPC_LOAD_U8(x) *(uint8_t*)(base + (x)) #define PPC_LOAD_U16(x) _byteswap_ushort(*(uint16_t*)(base + (x))) #define PPC_LOAD_U32(x) _byteswap_ulong(*(uint32_t*)(base + (x))) #define PPC_LOAD_U64(x) _byteswap_uint64(*(uint64_t*)(base + (x))) +#define PPC_STORE_U8(x, y) *(uint8_t*)(base + (x)) = (y) #define PPC_STORE_U16(x, y) *(uint16_t*)(base + (x)) = _byteswap_ushort(y) #define PPC_STORE_U32(x, y) *(uint32_t*)(base + (x)) = _byteswap_ulong(y) #define PPC_STORE_U64(x, y) *(uint64_t*)(base + (x)) = _byteswap_uint64(y) @@ -34,6 +36,14 @@ struct PPCRegister }; }; +struct PPCCRRegister +{ + uint8_t lt; + uint8_t gt; + uint8_t eq; + uint8_t so; +}; + typedef float float128[4]; struct PPCContext @@ -45,16 +55,16 @@ struct PPCContext { struct { - uint32_t cr0; - uint32_t cr1; - uint32_t cr2; - uint32_t cr3; - uint32_t cr4; - uint32_t cr5; - uint32_t cr6; - uint32_t cr7; + PPCCRRegister cr0; + PPCCRRegister cr1; + PPCCRRegister cr2; + PPCCRRegister cr3; + PPCCRRegister cr4; + PPCCRRegister cr5; + PPCCRRegister cr6; + PPCCRRegister cr7; }; - uint32_t cr[8]; + PPCCRRegister cr[8]; }; union