From 894a1192fda26dd49bce3e6036f8d3f6a2b62949 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 10:00:59 +0000 Subject: [PATCH] C -> O for ppc64; impl NZCV? Signed-off-by: lizzie --- externals/powah/powah_emit.hpp | 13 ++- externals/powah/powah_gen_base.hpp | 92 +++++++++---------- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 50 +++++++++- .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 6 +- .../ppc64/emit_ppc64_data_processing.cpp | 55 +++++++---- 5 files changed, 141 insertions(+), 75 deletions(-) diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index e4fdc3bf65..3e2c1268a8 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -31,6 +31,7 @@ enum class Cond : uint8_t { struct GPR { uint32_t index; }; struct FPR { uint32_t index; }; +struct VPR { uint32_t index; }; struct CPR { uint32_t index; }; struct Label { uint32_t index; }; @@ -110,6 +111,10 @@ constexpr inline CPR CR5{20}; constexpr inline CPR CR6{24}; constexpr inline CPR CR7{28}; +constexpr uint32_t XER_SO = 32; +constexpr uint32_t XER_OV = 33; +constexpr uint32_t XER_CA = 34; + enum class RelocKind : uint8_t { FormB, FormI, @@ -298,10 +303,10 @@ struct Context { std::abort(); } void emit_XFX(uint32_t op, GPR const rt, uint32_t spr) { - (void)op; - (void)rt; - (void)spr; - std::abort(); + base[offset++] = (op | + (rt.index & 0x1f) << 21 + | ((spr & 0xff) << 12) + ); } void emit_SC(uint32_t op, uint32_t lev) { (void)op; diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index e7260a3d75..9ef5d1dc1f 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -1,29 +1,29 @@ // this file is autogenerated DO NOT MODIFY #pragma once void ADD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, false, false); } -void ADDC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, true, false); } +void ADDO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, true, false); } void ADD_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, false, true); } -void ADDC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, true, true); } -//void ADDC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, false, false); } -void ADDCC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, true, false); } -//void ADDC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, false, true); } -void ADDCC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, true, true); } +void ADDO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000214, rt, ra, rb, true, true); } +void ADDC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, false, false); } +void ADDCO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, true, false); } +void ADDC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, false, true); } +void ADDCO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000014, rt, ra, rb, true, true); } void ADDE(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000114, rt, ra, rb, false, false); } -void ADDEC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000114, rt, ra, rb, true, false); } +void ADDEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000114, rt, ra, rb, true, false); } void ADDE_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000114, rt, ra, rb, false, true); } -void ADDEC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000114, rt, ra, rb, true, true); } +void ADDEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000114, rt, ra, rb, true, true); } void ADDI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x38000000, rt, ra, d); } void ADDIC(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x30000000, rt, ra, d); } void ADDIC_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x34000000, rt, ra, d); } void ADDIS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x3c000000, rt, ra, d); } void ADDME(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d4, rt, ra, rb, false, false); } -void ADDMEC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d4, rt, ra, rb, true, false); } +void ADDMEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d4, rt, ra, rb, true, false); } void ADDME_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d4, rt, ra, rb, false, true); } -void ADDMEC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d4, rt, ra, rb, true, true); } +void ADDMEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d4, rt, ra, rb, true, true); } void ADDZE(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, ra, rb, false, false); } -void ADDZEC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, ra, rb, true, false); } +void ADDZEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, ra, rb, true, false); } void ADDZE_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, ra, rb, false, true); } -void ADDZEC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, ra, rb, true, true); } +void ADDZEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, ra, rb, true, true); } void AND(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000038, rt, ra, rb, false); } void AND_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000038, rt, ra, rb, true); } void ANDC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, rt, ra, rb, false); } @@ -101,21 +101,21 @@ void DCBTST_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ec, rt, void DCBZ(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ec, rt, ra, rb, false); } void DCBZ_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ec, rt, ra, rb, true); } void DIVD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, false, false); } -void DIVDC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, true, false); } +void DIVDO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, true, false); } void DIVD_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, false, true); } -void DIVDC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, true, true); } +void DIVDO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, true, true); } void DIVDU(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000392, rt, ra, rb, false, false); } -void DIVDUC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000392, rt, ra, rb, true, false); } +void DIVDUO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000392, rt, ra, rb, true, false); } void DIVDU_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000392, rt, ra, rb, false, true); } -void DIVDUC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000392, rt, ra, rb, true, true); } +void DIVDUO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000392, rt, ra, rb, true, true); } void DIVW(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d6, rt, ra, rb, false, false); } -void DIVWC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d6, rt, ra, rb, true, false); } +void DIVWO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d6, rt, ra, rb, true, false); } void DIVW_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d6, rt, ra, rb, false, true); } -void DIVWC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d6, rt, ra, rb, true, true); } +void DIVWO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d6, rt, ra, rb, true, true); } void DIVWU(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, ra, rb, false, false); } -void DIVWUC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, ra, rb, true, false); } +void DIVWUO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, ra, rb, true, false); } void DIVWU_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, ra, rb, false, true); } -void DIVWUC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, ra, rb, true, true); } +void DIVWUO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, ra, rb, true, true); } void ECIWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00026c, rt, ra, rb, false); } void ECIWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00026c, rt, ra, rb, true); } void ECOWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036c, rt, ra, rb, false); } @@ -293,36 +293,36 @@ void MTSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001a4, rt, ra void MTSRIN(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001e4, rt, ra, rb, false); } void MTSRIN_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001e4, rt, ra, rb, true); } void MULHD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, false, false); } -void MULHDC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, true, false); } +void MULHDO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, true, false); } void MULHD_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, false, true); } -void MULHDC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, true, true); } +void MULHDO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, true, true); } void MULHDU(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000012, rt, ra, rb, false, false); } -void MULHDUC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000012, rt, ra, rb, true, false); } +void MULHDUO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000012, rt, ra, rb, true, false); } void MULHDU_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000012, rt, ra, rb, false, true); } -void MULHDUC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000012, rt, ra, rb, true, true); } +void MULHDUO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000012, rt, ra, rb, true, true); } void MULHW(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000096, rt, ra, rb, false, false); } -void MULHWC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000096, rt, ra, rb, true, false); } +void MULHWO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000096, rt, ra, rb, true, false); } void MULHW_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000096, rt, ra, rb, false, true); } -void MULHWC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000096, rt, ra, rb, true, true); } +void MULHWO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000096, rt, ra, rb, true, true); } void MULHWU(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000016, rt, ra, rb, false, false); } -void MULHWUC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000016, rt, ra, rb, true, false); } +void MULHWUO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000016, rt, ra, rb, true, false); } void MULHWU_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000016, rt, ra, rb, false, true); } -void MULHWUC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000016, rt, ra, rb, true, true); } +void MULHWUO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000016, rt, ra, rb, true, true); } void MULLD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d2, rt, ra, rb, false, false); } -void MULLDC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d2, rt, ra, rb, true, false); } +void MULLDO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d2, rt, ra, rb, true, false); } void MULLD_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d2, rt, ra, rb, false, true); } -void MULLDC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d2, rt, ra, rb, true, true); } +void MULLDO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d2, rt, ra, rb, true, true); } void MULLI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x1c000000, rt, ra, d); } void MULLW(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, ra, rb, false, false); } -void MULLWC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, ra, rb, true, false); } +void MULLWO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, ra, rb, true, false); } void MULLW_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, ra, rb, false, true); } -void MULLWC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, ra, rb, true, true); } +void MULLWO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, ra, rb, true, true); } void NAND(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003b8, rt, ra, rb, false); } void NAND_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003b8, rt, ra, rb, true); } void NEG(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, false, false); } -void NEGC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, true, false); } +void NEGO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, true, false); } void NEG_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, false, true); } -void NEGC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, true, true); } +void NEGO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, true, true); } void NOR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000f8, rt, ra, rb, false); } void NOR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000f8, rt, ra, rb, true); } void OR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000378, rt, ra, rb, false); } @@ -426,26 +426,26 @@ void STWUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016e, rt, r void STWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012e, rt, ra, rb, false); } void STWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012e, rt, ra, rb, true); } void SUBF(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, false, false); } -void SUBFC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, true, false); } +void SUBFO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, true, false); } void SUBF_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, false, true); } -void SUBFC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, true, true); } -//void SUBFC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, false, false); } -void SUBFCC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, true, false); } -//void SUBFC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, false, true); } -void SUBFCC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, true, true); } +void SUBFO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, true, true); } +void SUBFC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, false, false); } +void SUBFCO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, true, false); } +void SUBFC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, false, true); } +void SUBFCO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000010, rt, ra, rb, true, true); } void SUBFE(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000110, rt, ra, rb, false, false); } -void SUBFEC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000110, rt, ra, rb, true, false); } +void SUBFEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000110, rt, ra, rb, true, false); } void SUBFE_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000110, rt, ra, rb, false, true); } -void SUBFEC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000110, rt, ra, rb, true, true); } +void SUBFEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000110, rt, ra, rb, true, true); } void SUBFIC(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x20000000, rt, ra, d); } void SUBFME(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d0, rt, ra, rb, false, false); } -void SUBFMEC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d0, rt, ra, rb, true, false); } +void SUBFMEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d0, rt, ra, rb, true, false); } void SUBFME_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d0, rt, ra, rb, false, true); } -void SUBFMEC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d0, rt, ra, rb, true, true); } +void SUBFMEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d0, rt, ra, rb, true, true); } void SUBFZE(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, ra, rb, false, false); } -void SUBFZEC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, ra, rb, true, false); } +void SUBFZEO(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, ra, rb, true, false); } void SUBFZE_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, ra, rb, false, true); } -void SUBFZEC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, ra, rb, true, true); } +void SUBFZEO_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, ra, rb, true, true); } void SYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ac, rt, ra, rb, false); } void SYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ac, rt, ra, rb, true); } void TD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000088, rt, ra, rb, false); } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 5c8902924e..25db5e641d 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -62,8 +62,53 @@ void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { } template<> -void EmitIR(powah::Context&, EmitContext& ctx, IR::Inst* inst) { - ASSERT(false && "unimp"); +void EmitIR(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 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp index e2d9cb6ce7..195bca017f 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -38,7 +38,8 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(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(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"); 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 39cebc6339..cef9a7b06d 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 @@ -4,6 +4,7 @@ #include #include +#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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const result = ctx.reg_alloc.ScratchGpr();