From 2c57681ca1b11a2b55203fdd6f7177fde97b224a Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 20:02:52 +0000 Subject: [PATCH 01/49] fix stuff? --- externals/CMakeLists.txt | 3 + externals/powah/CMakeLists.txt | 9 + externals/powah/data2code.c | 273 +++++++++++ externals/powah/powah_emit.hpp | 339 +++++++++++++ externals/powah/powah_gen_base.hpp | 464 ++++++++++++++++++ externals/powah/tests.cpp | 139 ++++++ src/CMakeLists.txt | 2 +- src/core/CMakeLists.txt | 2 +- src/dynarmic/src/dynarmic/CMakeLists.txt | 28 +- .../src/dynarmic/backend/exception_handler.h | 11 +- .../backend/exception_handler_generic.cpp | 21 +- .../backend/exception_handler_posix.cpp | 6 + 12 files changed, 1280 insertions(+), 17 deletions(-) create mode 100644 externals/powah/CMakeLists.txt create mode 100644 externals/powah/data2code.c create mode 100644 externals/powah/powah_emit.hpp create mode 100644 externals/powah/powah_gen_base.hpp create mode 100644 externals/powah/tests.cpp diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 0682f643e2..d243569b52 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -249,6 +249,9 @@ endif() # TZDB (Time Zone Database) add_subdirectory(nx_tzdb) +# PowerPC emitter +add_subdirectory(powah) + add_library(tz tz/tz/tz.cpp) target_include_directories(tz PUBLIC ./tz) diff --git a/externals/powah/CMakeLists.txt b/externals/powah/CMakeLists.txt new file mode 100644 index 0000000000..68587ae10d --- /dev/null +++ b/externals/powah/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +add_library(powah INTERFACE) +target_include_directories(powah INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) + +add_executable(powah_tests tests.cpp) +create_target_directory_groups(powah_tests) +target_link_libraries(powah_tests PRIVATE Catch2::Catch2WithMain) diff --git a/externals/powah/data2code.c b/externals/powah/data2code.c new file mode 100644 index 0000000000..2f276b29c7 --- /dev/null +++ b/externals/powah/data2code.c @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include +int main(int argc, char *argv[]) { + printf( + "// this file is autogenerated DO NOT MODIFY\n" + "#pragma once\n" + ); + FILE* fp = fopen(argv[1], "rt"); + if (fp) { + char line[80]; + while (fgets(line, sizeof line, fp) != NULL) { + bool with_o = strstr(line, "[o]"), with_d = strstr(line, "[.]"); + char* p = strchr(line, '\n'), *name = strchr(line, ','), *mem = line; + if (p) *p = '\0'; + if (name) { + *name++ = '\0'; + char *form = strchr(name, ','); + if (form) { + *form++ = '\0'; + char *opc = strchr(form, ','); + if (opc) { + *opc++ = '\0'; + char *sec = strchr(opc, ','); + if (sec) { + struct b_info { const char *s; int o; } infos[] = { + {"",1}, + {"LT",1}, + {"LE",2}, + {"NG",2}, + {"EQ",3}, + {"GE",1}, + {"NL",1}, + {"GT",2}, + {"NE",3}, + {"SO",4}, + {"UN",4}, + {"NS",4}, + {"NU",4}, + }; + + if (strchr(mem, '[') != NULL) *strchr(mem, '[') = '\0'; + if (strchr(mem, '.') != NULL) *strchr(mem, '.') = '_'; + *sec++ = '\0'; + for (int i = 0; i < strlen(mem); ++i) + mem[i] = toupper(mem[i]); + int i_opcode = atoi(opc); + int i_extopc = atoi(sec); + //printf("// %s\n", mem); + if (!strcmp(form, "XO")) { + if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) + printf("//"); + printf( + "void %s(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, false, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sC(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, true, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) + printf("//"); + printf( + "void %s_(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, false, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sC_(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, true, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else if (!strcmp(form, "X")) { + if (!strcmp(mem, "CMPL") + || !strcmp(mem, "CMP")) { + printf( + "void %s(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, rb, false); " + "}\n" + , mem, form, i_opcode << 26); + } else if (strcmp(mem, "CNTLZD") == 0 || strcmp(mem, "CNTLZW") == 0) { + printf( + "void %s(GPR const rt, GPR const ra) {" + " emit_%s(0x%08x, rt, ra, R0, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rt, GPR const ra) {" + " emit_%s(0x%08x, rt, ra, R0, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else { + printf( + "void %s(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } + } else if (!strcmp(form, "I")) { + printf( + "void %s(Label const& i) {" + " emit_reloc_%s(0x%08x, i); " + "}\n" + , mem, form, i_opcode << 26); + printf( + "void %sL(Label const& i) {" + " emit_reloc_%s(0x%08x, i); " + "}\n" + , mem, form, i_opcode << 26); + } else if (!strcmp(form, "B")) { + for (int i = 0; i < 12; ++i) { + printf( + "void %s%s(CPR const cr, Label const& i) {" + " emit_reloc_%s(0x%08x, cr.index + %i, i, false); " + "}\n" + , mem, infos[i].s, form, i_opcode << 26, infos[i].o); + printf( + "void %s%sL(CPR const cr, Label const& i) {" + " emit_reloc_%s(0x%08x, cr.index + %i, i, true); " + "}\n" + , mem, infos[i].s, form, i_opcode << 26, infos[i].o); + if (!strcmp(mem, "BC")) mem[1] = '\0'; + } + } else if (!strcmp(form, "D")) { + if (!strcmp(mem, "CMPLI") + || !strcmp(mem, "CMPI")) { + printf( + "void %s(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) {" + " emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, d); " + "}\n" + , mem, form, i_opcode << 26); + } else { + printf( + "void %s(GPR const rt, GPR const ra, uint32_t d) {" + " emit_%s(0x%08x, rt, ra, d); " + "}\n" + , mem, form, i_opcode << 26); + } + } else if (!strcmp(form, "SC")) { + printf( + "void %s(uint32_t lev) {" + " emit_%s(0x%08x, lev); " + "}\n" + , mem, form, i_opcode << 26); + } else if (!strcmp(form, "DS")) { + printf( + "void %s(GPR const rt, GPR const ra, uint32_t d) {" + " emit_%s(0x%08x, rt, ra, d); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else if (!strcmp(form, "XS")) { + printf( + "void %s(GPR const rt, GPR const ra, uint32_t sh) {" + " emit_%s(0x%08x, rt, ra, sh, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rt, GPR const ra, uint32_t sh) {" + " emit_%s(0x%08x, rt, ra, sh, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else if (!strcmp(form, "XL")) { + if (mem[0] == 'B') { + printf( + "void %s(GPR const bt, CPR const ba, GPR const bb) {" + " emit_%s(0x%08x, bt.index, ba.index, bb.index, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sL(GPR const bt, CPR const ba, GPR const bb) {" + " emit_%s(0x%08x, bt.index, ba.index, bb.index, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s(GPR const bt, Cond const ba, GPR const bb) {" + " emit_%s(0x%08x, bt.index, cond2offset(ba), bb.index, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sL(GPR const bt, Cond const ba, GPR const bb) {" + " emit_%s(0x%08x, bt.index, cond2offset(ba), bb.index, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else { + printf( + "void %s(CPR const bt, CPR const ba, CPR const bb) {" + " emit_%s(0x%08x, bt.index, ba.index, bb.index, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sL(CPR const bt, CPR const ba, CPR const bb) {" + " emit_%s(0x%08x, bt.index, ba.index, bb.index, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } + } else if (!strcmp(form, "M")) { + printf( + "void %s(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" + " emit_%s(0x%08x, rs, ra, sh, mb, me, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" + " emit_%s(0x%08x, rs, ra, sh, mb, me, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else if (!strcmp(form, "MD")) { + printf( + "void %s(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) {" + " emit_%s(0x%08x, rs, ra, mb, sh, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 2)); + printf( + "void %s_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) {" + " emit_%s(0x%08x, rs, ra, mb, sh, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 2)); + } else if (!strcmp(form, "MDS")) { + printf( + "void %s(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) {" + " emit_%s(0x%08x, rs, ra, rb, mb, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) {" + " emit_%s(0x%08x, rs, ra, rb, mb, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else if (!strcmp(form, "A")) { + printf( + "void %s(FPR const frt, FPR const fra, FPR const frb, FPR const frc) {" + " emit_%s(0x%08x, frt, fra, frb, frc, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) {" + " emit_%s(0x%08x, frt, fra, frb, frc, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else if (!strcmp(form, "XFX")) { + printf( + "void %s(GPR const rt, uint32_t spr) {" + " emit_%s(0x%08x, rt, spr); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else { + printf( + "void %s() {" + " emit_%s(0x%08x); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } + } + } + } + } + //printf("%s\n", line); + } + fclose(fp); + return 0; + } + return 1; +} diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp new file mode 100644 index 0000000000..3a28910a75 --- /dev/null +++ b/externals/powah/powah_emit.hpp @@ -0,0 +1,339 @@ +#pragma once + +#undef NDEBUG + +#include +#include +#include +#include +#include +#include + +//#ifndef __cpp_lib_unreachable +namespace std { +[[noreturn]] inline void unreachable() { +#if defined(_MSC_VER) && !defined(__clang__) // MSVC + __assume(false); +#else // GCC, Clang + __builtin_unreachable(); +#endif +} +} +//#endif + +namespace powah { + +// Symbolic conditions +enum class Cond : uint8_t { + LT, LE, NG, EQ, GE, NL, GT, NE, SO, UN, NS, NU +}; + +struct GPR { uint32_t index; }; +struct FPR { uint32_t index; }; +struct CPR { uint32_t index; }; +struct Label { uint32_t index; }; + +constexpr inline GPR R0{0}; +constexpr inline GPR R1{1}; +constexpr inline GPR R2{2}; +constexpr inline GPR R3{3}; +constexpr inline GPR R4{4}; +constexpr inline GPR R5{5}; +constexpr inline GPR R6{6}; +constexpr inline GPR R7{7}; +constexpr inline GPR R8{8}; +constexpr inline GPR R9{9}; +constexpr inline GPR R10{10}; +constexpr inline GPR R11{11}; +constexpr inline GPR R12{12}; +constexpr inline GPR R13{13}; +constexpr inline GPR R14{14}; +constexpr inline GPR R15{15}; +constexpr inline GPR R16{16}; +constexpr inline GPR R17{17}; +constexpr inline GPR R18{18}; +constexpr inline GPR R19{19}; +constexpr inline GPR R20{20}; +constexpr inline GPR R21{21}; +constexpr inline GPR R22{22}; +constexpr inline GPR R23{23}; +constexpr inline GPR R24{24}; +constexpr inline GPR R25{25}; +constexpr inline GPR R26{26}; +constexpr inline GPR R27{27}; +constexpr inline GPR R28{28}; +constexpr inline GPR R29{29}; +constexpr inline GPR R30{30}; +constexpr inline GPR R31{31}; + +constexpr inline FPR FR0{0}; +constexpr inline FPR FR1{1}; +constexpr inline FPR FR2{2}; +constexpr inline FPR FR3{3}; +constexpr inline FPR FR4{4}; +constexpr inline FPR FR5{5}; +constexpr inline FPR FR6{6}; +constexpr inline FPR FR7{7}; +constexpr inline FPR FR8{8}; +constexpr inline FPR FR9{9}; +constexpr inline FPR FR10{10}; +constexpr inline FPR FR11{11}; +constexpr inline FPR FR12{12}; +constexpr inline FPR FR13{13}; +constexpr inline FPR FR14{14}; +constexpr inline FPR FR15{15}; +constexpr inline FPR FR16{16}; +constexpr inline FPR FR17{17}; +constexpr inline FPR FR18{18}; +constexpr inline FPR FR19{19}; +constexpr inline FPR FR20{20}; +constexpr inline FPR FR21{21}; +constexpr inline FPR FR22{22}; +constexpr inline FPR FR23{23}; +constexpr inline FPR FR24{24}; +constexpr inline FPR FR25{25}; +constexpr inline FPR FR26{26}; +constexpr inline FPR FR27{27}; +constexpr inline FPR FR28{28}; +constexpr inline FPR FR29{29}; +constexpr inline FPR FR30{30}; +constexpr inline FPR FR31{31}; + +// They call it CPR because when programmers see this code they- +constexpr inline CPR CR0{0}; +constexpr inline CPR CR1{4}; +constexpr inline CPR CR2{8}; +constexpr inline CPR CR3{12}; +constexpr inline CPR CR4{16}; +constexpr inline CPR CR5{20}; +constexpr inline CPR CR6{24}; +constexpr inline CPR CR7{28}; + +struct Context { + Context(void* ptr, size_t size) + : base{reinterpret_cast(ptr)} + , offset{0} + , size{uint32_t(size)} { + + } + ~Context() = default; + + std::vector labels; + + Label DefineLabel() { + labels.push_back(0); + return Label{ uint32_t(labels.size()) }; + } + + void LABEL(Label l) { + assert(labels[l.index] == 0); + labels[l.index] = offset; + } + + static constexpr uint32_t cond2offset(Cond c) noexcept { + switch (c) { + case Cond::LT: return 1; + case Cond::LE: return 2; + case Cond::NG: return 2; + case Cond::EQ: return 3; + case Cond::GE: return 1; + case Cond::NL: return 1; + case Cond::GT: return 2; + case Cond::NE: return 3; + case Cond::SO: return 4; + case Cond::UN: return 4; + case Cond::NS: return 4; + case Cond::NU: return 4; + default: return 0; //hopefully icc isn't stupid + } + } + + uint32_t bitExt(uint32_t value, uint32_t offs, uint32_t n) { + uint32_t mask = (1UL << (n + 1)) - 1; + return (value & mask) << (32 - (n + offs)); + } + void emit_XO(uint32_t op, GPR const rt, GPR const ra, GPR const rb, bool oe, bool rc) { + (void)op; + (void)rt; + (void)ra; + (void)rb; + (void)oe; + (void)rc; + std::abort(); + } + void emit_D(uint32_t op, GPR const rt, GPR const ra, uint32_t d) { + base[offset++] = __bswap32(op | + (op == 0x74000000 + ? (bitExt(ra.index, 6, 5) | bitExt(rt.index, 11, 5)) + : (bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5))) + | (d & 0xffff) + ); + } + void emit_X(uint32_t op, GPR const ra, GPR const rt, GPR const rb, bool rc) { + base[offset++] = __bswap32(op | + bitExt(rt.index, 6, 5) + | bitExt(ra.index, 11, 5) + | bitExt(rb.index, 16, 5) + | bitExt(rc, 31, 1) + ); + } + void emit_XS(uint32_t op, GPR const rt, GPR const ra, uint32_t sh, bool rc) { + base[offset++] = __bswap32(op | + bitExt(rt.index, 6, 5) + | bitExt(ra.index, 11, 5) + | bitExt(sh, 16, 5) + | bitExt(sh >> 5, 30, 1) + | bitExt(rc, 31, 1) + ); + } + void emit_reloc_I(uint32_t op, Label const& l) { + (void)op; + (void)l; + std::abort(); + } + void emit_reloc_B(uint32_t op, uint32_t cri, Label const& l, bool lk) { + (void)op; + (void)cri; + (void)l; + (void)lk; + std::abort(); + } + void emit_XL(uint32_t op, uint32_t bt, uint32_t ba, uint32_t bb, bool lk) { + base[offset++] = __bswap32(op | + bitExt(bt, 6, 5) + | bitExt(ba, 11, 5) + | bitExt(bb, 16, 5) + | bitExt(lk, 31, 1) + ); + } + void emit_A(uint32_t op, FPR const frt, FPR const fra, FPR const frb, FPR const frc, bool rc) { + base[offset++] = __bswap32(op | + bitExt(frt.index, 6, 5) + | bitExt(fra.index, 11, 5) + | bitExt(frb.index, 16, 5) + | bitExt(frc.index, 21, 5) + | bitExt(rc, 31, 1) + ); + } + void emit_DS(uint32_t op, GPR const rt, GPR const ra, uint32_t d) { + //assert(d & 0x03 == 0); + base[offset++] = __bswap32(op | + bitExt(rt.index, 6, 5) + | bitExt(ra.index, 11, 5) + | bitExt(d >> 2, 16, 14) + ); + } + void emit_M(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me, bool rc) { + (void)op; + (void)rs; + (void)ra; + (void)sh; + (void)mb; + (void)me; + (void)rc; + std::abort(); + } + void emit_MD(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) { + assert(mb <= 0x3f); + base[offset++] = __bswap32(op | + bitExt(ra.index, 6, 5) + | bitExt(rs.index, 11, 5) + | bitExt(rb.index, 16, 5) + | ((mb & 0x1f) << 6) | (mb & 0x20) + | bitExt(rc, 31, 1) + ); + } + void emit_MD(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, bool rc) { + assert(sh <= 0x3f && mb <= 0x3f); + base[offset++] = __bswap32(op | + bitExt(ra.index, 6, 5) + | bitExt(rs.index, 11, 5) + | ((mb & 0x1f) << 6) | (mb & 0x20) + | ((sh & 0x1f) << 11) | ((sh >> 4) & 0x02) + | bitExt(rc, 31, 1) + ); + } + void emit_MDS(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) { + base[offset++] = __bswap32(op | + bitExt(ra.index, 6, 5) + | bitExt(rs.index, 11, 5) + | bitExt(rb.index, 16, 5) + | ((mb & 0x1f) << 6) | (mb & 0x20) + | bitExt(rc, 31, 1) + ); + } + void emit_XFL(uint32_t op) { + (void)op; + std::abort(); + } + void emit_XFX(uint32_t op, GPR const rt, uint32_t spr) { + (void)op; + (void)rt; + (void)spr; + std::abort(); + } + void emit_SC(uint32_t op, uint32_t lev) { + (void)op; + (void)lev; + std::abort(); + } + + // Extended Memmonics, hand coded :) + void MR(GPR const ra, GPR const rs) { OR(ra, rs, rs); } + + void ROTLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, n, 0); } + void ROTRDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 64 - n, 0); } + + void ROTLWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, n, 0, 31); } + void ROTRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 32 - n, 0, 31); } + + void EXTLDI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLDICR(ra, rs, b, n - 1); } + void SLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICR(ra, rs, n, 63 - n); } + void CLRLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 0, n); } + + void EXTRDI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLDICL(ra, rs, b + n, 64 - n); } + void SRDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 64 - n, n); } + void CLLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICR(ra, rs, 0, n); } + void CLRSLDI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLDICR(ra, rs, n, b - n); } + + void EXTLWI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLWINM(ra, rs, b, 0, n - 1); } + void SRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 32 - n, n, 31); } + void CLRRWI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLWINM(ra, rs, 0, 0, 31 - n); } + + void CRSET(CPR const bx) { CREQV(bx, bx, bx); } + void CRCLR(CPR const bx) { CRXOR(bx, bx, bx); } + void CRMOVE(CPR const bx, CPR const by) { CROR(bx, by, by); } + void CRNOT(CPR const bx, CPR const by) { CRNOR(bx, by, by); } + + void CMPLDI(GPR const rx, uint32_t v) { CMPLI(0, 1, rx, v); } + void CMPLWI(GPR const rx, uint32_t v) { CMPLI(0, 0, rx, v); } + void CMPLD(GPR const rx, GPR const ry) { CMPL(0, 1, rx, ry); } + void CMPLW(GPR const rx, GPR const ry) { CMPL(0, 0, rx, ry); } + + void CMPLDI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index / 4, 1, rx, v); } + void CMPLWI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index / 4, 0, rx, v); } + void CMPLD(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index / 4, 1, rx, ry); } + void CMPLW(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index / 4, 0, rx, ry); } + + void CMPWI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 0, rx, si); } + void CMPW(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 0, rx, ry); } + void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 1, rx, si); } + void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 1, rx, ry); } + + // TODO: PowerPC 11 stuff + void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) { + std::unreachable(); + } + void ISELLT(GPR const rd, GPR const ra, GPR const rb) { ISEL(rd, ra, rb, 0); } + void ISELGT(GPR const rd, GPR const ra, GPR const rb) { ISEL(rd, ra, rb, 1); } + void ISELEQ(GPR const rd, GPR const ra, GPR const rb) { ISEL(rd, ra, rb, 2); } + + // Rawly pasted because fuck you +#include "powah_gen_base.hpp" + + uint32_t* base = nullptr; + uint32_t offset = 0; + uint32_t size = 0; +}; + +} diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp new file mode 100644 index 0000000000..cd1b7bc17b --- /dev/null +++ b/externals/powah/powah_gen_base.hpp @@ -0,0 +1,464 @@ +// 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 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 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 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 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 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 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 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 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); } +void ANDC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, rt, ra, rb, true); } +void ANDI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x70000000, rt, ra, d); } +void ANDIS_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x74000000, rt, ra, d); } +void B(Label const& i) { emit_reloc_I(0x48000000, i); } +void BL(Label const& i) { emit_reloc_I(0x48000000, i); } +void BC(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } +void BCL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } +void BLT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } +void BLTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } +void BLE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); } +void BLEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); } +void BNG(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); } +void BNGL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); } +void BEQ(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, false); } +void BEQL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, true); } +void BGE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } +void BGEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } +void BNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } +void BNLL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } +void BGT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); } +void BGTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); } +void BNE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, false); } +void BNEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, true); } +void BSO(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); } +void BSOL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); } +void BUN(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); } +void BUNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); } +void BNS(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); } +void BNSL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); } +void BCCTR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, ba.index, bb.index, false); } +void BCCTRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, ba.index, bb.index, true); } +void BCCTR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, cond2offset(ba), bb.index, false); } +void BCCTRL(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, cond2offset(ba), bb.index, true); } +void BCLR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, ba.index, bb.index, false); } +void BCLRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, ba.index, bb.index, true); } +void BCLR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, false); } +void BCLRL(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, true); } +void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); } +void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, GPR{(bf << 2) | l}, ra, d); } +void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); } +void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, GPR{(bf << 2) | l}, ra, d); } +void CNTLZD(GPR const rt, GPR const ra) { emit_X(0x7c000074, rt, ra, R0, false); } +void CNTLZD_(GPR const rt, GPR const ra) { emit_X(0x7c000074, rt, ra, R0, true); } +void CNTLZW(GPR const rt, GPR const ra) { emit_X(0x7c000034, rt, ra, R0, false); } +void CNTLZW_(GPR const rt, GPR const ra) { emit_X(0x7c000034, rt, ra, R0, true); } +void CRAND(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000202, bt.index, ba.index, bb.index, false); } +void CRANDL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000202, bt.index, ba.index, bb.index, true); } +void CRANDC(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000102, bt.index, ba.index, bb.index, false); } +void CRANDCL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000102, bt.index, ba.index, bb.index, true); } +void CREQV(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000242, bt.index, ba.index, bb.index, false); } +void CREQVL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000242, bt.index, ba.index, bb.index, true); } +void CRNAND(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c0001c2, bt.index, ba.index, bb.index, false); } +void CRNANDL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c0001c2, bt.index, ba.index, bb.index, true); } +void CRNOR(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000042, bt.index, ba.index, bb.index, false); } +void CRNORL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000042, bt.index, ba.index, bb.index, true); } +void CROR(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000382, bt.index, ba.index, bb.index, false); } +void CRORL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000382, bt.index, ba.index, bb.index, true); } +void CRORC(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000342, bt.index, ba.index, bb.index, false); } +void CRORCL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000342, bt.index, ba.index, bb.index, true); } +void CRXOR(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000182, bt.index, ba.index, bb.index, false); } +void CRXORL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000182, bt.index, ba.index, bb.index, true); } +void DCBF(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ac, rt, ra, rb, false); } +void DCBF_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ac, rt, ra, rb, true); } +void DCBI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003ac, rt, ra, rb, false); } +void DCBI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003ac, rt, ra, rb, true); } +void DCBST(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006c, rt, ra, rb, false); } +void DCBST_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006c, rt, ra, rb, true); } +void DCBT(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022c, rt, ra, rb, false); } +void DCBT_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022c, rt, ra, rb, true); } +void DCBTST(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ec, rt, ra, rb, false); } +void DCBTST_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ec, rt, ra, rb, true); } +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 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 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 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 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 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 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 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 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); } +void ECOWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036c, rt, ra, rb, true); } +void EIEIO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, rt, ra, rb, false); } +void EIEIO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, rt, ra, rb, true); } +void EQV(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, rt, ra, rb, false); } +void EQV_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, rt, ra, rb, true); } +void EXTSB(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000774, rt, ra, rb, false); } +void EXTSB_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000774, rt, ra, rb, true); } +void EXTSH(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, false, false); } +void EXTSHC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, true, false); } +void EXTSH_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, false, true); } +void EXTSHC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, true, true); } +void EXTSW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007b4, rt, ra, rb, false); } +void EXTSW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007b4, rt, ra, rb, true); } +void FABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, rt, ra, rb, false); } +void FABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, rt, ra, rb, true); } +void FADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002a, frt, fra, frb, frc, false); } +void FADD_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002a, frt, fra, frb, frc, true); } +void FADDS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00002a, frt, fra, frb, frc, false); } +void FADDS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00002a, frt, fra, frb, frc, true); } +void FCFID(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00069c, rt, ra, rb, false); } +void FCFID_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00069c, rt, ra, rb, true); } +void FCMPO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000040, rt, ra, rb, false); } +void FCMPO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000040, rt, ra, rb, true); } +void FCMPU(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc000000, bt.index, ba.index, bb.index, false); } +void FCMPUL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc000000, bt.index, ba.index, bb.index, true); } +void FCTID(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065c, rt, ra, rb, false); } +void FCTID_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065c, rt, ra, rb, true); } +void FCTIDZ(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065e, rt, ra, rb, false); } +void FCTIDZ_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065e, rt, ra, rb, true); } +void FCTIW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00001c, rt, ra, rb, false); } +void FCTIW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00001c, rt, ra, rb, true); } +void FCTIWZ(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc00001e, bt.index, ba.index, bb.index, false); } +void FCTIWZL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc00001e, bt.index, ba.index, bb.index, true); } +void FDIV(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000024, frt, fra, frb, frc, false); } +void FDIV_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000024, frt, fra, frb, frc, true); } +void FDIVS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000024, frt, fra, frb, frc, false); } +void FDIVS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000024, frt, fra, frb, frc, true); } +void FMADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003a, frt, fra, frb, frc, false); } +void FMADD_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003a, frt, fra, frb, frc, true); } +void FMADDS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003a, frt, fra, frb, frc, false); } +void FMADDS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003a, frt, fra, frb, frc, true); } +void FMR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000090, rt, ra, rb, false); } +void FMR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000090, rt, ra, rb, true); } +void FMSUB(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000038, frt, fra, frb, frc, false); } +void FMSUB_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000038, frt, fra, frb, frc, true); } +void FMSUBS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000038, frt, fra, frb, frc, false); } +void FMSUBS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000038, frt, fra, frb, frc, true); } +void FMUL(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000032, frt, fra, frb, frc, false); } +void FMUL_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000032, frt, fra, frb, frc, true); } +void FMULS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000032, frt, fra, frb, frc, false); } +void FMULS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000032, frt, fra, frb, frc, true); } +void FNABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000110, rt, ra, rb, false); } +void FNABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000110, rt, ra, rb, true); } +void FNEG(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000050, rt, ra, rb, false); } +void FNEG_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000050, rt, ra, rb, true); } +void FNMADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003e, frt, fra, frb, frc, false); } +void FNMADD_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003e, frt, fra, frb, frc, true); } +void FNMADDS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003e, frt, fra, frb, frc, false); } +void FNMADDS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003e, frt, fra, frb, frc, true); } +void FNMSUB(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003c, frt, fra, frb, frc, false); } +void FNMSUB_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003c, frt, fra, frb, frc, true); } +void FNMSUBS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003c, frt, fra, frb, frc, false); } +void FNMSUBS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003c, frt, fra, frb, frc, true); } +void FRES(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000030, frt, fra, frb, frc, false); } +void FRES_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000030, frt, fra, frb, frc, true); } +void FRSP(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000018, rt, ra, rb, false); } +void FRSP_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000018, rt, ra, rb, true); } +void FRSQRTE(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000034, frt, fra, frb, frc, false); } +void FRSQRTE_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000034, frt, fra, frb, frc, true); } +void FSEL(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002e, frt, fra, frb, frc, false); } +void FSEL_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002e, frt, fra, frb, frc, true); } +void FSUB(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000028, frt, fra, frb, frc, false); } +void FSUB_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000028, frt, fra, frb, frc, true); } +void FSUBS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000028, frt, fra, frb, frc, false); } +void FSUBS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000028, frt, fra, frb, frc, true); } +void ICBI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ac, rt, ra, rb, false); } +void ICBI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ac, rt, ra, rb, true); } +void ISYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c00012c, rt, ra, rb, false); } +void ISYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c00012c, rt, ra, rb, true); } +void LBZ(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x88000000, rt, ra, d); } +void LBZU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x8c000000, rt, ra, d); } +void LBZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ee, rt, ra, rb, false); } +void LBZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ee, rt, ra, rb, true); } +void LBZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, rt, ra, rb, false); } +void LBZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, rt, ra, rb, true); } +void LD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000000, rt, ra, d); } +void LDARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, rt, ra, rb, false); } +void LDARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, rt, ra, rb, true); } +void LDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000002, rt, ra, d); } +void LDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, rt, ra, rb, false); } +void LDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, rt, ra, rb, true); } +void LDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002a, rt, ra, rb, false); } +void LDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002a, rt, ra, rb, true); } +void LFD(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xc8000000, rt, ra, d); } +void LFDU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xcc000000, rt, ra, d); } +void LFDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ee, rt, ra, rb, false); } +void LFDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ee, rt, ra, rb, true); } +void LFDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ae, rt, ra, rb, false); } +void LFDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ae, rt, ra, rb, true); } +void LFS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xc0000000, rt, ra, d); } +void LFSU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xc4000000, rt, ra, d); } +void LFSUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046e, rt, ra, rb, false); } +void LFSUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046e, rt, ra, rb, true); } +void LFSX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042e, rt, ra, rb, false); } +void LFSX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042e, rt, ra, rb, true); } +void LHA(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xa8000000, rt, ra, d); } +void LHAU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xac000000, rt, ra, d); } +void LHAUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ee, rt, ra, rb, false); } +void LHAUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ee, rt, ra, rb, true); } +void LHAX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ae, rt, ra, rb, false); } +void LHAX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ae, rt, ra, rb, true); } +void LHBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00062c, rt, ra, rb, false); } +void LHBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00062c, rt, ra, rb, true); } +void LHZ(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xa0000000, rt, ra, d); } +void LHZU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xa4000000, rt, ra, d); } +void LHZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000296, rt, ra, rb, false); } +void LHZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000296, rt, ra, rb, true); } +void LHZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022e, rt, ra, rb, false); } +void LHZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022e, rt, ra, rb, true); } +void LMW(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xb8000000, rt, ra, d); } +void LSWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, rt, ra, rb, false); } +void LSWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, rt, ra, rb, true); } +void LSWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, rt, ra, rb, false); } +void LSWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, rt, ra, rb, true); } +void LWA(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000004, rt, ra, d); } +void LWARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, rt, ra, rb, false); } +void LWARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, rt, ra, rb, true); } +void LWAUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ea, rt, ra, rb, false); } +void LWAUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ea, rt, ra, rb, true); } +void LWAX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002aa, rt, ra, rb, false); } +void LWAX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002aa, rt, ra, rb, true); } +void LWBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042c, rt, ra, rb, false); } +void LWBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042c, rt, ra, rb, true); } +void LWZ(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x80000000, rt, ra, d); } +void LWZU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x84000000, rt, ra, d); } +void LWZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006e, rt, ra, rb, false); } +void LWZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006e, rt, ra, rb, true); } +void LWZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002e, rt, ra, rb, false); } +void LWZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002e, rt, ra, rb, true); } +void MCRF(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000000, bt.index, ba.index, bb.index, false); } +void MCRFL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000000, bt.index, ba.index, bb.index, true); } +void MCRFS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000080, rt, ra, rb, false); } +void MCRFS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000080, rt, ra, rb, true); } +void MCRXR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000400, rt, ra, rb, false); } +void MCRXR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000400, rt, ra, rb, true); } +void MFCR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000026, rt, ra, rb, false); } +void MFCR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000026, rt, ra, rb, true); } +void MFFS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00048e, rt, ra, rb, false); } +void MFFS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00048e, rt, ra, rb, true); } +void MFMSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a6, rt, ra, rb, false); } +void MFMSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a6, rt, ra, rb, true); } +void MFSPR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002a6, rt, ra, rb, false); } +void MFSPR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002a6, rt, ra, rb, true); } +void MFSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004a6, rt, ra, rb, false); } +void MFSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004a6, rt, ra, rb, true); } +void MFSRIN(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000526, rt, ra, rb, false); } +void MFSRIN_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000526, rt, ra, rb, true); } +void MTCRF(GPR const rt, uint32_t spr) { emit_XFX(0x7c000120, rt, spr); } +void MTFSB0(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00008c, rt, ra, rb, false); } +void MTFSB0_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00008c, rt, ra, rb, true); } +void MTFSB1(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00004c, rt, ra, rb, false); } +void MTFSB1_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00004c, rt, ra, rb, true); } +void MTFSF() { emit_XFL(0xfc00058e); } +void MTFSFI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00010c, rt, ra, rb, false); } +void MTFSFI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00010c, rt, ra, rb, true); } +void MTMSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000124, rt, ra, rb, false); } +void MTMSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000124, rt, ra, rb, true); } +void MTSPR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003a6, rt, ra, rb, false); } +void MTSPR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003a6, rt, ra, rb, true); } +void MTSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001a4, rt, ra, rb, false); } +void MTSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001a4, rt, ra, rb, true); } +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 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 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 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 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 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 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 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 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 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 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 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 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 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 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); } +void OR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000378, rt, ra, rb, true); } +void ORC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000338, rt, ra, rb, false); } +void ORC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000338, rt, ra, rb, true); } +void ORI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x60000000, rt, ra, d); } +void ORIS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x64000000, rt, ra, d); } +void RFI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c000064, rt, ra, rb, false); } +void RFI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c000064, rt, ra, rb, true); } +void RLDCL(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000010, rs, ra, rb, mb, false); } +void RLDCL_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000010, rs, ra, rb, mb, true); } +void RLDCR(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000012, rs, ra, rb, mb, false); } +void RLDCR_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000012, rs, ra, rb, mb, true); } +void RLDIC(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000008, rs, ra, mb, sh, false); } +void RLDIC_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000008, rs, ra, mb, sh, true); } +void RLDICL(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000000, rs, ra, mb, sh, false); } +void RLDICL_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000000, rs, ra, mb, sh, true); } +void RLDICR(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000004, rs, ra, mb, sh, false); } +void RLDICR_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000004, rs, ra, mb, sh, true); } +void RLDIMI(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x7800000c, rs, ra, mb, sh, false); } +void RLDIMI_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x7800000c, rs, ra, mb, sh, true); } +void RLWIMI(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, rs, ra, sh, mb, me, false); } +void RLWIMI_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, rs, ra, sh, mb, me, true); } +void RLWINM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, rs, ra, sh, mb, me, false); } +void RLWINM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, rs, ra, sh, mb, me, true); } +void RLWNM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, sh, mb, me, false); } +void RLWNM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, sh, mb, me, true); } +void SC(uint32_t lev) { emit_SC(0x44000000, lev); } +void SI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x30000000, rt, ra, d); } +void SI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x34000000, rt, ra, d); } +void SLBIA(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003e4, rt, ra, rb, false); } +void SLBIA_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003e4, rt, ra, rb, true); } +void SLBIE(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000364, rt, ra, rb, false); } +void SLBIE_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000364, rt, ra, rb, true); } +void SLD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000036, rt, ra, rb, false); } +void SLD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000036, rt, ra, rb, true); } +void SLW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, rt, ra, rb, false); } +void SLW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, rt, ra, rb, true); } +void SRAD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, rt, ra, rb, false); } +void SRAD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, rt, ra, rb, true); } +void SRADI(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c00033a, rt, ra, sh, false); } +void SRADI_(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c00033a, rt, ra, sh, true); } +void SRD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, rt, ra, rb, false); } +void SRD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, rt, ra, rb, true); } +void SRAW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000630, rt, ra, rb, false); } +void SRAW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000630, rt, ra, rb, true); } +void SRAWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000670, rt, ra, rb, false); } +void SRAWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000670, rt, ra, rb, true); } +void SRW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000430, rt, ra, rb, false); } +void SRW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000430, rt, ra, rb, true); } +void STB(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x98000000, rt, ra, d); } +void STBU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x9c000000, rt, ra, d); } +void STBUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ee, rt, ra, rb, false); } +void STBUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ee, rt, ra, rb, true); } +void STBX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, rt, ra, rb, false); } +void STBX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, rt, ra, rb, true); } +void STD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000000, rt, ra, d); } +void STDCX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, rt, ra, rb, false); } +void STDCX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, rt, ra, rb, true); } +void STDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000002, rt, ra, d); } +void STDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, rt, ra, rb, false); } +void STDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, rt, ra, rb, true); } +void STDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012a, rt, ra, rb, false); } +void STDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012a, rt, ra, rb, true); } +void STFD(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xd8000000, rt, ra, d); } +void STFDU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xdc000000, rt, ra, d); } +void STFDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ee, rt, ra, rb, false); } +void STFDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ee, rt, ra, rb, true); } +void STFDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ae, rt, ra, rb, false); } +void STFDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ae, rt, ra, rb, true); } +void STFIWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ae, rt, ra, rb, false); } +void STFIWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ae, rt, ra, rb, true); } +void STFS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xd0000000, rt, ra, d); } +void STFSU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xd4000000, rt, ra, d); } +void STFSUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00056e, rt, ra, rb, false); } +void STFSUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00056e, rt, ra, rb, true); } +void STFSX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052e, rt, ra, rb, false); } +void STFSX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052e, rt, ra, rb, true); } +void STH(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xb0000000, rt, ra, d); } +void STHBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00072c, rt, ra, rb, false); } +void STHBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00072c, rt, ra, rb, true); } +void STHU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xb4000000, rt, ra, d); } +void STHUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036e, rt, ra, rb, false); } +void STHUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036e, rt, ra, rb, true); } +void STHX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00032e, rt, ra, rb, false); } +void STHX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00032e, rt, ra, rb, true); } +void STMW(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xbc000000, rt, ra, d); } +void STSWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005aa, rt, ra, rb, false); } +void STSWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005aa, rt, ra, rb, true); } +void STSWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052a, rt, ra, rb, false); } +void STSWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052a, rt, ra, rb, true); } +void STW(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x90000000, rt, ra, d); } +void STWBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052c, rt, ra, rb, false); } +void STWBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052c, rt, ra, rb, true); } +void STWCX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012c, rt, ra, rb, false); } +void STWCX__(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012c, rt, ra, rb, true); } +void STWU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x94000000, rt, ra, d); } +void STWUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016e, rt, ra, rb, false); } +void STWUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016e, rt, ra, rb, true); } +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 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 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 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 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 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 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 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 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); } +void TD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000088, rt, ra, rb, true); } +void TDI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x08000000, rt, ra, d); } +void TLBIE(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000264, rt, ra, rb, false); } +void TLBIE_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000264, rt, ra, rb, true); } +void TLBSYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046c, rt, ra, rb, false); } +void TLBSYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046c, rt, ra, rb, true); } +void TW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000008, rt, ra, rb, false); } +void TW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000008, rt, ra, rb, true); } +void TWI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x0c000000, rt, ra, d); } +void XOR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000278, rt, ra, rb, false); } +void XOR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000278, rt, ra, rb, true); } +void XORI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x68000000, rt, ra, d); } +void XORIS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x6c000000, rt, ra, d); } diff --git a/externals/powah/tests.cpp b/externals/powah/tests.cpp new file mode 100644 index 0000000000..1ef820afcd --- /dev/null +++ b/externals/powah/tests.cpp @@ -0,0 +1,139 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include "powah_emit.hpp" + +TEST_CASE("ppc64: addi", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + + ctx.ADDI(powah::R2, powah::R2, 0); + ctx.ADDIS(powah::R2, powah::R12, 0); + REQUIRE(data[0] == 0x00004238); + REQUIRE(data[1] == 0x00004c3c); +} + +TEST_CASE("ppc64: std/mr", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + + ctx.STD(powah::R26, powah::R1, 144); + ctx.MR(powah::R26, powah::R4); + ctx.STD(powah::R30, powah::R1, 176); + ctx.MR(powah::R30, powah::R3); + ctx.RLDICR(powah::R4, powah::R5, 25, 6); + ctx.STD(powah::R28, powah::R1, 160); + REQUIRE(data[0] == 0x900041fb); + REQUIRE(data[1] == 0x78239a7c); + REQUIRE(data[2] == 0xb000c1fb); + REQUIRE(data[3] == 0x781b7e7c); + REQUIRE(data[4] == 0x84c9a478); + REQUIRE(data[5] == 0xa00081fb); +} + +TEST_CASE("ppc64: sldi", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + + ctx.SLDI(powah::R3, powah::R5, 37); + REQUIRE(data[0] == 0x862ea378); +} + +TEST_CASE("ppc64: rldicr", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + ctx.RLDICR(powah::R1, powah::R1, 0, 0); + ctx.RLDICR(powah::R1, powah::R1, 1, 0); + ctx.RLDICR(powah::R1, powah::R1, 0, 1); + ctx.RLDICR(powah::R1, powah::R1, 1, 1); + ctx.RLDICR(powah::R1, powah::R1, 31, 31); + REQUIRE(data[0] == 0x04002178); + REQUIRE(data[1] == 0x04082178); + REQUIRE(data[2] == 0x44002178); + REQUIRE(data[3] == 0x44082178); + REQUIRE(data[4] == 0xc4ff2178); +} + +TEST_CASE("ppc64: mr/or/std", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + ctx.MR(powah::R27, powah::R7); + ctx.MR(powah::R29, powah::R6); + ctx.OR(powah::R3, powah::R3, powah::R4); + ctx.MR(powah::R4, powah::R28); + ctx.CRMOVE(powah::CPR{8}, powah::CPR{1}); + ctx.MR(powah::R25, powah::R5); + ctx.OR(powah::R3, powah::R3, powah::R26); + ctx.STD(powah::R3, powah::R1, 56); + ctx.MR(powah::R3, powah::R30); + REQUIRE(data[0] == 0x783bfb7c); + REQUIRE(data[1] == 0x7833dd7c); + REQUIRE(data[2] == 0x7823637c); + REQUIRE(data[3] == 0x78e3847f); + REQUIRE(data[4] == 0x820b014d); + REQUIRE(data[5] == 0x782bb97c); + REQUIRE(data[6] == 0x78d3637c); + REQUIRE(data[7] == 0x380061f8); + REQUIRE(data[8] == 0x78f3c37f); +} + +TEST_CASE("ppc64: ld/crand+addi", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + ctx.LD(powah::R4, powah::R1, 72); + ctx.LWZ(powah::R5, powah::R1, 80); + ctx.CRAND(powah::CPR{20}, powah::CPR{10}, powah::CPR{9}); + ctx.ADDI(powah::R6, powah::R4, 4); + ctx.ANDIS_(powah::R4, powah::R5, 1992); + ctx.LD(powah::R5, powah::R30, 1984); + ctx.LBZ(powah::R3, powah::R1, 84); + ctx.CLRLDI(powah::R26, powah::R6, 8); + ctx.STW(powah::R4, powah::R1, 80); + ctx.ADDI(powah::R5, powah::R5, 1); + ctx.STD(powah::R26, powah::R1, 72); + ctx.STD(powah::R5, powah::R30, 1984); + REQUIRE(data[0] == 0x480081e8); + REQUIRE(data[1] == 0x5000a180); + REQUIRE(data[2] == 0x024a8a4e); + REQUIRE(data[3] == 0x0400c438); + REQUIRE(data[4] == 0xc807a474); + REQUIRE(data[5] == 0xc007bee8); + REQUIRE(data[6] == 0x54006188); + REQUIRE(data[7] == 0x0002da78); + REQUIRE(data[8] == 0x50008190); + REQUIRE(data[9] == 0x0100a538); + REQUIRE(data[10] == 0x480041fb); + REQUIRE(data[11] == 0xc007bef8); +} + +TEST_CASE("ppc64: rotldi", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + ctx.ROTLDI(powah::R5, powah::R3, 16); + ctx.ROTLDI(powah::R4, powah::R3, 8); + ctx.RLDIMI(powah::R4, powah::R5, 8, 48); + ctx.ROTLDI(powah::R5, powah::R3, 24); + ctx.RLDIMI(powah::R4, powah::R5, 16, 40); + ctx.ROTLDI(powah::R5, powah::R3, 32); + ctx.RLDIMI(powah::R4, powah::R5, 24, 32); + ctx.ROTLDI(powah::R5, powah::R3, 48); + ctx.RLDIMI(powah::R4, powah::R5, 40, 16); + ctx.ROTLDI(powah::R5, powah::R3, 56); + ctx.RLDIMI(powah::R4, powah::R5, 48, 8); + ctx.RLDIMI(powah::R4, powah::R3, 56, 0); + ctx.MR(powah::R3, powah::R4); + REQUIRE(data[0] == 0x00806578); + REQUIRE(data[1] == 0x00406478); + REQUIRE(data[2] == 0x2c44a478); + REQUIRE(data[3] == 0x00c06578); + REQUIRE(data[4] == 0x2c82a478); + REQUIRE(data[5] == 0x02006578); + REQUIRE(data[6] == 0x2cc0a478); + REQUIRE(data[7] == 0x02806578); + REQUIRE(data[8] == 0x0e44a478); + REQUIRE(data[9] == 0x02c06578); + REQUIRE(data[10] == 0x0e82a478); + REQUIRE(data[11] == 0x0ec06478); + REQUIRE(data[12] == 0x7823837c); +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a2abc7d1b3..9c62379d02 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,7 +8,7 @@ include_directories(.) # Dynarmic -if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) AND NOT YUZU_STATIC_ROOM) +if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64 OR ARCHITECTURE_powerpc64) AND NOT YUZU_STATIC_ROOM) add_subdirectory(dynarmic) add_library(dynarmic::dynarmic ALIAS dynarmic) endif() diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 508ace3501..bd3d78f7c6 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1241,7 +1241,7 @@ if (HAS_NCE) target_link_libraries(core PRIVATE merry::oaknut) endif() -if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) +if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64 OR ARCHITECTURE_powerpc64) target_sources(core PRIVATE arm/dynarmic/arm_dynarmic.h arm/dynarmic/arm_dynarmic_64.cpp diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index cc1cbcbe39..a21b56eea3 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -74,6 +74,7 @@ add_library(dynarmic STATIC interface/halt_reason.h interface/exclusive_monitor.h interface/optimization_flags.h + interface/halt_reason.h ir/acc_type.h ir/basic_block.cpp ir/basic_block.h @@ -139,10 +140,8 @@ if ("x86_64" IN_LIST ARCHITECTURE) # Newer versions of xbyak (>= 7.25.0) have stricter checks that currently # fail in dynarmic target_compile_definitions(dynarmic PRIVATE XBYAK_STRICT_CHECK_MEM_REG_SIZE=0) - target_compile_definitions(dynarmic PRIVATE XBYAK_OLD_DISP_CHECK=1) target_link_libraries(dynarmic PRIVATE xbyak::xbyak) - target_architecture_specific_sources(dynarmic "x86_64" backend/x64/abi.cpp backend/x64/abi.h @@ -294,6 +293,31 @@ if ("riscv64" IN_LIST ARCHITECTURE) ) message(WARNING "TODO: Incomplete frontend for this host architecture") endif() +if ("ppc64" IN_LIST ARCHITECTURE) + target_link_libraries(dynarmic PRIVATE powah) + target_sources(dynarmic PRIVATE + backend/ppc64/abi.h + backend/ppc64/emit_context.h + backend/ppc64/emit_ppc64_a32.cpp + backend/ppc64/emit_ppc64_a64.cpp + backend/ppc64/emit_ppc64_misc.cpp + backend/ppc64/emit_ppc64_data_processing.cpp + backend/ppc64/emit_ppc64_floating_point.cpp + backend/ppc64/emit_ppc64_vector.cpp + backend/ppc64/emit_ppc64.cpp + backend/ppc64/emit_ppc64.h + backend/ppc64/reg_alloc.cpp + backend/ppc64/reg_alloc.h + backend/ppc64/stack_layout.h + # A32 + backend/ppc64/a32_core.h + backend/ppc64/a32_interface.cpp + # A64 + backend/ppc64/a64_core.h + backend/ppc64/a64_interface.cpp + backend/ppc64/code_block.h + ) +endif() if ("loongarch64" IN_LIST ARCHITECTURE) target_link_libraries(dynarmic PRIVATE lagoon::lagoon) diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler.h b/src/dynarmic/src/dynarmic/backend/exception_handler.h index ce6abef5ce..f854e42c82 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler.h +++ b/src/dynarmic/src/dynarmic/backend/exception_handler.h @@ -17,7 +17,7 @@ #if defined(ARCHITECTURE_x86_64) namespace Dynarmic::Backend::X64 { class BlockOfCode; -} // namespace Dynarmic::Backend::X64 +} #elif defined(ARCHITECTURE_arm64) namespace oaknut { class CodeBlock; @@ -30,6 +30,10 @@ class CodeBlock; namespace Dynarmic::Backend::LoongArch64 { class CodeBlock; } // namespace Dynarmic::Backend::LoongArch64 +#elif defined(ARCHITECTURE_ppc64) +namespace Dynarmic::Backend::PPC64 { +class CodeBlock; +} #else # error "Invalid architecture" #endif @@ -53,6 +57,9 @@ struct FakeCall { struct FakeCall { u64 call_pc; }; +#elif defined(ARCHITECTURE_ppc64) +struct FakeCall { +}; #else # error "Invalid architecture" #endif @@ -70,6 +77,8 @@ public: void Register(RV64::CodeBlock& mem, std::size_t mem_size); #elif defined(ARCHITECTURE_loongarch64) void Register(LoongArch64::CodeBlock& mem, std::size_t mem_size); +#elif defined(ARCHITECTURE_ppc64) + void Register(PPC64::CodeBlock& mem, std::size_t mem_size); #else # error "Invalid architecture" #endif diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp index f19fe98a6d..c18481a688 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp @@ -17,24 +17,21 @@ ExceptionHandler::ExceptionHandler() = default; ExceptionHandler::~ExceptionHandler() = default; #if defined(ARCHITECTURE_x86_64) -void ExceptionHandler::Register(X64::BlockOfCode&) { - // Do nothing -} +void ExceptionHandler::Register(X64::BlockOfCode&) #elif defined(ARCHITECTURE_arm64) -void ExceptionHandler::Register(oaknut::CodeBlock&, std::size_t) { - // Do nothing -} +void ExceptionHandler::Register(oaknut::CodeBlock&, std::size_t) #elif defined(ARCHITECTURE_riscv64) -void ExceptionHandler::Register(RV64::CodeBlock&, std::size_t) { - // Do nothing -} +void ExceptionHandler::Register(RV64::CodeBlock&, std::size_t) #elif defined(ARCHITECTURE_loongarch64) -void ExceptionHandler::Register(LoongArch64::CodeBlock&, std::size_t) { - // Do nothing -} +void ExceptionHandler::Register(LoongArch64::CodeBlock&, std::size_t) +#elif defined(ARCHITECTURE_ppc64) +void ExceptionHandler::Register(PPC64::CodeBlock&, std::size_t) #else # error "Invalid architecture" #endif +{ + // Do nothing +} bool ExceptionHandler::SupportsFastmem() const noexcept { return false; diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp index 24a059aee2..eda4817d38 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp @@ -35,6 +35,8 @@ # include "dynarmic/backend/riscv64/code_block.h" #elif defined(ARCHITECTURE_loongarch64) # include "dynarmic/backend/loongarch64/code_block.h" +#elif defined(ARCHITECTURE_ppc64) +# include "dynarmic/backend/ppc64/code_block.h" #else # error "Invalid architecture" #endif @@ -205,6 +207,10 @@ void ExceptionHandler::Register(RV64::CodeBlock& mem, std::size_t size) { void ExceptionHandler::Register(LoongArch64::CodeBlock& mem, std::size_t size) { impl = std::make_unique(std::bit_cast(mem.ptr()), size); } +#elif defined(ARCHITECTURE_ppc64) +void ExceptionHandler::Register(PPC64::CodeBlock& mem, std::size_t size) { + impl = std::make_unique(std::bit_cast(mem.ptr()), size); +} #else # error "Invalid architecture" #endif From aafbcd6ce17c25c0f3f6ec38e4ac6f0a95854759 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 2 Nov 2025 10:29:37 +0000 Subject: [PATCH 02/49] a64+a32 stubs (+some impls) Signed-off-by: lizzie --- .../src/dynarmic/backend/ppc64/a32_core.h | 77 + .../dynarmic/backend/ppc64/a32_interface.cpp | 238 +++ .../src/dynarmic/backend/ppc64/a64_core.h | 79 + .../dynarmic/backend/ppc64/a64_interface.cpp | 350 ++++ src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 13 + .../src/dynarmic/backend/ppc64/code_block.h | 35 + .../src/dynarmic/backend/ppc64/emit_context.h | 24 + .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 128 ++ .../src/dynarmic/backend/ppc64/emit_ppc64.h | 56 + .../dynarmic/backend/ppc64/emit_ppc64_a32.cpp | 354 ++++ .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 305 +++ .../ppc64/emit_ppc64_data_processing.cpp | 969 +++++++++ .../ppc64/emit_ppc64_floating_point.cpp | 458 +++++ .../backend/ppc64/emit_ppc64_misc.cpp | 380 ++++ .../backend/ppc64/emit_ppc64_vector.cpp | 1810 +++++++++++++++++ .../src/dynarmic/backend/ppc64/reg_alloc.cpp | 245 +++ .../src/dynarmic/backend/ppc64/reg_alloc.h | 114 ++ .../src/dynarmic/backend/ppc64/stack_layout.h | 28 + 18 files changed, 5663 insertions(+) create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/abi.h create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/code_block.h create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h new file mode 100644 index 0000000000..e90b7b203b --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include +#include "dynarmic/backend/ppc64/code_block.h" +#include "dynarmic/backend/ppc64/emit_ppc64.h" +#include "dynarmic/frontend/A32/a32_location_descriptor.h" +#include "dynarmic/interface/A32/a32.h" +#include "dynarmic/interface/A32/config.h" +#include "dynarmic/ir/terminal.h" +#include "dynarmic/ir/basic_block.h" + +namespace Dynarmic::Backend::PPC64 { + +struct A32JitState { + alignas(16) std::array vec{}; + std::array regs{}; + u32 upper_location_descriptor; + u32 exclusive_state = 0; + u32 cpsr_nzcv = 0; + u32 fpsr = 0; + IR::LocationDescriptor GetLocationDescriptor() const { + return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; + } +}; + +class A32AddressSpace final { +public: + explicit A32AddressSpace(const A32::UserConfig& conf); + + IR::Block GenerateIR(IR::LocationDescriptor) const; + + CodePtr Get(IR::LocationDescriptor descriptor); + + CodePtr GetOrEmit(IR::LocationDescriptor descriptor); + + void ClearCache(); + +private: + friend class A32Core; + + void EmitPrelude(); + EmittedBlockInfo Emit(IR::Block ir_block); + void Link(EmittedBlockInfo& block); + + const A32::UserConfig conf; + + CodeBlock cb; + powah::Context as; + + ankerl::unordered_dense::map block_entries; + ankerl::unordered_dense::map block_infos; + + struct PreludeInfo { + CodePtr end_of_prelude; + + using RunCodeFuncType = HaltReason (*)(CodePtr entry_point, A32JitState* context, volatile u32* halt_reason); + RunCodeFuncType run_code; + CodePtr return_from_run_code; + } prelude_info; +}; + +class A32Core final { +public: + explicit A32Core(const A32::UserConfig&) {} + + HaltReason Run(A32AddressSpace& process, A32JitState& thread_ctx, volatile u32* halt_reason) { + const auto location_descriptor = thread_ctx.GetLocationDescriptor(); + const auto entry_point = process.GetOrEmit(location_descriptor); + return process.prelude_info.run_code(entry_point, &thread_ctx, halt_reason); + } +}; + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp new file mode 100644 index 0000000000..025fc0c989 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -0,0 +1,238 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include +#include "dynarmic/common/assert.h" +#include +#include "dynarmic/common/common_types.h" + +#include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/common/atomic.h" +#include "dynarmic/interface/A32/a32.h" + +namespace Dynarmic::Backend::PPC64 { + +A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf) + : conf(conf) + , cb(conf.code_cache_size) + , as(cb.ptr(), conf.code_cache_size) { + EmitPrelude(); +} + +IR::Block A32AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const { + IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); + Optimization::Optimize(ir_block, conf, {}); + return ir_block; +} + +CodePtr A32AddressSpace::Get(IR::LocationDescriptor descriptor) { + if (const auto iter = block_entries.find(descriptor.Value()); iter != block_entries.end()) + return iter->second; + return nullptr; +} + +CodePtr A32AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) { + if (CodePtr block_entry = Get(descriptor)) { + return block_entry; + } + + IR::Block ir_block = GenerateIR(descriptor); + const EmittedBlockInfo block_info = Emit(std::move(ir_block)); + + block_infos.insert_or_assign(descriptor.Value(), block_info); + block_entries.insert_or_assign(descriptor.Value(), block_info.entry_point); + return block_info.entry_point; +} + +void A32AddressSpace::ClearCache() { + block_entries.clear(); + block_infos.clear(); +} + +void A32AddressSpace::EmitPrelude() { + UNREACHABLE(); +} + +EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) { + EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { + .enable_cycle_counting = conf.enable_cycle_counting, + .always_little_endian = conf.always_little_endian, + }); + Link(block_info); + return block_info; +} + +void A32AddressSpace::Link(EmittedBlockInfo& block_info) { + UNREACHABLE(); +} + +namespace Dynarmic::A32 { + +struct Jit::Impl final { + Impl(Jit* jit_interface, A32::UserConfig conf) + : jit_interface(jit_interface) + , conf(conf) + , current_address_space(conf) + , core(conf) {} + + HaltReason Run() { + HaltReason hr = core.Run(current_address_space, current_state, &halt_reason); + RequestCacheInvalidation(); + return hr; + } + + HaltReason Step() { + RequestCacheInvalidation(); + return HaltReason{}; + } + + void ClearCache() { + std::unique_lock lock{invalidation_mutex}; + invalidate_entire_cache = true; + HaltExecution(HaltReason::CacheInvalidation); + } + + void InvalidateCacheRange(u32 start_address, size_t length) { + std::unique_lock lock{invalidation_mutex}; + invalid_cache_ranges.add(boost::icl::discrete_interval::closed(start_address, u32(start_address + length - 1))); + HaltExecution(HaltReason::CacheInvalidation); + } + + void Reset() { + current_state = {}; + } + + void HaltExecution(HaltReason hr) { + Atomic::Or(&halt_reason, ~u32(hr)); + } + + void ClearHalt(HaltReason hr) { + Atomic::And(&halt_reason, ~u32(hr)); + } + + std::array& Regs() { + return current_state.regs; + } + + const std::array& Regs() const { + return current_state.regs; + } + + std::array& ExtRegs() { + return current_state.ext_regs; + } + + const std::array& ExtRegs() const { + return current_state.ext_regs; + } + + u32 Cpsr() const { + return current_state.Cpsr(); + } + + void SetCpsr(u32 value) { + current_state.SetCpsr(value); + } + + u32 Fpscr() const { + return current_state.Fpscr(); + } + + void SetFpscr(u32 value) { + current_state.SetFpscr(value); + } + + void ClearExclusiveState() { + current_state.exclusive_state = false; + } + +private: + void RequestCacheInvalidation() { + // UNREACHABLE(); + + invalidate_entire_cache = false; + invalid_cache_ranges.clear(); + } + + Jit* jit_interface; + A32::UserConfig conf; + A32JitState current_state{}; + A32AddressSpace current_address_space; + A32Core core; + volatile u32 halt_reason = 0; + std::mutex invalidation_mutex; + boost::icl::interval_set invalid_cache_ranges; + bool invalidate_entire_cache = false; +}; + +Jit::Jit(UserConfig conf) : impl(std::make_unique(this, conf)) {} +Jit::~Jit() = default; + +HaltReason Jit::Run() { + return impl->Run(); +} + +HaltReason Jit::Step() { + return impl->Step(); +} + +void Jit::ClearCache() { + impl->ClearCache(); +} + +void Jit::InvalidateCacheRange(u32 start_address, std::size_t length) { + impl->InvalidateCacheRange(start_address, length); +} + +void Jit::Reset() { + impl->Reset(); +} + +void Jit::HaltExecution(HaltReason hr) { + impl->HaltExecution(hr); +} + +void Jit::ClearHalt(HaltReason hr) { + impl->ClearHalt(hr); +} + +std::array& Jit::Regs() { + return impl->Regs(); +} + +const std::array& Jit::Regs() const { + return impl->Regs(); +} + +std::array& Jit::ExtRegs() { + return impl->ExtRegs(); +} + +const std::array& Jit::ExtRegs() const { + return impl->ExtRegs(); +} + +u32 Jit::Cpsr() const { + return impl->Cpsr(); +} + +void Jit::SetCpsr(u32 value) { + impl->SetCpsr(value); +} + +u32 Jit::Fpscr() const { + return impl->Fpscr(); +} + +void Jit::SetFpscr(u32 value) { + impl->SetFpscr(value); +} + +void Jit::ClearExclusiveState() { + impl->ClearExclusiveState(); +} + +} // namespace Dynarmic::A32 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h new file mode 100644 index 0000000000..5e3edabe48 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + + +#include +#include +#include "dynarmic/backend/ppc64/code_block.h" +#include "dynarmic/backend/ppc64/emit_ppc64.h" +#include "dynarmic/frontend/A64/a64_location_descriptor.h" +#include "dynarmic/interface/A64/a64.h" +#include "dynarmic/interface/A64/config.h" +#include "dynarmic/ir/terminal.h" +#include "dynarmic/ir/basic_block.h" + +namespace Dynarmic::Backend::PPC64 { + +struct A64JitState { + using ProgramCounterType = u32; + alignas(16) std::array vec{}; + std::array regs{}; + u32 upper_location_descriptor; + u32 exclusive_state = 0; + u32 cpsr_nzcv = 0; + u32 fpsr = 0; + IR::LocationDescriptor GetLocationDescriptor() const { + return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; + } +}; + +class A64AddressSpace final { +public: + explicit A64AddressSpace(const A64::UserConfig& conf); + + IR::Block GenerateIR(IR::LocationDescriptor) const; + + CodePtr Get(IR::LocationDescriptor descriptor); + + CodePtr GetOrEmit(IR::LocationDescriptor descriptor); + + void ClearCache(); + +private: + friend class A64Core; + + void EmitPrelude(); + EmittedBlockInfo Emit(IR::Block ir_block); + void Link(EmittedBlockInfo& block); + + const A64::UserConfig conf; + + CodeBlock cb; + powah::Context as; + + ankerl::unordered_dense::map block_entries; + ankerl::unordered_dense::map block_infos; + + struct PreludeInfo { + CodePtr end_of_prelude; + + using RunCodeFuncType = HaltReason (*)(CodePtr entry_point, A64JitState* context, volatile u32* halt_reason); + RunCodeFuncType run_code; + CodePtr return_from_run_code; + } prelude_info; +}; + +class A64Core final { +public: + explicit A64Core(const A64::UserConfig&) {} + + HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { + const auto location_descriptor = thread_ctx.GetLocationDescriptor(); + const auto entry_point = process.GetOrEmit(location_descriptor); + return process.prelude_info.run_code(entry_point, &thread_ctx, halt_reason); + } +}; + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp new file mode 100644 index 0000000000..a0232a6ced --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -0,0 +1,350 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include +#include "dynarmic/common/assert.h" +#include "dynarmic/common/common_types.h" + +#include "dynarmic/backend/ppc64/a64_core.h" +#include "dynarmic/backend/ppc64/a64_core.h" +#include "dynarmic/common/atomic.h" +#include "dynarmic/interface/A64/a64.h" + +namespace Dynarmic::Backend::PPC64 { + +A64AddressSpace::A64AddressSpace(const A64::UserConfig& conf) + : conf(conf) + , cb(conf.code_cache_size) + , as(cb.ptr(), conf.code_cache_size) { + EmitPrelude(); +} + +IR::Block A64AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const { + IR::Block ir_block = A64::Translate(A64::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); + Optimization::Optimize(ir_block, conf, {}); + return ir_block; +} + +CodePtr A64AddressSpace::Get(IR::LocationDescriptor descriptor) { + if (const auto iter = block_entries.find(descriptor.Value()); iter != block_entries.end()) + return iter->second; + return nullptr; +} + +CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) { + if (CodePtr block_entry = Get(descriptor)) { + return block_entry; + } + + IR::Block ir_block = GenerateIR(descriptor); + const EmittedBlockInfo block_info = Emit(std::move(ir_block)); + + block_infos.insert_or_assign(descriptor.Value(), block_info); + block_entries.insert_or_assign(descriptor.Value(), block_info.entry_point); + return block_info.entry_point; +} + +void A64AddressSpace::ClearCache() { + block_entries.clear(); + block_infos.clear(); +} + +void A64AddressSpace::EmitPrelude() { + UNREACHABLE(); +} + +EmittedBlockInfo A64AddressSpace::Emit(IR::Block block) { + EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { + .enable_cycle_counting = conf.enable_cycle_counting, + .always_little_endian = conf.always_little_endian, + }); + Link(block_info); + return block_info; +} + +void A64AddressSpace::Link(EmittedBlockInfo& block_info) { + UNREACHABLE(); +} +} + +namespace Dynarmic::A64 { + +struct Jit::Impl final { + Impl(Jit* jit_interface, A64::UserConfig conf) + : jit_interface(jit_interface) + , conf(conf) + , current_address_space(conf) + , core(conf) {} + + HaltReason Run() { + ASSERT(!is_executing); + //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason))); + is_executing = true; + const HaltReason hr = block_of_code.RunCode(&jit_state, current_code_ptr); + //PerformRequestedCacheInvalidation(hr); + is_executing = false; + return hr; + } + + HaltReason Step() { + ASSERT(!is_executing); + //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason))); + is_executing = true; + const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); + //PerformRequestedCacheInvalidation(hr); + is_executing = false; + return hr; + } + + void ClearCache() { + std::unique_lock lock{invalidation_mutex}; + invalidate_entire_cache = true; + HaltExecution(HaltReason::CacheInvalidation); + } + + void InvalidateCacheRange(u64 start_address, size_t length) { + std::unique_lock lock{invalidation_mutex}; + const auto end_address = u64(start_address + length - 1); + invalid_cache_ranges.add(boost::icl::discrete_interval::closed(start_address, end_address)); + HaltExecution(HaltReason::CacheInvalidation); + } + + void Reset() { + ASSERT(!is_executing); + jit_state = {}; + } + + void HaltExecution(HaltReason hr) { + Atomic::Or(&jit_state.halt_reason, u32(hr)); + } + + void ClearHalt(HaltReason hr) { + Atomic::And(&jit_state.halt_reason, ~u32(hr)); + } + + u64 GetSP() const { + return jit_state.sp; + } + + void SetSP(u64 value) { + jit_state.sp = value; + } + + u64 GetPC() const { + return jit_state.pc; + } + + void SetPC(u64 value) { + jit_state.pc = value; + } + + u64 GetRegister(size_t index) const { + if (index == 31) + return GetSP(); + return jit_state.reg.at(index); + } + + void SetRegister(size_t index, u64 value) { + if (index == 31) + return SetSP(value); + jit_state.reg.at(index) = value; + } + + std::array GetRegisters() const { + return jit_state.reg; + } + + void SetRegisters(const std::array& value) { + jit_state.reg = value; + } + + Vector GetVector(size_t index) const { + return {jit_state.vec.at(index * 2), jit_state.vec.at(index * 2 + 1)}; + } + + void SetVector(size_t index, Vector value) { + jit_state.vec.at(index * 2) = value[0]; + jit_state.vec.at(index * 2 + 1) = value[1]; + } + + std::array GetVectors() const { + std::array ret; + static_assert(sizeof(ret) == sizeof(jit_state.vec)); + std::memcpy(ret.data(), jit_state.vec.data(), sizeof(jit_state.vec)); + return ret; + } + + void SetVectors(const std::array& value) { + static_assert(sizeof(value) == sizeof(jit_state.vec)); + std::memcpy(jit_state.vec.data(), value.data(), sizeof(jit_state.vec)); + } + + u32 GetFpcr() const { + return jit_state.GetFpcr(); + } + + void SetFpcr(u32 value) { + jit_state.SetFpcr(value); + } + + u32 GetFpsr() const { + return jit_state.GetFpsr(); + } + + void SetFpsr(u32 value) { + jit_state.SetFpsr(value); + } + + u32 GetPstate() const { + return jit_state.GetPstate(); + } + + void SetPstate(u32 value) { + jit_state.SetPstate(value); + } + + void ClearExclusiveState() { + jit_state.exclusive_state = 0; + } + + bool IsExecuting() const { + return is_executing; + } + +private: + void RequestCacheInvalidation() { + // UNREACHABLE(); + invalidate_entire_cache = false; + invalid_cache_ranges.clear(); + } + + bool is_executing = false; + const UserConfig conf; + A64JitState jit_state; + A64AddressSpace emitter; + BlockOfCode block_of_code; + Optimization::PolyfillOptions polyfill_options; + bool invalidate_entire_cache = false; + boost::icl::interval_set invalid_cache_ranges; + std::mutex invalidation_mutex; +}; + +Jit::Jit(UserConfig conf) : impl(std::make_unique(this, conf)) {} +Jit::~Jit() = default; + +HaltReason Jit::Run() { + return impl->Run(); +} + +HaltReason Jit::Step() { + return impl->Step(); +} + +void Jit::ClearCache() { + impl->ClearCache(); +} + +void Jit::InvalidateCacheRange(u64 start_address, size_t length) { + impl->InvalidateCacheRange(start_address, length); +} + +void Jit::Reset() { + impl->Reset(); +} + +void Jit::HaltExecution(HaltReason hr) { + impl->HaltExecution(hr); +} + +void Jit::ClearHalt(HaltReason hr) { + impl->ClearHalt(hr); +} + +u64 Jit::GetSP() const { + return impl->GetSP(); +} + +void Jit::SetSP(u64 value) { + impl->SetSP(value); +} + +u64 Jit::GetPC() const { + return impl->GetPC(); +} + +void Jit::SetPC(u64 value) { + impl->SetPC(value); +} + +u64 Jit::GetRegister(size_t index) const { + return impl->GetRegister(index); +} + +void Jit::SetRegister(size_t index, u64 value) { + impl->SetRegister(index, value); +} + +std::array Jit::GetRegisters() const { + return impl->GetRegisters(); +} + +void Jit::SetRegisters(const std::array& value) { + impl->SetRegisters(value); +} + +Vector Jit::GetVector(size_t index) const { + return impl->GetVector(index); +} + +void Jit::SetVector(size_t index, Vector value) { + impl->SetVector(index, value); +} + +std::array Jit::GetVectors() const { + return impl->GetVectors(); +} + +void Jit::SetVectors(const std::array& value) { + impl->SetVectors(value); +} + +u32 Jit::GetFpcr() const { + return impl->GetFpcr(); +} + +void Jit::SetFpcr(u32 value) { + impl->SetFpcr(value); +} + +u32 Jit::GetFpsr() const { + return impl->GetFpsr(); +} + +void Jit::SetFpsr(u32 value) { + impl->SetFpsr(value); +} + +u32 Jit::GetPstate() const { + return impl->GetPstate(); +} + +void Jit::SetPstate(u32 value) { + impl->SetPstate(value); +} + +void Jit::ClearExclusiveState() { + impl->ClearExclusiveState(); +} + +bool Jit::IsExecuting() const { + return impl->IsExecuting(); +} + +std::string Jit::Disassemble() const { + return impl->Disassemble(); +} + +} // namespace Dynarmic::A64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h new file mode 100644 index 0000000000..e47be9fe6a --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +namespace Dynarmic::Backend::PPC64 { + +constexpr powah::GPR RJIT = powah::R31; + +constexpr std::initializer_list GPR_ORDER{8, 9, 18, 19, 20, 21, 22, 23, 24, 25, 5, 6, 7, 28, 29, 10, 11, 12, 13, 14, 15, 16, 17}; +constexpr std::initializer_list FPR_ORDER{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h b/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h new file mode 100644 index 0000000000..3877b9c13f --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include +#include + +#include "dynarmic/common/common_types.h" +#include "dynarmic/common/assert.h" + +namespace Dynarmic::Backend::PPC64 { + +class CodeBlock { +public: + explicit CodeBlock(std::size_t size) noexcept : memsize(size) { + mem = (u8*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); + ASSERT(mem != nullptr); + } + ~CodeBlock() noexcept { + if (mem != nullptr) + munmap(mem, memsize); + } + template + T ptr() const noexcept { + static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); + return reinterpret_cast(mem); + } +protected: + u8* mem = nullptr; + size_t memsize = 0; +}; + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h new file mode 100644 index 0000000000..25c1562785 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dynarmic/backend/ppc64/emit_ppc64.h" +#include "dynarmic/backend/ppc64/reg_alloc.h" + +namespace Dynarmic::IR { +class Block; +} // namespace Dynarmic::IR + +namespace Dynarmic::Backend::PPC64 { + +struct EmitConfig; + +struct EmitContext { + IR::Block& block; + RegAlloc& reg_alloc; + const EmitConfig& emit_conf; + EmittedBlockInfo& ebi; +}; + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp new file mode 100644 index 0000000000..140e9a2d40 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -0,0 +1,128 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "dynarmic/backend/ppc64/emit_ppc64.h" + +#include + +#include +#include +#include + +#include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/backend/ppc64/abi.h" +#include "dynarmic/backend/ppc64/emit_context.h" +#include "dynarmic/backend/ppc64/reg_alloc.h" +#include "dynarmic/ir/basic_block.h" +#include "dynarmic/ir/microinstruction.h" +#include "dynarmic/ir/opcodes.h" + +namespace Dynarmic::Backend::PPC64 { + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) {} + +template<> +void EmitIR(powah::Context&, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +EmittedBlockInfo EmitPPC64(powah::Context& as, IR::Block block, const EmitConfig& emit_conf) { + EmittedBlockInfo ebi; + RegAlloc reg_alloc{as}; + EmitContext ctx{block, reg_alloc, emit_conf, ebi}; + //ebi.entry_point = reinterpret_cast(as.GetCursorPointer()); + for (auto iter = block.begin(); iter != block.end(); ++iter) { + IR::Inst* inst = &*iter; + + switch (inst->GetOpcode()) { +#define OPCODE(name, type, ...) \ + case IR::Opcode::name: \ + EmitIR(as, ctx, inst); \ + break; +#define A32OPC(name, type, ...) \ + case IR::Opcode::A32##name: \ + EmitIR(as, ctx, inst); \ + break; +#define A64OPC(name, type, ...) \ + case IR::Opcode::A64##name: \ + EmitIR(as, ctx, inst); \ + break; +#include "dynarmic/ir/opcodes.inc" +#undef OPCODE +#undef A32OPC +#undef A64OPC + default: + UNREACHABLE(); + } + } + //UNREACHABLE(); + //ebi.size = reinterpret_cast(as.GetCursorPointer()) - ebi.entry_point; + return ebi; +} + +void EmitRelocation(powah::Context& as, EmitContext& ctx, LinkTarget link_target) { + UNREACHABLE(); +} + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h new file mode 100644 index 0000000000..aad9d0dd63 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +#include +#include "dynarmic/common/common_types.h" + +namespace biscuit { +class Assembler; +} // namespace biscuit + +namespace Dynarmic::IR { +class Block; +class Inst; +enum class Cond; +enum class Opcode; +} // namespace Dynarmic::IR + +namespace Dynarmic::Backend::PPC64 { + +using CodePtr = std::byte*; + +enum class LinkTarget { + ReturnFromRunCode, +}; + +struct Relocation { + std::ptrdiff_t code_offset; + LinkTarget target; +}; + +struct EmittedBlockInfo { + CodePtr entry_point; + size_t size; + std::vector relocations; +}; + +struct EmitConfig { + bool enable_cycle_counting; + bool always_little_endian; +}; + +struct EmitContext; + +EmittedBlockInfo EmitPPC64(powah::Context& as, IR::Block block, const EmitConfig& emit_conf); + +template +void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst); +void EmitRelocation(powah::Context& as, EmitContext& ctx, LinkTarget link_target); +void EmitA32Cond(powah::Context& as, EmitContext& ctx, IR::Cond cond, powah::Label* label); +void EmitA32Terminal(powah::Context& as, EmitContext& ctx); + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp new file mode 100644 index 0000000000..f851882c4e --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp @@ -0,0 +1,354 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/backend/ppc64/abi.h" +#include "dynarmic/backend/ppc64/emit_context.h" +#include "dynarmic/backend/ppc64/emit_ppc64.h" +#include "dynarmic/backend/ppc64/reg_alloc.h" +#include "dynarmic/ir/basic_block.h" +#include "dynarmic/ir/microinstruction.h" +#include "dynarmic/ir/opcodes.h" + +namespace Dynarmic::Backend::PPC64 { + +void EmitA32Cond(powah::Context& as, EmitContext&, IR::Cond cond, powah::Label* label) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step); + +void EmitA32Terminal(powah::Context&, EmitContext&, IR::Term::Interpret, IR::LocationDescriptor, bool) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) { + EmitRelocation(as, ctx, LinkTarget::ReturnFromRunCode); +} + +void EmitSetUpperLocationDescriptor(powah::Context& as, EmitContext& ctx, IR::LocationDescriptor new_location, IR::LocationDescriptor old_location) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::PopRSBHint, IR::LocationDescriptor, bool) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::FastDispatchHint, IR::LocationDescriptor, bool) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + UNREACHABLE(); +} + +void EmitA32Terminal(powah::Context& as, EmitContext& ctx) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +// Memory +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +// Coprocesor +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp new file mode 100644 index 0000000000..2729d145f9 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -0,0 +1,305 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/backend/ppc64/abi.h" +#include "dynarmic/backend/ppc64/emit_context.h" +#include "dynarmic/backend/ppc64/emit_ppc64.h" +#include "dynarmic/backend/ppc64/reg_alloc.h" +#include "dynarmic/ir/basic_block.h" +#include "dynarmic/ir/microinstruction.h" +#include "dynarmic/ir/opcodes.h" + +namespace Dynarmic::Backend::PPC64 { + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +// Memory +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + + +} // namespace Dynarmic::Backend::RV64 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 new file mode 100644 index 0000000000..80aa9a13d5 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp @@ -0,0 +1,969 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include "dynarmic/common/assert.h" +#include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/backend/ppc64/abi.h" +#include "dynarmic/backend/ppc64/emit_context.h" +#include "dynarmic/backend/ppc64/emit_ppc64.h" +#include "dynarmic/backend/ppc64/reg_alloc.h" +#include "dynarmic/ir/basic_block.h" +#include "dynarmic/ir/microinstruction.h" +#include "dynarmic/ir/opcodes.h" + +namespace Dynarmic::Backend::PPC64 { + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +/* +uint64_t f(uint64_t a) { return (uint16_t)a; } +*/ +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.RLWINM(result, source, 0, 0xffff); + ctx.reg_alloc.DefineValue(inst, result); +} + +/* +uint64_t f(uint64_t a) { return (uint8_t)a; } +*/ +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.RLWINM(result, source, 0, 0xff); + ctx.reg_alloc.DefineValue(inst, result); +} + +/* +uint64_t f(uint64_t a) { return (uint32_t)(a >> 32); } +*/ +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.SRDI(result, source, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +/* +uint64_t f(uint64_t a) { return ((uint32_t)a) >> 31; } +*/ +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.RLWINM(result, source, 1, 31, 31); + ctx.reg_alloc.DefineValue(inst, result); +} + +/* +uint64_t f(uint64_t a) { return a == 0; } +*/ +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.CNTLZD(result, source); + code.SRDI(result, result, 6); + ctx.reg_alloc.DefineValue(inst, result); +} + +/* +uint64_t f(uint64_t a) { return (uint32_t)a == 0; } +*/ +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.CNTLZW(result, source); + code.SRWI(result, result, 5); + ctx.reg_alloc.DefineValue(inst, result); +} + +/* +uint64_t f(uint64_t a) { return (a & 1) != 0; } +*/ +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + if (args[1].IsImmediate()) { + auto const shift = args[1].GetImmediateU8(); + if (shift > 0) { + code.RLDICL(result, source, (64 - shift - 1) & 0x3f, 63); + } + } else { + UNREACHABLE(); + } + ctx.reg_alloc.DefineValue(inst, result); +} + +/* +struct jit { + uint64_t t; + uint64_t a; +}; +uint64_t f(jit *p, uint64_t a, uint64_t b) { + bool n = (p->a & 0b1000) != 0; + bool z = (p->a & 0b0100) != 0; + bool c = (p->a & 0b0010) != 0; + bool v = (p->a & 0b0001) != 0; + return (p->a & 0b0001) == 0 ? a : b; +} +*/ +static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const nzcv = ctx.reg_alloc.ScratchGpr(); + powah::GPR const then_ = ctx.reg_alloc.UseScratchGpr(args[1]); + powah::GPR const else_ = ctx.reg_alloc.UseScratchGpr(args[2]); + switch (args[0].GetImmediateCond()) { + case IR::Cond::EQ: // Z == 1 + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.ANDI_(nzcv, nzcv, 4); + code.ISELGT(nzcv, then_, else_); + break; + case IR::Cond::NE: // Z == 0 + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.ANDI_(nzcv, nzcv, 4); + code.ISELGT(nzcv, then_, else_); + break; + case IR::Cond::CS: // C == 1 + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.ANDI_(nzcv, nzcv, 2); + code.ISELGT(nzcv, then_, else_); + break; + case IR::Cond::CC: // C == 0 + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.ANDI_(nzcv, nzcv, 2); + code.ISELGT(nzcv, then_, else_); + break; + case IR::Cond::MI: // N == 1 + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.ANDI_(nzcv, nzcv, 8); + code.ISELGT(nzcv, then_, else_); + break; + case IR::Cond::PL: // N == 0 + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.ANDI_(nzcv, nzcv, 8); + code.ISELGT(nzcv, then_, else_); + break; + case IR::Cond::VS: // V == 1 + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.ANDI_(nzcv, nzcv, 1); + code.ISELGT(nzcv, then_, else_); + break; + case IR::Cond::VC: // V == 0 + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.ANDI_(nzcv, nzcv, 1); + code.ISELGT(nzcv, else_, then_); + break; + case IR::Cond::HI: // Z == 0 && C == 1 + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.RLWINM(nzcv, nzcv, 0, 29, 30); + code.CMPLDI(nzcv, 2); + code.ISELEQ(nzcv, then_, else_); + break; + case IR::Cond::LS: // Z == 1 || C == 0 + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.RLWINM(nzcv, nzcv, 0, 29, 30); + code.CMPLDI(nzcv, 2); + code.ISELEQ(nzcv, else_, then_); + break; + case IR::Cond::GE: { // N == V + powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + code.LWZ(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.SRWI(tmp, nzcv, 3); + code.XOR(nzcv, tmp, nzcv); + code.ANDI_(nzcv, nzcv, 1); + code.ISELGT(nzcv, else_, then_); + } break; + case IR::Cond::LT: { // N != V + powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + code.LWZ(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.SRWI(tmp, nzcv, 3); + code.XOR(nzcv, tmp, nzcv); + code.ANDI_(nzcv, nzcv, 1); + code.ISELGT(nzcv, then_, else_); + } break; + case IR::Cond::GT: { // Z == 0 && N == V + powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + powah::Label const l_ne = code.DefineLabel(); + powah::Label const l_cc = code.DefineLabel(); + powah::Label const l_fi = code.DefineLabel(); + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.ANDI_(tmp, nzcv, 4); + code.BNE(powah::CR0, l_ne); + code.SRWI(tmp, nzcv, 3); + code.XOR(nzcv, tmp, nzcv); + code.ANDI_(nzcv, nzcv, 1); + code.CMPLDI(nzcv, 0); + code.BGT(powah::CR0, l_fi); + code.LABEL(l_ne); + code.MR(then_, else_); + code.LABEL(l_cc); + code.MR(nzcv, then_); + code.LABEL(l_fi); + } break; + case IR::Cond::LE: { // Z == 1 || N != V + powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + powah::Label const l_ne = code.DefineLabel(); + code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.ANDI_(tmp, nzcv, 4); + code.BNE(powah::CR0, l_ne); + code.SRWI(tmp, nzcv, 3); + code.XOR(nzcv, tmp, nzcv); + code.ANDI_(nzcv, nzcv, 1); + code.ISELGT(then_, then_, else_); + code.LABEL(l_ne); + code.MR(nzcv, then_); + } break; + default: + UNREACHABLE(); + } + return nzcv; +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + powah::GPR const result = EmitConditionalSelectX(code, ctx, inst); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + powah::GPR const result = EmitConditionalSelectX(code, ctx, inst); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + powah::GPR const result = EmitConditionalSelectX(code, ctx, inst); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + code.SLW(result, source, shift); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + code.SLD(result, source, shift); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + code.SRW(result, source, shift); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +/* +uint64_t f(uint64_t a, uint64_t s) { return a >> s; } +*/ +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + code.SRD(result, source, shift); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + code.SRAW(result, source, shift); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + code.SRAD(result, source, shift); + ctx.reg_alloc.DefineValue(inst, result); +} + +// __builtin_rotateright32 +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.NEG(result, src_a, powah::R0); + code.ROTLW(result, result, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.NEG(result, src_a, powah::R0); + code.ROTLD(result, result, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.NEG(result, src_a, powah::R0); + code.ROTLD(result, result, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.SLW(result, source, source); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.SLD(result, source, source); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.SRW(result, source, source); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.SRD(result, source, source); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.SRAW(result, source, source); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.SRAL(result, source, source); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.NEG(result, src_a, powah::R0); + code.ROTLD(result, result, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.NEG(result, src_a, powah::R0); + code.ROTLD(result, result, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.ADD(result, src_a, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.ADD(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.SUBF(result, src_b, src_a); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.SUBF(result, src_b, src_a); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.MULLW(result, src_a, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.MULLD(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.MULLD(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.MULLD(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.DIVDU(result, src_a, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.DIVDU(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.DIVW(result, src_a, src_b); + code.EXTSW(result, result); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.DIVD(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.AND(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.AND(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.NAND(result, src_a, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.NAND(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.XOR(result, src_a, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.XOR(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.OR(result, src_a, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + code.OR(result, src_a, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.NOT(result, source); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.NOT(result, source); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.EXTSB(result, source); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.EXTSH(result, source); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.EXTSH(result, source); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.EXTSB(result, source); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.EXTSW(result, source); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.RLWINM(result, source, 0, 0xff); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.RLWINM(result, source, 0, 0xffff); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.RLWINM(result, source, 0, 0xff); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.RLWINM(result, source, 0, 0xffff); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +// __builtin_bswap32 +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + if (false) { + //code.BRW(result, source); + code.RLDICL(result, result, 0, 32); + } else { + code.ROTLWI(result, source, 8); + code.RLWIMI(result, source, 24, 16, 23); + code.RLWIMI(result, source, 24, 0, 7); + } + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + if (false) { + //code.BRH(result, source); + code.RLWINM(result, source, 0, 0xff); + } else { + code.ROTLWI(result, source, 24); + code.RLWIMI(result, source, 8, 0, 23); + code.CLRLDI(result, result, 48); + } + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + if (false) { + //code.BRD(result, source); + } else { + powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + code.ROTLDI(tmp, source, 16); + code.ROTLDI(result, source, 8); + code.RLDIMI(result, tmp, 8, 48); + code.ROTLDI(tmp, source, 24); + code.RLDIMI(result, tmp, 16, 40); + code.ROTLDI(tmp, source, 32); + code.RLDIMI(result, tmp, 24, 32); + code.ROTLDI(tmp, source, 48); + code.RLDIMI(result, tmp, 40, 16); + code.ROTLDI(tmp, source, 56); + code.RLDIMI(result, tmp, 48, 8); + code.RLDIMI(result, source, 56, 0); + } + ctx.reg_alloc.DefineValue(inst, result); +} + +// __builtin_clz +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.CNTLZW(result, source); + ctx.reg_alloc.DefineValue(inst, result); +} + +// __builtin_clz +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + code.CNTLZD(result, source); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.CMPD(powah::CR0, result, src_a); + code.ISELGT(result, result, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.CMPD(powah::CR0, result, src_a); + code.ISELGT(result, result, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.CMPLW(result, src_a); + code.ISELGT(result, result, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.CMPLD(result, src_a); + code.ISELGT(result, result, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.CMPW(powah::CR0, result, src_a); + code.ISELGT(result, result, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.CMPD(powah::CR0, result, src_a); + code.ISELGT(result, result, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.CMPLW(result, src_a); + code.ISELGT(result, result, src_b); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + code.CMPLD(result, src_a); + code.ISELGT(result, result, src_b); + ctx.reg_alloc.DefineValue(inst, result); +} + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp new file mode 100644 index 0000000000..b50f5027cd --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp @@ -0,0 +1,458 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/backend/ppc64/abi.h" +#include "dynarmic/backend/ppc64/emit_context.h" +#include "dynarmic/backend/ppc64/emit_ppc64.h" +#include "dynarmic/backend/ppc64/reg_alloc.h" +#include "dynarmic/ir/basic_block.h" +#include "dynarmic/ir/microinstruction.h" +#include "dynarmic/ir/opcodes.h" + +namespace Dynarmic::Backend::PPC64 { + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp new file mode 100644 index 0000000000..89d925e465 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp @@ -0,0 +1,380 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/backend/ppc64/abi.h" +#include "dynarmic/backend/ppc64/emit_context.h" +#include "dynarmic/backend/ppc64/emit_ppc64.h" +#include "dynarmic/backend/ppc64/reg_alloc.h" +#include "dynarmic/ir/basic_block.h" +#include "dynarmic/ir/microinstruction.h" +#include "dynarmic/ir/opcodes.h" + +namespace Dynarmic::Backend::PPC64 { + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +// Packed +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +// Crypto +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp new file mode 100644 index 0000000000..ccc4daf4b1 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp @@ -0,0 +1,1810 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/backend/ppc64/abi.h" +#include "dynarmic/backend/ppc64/emit_context.h" +#include "dynarmic/backend/ppc64/emit_ppc64.h" +#include "dynarmic/backend/ppc64/reg_alloc.h" +#include "dynarmic/ir/basic_block.h" +#include "dynarmic/ir/microinstruction.h" +#include "dynarmic/ir/opcodes.h" + +namespace Dynarmic::Backend::PPC64 { + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +// Vector saturation +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +// Vector VFP +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +template<> +void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { + UNREACHABLE(); +} + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp new file mode 100644 index 0000000000..a0c752fded --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -0,0 +1,245 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "dynarmic/backend/ppc64/reg_alloc.h" + +#include +#include + +#include "dynarmic/common/assert.h" +#include +#include "dynarmic/common/common_types.h" + +#include "dynarmic/common/always_false.h" + +namespace Dynarmic::Backend::PPC64 { + +constexpr size_t spill_offset = offsetof(StackLayout, spill); +constexpr size_t spill_slot_size = sizeof(decltype(StackLayout::spill)::value_type); + +static bool IsValuelessType(IR::Type type) { + return type == IR::Type::Table; +} + +IR::Type Argument::GetType() const { + return value.GetType(); +} + +bool Argument::IsImmediate() const { + return value.IsImmediate(); +} + +bool Argument::GetImmediateU1() const { + return value.GetU1(); +} + +u8 Argument::GetImmediateU8() const { + const u64 imm = value.GetImmediateAsU64(); + ASSERT(imm < 0x100); + return u8(imm); +} + +u16 Argument::GetImmediateU16() const { + const u64 imm = value.GetImmediateAsU64(); + ASSERT(imm < 0x10000); + return u16(imm); +} + +u32 Argument::GetImmediateU32() const { + const u64 imm = value.GetImmediateAsU64(); + ASSERT(imm < 0x100000000); + return u32(imm); +} + +u64 Argument::GetImmediateU64() const { + return value.GetImmediateAsU64(); +} + +IR::Cond Argument::GetImmediateCond() const { + ASSERT(IsImmediate() && GetType() == IR::Type::Cond); + return value.GetCond(); +} + +IR::AccType Argument::GetImmediateAccType() const { + ASSERT(IsImmediate() && GetType() == IR::Type::AccType); + return value.GetAccType(); +} + +bool HostLocInfo::Contains(const IR::Inst* value) const { + return std::find(values.begin(), values.end(), value) != values.end(); +} + +void HostLocInfo::SetupScratchLocation() { + ASSERT(IsCompletelyEmpty()); + realized = true; +} + +bool HostLocInfo::IsCompletelyEmpty() const { + return values.empty() && !locked && !realized && !accumulated_uses && !expected_uses && !uses_this_inst; +} + +void HostLocInfo::UpdateUses() { + accumulated_uses += uses_this_inst; + uses_this_inst = 0; + + if (accumulated_uses == expected_uses) { + values.clear(); + accumulated_uses = 0; + expected_uses = 0; + } +} + +RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) { + ArgumentInfo ret = {Argument{*this}, Argument{*this}, Argument{*this}, Argument{*this}}; + for (size_t i = 0; i < inst->NumArgs(); i++) { + const IR::Value arg = inst->GetArg(i); + ret[i].value = arg; + if (!arg.IsImmediate() && !IsValuelessType(arg.GetType())) { + ASSERT(ValueLocation(arg.GetInst()) && "argument must already been defined"); + ValueInfo(arg.GetInst()).uses_this_inst++; + } + } + return ret; +} + +bool RegAlloc::IsValueLive(IR::Inst* inst) const { + return !!ValueLocation(inst); +} + +void RegAlloc::UpdateAllUses() { + for (auto& gpr : gprs) { + gpr.UpdateUses(); + } + for (auto& fpr : fprs) { + fpr.UpdateUses(); + } + for (auto& spill : spills) { + spill.UpdateUses(); + } +} + +void RegAlloc::DefineAsExisting(IR::Inst* inst, Argument& arg) { + ASSERT(!ValueLocation(inst)); + + if (arg.value.IsImmediate()) { + inst->ReplaceUsesWith(arg.value); + return; + } + + auto& info = ValueInfo(arg.value.GetInst()); + info.values.emplace_back(inst); + info.expected_uses += inst->UseCount(); +} + +void RegAlloc::AssertNoMoreUses() const { + const auto is_empty = [](const auto& i) { return i.IsCompletelyEmpty(); }; + ASSERT(std::all_of(gprs.begin(), gprs.end(), is_empty)); + ASSERT(std::all_of(fprs.begin(), fprs.end(), is_empty)); + ASSERT(std::all_of(spills.begin(), spills.end(), is_empty)); +} + +u32 RegAlloc::AllocateRegister(const std::array& regs, const std::vector& order) const { + const auto empty = std::find_if(order.begin(), order.end(), [&](u32 i) { return regs[i].values.empty() && !regs[i].locked; }); + if (empty != order.end()) + return *empty; + + std::vector candidates; + std::copy_if(order.begin(), order.end(), std::back_inserter(candidates), [&](u32 i) { return !regs[i].locked; }); + // TODO: LRU + return candidates[0]; +} + +void RegAlloc::SpillGpr(u32 index) { + ASSERT(!gprs[index].locked && !gprs[index].realized); + if (gprs[index].values.empty()) + return; + const u32 new_location_index = FindFreeSpill(); + //as.SD(powah::GPR{index}, spill_offset + new_location_index * spill_slot_size, powah::sp); + spills[new_location_index] = std::exchange(gprs[index], {}); +} + +void RegAlloc::SpillFpr(u32 index) { + ASSERT(!fprs[index].locked && !fprs[index].realized); + if (fprs[index].values.empty()) { + return; + } + const u32 new_location_index = FindFreeSpill(); + //as.FSD(powah::FPR{index}, spill_offset + new_location_index * spill_slot_size, powah::sp); + spills[new_location_index] = std::exchange(fprs[index], {}); +} + +u32 RegAlloc::FindFreeSpill() const { + const auto iter = std::find_if(spills.begin(), spills.end(), [](const HostLocInfo& info) { return info.values.empty(); }); + ASSERT(iter != spills.end() && "All spill locations are full"); + return u32(iter - spills.begin()); +} + +std::optional RegAlloc::ValueLocation(const IR::Inst* value) const { + const auto contains_value = [value](const HostLocInfo& info) { + return info.Contains(value); + }; + if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) { + return HostLoc{HostLoc::Kind::Gpr, static_cast(iter - gprs.begin())}; + } else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), contains_value); iter != fprs.end()) { + return HostLoc{HostLoc::Kind::Fpr, static_cast(iter - fprs.begin())}; + } else if (const auto iter = std::find_if(spills.begin(), spills.end(), contains_value); iter != spills.end()) { + return HostLoc{HostLoc::Kind::Spill, static_cast(iter - spills.begin())}; + } + return std::nullopt; +} + +HostLocInfo& RegAlloc::ValueInfo(HostLoc host_loc) { + switch (host_loc.kind) { + case HostLoc::Kind::Gpr: + return gprs[size_t(host_loc.index)]; + case HostLoc::Kind::Fpr: + return fprs[size_t(host_loc.index)]; + case HostLoc::Kind::Spill: + return spills[size_t(host_loc.index)]; + } + UNREACHABLE(); +} + +HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) { + const auto contains_value = [value](const HostLocInfo& info) { + return info.Contains(value); + }; + if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) { + return *iter; + } else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), contains_value); iter != gprs.end()) { + return *iter; + } else if (const auto iter = std::find_if(spills.begin(), spills.end(), contains_value); iter != gprs.end()) { + return *iter; + } + UNREACHABLE(); +} + +powah::GPR RegAlloc::ScratchGpr(std::optional> desired_locations) { + UNREACHABLE(); +} + +void RegAlloc::Use(Argument& arg, HostLoc host_loc) { + UNREACHABLE(); +} + +void RegAlloc::UseScratch(Argument& arg, HostLoc host_loc) { + UNREACHABLE(); +} + +powah::GPR RegAlloc::UseGpr(Argument& arg) { + UNREACHABLE(); +} + +powah::GPR RegAlloc::UseScratchGpr(Argument& arg) { + UNREACHABLE(); +} + +void RegAlloc::DefineValue(IR::Inst* inst, powah::GPR const gpr) noexcept { + UNREACHABLE(); +} + +void RegAlloc::DefineValue(IR::Inst* inst, Argument& arg) noexcept { + UNREACHABLE(); +} + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h new file mode 100644 index 0000000000..5e73513d14 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -0,0 +1,114 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include "dynarmic/common/assert.h" +#include "dynarmic/common/common_types.h" +#include + +#include "dynarmic/backend/ppc64/stack_layout.h" +#include "dynarmic/ir/cond.h" +#include "dynarmic/ir/microinstruction.h" +#include "dynarmic/ir/value.h" + +namespace Dynarmic::Backend::PPC64 { + +class RegAlloc; + +enum class HostLoc : uint8_t { + R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, + R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, + R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, + R30, R31, + VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9, + VR10, VR11, VR12, VR13, VR14, VR15, VR16, VR17, VR18, VR19, + VR20, VR21, VR22, VR23, VR24, VR25, VR26, VR27, VR28, VR29, + VR30, VR31, + FirstSpill, +}; + +struct Argument { +public: + using copyable_reference = std::reference_wrapper; + + IR::Type GetType() const; + bool IsImmediate() const; + + bool GetImmediateU1() const; + u8 GetImmediateU8() const; + u16 GetImmediateU16() const; + u32 GetImmediateU32() const; + u64 GetImmediateU64() const; + IR::Cond GetImmediateCond() const; + IR::AccType GetImmediateAccType() const; + +private: + friend class RegAlloc; + explicit Argument(RegAlloc& reg_alloc) + : reg_alloc{reg_alloc} {} + + bool allocated = false; + RegAlloc& reg_alloc; + IR::Value value; +}; + +struct HostLocInfo final { + std::vector values; + size_t locked = 0; + size_t uses_this_inst = 0; + size_t accumulated_uses = 0; + size_t expected_uses = 0; + bool realized = false; + + bool Contains(const IR::Inst*) const; + void SetupScratchLocation(); + bool IsCompletelyEmpty() const; + void UpdateUses(); +}; + +class RegAlloc { +public: + using ArgumentInfo = std::array; + + explicit RegAlloc(powah::Context& as) : as{as} {} + + ArgumentInfo GetArgumentInfo(IR::Inst* inst); + bool IsValueLive(IR::Inst* inst) const; + void DefineAsExisting(IR::Inst* inst, Argument& arg); + + void SpillAll(); + void UpdateAllUses(); + void AssertNoMoreUses() const; + + powah::GPR ScratchGpr(std::optional> desired_locations = {}); + void Use(Argument& arg, HostLoc host_loc); + void UseScratch(Argument& arg, HostLoc host_loc); + powah::GPR UseGpr(Argument& arg); + powah::GPR UseScratchGpr(Argument& arg); + void DefineValue(IR::Inst* inst, powah::GPR const gpr) noexcept; + void DefineValue(IR::Inst* inst, Argument& arg) noexcept; +private: + u32 AllocateRegister(const std::array& regs, const std::vector& order) const; + void SpillGpr(u32 index); + void SpillFpr(u32 index); + u32 FindFreeSpill() const; + + std::optional ValueLocation(const IR::Inst* value) const; + HostLocInfo& ValueInfo(HostLoc host_loc); + HostLocInfo& ValueInfo(const IR::Inst* value); + + powah::Context& as; + std::array gprs; + std::array fprs; + std::array spills; +}; + +} // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h new file mode 100644 index 0000000000..bb70a359a9 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +#include "dynarmic/common/common_types.h" + +namespace Dynarmic::Backend::PPC64 { + +constexpr size_t SpillCount = 64; + +struct alignas(16) StackLayout { + s64 cycles_remaining; + s64 cycles_to_run; + + std::array spill; + + u32 save_host_fpcr; + u32 save_host_fpsr; + + bool check_bit; +}; + +static_assert(sizeof(StackLayout) % 16 == 0); + +} // namespace Dynarmic::Backend::RV64 From a86e24731d8966c61c1212635c1a7b10839d28e4 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 2 Nov 2025 10:30:54 +0000 Subject: [PATCH 03/49] cross compile instructions Signed-off-by: lizzie --- docs/CrossCompile.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/CrossCompile.md b/docs/CrossCompile.md index 06bac5d9db..f5aac2f939 100644 --- a/docs/CrossCompile.md +++ b/docs/CrossCompile.md @@ -88,3 +88,39 @@ And finally, run the compiled executable with QEMU! ```sh qemu-aarch64 build/aarch64/bin/eden ``` + +## PowerPC + +This is a guide for FreeBSD users mainly. + +Now you got a PowerPC sysroot - quickly decompress it somewhere, say `/home/user/opt/powerpc64le`. + +```sh +fetch https://download.freebsd.org/ftp/releases/powerpc/powerpc64le/14.3-RELEASE/base.txz +mkdir -p ~/opt/powerpc64le/sysroot +mkdir -p ~/opt/powerpc64le/staging +cd ~/opt/powerpc64le/sysroot +tar -xvzf base.txz +``` + +Create a toolchain file, for example `powerpc64le-toolchain.cmake`; always [consult the manual](https://man.freebsd.org/cgi/man.cgi?query=cmake-toolchains&sektion=7&manpath=FreeBSD+13.2-RELEASE+and+Ports). + +```sh +set(CMAKE_SYSROOT "$ENV{HOME}/opt/powerpc64le/sysroot") +set(CMAKE_STAGING_PREFIX "$ENV{HOME}/opt/powerpc64le/sysroot") + +set(CMAKE_C_COMPILER /usr/bin/clang) +set(CMAKE_CXX_COMPILER /usr/bin/clang++) +set(CMAKE_C_FLAGS "--target=ppc64le-pc-freebsd") +set(CMAKE_CXX_FLAGS "--target=ppc64le-pc-freebsd") + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +``` + +Specify: +- `YUZU_USE_CPM`: Set this to `ON` so packages can be found and built if your sysroot doesn't have them. +- `YUZU_USE_EXTERNAL_FFMPEG`: Set this to `ON` as well. + From 0325b44d8e2838681ab37cb460b941509b9f3a70 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 2 Nov 2025 20:37:30 +0000 Subject: [PATCH 04/49] spinlocks, annoyances with organistaion Signed-off-by: lizzie --- externals/powah/data2code.c | 107 ++++++++++++------ externals/powah/powah_emit.hpp | 14 ++- externals/powah/powah_gen_base.hpp | 20 ++-- src/dynarmic/src/dynarmic/CMakeLists.txt | 4 + .../src/dynarmic/backend/ppc64/a32_core.h | 4 +- .../dynarmic/backend/ppc64/a32_interface.cpp | 16 ++- .../src/dynarmic/backend/ppc64/a64_core.h | 15 +-- .../dynarmic/backend/ppc64/a64_interface.cpp | 84 +++++++------- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 8 ++ .../ppc64/emit_ppc64_data_processing.cpp | 2 +- .../backend/ppc64/exclusive_monitor.cpp | 50 ++++++++ .../src/dynarmic/backend/ppc64/hostloc.h | 26 +++++ .../src/dynarmic/backend/ppc64/reg_alloc.cpp | 43 +++---- .../src/dynarmic/backend/ppc64/reg_alloc.h | 14 +-- .../src/dynarmic/common/spin_lock_ppc64.cpp | 71 ++++++++++++ .../src/dynarmic/common/spin_lock_ppc64.h | 13 +++ 16 files changed, 356 insertions(+), 135 deletions(-) create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp create mode 100644 src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h create mode 100644 src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp create mode 100644 src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h diff --git a/externals/powah/data2code.c b/externals/powah/data2code.c index 2f276b29c7..3e6bad32c8 100644 --- a/externals/powah/data2code.c +++ b/externals/powah/data2code.c @@ -51,30 +51,53 @@ int main(int argc, char *argv[]) { int i_extopc = atoi(sec); //printf("// %s\n", mem); if (!strcmp(form, "XO")) { - if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) - printf("//"); - printf( - "void %s(GPR const rt, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, rt, ra, rb, false, false); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); - printf( - "void %sC(GPR const rt, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, rt, ra, rb, true, false); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); - if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) - printf("//"); - printf( - "void %s_(GPR const rt, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, rt, ra, rb, false, true); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); - printf( - "void %sC_(GPR const rt, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, rt, ra, rb, true, true); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + if (!strcmp(mem, "EXTSH")) { + printf( + "void %s(GPR const rt, GPR const ra) {" + " emit_%s(0x%08x, rt, ra, R0, false, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sC(GPR const rt, GPR const ra) {" + " emit_%s(0x%08x, rt, ra, R0, true, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rt, GPR const ra) {" + " emit_%s(0x%08x, rt, ra, R0, false, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sC_(GPR const rt, GPR const ra) {" + " emit_%s(0x%08x, rt, ra, R0, true, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else { + if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) + printf("//"); + printf( + "void %s(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, false, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sC(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, true, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) + printf("//"); + printf( + "void %s_(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, false, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %sC_(GPR const rt, GPR const ra, GPR const rb) {" + " emit_%s(0x%08x, rt, ra, rb, true, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } } else if (!strcmp(form, "X")) { if (!strcmp(mem, "CMPL") || !strcmp(mem, "CMP")) { @@ -83,7 +106,8 @@ int main(int argc, char *argv[]) { " emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, rb, false); " "}\n" , mem, form, i_opcode << 26); - } else if (strcmp(mem, "CNTLZD") == 0 || strcmp(mem, "CNTLZW") == 0) { + } else if (!strcmp(mem, "CNTLZD") || !strcmp(mem, "CNTLZW") + || !strcmp(mem, "EXTSB") || !strcmp(mem, "EXTSH") || !strcmp(mem, "EXTSW")) { printf( "void %s(GPR const rt, GPR const ra) {" " emit_%s(0x%08x, rt, ra, R0, false); " @@ -204,16 +228,29 @@ int main(int argc, char *argv[]) { , mem, form, (i_opcode << 26) | (i_extopc << 1)); } } else if (!strcmp(form, "M")) { - printf( - "void %s(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" - " emit_%s(0x%08x, rs, ra, sh, mb, me, false); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); - printf( - "void %s_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" - " emit_%s(0x%08x, rs, ra, sh, mb, me, true); " - "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + if (!strcmp(mem, "RLWNM")) { + printf( + "void %s(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) {" + " emit_%s(0x%08x, rs, ra, rb.index, mb, me, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) {" + " emit_%s(0x%08x, rs, ra, rb.index, mb, me, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } else { + printf( + "void %s(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" + " emit_%s(0x%08x, rs, ra, sh, mb, me, false); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + printf( + "void %s_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" + " emit_%s(0x%08x, rs, ra, sh, mb, me, true); " + "}\n" + , mem, form, (i_opcode << 26) | (i_extopc << 1)); + } } else if (!strcmp(form, "MD")) { printf( "void %s(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) {" diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 3a28910a75..d10fc835ff 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -110,6 +110,7 @@ constexpr inline CPR CR6{24}; constexpr inline CPR CR7{28}; struct Context { + Context() = default; Context(void* ptr, size_t size) : base{reinterpret_cast(ptr)} , offset{0} @@ -280,6 +281,8 @@ struct Context { // Extended Memmonics, hand coded :) void MR(GPR const ra, GPR const rs) { OR(ra, rs, rs); } + void NOP() { ORI(R0, R0, 0); } + void NOT(GPR const ra, GPR const rs) { NOR(ra, rs, rs); } void ROTLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, n, 0); } void ROTRDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 64 - n, 0); } @@ -287,6 +290,9 @@ struct Context { void ROTLWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, n, 0, 31); } void ROTRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 32 - n, 0, 31); } + void ROTLW(GPR const ra, GPR const rs, GPR const rb) { RLWNM(ra, rs, rb, 0, 31); } + void ROTLD(GPR const ra, GPR const rs, GPR const rb) { RLDCL(ra, rs, rb, 0); } + void EXTLDI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLDICR(ra, rs, b, n - 1); } void SLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICR(ra, rs, n, 63 - n); } void CLRLDI(GPR const ra, GPR const rs, uint32_t n) { RLDICL(ra, rs, 0, n); } @@ -298,7 +304,7 @@ struct Context { void EXTLWI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLWINM(ra, rs, b, 0, n - 1); } void SRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 32 - n, n, 31); } - void CLRRWI(GPR const ra, GPR const rs, uint32_t n, uint32_t b) { RLWINM(ra, rs, 0, 0, 31 - n); } + void CLRRWI(GPR const ra, GPR const rs, uint32_t n) { RLWINM(ra, rs, 0, 0, 31 - n); } void CRSET(CPR const bx) { CREQV(bx, bx, bx); } void CRCLR(CPR const bx) { CRXOR(bx, bx, bx); } @@ -320,8 +326,14 @@ struct Context { void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 1, rx, si); } void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 1, rx, ry); } + void BLR() { BCLR(R0, CR0, R0); } + // TODO: PowerPC 11 stuff void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) { + (void)rd; + (void)ra; + (void)rb; + (void)d; std::unreachable(); } void ISELLT(GPR const rd, GPR const ra, GPR const rb) { ISEL(rd, ra, rb, 0); } diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index cd1b7bc17b..7783bf56d6 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -124,14 +124,14 @@ void EIEIO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, rt, ra void EIEIO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, rt, ra, rb, true); } void EQV(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, rt, ra, rb, false); } void EQV_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, rt, ra, rb, true); } -void EXTSB(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000774, rt, ra, rb, false); } -void EXTSB_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000774, rt, ra, rb, true); } -void EXTSH(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, false, false); } -void EXTSHC(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, true, false); } -void EXTSH_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, false, true); } -void EXTSHC_(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000734, rt, ra, rb, true, true); } -void EXTSW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007b4, rt, ra, rb, false); } -void EXTSW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007b4, rt, ra, rb, true); } +void EXTSB(GPR const rt, GPR const ra) { emit_X(0x7c000774, rt, ra, R0, false); } +void EXTSB_(GPR const rt, GPR const ra) { emit_X(0x7c000774, rt, ra, R0, true); } +void EXTSH(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, false, false); } +void EXTSHC(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, true, false); } +void EXTSH_(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, false, true); } +void EXTSHC_(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, true, true); } +void EXTSW(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, rt, ra, R0, false); } +void EXTSW_(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, rt, ra, R0, true); } void FABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, rt, ra, rb, false); } void FABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, rt, ra, rb, true); } void FADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002a, frt, fra, frb, frc, false); } @@ -349,8 +349,8 @@ void RLWIMI(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = void RLWIMI_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, rs, ra, sh, mb, me, true); } void RLWINM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, rs, ra, sh, mb, me, false); } void RLWINM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, rs, ra, sh, mb, me, true); } -void RLWNM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, sh, mb, me, false); } -void RLWNM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, sh, mb, me, true); } +void RLWNM(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, rb.index, mb, me, false); } +void RLWNM_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, rb.index, mb, me, true); } void SC(uint32_t lev) { emit_SC(0x44000000, lev); } void SI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x30000000, rt, ra, d); } void SI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x34000000, rt, ra, d); } diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index a21b56eea3..1523b0a0b3 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -306,9 +306,13 @@ if ("ppc64" IN_LIST ARCHITECTURE) backend/ppc64/emit_ppc64_vector.cpp backend/ppc64/emit_ppc64.cpp backend/ppc64/emit_ppc64.h + backend/ppc64/exclusive_monitor.cpp backend/ppc64/reg_alloc.cpp backend/ppc64/reg_alloc.h backend/ppc64/stack_layout.h + backend/ppc64/hostloc.h + common/spin_lock_ppc64.cpp + common/spin_lock_ppc64.h # A32 backend/ppc64/a32_core.h backend/ppc64/a32_interface.cpp diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index e90b7b203b..2d113e8c8f 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -16,12 +16,12 @@ namespace Dynarmic::Backend::PPC64 { struct A32JitState { - alignas(16) std::array vec{}; + alignas(16) std::array ext_regs{}; std::array regs{}; u32 upper_location_descriptor; u32 exclusive_state = 0; u32 cpsr_nzcv = 0; - u32 fpsr = 0; + u32 fpscr = 0; IR::LocationDescriptor GetLocationDescriptor() const { return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index 025fc0c989..178bb9775a 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -9,8 +9,12 @@ #include #include "dynarmic/common/common_types.h" +#include "dynarmic/frontend/A32/a32_location_descriptor.h" +#include "dynarmic/frontend/A32/translate/a32_translate.h" +#include "dynarmic/interface/A32/config.h" #include "dynarmic/backend/ppc64/a32_core.h" #include "dynarmic/common/atomic.h" +#include "dynarmic/ir/opt_passes.h" #include "dynarmic/interface/A32/a32.h" namespace Dynarmic::Backend::PPC64 { @@ -69,8 +73,12 @@ void A32AddressSpace::Link(EmittedBlockInfo& block_info) { UNREACHABLE(); } +} + namespace Dynarmic::A32 { +using namespace Dynarmic::Backend::PPC64; + struct Jit::Impl final { Impl(Jit* jit_interface, A32::UserConfig conf) : jit_interface(jit_interface) @@ -130,19 +138,19 @@ struct Jit::Impl final { } u32 Cpsr() const { - return current_state.Cpsr(); + return current_state.cpsr_nzcv; } void SetCpsr(u32 value) { - current_state.SetCpsr(value); + current_state.cpsr_nzcv = value; } u32 Fpscr() const { - return current_state.Fpscr(); + return current_state.fpscr; } void SetFpscr(u32 value) { - current_state.SetFpscr(value); + current_state.fpscr = value; } void ClearExclusiveState() { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 5e3edabe48..4236e1f281 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -20,10 +20,15 @@ struct A64JitState { using ProgramCounterType = u32; alignas(16) std::array vec{}; std::array regs{}; + u64 sp = 0; + u64 pc = 0; u32 upper_location_descriptor; u32 exclusive_state = 0; u32 cpsr_nzcv = 0; + u32 pstate = 0; + u32 fpcr = 0; u32 fpsr = 0; + volatile u32 halt_reason = 0; IR::LocationDescriptor GetLocationDescriptor() const { return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; } @@ -32,15 +37,9 @@ struct A64JitState { class A64AddressSpace final { public: explicit A64AddressSpace(const A64::UserConfig& conf); - - IR::Block GenerateIR(IR::LocationDescriptor) const; - CodePtr Get(IR::LocationDescriptor descriptor); - CodePtr GetOrEmit(IR::LocationDescriptor descriptor); - void ClearCache(); - private: friend class A64Core; @@ -49,16 +48,12 @@ private: void Link(EmittedBlockInfo& block); const A64::UserConfig conf; - CodeBlock cb; powah::Context as; - ankerl::unordered_dense::map block_entries; ankerl::unordered_dense::map block_infos; - struct PreludeInfo { CodePtr end_of_prelude; - using RunCodeFuncType = HaltReason (*)(CodePtr entry_point, A64JitState* context, volatile u32* halt_reason); RunCodeFuncType run_code; CodePtr return_from_run_code; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index a0232a6ced..b324a8897f 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -8,9 +8,12 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" -#include "dynarmic/backend/ppc64/a64_core.h" +#include "dynarmic/frontend/A64/a64_location_descriptor.h" +#include "dynarmic/frontend/A64/translate/a64_translate.h" +#include "dynarmic/interface/A64/config.h" #include "dynarmic/backend/ppc64/a64_core.h" #include "dynarmic/common/atomic.h" +#include "dynarmic/ir/opt_passes.h" #include "dynarmic/interface/A64/a64.h" namespace Dynarmic::Backend::PPC64 { @@ -22,28 +25,25 @@ A64AddressSpace::A64AddressSpace(const A64::UserConfig& conf) EmitPrelude(); } -IR::Block A64AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const { - IR::Block ir_block = A64::Translate(A64::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); - Optimization::Optimize(ir_block, conf, {}); - return ir_block; -} - CodePtr A64AddressSpace::Get(IR::LocationDescriptor descriptor) { - if (const auto iter = block_entries.find(descriptor.Value()); iter != block_entries.end()) + if (auto const iter = block_entries.find(descriptor.Value()); iter != block_entries.end()) return iter->second; return nullptr; } -CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) { - if (CodePtr block_entry = Get(descriptor)) { +CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor desc) { + if (CodePtr block_entry = Get(desc)) return block_entry; - } - IR::Block ir_block = GenerateIR(descriptor); + const auto get_code = [this](u64 vaddr) { + return conf.callbacks->MemoryReadCode(vaddr); + }; + IR::Block ir_block = A64::Translate(A64::LocationDescriptor{desc}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); + Optimization::Optimize(ir_block, conf, {}); const EmittedBlockInfo block_info = Emit(std::move(ir_block)); - block_infos.insert_or_assign(descriptor.Value(), block_info); - block_entries.insert_or_assign(descriptor.Value(), block_info.entry_point); + block_infos.insert_or_assign(desc.Value(), block_info); + block_entries.insert_or_assign(desc.Value(), block_info.entry_point); return block_info.entry_point; } @@ -59,7 +59,7 @@ void A64AddressSpace::EmitPrelude() { EmittedBlockInfo A64AddressSpace::Emit(IR::Block block) { EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { .enable_cycle_counting = conf.enable_cycle_counting, - .always_little_endian = conf.always_little_endian, + .always_little_endian = true, }); Link(block_info); return block_info; @@ -72,18 +72,19 @@ void A64AddressSpace::Link(EmittedBlockInfo& block_info) { namespace Dynarmic::A64 { +using namespace Dynarmic::Backend::PPC64; + struct Jit::Impl final { Impl(Jit* jit_interface, A64::UserConfig conf) - : jit_interface(jit_interface) - , conf(conf) - , current_address_space(conf) - , core(conf) {} + : conf(conf) + , emitter(conf) {} HaltReason Run() { ASSERT(!is_executing); //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason))); is_executing = true; - const HaltReason hr = block_of_code.RunCode(&jit_state, current_code_ptr); + auto const current_loc = jit_state.GetLocationDescriptor(); + const HaltReason hr = {};//block_of_code.RunCode(&jit_state, jit_state.GetOrEmit(current_loc)); //PerformRequestedCacheInvalidation(hr); is_executing = false; return hr; @@ -91,12 +92,13 @@ struct Jit::Impl final { HaltReason Step() { ASSERT(!is_executing); - //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason))); - is_executing = true; - const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); - //PerformRequestedCacheInvalidation(hr); - is_executing = false; - return hr; + // //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason))); + // is_executing = true; + // //const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); + // //PerformRequestedCacheInvalidation(hr); + // is_executing = false; + // return hr; + return {}; } void ClearCache() { @@ -142,23 +144,21 @@ struct Jit::Impl final { } u64 GetRegister(size_t index) const { - if (index == 31) - return GetSP(); - return jit_state.reg.at(index); + return index == 31 ? GetSP() : jit_state.regs.at(index); } void SetRegister(size_t index, u64 value) { if (index == 31) return SetSP(value); - jit_state.reg.at(index) = value; + jit_state.regs.at(index) = value; } std::array GetRegisters() const { - return jit_state.reg; + return jit_state.regs; } void SetRegisters(const std::array& value) { - jit_state.reg = value; + jit_state.regs = value; } Vector GetVector(size_t index) const { @@ -183,27 +183,27 @@ struct Jit::Impl final { } u32 GetFpcr() const { - return jit_state.GetFpcr(); + return jit_state.fpcr; } void SetFpcr(u32 value) { - jit_state.SetFpcr(value); + jit_state.fpcr = value; } u32 GetFpsr() const { - return jit_state.GetFpsr(); + return jit_state.fpsr; } void SetFpsr(u32 value) { - jit_state.SetFpsr(value); + jit_state.fpsr = value; } u32 GetPstate() const { - return jit_state.GetPstate(); + return jit_state.pstate; } void SetPstate(u32 value) { - jit_state.SetPstate(value); + jit_state.pstate = value; } void ClearExclusiveState() { @@ -214,6 +214,13 @@ struct Jit::Impl final { return is_executing; } + std::string Disassemble() const { + // const size_t size = reinterpret_cast(block_of_code.getCurr()) - reinterpret_cast(block_of_code.GetCodeBegin()); + // auto const* p = reinterpret_cast(block_of_code.GetCodeBegin()); + // return Common::DisassemblePPC64(p, p + size); + return {}; + } + private: void RequestCacheInvalidation() { // UNREACHABLE(); @@ -225,7 +232,6 @@ private: const UserConfig conf; A64JitState jit_state; A64AddressSpace emitter; - BlockOfCode block_of_code; Optimization::PolyfillOptions polyfill_options; bool invalidate_entire_cache = false; boost::icl::interval_set invalid_cache_ranges; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index e47be9fe6a..719091c872 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -3,10 +3,18 @@ #pragma once +#include +#include "dynarmic/common/common_types.h" + namespace Dynarmic::Backend::PPC64 { constexpr powah::GPR RJIT = powah::R31; +constexpr powah::GPR ABI_PARAM1 = powah::R3; +constexpr powah::GPR ABI_PARAM2 = powah::R4; +constexpr powah::GPR ABI_PARAM3 = powah::R5; +constexpr powah::GPR ABI_PARAM4 = powah::R6; + constexpr std::initializer_list GPR_ORDER{8, 9, 18, 19, 20, 21, 22, 23, 24, 25, 5, 6, 7, 28, 29, 10, 11, 12, 13, 14, 15, 16, 17}; constexpr std::initializer_list FPR_ORDER{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; 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 80aa9a13d5..a376929a36 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 @@ -423,7 +423,7 @@ void EmitIR(powah::Context& code, Emit auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); - code.SRAL(result, source, source); + code.SRAD(result, source, source); ctx.reg_alloc.DefineValue(inst, result); } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp new file mode 100644 index 0000000000..9fcb0f0629 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "dynarmic/interface/exclusive_monitor.h" +#include +#include "dynarmic/common/assert.h" + +namespace Dynarmic { + +ExclusiveMonitor::ExclusiveMonitor(std::size_t processor_count) + : exclusive_addresses(processor_count, INVALID_EXCLUSIVE_ADDRESS), exclusive_values(processor_count) {} + +size_t ExclusiveMonitor::GetProcessorCount() const { + return exclusive_addresses.size(); +} + +void ExclusiveMonitor::Lock() { + lock.Lock(); +} + +void ExclusiveMonitor::Unlock() { + lock.Unlock(); +} + +bool ExclusiveMonitor::CheckAndClear(std::size_t processor_id, VAddr address) { + const VAddr masked_address = address & RESERVATION_GRANULE_MASK; + Lock(); + if (exclusive_addresses[processor_id] != masked_address) { + Unlock(); + return false; + } + for (VAddr& other_address : exclusive_addresses) + if (other_address == masked_address) + other_address = INVALID_EXCLUSIVE_ADDRESS; + return true; +} + +void ExclusiveMonitor::Clear() { + Lock(); + std::fill(exclusive_addresses.begin(), exclusive_addresses.end(), INVALID_EXCLUSIVE_ADDRESS); + Unlock(); +} + +void ExclusiveMonitor::ClearProcessor(size_t processor_id) { + Lock(); + exclusive_addresses[processor_id] = INVALID_EXCLUSIVE_ADDRESS; + Unlock(); +} + +} // namespace Dynarmic diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h new file mode 100644 index 0000000000..17b1f71517 --- /dev/null +++ b/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "dynarmic/common/common_types.h" + +namespace Dynarmic::Backend::PPC64 { + +enum class HostLoc : uint8_t { + R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, + R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, + R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, + R30, R31, + FR0, FR1, FR2, FR3, FR4, FR5, FR6, FR7, FR8, FR9, + FR10, FR11, FR12, FR13, FR14, FR15, FR16, FR17, FR18, FR19, + FR20, FR21, FR22, FR23, FR24, FR25, FR26, FR27, FR28, FR29, + FR30, FR31, + VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9, + VR10, VR11, VR12, VR13, VR14, VR15, VR16, VR17, VR18, VR19, + VR20, VR21, VR22, VR23, VR24, VR25, VR26, VR27, VR28, VR29, + VR30, VR31, + FirstSpill, +}; + +} // namespace Dynarmic::Backend::PPC64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp index a0c752fded..4e2037790a 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "dynarmic/common/assert.h" #include @@ -175,42 +176,42 @@ u32 RegAlloc::FindFreeSpill() const { } std::optional RegAlloc::ValueLocation(const IR::Inst* value) const { - const auto contains_value = [value](const HostLocInfo& info) { + const auto fn = [value](const HostLocInfo& info) { return info.Contains(value); }; - if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) { - return HostLoc{HostLoc::Kind::Gpr, static_cast(iter - gprs.begin())}; - } else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), contains_value); iter != fprs.end()) { - return HostLoc{HostLoc::Kind::Fpr, static_cast(iter - fprs.begin())}; - } else if (const auto iter = std::find_if(spills.begin(), spills.end(), contains_value); iter != spills.end()) { - return HostLoc{HostLoc::Kind::Spill, static_cast(iter - spills.begin())}; - } + if (const auto iter = std::ranges::find_if(gprs, fn); iter != gprs.end()) + return HostLoc(u32(HostLoc::R0) + u32(iter - gprs.begin())); + else if (const auto iter = std::ranges::find_if(fprs, fn); iter != fprs.end()) + return HostLoc(u32(HostLoc::FR0) + u32(iter - fprs.begin())); + else if (const auto iter = std::ranges::find_if(vprs, fn); iter != vprs.end()) + return HostLoc(u32(HostLoc::VR0) + u32(iter - vprs.begin())); + else if (const auto iter = std::ranges::find_if(spills, fn); iter != spills.end()) + return HostLoc(u32(HostLoc::FirstSpill) + u32(iter - spills.begin())); return std::nullopt; } HostLocInfo& RegAlloc::ValueInfo(HostLoc host_loc) { - switch (host_loc.kind) { - case HostLoc::Kind::Gpr: - return gprs[size_t(host_loc.index)]; - case HostLoc::Kind::Fpr: - return fprs[size_t(host_loc.index)]; - case HostLoc::Kind::Spill: - return spills[size_t(host_loc.index)]; - } + // switch (host_loc.kind) { + // case HostLoc::Kind::Gpr: + // return gprs[size_t(host_loc.index)]; + // case HostLoc::Kind::Fpr: + // return fprs[size_t(host_loc.index)]; + // case HostLoc::Kind::Spill: + // return spills[size_t(host_loc.index)]; + // } UNREACHABLE(); } HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) { - const auto contains_value = [value](const HostLocInfo& info) { + const auto fn = [value](const HostLocInfo& info) { return info.Contains(value); }; - if (const auto iter = std::find_if(gprs.begin(), gprs.end(), contains_value); iter != gprs.end()) { + if (const auto iter = std::find_if(gprs.begin(), gprs.end(), fn); iter != gprs.end()) return *iter; - } else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), contains_value); iter != gprs.end()) { + else if (const auto iter = std::find_if(fprs.begin(), fprs.end(), fn); iter != fprs.end()) return *iter; - } else if (const auto iter = std::find_if(spills.begin(), spills.end(), contains_value); iter != gprs.end()) { + else if (const auto iter = std::find_if(spills.begin(), spills.end(), fn); iter != spills.end()) return *iter; - } UNREACHABLE(); } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h index 5e73513d14..034935e311 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -15,6 +15,7 @@ #include #include "dynarmic/backend/ppc64/stack_layout.h" +#include "dynarmic/backend/ppc64/hostloc.h" #include "dynarmic/ir/cond.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/value.h" @@ -23,18 +24,6 @@ namespace Dynarmic::Backend::PPC64 { class RegAlloc; -enum class HostLoc : uint8_t { - R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, - R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, - R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, - R30, R31, - VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9, - VR10, VR11, VR12, VR13, VR14, VR15, VR16, VR17, VR18, VR19, - VR20, VR21, VR22, VR23, VR24, VR25, VR26, VR27, VR28, VR29, - VR30, VR31, - FirstSpill, -}; - struct Argument { public: using copyable_reference = std::reference_wrapper; @@ -108,6 +97,7 @@ private: powah::Context& as; std::array gprs; std::array fprs; + std::array vprs; std::array spills; }; diff --git a/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp new file mode 100644 index 0000000000..8ce6d40021 --- /dev/null +++ b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include +#include +#include "dynarmic/backend/ppc64/abi.h" +#include "dynarmic/backend/ppc64/hostloc.h" +#include "dynarmic/common/spin_lock.h" +#include "dynarmic/common/assert.h" + +namespace Dynarmic { + +/* +void acquire(atomic_flag* lock) { + while(atomic_flag_test_and_set_explicit( lock, memory_order_acquire)) + ; +} +*/ +void EmitSpinLockLock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp) { + +} + +/* +void release(atomic_flag* lock) { + atomic_flag_clear_explicit(lock, memory_order_release); +} +*/ +void EmitSpinLockUnlock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp) { + +} + +namespace { + +struct SpinLockImpl { + void Initialize(); + powah::Context code; + void* page = nullptr; + void (*lock)(volatile int*); + void (*unlock)(volatile int*); +}; + +std::once_flag flag; +SpinLockImpl impl; + +void SpinLockImpl::Initialize() { + page = mmap(nullptr, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); + ASSERT(page != nullptr); + code = powah::Context(page, 4096); + lock = reinterpret_cast(code.base); + EmitSpinLockLock(code, Backend::PPC64::ABI_PARAM1, Backend::PPC64::ABI_PARAM2); + code.BLR(); + unlock = reinterpret_cast(code.base); + EmitSpinLockUnlock(code, Backend::PPC64::ABI_PARAM1, Backend::PPC64::ABI_PARAM2); + code.BLR(); + // TODO: free the page, rework the stupid spinlock API +} + +} // namespace + +void SpinLock::Lock() noexcept { + std::call_once(flag, &SpinLockImpl::Initialize, impl); + impl.lock(&storage); +} + +void SpinLock::Unlock() noexcept { + std::call_once(flag, &SpinLockImpl::Initialize, impl); + impl.unlock(&storage); +} + +} // namespace Dynarmic diff --git a/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h new file mode 100644 index 0000000000..d2e78cc66f --- /dev/null +++ b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include + +namespace Dynarmic { + +void EmitSpinLockLock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp); +void EmitSpinLockUnlock(powah::Context& code, powah::GPR const ptr, powah::GPR const tmp); + +} // namespace Dynarmic From 8c3404960adb64b1f320d6f1dd266d2ebbf54a63 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sun, 2 Nov 2025 22:27:01 +0000 Subject: [PATCH 05/49] cross compile instructions; ignore toolchain files Signed-off-by: lizzie --- .gitignore | 1 + docs/CrossCompile.md | 32 ++----- externals/powah/powah_emit.hpp | 1 + .../src/dynarmic/backend/ppc64/code_block.h | 3 +- tools/README.md | 1 + tools/setup-cross-sysroot.sh | 86 +++++++++++++++++++ 6 files changed, 98 insertions(+), 26 deletions(-) create mode 100755 tools/setup-cross-sysroot.sh diff --git a/.gitignore b/.gitignore index 20ed5e93c1..4abfc271d2 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ log.txt # Generated source files src/common/scm_rev.cpp dist/english_plurals/generated_en.ts +*-toolchain.cmake # Project/editor files *.swp diff --git a/docs/CrossCompile.md b/docs/CrossCompile.md index f5aac2f939..77bf5106f6 100644 --- a/docs/CrossCompile.md +++ b/docs/CrossCompile.md @@ -93,34 +93,16 @@ qemu-aarch64 build/aarch64/bin/eden This is a guide for FreeBSD users mainly. -Now you got a PowerPC sysroot - quickly decompress it somewhere, say `/home/user/opt/powerpc64le`. +Now you got a PowerPC sysroot - quickly decompress it somewhere, say `/home/user/opt/powerpc64le`. Create a toolchain file, for example `powerpc64le-toolchain.cmake`; always [consult the manual](https://man.freebsd.org/cgi/man.cgi?query=cmake-toolchains&sektion=7&manpath=FreeBSD+13.2-RELEASE+and+Ports). -```sh -fetch https://download.freebsd.org/ftp/releases/powerpc/powerpc64le/14.3-RELEASE/base.txz -mkdir -p ~/opt/powerpc64le/sysroot -mkdir -p ~/opt/powerpc64le/staging -cd ~/opt/powerpc64le/sysroot -tar -xvzf base.txz -``` - -Create a toolchain file, for example `powerpc64le-toolchain.cmake`; always [consult the manual](https://man.freebsd.org/cgi/man.cgi?query=cmake-toolchains&sektion=7&manpath=FreeBSD+13.2-RELEASE+and+Ports). - -```sh -set(CMAKE_SYSROOT "$ENV{HOME}/opt/powerpc64le/sysroot") -set(CMAKE_STAGING_PREFIX "$ENV{HOME}/opt/powerpc64le/sysroot") - -set(CMAKE_C_COMPILER /usr/bin/clang) -set(CMAKE_CXX_COMPILER /usr/bin/clang++) -set(CMAKE_C_FLAGS "--target=ppc64le-pc-freebsd") -set(CMAKE_CXX_FLAGS "--target=ppc64le-pc-freebsd") - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -``` +There is a script to automatically do all of this under `./tools/setup-cross-sysroot.sh` Specify: - `YUZU_USE_CPM`: Set this to `ON` so packages can be found and built if your sysroot doesn't have them. - `YUZU_USE_EXTERNAL_FFMPEG`: Set this to `ON` as well. +Then run using a program such as QEMU to emulate userland syscalls: + +```sh +cmake --build build-ppc64-pc-freebsd -t dynarmic_tests -- -j8 && qemu-ppc64-static -L $HOME/opt/ppc64-freebsd/sysroot ./build-ppc64-pc-freebsd/bin/dynarmic_tests +``` diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index d10fc835ff..82cb2450c9 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -8,6 +8,7 @@ #include #include #include +#include //#ifndef __cpp_lib_unreachable namespace std { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h b/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h index 3877b9c13f..063863100f 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include @@ -15,7 +16,7 @@ namespace Dynarmic::Backend::PPC64 { class CodeBlock { public: explicit CodeBlock(std::size_t size) noexcept : memsize(size) { - mem = (u8*)mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); + mem = (u8*)mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ASSERT(mem != nullptr); } ~CodeBlock() noexcept { diff --git a/tools/README.md b/tools/README.md index cde6a21464..e9315e1dfb 100644 --- a/tools/README.md +++ b/tools/README.md @@ -19,6 +19,7 @@ Tools for Eden and other subprojects. When adding new scripts please use `#!/bin - `shellcheck.sh`: Ensure POSIX compliance (and syntax sanity) for all tools in this directory and subdirectories. - `llvmpipe-run.sh`: Sets environment variables needed to run any command (or Eden) with llvmpipe. - `optimize-assets.sh`: Optimizes PNG assets with OptiPng. +- `setup-cross-sysroot.sh`: Allows to quickly create a sysroot of a given system for cross compilation (experimental). - `update-cpm.sh`: Updates CPM.cmake to the latest version. - `update-icons.sh`: Rebuild all icons (macOS, Windows, bitmaps) based on the master SVG file (`dist/dev.eden_emu.eden.svg`) * Also optimizes the master SVG diff --git a/tools/setup-cross-sysroot.sh b/tools/setup-cross-sysroot.sh new file mode 100755 index 0000000000..746197d911 --- /dev/null +++ b/tools/setup-cross-sysroot.sh @@ -0,0 +1,86 @@ +#!/bin/sh -e +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +die() { + echo "$@" >&2 + exit 1 +} +help() { + cat << EOF +--arch Specify the target architecture (default: ppc64) +--os Specify the OS sysroot to use (default: freebsd) +--sysroot Specify sysroot to use +EOF +} + +TARGET_ARCH="ppc64" +TARGET_OS="freebsd" +TARGET_CMAKE="$TARGET_ARCH-pc-$TARGET_OS" +BASE_DIR="$PWD" + +while true; do + case "$1" in + --arch) shift; TARGET_ARCH=$1; [ -z "$TARGET_ARCH" ] && die "Expected argument";; + --os) shift; TARGET_OS=$1; [ -z "$TARGET_OS" ] && die "Expected argument";; + --sysroot) shift; SYSROOT=$1; [ -z "$SYSROOT" ] && die "Expected argument";; + --help) help "$@";; + --*) die "Invalid option $1" ;; + "$0" | "") break;; + esac + shift +done + +[ -z "$SYSROOT" ] && SYSROOT="$HOME/opt/$TARGET_ARCH-$TARGET_OS/sysroot" +mkdir -p "$SYSROOT" && cd "$SYSROOT" +case "$TARGET_OS" in +freebsd*) + case "$TARGET_ARCH" in + ppc64pe) URL="https://download.freebsd.org/ftp/releases/powerpc/powerpc64pe/14.3-RELEASE/base.txz" break;; + ppc64le) URL="https://download.freebsd.org/ftp/releases/powerpc/powerpc64le/14.3-RELEASE/base.txz" break;; + ppc64) URL="https://download.freebsd.org/ftp/releases/powerpc/powerpc64/14.3-RELEASE/base.txz" break;; + ppc) URL="https://download.freebsd.org/ftp/releases/powerpc/powerpc/14.3-RELEASE/base.txz" break;; + amd64 | x86_64) URL="https://download.freebsd.org/ftp/releases/amd64/14.3-RELEASE/base.txz" break;; + arm64*) URL="https://download.freebsd.org/ftp/releases/arm64/$TARGET_ARCH/14.3-RELEASE/base.txz" break;; + arm*) URL="https://download.freebsd.org/ftp/releases/arm/$TARGET_ARCH/14.3-RELEASE/base.txz" break;; + *) die "Unknown arch $TARGET_ARCH" break;; + esac + [ -z "$TARGET_CMAKE" ] && TARGET_CMAKE="$TARGET_ARCH-pc-$TARGET_OS" + [ -f "base.txz" ] || fetch "$URL" || die "Can't download" + tar -xvzf base.txz + break;; +*) die "Unknown OS $TARGET_OS" break;; +esac + +[ -z "$CC" ] && CC=$(which clang) +[ -z "$CXX" ] && CXX=$(which clang++) + +TOOLCHAIN_FILE="$BASE_DIR/$TARGET_CMAKE-toolchain.cmake" +cat << EOF >"$TOOLCHAIN_FILE" +# Script to generate .cmake toolchain files :) +# See https://man.freebsd.org/cgi/man.cgi?query=cmake-toolchains&sektion=7&manpath=FreeBSD+13.2-RELEASE+and+Ports + +set(CMAKE_SYSROOT "$SYSROOT") +set(CMAKE_STAGING_PREFIX "$SYSROOT") + +set(CMAKE_C_COMPILER $CC) +set(CMAKE_CXX_COMPILER $CXX) +set(CMAKE_C_FLAGS "--target=$TARGET_CMAKE") +set(CMAKE_CXX_FLAGS "--target=$TARGET_CMAKE") + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +EOF + +# cmake \ +# -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \ +# -DCMAKE_BUILD_TYPE=Release \ +# -B "build-$TARGET_CMAKE" \ +# -DDYNARMIC_TESTS=ON \ +# -DENABLE_QT=OFF \ +# -DENABLE_SDL2=OFF \ +# -DYUZU_USE_CPM=ON \ +# -DYUZU_USE_EXTERNAL_FFMPEG=ON +#cmake --build "build-$TARGET_CMAKE" dynarmic_tests -- -j8 From e4c55e1affc526bffe52cd0a80c87b3666d0727a Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 3 Nov 2025 00:23:06 +0000 Subject: [PATCH 06/49] relocations Signed-off-by: lizzie --- externals/powah/data2code.c | 44 +++---- externals/powah/powah_emit.hpp | 106 +++++++++++------ externals/powah/powah_gen_base.hpp | 60 +++++----- externals/powah/tests.cpp | 184 +++++++++++++++++++++-------- 4 files changed, 257 insertions(+), 137 deletions(-) diff --git a/externals/powah/data2code.c b/externals/powah/data2code.c index 3e6bad32c8..90b94202c7 100644 --- a/externals/powah/data2code.c +++ b/externals/powah/data2code.c @@ -26,20 +26,20 @@ int main(int argc, char *argv[]) { *opc++ = '\0'; char *sec = strchr(opc, ','); if (sec) { - struct b_info { const char *s; int o; } infos[] = { - {"",1}, - {"LT",1}, - {"LE",2}, - {"NG",2}, - {"EQ",3}, - {"GE",1}, - {"NL",1}, - {"GT",2}, - {"NE",3}, - {"SO",4}, - {"UN",4}, - {"NS",4}, - {"NU",4}, + struct b_info { const char *s; int o; int p; } infos[] = { + {"",1,0}, + {"LT",1,12}, + {"LE",2,4}, + {"NG",2,4}, + {"EQ",3,12}, + {"GE",1,4}, + {"NL",1,4}, + {"GT",2,12}, + {"NE",3,4}, + {"SO",4,12}, + {"UN",4,12}, + {"NS",4,4}, + {"NU",4,4}, }; if (strchr(mem, '[') != NULL) *strchr(mem, '[') = '\0'; @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) { || !strcmp(mem, "CMP")) { printf( "void %s(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, rb, false); " + " emit_%s(0x%08x, ra, GPR{(bf << 2) | l}, rb, false); " "}\n" , mem, form, i_opcode << 26); } else if (!strcmp(mem, "CNTLZD") || !strcmp(mem, "CNTLZW") @@ -133,26 +133,26 @@ int main(int argc, char *argv[]) { } else if (!strcmp(form, "I")) { printf( "void %s(Label const& i) {" - " emit_reloc_%s(0x%08x, i); " + " emit_reloc_%s(0x%08x, i, false); " "}\n" , mem, form, i_opcode << 26); printf( "void %sL(Label const& i) {" - " emit_reloc_%s(0x%08x, i); " + " emit_reloc_%s(0x%08x, i, true); " "}\n" , mem, form, i_opcode << 26); } else if (!strcmp(form, "B")) { for (int i = 0; i < 12; ++i) { printf( "void %s%s(CPR const cr, Label const& i) {" - " emit_reloc_%s(0x%08x, cr.index + %i, i, false); " + " emit_reloc_%s(0x%08x, %i, cr.index + %i, i, false); " "}\n" - , mem, infos[i].s, form, i_opcode << 26, infos[i].o); + , mem, infos[i].s, form, i_opcode << 26, infos[i].p, infos[i].o - 1); printf( "void %s%sL(CPR const cr, Label const& i) {" - " emit_reloc_%s(0x%08x, cr.index + %i, i, true); " + " emit_reloc_%s(0x%08x, %i, cr.index + %i, i, true); " "}\n" - , mem, infos[i].s, form, i_opcode << 26, infos[i].o); + , mem, infos[i].s, form, i_opcode << 26, infos[i].p, infos[i].o - 1); if (!strcmp(mem, "BC")) mem[1] = '\0'; } } else if (!strcmp(form, "D")) { @@ -160,7 +160,7 @@ int main(int argc, char *argv[]) { || !strcmp(mem, "CMPI")) { printf( "void %s(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) {" - " emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, d); " + " emit_%s(0x%08x, ra, GPR{(bf << 2) | l}, d); " "}\n" , mem, form, i_opcode << 26); } else { diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 82cb2450c9..bc1bfb803b 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -110,6 +110,15 @@ constexpr inline CPR CR5{20}; constexpr inline CPR CR6{24}; constexpr inline CPR CR7{28}; +enum class RelocKind : uint8_t { + FormB, + FormI, +}; +struct RelocInfo { + uint32_t offset; + RelocKind kind; +}; + struct Context { Context() = default; Context(void* ptr, size_t size) @@ -121,10 +130,26 @@ struct Context { ~Context() = default; std::vector labels; + std::vector> relocs; Label DefineLabel() { labels.push_back(0); - return Label{ uint32_t(labels.size()) }; + return Label{ uint32_t(labels.size() - 1) }; + } + + void ApplyRelocs() { + for (auto const [index, info] : relocs) { + assert(labels[index] != 0); //label must have an addr + switch (info.kind) { + case RelocKind::FormB: + base[info.offset] |= bitExt(labels[index] - info.offset, 16, 14); + break; + case RelocKind::FormI: + base[info.offset] |= bitExt(labels[index] - info.offset, 6, 24); + break; + } + } + relocs.clear(); } void LABEL(Label l) { @@ -155,16 +180,16 @@ struct Context { return (value & mask) << (32 - (n + offs)); } void emit_XO(uint32_t op, GPR const rt, GPR const ra, GPR const rb, bool oe, bool rc) { - (void)op; - (void)rt; - (void)ra; - (void)rb; - (void)oe; - (void)rc; - std::abort(); + base[offset++] = (op | + bitExt(rt.index, 6, 5) + | bitExt(ra.index, 11, 5) + | bitExt(rb.index, 16, 5) + | bitExt(oe, 21, 1) + | bitExt(rc, 31, 1) + ); } void emit_D(uint32_t op, GPR const rt, GPR const ra, uint32_t d) { - base[offset++] = __bswap32(op | + base[offset++] = (op | (op == 0x74000000 ? (bitExt(ra.index, 6, 5) | bitExt(rt.index, 11, 5)) : (bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5))) @@ -172,7 +197,7 @@ struct Context { ); } void emit_X(uint32_t op, GPR const ra, GPR const rt, GPR const rb, bool rc) { - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5) | bitExt(rb.index, 16, 5) @@ -180,7 +205,7 @@ struct Context { ); } void emit_XS(uint32_t op, GPR const rt, GPR const ra, uint32_t sh, bool rc) { - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5) | bitExt(sh, 16, 5) @@ -188,20 +213,22 @@ struct Context { | bitExt(rc, 31, 1) ); } - void emit_reloc_I(uint32_t op, Label const& l) { - (void)op; - (void)l; - std::abort(); + void emit_reloc_I(uint32_t op, Label const& l, bool lk) { + relocs.emplace_back(l.index, RelocInfo{ offset, RelocKind::FormI }); + base[offset++] = (op | + bitExt(lk, 31, 1) + ); } - void emit_reloc_B(uint32_t op, uint32_t cri, Label const& l, bool lk) { - (void)op; - (void)cri; - (void)l; - (void)lk; - std::abort(); + void emit_reloc_B(uint32_t op, uint32_t bo, uint32_t cri, Label const& l, bool lk) { + relocs.emplace_back(l.index, RelocInfo{ offset, RelocKind::FormB }); + base[offset++] = (op | + bitExt(bo, 6, 5) + | bitExt(cri, 11, 5) + | bitExt(lk, 31, 1) + ); } void emit_XL(uint32_t op, uint32_t bt, uint32_t ba, uint32_t bb, bool lk) { - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(bt, 6, 5) | bitExt(ba, 11, 5) | bitExt(bb, 16, 5) @@ -209,7 +236,7 @@ struct Context { ); } void emit_A(uint32_t op, FPR const frt, FPR const fra, FPR const frb, FPR const frc, bool rc) { - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(frt.index, 6, 5) | bitExt(fra.index, 11, 5) | bitExt(frb.index, 16, 5) @@ -219,7 +246,7 @@ struct Context { } void emit_DS(uint32_t op, GPR const rt, GPR const ra, uint32_t d) { //assert(d & 0x03 == 0); - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5) | bitExt(d >> 2, 16, 14) @@ -237,7 +264,7 @@ struct Context { } void emit_MD(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) { assert(mb <= 0x3f); - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(ra.index, 6, 5) | bitExt(rs.index, 11, 5) | bitExt(rb.index, 16, 5) @@ -247,7 +274,7 @@ struct Context { } void emit_MD(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, bool rc) { assert(sh <= 0x3f && mb <= 0x3f); - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(ra.index, 6, 5) | bitExt(rs.index, 11, 5) | ((mb & 0x1f) << 6) | (mb & 0x20) @@ -256,7 +283,7 @@ struct Context { ); } void emit_MDS(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) { - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(ra.index, 6, 5) | bitExt(rs.index, 11, 5) | bitExt(rb.index, 16, 5) @@ -312,22 +339,27 @@ struct Context { void CRMOVE(CPR const bx, CPR const by) { CROR(bx, by, by); } void CRNOT(CPR const bx, CPR const by) { CRNOR(bx, by, by); } + void CMPLDI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index, 1, rx, v); } + void CMPLWI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index, 0, rx, v); } + void CMPLD(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index, 1, rx, ry); } + void CMPLW(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index, 0, rx, ry); } void CMPLDI(GPR const rx, uint32_t v) { CMPLI(0, 1, rx, v); } void CMPLWI(GPR const rx, uint32_t v) { CMPLI(0, 0, rx, v); } void CMPLD(GPR const rx, GPR const ry) { CMPL(0, 1, rx, ry); } void CMPLW(GPR const rx, GPR const ry) { CMPL(0, 0, rx, ry); } - void CMPLDI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index / 4, 1, rx, v); } - void CMPLWI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index / 4, 0, rx, v); } - void CMPLD(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index / 4, 1, rx, ry); } - void CMPLW(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index / 4, 0, rx, ry); } + void CMPWI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index, 0, rx, si); } + void CMPW(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index, 0, rx, ry); } + void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index, 1, rx, si); } + void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index, 1, rx, ry); } + void CMPWI(GPR const rx, uint32_t si) { CMPI(0, 0, rx, si); } + void CMPW(GPR const rx, GPR const ry) { CMP(0, 0, rx, ry); } + void CMPDI(GPR const rx, uint32_t si) { CMPI(0, 1, rx, si); } + void CMPD(GPR const rx, GPR const ry) { CMP(0, 1, rx, ry); } - void CMPWI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 0, rx, si); } - void CMPW(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 0, rx, ry); } - void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 1, rx, si); } - void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 1, rx, ry); } - - void BLR() { BCLR(R0, CR0, R0); } + void BLR() { + base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0); + } // TODO: PowerPC 11 stuff void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) { diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index 7783bf56d6..e7260a3d75 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -30,32 +30,32 @@ void ANDC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, rt, ra, void ANDC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, rt, ra, rb, true); } void ANDI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x70000000, rt, ra, d); } void ANDIS_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x74000000, rt, ra, d); } -void B(Label const& i) { emit_reloc_I(0x48000000, i); } -void BL(Label const& i) { emit_reloc_I(0x48000000, i); } -void BC(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } -void BCL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } -void BLT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } -void BLTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } -void BLE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); } -void BLEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); } -void BNG(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); } -void BNGL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); } -void BEQ(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, false); } -void BEQL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, true); } -void BGE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } -void BGEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } -void BNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } -void BNLL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } -void BGT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); } -void BGTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); } -void BNE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, false); } -void BNEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, true); } -void BSO(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); } -void BSOL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); } -void BUN(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); } -void BUNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); } -void BNS(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); } -void BNSL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); } +void B(Label const& i) { emit_reloc_I(0x48000000, i, false); } +void BL(Label const& i) { emit_reloc_I(0x48000000, i, true); } +void BC(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 0, cr.index + 0, i, false); } +void BCL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 0, cr.index + 0, i, true); } +void BLT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 0, i, false); } +void BLTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 0, i, true); } +void BLE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, false); } +void BLEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, true); } +void BNG(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, false); } +void BNGL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, true); } +void BEQ(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 2, i, false); } +void BEQL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 2, i, true); } +void BGE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, false); } +void BGEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, true); } +void BNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, false); } +void BNLL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, true); } +void BGT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 1, i, false); } +void BGTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 1, i, true); } +void BNE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 2, i, false); } +void BNEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 2, i, true); } +void BSO(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, false); } +void BSOL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, true); } +void BUN(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, false); } +void BUNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, true); } +void BNS(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 3, i, false); } +void BNSL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 3, i, true); } void BCCTR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, ba.index, bb.index, false); } void BCCTRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, ba.index, bb.index, true); } void BCCTR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, cond2offset(ba), bb.index, false); } @@ -64,10 +64,10 @@ void BCLR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.ind void BCLRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, ba.index, bb.index, true); } void BCLR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, false); } void BCLRL(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, true); } -void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); } -void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, GPR{(bf << 2) | l}, ra, d); } -void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); } -void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, GPR{(bf << 2) | l}, ra, d); } +void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, ra, GPR{(bf << 2) | l}, rb, false); } +void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, ra, GPR{(bf << 2) | l}, d); } +void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, ra, GPR{(bf << 2) | l}, rb, false); } +void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, ra, GPR{(bf << 2) | l}, d); } void CNTLZD(GPR const rt, GPR const ra) { emit_X(0x7c000074, rt, ra, R0, false); } void CNTLZD_(GPR const rt, GPR const ra) { emit_X(0x7c000074, rt, ra, R0, true); } void CNTLZW(GPR const rt, GPR const ra) { emit_X(0x7c000034, rt, ra, R0, false); } diff --git a/externals/powah/tests.cpp b/externals/powah/tests.cpp index 1ef820afcd..6d555b4f4a 100644 --- a/externals/powah/tests.cpp +++ b/externals/powah/tests.cpp @@ -2,16 +2,19 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include +#include #include "powah_emit.hpp" +#define EB32(X) __bswap32(X) + TEST_CASE("ppc64: addi", "[ppc64]") { std::vector data(64); powah::Context ctx(data.data(), data.size()); ctx.ADDI(powah::R2, powah::R2, 0); ctx.ADDIS(powah::R2, powah::R12, 0); - REQUIRE(data[0] == 0x00004238); - REQUIRE(data[1] == 0x00004c3c); + REQUIRE(data[0] == EB32(0x00004238)); + REQUIRE(data[1] == EB32(0x00004c3c)); } TEST_CASE("ppc64: std/mr", "[ppc64]") { @@ -24,12 +27,12 @@ TEST_CASE("ppc64: std/mr", "[ppc64]") { ctx.MR(powah::R30, powah::R3); ctx.RLDICR(powah::R4, powah::R5, 25, 6); ctx.STD(powah::R28, powah::R1, 160); - REQUIRE(data[0] == 0x900041fb); - REQUIRE(data[1] == 0x78239a7c); - REQUIRE(data[2] == 0xb000c1fb); - REQUIRE(data[3] == 0x781b7e7c); - REQUIRE(data[4] == 0x84c9a478); - REQUIRE(data[5] == 0xa00081fb); + REQUIRE(data[0] == EB32(0x900041fb)); + REQUIRE(data[1] == EB32(0x78239a7c)); + REQUIRE(data[2] == EB32(0xb000c1fb)); + REQUIRE(data[3] == EB32(0x781b7e7c)); + REQUIRE(data[4] == EB32(0x84c9a478)); + REQUIRE(data[5] == EB32(0xa00081fb)); } TEST_CASE("ppc64: sldi", "[ppc64]") { @@ -37,7 +40,7 @@ TEST_CASE("ppc64: sldi", "[ppc64]") { powah::Context ctx(data.data(), data.size()); ctx.SLDI(powah::R3, powah::R5, 37); - REQUIRE(data[0] == 0x862ea378); + REQUIRE(data[0] == EB32(0x862ea378)); } TEST_CASE("ppc64: rldicr", "[ppc64]") { @@ -48,11 +51,11 @@ TEST_CASE("ppc64: rldicr", "[ppc64]") { ctx.RLDICR(powah::R1, powah::R1, 0, 1); ctx.RLDICR(powah::R1, powah::R1, 1, 1); ctx.RLDICR(powah::R1, powah::R1, 31, 31); - REQUIRE(data[0] == 0x04002178); - REQUIRE(data[1] == 0x04082178); - REQUIRE(data[2] == 0x44002178); - REQUIRE(data[3] == 0x44082178); - REQUIRE(data[4] == 0xc4ff2178); + REQUIRE(data[0] == EB32(0x04002178)); + REQUIRE(data[1] == EB32(0x04082178)); + REQUIRE(data[2] == EB32(0x44002178)); + REQUIRE(data[3] == EB32(0x44082178)); + REQUIRE(data[4] == EB32(0xc4ff2178)); } TEST_CASE("ppc64: mr/or/std", "[ppc64]") { @@ -67,15 +70,15 @@ TEST_CASE("ppc64: mr/or/std", "[ppc64]") { ctx.OR(powah::R3, powah::R3, powah::R26); ctx.STD(powah::R3, powah::R1, 56); ctx.MR(powah::R3, powah::R30); - REQUIRE(data[0] == 0x783bfb7c); - REQUIRE(data[1] == 0x7833dd7c); - REQUIRE(data[2] == 0x7823637c); - REQUIRE(data[3] == 0x78e3847f); - REQUIRE(data[4] == 0x820b014d); - REQUIRE(data[5] == 0x782bb97c); - REQUIRE(data[6] == 0x78d3637c); - REQUIRE(data[7] == 0x380061f8); - REQUIRE(data[8] == 0x78f3c37f); + REQUIRE(data[0] == EB32(0x783bfb7c)); + REQUIRE(data[1] == EB32(0x7833dd7c)); + REQUIRE(data[2] == EB32(0x7823637c)); + REQUIRE(data[3] == EB32(0x78e3847f)); + REQUIRE(data[4] == EB32(0x820b014d)); + REQUIRE(data[5] == EB32(0x782bb97c)); + REQUIRE(data[6] == EB32(0x78d3637c)); + REQUIRE(data[7] == EB32(0x380061f8)); + REQUIRE(data[8] == EB32(0x78f3c37f)); } TEST_CASE("ppc64: ld/crand+addi", "[ppc64]") { @@ -93,18 +96,18 @@ TEST_CASE("ppc64: ld/crand+addi", "[ppc64]") { ctx.ADDI(powah::R5, powah::R5, 1); ctx.STD(powah::R26, powah::R1, 72); ctx.STD(powah::R5, powah::R30, 1984); - REQUIRE(data[0] == 0x480081e8); - REQUIRE(data[1] == 0x5000a180); - REQUIRE(data[2] == 0x024a8a4e); - REQUIRE(data[3] == 0x0400c438); - REQUIRE(data[4] == 0xc807a474); - REQUIRE(data[5] == 0xc007bee8); - REQUIRE(data[6] == 0x54006188); - REQUIRE(data[7] == 0x0002da78); - REQUIRE(data[8] == 0x50008190); - REQUIRE(data[9] == 0x0100a538); - REQUIRE(data[10] == 0x480041fb); - REQUIRE(data[11] == 0xc007bef8); + REQUIRE(data[0] == EB32(0x480081e8)); + REQUIRE(data[1] == EB32(0x5000a180)); + REQUIRE(data[2] == EB32(0x024a8a4e)); + REQUIRE(data[3] == EB32(0x0400c438)); + REQUIRE(data[4] == EB32(0xc807a474)); + REQUIRE(data[5] == EB32(0xc007bee8)); + REQUIRE(data[6] == EB32(0x54006188)); + REQUIRE(data[7] == EB32(0x0002da78)); + REQUIRE(data[8] == EB32(0x50008190)); + REQUIRE(data[9] == EB32(0x0100a538)); + REQUIRE(data[10] == EB32(0x480041fb)); + REQUIRE(data[11] == EB32(0xc007bef8)); } TEST_CASE("ppc64: rotldi", "[ppc64]") { @@ -123,17 +126,102 @@ TEST_CASE("ppc64: rotldi", "[ppc64]") { ctx.RLDIMI(powah::R4, powah::R5, 48, 8); ctx.RLDIMI(powah::R4, powah::R3, 56, 0); ctx.MR(powah::R3, powah::R4); - REQUIRE(data[0] == 0x00806578); - REQUIRE(data[1] == 0x00406478); - REQUIRE(data[2] == 0x2c44a478); - REQUIRE(data[3] == 0x00c06578); - REQUIRE(data[4] == 0x2c82a478); - REQUIRE(data[5] == 0x02006578); - REQUIRE(data[6] == 0x2cc0a478); - REQUIRE(data[7] == 0x02806578); - REQUIRE(data[8] == 0x0e44a478); - REQUIRE(data[9] == 0x02c06578); - REQUIRE(data[10] == 0x0e82a478); - REQUIRE(data[11] == 0x0ec06478); - REQUIRE(data[12] == 0x7823837c); + REQUIRE(data[0] == EB32(0x00806578)); + REQUIRE(data[1] == EB32(0x00406478)); + REQUIRE(data[2] == EB32(0x2c44a478)); + REQUIRE(data[3] == EB32(0x00c06578)); + REQUIRE(data[4] == EB32(0x2c82a478)); + REQUIRE(data[5] == EB32(0x02006578)); + REQUIRE(data[6] == EB32(0x2cc0a478)); + REQUIRE(data[7] == EB32(0x02806578)); + REQUIRE(data[8] == EB32(0x0e44a478)); + REQUIRE(data[9] == EB32(0x02c06578)); + REQUIRE(data[10] == EB32(0x0e82a478)); + REQUIRE(data[11] == EB32(0x0ec06478)); + REQUIRE(data[12] == EB32(0x7823837c)); } + +#if 1 //&& defined(ARCHITECTURE_ppc64) +/* + 0: d619637c mullw 3, 3, 3 + 4: 20006378 clrldi 3, 3, 32 + 8: 2000804e blr +*/ +TEST_CASE("ppc64: live-exec square", "[ppc64]") { + uint32_t* data = (uint32_t*)mmap(nullptr, 4096, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + REQUIRE(data != nullptr); + + powah::Context ctx((void*)data, 4096); + ctx.MULLW(powah::R3, powah::R3, powah::R3); + ctx.CLRLDI(powah::R3, powah::R3, 32); + ctx.BLR(); + REQUIRE(data[0] == EB32(0xd619637c)); + REQUIRE(data[1] == EB32(0x20006378)); + REQUIRE(data[2] == EB32(0x2000804e)); + + auto* fn = (int (*)(int))data; + REQUIRE(fn(4) == 4 * 4); + REQUIRE(fn(8) == 8 * 8); + + munmap((void*)data, 4096); +} + +/* +int f(int a, int b, int c) { + a += (a > b) ? b - 0xffff : c + 402, b += 2, c &= b*c; + return a * a + b ^ c & b; +} +*/ +TEST_CASE("ppc64: live-exec xoralu", "[ppc64]") { + uint32_t* data = (uint32_t*)mmap(nullptr, 4096, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + REQUIRE(data != nullptr); + + powah::Context ctx((void*)data, 4096); + powah::Label l_2 = ctx.DefineLabel(); + powah::Label l_3 = ctx.DefineLabel(); + ctx.CMPW(powah::R3, powah::R4); + ctx.BGT(powah::CR0, l_2); + ctx.ADDI(powah::R6, powah::R5, 402); + ctx.B(l_3); + ctx.LABEL(l_2); + ctx.ADDI(powah::R6, powah::R4, 1); + ctx.ADDIS(powah::R6, powah::R6, -1); + ctx.LABEL(l_3); + ctx.ADDI(powah::R4, powah::R4, 2); + ctx.ADD(powah::R3, powah::R6, powah::R3); + ctx.MULLW(powah::R6, powah::R4, powah::R5); + ctx.MULLW(powah::R3, powah::R3, powah::R3); + ctx.AND(powah::R5, powah::R5, powah::R6); + ctx.ADD(powah::R3, powah::R3, powah::R4); + ctx.AND(powah::R4, powah::R5, powah::R4); + ctx.XOR(powah::R3, powah::R3, powah::R4); + ctx.EXTSW(powah::R3, powah::R3); + ctx.BLR(); + ctx.ApplyRelocs(); + REQUIRE(data[0] == EB32(0x0020037c)); + REQUIRE(data[1] == EB32(0x0c008141)); + REQUIRE(data[2] == EB32(0x9201c538)); + REQUIRE(data[3] == EB32(0x0c000048)); + REQUIRE(data[4] == EB32(0x0100c438)); + REQUIRE(data[5] == EB32(0xffffc63c)); + REQUIRE(data[6] == EB32(0x02008438)); + REQUIRE(data[7] == EB32(0x141a667c)); + REQUIRE(data[8] == EB32(0xd629c47c)); + REQUIRE(data[9] == EB32(0xd619637c)); + REQUIRE(data[10] == EB32(0x3830a57c)); + REQUIRE(data[11] == EB32(0x1422637c)); + REQUIRE(data[12] == EB32(0x3820a47c)); + REQUIRE(data[13] == EB32(0x7822637c)); + REQUIRE(data[14] == EB32(0xb407637c)); + REQUIRE(data[15] == EB32(0x2000804e)); + + auto const orig = [](int a, int b, int c) { + a += (a > b) ? b - 0xffff : c + 402, b += 2, c &= b*c; + return a * a + b ^ c & b; + }; + auto* fn = (int (*)(int, int, int))data; + REQUIRE(fn(0, 1, 2) == orig(0, 1, 2)); + + munmap((void*)data, 4096); +} +#endif From d85d576b0d1369321f176e6474943fd856f0f80c Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 3 Nov 2025 00:39:38 +0000 Subject: [PATCH 07/49] backwards relocs Signed-off-by: lizzie --- externals/powah/powah_emit.hpp | 11 ++++++----- externals/powah/tests.cpp | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index bc1bfb803b..51fea03fc9 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -138,14 +138,15 @@ struct Context { } void ApplyRelocs() { - for (auto const [index, info] : relocs) { - assert(labels[index] != 0); //label must have an addr + for (auto const &[index, info] : relocs) { + //assert(labels[index] != 0); //label must have an addr + int32_t rel = (int32_t)labels[index] - (int32_t)info.offset; switch (info.kind) { case RelocKind::FormB: - base[info.offset] |= bitExt(labels[index] - info.offset, 16, 14); + base[info.offset] |= bitExt(rel, 16, 14); break; case RelocKind::FormI: - base[info.offset] |= bitExt(labels[index] - info.offset, 6, 24); + base[info.offset] |= bitExt(rel, 6, 24); break; } } @@ -176,7 +177,7 @@ struct Context { } uint32_t bitExt(uint32_t value, uint32_t offs, uint32_t n) { - uint32_t mask = (1UL << (n + 1)) - 1; + uint32_t mask = (1UL << n) - 1; return (value & mask) << (32 - (n + offs)); } void emit_XO(uint32_t op, GPR const rt, GPR const ra, GPR const rb, bool oe, bool rc) { diff --git a/externals/powah/tests.cpp b/externals/powah/tests.cpp index 6d555b4f4a..c60ce0c724 100644 --- a/externals/powah/tests.cpp +++ b/externals/powah/tests.cpp @@ -141,7 +141,19 @@ TEST_CASE("ppc64: rotldi", "[ppc64]") { REQUIRE(data[12] == EB32(0x7823837c)); } -#if 1 //&& defined(ARCHITECTURE_ppc64) +TEST_CASE("ppc64: branch-backwards", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + powah::Label l_3 = ctx.DefineLabel(); + ctx.LABEL(l_3); + ctx.ADD(powah::R1, powah::R2, powah::R3); + ctx.B(l_3); + ctx.ApplyRelocs(); + REQUIRE(data[0] == EB32(0x141a227c)); + REQUIRE(data[1] == EB32(0xfcffff4b)); +} + +#if defined(ARCHITECTURE_ppc64) /* 0: d619637c mullw 3, 3, 3 4: 20006378 clrldi 3, 3, 32 @@ -221,6 +233,7 @@ TEST_CASE("ppc64: live-exec xoralu", "[ppc64]") { }; auto* fn = (int (*)(int, int, int))data; REQUIRE(fn(0, 1, 2) == orig(0, 1, 2)); + REQUIRE(fn(6456, 4564, 4564561) == orig(6456, 4564, 4564561)); munmap((void*)data, 4096); } From 3d6974607e8b9bb5f8c2e579cbfb6f4ddcbda658 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 3 Nov 2025 01:30:56 +0000 Subject: [PATCH 08/49] first emitted block Signed-off-by: lizzie --- .../backend/arm64/a64_address_space.h | 3 -- .../src/dynarmic/backend/ppc64/a32_core.h | 26 +++-------------- .../dynarmic/backend/ppc64/a32_interface.cpp | 17 ++++------- .../src/dynarmic/backend/ppc64/a64_core.h | 13 +++------ .../dynarmic/backend/ppc64/a64_interface.cpp | 9 ++---- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 6 ++-- .../src/dynarmic/backend/ppc64/code_block.h | 17 +++++------ .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 28 +++++++++++++------ 8 files changed, 48 insertions(+), 71 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.h b/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.h index 512894fdce..6161bfebe2 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.h @@ -26,11 +26,8 @@ public: protected: friend class A64Core; - - void EmitPrelude(); EmitConfig GetEmitConfig() override; void RegisterNewBasicBlock(const IR::Block& block, const EmittedBlockInfo& block_info) override; - const A64::UserConfig conf; BlockRangeInformation block_ranges; }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index 2d113e8c8f..b4f69c25e0 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -30,47 +30,29 @@ struct A32JitState { class A32AddressSpace final { public: explicit A32AddressSpace(const A32::UserConfig& conf); - IR::Block GenerateIR(IR::LocationDescriptor) const; - CodePtr Get(IR::LocationDescriptor descriptor); - CodePtr GetOrEmit(IR::LocationDescriptor descriptor); - void ClearCache(); - private: friend class A32Core; - - void EmitPrelude(); EmittedBlockInfo Emit(IR::Block ir_block); void Link(EmittedBlockInfo& block); - const A32::UserConfig conf; - CodeBlock cb; powah::Context as; - ankerl::unordered_dense::map block_entries; ankerl::unordered_dense::map block_infos; - - struct PreludeInfo { - CodePtr end_of_prelude; - - using RunCodeFuncType = HaltReason (*)(CodePtr entry_point, A32JitState* context, volatile u32* halt_reason); - RunCodeFuncType run_code; - CodePtr return_from_run_code; - } prelude_info; }; class A32Core final { public: explicit A32Core(const A32::UserConfig&) {} - HaltReason Run(A32AddressSpace& process, A32JitState& thread_ctx, volatile u32* halt_reason) { - const auto location_descriptor = thread_ctx.GetLocationDescriptor(); - const auto entry_point = process.GetOrEmit(location_descriptor); - return process.prelude_info.run_code(entry_point, &thread_ctx, halt_reason); + auto const loc = thread_ctx.GetLocationDescriptor(); + auto const entry = process.GetOrEmit(loc); + using CodeFn = HaltReason (*)(A32JitState*, volatile u32*); + return (CodeFn(entry))(&thread_ctx, halt_reason); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index 178bb9775a..b519f95c49 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -23,7 +23,7 @@ A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf) : conf(conf) , cb(conf.code_cache_size) , as(cb.ptr(), conf.code_cache_size) { - EmitPrelude(); + } IR::Block A32AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const { @@ -33,15 +33,13 @@ IR::Block A32AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const { } CodePtr A32AddressSpace::Get(IR::LocationDescriptor descriptor) { - if (const auto iter = block_entries.find(descriptor.Value()); iter != block_entries.end()) - return iter->second; - return nullptr; + auto const it = block_entries.find(descriptor.Value()); + return it != block_entries.end() ? it->second : nullptr; } CodePtr A32AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) { - if (CodePtr block_entry = Get(descriptor)) { + if (CodePtr block_entry = Get(descriptor); block_entry != nullptr) return block_entry; - } IR::Block ir_block = GenerateIR(descriptor); const EmittedBlockInfo block_info = Emit(std::move(ir_block)); @@ -56,10 +54,6 @@ void A32AddressSpace::ClearCache() { block_infos.clear(); } -void A32AddressSpace::EmitPrelude() { - UNREACHABLE(); -} - EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) { EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { .enable_cycle_counting = conf.enable_cycle_counting, @@ -70,7 +64,7 @@ EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) { } void A32AddressSpace::Link(EmittedBlockInfo& block_info) { - UNREACHABLE(); + //UNREACHABLE(); } } @@ -160,7 +154,6 @@ struct Jit::Impl final { private: void RequestCacheInvalidation() { // UNREACHABLE(); - invalidate_entire_cache = false; invalid_cache_ranges.clear(); } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 4236e1f281..143dbb19f7 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -52,12 +52,6 @@ private: powah::Context as; ankerl::unordered_dense::map block_entries; ankerl::unordered_dense::map block_infos; - struct PreludeInfo { - CodePtr end_of_prelude; - using RunCodeFuncType = HaltReason (*)(CodePtr entry_point, A64JitState* context, volatile u32* halt_reason); - RunCodeFuncType run_code; - CodePtr return_from_run_code; - } prelude_info; }; class A64Core final { @@ -65,9 +59,10 @@ public: explicit A64Core(const A64::UserConfig&) {} HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { - const auto location_descriptor = thread_ctx.GetLocationDescriptor(); - const auto entry_point = process.GetOrEmit(location_descriptor); - return process.prelude_info.run_code(entry_point, &thread_ctx, halt_reason); + const auto loc = thread_ctx.GetLocationDescriptor(); + const auto entry = process.GetOrEmit(loc); + using CodeFn = HaltReason (*)(A64JitState*, volatile u32*); + return (CodeFn(entry))(&thread_ctx, halt_reason); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index b324a8897f..4272ee183b 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -22,7 +22,7 @@ A64AddressSpace::A64AddressSpace(const A64::UserConfig& conf) : conf(conf) , cb(conf.code_cache_size) , as(cb.ptr(), conf.code_cache_size) { - EmitPrelude(); + } CodePtr A64AddressSpace::Get(IR::LocationDescriptor descriptor) { @@ -52,10 +52,6 @@ void A64AddressSpace::ClearCache() { block_infos.clear(); } -void A64AddressSpace::EmitPrelude() { - UNREACHABLE(); -} - EmittedBlockInfo A64AddressSpace::Emit(IR::Block block) { EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { .enable_cycle_counting = conf.enable_cycle_counting, @@ -66,7 +62,8 @@ EmittedBlockInfo A64AddressSpace::Emit(IR::Block block) { } void A64AddressSpace::Link(EmittedBlockInfo& block_info) { - UNREACHABLE(); + // TODO(lizzie): Block linking + // UNREACHABLE(); } } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 719091c872..364a7c8bc0 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -15,7 +15,9 @@ constexpr powah::GPR ABI_PARAM2 = powah::R4; constexpr powah::GPR ABI_PARAM3 = powah::R5; constexpr powah::GPR ABI_PARAM4 = powah::R6; -constexpr std::initializer_list GPR_ORDER{8, 9, 18, 19, 20, 21, 22, 23, 24, 25, 5, 6, 7, 28, 29, 10, 11, 12, 13, 14, 15, 16, 17}; -constexpr std::initializer_list FPR_ORDER{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; +// See https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#REG +constexpr std::initializer_list GPR_ORDER{ + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +}; } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h b/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h index 063863100f..25a17a400d 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h @@ -15,22 +15,23 @@ namespace Dynarmic::Backend::PPC64 { class CodeBlock { public: - explicit CodeBlock(std::size_t size) noexcept : memsize(size) { - mem = (u8*)mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - ASSERT(mem != nullptr); + explicit CodeBlock(size_t size_) noexcept : size{size_} { + block = (u8*)mmap(nullptr, size, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + //printf("block = %p, size= %zx\n", block, size); + ASSERT(block != nullptr); } ~CodeBlock() noexcept { - if (mem != nullptr) - munmap(mem, memsize); + if (block != nullptr) + munmap(block, size); } template T ptr() const noexcept { static_assert(std::is_pointer_v || std::is_same_v || std::is_same_v); - return reinterpret_cast(mem); + return reinterpret_cast(block); } protected: - u8* mem = nullptr; - size_t memsize = 0; + void* block = nullptr; + size_t size = 0; }; } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 140e9a2d40..f95ca8aa82 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -87,26 +87,33 @@ void EmitIR(powah::Context&, EmitContext&, IR:: UNREACHABLE(); } -EmittedBlockInfo EmitPPC64(powah::Context& as, IR::Block block, const EmitConfig& emit_conf) { +EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConfig& emit_conf) { EmittedBlockInfo ebi; - RegAlloc reg_alloc{as}; + RegAlloc reg_alloc{code}; EmitContext ctx{block, reg_alloc, emit_conf, ebi}; - //ebi.entry_point = reinterpret_cast(as.GetCursorPointer()); + ebi.entry_point = CodePtr(code.base + code.offset); + + code.BLR(); + + // Non-volatile saves + std::vector gpr_order{GPR_ORDER}; + for (size_t i = 0; i < gpr_order.size(); ++i) + code.STD(powah::GPR{gpr_order[i]}, powah::R1, -(i * 8)); + for (auto iter = block.begin(); iter != block.end(); ++iter) { IR::Inst* inst = &*iter; - switch (inst->GetOpcode()) { #define OPCODE(name, type, ...) \ case IR::Opcode::name: \ - EmitIR(as, ctx, inst); \ + EmitIR(code, ctx, inst); \ break; #define A32OPC(name, type, ...) \ case IR::Opcode::A32##name: \ - EmitIR(as, ctx, inst); \ + EmitIR(code, ctx, inst); \ break; #define A64OPC(name, type, ...) \ case IR::Opcode::A64##name: \ - EmitIR(as, ctx, inst); \ + EmitIR(code, ctx, inst); \ break; #include "dynarmic/ir/opcodes.inc" #undef OPCODE @@ -116,8 +123,11 @@ EmittedBlockInfo EmitPPC64(powah::Context& as, IR::Block block, const EmitConfig UNREACHABLE(); } } - //UNREACHABLE(); - //ebi.size = reinterpret_cast(as.GetCursorPointer()) - ebi.entry_point; + + for (size_t i = 0; i < gpr_order.size(); ++i) + code.LD(powah::GPR{gpr_order[i]}, powah::R1, -(i * 8)); + code.BLR(); + ebi.size = code.offset; return ebi; } From e79ece6518304a1eaf99d46736889e8b5984e0d7 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 3 Nov 2025 03:24:06 +0000 Subject: [PATCH 09/49] generation of add and extraction of flags Signed-off-by: lizzie --- externals/powah/powah_emit.hpp | 17 +- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 10 +- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 48 +- .../src/dynarmic/backend/ppc64/emit_ppc64.h | 10 +- .../dynarmic/backend/ppc64/emit_ppc64_a32.cpp | 189 ++--- .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 114 +-- .../ppc64/emit_ppc64_data_processing.cpp | 20 +- .../ppc64/emit_ppc64_floating_point.cpp | 176 ++--- .../backend/ppc64/emit_ppc64_misc.cpp | 144 ++-- .../backend/ppc64/emit_ppc64_vector.cpp | 716 +++++++++--------- .../src/dynarmic/backend/ppc64/reg_alloc.cpp | 165 ++-- .../src/dynarmic/backend/ppc64/reg_alloc.h | 77 +- 12 files changed, 851 insertions(+), 835 deletions(-) diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 51fea03fc9..b2f26dc84a 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -254,14 +254,15 @@ struct Context { ); } void emit_M(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me, bool rc) { - (void)op; - (void)rs; - (void)ra; - (void)sh; - (void)mb; - (void)me; - (void)rc; - std::abort(); + assert(sh <= 0x3f && mb <= 0x3f); + base[offset++] = (op | + bitExt(ra.index, 6, 5) + | bitExt(rs.index, 11, 5) + | bitExt(sh, 16, 5) + | bitExt(mb, 21, 4) + | bitExt(me, 26, 4) + | bitExt(rc, 31, 1) + ); } void emit_MD(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) { assert(mb <= 0x3f); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 364a7c8bc0..c5a536f1e5 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -8,7 +8,7 @@ namespace Dynarmic::Backend::PPC64 { -constexpr powah::GPR RJIT = powah::R31; +constexpr powah::GPR RJIT = powah::R3; //yeah it's param, so what? constexpr powah::GPR ABI_PARAM1 = powah::R3; constexpr powah::GPR ABI_PARAM2 = powah::R4; @@ -20,4 +20,12 @@ constexpr std::initializer_list GPR_ORDER{ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; +constexpr std::initializer_list ABI_CALLEE_SAVED{ + powah::R14, powah::R15, powah::R16, powah::R17, + powah::R18, powah::R19, powah::R20, powah::R21, + powah::R22, powah::R23, powah::R24, powah::R25, + powah::R26, powah::R27, powah::R28, powah::R29, + powah::R30, powah::R31 +}; + } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index f95ca8aa82..94e1c50862 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -24,76 +24,76 @@ void EmitIR(powah::Context&, EmitContext&, IR::Inst*) {} template<> void EmitIR(powah::Context&, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConfig& emit_conf) { EmittedBlockInfo ebi; RegAlloc reg_alloc{code}; EmitContext ctx{block, reg_alloc, emit_conf, ebi}; - ebi.entry_point = CodePtr(code.base + code.offset); - code.BLR(); + auto const start_offset = code.offset; + ebi.entry_point = CodePtr(code.base + start_offset); // Non-volatile saves std::vector gpr_order{GPR_ORDER}; @@ -127,12 +127,20 @@ 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(); - ebi.size = code.offset; + + /* + llvm-objcopy -I binary -O elf64-powerpc --rename-section=.data=.text,code test.bin test.elf + llvm-objdump -d test.elf + */ + static FILE* fp = fopen("test.bin", "ab"); + fwrite(code.base, code.offset - start_offset, sizeof(uint32_t), fp); + + ebi.size = code.offset - start_offset; return ebi; } -void EmitRelocation(powah::Context& as, EmitContext& ctx, LinkTarget link_target) { - UNREACHABLE(); +void EmitRelocation(powah::Context& code, EmitContext& ctx, LinkTarget link_target) { + ASSERT(false && "unimp"); } } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h index aad9d0dd63..5d53027d1d 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h @@ -45,12 +45,12 @@ struct EmitConfig { struct EmitContext; -EmittedBlockInfo EmitPPC64(powah::Context& as, IR::Block block, const EmitConfig& emit_conf); +EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConfig& emit_conf); template -void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst); -void EmitRelocation(powah::Context& as, EmitContext& ctx, LinkTarget link_target); -void EmitA32Cond(powah::Context& as, EmitContext& ctx, IR::Cond cond, powah::Label* label); -void EmitA32Terminal(powah::Context& as, EmitContext& ctx); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst); +void EmitRelocation(powah::Context& code, EmitContext& ctx, LinkTarget link_target); +void EmitA32Cond(powah::Context& code, EmitContext& ctx, IR::Cond cond, powah::Label* label); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx); } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp index f851882c4e..c032f38500 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp @@ -15,340 +15,355 @@ namespace Dynarmic::Backend::PPC64 { -void EmitA32Cond(powah::Context& as, EmitContext&, IR::Cond cond, powah::Label* label) { - UNREACHABLE(); +void EmitA32Cond(powah::Context& code, EmitContext&, IR::Cond cond, powah::Label* label) { + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step); void EmitA32Terminal(powah::Context&, EmitContext&, IR::Term::Interpret, IR::LocationDescriptor, bool) { - UNREACHABLE(); + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) { - EmitRelocation(as, ctx, LinkTarget::ReturnFromRunCode); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) { + EmitRelocation(code, ctx, LinkTarget::ReturnFromRunCode); } -void EmitSetUpperLocationDescriptor(powah::Context& as, EmitContext& ctx, IR::LocationDescriptor new_location, IR::LocationDescriptor old_location) { - UNREACHABLE(); +void EmitSetUpperLocationDescriptor(powah::Context& code, EmitContext& ctx, IR::LocationDescriptor new_location, IR::LocationDescriptor old_location) { + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { - UNREACHABLE(); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { - UNREACHABLE(); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::PopRSBHint, IR::LocationDescriptor, bool) { - UNREACHABLE(); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::PopRSBHint, IR::LocationDescriptor, bool) { + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::FastDispatchHint, IR::LocationDescriptor, bool) { - UNREACHABLE(); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::FastDispatchHint, IR::LocationDescriptor, bool) { + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - UNREACHABLE(); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - UNREACHABLE(); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - UNREACHABLE(); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - UNREACHABLE(); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + ASSERT(false && "unimp"); } -void EmitA32Terminal(powah::Context& as, EmitContext& ctx) { - UNREACHABLE(); +void EmitA32Terminal(powah::Context& code, EmitContext& ctx) { + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const index = ctx.reg_alloc.UseScratchGpr(args[1]); + code.SLDI(index, index, 3); + code.ADD(result, PPC64::RJIT, index); + code.LD(result, result, offsetof(A32JitState, regs)); + ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + auto args = ctx.reg_alloc.GetArgumentInfo(inst); + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const index = ctx.reg_alloc.UseScratchGpr(args[1]); + code.SLDI(index, index, 3); + code.ADD(result, PPC64::RJIT, index); + code.STD(result, result, offsetof(A32JitState, regs)); + ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context& as, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + code.LD(result, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); + code.RLWINM(result, result, 31, 31, 31); + ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } // Memory template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } // Coprocesor template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } } // namespace Dynarmic::Backend::RV64 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 2729d145f9..d74baa8252 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -17,288 +17,288 @@ namespace Dynarmic::Backend::PPC64 { template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } // Memory template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + 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 a376929a36..34edd4270c 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 @@ -18,17 +18,17 @@ namespace Dynarmic::Backend::PPC64 { template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } /* @@ -119,7 +119,7 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Ins code.RLDICL(result, source, (64 - shift - 1) & 0x3f, 63); } } else { - UNREACHABLE(); + ASSERT(false && "unimp"); } ctx.reg_alloc.DefineValue(inst, result); } @@ -244,7 +244,7 @@ static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, code.MR(nzcv, then_); } break; default: - UNREACHABLE(); + ASSERT(false && "unimp"); } return nzcv; } @@ -773,7 +773,7 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } // __builtin_bswap32 @@ -856,22 +856,22 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp index b50f5027cd..a8bb06864e 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp @@ -17,442 +17,442 @@ namespace Dynarmic::Backend::PPC64 { template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp index 89d925e465..7db5dbd992 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp @@ -17,364 +17,364 @@ namespace Dynarmic::Backend::PPC64 { template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } // Packed template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } // Crypto template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp index ccc4daf4b1..d53b804d73 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp @@ -17,1794 +17,1794 @@ namespace Dynarmic::Backend::PPC64 { template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } // Vector saturation template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } // Vector VFP template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - UNREACHABLE(); + ASSERT(false && "unimp"); } } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp index 4e2037790a..e1d5cd9ee5 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -1,16 +1,15 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#include "dynarmic/backend/ppc64/reg_alloc.h" #include #include #include +#include "dynarmic/backend/ppc64/reg_alloc.h" +#include "dynarmic/backend/ppc64/abi.h" #include "dynarmic/common/assert.h" -#include #include "dynarmic/common/common_types.h" - #include "dynarmic/common/always_false.h" namespace Dynarmic::Backend::PPC64 { @@ -22,67 +21,9 @@ static bool IsValuelessType(IR::Type type) { return type == IR::Type::Table; } -IR::Type Argument::GetType() const { - return value.GetType(); -} - -bool Argument::IsImmediate() const { - return value.IsImmediate(); -} - -bool Argument::GetImmediateU1() const { - return value.GetU1(); -} - -u8 Argument::GetImmediateU8() const { - const u64 imm = value.GetImmediateAsU64(); - ASSERT(imm < 0x100); - return u8(imm); -} - -u16 Argument::GetImmediateU16() const { - const u64 imm = value.GetImmediateAsU64(); - ASSERT(imm < 0x10000); - return u16(imm); -} - -u32 Argument::GetImmediateU32() const { - const u64 imm = value.GetImmediateAsU64(); - ASSERT(imm < 0x100000000); - return u32(imm); -} - -u64 Argument::GetImmediateU64() const { - return value.GetImmediateAsU64(); -} - -IR::Cond Argument::GetImmediateCond() const { - ASSERT(IsImmediate() && GetType() == IR::Type::Cond); - return value.GetCond(); -} - -IR::AccType Argument::GetImmediateAccType() const { - ASSERT(IsImmediate() && GetType() == IR::Type::AccType); - return value.GetAccType(); -} - -bool HostLocInfo::Contains(const IR::Inst* value) const { - return std::find(values.begin(), values.end(), value) != values.end(); -} - -void HostLocInfo::SetupScratchLocation() { - ASSERT(IsCompletelyEmpty()); - realized = true; -} - -bool HostLocInfo::IsCompletelyEmpty() const { - return values.empty() && !locked && !realized && !accumulated_uses && !expected_uses && !uses_this_inst; -} - void HostLocInfo::UpdateUses() { accumulated_uses += uses_this_inst; uses_this_inst = 0; - if (accumulated_uses == expected_uses) { values.clear(); accumulated_uses = 0; @@ -139,34 +80,32 @@ void RegAlloc::AssertNoMoreUses() const { ASSERT(std::all_of(spills.begin(), spills.end(), is_empty)); } -u32 RegAlloc::AllocateRegister(const std::array& regs, const std::vector& order) const { - const auto empty = std::find_if(order.begin(), order.end(), [&](u32 i) { return regs[i].values.empty() && !regs[i].locked; }); - if (empty != order.end()) - return *empty; - +std::optional RegAlloc::AllocateRegister(const std::array& regs, const std::vector& order) const { + if (auto const it = std::find_if(order.begin(), order.end(), [&](u32 i) { + return regs[i].values.empty() && !regs[i].locked; + }); it != order.end()) + return *it; std::vector candidates; std::copy_if(order.begin(), order.end(), std::back_inserter(candidates), [&](u32 i) { return !regs[i].locked; }); - // TODO: LRU - return candidates[0]; + return candidates.empty() ? std::nullopt : std::optional{candidates[0]}; // TODO: LRU } void RegAlloc::SpillGpr(u32 index) { ASSERT(!gprs[index].locked && !gprs[index].realized); - if (gprs[index].values.empty()) - return; - const u32 new_location_index = FindFreeSpill(); - //as.SD(powah::GPR{index}, spill_offset + new_location_index * spill_slot_size, powah::sp); - spills[new_location_index] = std::exchange(gprs[index], {}); + if (!gprs[index].values.empty()) { + const u32 new_location_index = FindFreeSpill(); + code.STD(powah::GPR{index}, powah::R1, spill_offset + new_location_index * spill_slot_size); + spills[new_location_index] = std::exchange(gprs[index], {}); + } } void RegAlloc::SpillFpr(u32 index) { ASSERT(!fprs[index].locked && !fprs[index].realized); - if (fprs[index].values.empty()) { - return; + if (!fprs[index].values.empty()) { + const u32 new_location_index = FindFreeSpill(); + //code.FSD(powah::FPR{index}, spill_offset + new_location_index * spill_slot_size, powah::sp); + spills[new_location_index] = std::exchange(fprs[index], {}); } - const u32 new_location_index = FindFreeSpill(); - //as.FSD(powah::FPR{index}, spill_offset + new_location_index * spill_slot_size, powah::sp); - spills[new_location_index] = std::exchange(fprs[index], {}); } u32 RegAlloc::FindFreeSpill() const { @@ -190,16 +129,22 @@ std::optional RegAlloc::ValueLocation(const IR::Inst* value) const { return std::nullopt; } -HostLocInfo& RegAlloc::ValueInfo(HostLoc host_loc) { - // switch (host_loc.kind) { - // case HostLoc::Kind::Gpr: - // return gprs[size_t(host_loc.index)]; - // case HostLoc::Kind::Fpr: - // return fprs[size_t(host_loc.index)]; - // case HostLoc::Kind::Spill: - // return spills[size_t(host_loc.index)]; - // } - UNREACHABLE(); +static powah::GPR HostLocToReg(HostLoc h) noexcept { + if (u8(h) >= u8(HostLoc::R0) && u8(h) <= u8(HostLoc::R31)) + return powah::GPR{uint32_t(h)}; + ASSERT(false && "unimp"); +} + +HostLocInfo& RegAlloc::ValueInfo(HostLoc h) { + if (u8(h) >= u8(HostLoc::R0) && u8(h) <= u8(HostLoc::R31)) + return gprs[size_t(h)]; + else if (u8(h) >= u8(HostLoc::FR0) && u8(h) <= u8(HostLoc::FR31)) + return gprs[size_t(h) - size_t(HostLoc::FR0)]; + else if (u8(h) >= u8(HostLoc::VR0) && u8(h) <= u8(HostLoc::VR31)) + return vprs[size_t(h) - size_t(HostLoc::VR0)]; + auto const index = size_t(h) - size_t(HostLoc::FirstSpill); + ASSERT(index <= spills.size()); + return spills[index]; } HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) { @@ -212,35 +157,49 @@ HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) { return *iter; else if (const auto iter = std::find_if(spills.begin(), spills.end(), fn); iter != spills.end()) return *iter; - UNREACHABLE(); + ASSERT(false && "unimp"); } -powah::GPR RegAlloc::ScratchGpr(std::optional> desired_locations) { - UNREACHABLE(); -} - -void RegAlloc::Use(Argument& arg, HostLoc host_loc) { - UNREACHABLE(); -} - -void RegAlloc::UseScratch(Argument& arg, HostLoc host_loc) { - UNREACHABLE(); +powah::GPR RegAlloc::ScratchGpr() { + auto const r = AllocateRegister(gprs, PPC64::GPR_ORDER); + return powah::GPR{*r}; } powah::GPR RegAlloc::UseGpr(Argument& arg) { - UNREACHABLE(); + ASSERT(!arg.allocated); + arg.allocated = true; + return ScratchGpr(); } powah::GPR RegAlloc::UseScratchGpr(Argument& arg) { - UNREACHABLE(); + ASSERT(!arg.allocated); + arg.allocated = true; + return ScratchGpr(); } void RegAlloc::DefineValue(IR::Inst* inst, powah::GPR const gpr) noexcept { - UNREACHABLE(); + ASSERT(!ValueLocation(inst) && "inst has already been defined"); + ValueInfo(HostLoc(gpr.index)).values.push_back(inst); } void RegAlloc::DefineValue(IR::Inst* inst, Argument& arg) noexcept { - UNREACHABLE(); + ASSERT(!arg.allocated); + arg.allocated = true; + ASSERT(!ValueLocation(inst) && "inst has already been defined"); + if (arg.value.IsImmediate()) { + HostLoc const loc{u8(ScratchGpr().index)}; + ValueInfo(loc).values.push_back(inst); + auto const value = arg.value.GetImmediateAsU64(); + if (value >= 0x7fff) { + ASSERT(false && "unimp"); + } else { + //code.LI(HostLocToReg(loc), value); + } + } else { + ASSERT(ValueLocation(arg.value.GetInst()) && "arg.value must already be defined"); + const HostLoc loc = *ValueLocation(arg.value.GetInst()); + ValueInfo(loc).values.push_back(inst); + } } } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h index 034935e311..4e5454b86e 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -26,27 +26,47 @@ class RegAlloc; struct Argument { public: - using copyable_reference = std::reference_wrapper; - - IR::Type GetType() const; - bool IsImmediate() const; - - bool GetImmediateU1() const; - u8 GetImmediateU8() const; - u16 GetImmediateU16() const; - u32 GetImmediateU32() const; - u64 GetImmediateU64() const; - IR::Cond GetImmediateCond() const; - IR::AccType GetImmediateAccType() const; - + IR::Type GetType() const { + return value.GetType(); + } + bool IsImmediate() const { + return value.IsImmediate(); + } + bool GetImmediateU1() const { + return value.GetU1(); + } + u8 GetImmediateU8() const { + const u64 imm = value.GetImmediateAsU64(); + ASSERT(imm < 0x100); + return u8(imm); + } + u16 GetImmediateU16() const { + const u64 imm = value.GetImmediateAsU64(); + ASSERT(imm < 0x10000); + return u16(imm); + } + u32 GetImmediateU32() const { + const u64 imm = value.GetImmediateAsU64(); + ASSERT(imm < 0x100000000); + return u32(imm); + } + u64 GetImmediateU64() const { + return value.GetImmediateAsU64(); + } + IR::Cond GetImmediateCond() const { + ASSERT(IsImmediate() && GetType() == IR::Type::Cond); + return value.GetCond(); + } + IR::AccType GetImmediateAccType() const { + ASSERT(IsImmediate() && GetType() == IR::Type::AccType); + return value.GetAccType(); + } private: friend class RegAlloc; - explicit Argument(RegAlloc& reg_alloc) - : reg_alloc{reg_alloc} {} - - bool allocated = false; + explicit Argument(RegAlloc& reg_alloc) : reg_alloc{reg_alloc} {} RegAlloc& reg_alloc; IR::Value value; + bool allocated = false; }; struct HostLocInfo final { @@ -57,9 +77,16 @@ struct HostLocInfo final { size_t expected_uses = 0; bool realized = false; - bool Contains(const IR::Inst*) const; - void SetupScratchLocation(); - bool IsCompletelyEmpty() const; + bool Contains(const IR::Inst* value) const { + return std::find(values.begin(), values.end(), value) != values.end(); + } + void SetupScratchLocation() { + ASSERT(IsCompletelyEmpty()); + realized = true; + } + bool IsCompletelyEmpty() const { + return values.empty() && !locked && !realized && !accumulated_uses && !expected_uses && !uses_this_inst; + } void UpdateUses(); }; @@ -67,7 +94,7 @@ class RegAlloc { public: using ArgumentInfo = std::array; - explicit RegAlloc(powah::Context& as) : as{as} {} + explicit RegAlloc(powah::Context& code) : code{code} {} ArgumentInfo GetArgumentInfo(IR::Inst* inst); bool IsValueLive(IR::Inst* inst) const; @@ -77,15 +104,13 @@ public: void UpdateAllUses(); void AssertNoMoreUses() const; - powah::GPR ScratchGpr(std::optional> desired_locations = {}); - void Use(Argument& arg, HostLoc host_loc); - void UseScratch(Argument& arg, HostLoc host_loc); + powah::GPR ScratchGpr(); powah::GPR UseGpr(Argument& arg); powah::GPR UseScratchGpr(Argument& arg); void DefineValue(IR::Inst* inst, powah::GPR const gpr) noexcept; void DefineValue(IR::Inst* inst, Argument& arg) noexcept; private: - u32 AllocateRegister(const std::array& regs, const std::vector& order) const; + std::optional AllocateRegister(const std::array& regs, const std::vector& order) const; void SpillGpr(u32 index); void SpillFpr(u32 index); u32 FindFreeSpill() const; @@ -94,7 +119,7 @@ private: HostLocInfo& ValueInfo(HostLoc host_loc); HostLocInfo& ValueInfo(const IR::Inst* value); - powah::Context& as; + powah::Context& code; std::array gprs; std::array fprs; std::array vprs; From 897f9d50294db39a404700afd1cca5896c75f372 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 3 Nov 2025 03:41:46 +0000 Subject: [PATCH 10/49] exclude powah from non-ppc64 Signed-off-by: lizzie --- externals/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index d243569b52..b0cce968ec 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -250,7 +250,9 @@ endif() add_subdirectory(nx_tzdb) # PowerPC emitter -add_subdirectory(powah) +if (ARCHITECTURE_ppc64) + add_subdirectory(powah) +endif() add_library(tz tz/tz/tz.cpp) target_include_directories(tz PUBLIC ./tz) From 695a40872a959eec4fa8c402ce7a84e4c5859efd Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 3 Nov 2025 04:10:19 +0000 Subject: [PATCH 11/49] fix license Signed-off-by: lizzie --- src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.h b/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.h index 6161bfebe2..512894fdce 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/a64_address_space.h @@ -26,8 +26,11 @@ public: protected: friend class A64Core; + + void EmitPrelude(); EmitConfig GetEmitConfig() override; void RegisterNewBasicBlock(const IR::Block& block, const EmittedBlockInfo& block_info) override; + const A64::UserConfig conf; BlockRangeInformation block_ranges; }; From f6d6e3c19586181b20192e489913709a724f9f91 Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 3 Nov 2025 20:26:56 +0000 Subject: [PATCH 12/49] remove args, directly ref inst stuff Signed-off-by: lizzie --- .../dynarmic/backend/ppc64/emit_ppc64_a32.cpp | 31 +- .../ppc64/emit_ppc64_data_processing.cpp | 304 +++++++----------- .../src/dynarmic/backend/ppc64/reg_alloc.cpp | 92 +++--- .../src/dynarmic/backend/ppc64/reg_alloc.h | 56 +--- 4 files changed, 186 insertions(+), 297 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp index c032f38500..6b8976811f 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp @@ -4,6 +4,7 @@ #include #include +#include "dynarmic/frontend/A32/a32_types.h" #include "dynarmic/backend/ppc64/a32_core.h" #include "dynarmic/backend/ppc64/abi.h" #include "dynarmic/backend/ppc64/emit_context.h" @@ -76,13 +77,14 @@ void EmitIR(powah::Context&, EmitContext&, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const index = ctx.reg_alloc.UseScratchGpr(args[1]); - code.SLDI(index, index, 3); - code.ADD(result, PPC64::RJIT, index); - code.LD(result, result, offsetof(A32JitState, regs)); - ctx.reg_alloc.DefineValue(inst, result); + if (inst->GetArg(0).GetType() == IR::Type::A32Reg) { + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + code.ADDI(result, PPC64::RJIT, A32::RegNumber(inst->GetArg(0).GetA32RegRef()) * sizeof(u32)); + code.LD(result, result, offsetof(A32JitState, regs)); + ctx.reg_alloc.DefineValue(inst, result); + } else { + ASSERT(false && "unimp"); + } } template<> @@ -102,13 +104,14 @@ void EmitIR(powah::Context&, EmitContext&, IR::Inst*) template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const index = ctx.reg_alloc.UseScratchGpr(args[1]); - code.SLDI(index, index, 3); - code.ADD(result, PPC64::RJIT, index); - code.STD(result, result, offsetof(A32JitState, regs)); - ctx.reg_alloc.DefineValue(inst, result); + powah::GPR const value = ctx.reg_alloc.UseGpr(args[1]); + if (inst->GetArg(0).GetType() == IR::Type::A32Reg) { + powah::GPR const addr = ctx.reg_alloc.ScratchGpr(); + code.ADDI(addr, PPC64::RJIT, A32::RegNumber(inst->GetArg(0).GetA32RegRef()) * sizeof(u32)); + code.STD(value, addr, offsetof(A32JitState, regs)); + } else { + ASSERT(false && "unimp"); + } } template<> 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 34edd4270c..60e7865e6d 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 @@ -36,9 +36,8 @@ uint64_t f(uint64_t a) { return (uint16_t)a; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xffff); ctx.reg_alloc.DefineValue(inst, result); } @@ -48,9 +47,8 @@ uint64_t f(uint64_t a) { return (uint8_t)a; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xff); ctx.reg_alloc.DefineValue(inst, result); } @@ -60,9 +58,8 @@ uint64_t f(uint64_t a) { return (uint32_t)(a >> 32); } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SRDI(result, source, 32); ctx.reg_alloc.DefineValue(inst, result); } @@ -72,9 +69,8 @@ uint64_t f(uint64_t a) { return ((uint32_t)a) >> 31; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 1, 31, 31); ctx.reg_alloc.DefineValue(inst, result); } @@ -84,9 +80,8 @@ uint64_t f(uint64_t a) { return a == 0; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CNTLZD(result, source); code.SRDI(result, result, 6); ctx.reg_alloc.DefineValue(inst, result); @@ -97,9 +92,8 @@ uint64_t f(uint64_t a) { return (uint32_t)a == 0; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CNTLZW(result, source); code.SRWI(result, result, 5); ctx.reg_alloc.DefineValue(inst, result); @@ -110,11 +104,10 @@ uint64_t f(uint64_t a) { return (a & 1) != 0; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); - if (args[1].IsImmediate()) { - auto const shift = args[1].GetImmediateU8(); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + if (inst->GetArg(1).IsImmediate()) { + auto const shift = inst->GetArg(1).GetImmediateAsU64(); if (shift > 0) { code.RLDICL(result, source, (64 - shift - 1) & 0x3f, 63); } @@ -138,11 +131,10 @@ uint64_t f(jit *p, uint64_t a, uint64_t b) { } */ static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const nzcv = ctx.reg_alloc.ScratchGpr(); - powah::GPR const then_ = ctx.reg_alloc.UseScratchGpr(args[1]); - powah::GPR const else_ = ctx.reg_alloc.UseScratchGpr(args[2]); - switch (args[0].GetImmediateCond()) { + powah::GPR const then_ = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + powah::GPR const else_ = ctx.reg_alloc.UseGpr(args[2]); + switch (inst->GetArg(0).GetCond()) { case IR::Cond::EQ: // Z == 1 code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); code.ANDI_(nzcv, nzcv, 4); @@ -232,16 +224,18 @@ static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, } break; case IR::Cond::LE: { // Z == 1 || N != V powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + powah::GPR const tmp2 = ctx.reg_alloc.ScratchGpr(); powah::Label const l_ne = code.DefineLabel(); + code.MR(tmp2, then_); code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); code.ANDI_(tmp, nzcv, 4); code.BNE(powah::CR0, l_ne); code.SRWI(tmp, nzcv, 3); code.XOR(nzcv, tmp, nzcv); code.ANDI_(nzcv, nzcv, 1); - code.ISELGT(then_, then_, else_); + code.ISELGT(tmp2, then_, else_); code.LABEL(l_ne); - code.MR(nzcv, then_); + code.MR(nzcv, tmp2); } break; default: ASSERT(false && "unimp"); @@ -271,10 +265,9 @@ void EmitIR(powah::Context& code, EmitContext template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SLW(result, source, shift); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -282,20 +275,18 @@ void EmitIR(powah::Context& code, EmitContext& c template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SLD(result, source, shift); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SRW(result, source, shift); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -306,20 +297,18 @@ uint64_t f(uint64_t a, uint64_t s) { return a >> s; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SRD(result, source, shift); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SRAW(result, source, shift); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -327,10 +316,9 @@ void EmitIR(powah::Context& code, EmitContex template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const shift = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SRAD(result, source, shift); ctx.reg_alloc.DefineValue(inst, result); } @@ -338,10 +326,9 @@ void EmitIR(powah::Context& code, EmitContex // __builtin_rotateright32 template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.NEG(result, src_a, powah::R0); code.ROTLW(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -350,10 +337,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.NEG(result, src_a, powah::R0); code.ROTLD(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -361,10 +347,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.NEG(result, src_a, powah::R0); code.ROTLD(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -372,9 +357,8 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SLW(result, source, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -382,18 +366,16 @@ void EmitIR(powah::Context& code, EmitCont template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SLD(result, source, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SRW(result, source, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -401,18 +383,16 @@ void EmitIR(powah::Context& code, EmitCon template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SRD(result, source, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SRAW(result, source, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -420,19 +400,17 @@ void EmitIR(powah::Context& code, Emit template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SRAD(result, source, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.NEG(result, src_a, powah::R0); code.ROTLD(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -441,10 +419,9 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.NEG(result, src_a, powah::R0); code.ROTLD(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -452,10 +429,9 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.ADD(result, src_a, src_b); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -463,20 +439,18 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.ADD(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SUBF(result, src_b, src_a); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -484,20 +458,18 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SUBF(result, src_b, src_a); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.MULLW(result, src_a, src_b); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -505,40 +477,36 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.MULLD(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.MULLD(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.MULLD(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.DIVDU(result, src_a, src_b); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -546,20 +514,18 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.DIVDU(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.DIVW(result, src_a, src_b); code.EXTSW(result, result); ctx.reg_alloc.DefineValue(inst, result); @@ -567,40 +533,36 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.DIVD(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.AND(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.AND(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.NAND(result, src_a, src_b); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -608,20 +570,18 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::In template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.NAND(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.XOR(result, src_a, src_b); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -629,20 +589,18 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.XOR(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.OR(result, src_a, src_b); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -650,19 +608,17 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.OR(result, src_a, src_b); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.NOT(result, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -670,18 +626,16 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.NOT(result, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.EXTSB(result, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -689,9 +643,8 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.EXTSH(result, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -699,36 +652,32 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.EXTSH(result, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.EXTSB(result, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.EXTSW(result, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xff); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -736,9 +685,8 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xffff); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -746,28 +694,25 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xff); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xffff); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); - code.RLDICL(result, result, 0, 32); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + code.RLDICL(result, source, 0, 32); ctx.reg_alloc.DefineValue(inst, result); } @@ -779,9 +724,8 @@ void EmitIR(powah::Context& code, EmitContext& // __builtin_bswap32 template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); if (false) { //code.BRW(result, source); code.RLDICL(result, result, 0, 32); @@ -795,9 +739,8 @@ void EmitIR(powah::Context& code, EmitContext& ctx, template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); if (false) { //code.BRH(result, source); code.RLWINM(result, source, 0, 0xff); @@ -811,9 +754,8 @@ void EmitIR(powah::Context& code, EmitContext& ctx, template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); if (false) { //code.BRD(result, source); } else { @@ -837,9 +779,8 @@ void EmitIR(powah::Context& code, EmitContext& ctx, // __builtin_clz template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CNTLZW(result, source); ctx.reg_alloc.DefineValue(inst, result); } @@ -847,9 +788,8 @@ void EmitIR(powah::Context& code, EmitContext& // __builtin_clz template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CNTLZD(result, source); ctx.reg_alloc.DefineValue(inst, result); } @@ -876,10 +816,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CMPD(powah::CR0, result, src_a); code.ISELGT(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -888,10 +827,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CMPD(powah::CR0, result, src_a); code.ISELGT(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -899,10 +837,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CMPLW(result, src_a); code.ISELGT(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -911,10 +848,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CMPLD(result, src_a); code.ISELGT(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -922,10 +858,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CMPW(powah::CR0, result, src_a); code.ISELGT(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -934,10 +869,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CMPD(powah::CR0, result, src_a); code.ISELGT(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -945,10 +879,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CMPLW(result, src_a); code.ISELGT(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -957,10 +890,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(args[0]); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(args[0]); + powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CMPLD(result, src_a); code.ISELGT(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp index e1d5cd9ee5..b389551cf5 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -31,46 +31,28 @@ void HostLocInfo::UpdateUses() { } } -RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) { - ArgumentInfo ret = {Argument{*this}, Argument{*this}, Argument{*this}, Argument{*this}}; - for (size_t i = 0; i < inst->NumArgs(); i++) { - const IR::Value arg = inst->GetArg(i); - ret[i].value = arg; - if (!arg.IsImmediate() && !IsValuelessType(arg.GetType())) { - ASSERT(ValueLocation(arg.GetInst()) && "argument must already been defined"); - ValueInfo(arg.GetInst()).uses_this_inst++; - } - } - return ret; -} - bool RegAlloc::IsValueLive(IR::Inst* inst) const { return !!ValueLocation(inst); } void RegAlloc::UpdateAllUses() { - for (auto& gpr : gprs) { + for (auto& gpr : gprs) gpr.UpdateUses(); - } - for (auto& fpr : fprs) { + for (auto& fpr : fprs) fpr.UpdateUses(); - } - for (auto& spill : spills) { + for (auto& spill : spills) spill.UpdateUses(); - } } -void RegAlloc::DefineAsExisting(IR::Inst* inst, Argument& arg) { +void RegAlloc::DefineAsExisting(IR::Inst* inst, IR::Value arg) { ASSERT(!ValueLocation(inst)); - - if (arg.value.IsImmediate()) { - inst->ReplaceUsesWith(arg.value); - return; + if (arg.IsImmediate()) { + inst->ReplaceUsesWith(arg); + } else { + auto& info = ValueInfo(arg.GetInst()); + info.values.emplace_back(inst); + info.expected_uses += inst->UseCount(); } - - auto& info = ValueInfo(arg.value.GetInst()); - info.values.emplace_back(inst); - info.expected_uses += inst->UseCount(); } void RegAlloc::AssertNoMoreUses() const { @@ -129,8 +111,17 @@ std::optional RegAlloc::ValueLocation(const IR::Inst* value) const { return std::nullopt; } -static powah::GPR HostLocToReg(HostLoc h) noexcept { - if (u8(h) >= u8(HostLoc::R0) && u8(h) <= u8(HostLoc::R31)) +inline bool HostLocIsGpr(HostLoc h) noexcept { + return u8(h) >= u8(HostLoc::R0) && u8(h) <= u8(HostLoc::R31); +} +inline bool HostLocIsFpr(HostLoc h) noexcept { + return u8(h) >= u8(HostLoc::FR0) && u8(h) <= u8(HostLoc::FR31); +} +inline bool HostLocIsVpr(HostLoc h) noexcept { + return u8(h) >= u8(HostLoc::VR0) && u8(h) <= u8(HostLoc::VR31); +} +inline std::variant HostLocToReg(HostLoc h) noexcept { + if (HostLocIsGpr(h)) return powah::GPR{uint32_t(h)}; ASSERT(false && "unimp"); } @@ -160,21 +151,30 @@ HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) { ASSERT(false && "unimp"); } +/// @brief Defines a register temporal to use (and locks it) powah::GPR RegAlloc::ScratchGpr() { auto const r = AllocateRegister(gprs, PPC64::GPR_ORDER); return powah::GPR{*r}; } -powah::GPR RegAlloc::UseGpr(Argument& arg) { - ASSERT(!arg.allocated); - arg.allocated = true; - return ScratchGpr(); -} - -powah::GPR RegAlloc::UseScratchGpr(Argument& arg) { - ASSERT(!arg.allocated); - arg.allocated = true; - return ScratchGpr(); +/// @brief Uses the given GPR of the argument +powah::GPR RegAlloc::UseGpr(IR::Value arg) { + if (arg.IsImmediate()) { + // HOLY SHIT EVIL HAXX + auto const reg = ScratchGpr(); + auto const imm = arg.GetImmediateAsU64(); + if (imm >= 0xffff) { + ASSERT(false && "big imms"); + } else { + code.LI(reg, imm); + } + return reg; + } else { + ASSERT(arg.allocated && "undefined (non-imm) arg"); + auto const loc = ValueLocation(arg.GetInst()); + ASSERT(loc && HostLocIsGpr(*loc)); + return std::get(HostLocToReg(*loc)); + } } void RegAlloc::DefineValue(IR::Inst* inst, powah::GPR const gpr) noexcept { @@ -182,22 +182,22 @@ void RegAlloc::DefineValue(IR::Inst* inst, powah::GPR const gpr) noexcept { ValueInfo(HostLoc(gpr.index)).values.push_back(inst); } -void RegAlloc::DefineValue(IR::Inst* inst, Argument& arg) noexcept { +void RegAlloc::DefineValue(IR::Inst* inst, IR::Value arg) noexcept { + ASSERT(!ValueLocation(inst) && "inst has already been defined"); ASSERT(!arg.allocated); arg.allocated = true; - ASSERT(!ValueLocation(inst) && "inst has already been defined"); - if (arg.value.IsImmediate()) { + if (arg.IsImmediate()) { HostLoc const loc{u8(ScratchGpr().index)}; ValueInfo(loc).values.push_back(inst); - auto const value = arg.value.GetImmediateAsU64(); + auto const value = arg.GetImmediateAsU64(); if (value >= 0x7fff) { ASSERT(false && "unimp"); } else { //code.LI(HostLocToReg(loc), value); } } else { - ASSERT(ValueLocation(arg.value.GetInst()) && "arg.value must already be defined"); - const HostLoc loc = *ValueLocation(arg.value.GetInst()); + ASSERT(ValueLocation(arg.GetInst()) && "arg must already be defined"); + const HostLoc loc = *ValueLocation(arg.GetInst()); ValueInfo(loc).values.push_back(inst); } } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h index 4e5454b86e..89ad92c475 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -24,59 +24,14 @@ namespace Dynarmic::Backend::PPC64 { class RegAlloc; -struct Argument { -public: - IR::Type GetType() const { - return value.GetType(); - } - bool IsImmediate() const { - return value.IsImmediate(); - } - bool GetImmediateU1() const { - return value.GetU1(); - } - u8 GetImmediateU8() const { - const u64 imm = value.GetImmediateAsU64(); - ASSERT(imm < 0x100); - return u8(imm); - } - u16 GetImmediateU16() const { - const u64 imm = value.GetImmediateAsU64(); - ASSERT(imm < 0x10000); - return u16(imm); - } - u32 GetImmediateU32() const { - const u64 imm = value.GetImmediateAsU64(); - ASSERT(imm < 0x100000000); - return u32(imm); - } - u64 GetImmediateU64() const { - return value.GetImmediateAsU64(); - } - IR::Cond GetImmediateCond() const { - ASSERT(IsImmediate() && GetType() == IR::Type::Cond); - return value.GetCond(); - } - IR::AccType GetImmediateAccType() const { - ASSERT(IsImmediate() && GetType() == IR::Type::AccType); - return value.GetAccType(); - } -private: - friend class RegAlloc; - explicit Argument(RegAlloc& reg_alloc) : reg_alloc{reg_alloc} {} - RegAlloc& reg_alloc; - IR::Value value; - bool allocated = false; -}; - struct HostLocInfo final { std::vector values; - size_t locked = 0; size_t uses_this_inst = 0; size_t accumulated_uses = 0; size_t expected_uses = 0; + /// @brief Lock usage of this register UNTIL a DefineValue() is issued + bool locked = false; bool realized = false; - bool Contains(const IR::Inst* value) const { return std::find(values.begin(), values.end(), value) != values.end(); } @@ -98,17 +53,16 @@ public: ArgumentInfo GetArgumentInfo(IR::Inst* inst); bool IsValueLive(IR::Inst* inst) const; - void DefineAsExisting(IR::Inst* inst, Argument& arg); + void DefineAsExisting(IR::Inst* inst, IR::Value arg); void SpillAll(); void UpdateAllUses(); void AssertNoMoreUses() const; powah::GPR ScratchGpr(); - powah::GPR UseGpr(Argument& arg); - powah::GPR UseScratchGpr(Argument& arg); + powah::GPR UseGpr(IR::Value arg); void DefineValue(IR::Inst* inst, powah::GPR const gpr) noexcept; - void DefineValue(IR::Inst* inst, Argument& arg) noexcept; + void DefineValue(IR::Inst* inst, IR::Value arg) noexcept; private: std::optional AllocateRegister(const std::array& regs, const std::vector& order) const; void SpillGpr(u32 index); From 6e69740ab7e35b8d4b744c127aff7f6cd1720b1d Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 03:21:21 +0000 Subject: [PATCH 13/49] polish up A64 to be ready to accept stuff (but NO-op) Signed-off-by: lizzie --- .../src/dynarmic/backend/ppc64/a32_core.h | 2 - .../dynarmic/backend/ppc64/a32_interface.cpp | 66 +++++++++---------- .../src/dynarmic/backend/ppc64/a64_core.h | 3 - .../dynarmic/backend/ppc64/a64_interface.cpp | 44 +++++-------- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 2 + .../dynarmic/backend/ppc64/emit_ppc64_a32.cpp | 2 +- .../ppc64/emit_ppc64_data_processing.cpp | 2 +- .../src/dynarmic/backend/ppc64/reg_alloc.cpp | 3 - .../src/dynarmic/backend/ppc64/reg_alloc.h | 4 -- 9 files changed, 53 insertions(+), 75 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index b4f69c25e0..2f051ab5e7 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -30,8 +30,6 @@ struct A32JitState { class A32AddressSpace final { public: explicit A32AddressSpace(const A32::UserConfig& conf); - IR::Block GenerateIR(IR::LocationDescriptor) const; - CodePtr Get(IR::LocationDescriptor descriptor); CodePtr GetOrEmit(IR::LocationDescriptor descriptor); void ClearCache(); private: diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index b519f95c49..b7f2808728 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -26,26 +26,16 @@ A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf) } -IR::Block A32AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const { - IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); +CodePtr A32AddressSpace::GetOrEmit(IR::LocationDescriptor desc) { + if (auto const it = block_entries.find(desc.Value()); it != block_entries.end()) + return it->second; + + IR::Block ir_block = A32::Translate(A32::LocationDescriptor{desc}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); Optimization::Optimize(ir_block, conf, {}); - return ir_block; -} - -CodePtr A32AddressSpace::Get(IR::LocationDescriptor descriptor) { - auto const it = block_entries.find(descriptor.Value()); - return it != block_entries.end() ? it->second : nullptr; -} - -CodePtr A32AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) { - if (CodePtr block_entry = Get(descriptor); block_entry != nullptr) - return block_entry; - - IR::Block ir_block = GenerateIR(descriptor); const EmittedBlockInfo block_info = Emit(std::move(ir_block)); - block_infos.insert_or_assign(descriptor.Value(), block_info); - block_entries.insert_or_assign(descriptor.Value(), block_info.entry_point); + block_infos.insert_or_assign(desc.Value(), block_info); + block_entries.insert_or_assign(desc.Value(), block_info.entry_point); return block_info.entry_point; } @@ -75,19 +65,23 @@ using namespace Dynarmic::Backend::PPC64; struct Jit::Impl final { Impl(Jit* jit_interface, A32::UserConfig conf) - : jit_interface(jit_interface) - , conf(conf) + : conf(conf) , current_address_space(conf) - , core(conf) {} + , core(conf) + , jit_interface(jit_interface) {} HaltReason Run() { - HaltReason hr = core.Run(current_address_space, current_state, &halt_reason); + ASSERT(!is_executing); + is_executing = false; + HaltReason hr = core.Run(current_address_space, jit_state, &halt_reason); + is_executing = true; RequestCacheInvalidation(); return hr; } HaltReason Step() { - RequestCacheInvalidation(); + // HaltReason hr = core.Step(current_address_space, jit_state, &halt_reason); + // RequestCacheInvalidation(); return HaltReason{}; } @@ -104,7 +98,7 @@ struct Jit::Impl final { } void Reset() { - current_state = {}; + jit_state = {}; } void HaltExecution(HaltReason hr) { @@ -116,39 +110,39 @@ struct Jit::Impl final { } std::array& Regs() { - return current_state.regs; + return jit_state.regs; } const std::array& Regs() const { - return current_state.regs; + return jit_state.regs; } std::array& ExtRegs() { - return current_state.ext_regs; + return jit_state.ext_regs; } const std::array& ExtRegs() const { - return current_state.ext_regs; + return jit_state.ext_regs; } u32 Cpsr() const { - return current_state.cpsr_nzcv; + return jit_state.cpsr_nzcv; } void SetCpsr(u32 value) { - current_state.cpsr_nzcv = value; + jit_state.cpsr_nzcv = value; } u32 Fpscr() const { - return current_state.fpscr; + return jit_state.fpscr; } void SetFpscr(u32 value) { - current_state.fpscr = value; + jit_state.fpscr = value; } void ClearExclusiveState() { - current_state.exclusive_state = false; + jit_state.exclusive_state = false; } private: @@ -158,15 +152,17 @@ private: invalid_cache_ranges.clear(); } - Jit* jit_interface; A32::UserConfig conf; - A32JitState current_state{}; + A32JitState jit_state{}; A32AddressSpace current_address_space; A32Core core; + Jit* jit_interface; volatile u32 halt_reason = 0; - std::mutex invalidation_mutex; + bool is_executing = false; + boost::icl::interval_set invalid_cache_ranges; bool invalidate_entire_cache = false; + std::mutex invalidation_mutex; }; Jit::Jit(UserConfig conf) : impl(std::make_unique(this, conf)) {} diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 143dbb19f7..2ed033323b 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -37,12 +37,10 @@ struct A64JitState { class A64AddressSpace final { public: explicit A64AddressSpace(const A64::UserConfig& conf); - CodePtr Get(IR::LocationDescriptor descriptor); CodePtr GetOrEmit(IR::LocationDescriptor descriptor); void ClearCache(); private: friend class A64Core; - void EmitPrelude(); EmittedBlockInfo Emit(IR::Block ir_block); void Link(EmittedBlockInfo& block); @@ -57,7 +55,6 @@ private: class A64Core final { public: explicit A64Core(const A64::UserConfig&) {} - HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { const auto loc = thread_ctx.GetLocationDescriptor(); const auto entry = process.GetOrEmit(loc); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 4272ee183b..2e2b3421b6 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -25,15 +25,9 @@ A64AddressSpace::A64AddressSpace(const A64::UserConfig& conf) } -CodePtr A64AddressSpace::Get(IR::LocationDescriptor descriptor) { - if (auto const iter = block_entries.find(descriptor.Value()); iter != block_entries.end()) - return iter->second; - return nullptr; -} - CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor desc) { - if (CodePtr block_entry = Get(desc)) - return block_entry; + if (auto const it = block_entries.find(desc.Value()); it != block_entries.end()) + return it->second; const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); @@ -74,28 +68,23 @@ using namespace Dynarmic::Backend::PPC64; struct Jit::Impl final { Impl(Jit* jit_interface, A64::UserConfig conf) : conf(conf) - , emitter(conf) {} + , current_address_space(conf) + , core(conf) + , jit_interface(jit_interface) {} HaltReason Run() { ASSERT(!is_executing); - //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason))); is_executing = true; - auto const current_loc = jit_state.GetLocationDescriptor(); - const HaltReason hr = {};//block_of_code.RunCode(&jit_state, jit_state.GetOrEmit(current_loc)); - //PerformRequestedCacheInvalidation(hr); + HaltReason hr = core.Run(current_address_space, jit_state, &halt_reason); is_executing = false; + RequestCacheInvalidation(); return hr; } HaltReason Step() { - ASSERT(!is_executing); - // //PerformRequestedCacheInvalidation(HaltReason(Atomic::Load(&jit_state.halt_reason))); - // is_executing = true; - // //const HaltReason hr = block_of_code.StepCode(&jit_state, GetCurrentSingleStep()); - // //PerformRequestedCacheInvalidation(hr); - // is_executing = false; - // return hr; - return {}; + // HaltReason hr = core.Step(current_address_space, jit_state, &halt_reason); + // RequestCacheInvalidation(); + return HaltReason{}; } void ClearCache() { @@ -225,13 +214,16 @@ private: invalid_cache_ranges.clear(); } + A64::UserConfig conf; + A64JitState jit_state{}; + A64AddressSpace current_address_space; + A64Core core; + Jit* jit_interface; + volatile u32 halt_reason = 0; bool is_executing = false; - const UserConfig conf; - A64JitState jit_state; - A64AddressSpace emitter; - Optimization::PolyfillOptions polyfill_options; - bool invalidate_entire_cache = false; + boost::icl::interval_set invalid_cache_ranges; + bool invalidate_entire_cache = false; std::mutex invalidation_mutex; }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 94e1c50862..6109d4c3a9 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -124,6 +124,8 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf } } + // auto const cycles_to_add = block.CycleCount(); + // Xticks for (size_t i = 0; i < gpr_order.size(); ++i) code.LD(powah::GPR{gpr_order[i]}, powah::R1, -(i * 8)); code.BLR(); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp index 6b8976811f..2200df3c8c 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp @@ -104,7 +104,7 @@ void EmitIR(powah::Context&, EmitContext&, IR::Inst*) template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const value = ctx.reg_alloc.UseGpr(args[1]); + powah::GPR const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); if (inst->GetArg(0).GetType() == IR::Type::A32Reg) { powah::GPR const addr = ctx.reg_alloc.ScratchGpr(); code.ADDI(addr, PPC64::RJIT, A32::RegNumber(inst->GetArg(0).GetA32RegRef()) * sizeof(u32)); 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 60e7865e6d..8ae23c2487 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 @@ -133,7 +133,7 @@ uint64_t f(jit *p, uint64_t a, uint64_t b) { static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { powah::GPR const nzcv = ctx.reg_alloc.ScratchGpr(); powah::GPR const then_ = ctx.reg_alloc.UseGpr(inst->GetArg(1)); - powah::GPR const else_ = ctx.reg_alloc.UseGpr(args[2]); + powah::GPR const else_ = ctx.reg_alloc.UseGpr(inst->GetArg(2)); switch (inst->GetArg(0).GetCond()) { case IR::Cond::EQ: // Z == 1 code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp index b389551cf5..7a114fe5fd 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -170,7 +170,6 @@ powah::GPR RegAlloc::UseGpr(IR::Value arg) { } return reg; } else { - ASSERT(arg.allocated && "undefined (non-imm) arg"); auto const loc = ValueLocation(arg.GetInst()); ASSERT(loc && HostLocIsGpr(*loc)); return std::get(HostLocToReg(*loc)); @@ -184,8 +183,6 @@ void RegAlloc::DefineValue(IR::Inst* inst, powah::GPR const gpr) noexcept { void RegAlloc::DefineValue(IR::Inst* inst, IR::Value arg) noexcept { ASSERT(!ValueLocation(inst) && "inst has already been defined"); - ASSERT(!arg.allocated); - arg.allocated = true; if (arg.IsImmediate()) { HostLoc const loc{u8(ScratchGpr().index)}; ValueInfo(loc).values.push_back(inst); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h index 89ad92c475..8798a33962 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -47,11 +47,7 @@ struct HostLocInfo final { class RegAlloc { public: - using ArgumentInfo = std::array; - explicit RegAlloc(powah::Context& code) : code{code} {} - - ArgumentInfo GetArgumentInfo(IR::Inst* inst); bool IsValueLive(IR::Inst* inst) const; void DefineAsExisting(IR::Inst* inst, IR::Value arg); From 684188d3755a168a6687e12f145aac9276e3c0a5 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 03:41:22 +0000 Subject: [PATCH 14/49] "A64: ADD" passes (except on PC check) Signed-off-by: lizzie --- .../dynarmic/backend/ppc64/a64_interface.cpp | 4 +++ .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 7 ++++-- .../dynarmic/backend/ppc64/emit_ppc64_a32.cpp | 4 +-- .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 25 +++++++++++++++---- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 2e2b3421b6..0490792546 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -34,6 +34,10 @@ CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor desc) { }; IR::Block ir_block = A64::Translate(A64::LocationDescriptor{desc}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); Optimization::Optimize(ir_block, conf, {}); + + fmt::print("IR:\n"); + fmt::print("{}\n", IR::DumpBlock(ir_block)); + const EmittedBlockInfo block_info = Emit(std::move(ir_block)); block_infos.insert_or_assign(desc.Value(), block_info); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 6109d4c3a9..6a7cd85a0e 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -23,8 +23,11 @@ template<> 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) { + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + code.MR(result, source); + ctx.reg_alloc.DefineValue(inst, result); } template<> diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp index 2200df3c8c..e577debe1e 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp @@ -80,7 +80,7 @@ void EmitIR(powah::Context& code, EmitContext& ctx, if (inst->GetArg(0).GetType() == IR::Type::A32Reg) { powah::GPR const result = ctx.reg_alloc.ScratchGpr(); code.ADDI(result, PPC64::RJIT, A32::RegNumber(inst->GetArg(0).GetA32RegRef()) * sizeof(u32)); - code.LD(result, result, offsetof(A32JitState, regs)); + code.LWZ(result, result, offsetof(A32JitState, regs)); ctx.reg_alloc.DefineValue(inst, result); } else { ASSERT(false && "unimp"); @@ -108,7 +108,7 @@ void EmitIR(powah::Context& code, EmitContext& ctx, if (inst->GetArg(0).GetType() == IR::Type::A32Reg) { powah::GPR const addr = ctx.reg_alloc.ScratchGpr(); code.ADDI(addr, PPC64::RJIT, A32::RegNumber(inst->GetArg(0).GetA32RegRef()) * sizeof(u32)); - code.STD(value, addr, offsetof(A32JitState, regs)); + code.STW(value, addr, offsetof(A32JitState, regs)); } else { ASSERT(false && "unimp"); } 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 d74baa8252..9a2a7fd4e3 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -4,7 +4,8 @@ #include #include -#include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/frontend/A64/a64_types.h" +#include "dynarmic/backend/ppc64/a64_core.h" #include "dynarmic/backend/ppc64/abi.h" #include "dynarmic/backend/ppc64/emit_context.h" #include "dynarmic/backend/ppc64/emit_ppc64.h" @@ -46,8 +47,15 @@ void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - ASSERT(false && "unimp"); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + code.ADDI(result, PPC64::RJIT, A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64)); + code.LD(result, result, offsetof(A64JitState, regs)); + ctx.reg_alloc.DefineValue(inst, result); + } else { + ASSERT(false && "unimp"); + } } template<> @@ -86,8 +94,15 @@ void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - ASSERT(false && "unimp"); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + powah::GPR const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { + powah::GPR const addr = ctx.reg_alloc.ScratchGpr(); + code.ADDI(addr, PPC64::RJIT, A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64)); + code.STD(value, addr, offsetof(A64JitState, regs)); + } else { + ASSERT(false && "unimp"); + } } template<> From a06a5377ad96c268f691353781fac61900f6face Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 04:02:23 +0000 Subject: [PATCH 15/49] terminal draft1 Signed-off-by: lizzie --- .../dynarmic/backend/ppc64/a32_interface.cpp | 1 + .../dynarmic/backend/ppc64/a64_interface.cpp | 1 + .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 61 +++++++++++++++++-- .../src/dynarmic/backend/ppc64/emit_ppc64.h | 5 +- .../dynarmic/backend/ppc64/emit_ppc64_a32.cpp | 54 ---------------- 5 files changed, 59 insertions(+), 63 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index b7f2808728..6c50e1c647 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -48,6 +48,7 @@ EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) { EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { .enable_cycle_counting = conf.enable_cycle_counting, .always_little_endian = conf.always_little_endian, + .a64_variant = false }); Link(block_info); return block_info; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 0490792546..5e56789fb5 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -54,6 +54,7 @@ EmittedBlockInfo A64AddressSpace::Emit(IR::Block block) { EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { .enable_cycle_counting = conf.enable_cycle_counting, .always_little_endian = true, + .a64_variant = true }); Link(block_info); return block_info; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 6a7cd85a0e..4f1dd49bd9 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -10,6 +10,7 @@ #include #include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/backend/ppc64/a64_core.h" #include "dynarmic/backend/ppc64/abi.h" #include "dynarmic/backend/ppc64/emit_context.h" #include "dynarmic/backend/ppc64/reg_alloc.h" @@ -90,6 +91,57 @@ void EmitIR(powah::Context&, EmitContext&, IR:: ASSERT(false && "unimp"); } +namespace { +void EmitTerminal(powah::Context&, EmitContext&, IR::Term::Interpret, IR::LocationDescriptor, bool) { + ASSERT(false && "unimp"); +} + +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) { + ASSERT(false && "unimp"); +} + +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { + powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + if (ctx.emit_conf.a64_variant) { + code.LI(tmp, terminal.next.Value()); + code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); + } else { + code.LI(tmp, terminal.next.Value()); + code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15); + } +} + +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { + ASSERT(false && "unimp"); +} + +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::PopRSBHint, IR::LocationDescriptor, bool) { + ASSERT(false && "unimp"); +} + +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::FastDispatchHint, IR::LocationDescriptor, bool) { + ASSERT(false && "unimp"); +} + +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + ASSERT(false && "unimp"); +} + +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + ASSERT(false && "unimp"); +} + +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + ASSERT(false && "unimp"); +} + +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + boost::apply_visitor([&](const auto& t) { + EmitTerminal(code, ctx, t, initial_location, is_single_step); + }, terminal); +} +} + EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConfig& emit_conf) { EmittedBlockInfo ebi; RegAlloc reg_alloc{code}; @@ -128,7 +180,10 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf } // auto const cycles_to_add = block.CycleCount(); - // Xticks + + auto const location{ctx.block.Location()}; + auto const term = ctx.block.GetTerminal(); + for (size_t i = 0; i < gpr_order.size(); ++i) code.LD(powah::GPR{gpr_order[i]}, powah::R1, -(i * 8)); code.BLR(); @@ -144,8 +199,4 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf return ebi; } -void EmitRelocation(powah::Context& code, EmitContext& ctx, LinkTarget link_target) { - ASSERT(false && "unimp"); -} - } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h index 5d53027d1d..ac209d8099 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h @@ -41,16 +41,13 @@ struct EmittedBlockInfo { struct EmitConfig { bool enable_cycle_counting; bool always_little_endian; + bool a64_variant; }; struct EmitContext; EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConfig& emit_conf); - template void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst); -void EmitRelocation(powah::Context& code, EmitContext& ctx, LinkTarget link_target); -void EmitA32Cond(powah::Context& code, EmitContext& ctx, IR::Cond cond, powah::Label* label); -void EmitA32Terminal(powah::Context& code, EmitContext& ctx); } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp index e577debe1e..6b8d1997fe 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp @@ -16,60 +16,6 @@ namespace Dynarmic::Backend::PPC64 { -void EmitA32Cond(powah::Context& code, EmitContext&, IR::Cond cond, powah::Label* label) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step); - -void EmitA32Terminal(powah::Context&, EmitContext&, IR::Term::Interpret, IR::LocationDescriptor, bool) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) { - EmitRelocation(code, ctx, LinkTarget::ReturnFromRunCode); -} - -void EmitSetUpperLocationDescriptor(powah::Context& code, EmitContext& ctx, IR::LocationDescriptor new_location, IR::LocationDescriptor old_location) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::PopRSBHint, IR::LocationDescriptor, bool) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::FastDispatchHint, IR::LocationDescriptor, bool) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - ASSERT(false && "unimp"); -} - -void EmitA32Terminal(powah::Context& code, EmitContext& ctx) { - ASSERT(false && "unimp"); -} - template<> void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { ASSERT(false && "unimp"); From 37d4c6e63696196ab56cd365d61b74812133a024 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 04:10:30 +0000 Subject: [PATCH 16/49] A64: ADD now passes Signed-off-by: lizzie --- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 4f1dd49bd9..20c95a62ec 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -180,19 +180,16 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf } // auto const cycles_to_add = block.CycleCount(); - - auto const location{ctx.block.Location()}; - auto const term = ctx.block.GetTerminal(); + EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); for (size_t i = 0; i < gpr_order.size(); ++i) code.LD(powah::GPR{gpr_order[i]}, powah::R1, -(i * 8)); code.BLR(); /* - llvm-objcopy -I binary -O elf64-powerpc --rename-section=.data=.text,code test.bin test.elf - llvm-objdump -d test.elf + llvm-objcopy -I binary -O elf64-powerpc --rename-section=.data=.text,code test.bin test.elf && llvm-objdump -d test.elf */ - static FILE* fp = fopen("test.bin", "ab"); + static FILE* fp = fopen("test.bin", "wb"); fwrite(code.base, code.offset - start_offset, sizeof(uint32_t), fp); ebi.size = code.offset - start_offset; From ff4ae20a8889eaf51e3ef0bf724ed12aed2cb564 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 05:13:48 +0000 Subject: [PATCH 17/49] reglock draft 1 Signed-off-by: lizzie --- externals/powah/powah_emit.hpp | 8 +- .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 142 ++++++++++-------- .../ppc64/emit_ppc64_data_processing.cpp | 28 ++-- .../src/dynarmic/backend/ppc64/reg_alloc.cpp | 22 +-- .../src/dynarmic/backend/ppc64/reg_alloc.h | 45 +++++- 5 files changed, 146 insertions(+), 99 deletions(-) diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index b2f26dc84a..e4fdc3bf65 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -258,9 +258,9 @@ struct Context { base[offset++] = (op | bitExt(ra.index, 6, 5) | bitExt(rs.index, 11, 5) - | bitExt(sh, 16, 5) - | bitExt(mb, 21, 4) - | bitExt(me, 26, 4) + | ((sh & 0x1f) << 11) + | ((mb & 0x1f) << 6) + | ((me & 0x1f) << 1) | bitExt(rc, 31, 1) ); } @@ -359,6 +359,8 @@ struct Context { void CMPDI(GPR const rx, uint32_t si) { CMPI(0, 1, rx, si); } 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 BLR() { base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0); } 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 9a2a7fd4e3..9e2c80c7a1 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -17,41 +17,37 @@ namespace Dynarmic::Backend::PPC64 { template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - ASSERT(false && "unimp"); -} - -template<> -void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - code.ADDI(result, PPC64::RJIT, A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64)); - code.LD(result, result, offsetof(A64JitState, regs)); + auto const offs = offsetof(A64JitState, regs) + + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64); + code.LWZ(result, PPC64::RJIT, offs); ctx.reg_alloc.DefineValue(inst, result); } else { ASSERT(false && "unimp"); @@ -59,38 +55,58 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Ins } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { + powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + auto const offs = offsetof(A64JitState, regs) + + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64); + code.LD(result, PPC64::RJIT, offs); + ctx.reg_alloc.DefineValue(inst, result); + } else { + ASSERT(false && "unimp"); + } +} + +template<> +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { - ASSERT(false && "unimp"); +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { + powah::GPR const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { + powah::GPR const addr = ctx.reg_alloc.ScratchGpr(); + code.ADDI(addr, PPC64::RJIT, A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64)); + code.STD(value, addr, offsetof(A64JitState, regs)); + } else { + ASSERT(false && "unimp"); + } } template<> @@ -106,213 +122,213 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Ins } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } // Memory template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { ASSERT(false && "unimp"); } template<> -void EmitIR(powah::Context&, EmitContext&, IR::Inst*) { +void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { 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 8ae23c2487..242ae03ff1 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 @@ -754,26 +754,24 @@ void EmitIR(powah::Context& code, EmitContext& ctx, template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); if (false) { //code.BRD(result, source); } else { - powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); - code.ROTLDI(tmp, source, 16); - code.ROTLDI(result, source, 8); - code.RLDIMI(result, tmp, 8, 48); - code.ROTLDI(tmp, source, 24); - code.RLDIMI(result, tmp, 16, 40); - code.ROTLDI(tmp, source, 32); - code.RLDIMI(result, tmp, 24, 32); - code.ROTLDI(tmp, source, 48); - code.RLDIMI(result, tmp, 40, 16); - code.ROTLDI(tmp, source, 56); - code.RLDIMI(result, tmp, 48, 8); - code.RLDIMI(result, source, 56, 0); + powah::GPR const tmp10 = ctx.reg_alloc.ScratchGpr(); + powah::GPR const tmp9 = ctx.reg_alloc.ScratchGpr(); + powah::GPR const tmp3 = ctx.reg_alloc.ScratchGpr(); + code.MR(tmp3, source); + code.ROTLWI(tmp10, tmp3, 24); + code.SRDI(tmp9, tmp3, 32); + code.RLWIMI(tmp10, tmp3, 8, 8, 15); + code.RLWIMI(tmp10, tmp3, 8, 24, 31); + code.ROTLWI(tmp3, tmp9, 24); + code.RLWIMI(tmp3, tmp9, 8, 8, 15); + code.RLWIMI(tmp3, tmp9, 8, 24, 31); + code.RLDIMI(tmp3, tmp10, 32, 0); + ctx.reg_alloc.DefineValue(inst, tmp3); } - ctx.reg_alloc.DefineValue(inst, result); } // __builtin_clz diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp index 7a114fe5fd..5cd113789e 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -62,14 +62,14 @@ void RegAlloc::AssertNoMoreUses() const { ASSERT(std::all_of(spills.begin(), spills.end(), is_empty)); } -std::optional RegAlloc::AllocateRegister(const std::array& regs, const std::vector& order) const { +std::optional RegAlloc::AllocateRegister(const std::array& regs) const { + auto const order = PPC64::GPR_ORDER; if (auto const it = std::find_if(order.begin(), order.end(), [&](u32 i) { return regs[i].values.empty() && !regs[i].locked; }); it != order.end()) return *it; - std::vector candidates; - std::copy_if(order.begin(), order.end(), std::back_inserter(candidates), [&](u32 i) { return !regs[i].locked; }); - return candidates.empty() ? std::nullopt : std::optional{candidates[0]}; // TODO: LRU + // TODO: Actual proper LRU + return std::nullopt; } void RegAlloc::SpillGpr(u32 index) { @@ -151,14 +151,14 @@ HostLocInfo& RegAlloc::ValueInfo(const IR::Inst* value) { ASSERT(false && "unimp"); } -/// @brief Defines a register temporal to use (and locks it) -powah::GPR RegAlloc::ScratchGpr() { - auto const r = AllocateRegister(gprs, PPC64::GPR_ORDER); - return powah::GPR{*r}; +/// @brief Defines a register RegLock to use (and locks it) +RegLock RegAlloc::ScratchGpr() { + auto const r = AllocateRegister(gprs); + return RegLock(*this, powah::GPR{*r}); } /// @brief Uses the given GPR of the argument -powah::GPR RegAlloc::UseGpr(IR::Value arg) { +RegLock RegAlloc::UseGpr(IR::Value arg) { if (arg.IsImmediate()) { // HOLY SHIT EVIL HAXX auto const reg = ScratchGpr(); @@ -172,7 +172,7 @@ powah::GPR RegAlloc::UseGpr(IR::Value arg) { } else { auto const loc = ValueLocation(arg.GetInst()); ASSERT(loc && HostLocIsGpr(*loc)); - return std::get(HostLocToReg(*loc)); + return RegLock(*this, std::get(HostLocToReg(*loc))); } } @@ -184,7 +184,7 @@ void RegAlloc::DefineValue(IR::Inst* inst, powah::GPR const gpr) noexcept { void RegAlloc::DefineValue(IR::Inst* inst, IR::Value arg) noexcept { ASSERT(!ValueLocation(inst) && "inst has already been defined"); if (arg.IsImmediate()) { - HostLoc const loc{u8(ScratchGpr().index)}; + HostLoc const loc{u8(ScratchGpr().value.index)}; ValueInfo(loc).values.push_back(inst); auto const value = arg.GetImmediateAsU64(); if (value >= 0x7fff) { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h index 8798a33962..00815cf902 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -22,8 +22,6 @@ namespace Dynarmic::Backend::PPC64 { -class RegAlloc; - struct HostLocInfo final { std::vector values; size_t uses_this_inst = 0; @@ -45,8 +43,27 @@ struct HostLocInfo final { void UpdateUses(); }; -class RegAlloc { -public: +struct RegAlloc; + +/// @brief Allows to use RAII to denote liveness/locking of a given register +/// this basically means that we can use temporals and not need to go thru +/// any weird deallocation stuffs :) +template struct RegLock { + inline RegLock(RegAlloc& reg_alloc, T const value) noexcept + : reg_alloc{reg_alloc} + , value{value} + { + SetLock(true); + } + inline ~RegLock() noexcept { SetLock(false); } + operator T const&() { return value; } + operator T() const { return value; } + inline void SetLock(bool v) noexcept; + RegAlloc& reg_alloc; + const T value; +}; + +struct RegAlloc { explicit RegAlloc(powah::Context& code) : code{code} {} bool IsValueLive(IR::Inst* inst) const; void DefineAsExisting(IR::Inst* inst, IR::Value arg); @@ -55,12 +72,15 @@ public: void UpdateAllUses(); void AssertNoMoreUses() const; - powah::GPR ScratchGpr(); - powah::GPR UseGpr(IR::Value arg); + RegLock ScratchGpr(); + RegLock UseGpr(IR::Value arg); void DefineValue(IR::Inst* inst, powah::GPR const gpr) noexcept; void DefineValue(IR::Inst* inst, IR::Value arg) noexcept; private: - std::optional AllocateRegister(const std::array& regs, const std::vector& order) const; + template + friend struct RegLock; + + std::optional AllocateRegister(const std::array& regs) const; void SpillGpr(u32 index); void SpillFpr(u32 index); u32 FindFreeSpill() const; @@ -74,6 +94,17 @@ private: std::array fprs; std::array vprs; std::array spills; + uint32_t lru_counter = 0; }; +template<> inline void RegLock::SetLock(bool v) noexcept { + reg_alloc.gprs[value.index].locked = v; +} +template<> inline void RegLock::SetLock(bool v) noexcept { + reg_alloc.fprs[value.index].locked = v; +} +template<> inline void RegLock::SetLock(bool v) noexcept { + reg_alloc.vprs[value.index].locked = v; +} + } // namespace Dynarmic::Backend::RV64 From 23e11d2a581eaa2b4ddc6ad004deac39cfbcd1de Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 05:14:24 +0000 Subject: [PATCH 18/49] let type deduction do its thing Signed-off-by: lizzie --- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 6 +- .../dynarmic/backend/ppc64/emit_ppc64_a32.cpp | 8 +- .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 12 +- .../ppc64/emit_ppc64_data_processing.cpp | 380 +++++++++--------- 4 files changed, 203 insertions(+), 203 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 20c95a62ec..c71b0c1a5a 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -25,8 +25,8 @@ void EmitIR(powah::Context&, EmitContext&, IR::Inst*) {} template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.MR(result, source); ctx.reg_alloc.DefineValue(inst, result); } @@ -101,7 +101,7 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDisp } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { - powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + auto const tmp = ctx.reg_alloc.ScratchGpr(); if (ctx.emit_conf.a64_variant) { code.LI(tmp, terminal.next.Value()); code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp index 6b8d1997fe..2b9c77f95c 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp @@ -24,7 +24,7 @@ void EmitIR(powah::Context&, EmitContext&, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { if (inst->GetArg(0).GetType() == IR::Type::A32Reg) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + auto const result = ctx.reg_alloc.ScratchGpr(); code.ADDI(result, PPC64::RJIT, A32::RegNumber(inst->GetArg(0).GetA32RegRef()) * sizeof(u32)); code.LWZ(result, result, offsetof(A32JitState, regs)); ctx.reg_alloc.DefineValue(inst, result); @@ -50,9 +50,9 @@ void EmitIR(powah::Context&, EmitContext&, IR::Inst*) template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); if (inst->GetArg(0).GetType() == IR::Type::A32Reg) { - powah::GPR const addr = ctx.reg_alloc.ScratchGpr(); + auto const addr = ctx.reg_alloc.ScratchGpr(); code.ADDI(addr, PPC64::RJIT, A32::RegNumber(inst->GetArg(0).GetA32RegRef()) * sizeof(u32)); code.STW(value, addr, offsetof(A32JitState, regs)); } else { @@ -112,7 +112,7 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + auto const result = ctx.reg_alloc.ScratchGpr(); code.LD(result, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); code.RLWINM(result, result, 31, 31, 31); ctx.reg_alloc.DefineValue(inst, result); 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 9e2c80c7a1..fef31c9de6 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -44,7 +44,7 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR:: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + auto const result = ctx.reg_alloc.ScratchGpr(); auto const offs = offsetof(A64JitState, regs) + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64); code.LWZ(result, PPC64::RJIT, offs); @@ -57,7 +57,7 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Ins template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); + auto const result = ctx.reg_alloc.ScratchGpr(); auto const offs = offsetof(A64JitState, regs) + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64); code.LD(result, PPC64::RJIT, offs); @@ -99,9 +99,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR:: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { - powah::GPR const addr = ctx.reg_alloc.ScratchGpr(); + auto const addr = ctx.reg_alloc.ScratchGpr(); code.ADDI(addr, PPC64::RJIT, A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64)); code.STD(value, addr, offsetof(A64JitState, regs)); } else { @@ -111,9 +111,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Ins template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { - powah::GPR const addr = ctx.reg_alloc.ScratchGpr(); + auto const addr = ctx.reg_alloc.ScratchGpr(); code.ADDI(addr, PPC64::RJIT, A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64)); code.STD(value, addr, offsetof(A64JitState, regs)); } else { 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 242ae03ff1..5c34ff9961 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 @@ -36,8 +36,8 @@ uint64_t f(uint64_t a) { return (uint16_t)a; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xffff); ctx.reg_alloc.DefineValue(inst, result); } @@ -47,8 +47,8 @@ uint64_t f(uint64_t a) { return (uint8_t)a; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xff); ctx.reg_alloc.DefineValue(inst, result); } @@ -58,8 +58,8 @@ uint64_t f(uint64_t a) { return (uint32_t)(a >> 32); } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SRDI(result, source, 32); ctx.reg_alloc.DefineValue(inst, result); } @@ -69,8 +69,8 @@ uint64_t f(uint64_t a) { return ((uint32_t)a) >> 31; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 1, 31, 31); ctx.reg_alloc.DefineValue(inst, result); } @@ -80,8 +80,8 @@ uint64_t f(uint64_t a) { return a == 0; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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); ctx.reg_alloc.DefineValue(inst, result); @@ -92,8 +92,8 @@ uint64_t f(uint64_t a) { return (uint32_t)a == 0; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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); ctx.reg_alloc.DefineValue(inst, result); @@ -104,8 +104,8 @@ uint64_t f(uint64_t a) { return (a & 1) != 0; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); if (inst->GetArg(1).IsImmediate()) { auto const shift = inst->GetArg(1).GetImmediateAsU64(); if (shift > 0) { @@ -131,9 +131,9 @@ uint64_t f(jit *p, uint64_t a, uint64_t b) { } */ static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const nzcv = ctx.reg_alloc.ScratchGpr(); - powah::GPR const then_ = ctx.reg_alloc.UseGpr(inst->GetArg(1)); - powah::GPR const else_ = ctx.reg_alloc.UseGpr(inst->GetArg(2)); + auto const nzcv = ctx.reg_alloc.ScratchGpr(); + auto const then_ = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const else_ = ctx.reg_alloc.UseGpr(inst->GetArg(2)); switch (inst->GetArg(0).GetCond()) { case IR::Cond::EQ: // Z == 1 code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); @@ -188,7 +188,7 @@ static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, code.ISELEQ(nzcv, else_, then_); break; case IR::Cond::GE: { // N == V - powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LWZ(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); code.SRWI(tmp, nzcv, 3); code.XOR(nzcv, tmp, nzcv); @@ -196,7 +196,7 @@ static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, code.ISELGT(nzcv, else_, then_); } break; case IR::Cond::LT: { // N != V - powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LWZ(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); code.SRWI(tmp, nzcv, 3); code.XOR(nzcv, tmp, nzcv); @@ -204,7 +204,7 @@ static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, code.ISELGT(nzcv, then_, else_); } break; case IR::Cond::GT: { // Z == 0 && N == V - powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); + auto const tmp = ctx.reg_alloc.ScratchGpr(); powah::Label const l_ne = code.DefineLabel(); powah::Label const l_cc = code.DefineLabel(); powah::Label const l_fi = code.DefineLabel(); @@ -223,8 +223,8 @@ static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, code.LABEL(l_fi); } break; case IR::Cond::LE: { // Z == 1 || N != V - powah::GPR const tmp = ctx.reg_alloc.ScratchGpr(); - powah::GPR const tmp2 = ctx.reg_alloc.ScratchGpr(); + auto const tmp = ctx.reg_alloc.ScratchGpr(); + auto const tmp2 = ctx.reg_alloc.ScratchGpr(); powah::Label const l_ne = code.DefineLabel(); code.MR(tmp2, then_); code.LD(nzcv, PPC64::RJIT, offsetof(A32JitState, cpsr_nzcv)); @@ -245,29 +245,29 @@ static powah::GPR EmitConditionalSelectX(powah::Context& code, EmitContext& ctx, template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = EmitConditionalSelectX(code, ctx, inst); + auto const result = EmitConditionalSelectX(code, ctx, inst); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = EmitConditionalSelectX(code, ctx, inst); + auto const result = EmitConditionalSelectX(code, ctx, inst); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = EmitConditionalSelectX(code, ctx, inst); + auto const result = EmitConditionalSelectX(code, ctx, inst); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SLW(result, source, shift); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -275,18 +275,18 @@ void EmitIR(powah::Context& code, EmitContext& c template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SLD(result, source, shift); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SRW(result, source, shift); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -297,18 +297,18 @@ uint64_t f(uint64_t a, uint64_t s) { return a >> s; } */ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SRD(result, source, shift); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SRAW(result, source, shift); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -316,9 +316,9 @@ void EmitIR(powah::Context& code, EmitContex template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const shift = ctx.reg_alloc.UseGpr(inst->GetArg(1)); code.SRAD(result, source, shift); ctx.reg_alloc.DefineValue(inst, result); } @@ -326,9 +326,9 @@ void EmitIR(powah::Context& code, EmitContex // __builtin_rotateright32 template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.NEG(result, src_a, powah::R0); code.ROTLW(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -337,9 +337,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.NEG(result, src_a, powah::R0); code.ROTLD(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -347,9 +347,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.NEG(result, src_a, powah::R0); code.ROTLD(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -357,8 +357,8 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SLW(result, source, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -366,16 +366,16 @@ void EmitIR(powah::Context& code, EmitCont template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SLD(result, source, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SRW(result, source, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -383,16 +383,16 @@ void EmitIR(powah::Context& code, EmitCon template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SRD(result, source, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SRAW(result, source, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -400,17 +400,17 @@ void EmitIR(powah::Context& code, Emit template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.SRAD(result, source, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.NEG(result, src_a, powah::R0); code.ROTLD(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -419,9 +419,9 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.NEG(result, src_a, powah::R0); code.ROTLD(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -429,9 +429,9 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -439,18 +439,18 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -458,18 +458,18 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -477,36 +477,36 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -514,18 +514,18 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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.EXTSW(result, result); ctx.reg_alloc.DefineValue(inst, result); @@ -533,36 +533,36 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -570,18 +570,18 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::In template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -589,18 +589,18 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -608,17 +608,17 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + 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); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.NOT(result, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -626,16 +626,16 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.NOT(result, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.EXTSB(result, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -643,8 +643,8 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.EXTSH(result, source); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -652,32 +652,32 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.EXTSH(result, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.EXTSB(result, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.EXTSW(result, source); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xff); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -685,8 +685,8 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xffff); code.RLDICL(result, result, 0, 32); ctx.reg_alloc.DefineValue(inst, result); @@ -694,24 +694,24 @@ void EmitIR(powah::Context& code, EmitContext& template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xff); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLWINM(result, source, 0, 0xffff); ctx.reg_alloc.DefineValue(inst, result); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.RLDICL(result, source, 0, 32); ctx.reg_alloc.DefineValue(inst, result); } @@ -724,8 +724,8 @@ void EmitIR(powah::Context& code, EmitContext& // __builtin_bswap32 template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); if (false) { //code.BRW(result, source); code.RLDICL(result, result, 0, 32); @@ -739,8 +739,8 @@ void EmitIR(powah::Context& code, EmitContext& ctx, template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); if (false) { //code.BRH(result, source); code.RLWINM(result, source, 0, 0xff); @@ -754,13 +754,13 @@ void EmitIR(powah::Context& code, EmitContext& ctx, template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); if (false) { //code.BRD(result, source); } else { - powah::GPR const tmp10 = ctx.reg_alloc.ScratchGpr(); - powah::GPR const tmp9 = ctx.reg_alloc.ScratchGpr(); - powah::GPR const tmp3 = ctx.reg_alloc.ScratchGpr(); + auto const tmp10 = ctx.reg_alloc.ScratchGpr(); + auto const tmp9 = ctx.reg_alloc.ScratchGpr(); + auto const tmp3 = ctx.reg_alloc.ScratchGpr(); code.MR(tmp3, source); code.ROTLWI(tmp10, tmp3, 24); code.SRDI(tmp9, tmp3, 32); @@ -777,8 +777,8 @@ void EmitIR(powah::Context& code, EmitContext& ctx, // __builtin_clz template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CNTLZW(result, source); ctx.reg_alloc.DefineValue(inst, result); } @@ -786,8 +786,8 @@ void EmitIR(powah::Context& code, EmitContext& // __builtin_clz template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); code.CNTLZD(result, source); ctx.reg_alloc.DefineValue(inst, result); } @@ -814,9 +814,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.CMPD(powah::CR0, result, src_a); code.ISELGT(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -825,9 +825,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.CMPD(powah::CR0, result, src_a); code.ISELGT(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -835,9 +835,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.CMPLW(result, src_a); code.ISELGT(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -846,9 +846,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.CMPLD(result, src_a); code.ISELGT(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -856,9 +856,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.CMPW(powah::CR0, result, src_a); code.ISELGT(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -867,9 +867,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.CMPD(powah::CR0, result, src_a); code.ISELGT(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); @@ -877,9 +877,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.CMPLW(result, src_a); code.ISELGT(result, result, src_b); code.RLDICL(result, result, 0, 32); @@ -888,9 +888,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - powah::GPR const result = ctx.reg_alloc.ScratchGpr(); - powah::GPR const src_a = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - powah::GPR const src_b = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + 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(0)); code.CMPLD(result, src_a); code.ISELGT(result, result, src_b); ctx.reg_alloc.DefineValue(inst, result); From 76b1180d0248d6e438043130d5b2b879a06497f3 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 05:23:22 +0000 Subject: [PATCH 19/49] just use STD() + offset, reorder stuff Signed-off-by: lizzie --- src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h | 4 ++-- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 1 + .../src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 13 +++++++++---- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index 2f051ab5e7..51309df704 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -16,8 +16,8 @@ namespace Dynarmic::Backend::PPC64 { struct A32JitState { - alignas(16) std::array ext_regs{}; std::array regs{}; + alignas(16) std::array ext_regs{}; u32 upper_location_descriptor; u32 exclusive_state = 0; u32 cpsr_nzcv = 0; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 2ed033323b..5943072413 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -18,10 +18,10 @@ namespace Dynarmic::Backend::PPC64 { struct A64JitState { using ProgramCounterType = u32; - alignas(16) std::array vec{}; std::array regs{}; - u64 sp = 0; u64 pc = 0; + alignas(16) std::array vec{}; + u64 sp = 0; u32 upper_location_descriptor; u32 exclusive_state = 0; u32 cpsr_nzcv = 0; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index c71b0c1a5a..5c8902924e 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -191,6 +191,7 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf */ static FILE* fp = fopen("test.bin", "wb"); fwrite(code.base, code.offset - start_offset, sizeof(uint32_t), fp); + fflush(fp); ebi.size = code.offset - start_offset; return ebi; 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 fef31c9de6..d446daa0a1 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -102,8 +102,12 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Ins auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { auto const addr = ctx.reg_alloc.ScratchGpr(); - code.ADDI(addr, PPC64::RJIT, A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64)); - code.STD(value, addr, offsetof(A64JitState, regs)); + 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.STD(tmp, addr, offs); } else { ASSERT(false && "unimp"); } @@ -114,8 +118,9 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Ins auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { auto const addr = ctx.reg_alloc.ScratchGpr(); - code.ADDI(addr, PPC64::RJIT, A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64)); - code.STD(value, addr, offsetof(A64JitState, regs)); + auto const offs = offsetof(A64JitState, regs) + + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64); + code.STD(value, addr, offs); } else { ASSERT(false && "unimp"); } From 72bc40c50b6c98e3fa9aaecf8559238ac38127c9 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 05:24:29 +0000 Subject: [PATCH 20/49] i forgot jit pointer, again Signed-off-by: lizzie --- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 d446daa0a1..35e951bc0a 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -101,13 +101,12 @@ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { - auto const addr = ctx.reg_alloc.ScratchGpr(); 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.STD(tmp, addr, offs); + code.STD(tmp, PPC64::RJIT, offs); } else { ASSERT(false && "unimp"); } @@ -117,10 +116,9 @@ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(1)); if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { - auto const addr = ctx.reg_alloc.ScratchGpr(); auto const offs = offsetof(A64JitState, regs) + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64); - code.STD(value, addr, offs); + code.STD(value, PPC64::RJIT, offs); } else { ASSERT(false && "unimp"); } From 70b407070922edd59a04c3cbad9c3d7e7445adb2 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 05:44:54 +0000 Subject: [PATCH 21/49] more fixes Signed-off-by: lizzie --- .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 9 ++++- .../ppc64/emit_ppc64_data_processing.cpp | 40 +++++++++++-------- 2 files changed, 31 insertions(+), 18 deletions(-) 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 35e951bc0a..e2d9cb6ce7 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -45,8 +45,15 @@ template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { auto const result = ctx.reg_alloc.ScratchGpr(); + // Need to account for endianess here... +#ifdef __ORDER_BIG_ENDIAN__ + constexpr u32 pe_offset64 = 4; +#else + constexpr u32 pe_offset64 = 0; +#endif auto const offs = offsetof(A64JitState, regs) - + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64); + + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64) + + pe_offset64; code.LWZ(result, PPC64::RJIT, offs); ctx.reg_alloc.DefineValue(inst, result); } else { 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 5c34ff9961..39cebc6339 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 @@ -16,9 +16,15 @@ namespace Dynarmic::Backend::PPC64 { +// uint64_t pack2x1(uint32_t lo, uint32_t hi) { return (uint64_t)lo | ((uint64_t)hi << 32); } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - ASSERT(false && "unimp"); + auto const lo = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + auto const hi = ctx.reg_alloc.UseGpr(inst->GetArg(1)); + auto const result = ctx.reg_alloc.ScratchGpr(); + code.SLDI(result, hi, 32); + code.OR(result, result, lo); + ctx.reg_alloc.DefineValue(inst, result); } template<> @@ -26,14 +32,16 @@ void EmitIR(powah::Context& code, EmitContext& ctx, ASSERT(false && "unimp"); } +// uint64_t lsw(uint64_t a) { return (uint32_t)a; } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { - ASSERT(false && "unimp"); + auto const result = ctx.reg_alloc.ScratchGpr(); + auto const source = ctx.reg_alloc.UseGpr(inst->GetArg(0)); + code.RLDICL(result, source, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); } -/* -uint64_t f(uint64_t a) { return (uint16_t)a; } -*/ +// uint64_t f(uint64_t a) { return (uint16_t)a; } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const result = ctx.reg_alloc.ScratchGpr(); @@ -42,9 +50,7 @@ void EmitIR(powah::Context& code, EmitContext& ctx.reg_alloc.DefineValue(inst, result); } -/* -uint64_t f(uint64_t a) { return (uint8_t)a; } -*/ +// uint64_t f(uint64_t a) { return (uint8_t)a; } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const result = ctx.reg_alloc.ScratchGpr(); @@ -53,9 +59,7 @@ void EmitIR(powah::Context& code, EmitContext& ctx.reg_alloc.DefineValue(inst, result); } -/* -uint64_t f(uint64_t a) { return (uint32_t)(a >> 32); } -*/ +// uint64_t msw(uint64_t a) { return a >> 32; } template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const result = ctx.reg_alloc.ScratchGpr(); @@ -724,19 +728,21 @@ void EmitIR(powah::Context& code, EmitContext& // __builtin_bswap32 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)); if (false) { //code.BRW(result, source); - code.RLDICL(result, result, 0, 32); + //code.RLDICL(result, result, 0, 32); } else { - code.ROTLWI(result, source, 8); - code.RLWIMI(result, source, 24, 16, 23); - code.RLWIMI(result, source, 24, 0, 7); + auto const result = ctx.reg_alloc.ScratchGpr(); + code.ROTLWI(result, source, 24); + code.RLWIMI(result, source, 8, 8, 15); + code.RLWIMI(result, source, 8, 24, 31); + code.RLDICL(result, result, 0, 32); + ctx.reg_alloc.DefineValue(inst, result); } - ctx.reg_alloc.DefineValue(inst, result); } +// __builtin_bswap64 template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const result = ctx.reg_alloc.ScratchGpr(); From a3ecd2b6cb3d1526fc16309583672003fa8f8b1a Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 10:00:59 +0000 Subject: [PATCH 22/49] 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(); From 08e5861af98be5ad28d4c464403f76efb29da9e1 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 23:35:00 +0000 Subject: [PATCH 23/49] fixes for cmpld(i) encodings Signed-off-by: lizzie --- externals/powah/data2code.c | 145 +++++---- externals/powah/powah_emit.hpp | 23 +- externals/powah/powah_gen_base.hpp | 468 ++++++++++++++--------------- 3 files changed, 331 insertions(+), 305 deletions(-) diff --git a/externals/powah/data2code.c b/externals/powah/data2code.c index 90b94202c7..13a6bdbb16 100644 --- a/externals/powah/data2code.c +++ b/externals/powah/data2code.c @@ -42,6 +42,8 @@ int main(int argc, char *argv[]) { {"NU",4,4}, }; +#define OP_EXT ((i_opcode << 26) | (i_extopc << 1)) + if (strchr(mem, '[') != NULL) *strchr(mem, '[') = '\0'; if (strchr(mem, '.') != NULL) *strchr(mem, '.') = '_'; *sec++ = '\0'; @@ -56,79 +58,73 @@ int main(int argc, char *argv[]) { "void %s(GPR const rt, GPR const ra) {" " emit_%s(0x%08x, rt, ra, R0, false, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %sC(GPR const rt, GPR const ra) {" " emit_%s(0x%08x, rt, ra, R0, true, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %s_(GPR const rt, GPR const ra) {" " emit_%s(0x%08x, rt, ra, R0, false, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %sC_(GPR const rt, GPR const ra) {" " emit_%s(0x%08x, rt, ra, R0, true, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } else { - if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) - printf("//"); printf( "void %s(GPR const rt, GPR const ra, GPR const rb) {" " emit_%s(0x%08x, rt, ra, rb, false, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( - "void %sC(GPR const rt, GPR const ra, GPR const rb) {" + "void %sO(GPR const rt, GPR const ra, GPR const rb) {" " emit_%s(0x%08x, rt, ra, rb, true, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); - if (strcmp(mem, "ADDC") == 0 || strcmp(mem, "SUBFC") == 0) - printf("//"); + , mem, form, OP_EXT); printf( "void %s_(GPR const rt, GPR const ra, GPR const rb) {" " emit_%s(0x%08x, rt, ra, rb, false, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( - "void %sC_(GPR const rt, GPR const ra, GPR const rb) {" + "void %sO_(GPR const rt, GPR const ra, GPR const rb) {" " emit_%s(0x%08x, rt, ra, rb, true, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } } else if (!strcmp(form, "X")) { - if (!strcmp(mem, "CMPL") - || !strcmp(mem, "CMP")) { + if (!strcmp(mem, "CMPL") || !strcmp(mem, "CMP")) { printf( "void %s(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, ra, GPR{(bf << 2) | l}, rb, false); " + " emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, rb, false); " "}\n" - , mem, form, i_opcode << 26); - } else if (!strcmp(mem, "CNTLZD") || !strcmp(mem, "CNTLZW") - || !strcmp(mem, "EXTSB") || !strcmp(mem, "EXTSH") || !strcmp(mem, "EXTSW")) { + , mem, form, OP_EXT); + } else if (!strcmp(mem, "CNTLZD") || !strcmp(mem, "CNTLZW") || !strcmp(mem, "EXTSB") || !strcmp(mem, "EXTSH") || !strcmp(mem, "EXTSW")) { printf( "void %s(GPR const rt, GPR const ra) {" - " emit_%s(0x%08x, rt, ra, R0, false); " + " emit_%s(0x%08x, ra, rt, R0, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %s_(GPR const rt, GPR const ra) {" - " emit_%s(0x%08x, rt, ra, R0, true); " + " emit_%s(0x%08x, ra, rt, R0, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } else { printf( "void %s(GPR const rt, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, rt, ra, rb, false); " + " emit_%s(0x%08x, ra, rt, rb, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %s_(GPR const rt, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, rt, ra, rb, true); " + " emit_%s(0x%08x, ra, rt, rb, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } } else if (!strcmp(form, "I")) { printf( @@ -156,11 +152,18 @@ int main(int argc, char *argv[]) { if (!strcmp(mem, "BC")) mem[1] = '\0'; } } else if (!strcmp(form, "D")) { - if (!strcmp(mem, "CMPLI") - || !strcmp(mem, "CMPI")) { + if (!strcmp(mem, "CMPLI") || !strcmp(mem, "CMPI")) { printf( "void %s(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) {" - " emit_%s(0x%08x, ra, GPR{(bf << 2) | l}, d); " + " emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, d); " + "}\n" + , mem, form, i_opcode << 26); + } else if (!strcmp(mem, "ANDIS_") || !strcmp(mem, "ANDI_") + || !strcmp(mem, "ORI") || !strcmp(mem, "ORIS") + || !strcmp(mem, "XORI") || !strcmp(mem, "XORIS")) { + printf( + "void %s(GPR const rt, GPR const ra, uint32_t d) {" + " emit_%s(0x%08x, ra, rt, d); " "}\n" , mem, form, i_opcode << 26); } else { @@ -181,121 +184,145 @@ int main(int argc, char *argv[]) { "void %s(GPR const rt, GPR const ra, uint32_t d) {" " emit_%s(0x%08x, rt, ra, d); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } else if (!strcmp(form, "XS")) { printf( "void %s(GPR const rt, GPR const ra, uint32_t sh) {" " emit_%s(0x%08x, rt, ra, sh, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %s_(GPR const rt, GPR const ra, uint32_t sh) {" " emit_%s(0x%08x, rt, ra, sh, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } else if (!strcmp(form, "XL")) { - if (mem[0] == 'B') { + if (!strcmp(mem, "BCLR")) { printf( "void %s(GPR const bt, CPR const ba, GPR const bb) {" " emit_%s(0x%08x, bt.index, ba.index, bb.index, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %sL(GPR const bt, CPR const ba, GPR const bb) {" " emit_%s(0x%08x, bt.index, ba.index, bb.index, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); + if (!strcmp(mem, "BCLR")) mem[1] = '\0'; + for (int i = 1; i < 12; ++i) { + printf( + "void %s%sLR(CPR const cr) {" + " emit_%s(0x%08x, %i, cr.index + %i, 0, false); " + "}\n" + , mem, infos[i].s, form, OP_EXT, infos[i].p, infos[i].o - 1); + printf( + "void %s%sLRL(CPR const cr) {" + " emit_%s(0x%08x, %i, cr.index + %i, 0, true); " + "}\n" + , mem, infos[i].s, form, OP_EXT, infos[i].p, infos[i].o - 1); + } + } else if (mem[0] == 'B') { + printf( + "void %s(GPR const bt, CPR const ba, GPR const bb) {" + " emit_%s(0x%08x, bt.index, ba.index, bb.index, false); " + "}\n" + , mem, form, OP_EXT); + printf( + "void %sL(GPR const bt, CPR const ba, GPR const bb) {" + " emit_%s(0x%08x, bt.index, ba.index, bb.index, true); " + "}\n" + , mem, form, OP_EXT); printf( "void %s(GPR const bt, Cond const ba, GPR const bb) {" " emit_%s(0x%08x, bt.index, cond2offset(ba), bb.index, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %sL(GPR const bt, Cond const ba, GPR const bb) {" " emit_%s(0x%08x, bt.index, cond2offset(ba), bb.index, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } else { printf( "void %s(CPR const bt, CPR const ba, CPR const bb) {" " emit_%s(0x%08x, bt.index, ba.index, bb.index, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %sL(CPR const bt, CPR const ba, CPR const bb) {" " emit_%s(0x%08x, bt.index, ba.index, bb.index, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } } else if (!strcmp(form, "M")) { if (!strcmp(mem, "RLWNM")) { printf( "void %s(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) {" - " emit_%s(0x%08x, rs, ra, rb.index, mb, me, false); " + " emit_%s(0x%08x, ra, rs, rb.index, mb, me, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %s_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) {" - " emit_%s(0x%08x, rs, ra, rb.index, mb, me, true); " + " emit_%s(0x%08x, ra, rs, rb.index, mb, me, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } else { printf( "void %s(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" - " emit_%s(0x%08x, rs, ra, sh, mb, me, false); " + " emit_%s(0x%08x, ra, rs, sh, mb, me, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %s_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) {" - " emit_%s(0x%08x, rs, ra, sh, mb, me, true); " + " emit_%s(0x%08x, ra, rs, sh, mb, me, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } } else if (!strcmp(form, "MD")) { printf( "void %s(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) {" - " emit_%s(0x%08x, rs, ra, mb, sh, false); " + " emit_%s(0x%08x, ra, rs, mb, sh, false); " "}\n" , mem, form, (i_opcode << 26) | (i_extopc << 2)); printf( "void %s_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) {" - " emit_%s(0x%08x, rs, ra, mb, sh, true); " + " emit_%s(0x%08x, ra, rs, mb, sh, true); " "}\n" , mem, form, (i_opcode << 26) | (i_extopc << 2)); } else if (!strcmp(form, "MDS")) { printf( "void %s(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) {" - " emit_%s(0x%08x, rs, ra, rb, mb, false); " + " emit_%s(0x%08x, ra, rs, rb, mb, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %s_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) {" - " emit_%s(0x%08x, rs, ra, rb, mb, true); " + " emit_%s(0x%08x, ra, rs, rb, mb, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } else if (!strcmp(form, "A")) { printf( "void %s(FPR const frt, FPR const fra, FPR const frb, FPR const frc) {" " emit_%s(0x%08x, frt, fra, frb, frc, false); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); printf( "void %s_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) {" " emit_%s(0x%08x, frt, fra, frb, frc, true); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } else if (!strcmp(form, "XFX")) { printf( "void %s(GPR const rt, uint32_t spr) {" " emit_%s(0x%08x, rt, spr); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } else { printf( "void %s() {" " emit_%s(0x%08x); " "}\n" - , mem, form, (i_opcode << 26) | (i_extopc << 1)); + , mem, form, OP_EXT); } } } diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 3e2c1268a8..b00be04623 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -196,13 +196,12 @@ struct Context { } void emit_D(uint32_t op, GPR const rt, GPR const ra, uint32_t d) { base[offset++] = (op | - (op == 0x74000000 - ? (bitExt(ra.index, 6, 5) | bitExt(rt.index, 11, 5)) - : (bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5))) + bitExt(rt.index, 6, 5) + | bitExt(ra.index, 11, 5) | (d & 0xffff) ); } - void emit_X(uint32_t op, GPR const ra, GPR const rt, GPR const rb, bool rc) { + void emit_X(uint32_t op, GPR const rt, GPR const ra, GPR const rb, bool rc) { base[offset++] = (op | bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5) @@ -261,8 +260,8 @@ struct Context { void emit_M(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me, bool rc) { assert(sh <= 0x3f && mb <= 0x3f); base[offset++] = (op | - bitExt(ra.index, 6, 5) - | bitExt(rs.index, 11, 5) + bitExt(rs.index, 6, 5) + | bitExt(ra.index, 11, 5) | ((sh & 0x1f) << 11) | ((mb & 0x1f) << 6) | ((me & 0x1f) << 1) @@ -272,8 +271,8 @@ struct Context { void emit_MD(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) { assert(mb <= 0x3f); base[offset++] = (op | - bitExt(ra.index, 6, 5) - | bitExt(rs.index, 11, 5) + bitExt(rs.index, 6, 5) + | bitExt(ra.index, 11, 5) | bitExt(rb.index, 16, 5) | ((mb & 0x1f) << 6) | (mb & 0x20) | bitExt(rc, 31, 1) @@ -282,8 +281,8 @@ struct Context { void emit_MD(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, bool rc) { assert(sh <= 0x3f && mb <= 0x3f); base[offset++] = (op | - bitExt(ra.index, 6, 5) - | bitExt(rs.index, 11, 5) + bitExt(rs.index, 6, 5) + | bitExt(ra.index, 11, 5) | ((mb & 0x1f) << 6) | (mb & 0x20) | ((sh & 0x1f) << 11) | ((sh >> 4) & 0x02) | bitExt(rc, 31, 1) @@ -291,8 +290,8 @@ struct Context { } void emit_MDS(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) { base[offset++] = (op | - bitExt(ra.index, 6, 5) - | bitExt(rs.index, 11, 5) + bitExt(rs.index, 6, 5) + | bitExt(ra.index, 11, 5) | bitExt(rb.index, 16, 5) | ((mb & 0x1f) << 6) | (mb & 0x20) | bitExt(rc, 31, 1) diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index 9ef5d1dc1f..2fcc01ea64 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -24,12 +24,12 @@ void ADDZE(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000194, rt, r 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 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); } -void ANDC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, rt, ra, rb, true); } -void ANDI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x70000000, rt, ra, d); } -void ANDIS_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x74000000, rt, ra, d); } +void AND(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000038, ra, rt, rb, false); } +void AND_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000038, ra, rt, rb, true); } +void ANDC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, ra, rt, rb, false); } +void ANDC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, ra, rt, rb, true); } +void ANDI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x70000000, ra, rt, d); } +void ANDIS_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x74000000, ra, rt, d); } void B(Label const& i) { emit_reloc_I(0x48000000, i, false); } void BL(Label const& i) { emit_reloc_I(0x48000000, i, true); } void BC(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 0, cr.index + 0, i, false); } @@ -64,14 +64,14 @@ void BCLR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.ind void BCLRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, ba.index, bb.index, true); } void BCLR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, false); } void BCLRL(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, true); } -void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, ra, GPR{(bf << 2) | l}, rb, false); } +void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); } void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, ra, GPR{(bf << 2) | l}, d); } -void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, ra, GPR{(bf << 2) | l}, rb, false); } +void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); } void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, ra, GPR{(bf << 2) | l}, d); } -void CNTLZD(GPR const rt, GPR const ra) { emit_X(0x7c000074, rt, ra, R0, false); } -void CNTLZD_(GPR const rt, GPR const ra) { emit_X(0x7c000074, rt, ra, R0, true); } -void CNTLZW(GPR const rt, GPR const ra) { emit_X(0x7c000034, rt, ra, R0, false); } -void CNTLZW_(GPR const rt, GPR const ra) { emit_X(0x7c000034, rt, ra, R0, true); } +void CNTLZD(GPR const rt, GPR const ra) { emit_X(0x7c000074, ra, rt, R0, false); } +void CNTLZD_(GPR const rt, GPR const ra) { emit_X(0x7c000074, ra, rt, R0, true); } +void CNTLZW(GPR const rt, GPR const ra) { emit_X(0x7c000034, ra, rt, R0, false); } +void CNTLZW_(GPR const rt, GPR const ra) { emit_X(0x7c000034, ra, rt, R0, true); } void CRAND(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000202, bt.index, ba.index, bb.index, false); } void CRANDL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000202, bt.index, ba.index, bb.index, true); } void CRANDC(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000102, bt.index, ba.index, bb.index, false); } @@ -88,18 +88,18 @@ void CRORC(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000342, bt.in void CRORCL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000342, bt.index, ba.index, bb.index, true); } void CRXOR(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000182, bt.index, ba.index, bb.index, false); } void CRXORL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000182, bt.index, ba.index, bb.index, true); } -void DCBF(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ac, rt, ra, rb, false); } -void DCBF_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ac, rt, ra, rb, true); } -void DCBI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003ac, rt, ra, rb, false); } -void DCBI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003ac, rt, ra, rb, true); } -void DCBST(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006c, rt, ra, rb, false); } -void DCBST_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006c, rt, ra, rb, true); } -void DCBT(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022c, rt, ra, rb, false); } -void DCBT_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022c, rt, ra, rb, true); } -void DCBTST(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ec, rt, ra, rb, false); } -void DCBTST_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ec, rt, ra, rb, true); } -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 DCBF(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ac, ra, rt, rb, false); } +void DCBF_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ac, ra, rt, rb, true); } +void DCBI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003ac, ra, rt, rb, false); } +void DCBI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003ac, ra, rt, rb, true); } +void DCBST(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006c, ra, rt, rb, false); } +void DCBST_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006c, ra, rt, rb, true); } +void DCBT(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022c, ra, rt, rb, false); } +void DCBT_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022c, ra, rt, rb, true); } +void DCBTST(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ec, ra, rt, rb, false); } +void DCBTST_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ec, ra, rt, rb, true); } +void DCBZ(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ec, ra, rt, rb, false); } +void DCBZ_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ec, ra, rt, rb, true); } void DIVD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0003d2, rt, ra, rb, false, 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); } @@ -116,40 +116,40 @@ void DIVWU(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000396, rt, r 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 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); } -void ECOWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036c, rt, ra, rb, true); } -void EIEIO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, rt, ra, rb, false); } -void EIEIO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, rt, ra, rb, true); } -void EQV(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, rt, ra, rb, false); } -void EQV_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, rt, ra, rb, true); } -void EXTSB(GPR const rt, GPR const ra) { emit_X(0x7c000774, rt, ra, R0, false); } -void EXTSB_(GPR const rt, GPR const ra) { emit_X(0x7c000774, rt, ra, R0, true); } +void ECIWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00026c, ra, rt, rb, false); } +void ECIWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00026c, ra, rt, rb, true); } +void ECOWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036c, ra, rt, rb, false); } +void ECOWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036c, ra, rt, rb, true); } +void EIEIO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, ra, rt, rb, false); } +void EIEIO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0006ac, ra, rt, rb, true); } +void EQV(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, ra, rt, rb, false); } +void EQV_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000238, ra, rt, rb, true); } +void EXTSB(GPR const rt, GPR const ra) { emit_X(0x7c000774, ra, rt, R0, false); } +void EXTSB_(GPR const rt, GPR const ra) { emit_X(0x7c000774, ra, rt, R0, true); } void EXTSH(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, false, false); } void EXTSHC(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, true, false); } void EXTSH_(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, false, true); } void EXTSHC_(GPR const rt, GPR const ra) { emit_XO(0x7c000734, rt, ra, R0, true, true); } -void EXTSW(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, rt, ra, R0, false); } -void EXTSW_(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, rt, ra, R0, true); } -void FABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, rt, ra, rb, false); } -void FABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, rt, ra, rb, true); } +void EXTSW(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, ra, rt, R0, false); } +void EXTSW_(GPR const rt, GPR const ra) { emit_X(0x7c0007b4, ra, rt, R0, true); } +void FABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, ra, rt, rb, false); } +void FABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000210, ra, rt, rb, true); } void FADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002a, frt, fra, frb, frc, false); } void FADD_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002a, frt, fra, frb, frc, true); } void FADDS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00002a, frt, fra, frb, frc, false); } void FADDS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00002a, frt, fra, frb, frc, true); } -void FCFID(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00069c, rt, ra, rb, false); } -void FCFID_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00069c, rt, ra, rb, true); } -void FCMPO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000040, rt, ra, rb, false); } -void FCMPO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000040, rt, ra, rb, true); } +void FCFID(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00069c, ra, rt, rb, false); } +void FCFID_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00069c, ra, rt, rb, true); } +void FCMPO(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000040, ra, rt, rb, false); } +void FCMPO_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000040, ra, rt, rb, true); } void FCMPU(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc000000, bt.index, ba.index, bb.index, false); } void FCMPUL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc000000, bt.index, ba.index, bb.index, true); } -void FCTID(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065c, rt, ra, rb, false); } -void FCTID_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065c, rt, ra, rb, true); } -void FCTIDZ(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065e, rt, ra, rb, false); } -void FCTIDZ_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065e, rt, ra, rb, true); } -void FCTIW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00001c, rt, ra, rb, false); } -void FCTIW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00001c, rt, ra, rb, true); } +void FCTID(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065c, ra, rt, rb, false); } +void FCTID_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065c, ra, rt, rb, true); } +void FCTIDZ(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065e, ra, rt, rb, false); } +void FCTIDZ_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00065e, ra, rt, rb, true); } +void FCTIW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00001c, ra, rt, rb, false); } +void FCTIW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00001c, ra, rt, rb, true); } void FCTIWZ(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc00001e, bt.index, ba.index, bb.index, false); } void FCTIWZL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0xfc00001e, bt.index, ba.index, bb.index, true); } void FDIV(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000024, frt, fra, frb, frc, false); } @@ -160,8 +160,8 @@ void FMADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A( void FMADD_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003a, frt, fra, frb, frc, true); } void FMADDS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003a, frt, fra, frb, frc, false); } void FMADDS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003a, frt, fra, frb, frc, true); } -void FMR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000090, rt, ra, rb, false); } -void FMR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000090, rt, ra, rb, true); } +void FMR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000090, ra, rt, rb, false); } +void FMR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000090, ra, rt, rb, true); } void FMSUB(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000038, frt, fra, frb, frc, false); } void FMSUB_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000038, frt, fra, frb, frc, true); } void FMSUBS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000038, frt, fra, frb, frc, false); } @@ -170,10 +170,10 @@ void FMUL(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0 void FMUL_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000032, frt, fra, frb, frc, true); } void FMULS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000032, frt, fra, frb, frc, false); } void FMULS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000032, frt, fra, frb, frc, true); } -void FNABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000110, rt, ra, rb, false); } -void FNABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000110, rt, ra, rb, true); } -void FNEG(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000050, rt, ra, rb, false); } -void FNEG_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000050, rt, ra, rb, true); } +void FNABS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000110, ra, rt, rb, false); } +void FNABS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000110, ra, rt, rb, true); } +void FNEG(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000050, ra, rt, rb, false); } +void FNEG_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000050, ra, rt, rb, true); } void FNMADD(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003e, frt, fra, frb, frc, false); } void FNMADD_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00003e, frt, fra, frb, frc, true); } void FNMADDS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003e, frt, fra, frb, frc, false); } @@ -184,8 +184,8 @@ void FNMSUBS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_ void FNMSUBS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec00003c, frt, fra, frb, frc, true); } void FRES(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000030, frt, fra, frb, frc, false); } void FRES_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000030, frt, fra, frb, frc, true); } -void FRSP(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000018, rt, ra, rb, false); } -void FRSP_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000018, rt, ra, rb, true); } +void FRSP(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000018, ra, rt, rb, false); } +void FRSP_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000018, ra, rt, rb, true); } void FRSQRTE(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000034, frt, fra, frb, frc, false); } void FRSQRTE_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000034, frt, fra, frb, frc, true); } void FSEL(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc00002e, frt, fra, frb, frc, false); } @@ -194,104 +194,104 @@ void FSUB(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0 void FSUB_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xfc000028, frt, fra, frb, frc, true); } void FSUBS(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000028, frt, fra, frb, frc, false); } void FSUBS_(FPR const frt, FPR const fra, FPR const frb, FPR const frc) { emit_A(0xec000028, frt, fra, frb, frc, true); } -void ICBI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ac, rt, ra, rb, false); } -void ICBI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ac, rt, ra, rb, true); } -void ISYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c00012c, rt, ra, rb, false); } -void ISYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c00012c, rt, ra, rb, true); } +void ICBI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ac, ra, rt, rb, false); } +void ICBI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ac, ra, rt, rb, true); } +void ISYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c00012c, ra, rt, rb, false); } +void ISYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c00012c, ra, rt, rb, true); } void LBZ(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x88000000, rt, ra, d); } void LBZU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x8c000000, rt, ra, d); } -void LBZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ee, rt, ra, rb, false); } -void LBZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ee, rt, ra, rb, true); } -void LBZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, rt, ra, rb, false); } -void LBZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, rt, ra, rb, true); } +void LBZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ee, ra, rt, rb, false); } +void LBZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ee, ra, rt, rb, true); } +void LBZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, ra, rt, rb, false); } +void LBZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, ra, rt, rb, true); } void LD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000000, rt, ra, d); } -void LDARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, rt, ra, rb, false); } -void LDARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, rt, ra, rb, true); } +void LDARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, ra, rt, rb, false); } +void LDARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, ra, rt, rb, true); } void LDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000002, rt, ra, d); } -void LDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, rt, ra, rb, false); } -void LDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, rt, ra, rb, true); } -void LDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002a, rt, ra, rb, false); } -void LDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002a, rt, ra, rb, true); } +void LDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, ra, rt, rb, false); } +void LDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, ra, rt, rb, true); } +void LDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002a, ra, rt, rb, false); } +void LDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002a, ra, rt, rb, true); } void LFD(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xc8000000, rt, ra, d); } void LFDU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xcc000000, rt, ra, d); } -void LFDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ee, rt, ra, rb, false); } -void LFDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ee, rt, ra, rb, true); } -void LFDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ae, rt, ra, rb, false); } -void LFDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ae, rt, ra, rb, true); } +void LFDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ee, ra, rt, rb, false); } +void LFDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ee, ra, rt, rb, true); } +void LFDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ae, ra, rt, rb, false); } +void LFDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ae, ra, rt, rb, true); } void LFS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xc0000000, rt, ra, d); } void LFSU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xc4000000, rt, ra, d); } -void LFSUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046e, rt, ra, rb, false); } -void LFSUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046e, rt, ra, rb, true); } -void LFSX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042e, rt, ra, rb, false); } -void LFSX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042e, rt, ra, rb, true); } +void LFSUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046e, ra, rt, rb, false); } +void LFSUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046e, ra, rt, rb, true); } +void LFSX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042e, ra, rt, rb, false); } +void LFSX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042e, ra, rt, rb, true); } void LHA(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xa8000000, rt, ra, d); } void LHAU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xac000000, rt, ra, d); } -void LHAUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ee, rt, ra, rb, false); } -void LHAUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ee, rt, ra, rb, true); } -void LHAX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ae, rt, ra, rb, false); } -void LHAX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ae, rt, ra, rb, true); } -void LHBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00062c, rt, ra, rb, false); } -void LHBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00062c, rt, ra, rb, true); } +void LHAUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ee, ra, rt, rb, false); } +void LHAUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ee, ra, rt, rb, true); } +void LHAX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ae, ra, rt, rb, false); } +void LHAX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ae, ra, rt, rb, true); } +void LHBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00062c, ra, rt, rb, false); } +void LHBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00062c, ra, rt, rb, true); } void LHZ(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xa0000000, rt, ra, d); } void LHZU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xa4000000, rt, ra, d); } -void LHZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000296, rt, ra, rb, false); } -void LHZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000296, rt, ra, rb, true); } -void LHZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022e, rt, ra, rb, false); } -void LHZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022e, rt, ra, rb, true); } +void LHZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000296, ra, rt, rb, false); } +void LHZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000296, ra, rt, rb, true); } +void LHZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022e, ra, rt, rb, false); } +void LHZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00022e, ra, rt, rb, true); } void LMW(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xb8000000, rt, ra, d); } -void LSWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, rt, ra, rb, false); } -void LSWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, rt, ra, rb, true); } -void LSWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, rt, ra, rb, false); } -void LSWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, rt, ra, rb, true); } +void LSWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, ra, rt, rb, false); } +void LSWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, ra, rt, rb, true); } +void LSWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, ra, rt, rb, false); } +void LSWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, ra, rt, rb, true); } void LWA(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000004, rt, ra, d); } -void LWARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, rt, ra, rb, false); } -void LWARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, rt, ra, rb, true); } -void LWAUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ea, rt, ra, rb, false); } -void LWAUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ea, rt, ra, rb, true); } -void LWAX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002aa, rt, ra, rb, false); } -void LWAX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002aa, rt, ra, rb, true); } -void LWBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042c, rt, ra, rb, false); } -void LWBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042c, rt, ra, rb, true); } +void LWARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, ra, rt, rb, false); } +void LWARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, ra, rt, rb, true); } +void LWAUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ea, ra, rt, rb, false); } +void LWAUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ea, ra, rt, rb, true); } +void LWAX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002aa, ra, rt, rb, false); } +void LWAX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002aa, ra, rt, rb, true); } +void LWBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042c, ra, rt, rb, false); } +void LWBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042c, ra, rt, rb, true); } void LWZ(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x80000000, rt, ra, d); } void LWZU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x84000000, rt, ra, d); } -void LWZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006e, rt, ra, rb, false); } -void LWZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006e, rt, ra, rb, true); } -void LWZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002e, rt, ra, rb, false); } -void LWZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002e, rt, ra, rb, true); } +void LWZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006e, ra, rt, rb, false); } +void LWZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006e, ra, rt, rb, true); } +void LWZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002e, ra, rt, rb, false); } +void LWZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002e, ra, rt, rb, true); } void MCRF(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000000, bt.index, ba.index, bb.index, false); } void MCRFL(CPR const bt, CPR const ba, CPR const bb) { emit_XL(0x4c000000, bt.index, ba.index, bb.index, true); } -void MCRFS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000080, rt, ra, rb, false); } -void MCRFS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000080, rt, ra, rb, true); } -void MCRXR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000400, rt, ra, rb, false); } -void MCRXR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000400, rt, ra, rb, true); } -void MFCR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000026, rt, ra, rb, false); } -void MFCR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000026, rt, ra, rb, true); } -void MFFS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00048e, rt, ra, rb, false); } -void MFFS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00048e, rt, ra, rb, true); } -void MFMSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a6, rt, ra, rb, false); } -void MFMSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a6, rt, ra, rb, true); } -void MFSPR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002a6, rt, ra, rb, false); } -void MFSPR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002a6, rt, ra, rb, true); } -void MFSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004a6, rt, ra, rb, false); } -void MFSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004a6, rt, ra, rb, true); } -void MFSRIN(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000526, rt, ra, rb, false); } -void MFSRIN_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000526, rt, ra, rb, true); } +void MCRFS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000080, ra, rt, rb, false); } +void MCRFS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc000080, ra, rt, rb, true); } +void MCRXR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000400, ra, rt, rb, false); } +void MCRXR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000400, ra, rt, rb, true); } +void MFCR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000026, ra, rt, rb, false); } +void MFCR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000026, ra, rt, rb, true); } +void MFFS(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00048e, ra, rt, rb, false); } +void MFFS_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00048e, ra, rt, rb, true); } +void MFMSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a6, ra, rt, rb, false); } +void MFMSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a6, ra, rt, rb, true); } +void MFSPR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002a6, ra, rt, rb, false); } +void MFSPR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002a6, ra, rt, rb, true); } +void MFSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004a6, ra, rt, rb, false); } +void MFSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004a6, ra, rt, rb, true); } +void MFSRIN(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000526, ra, rt, rb, false); } +void MFSRIN_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000526, ra, rt, rb, true); } void MTCRF(GPR const rt, uint32_t spr) { emit_XFX(0x7c000120, rt, spr); } -void MTFSB0(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00008c, rt, ra, rb, false); } -void MTFSB0_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00008c, rt, ra, rb, true); } -void MTFSB1(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00004c, rt, ra, rb, false); } -void MTFSB1_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00004c, rt, ra, rb, true); } +void MTFSB0(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00008c, ra, rt, rb, false); } +void MTFSB0_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00008c, ra, rt, rb, true); } +void MTFSB1(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00004c, ra, rt, rb, false); } +void MTFSB1_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00004c, ra, rt, rb, true); } void MTFSF() { emit_XFL(0xfc00058e); } -void MTFSFI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00010c, rt, ra, rb, false); } -void MTFSFI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00010c, rt, ra, rb, true); } -void MTMSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000124, rt, ra, rb, false); } -void MTMSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000124, rt, ra, rb, true); } -void MTSPR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003a6, rt, ra, rb, false); } -void MTSPR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003a6, rt, ra, rb, true); } -void MTSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001a4, rt, ra, rb, false); } -void MTSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001a4, rt, ra, rb, true); } -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 MTFSFI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00010c, ra, rt, rb, false); } +void MTFSFI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0xfc00010c, ra, rt, rb, true); } +void MTMSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000124, ra, rt, rb, false); } +void MTMSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000124, ra, rt, rb, true); } +void MTSPR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003a6, ra, rt, rb, false); } +void MTSPR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003a6, ra, rt, rb, true); } +void MTSR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001a4, ra, rt, rb, false); } +void MTSR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001a4, ra, rt, rb, true); } +void MTSRIN(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001e4, ra, rt, rb, false); } +void MTSRIN_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001e4, ra, rt, rb, true); } void MULHD(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000092, rt, ra, rb, false, 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); } @@ -317,114 +317,114 @@ void MULLW(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0001d6, rt, r 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 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 NAND(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003b8, ra, rt, rb, false); } +void NAND_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003b8, ra, rt, rb, true); } void NEG(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c0000d0, rt, ra, rb, false, 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 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); } -void OR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000378, rt, ra, rb, true); } -void ORC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000338, rt, ra, rb, false); } -void ORC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000338, rt, ra, rb, true); } -void ORI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x60000000, rt, ra, d); } -void ORIS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x64000000, rt, ra, d); } -void RFI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c000064, rt, ra, rb, false); } -void RFI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c000064, rt, ra, rb, true); } -void RLDCL(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000010, rs, ra, rb, mb, false); } -void RLDCL_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000010, rs, ra, rb, mb, true); } -void RLDCR(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000012, rs, ra, rb, mb, false); } -void RLDCR_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000012, rs, ra, rb, mb, true); } -void RLDIC(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000008, rs, ra, mb, sh, false); } -void RLDIC_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000008, rs, ra, mb, sh, true); } -void RLDICL(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000000, rs, ra, mb, sh, false); } -void RLDICL_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000000, rs, ra, mb, sh, true); } -void RLDICR(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000004, rs, ra, mb, sh, false); } -void RLDICR_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000004, rs, ra, mb, sh, true); } -void RLDIMI(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x7800000c, rs, ra, mb, sh, false); } -void RLDIMI_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x7800000c, rs, ra, mb, sh, true); } -void RLWIMI(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, rs, ra, sh, mb, me, false); } -void RLWIMI_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, rs, ra, sh, mb, me, true); } -void RLWINM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, rs, ra, sh, mb, me, false); } -void RLWINM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, rs, ra, sh, mb, me, true); } -void RLWNM(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, rb.index, mb, me, false); } -void RLWNM_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, rs, ra, rb.index, mb, me, true); } +void NOR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000f8, ra, rt, rb, false); } +void NOR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000f8, ra, rt, rb, true); } +void OR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000378, ra, rt, rb, false); } +void OR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000378, ra, rt, rb, true); } +void ORC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000338, ra, rt, rb, false); } +void ORC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000338, ra, rt, rb, true); } +void ORI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x60000000, ra, rt, d); } +void ORIS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x64000000, ra, rt, d); } +void RFI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c000064, ra, rt, rb, false); } +void RFI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x4c000064, ra, rt, rb, true); } +void RLDCL(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000010, ra, rs, rb, mb, false); } +void RLDCL_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000010, ra, rs, rb, mb, true); } +void RLDCR(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000012, ra, rs, rb, mb, false); } +void RLDCR_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb) { emit_MDS(0x78000012, ra, rs, rb, mb, true); } +void RLDIC(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000008, ra, rs, mb, sh, false); } +void RLDIC_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000008, ra, rs, mb, sh, true); } +void RLDICL(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000000, ra, rs, mb, sh, false); } +void RLDICL_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000000, ra, rs, mb, sh, true); } +void RLDICR(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000004, ra, rs, mb, sh, false); } +void RLDICR_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x78000004, ra, rs, mb, sh, true); } +void RLDIMI(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x7800000c, ra, rs, mb, sh, false); } +void RLDIMI_(GPR const rs, GPR const ra, uint32_t mb, uint32_t sh) { emit_MD(0x7800000c, ra, rs, mb, sh, true); } +void RLWIMI(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, ra, rs, sh, mb, me, false); } +void RLWIMI_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x50000000, ra, rs, sh, mb, me, true); } +void RLWINM(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, ra, rs, sh, mb, me, false); } +void RLWINM_(GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me = 0) { emit_M(0x54000000, ra, rs, sh, mb, me, true); } +void RLWNM(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, ra, rs, rb.index, mb, me, false); } +void RLWNM_(GPR const rs, GPR const ra, GPR const rb, uint32_t mb, uint32_t me = 0) { emit_M(0x5c000000, ra, rs, rb.index, mb, me, true); } void SC(uint32_t lev) { emit_SC(0x44000000, lev); } void SI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x30000000, rt, ra, d); } void SI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x34000000, rt, ra, d); } -void SLBIA(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003e4, rt, ra, rb, false); } -void SLBIA_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003e4, rt, ra, rb, true); } -void SLBIE(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000364, rt, ra, rb, false); } -void SLBIE_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000364, rt, ra, rb, true); } -void SLD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000036, rt, ra, rb, false); } -void SLD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000036, rt, ra, rb, true); } -void SLW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, rt, ra, rb, false); } -void SLW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, rt, ra, rb, true); } -void SRAD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, rt, ra, rb, false); } -void SRAD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, rt, ra, rb, true); } +void SLBIA(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003e4, ra, rt, rb, false); } +void SLBIA_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0003e4, ra, rt, rb, true); } +void SLBIE(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000364, ra, rt, rb, false); } +void SLBIE_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000364, ra, rt, rb, true); } +void SLD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000036, ra, rt, rb, false); } +void SLD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000036, ra, rt, rb, true); } +void SLW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, ra, rt, rb, false); } +void SLW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, ra, rt, rb, true); } +void SRAD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, ra, rt, rb, false); } +void SRAD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, ra, rt, rb, true); } void SRADI(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c00033a, rt, ra, sh, false); } void SRADI_(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c00033a, rt, ra, sh, true); } -void SRD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, rt, ra, rb, false); } -void SRD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, rt, ra, rb, true); } -void SRAW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000630, rt, ra, rb, false); } -void SRAW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000630, rt, ra, rb, true); } -void SRAWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000670, rt, ra, rb, false); } -void SRAWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000670, rt, ra, rb, true); } -void SRW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000430, rt, ra, rb, false); } -void SRW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000430, rt, ra, rb, true); } +void SRD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, ra, rt, rb, false); } +void SRD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, ra, rt, rb, true); } +void SRAW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000630, ra, rt, rb, false); } +void SRAW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000630, ra, rt, rb, true); } +void SRAWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000670, ra, rt, rb, false); } +void SRAWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000670, ra, rt, rb, true); } +void SRW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000430, ra, rt, rb, false); } +void SRW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000430, ra, rt, rb, true); } void STB(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x98000000, rt, ra, d); } void STBU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x9c000000, rt, ra, d); } -void STBUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ee, rt, ra, rb, false); } -void STBUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ee, rt, ra, rb, true); } -void STBX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, rt, ra, rb, false); } -void STBX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, rt, ra, rb, true); } +void STBUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ee, ra, rt, rb, false); } +void STBUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ee, ra, rt, rb, true); } +void STBX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, ra, rt, rb, false); } +void STBX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, ra, rt, rb, true); } void STD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000000, rt, ra, d); } -void STDCX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, rt, ra, rb, false); } -void STDCX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, rt, ra, rb, true); } +void STDCX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, ra, rt, rb, false); } +void STDCX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, ra, rt, rb, true); } void STDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000002, rt, ra, d); } -void STDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, rt, ra, rb, false); } -void STDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, rt, ra, rb, true); } -void STDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012a, rt, ra, rb, false); } -void STDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012a, rt, ra, rb, true); } +void STDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, ra, rt, rb, false); } +void STDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, ra, rt, rb, true); } +void STDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012a, ra, rt, rb, false); } +void STDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012a, ra, rt, rb, true); } void STFD(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xd8000000, rt, ra, d); } void STFDU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xdc000000, rt, ra, d); } -void STFDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ee, rt, ra, rb, false); } -void STFDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ee, rt, ra, rb, true); } -void STFDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ae, rt, ra, rb, false); } -void STFDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ae, rt, ra, rb, true); } -void STFIWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ae, rt, ra, rb, false); } -void STFIWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ae, rt, ra, rb, true); } +void STFDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ee, ra, rt, rb, false); } +void STFDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ee, ra, rt, rb, true); } +void STFDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ae, ra, rt, rb, false); } +void STFDX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005ae, ra, rt, rb, true); } +void STFIWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ae, ra, rt, rb, false); } +void STFIWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0007ae, ra, rt, rb, true); } void STFS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xd0000000, rt, ra, d); } void STFSU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xd4000000, rt, ra, d); } -void STFSUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00056e, rt, ra, rb, false); } -void STFSUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00056e, rt, ra, rb, true); } -void STFSX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052e, rt, ra, rb, false); } -void STFSX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052e, rt, ra, rb, true); } +void STFSUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00056e, ra, rt, rb, false); } +void STFSUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00056e, ra, rt, rb, true); } +void STFSX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052e, ra, rt, rb, false); } +void STFSX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052e, ra, rt, rb, true); } void STH(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xb0000000, rt, ra, d); } -void STHBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00072c, rt, ra, rb, false); } -void STHBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00072c, rt, ra, rb, true); } +void STHBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00072c, ra, rt, rb, false); } +void STHBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00072c, ra, rt, rb, true); } void STHU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xb4000000, rt, ra, d); } -void STHUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036e, rt, ra, rb, false); } -void STHUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036e, rt, ra, rb, true); } -void STHX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00032e, rt, ra, rb, false); } -void STHX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00032e, rt, ra, rb, true); } +void STHUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036e, ra, rt, rb, false); } +void STHUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00036e, ra, rt, rb, true); } +void STHX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00032e, ra, rt, rb, false); } +void STHX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00032e, ra, rt, rb, true); } void STMW(GPR const rt, GPR const ra, uint32_t d) { emit_D(0xbc000000, rt, ra, d); } -void STSWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005aa, rt, ra, rb, false); } -void STSWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005aa, rt, ra, rb, true); } -void STSWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052a, rt, ra, rb, false); } -void STSWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052a, rt, ra, rb, true); } +void STSWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005aa, ra, rt, rb, false); } +void STSWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0005aa, ra, rt, rb, true); } +void STSWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052a, ra, rt, rb, false); } +void STSWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052a, ra, rt, rb, true); } void STW(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x90000000, rt, ra, d); } -void STWBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052c, rt, ra, rb, false); } -void STWBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052c, rt, ra, rb, true); } -void STWCX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012c, rt, ra, rb, false); } -void STWCX__(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012c, rt, ra, rb, true); } +void STWBRX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052c, ra, rt, rb, false); } +void STWBRX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00052c, ra, rt, rb, true); } +void STWCX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012c, ra, rt, rb, false); } +void STWCX__(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012c, ra, rt, rb, true); } void STWU(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x94000000, rt, ra, d); } -void STWUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016e, rt, ra, rb, false); } -void STWUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016e, rt, ra, rb, true); } -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 STWUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016e, ra, rt, rb, false); } +void STWUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016e, ra, rt, rb, true); } +void STWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012e, ra, rt, rb, false); } +void STWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012e, ra, rt, rb, true); } void SUBF(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000050, rt, ra, rb, false, 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); } @@ -446,19 +446,19 @@ void SUBFZE(GPR const rt, GPR const ra, GPR const rb) { emit_XO(0x7c000190, rt, 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 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); } -void TD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000088, rt, ra, rb, true); } +void SYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ac, ra, rt, rb, false); } +void SYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004ac, ra, rt, rb, true); } +void TD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000088, ra, rt, rb, false); } +void TD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000088, ra, rt, rb, true); } void TDI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x08000000, rt, ra, d); } -void TLBIE(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000264, rt, ra, rb, false); } -void TLBIE_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000264, rt, ra, rb, true); } -void TLBSYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046c, rt, ra, rb, false); } -void TLBSYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046c, rt, ra, rb, true); } -void TW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000008, rt, ra, rb, false); } -void TW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000008, rt, ra, rb, true); } +void TLBIE(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000264, ra, rt, rb, false); } +void TLBIE_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000264, ra, rt, rb, true); } +void TLBSYNC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046c, ra, rt, rb, false); } +void TLBSYNC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00046c, ra, rt, rb, true); } +void TW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000008, ra, rt, rb, false); } +void TW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000008, ra, rt, rb, true); } void TWI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x0c000000, rt, ra, d); } -void XOR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000278, rt, ra, rb, false); } -void XOR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000278, rt, ra, rb, true); } -void XORI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x68000000, rt, ra, d); } -void XORIS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x6c000000, rt, ra, d); } +void XOR(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000278, ra, rt, rb, false); } +void XOR_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000278, ra, rt, rb, true); } +void XORI(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x68000000, ra, rt, d); } +void XORIS(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x6c000000, ra, rt, d); } From 51224713b7800a0a0961ad4eae7bf089f3a0dc48 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 4 Nov 2025 23:38:36 +0000 Subject: [PATCH 24/49] more bclr fixes Signed-off-by: lizzie --- externals/powah/powah_gen_base.hpp | 30 +++++++++++--- externals/powah/tests.cpp | 63 ++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index 2fcc01ea64..6852da14f4 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -62,12 +62,32 @@ void BCCTR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000420, bt.i void BCCTRL(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, cond2offset(ba), bb.index, true); } void BCLR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, ba.index, bb.index, false); } void BCLRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, ba.index, bb.index, true); } -void BCLR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, false); } -void BCLRL(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, true); } +void BLTLR(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 0, 0, false); } +void BLTLRL(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 0, 0, true); } +void BLELR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 1, 0, false); } +void BLELRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 1, 0, true); } +void BNGLR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 1, 0, false); } +void BNGLRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 1, 0, true); } +void BEQLR(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 2, 0, false); } +void BEQLRL(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 2, 0, true); } +void BGELR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 0, 0, false); } +void BGELRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 0, 0, true); } +void BNLLR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 0, 0, false); } +void BNLLRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 0, 0, true); } +void BGTLR(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 1, 0, false); } +void BGTLRL(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 1, 0, true); } +void BNELR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 2, 0, false); } +void BNELRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 2, 0, true); } +void BSOLR(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 3, 0, false); } +void BSOLRL(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 3, 0, true); } +void BUNLR(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 3, 0, false); } +void BUNLRL(CPR const cr) { emit_XL(0x4c000020, 12, cr.index + 3, 0, true); } +void BNSLR(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 3, 0, false); } +void BNSLRL(CPR const cr) { emit_XL(0x4c000020, 4, cr.index + 3, 0, true); } void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); } -void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, ra, GPR{(bf << 2) | l}, d); } -void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); } -void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, ra, GPR{(bf << 2) | l}, d); } +void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, GPR{(bf << 2) | l}, ra, d); } +void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000040, GPR{(bf << 2) | l}, ra, rb, false); } +void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, GPR{(bf << 2) | l}, ra, d); } void CNTLZD(GPR const rt, GPR const ra) { emit_X(0x7c000074, ra, rt, R0, false); } void CNTLZD_(GPR const rt, GPR const ra) { emit_X(0x7c000074, ra, rt, R0, true); } void CNTLZW(GPR const rt, GPR const ra) { emit_X(0x7c000034, ra, rt, R0, false); } diff --git a/externals/powah/tests.cpp b/externals/powah/tests.cpp index c60ce0c724..65baedb47b 100644 --- a/externals/powah/tests.cpp +++ b/externals/powah/tests.cpp @@ -153,6 +153,69 @@ TEST_CASE("ppc64: branch-backwards", "[ppc64]") { REQUIRE(data[1] == EB32(0xfcffff4b)); } +TEST_CASE("ppc64: rlwimi madness", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + ctx.ROTLWI(powah::R10, powah::R3, 24); + ctx.SRDI(powah::R9, powah::R3, 32); + ctx.RLWIMI(powah::R10, powah::R3, 8, 8, 15); + ctx.RLWIMI(powah::R10, powah::R3, 8, 24, 31); + ctx.ROTLWI(powah::R3, powah::R9, 24); + ctx.RLWIMI(powah::R3, powah::R9, 8, 8, 15); + ctx.RLWIMI(powah::R3, powah::R9, 8, 24, 31); + ctx.RLDIMI(powah::R3, powah::R10, 32, 0); + REQUIRE(data[0] == EB32(0x3ec06a54)); + REQUIRE(data[1] == EB32(0x22006978)); + REQUIRE(data[2] == EB32(0x1e426a50)); + REQUIRE(data[3] == EB32(0x3e466a50)); + REQUIRE(data[4] == EB32(0x3ec02355)); + REQUIRE(data[5] == EB32(0x1e422351)); + REQUIRE(data[6] == EB32(0x3e462351)); + REQUIRE(data[7] == EB32(0x0e004379)); +} + +TEST_CASE("ppc64: functor-1", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + powah::Label l_4 = ctx.DefineLabel(); + powah::Label l_7 = ctx.DefineLabel(); + ctx.CMPLD(powah::CR0, powah::R3, powah::R4); + ctx.MR(powah::R9, powah::R3); + ctx.BGT(powah::CR0, l_7); + ctx.CMPLDI(powah::CR0, powah::R3, 3781); + ctx.LI(powah::R3, 1); + ctx.BGTLR(powah::CR0); + ctx.CMPLD(powah::CR0, powah::R9, powah::R5); + ctx.BLE(powah::CR0, l_4); + ctx.SUBF(powah::R5, powah::R9, powah::R5); + ctx.XOR(powah::R3, powah::R5, powah::R4); + ctx.BLR(); + ctx.LABEL(l_4); + ctx.ADD(powah::R5, powah::R4, powah::R5); + ctx.ADD(powah::R3, powah::R5, powah::R9); + ctx.BLR(); + ctx.LABEL(l_7); + ctx.ADD(powah::R3, powah::R4, powah::R5); + ctx.BLR(); + ctx.ApplyRelocs(); + REQUIRE(data[0] == EB32(0x4020237c)); + REQUIRE(data[1] == EB32(0x781b697c)); + REQUIRE(data[2] == EB32(0x30008141)); + REQUIRE(data[3] == EB32(0xc50e2328)); + REQUIRE(data[4] == EB32(0x01006038)); + REQUIRE(data[5] == EB32(0x2000814d)); + REQUIRE(data[6] == EB32(0x4028297c)); + REQUIRE(data[7] == EB32(0x10008140)); + REQUIRE(data[8] == EB32(0x5028a97c)); + REQUIRE(data[9] == EB32(0x7822a37c)); + REQUIRE(data[10] == EB32(0x2000804e)); + REQUIRE(data[11] == EB32(0x142aa47c)); + REQUIRE(data[12] == EB32(0x144a657c)); + REQUIRE(data[13] == EB32(0x2000804e)); + REQUIRE(data[14] == EB32(0x142a647c)); + REQUIRE(data[15] == EB32(0x2000804e)); +} + #if defined(ARCHITECTURE_ppc64) /* 0: d619637c mullw 3, 3, 3 From 39ee32a311a095470477ca8a8b43080f31d7d392 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 5 Nov 2025 00:46:29 +0000 Subject: [PATCH 25/49] fix xs stuffs Signed-off-by: lizzie --- externals/powah/data2code.c | 10 +++-- externals/powah/powah_emit.hpp | 8 ++-- externals/powah/powah_gen_base.hpp | 4 +- externals/powah/tests.cpp | 37 +++++++++++++++++++ .../ppc64/emit_ppc64_data_processing.cpp | 4 +- 5 files changed, 52 insertions(+), 11 deletions(-) diff --git a/externals/powah/data2code.c b/externals/powah/data2code.c index 13a6bdbb16..76f98c5e18 100644 --- a/externals/powah/data2code.c +++ b/externals/powah/data2code.c @@ -43,6 +43,7 @@ int main(int argc, char *argv[]) { }; #define OP_EXT ((i_opcode << 26) | (i_extopc << 1)) +#define OP_EXT_XS ((i_opcode << 26) | (i_extopc << 2)) if (strchr(mem, '[') != NULL) *strchr(mem, '[') = '\0'; if (strchr(mem, '.') != NULL) *strchr(mem, '.') = '_'; @@ -186,16 +187,17 @@ int main(int argc, char *argv[]) { "}\n" , mem, form, OP_EXT); } else if (!strcmp(form, "XS")) { + /* HUGE DIFFERENCE DO NOT REMOVE */ printf( "void %s(GPR const rt, GPR const ra, uint32_t sh) {" - " emit_%s(0x%08x, rt, ra, sh, false); " + " emit_%s(0x%08x, ra, rt, sh, false); " "}\n" - , mem, form, OP_EXT); + , mem, form, OP_EXT_XS); printf( "void %s_(GPR const rt, GPR const ra, uint32_t sh) {" - " emit_%s(0x%08x, rt, ra, sh, true); " + " emit_%s(0x%08x, ra, rt, sh, true); " "}\n" - , mem, form, OP_EXT); + , mem, form, OP_EXT_XS); } else if (!strcmp(form, "XL")) { if (!strcmp(mem, "BCLR")) { printf( diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index b00be04623..1aa11f53a2 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -211,10 +211,10 @@ struct Context { } void emit_XS(uint32_t op, GPR const rt, GPR const ra, uint32_t sh, bool rc) { base[offset++] = (op | - bitExt(rt.index, 6, 5) - | bitExt(ra.index, 11, 5) - | bitExt(sh, 16, 5) - | bitExt(sh >> 5, 30, 1) + ((rt.index & 0x1f) << 16) + | ((ra.index & 0x1f) << 21) + | ((sh & 0x1f) << 11) + | ((sh >> 4) & 0x02) | bitExt(rc, 31, 1) ); } diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index 6852da14f4..97b2410a09 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -384,8 +384,8 @@ void SLW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, ra, rt, void SLW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, ra, rt, rb, true); } void SRAD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, ra, rt, rb, false); } void SRAD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, ra, rt, rb, true); } -void SRADI(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c00033a, rt, ra, sh, false); } -void SRADI_(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c00033a, rt, ra, sh, true); } +void SRADI(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c000674, ra, rt, sh, false); } +void SRADI_(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c000674, ra, rt, sh, true); } void SRD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, ra, rt, rb, false); } void SRD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, ra, rt, rb, true); } void SRAW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000630, ra, rt, rb, false); } diff --git a/externals/powah/tests.cpp b/externals/powah/tests.cpp index 65baedb47b..c9e0add6b2 100644 --- a/externals/powah/tests.cpp +++ b/externals/powah/tests.cpp @@ -174,6 +174,43 @@ TEST_CASE("ppc64: rlwimi madness", "[ppc64]") { REQUIRE(data[7] == EB32(0x0e004379)); } +/* + 0: 78 1b 68 7c mr 8, 3 + 4: 38 28 83 7c and 3, 4, 5 + 8: 74 00 6a 7c cntlzd 10, 3 + c: 76 06 69 7c sradi 9, 3, 32 + 10: 82 d1 4a 79 rldicl 10, 10, 58, 6 + 14: 00 00 29 55 rlwinm 9, 9, 0, 0, 0 + 18: 64 f0 4a 79 sldi 10, 10, 30 + 1c: 78 53 29 7d or 9, 9, 10 + 20: 00 00 28 f9 std 9, 0(8) + 24: 20 00 80 4e blr +*/ +TEST_CASE("ppc64: functor-2", "[ppc64]") { + std::vector data(64); + powah::Context ctx(data.data(), data.size()); + ctx.MR(powah::R8, powah::R3); + ctx.AND(powah::R3, powah::R4, powah::R5); + ctx.CNTLZD(powah::R10, powah::R3); + ctx.SRADI(powah::R9, powah::R3, 32); + ctx.RLDICL(powah::R10, powah::R10, 58, 6); + ctx.RLWINM(powah::R9, powah::R9, 0, 0, 0); + ctx.SLDI(powah::R10, powah::R10, 30); + ctx.OR(powah::R9, powah::R9, powah::R10); + ctx.STD(powah::R9, powah::R8, 8); + ctx.BLR(); + REQUIRE(data[0] == EB32(0x781b687c)); + REQUIRE(data[1] == EB32(0x3828837c)); + REQUIRE(data[2] == EB32(0x74006a7c)); + REQUIRE(data[3] == EB32(0x7606697c)); + REQUIRE(data[4] == EB32(0x82d14a79)); + REQUIRE(data[5] == EB32(0x00002955)); + REQUIRE(data[6] == EB32(0x64f04a79)); + REQUIRE(data[7] == EB32(0x7853297d)); + REQUIRE(data[8] == EB32(0x000028f9)); + REQUIRE(data[9] == EB32(0x2000804e)); +} + TEST_CASE("ppc64: functor-1", "[ppc64]") { std::vector data(64); powah::Context ctx(data.data(), data.size()); 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 cef9a7b06d..ee3002ce89 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 @@ -562,7 +562,9 @@ 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)); code.RLDICL(result, src_a, 0, 32); // Truncate - code.AND_(result, result, src_b); + code.AND(result, result, src_b); + auto const tmp = ctx.reg_alloc.ScratchGpr(); + code.ANDI_(tmp, result, 0); ctx.reg_alloc.DefineValue(inst, result); } From 36bd1c262a662f5f3c6f2d7e4a878430dd1d8d5c Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 5 Nov 2025 00:53:19 +0000 Subject: [PATCH 26/49] even more stupid fixes i feel angry Signed-off-by: lizzie --- externals/powah/data2code.c | 6 ++-- externals/powah/powah_emit.hpp | 2 +- externals/powah/powah_gen_base.hpp | 14 ++++---- externals/powah/tests.cpp | 2 +- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 26 ++++++++------- .../ppc64/emit_ppc64_data_processing.cpp | 32 +++++++++++++++---- 6 files changed, 52 insertions(+), 30 deletions(-) diff --git a/externals/powah/data2code.c b/externals/powah/data2code.c index 76f98c5e18..05b2fd4e1a 100644 --- a/externals/powah/data2code.c +++ b/externals/powah/data2code.c @@ -183,19 +183,19 @@ int main(int argc, char *argv[]) { } else if (!strcmp(form, "DS")) { printf( "void %s(GPR const rt, GPR const ra, uint32_t d) {" - " emit_%s(0x%08x, rt, ra, d); " + " emit_%s(0x%08x, rt, ra, d >> 2); " "}\n" , mem, form, OP_EXT); } else if (!strcmp(form, "XS")) { /* HUGE DIFFERENCE DO NOT REMOVE */ printf( "void %s(GPR const rt, GPR const ra, uint32_t sh) {" - " emit_%s(0x%08x, ra, rt, sh, false); " + " emit_%s(0x%08x, rt, ra, sh, false); " "}\n" , mem, form, OP_EXT_XS); printf( "void %s_(GPR const rt, GPR const ra, uint32_t sh) {" - " emit_%s(0x%08x, ra, rt, sh, true); " + " emit_%s(0x%08x, rt, ra, sh, true); " "}\n" , mem, form, OP_EXT_XS); } else if (!strcmp(form, "XL")) { diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 1aa11f53a2..858f846574 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -254,7 +254,7 @@ struct Context { base[offset++] = (op | bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5) - | bitExt(d >> 2, 16, 14) + | bitExt(d, 16, 14) ); } void emit_M(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, uint32_t me, bool rc) { diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index 97b2410a09..bba6bc9067 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -224,10 +224,10 @@ void LBZUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ee, ra, rt void LBZUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ee, ra, rt, rb, true); } void LBZX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, ra, rt, rb, false); } void LBZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, ra, rt, rb, true); } -void LD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000000, rt, ra, d); } +void LD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000000, rt, ra, d >> 2); } void LDARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, ra, rt, rb, false); } void LDARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, ra, rt, rb, true); } -void LDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000002, rt, ra, d); } +void LDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000002, rt, ra, d >> 2); } void LDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, ra, rt, rb, false); } void LDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, ra, rt, rb, true); } void LDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002a, ra, rt, rb, false); } @@ -263,7 +263,7 @@ void LSWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, ra, rt, void LSWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, ra, rt, rb, true); } void LSWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, ra, rt, rb, false); } void LSWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, ra, rt, rb, true); } -void LWA(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000004, rt, ra, d); } +void LWA(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000004, rt, ra, d >> 2); } void LWARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, ra, rt, rb, false); } void LWARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, ra, rt, rb, true); } void LWAUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ea, ra, rt, rb, false); } @@ -384,8 +384,8 @@ void SLW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, ra, rt, void SLW_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000030, ra, rt, rb, true); } void SRAD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, ra, rt, rb, false); } void SRAD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000634, ra, rt, rb, true); } -void SRADI(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c000674, ra, rt, sh, false); } -void SRADI_(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c000674, ra, rt, sh, true); } +void SRADI(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c000674, rt, ra, sh, false); } +void SRADI_(GPR const rt, GPR const ra, uint32_t sh) { emit_XS(0x7c000674, rt, ra, sh, true); } void SRD(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, ra, rt, rb, false); } void SRD_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000436, ra, rt, rb, true); } void SRAW(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000630, ra, rt, rb, false); } @@ -400,10 +400,10 @@ void STBUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ee, ra, rt void STBUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ee, ra, rt, rb, true); } void STBX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, ra, rt, rb, false); } void STBX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, ra, rt, rb, true); } -void STD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000000, rt, ra, d); } +void STD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000000, rt, ra, d >> 2); } void STDCX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, ra, rt, rb, false); } void STDCX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, ra, rt, rb, true); } -void STDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000002, rt, ra, d); } +void STDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000002, rt, ra, d >> 2); } void STDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, ra, rt, rb, false); } void STDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, ra, rt, rb, true); } void STDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012a, ra, rt, rb, false); } diff --git a/externals/powah/tests.cpp b/externals/powah/tests.cpp index c9e0add6b2..43fff657c8 100644 --- a/externals/powah/tests.cpp +++ b/externals/powah/tests.cpp @@ -197,7 +197,7 @@ TEST_CASE("ppc64: functor-2", "[ppc64]") { ctx.RLWINM(powah::R9, powah::R9, 0, 0, 0); ctx.SLDI(powah::R10, powah::R10, 30); ctx.OR(powah::R9, powah::R9, powah::R10); - ctx.STD(powah::R9, powah::R8, 8); + ctx.STD(powah::R9, powah::R8, 0); ctx.BLR(); REQUIRE(data[0] == EB32(0x781b687c)); REQUIRE(data[1] == EB32(0x3828837c)); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 25db5e641d..4f3fcff594 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -9,6 +9,7 @@ #include #include +#include "abi.h" #include "dynarmic/backend/ppc64/a32_core.h" #include "dynarmic/backend/ppc64/a64_core.h" #include "dynarmic/backend/ppc64/abi.h" @@ -67,11 +68,20 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I ASSERT(false && "unimp value live"); return; } + + // All logical operations whom set (RC) are going to compute as the following: + // 1. Rt <- logical_op (Ra, Rb) + // 2. Compare as Signed(Rt) against 0 + // Basically, it's equivalent to say: + // + // add r0, r1, r2 -> add. r0, r1, r2 + // cmpli r0, 0 + // // 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?) + // 0 - 0x08 - N/LT, result is negative + // 1 - 0x04 - P/GT, result is positive + // 2 - 0x02 - Z/EQ, result is zero + // 3 - 0x01 - S/SO, summary overflow (carry?) // XER: // 32 - SO // 33 - Overflow @@ -99,14 +109,8 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I // 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); + code.MR(tmp3, PPC64::RNZCV); ctx.reg_alloc.DefineValue(inst, tmp3); } } 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 ee3002ce89..44323a4721 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 @@ -558,14 +558,33 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR: 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.RLDICL(result, src_a, 0, 32); // Truncate - code.AND(result, result, src_b); - auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.ANDI_(tmp, result, 0); - 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.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 +*/ + + ctx.reg_alloc.DefineValue(inst, tmp3); } template<> @@ -574,7 +593,6 @@ 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)); code.AND_(result, src_a, src_b); - code.ADDI(result, result, 0); //update cr0 ctx.reg_alloc.DefineValue(inst, result); } From 16b103aa6c4d009884335621a7561e14e9def1ed Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 5 Nov 2025 02:06:11 +0000 Subject: [PATCH 27/49] A64: addition fixes extra Signed-off-by: lizzie --- externals/powah/powah_emit.hpp | 1 + .../src/dynarmic/backend/ppc64/a64_core.h | 1 - src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 1 + .../ppc64/emit_ppc64_data_processing.cpp | 52 ++++++++----------- .../src/dynarmic/backend/ppc64/reg_alloc.cpp | 16 ++++-- 5 files changed, 38 insertions(+), 33 deletions(-) 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,41 +561,35 @@ 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(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 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 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); - -/* - 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 -*/ - 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); -} - template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const result = ctx.reg_alloc.ScratchGpr(); 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; From 08c284fcb8afe6f0985fd4627bf3b2de72443ef2 Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 6 Nov 2025 19:03:59 +0000 Subject: [PATCH 28/49] A64checkbit Signed-off-by: lizzie --- .../src/dynarmic/backend/ppc64/a32_core.h | 1 + .../src/dynarmic/backend/ppc64/a64_core.h | 1 + .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 26 ++++++++++++++----- .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 3 ++- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index 51309df704..a84185dd37 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -22,6 +22,7 @@ struct A32JitState { u32 exclusive_state = 0; u32 cpsr_nzcv = 0; u32 fpscr = 0; + u8 check_bit = 0; IR::LocationDescriptor GetLocationDescriptor() const { return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 5d79a47036..0f955a9e5b 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -28,6 +28,7 @@ struct A64JitState { u32 fpcr = 0; u32 fpsr = 0; volatile u32 halt_reason = 0; + u8 check_bit = 0; IR::LocationDescriptor GetLocationDescriptor() const { return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 4f3fcff594..e6da30be82 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -9,6 +9,8 @@ #include #include +#include "a32_core.h" +#include "a64_core.h" #include "abi.h" #include "dynarmic/backend/ppc64/a32_core.h" #include "dynarmic/backend/ppc64/a64_core.h" @@ -141,6 +143,8 @@ void EmitIR(powah::Context&, EmitContext&, IR:: } namespace { +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step); + void EmitTerminal(powah::Context&, EmitContext&, IR::Term::Interpret, IR::LocationDescriptor, bool) { ASSERT(false && "unimp"); } @@ -151,13 +155,11 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDisp void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { auto const tmp = ctx.reg_alloc.ScratchGpr(); - if (ctx.emit_conf.a64_variant) { - code.LI(tmp, terminal.next.Value()); + code.LI(tmp, terminal.next.Value()); + if (ctx.emit_conf.a64_variant) code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); - } else { - code.LI(tmp, terminal.next.Value()); + else code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15); - } } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { @@ -177,7 +179,19 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::If terminal, } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - ASSERT(false && "unimp"); + powah::Label const l_else = code.DefineLabel(); + powah::Label const l_end = code.DefineLabel(); + auto const tmp = ctx.reg_alloc.ScratchGpr(); + code.LBZ(tmp, PPC64::RJIT, ctx.emit_conf.a64_variant ? offsetof(A64JitState, check_bit) : offsetof(A32JitState, check_bit)); + code.CMPLWI(tmp, 0); + code.BEQ(powah::CR0, l_else); + // CheckBit == 1 + EmitTerminal(code, ctx, terminal.then_, initial_location, is_single_step); + code.B(l_end); + // CheckBit == 0 + code.LABEL(l_else); + EmitTerminal(code, ctx, terminal.else_, initial_location, is_single_step); + code.LABEL(l_end); } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) { 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 195bca017f..0ed9a09c6e 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -18,7 +18,8 @@ namespace Dynarmic::Backend::PPC64 { 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.STB(value, PPC64::RJIT, offsetof(A64JitState, check_bit)); } template<> From c040f737942c6f8dc9cb4a087993234c4755f40b Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 6 Nov 2025 19:16:33 +0000 Subject: [PATCH 29/49] fix invalidations, use stack for checkbit Signed-off-by: lizzie --- docs/dynarmic/README.md | 2 +- .../src/dynarmic/backend/ppc64/a64_interface.cpp | 1 + .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 4 ++-- .../src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 2 +- .../src/dynarmic/backend/ppc64/stack_layout.h | 12 +++--------- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/docs/dynarmic/README.md b/docs/dynarmic/README.md index 0fa893d550..521f78ee7c 100644 --- a/docs/dynarmic/README.md +++ b/docs/dynarmic/README.md @@ -7,7 +7,7 @@ A dynamic recompiler for ARM. Cortex-A57 (32 and 64 bit) is the emulated guest target. See [ArchVersion](../../src/dynarmic/src/dynarmic/interface/A32/arch_version.h). -The only supported host architectures are x86-64, and AArch64. There are no plans to support any 32-bit architectures. +The only supported host architectures are x86-64, PowerPC 64, and AArch64. There are no plans to support any 32-bit architectures. See [an example usage](../../src/dynarmic/tests/print_info.cpp). diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 5e56789fb5..bc47dcedc1 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -81,6 +81,7 @@ struct Jit::Impl final { ASSERT(!is_executing); is_executing = true; HaltReason hr = core.Run(current_address_space, jit_state, &halt_reason); + current_address_space.ClearCache(); // TODO: dont just invalidate everything is_executing = false; RequestCacheInvalidation(); return hr; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index e6da30be82..d463c7c069 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -182,8 +182,8 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckBit ter powah::Label const l_else = code.DefineLabel(); powah::Label const l_end = code.DefineLabel(); auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.LBZ(tmp, PPC64::RJIT, ctx.emit_conf.a64_variant ? offsetof(A64JitState, check_bit) : offsetof(A32JitState, check_bit)); - code.CMPLWI(tmp, 0); + code.LD(tmp, powah::R1, offsetof(StackLayout, check_bit)); + code.CMPLDI(tmp, 0); code.BEQ(powah::CR0, l_else); // CheckBit == 1 EmitTerminal(code, ctx, terminal.then_, initial_location, is_single_step); 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 0ed9a09c6e..b341373d61 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -19,7 +19,7 @@ namespace Dynarmic::Backend::PPC64 { template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - code.STB(value, PPC64::RJIT, offsetof(A64JitState, check_bit)); + code.STD(value, powah::R1, offsetof(StackLayout, check_bit)); } template<> diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h index bb70a359a9..9b83d971d6 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h @@ -9,18 +9,12 @@ namespace Dynarmic::Backend::PPC64 { -constexpr size_t SpillCount = 64; +constexpr size_t SpillCount = 16; struct alignas(16) StackLayout { - s64 cycles_remaining; - s64 cycles_to_run; - + std::array regs; std::array spill; - - u32 save_host_fpcr; - u32 save_host_fpsr; - - bool check_bit; + u64 check_bit; }; static_assert(sizeof(StackLayout) % 16 == 0); From 2b952b79d7064a23e19854e98849c748f128dac1 Mon Sep 17 00:00:00 2001 From: crueter Date: Sun, 23 Nov 2025 20:43:29 -0500 Subject: [PATCH 30/49] build fixes + gentoo cross docs Signed-off-by: crueter --- CMakeModules/GentooCross.cmake | 18 +++ docs/CrossCompile.md | 118 +++++++++++++++++- externals/powah/CMakeLists.txt | 1 + externals/powah/powah_emit.hpp | 4 +- .../backend/exception_handler_posix.cpp | 1 + .../src/dynarmic/backend/ppc64/reg_alloc.cpp | 1 + 6 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 CMakeModules/GentooCross.cmake diff --git a/CMakeModules/GentooCross.cmake b/CMakeModules/GentooCross.cmake new file mode 100644 index 0000000000..69e9afc69b --- /dev/null +++ b/CMakeModules/GentooCross.cmake @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + +set(CROSS_TARGET "powerpc64le" CACHE STRING "Cross-compilation target (aarch64, powerpc64le, riscv64, etc)") + +set(CMAKE_SYSROOT /usr/${CROSS_TARGET}-unknown-linux-gnu) + +set(CMAKE_C_COMPILER ${CROSS_TARGET}-unknown-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER ${CROSS_TARGET}-unknown-linux-gnu-g++) + +# search programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + +# search headers and libraries in the target environment +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +set(CMAKE_FIND_ROOT_PATH /usr/${CROSS_TARGET}-unknown-linux-gnu) diff --git a/docs/CrossCompile.md b/docs/CrossCompile.md index 77bf5106f6..d0b0732310 100644 --- a/docs/CrossCompile.md +++ b/docs/CrossCompile.md @@ -2,7 +2,122 @@ General guide for cross compiling. -## Debian ARM64 +## Gentoo + +Gentoo's cross-compilation setup is relatively easy, provided you're already familiar with portage. + +### Crossdev + +First, emerge crossdev via `sudo emerge -a sys-devel/crossdev`. + +Now, set up the environment depending on the target architecture; e.g. + +```sh +sudo crossdev powerpc64le +sudo crossdev aarch64 +``` + +### QEMU + +Installing a qemu user setup is recommended for testing. To do so, you will need the relevant USE flags: + +```sh +app-emulation/qemu static-user qemu_user_targets_ppc64le qemu_user_targets_aarch64 +``` + +Note that to use cross-emerged libraries, you will need to tell qemu where the sysroot is. You can do this with an alias: + +```sh +alias qemu-ppc64le="qemu-ppc64le -L /usr/powerpc64le-unknown-linux-gnu" +alias qemu-aarch64="qemu-aarch64 -L /usr/aarch64-unknown-linux-gnu" +``` + +### Dependencies + +Some packages have broken USE flags on other architectures; you'll also need to set up python targets. In `/usr/-unknown-linux-gnu/etc/portage/package.use`: + +```sh +>=net-misc/curl-8.16.0-r1 ssl + +*/* PYTHON_TARGETS: python3_13 PYTHON_SINGLE_TARGET: python3_13 +*/* pam + +sys-apps/util-linux pam su +app-shells/bash -readline +>=dev-libs/libpcre2-10.47 unicode +>=x11-libs/libxkbcommon-1.12.3 X +>=sys-libs/zlib-1.3.1-r1 minizip +>=app-alternatives/gpg-1-r3 ssl +>=app-crypt/gnupg-2.5.13-r2 ssl + +dev-libs/* -introspection +media-libs/harfbuzz -introspection +dev-libs/quazip -qt5 qt6 +``` + +Dependencies should be about the same [as normal Gentoo](./Deps.md), but removing gamemode and renderdoc is recommended. Keep in mind that when emerging, you want to use `emerge--unknown-linux-gnu`, e.g. `emerge-powerpc64le-unknown-linux-gnu`. + +Enable GURU in the cross environment (as root): + +```sh +mkdir -p /usr/powerpc64le-unknown-linux-gnu/etc/portage/repos.conf +cat << EOF > /usr/powerpc64le-unknown-linux-gnu/etc/portage/repos.conf/guru.conf +[guru] +location = /var/db/repos/guru +auto-sync = no +priority = 1 +EOF +``` + +Now emerge your dependencies: + +```sh +sudo emerge-powerpc64le-unknown-linux-gnu -aU app-arch/lz4 app-arch/zstd app-arch/unzip \ + dev-libs/libfmt dev-libs/libusb dev-libs/mcl dev-libs/sirit dev-libs/oaknut \ + dev-libs/unordered_dense dev-libs/boost dev-libs/openssl dev-libs/discord-rpc \ + dev-util/spirv-tools dev-util/spirv-headers dev-util/vulkan-headers \ + dev-util/vulkan-utility-libraries dev-util/glslang \ + media-libs/libva media-libs/opus media-video/ffmpeg \ + media-libs/VulkanMemoryAllocator media-libs/libsdl2 media-libs/cubeb \ + net-libs/enet net-libs/mbedtls \ + sys-libs/zlib \ + dev-cpp/nlohmann_json dev-cpp/simpleini dev-cpp/cpp-httplib dev-cpp/cpp-jwt dev-cpp/catch \ + net-wireless/wireless-tools \ + dev-qt/qtbase:6 dev-libs/quazip \ + virtual/pkgconfig +``` + +### Building + +A toolchain is provided in `CMakeModules/GentooCross.cmake`. To use it: + +```sh +cmake -S . -B build/ppc64 -DCMAKE_TOOLCHAIN_FILE=CMakeModules/GentooCross.cmake -G Ninja -DCROSS_TARGET=powerpc64le -DENABLE_OPENGL=OFF +``` + +Now build as normal: + +```sh +cmake --build build/ppc64 -j$(nproc) +``` + +### Alternatively + +Only emerge the absolute necessities: + +```sh +sudo emerge-powerpc64le-unknown-linux-gnu -aU media-video/ffmpeg media-libs/libsdl2 dev-qt/qtbase:6 +``` + +Then set `YUZU_USE_CPM=ON`: + +```sh +cmake -S . -B build/ppc64 -DCMAKE_TOOLCHAIN_FILE=CMakeModules/GentooCross.cmake -G Ninja -DCROSS_TARGET=powerpc64le -DENABLE_OPENGL=OFF -DYUZU_USE_CPM=ON +``` + +## ARM64 + +### Debian ARM64 A painless guide for cross compilation (or to test NCE) from a x86_64 system without polluting your main. @@ -98,6 +213,7 @@ Now you got a PowerPC sysroot - quickly decompress it somewhere, say `/home/user There is a script to automatically do all of this under `./tools/setup-cross-sysroot.sh` Specify: + - `YUZU_USE_CPM`: Set this to `ON` so packages can be found and built if your sysroot doesn't have them. - `YUZU_USE_EXTERNAL_FFMPEG`: Set this to `ON` as well. diff --git a/externals/powah/CMakeLists.txt b/externals/powah/CMakeLists.txt index 68587ae10d..f5301b2946 100644 --- a/externals/powah/CMakeLists.txt +++ b/externals/powah/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(powah INTERFACE) target_include_directories(powah INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_options(powah INTERFACE -Wno-unused-parameter) add_executable(powah_tests tests.cpp) create_target_directory_groups(powah_tests) diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index c3f110b103..167a2c6945 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -5,10 +5,10 @@ #include #include #include -#include -#include +#include #include #include +#include //#ifndef __cpp_lib_unreachable namespace std { diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp index eda4817d38..6776fc22b3 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp index 3e524571b0..2aa02777f9 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "dynarmic/backend/ppc64/reg_alloc.h" #include "dynarmic/backend/ppc64/abi.h" From f8685e0c9277614ee1ec2350ea7a343452b1275a Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 10 Nov 2025 19:44:17 +0000 Subject: [PATCH 31/49] inline a32core/a64core Signed-off-by: lizzie --- .../src/dynarmic/backend/ppc64/a32_core.h | 27 ---- .../dynarmic/backend/ppc64/a32_interface.cpp | 105 +++++++++------- .../src/dynarmic/backend/ppc64/a64_core.h | 29 ----- .../dynarmic/backend/ppc64/a64_interface.cpp | 117 ++++++++++-------- 4 files changed, 120 insertions(+), 158 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index a84185dd37..2fb0268614 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -28,31 +28,4 @@ struct A32JitState { } }; -class A32AddressSpace final { -public: - explicit A32AddressSpace(const A32::UserConfig& conf); - CodePtr GetOrEmit(IR::LocationDescriptor descriptor); - void ClearCache(); -private: - friend class A32Core; - EmittedBlockInfo Emit(IR::Block ir_block); - void Link(EmittedBlockInfo& block); - const A32::UserConfig conf; - CodeBlock cb; - powah::Context as; - ankerl::unordered_dense::map block_entries; - ankerl::unordered_dense::map block_infos; -}; - -class A32Core final { -public: - explicit A32Core(const A32::UserConfig&) {} - HaltReason Run(A32AddressSpace& process, A32JitState& thread_ctx, volatile u32* halt_reason) { - auto const loc = thread_ctx.GetLocationDescriptor(); - auto const entry = process.GetOrEmit(loc); - using CodeFn = HaltReason (*)(A32JitState*, volatile u32*); - return (CodeFn(entry))(&thread_ctx, halt_reason); - } -}; - } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index 6c50e1c647..b67fa50c10 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -17,71 +17,83 @@ #include "dynarmic/ir/opt_passes.h" #include "dynarmic/interface/A32/a32.h" -namespace Dynarmic::Backend::PPC64 { - -A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf) - : conf(conf) - , cb(conf.code_cache_size) - , as(cb.ptr(), conf.code_cache_size) { - -} - -CodePtr A32AddressSpace::GetOrEmit(IR::LocationDescriptor desc) { - if (auto const it = block_entries.find(desc.Value()); it != block_entries.end()) - return it->second; - - IR::Block ir_block = A32::Translate(A32::LocationDescriptor{desc}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); - Optimization::Optimize(ir_block, conf, {}); - const EmittedBlockInfo block_info = Emit(std::move(ir_block)); - - block_infos.insert_or_assign(desc.Value(), block_info); - block_entries.insert_or_assign(desc.Value(), block_info.entry_point); - return block_info.entry_point; -} - -void A32AddressSpace::ClearCache() { - block_entries.clear(); - block_infos.clear(); -} - -EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) { - EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { - .enable_cycle_counting = conf.enable_cycle_counting, - .always_little_endian = conf.always_little_endian, - .a64_variant = false - }); - Link(block_info); - return block_info; -} - -void A32AddressSpace::Link(EmittedBlockInfo& block_info) { - //UNREACHABLE(); -} - -} - namespace Dynarmic::A32 { using namespace Dynarmic::Backend::PPC64; +struct A32AddressSpace final { + explicit A32AddressSpace(const A32::UserConfig& conf) + : conf(conf) + , cb(conf.code_cache_size) + , as(cb.ptr(), conf.code_cache_size) { + + } + + CodePtr GetOrEmit(IR::LocationDescriptor desc) { + if (auto const it = block_entries.find(desc.Value()); it != block_entries.end()) + return it->second; + + IR::Block ir_block = A32::Translate(A32::LocationDescriptor{desc}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); + Optimization::Optimize(ir_block, conf, {}); + const EmittedBlockInfo block_info = Emit(std::move(ir_block)); + + block_infos.insert_or_assign(desc.Value(), block_info); + block_entries.insert_or_assign(desc.Value(), block_info.entry_point); + return block_info.entry_point; + } + + void ClearCache() { + block_entries.clear(); + block_infos.clear(); + } + + EmittedBlockInfo Emit(IR::Block block) { + EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { + .enable_cycle_counting = conf.enable_cycle_counting, + .always_little_endian = conf.always_little_endian, + .a64_variant = false + }); + Link(block_info); + return block_info; + } + + void Link(EmittedBlockInfo& block_info) { + //UNREACHABLE(); + } + + const A32::UserConfig conf; + CodeBlock cb; + powah::Context as; + ankerl::unordered_dense::map block_entries; + ankerl::unordered_dense::map block_infos; +}; + +struct A32Core final { + static HaltReason Run(A32AddressSpace& process, A32JitState& thread_ctx, volatile u32* halt_reason) { + auto const loc = thread_ctx.GetLocationDescriptor(); + auto const entry = process.GetOrEmit(loc); + using CodeFn = HaltReason (*)(A32JitState*, volatile u32*); + return (CodeFn(entry))(&thread_ctx, halt_reason); + } +}; + struct Jit::Impl final { Impl(Jit* jit_interface, A32::UserConfig conf) : conf(conf) , current_address_space(conf) - , core(conf) , jit_interface(jit_interface) {} HaltReason Run() { ASSERT(!is_executing); is_executing = false; - HaltReason hr = core.Run(current_address_space, jit_state, &halt_reason); + HaltReason hr = A32Core::Run(current_address_space, jit_state, &halt_reason); is_executing = true; RequestCacheInvalidation(); return hr; } HaltReason Step() { - // HaltReason hr = core.Step(current_address_space, jit_state, &halt_reason); + // HaltReason hr = A32Core::Step(current_address_space, jit_state, &halt_reason); // RequestCacheInvalidation(); return HaltReason{}; } @@ -156,7 +168,6 @@ private: A32::UserConfig conf; A32JitState jit_state{}; A32AddressSpace current_address_space; - A32Core core; Jit* jit_interface; volatile u32 halt_reason = 0; bool is_executing = false; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 0f955a9e5b..94ddd84dad 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -34,33 +34,4 @@ struct A64JitState { } }; -class A64AddressSpace final { -public: - explicit A64AddressSpace(const A64::UserConfig& conf); - CodePtr GetOrEmit(IR::LocationDescriptor descriptor); - void ClearCache(); -private: - friend class A64Core; - void EmitPrelude(); - EmittedBlockInfo Emit(IR::Block ir_block); - void Link(EmittedBlockInfo& block); - - const A64::UserConfig conf; - CodeBlock cb; - powah::Context as; - ankerl::unordered_dense::map block_entries; - ankerl::unordered_dense::map block_infos; -}; - -class A64Core final { -public: - explicit A64Core(const A64::UserConfig&) {} - HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { - const auto loc = thread_ctx.GetLocationDescriptor(); - const auto entry = process.GetOrEmit(loc); - using CodeFn = HaltReason (*)(A64JitState*, volatile u32*); - return (CodeFn(entry))(&thread_ctx, halt_reason); - } -}; - } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index bc47dcedc1..accbceaaaf 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -16,79 +16,87 @@ #include "dynarmic/ir/opt_passes.h" #include "dynarmic/interface/A64/a64.h" -namespace Dynarmic::Backend::PPC64 { - -A64AddressSpace::A64AddressSpace(const A64::UserConfig& conf) - : conf(conf) - , cb(conf.code_cache_size) - , as(cb.ptr(), conf.code_cache_size) { - -} - -CodePtr A64AddressSpace::GetOrEmit(IR::LocationDescriptor desc) { - if (auto const it = block_entries.find(desc.Value()); it != block_entries.end()) - return it->second; - - const auto get_code = [this](u64 vaddr) { - return conf.callbacks->MemoryReadCode(vaddr); - }; - IR::Block ir_block = A64::Translate(A64::LocationDescriptor{desc}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); - Optimization::Optimize(ir_block, conf, {}); - - fmt::print("IR:\n"); - fmt::print("{}\n", IR::DumpBlock(ir_block)); - - const EmittedBlockInfo block_info = Emit(std::move(ir_block)); - - block_infos.insert_or_assign(desc.Value(), block_info); - block_entries.insert_or_assign(desc.Value(), block_info.entry_point); - return block_info.entry_point; -} - -void A64AddressSpace::ClearCache() { - block_entries.clear(); - block_infos.clear(); -} - -EmittedBlockInfo A64AddressSpace::Emit(IR::Block block) { - EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { - .enable_cycle_counting = conf.enable_cycle_counting, - .always_little_endian = true, - .a64_variant = true - }); - Link(block_info); - return block_info; -} - -void A64AddressSpace::Link(EmittedBlockInfo& block_info) { - // TODO(lizzie): Block linking - // UNREACHABLE(); -} -} - namespace Dynarmic::A64 { using namespace Dynarmic::Backend::PPC64; +struct A64AddressSpace final { + explicit A64AddressSpace(const A64::UserConfig& conf) + : conf(conf) + , cb(conf.code_cache_size) + , as(cb.ptr(), conf.code_cache_size) { + + } + + CodePtr GetOrEmit(IR::LocationDescriptor desc) { + if (auto const it = block_entries.find(desc.Value()); it != block_entries.end()) + return it->second; + + const auto get_code = [this](u64 vaddr) { + return conf.callbacks->MemoryReadCode(vaddr); + }; + IR::Block ir_block = A64::Translate(A64::LocationDescriptor{desc}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); + Optimization::Optimize(ir_block, conf, {}); + fmt::print("IR:\n{}\n", IR::DumpBlock(ir_block)); + const EmittedBlockInfo block_info = Emit(std::move(ir_block)); + block_infos.insert_or_assign(desc.Value(), block_info); + block_entries.insert_or_assign(desc.Value(), block_info.entry_point); + return block_info.entry_point; + } + + void ClearCache() { + block_entries.clear(); + block_infos.clear(); + } + + EmittedBlockInfo Emit(IR::Block block) { + EmittedBlockInfo block_info = EmitPPC64(as, std::move(block), { + .enable_cycle_counting = conf.enable_cycle_counting, + .always_little_endian = true, + .a64_variant = true + }); + Link(block_info); + return block_info; + } + + void Link(EmittedBlockInfo& block_info) { + // TODO(lizzie): Block linking + // UNREACHABLE(); + } + + const A64::UserConfig conf; + CodeBlock cb; + powah::Context as; + ankerl::unordered_dense::map block_entries; + ankerl::unordered_dense::map block_infos; +}; + +struct A64Core final { + static HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { + const auto loc = thread_ctx.GetLocationDescriptor(); + const auto entry = process.GetOrEmit(loc); + using CodeFn = HaltReason (*)(A64JitState*, volatile u32*); + return (CodeFn(entry))(&thread_ctx, halt_reason); + } +}; + struct Jit::Impl final { Impl(Jit* jit_interface, A64::UserConfig conf) : conf(conf) , current_address_space(conf) - , core(conf) , jit_interface(jit_interface) {} HaltReason Run() { ASSERT(!is_executing); is_executing = true; - HaltReason hr = core.Run(current_address_space, jit_state, &halt_reason); - current_address_space.ClearCache(); // TODO: dont just invalidate everything + HaltReason hr = A64Core::Run(current_address_space, jit_state, &halt_reason); is_executing = false; RequestCacheInvalidation(); return hr; } HaltReason Step() { - // HaltReason hr = core.Step(current_address_space, jit_state, &halt_reason); + // HaltReason hr = A64Core::Step(current_address_space, jit_state, &halt_reason); // RequestCacheInvalidation(); return HaltReason{}; } @@ -223,7 +231,6 @@ private: A64::UserConfig conf; A64JitState jit_state{}; A64AddressSpace current_address_space; - A64Core core; Jit* jit_interface; volatile u32 halt_reason = 0; bool is_executing = false; From 4e5f0cd4e1b1eb4bd7ab02e7bb673459bf7bc107 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 11 Nov 2025 01:44:12 +0000 Subject: [PATCH 32/49] chained calls for ppc64 Signed-off-by: lizzie --- externals/powah/powah_emit.hpp | 3 +++ .../dynarmic/backend/ppc64/a32_interface.cpp | 4 ++-- .../src/dynarmic/backend/ppc64/a64_core.h | 6 ++++-- .../dynarmic/backend/ppc64/a64_interface.cpp | 7 +++---- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 5 ++++- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 18 +++++++++++++++--- .../src/dynarmic/backend/ppc64/emit_ppc64.h | 14 +------------- 7 files changed, 32 insertions(+), 25 deletions(-) diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 167a2c6945..0f10199a77 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -366,6 +366,9 @@ struct Context { 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 MFLR(GPR const rt) { MFSPR(powah::GPR{8}, rt, powah::GPR{0}); } + void MTLR(GPR const rt) { MTSPR(powah::GPR{8}, rt, powah::GPR{0}); } + void BLR() { base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0); } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index b67fa50c10..5568ff1fab 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -72,8 +72,8 @@ struct A32Core final { static HaltReason Run(A32AddressSpace& process, A32JitState& thread_ctx, volatile u32* halt_reason) { auto const loc = thread_ctx.GetLocationDescriptor(); auto const entry = process.GetOrEmit(loc); - using CodeFn = HaltReason (*)(A32JitState*, volatile u32*); - return (CodeFn(entry))(&thread_ctx, halt_reason); + using CodeFn = HaltReason (*)(A32AddressSpace*, A32JitState*, volatile u32*); + return (CodeFn(entry))(&process, &thread_ctx, halt_reason); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 94ddd84dad..5cd10c726f 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -22,7 +22,7 @@ struct A64JitState { u64 pc = 0; alignas(16) std::array vec{}; u64 sp = 0; - u32 upper_location_descriptor; + u32 upper_location_descriptor = 0; u32 exclusive_state = 0; u32 pstate = 0; u32 fpcr = 0; @@ -30,7 +30,9 @@ struct A64JitState { volatile u32 halt_reason = 0; u8 check_bit = 0; IR::LocationDescriptor GetLocationDescriptor() const { - return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; + const u64 fpcr_u64 = u64(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift; + const u64 pc_u64 = pc & A64::LocationDescriptor::pc_mask; + return IR::LocationDescriptor{pc_u64 | fpcr_u64}; } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index accbceaaaf..75ea6afc95 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -31,8 +31,7 @@ struct A64AddressSpace final { CodePtr GetOrEmit(IR::LocationDescriptor desc) { if (auto const it = block_entries.find(desc.Value()); it != block_entries.end()) return it->second; - - const auto get_code = [this](u64 vaddr) { + auto const get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); }; IR::Block ir_block = A64::Translate(A64::LocationDescriptor{desc}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); @@ -75,8 +74,8 @@ struct A64Core final { static HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { const auto loc = thread_ctx.GetLocationDescriptor(); const auto entry = process.GetOrEmit(loc); - using CodeFn = HaltReason (*)(A64JitState*, volatile u32*); - return (CodeFn(entry))(&thread_ctx, halt_reason); + using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*); + return (CodeFn(entry))(&process, &thread_ctx, halt_reason); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 3e8bbbacf2..0f7e059110 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -8,7 +8,10 @@ namespace Dynarmic::Backend::PPC64 { -constexpr powah::GPR RJIT = powah::R3; //yeah it's param, so what? +// Jit fn signature => (AXXAddressSpace& process, AXXJitState& thread_ctx, volatile u32* halt_reason) +constexpr powah::GPR RPROCESS = powah::R3; +constexpr powah::GPR RJIT = powah::R4; +constexpr powah::GPR RHALTREASON = powah::R5; constexpr powah::GPR RNZCV = powah::R31; constexpr powah::GPR ABI_PARAM1 = powah::R3; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index d463c7c069..09d9e15d82 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -4,6 +4,7 @@ #include "dynarmic/backend/ppc64/emit_ppc64.h" #include +#include #include #include @@ -156,10 +157,21 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDisp void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); - if (ctx.emit_conf.a64_variant) + if (ctx.emit_conf.a64_variant) { code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); - else + code.MFLR(PPC64::RLINKFN); + for (u32 i = 0; i < 4; ++i) + code.STD(powah::GPR{3 + i}, powah::R1, -((GPR_ORDER.size() + i) * 8)); + code.ADDIS(powah::R1, powah::R1, -sizeof(StackLayout)); + code.BLR(); + code.ADDI(powah::R1, powah::R1, sizeof(StackLayout)); + for (u32 i = 0; i < 4; ++i) + code.LD(powah::GPR{3 + i}, powah::R1, -((GPR_ORDER.size() + i) * 8)); + code.MTLR(PPC64::RLINKFN); + } else { code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15); + ASSERT(false && "unimp"); + } } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { @@ -211,7 +223,7 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf EmitContext ctx{block, reg_alloc, emit_conf, ebi}; auto const start_offset = code.offset; - ebi.entry_point = CodePtr(code.base + start_offset); + ebi.entry_point = &code.base[start_offset]; // Non-volatile saves std::vector gpr_order{GPR_ORDER}; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h index ac209d8099..b7e68b71ed 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h @@ -21,21 +21,9 @@ enum class Opcode; namespace Dynarmic::Backend::PPC64 { -using CodePtr = std::byte*; - -enum class LinkTarget { - ReturnFromRunCode, -}; - -struct Relocation { - std::ptrdiff_t code_offset; - LinkTarget target; -}; - struct EmittedBlockInfo { - CodePtr entry_point; + std::uint32_t* entry_point; size_t size; - std::vector relocations; }; struct EmitConfig { From ed8d2d9dedc2d11eb6347aa78d6a5d646649479e Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 13 Nov 2025 23:49:31 +0000 Subject: [PATCH 33/49] more ppc fixes Signed-off-by: lizzie --- src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp | 5 +++-- src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp | 5 +++-- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index 5568ff1fab..a2d443ad9b 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -20,6 +20,7 @@ namespace Dynarmic::A32 { using namespace Dynarmic::Backend::PPC64; +using CodePtr = std::uint32_t*; struct A32AddressSpace final { explicit A32AddressSpace(const A32::UserConfig& conf) @@ -72,8 +73,8 @@ struct A32Core final { static HaltReason Run(A32AddressSpace& process, A32JitState& thread_ctx, volatile u32* halt_reason) { auto const loc = thread_ctx.GetLocationDescriptor(); auto const entry = process.GetOrEmit(loc); - using CodeFn = HaltReason (*)(A32AddressSpace*, A32JitState*, volatile u32*); - return (CodeFn(entry))(&process, &thread_ctx, halt_reason); + using CodeFn = HaltReason (*)(A32AddressSpace*, A32JitState*, volatile u32*, void*); + return (CodeFn(entry))(&process, &thread_ctx, halt_reason, reinterpret_cast(&A32Core::Run)); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 75ea6afc95..063f74cc68 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -19,6 +19,7 @@ namespace Dynarmic::A64 { using namespace Dynarmic::Backend::PPC64; +using CodePtr = std::uint32_t*; struct A64AddressSpace final { explicit A64AddressSpace(const A64::UserConfig& conf) @@ -74,8 +75,8 @@ struct A64Core final { static HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { const auto loc = thread_ctx.GetLocationDescriptor(); const auto entry = process.GetOrEmit(loc); - using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*); - return (CodeFn(entry))(&process, &thread_ctx, halt_reason); + using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void*); + return (CodeFn(entry))(&process, &thread_ctx, halt_reason, reinterpret_cast(&A64Core::Run)); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 0f7e059110..3d4b2c70bd 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -8,10 +8,11 @@ namespace Dynarmic::Backend::PPC64 { -// Jit fn signature => (AXXAddressSpace& process, AXXJitState& thread_ctx, volatile u32* halt_reason) +// Jit fn signature => (AXXAddressSpace& process, AXXJitState& thread_ctx, volatile u32* halt_reason, void* link_fn) constexpr powah::GPR RPROCESS = powah::R3; constexpr powah::GPR RJIT = powah::R4; constexpr powah::GPR RHALTREASON = powah::R5; +constexpr powah::GPR RLINKFN = powah::R6; constexpr powah::GPR RNZCV = powah::R31; constexpr powah::GPR ABI_PARAM1 = powah::R3; From 7a80ce616b48bbe9457d51fa8091e4b69b9149f0 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 10 Dec 2025 09:13:26 +0000 Subject: [PATCH 34/49] Use ctr like gcc does Signed-off-by: lizzie --- externals/powah/powah_emit.hpp | 7 ++++--- src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h | 2 ++ .../src/dynarmic/backend/ppc64/a32_interface.cpp | 1 + src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h | 2 ++ .../src/dynarmic/backend/ppc64/a64_interface.cpp | 1 + src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 3 +-- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 14 ++++++++++---- .../src/dynarmic/backend/ppc64/stack_layout.h | 1 + 8 files changed, 22 insertions(+), 9 deletions(-) diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 0f10199a77..4b6f1d72e6 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -368,10 +368,11 @@ struct Context { void MFLR(GPR const rt) { MFSPR(powah::GPR{8}, rt, powah::GPR{0}); } void MTLR(GPR const rt) { MTSPR(powah::GPR{8}, rt, powah::GPR{0}); } + void BLR() { base[offset++] = 0x4e800020; } //BCLR(R0, CR0, R0); - void BLR() { - base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0); - } + void MFCTR(GPR const rt) { MFSPR(powah::GPR{9}, rt, powah::GPR{0}); } + void MTCTR(GPR const rt) { MTSPR(powah::GPR{9}, rt, powah::GPR{0}); } + void BCTRL() { base[offset++] = 0x4e800421; } //BCCTRL(R0, CR0, R0); // TODO: PowerPC 11 stuff void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index 2fb0268614..19816d4c93 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -23,6 +23,8 @@ struct A32JitState { u32 cpsr_nzcv = 0; u32 fpscr = 0; u8 check_bit = 0; + void* run_fn = nullptr; + IR::LocationDescriptor GetLocationDescriptor() const { return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; } diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index a2d443ad9b..e7269582c3 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -74,6 +74,7 @@ struct A32Core final { auto const loc = thread_ctx.GetLocationDescriptor(); auto const entry = process.GetOrEmit(loc); using CodeFn = HaltReason (*)(A32AddressSpace*, A32JitState*, volatile u32*, void*); + thread_ctx.run_fn = (void*)&A32Core::Run; return (CodeFn(entry))(&process, &thread_ctx, halt_reason, reinterpret_cast(&A32Core::Run)); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 5cd10c726f..0d5fc6eace 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -29,6 +29,8 @@ struct A64JitState { u32 fpsr = 0; volatile u32 halt_reason = 0; u8 check_bit = 0; + void* run_fn = nullptr; + IR::LocationDescriptor GetLocationDescriptor() const { const u64 fpcr_u64 = u64(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift; const u64 pc_u64 = pc & A64::LocationDescriptor::pc_mask; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 063f74cc68..f07b8ef1be 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -76,6 +76,7 @@ struct A64Core final { const auto loc = thread_ctx.GetLocationDescriptor(); const auto entry = process.GetOrEmit(loc); using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void*); + thread_ctx.run_fn = (void*)&A64Core::Run; return (CodeFn(entry))(&process, &thread_ctx, halt_reason, reinterpret_cast(&A64Core::Run)); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 3d4b2c70bd..0f7e059110 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -8,11 +8,10 @@ namespace Dynarmic::Backend::PPC64 { -// Jit fn signature => (AXXAddressSpace& process, AXXJitState& thread_ctx, volatile u32* halt_reason, void* link_fn) +// Jit fn signature => (AXXAddressSpace& process, AXXJitState& thread_ctx, volatile u32* halt_reason) constexpr powah::GPR RPROCESS = powah::R3; constexpr powah::GPR RJIT = powah::R4; constexpr powah::GPR RHALTREASON = powah::R5; -constexpr powah::GPR RLINKFN = powah::R6; constexpr powah::GPR RNZCV = powah::R31; constexpr powah::GPR ABI_PARAM1 = powah::R3; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 09d9e15d82..14be3d3aaa 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -21,6 +21,7 @@ #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" +#include "stack_layout.h" namespace Dynarmic::Backend::PPC64 { @@ -155,23 +156,28 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDisp } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { + auto const tmp_lr = ctx.reg_alloc.ScratchGpr(); auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.LI(tmp, terminal.next.Value()); + code.LD(tmp_lr, PPC64::RJIT, offsetof(StackLayout, lr)); + code.MFCTR(tmp_lr); if (ctx.emit_conf.a64_variant) { + code.LI(tmp, terminal.next.Value()); code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); - code.MFLR(PPC64::RLINKFN); + code.LD(tmp, PPC64::RJIT, offsetof(A64JitState, run_fn)); + code.MTCTR(tmp); for (u32 i = 0; i < 4; ++i) code.STD(powah::GPR{3 + i}, powah::R1, -((GPR_ORDER.size() + i) * 8)); code.ADDIS(powah::R1, powah::R1, -sizeof(StackLayout)); - code.BLR(); + code.BCTRL(); code.ADDI(powah::R1, powah::R1, sizeof(StackLayout)); for (u32 i = 0; i < 4; ++i) code.LD(powah::GPR{3 + i}, powah::R1, -((GPR_ORDER.size() + i) * 8)); - code.MTLR(PPC64::RLINKFN); } else { + code.LI(tmp, terminal.next.Value()); code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15); ASSERT(false && "unimp"); } + code.MTCTR(tmp_lr); } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h index 9b83d971d6..91aac3d942 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h @@ -15,6 +15,7 @@ struct alignas(16) StackLayout { std::array regs; std::array spill; u64 check_bit; + void* lr; }; static_assert(sizeof(StackLayout) % 16 == 0); From bfcdcdc145a03c69c89a5c343d7bc1dd96558692 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 10 Dec 2025 09:31:57 +0000 Subject: [PATCH 35/49] save more regs Signed-off-by: lizzie --- .../dynarmic/backend/ppc64/a32_interface.cpp | 5 ++- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 34 +++++++++++++++++++ .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 24 +++++-------- .../ppc64/emit_ppc64_data_processing.cpp | 1 - .../src/dynarmic/backend/ppc64/reg_alloc.h | 4 +-- .../src/dynarmic/backend/ppc64/stack_layout.h | 1 + 6 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index e7269582c3..1f01592005 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -5,10 +5,9 @@ #include #include -#include "dynarmic/common/assert.h" -#include -#include "dynarmic/common/common_types.h" +#include "dynarmic/common/assert.h" +#include "dynarmic/common/common_types.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/frontend/A32/translate/a32_translate.h" #include "dynarmic/interface/A32/config.h" diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 0f7e059110..1b24e1e9a8 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -8,6 +8,40 @@ namespace Dynarmic::Backend::PPC64 { +/* +https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#REG + +r0 Volatile register used in function prologs +r1 Stack frame pointer +r2 TOC pointer +r3 Volatile parameter and return value register +r4-r10 Volatile registers used for function parameters +r11 Volatile register used in calls by pointer and as an environment pointer for languages which require one +r12 Volatile register used for exception handling and glink code +r13 Reserved for use as system thread ID +r14-r31 Nonvolatile registers used for local variables + +f0 Volatile scratch register +f1-f4 Volatile floating point parameter and return value registers +f5-f13 Volatile floating point parameter registers +f14-f31 Nonvolatile registers + +LR Link register (volatile) +CTR Loop counter register (volatile) +XER Fixed point exception register (volatile) +FPSCR Floating point status and control register (volatile) + +CR0-CR1 Volatile condition code register fields +CR2-CR4 Nonvolatile condition code register fields +CR5-CR7 Volatile condition code register fields + +v0-v1 Volatile scratch registers +v2-v13 Volatile vector parameters registers +v14-v19 Volatile scratch registers +v20-v31 Non-volatile registers +vrsave Non-volatile 32-bit register +*/ + // Jit fn signature => (AXXAddressSpace& process, AXXJitState& thread_ctx, volatile u32* halt_reason) constexpr powah::GPR RPROCESS = powah::R3; constexpr powah::GPR RJIT = powah::R4; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 14be3d3aaa..0d4e6e93c5 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -1,27 +1,25 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#include "dynarmic/backend/ppc64/emit_ppc64.h" - #include #include #include #include -#include -#include "a32_core.h" -#include "a64_core.h" -#include "abi.h" +#include "dynarmic/backend/ppc64/emit_ppc64.h" +#include "dynarmic/backend/ppc64/a32_core.h" +#include "dynarmic/backend/ppc64/a64_core.h" +#include "dynarmic/backend/ppc64/abi.h" #include "dynarmic/backend/ppc64/a32_core.h" #include "dynarmic/backend/ppc64/a64_core.h" #include "dynarmic/backend/ppc64/abi.h" #include "dynarmic/backend/ppc64/emit_context.h" #include "dynarmic/backend/ppc64/reg_alloc.h" +#include "dynarmic/backend/ppc64/stack_layout.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" -#include "stack_layout.h" namespace Dynarmic::Backend::PPC64 { @@ -156,28 +154,24 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDisp } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { - auto const tmp_lr = ctx.reg_alloc.ScratchGpr(); auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.LD(tmp_lr, PPC64::RJIT, offsetof(StackLayout, lr)); - code.MFCTR(tmp_lr); if (ctx.emit_conf.a64_variant) { code.LI(tmp, terminal.next.Value()); code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); code.LD(tmp, PPC64::RJIT, offsetof(A64JitState, run_fn)); code.MTCTR(tmp); - for (u32 i = 0; i < 4; ++i) - code.STD(powah::GPR{3 + i}, powah::R1, -((GPR_ORDER.size() + i) * 8)); + for (u32 i = 0; i < 16; ++i) + code.STD(powah::GPR{14 + i}, powah::R1, -(offsetof(StackLayout, extra_regs) + (i * 8))); code.ADDIS(powah::R1, powah::R1, -sizeof(StackLayout)); code.BCTRL(); code.ADDI(powah::R1, powah::R1, sizeof(StackLayout)); - for (u32 i = 0; i < 4; ++i) - code.LD(powah::GPR{3 + i}, powah::R1, -((GPR_ORDER.size() + i) * 8)); + for (u32 i = 0; i < 16; ++i) + code.LD(powah::GPR{14 + i}, powah::R1, -(offsetof(StackLayout, extra_regs) + (i * 8))); } else { code.LI(tmp, terminal.next.Value()); code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15); ASSERT(false && "unimp"); } - code.MTCTR(tmp_lr); } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { 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 98a73f2028..24c677c9ff 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,7 +4,6 @@ #include #include -#include "abi.h" #include "dynarmic/common/assert.h" #include "dynarmic/backend/ppc64/a32_core.h" #include "dynarmic/backend/ppc64/abi.h" diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h index 00815cf902..a8122bfb92 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -10,10 +10,10 @@ #include #include -#include "dynarmic/common/assert.h" -#include "dynarmic/common/common_types.h" #include +#include "dynarmic/common/assert.h" +#include "dynarmic/common/common_types.h" #include "dynarmic/backend/ppc64/stack_layout.h" #include "dynarmic/backend/ppc64/hostloc.h" #include "dynarmic/ir/cond.h" diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h index 91aac3d942..fa4948b364 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h @@ -16,6 +16,7 @@ struct alignas(16) StackLayout { std::array spill; u64 check_bit; void* lr; + std::array extra_regs; }; static_assert(sizeof(StackLayout) % 16 == 0); From 61fd747cbd72b2e3e995c7ccfa730efd1e277b19 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 10 Dec 2025 09:58:20 +0000 Subject: [PATCH 36/49] fix stdu/ldu Signed-off-by: lizzie --- externals/powah/data2code.c | 9 +++++---- externals/powah/powah_gen_base.hpp | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/externals/powah/data2code.c b/externals/powah/data2code.c index 05b2fd4e1a..54bc17a1bf 100644 --- a/externals/powah/data2code.c +++ b/externals/powah/data2code.c @@ -41,10 +41,7 @@ int main(int argc, char *argv[]) { {"NS",4,4}, {"NU",4,4}, }; - #define OP_EXT ((i_opcode << 26) | (i_extopc << 1)) -#define OP_EXT_XS ((i_opcode << 26) | (i_extopc << 2)) - if (strchr(mem, '[') != NULL) *strchr(mem, '[') = '\0'; if (strchr(mem, '.') != NULL) *strchr(mem, '.') = '_'; *sec++ = '\0'; @@ -181,12 +178,15 @@ int main(int argc, char *argv[]) { "}\n" , mem, form, i_opcode << 26); } else if (!strcmp(form, "DS")) { +#define OP_EXT_DS ((i_opcode << 26) | (i_extopc << 0)) printf( "void %s(GPR const rt, GPR const ra, uint32_t d) {" " emit_%s(0x%08x, rt, ra, d >> 2); " "}\n" - , mem, form, OP_EXT); + , mem, form, OP_EXT_DS); +#undef OP_EXT_DS } else if (!strcmp(form, "XS")) { +#define OP_EXT_XS ((i_opcode << 26) | (i_extopc << 2)) /* HUGE DIFFERENCE DO NOT REMOVE */ printf( "void %s(GPR const rt, GPR const ra, uint32_t sh) {" @@ -198,6 +198,7 @@ int main(int argc, char *argv[]) { " emit_%s(0x%08x, rt, ra, sh, true); " "}\n" , mem, form, OP_EXT_XS); +#undef OP_EXT_XS } else if (!strcmp(form, "XL")) { if (!strcmp(mem, "BCLR")) { printf( diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index bba6bc9067..6f3f27f6f0 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -227,7 +227,7 @@ void LBZX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000ae, ra, rt void LD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000000, rt, ra, d >> 2); } void LDARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, ra, rt, rb, false); } void LDARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0000a8, ra, rt, rb, true); } -void LDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000002, rt, ra, d >> 2); } +void LDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000001, rt, ra, d >> 2); } void LDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, ra, rt, rb, false); } void LDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00006a, ra, rt, rb, true); } void LDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00002a, ra, rt, rb, false); } @@ -263,7 +263,7 @@ void LSWI(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, ra, rt, void LSWI_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0004aa, ra, rt, rb, true); } void LSWX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, ra, rt, rb, false); } void LSWX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00042a, ra, rt, rb, true); } -void LWA(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000004, rt, ra, d >> 2); } +void LWA(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xe8000002, rt, ra, d >> 2); } void LWARX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, ra, rt, rb, false); } void LWARX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000028, ra, rt, rb, true); } void LWAUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0002ea, ra, rt, rb, false); } @@ -403,7 +403,7 @@ void STBX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ae, ra, rt void STD(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000000, rt, ra, d >> 2); } void STDCX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, ra, rt, rb, false); } void STDCX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c0001ac, ra, rt, rb, true); } -void STDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000002, rt, ra, d >> 2); } +void STDU(GPR const rt, GPR const ra, uint32_t d) { emit_DS(0xf8000001, rt, ra, d >> 2); } void STDUX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, ra, rt, rb, false); } void STDUX_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00016a, ra, rt, rb, true); } void STDX(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c00012a, ra, rt, rb, false); } From e47aee12156749d212904baaae7546b682f99fdf Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 10 Dec 2025 10:41:45 +0000 Subject: [PATCH 37/49] the abi sucks Signed-off-by: lizzie --- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 9 +++++- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 28 +++++++++++-------- .../src/dynarmic/backend/ppc64/stack_layout.h | 7 +++-- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 1b24e1e9a8..51af0d73b7 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -55,9 +55,16 @@ constexpr powah::GPR ABI_PARAM4 = powah::R6; // See https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#REG constexpr std::initializer_list GPR_ORDER{ - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 + //6, 7, 8, 9, 10, 11, 12, //volatile + // r13 is thread-id + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 //non-volatile }; +constexpr std::initializer_list ABI_CALLEER_SAVED{ + powah::R3, powah::R4, powah::R5, powah::R6, + powah::R7, powah::R8, powah::R9, powah::R10, + powah::R11, powah::R12 +}; constexpr std::initializer_list ABI_CALLEE_SAVED{ powah::R14, powah::R15, powah::R16, powah::R17, powah::R18, powah::R19, powah::R20, powah::R21, diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 0d4e6e93c5..38e40af3f5 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -20,6 +20,7 @@ #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/microinstruction.h" #include "dynarmic/ir/opcodes.h" +#include "stack_layout.h" namespace Dynarmic::Backend::PPC64 { @@ -154,20 +155,16 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDisp } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { - auto const tmp = ctx.reg_alloc.ScratchGpr(); if (ctx.emit_conf.a64_variant) { + auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); code.LD(tmp, PPC64::RJIT, offsetof(A64JitState, run_fn)); code.MTCTR(tmp); - for (u32 i = 0; i < 16; ++i) - code.STD(powah::GPR{14 + i}, powah::R1, -(offsetof(StackLayout, extra_regs) + (i * 8))); - code.ADDIS(powah::R1, powah::R1, -sizeof(StackLayout)); code.BCTRL(); - code.ADDI(powah::R1, powah::R1, sizeof(StackLayout)); - for (u32 i = 0; i < 16; ++i) - code.LD(powah::GPR{14 + i}, powah::R1, -(offsetof(StackLayout, extra_regs) + (i * 8))); + code.LD(powah::R2, powah::R1, offsetof(StackLayout, sp)); } else { + auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15); ASSERT(false && "unimp"); @@ -225,10 +222,14 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf auto const start_offset = code.offset; ebi.entry_point = &code.base[start_offset]; + code.MFLR(powah::R0); + code.STD(powah::R0, powah::R1, offsetof(StackLayout, lr)); // Non-volatile saves - std::vector gpr_order{GPR_ORDER}; - for (size_t i = 0; i < gpr_order.size(); ++i) - code.STD(powah::GPR{gpr_order[i]}, powah::R1, -(i * 8)); + std::vector abi_callee_saved{ABI_CALLEE_SAVED}; + for (size_t i = 0; i < abi_callee_saved.size(); ++i) + code.STD(abi_callee_saved[i], powah::R1, -(8 + i * 8)); + code.STDU(powah::R1, powah::R1, -sizeof(StackLayout)); + code.STD(powah::R2, powah::R1, offsetof(StackLayout, sp)); for (auto iter = block.begin(); iter != block.end(); ++iter) { IR::Inst* inst = &*iter; @@ -257,8 +258,11 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf // auto const cycles_to_add = block.CycleCount(); EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); - for (size_t i = 0; i < gpr_order.size(); ++i) - code.LD(powah::GPR{gpr_order[i]}, powah::R1, -(i * 8)); + code.ADDI(powah::R1, powah::R1, sizeof(StackLayout)); + code.LD(powah::R0, powah::R1, offsetof(StackLayout, lr)); + code.MTLR(powah::R0); + for (size_t i = 0; i < abi_callee_saved.size(); ++i) + code.LD(abi_callee_saved[i], powah::R1, -(8 + i * 8)); code.BLR(); code.ApplyRelocs(); diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h index fa4948b364..d672ccea6b 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h @@ -12,11 +12,12 @@ namespace Dynarmic::Backend::PPC64 { constexpr size_t SpillCount = 16; struct alignas(16) StackLayout { - std::array regs; + u64 resv0; //0 + u64 resv1; //8 + u64 lr; //16 + u64 sp; //24 std::array spill; u64 check_bit; - void* lr; - std::array extra_regs; }; static_assert(sizeof(StackLayout) % 16 == 0); From 9b0008008a6c630c8a45367efe732c29bee1c884 Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 8 Jan 2026 07:51:09 +0000 Subject: [PATCH 38/49] move docs inline, add data.txt + altivec_data.txt --- docs/dynarmic/PowerPC.md | 8 ++ docs/dynarmic/README.md | 1 + externals/powah/altivec_data.txt | 145 ++++++++++++++++++++ externals/powah/build.sh | 3 + externals/powah/data.txt | 222 +++++++++++++++++++++++++++++++ 5 files changed, 379 insertions(+) create mode 100644 docs/dynarmic/PowerPC.md create mode 100644 externals/powah/altivec_data.txt create mode 100755 externals/powah/build.sh create mode 100644 externals/powah/data.txt diff --git a/docs/dynarmic/PowerPC.md b/docs/dynarmic/PowerPC.md new file mode 100644 index 0000000000..d625bb30fa --- /dev/null +++ b/docs/dynarmic/PowerPC.md @@ -0,0 +1,8 @@ +# PowerPC 64 backend + +The ppc64 backend currently only supports the little endian variant, with big endian support being experimental for the time being. Additionally only A32 is supported (for now). + +- Flag handling: Flags are emulated via software, while there may be some funny tricks with the CTR, I'd rather not bother - plus it's widely known that those instructions are not nice on real metal - so I would rather take the i-cache cost. +- 128-bit atomics: No 128-bit atomic support is provided, this may cause wrong or erroneous execution in some contexts. + +To handle endianess differences all 16/32/64-bit loads and stores to the "emulated memory" are byteswapped beforehand. diff --git a/docs/dynarmic/README.md b/docs/dynarmic/README.md index 521f78ee7c..5d5a451961 100644 --- a/docs/dynarmic/README.md +++ b/docs/dynarmic/README.md @@ -12,6 +12,7 @@ The only supported host architectures are x86-64, PowerPC 64, and AArch64. There See [an example usage](../../src/dynarmic/tests/print_info.cpp). Design documentation can be found at [./Design.md](./Design.md). +PowerPC design documentation can be found at [./PowerPC](./PowerPC.md). Alternatives to Dynarmic ------------------------ diff --git a/externals/powah/altivec_data.txt b/externals/powah/altivec_data.txt new file mode 100644 index 0000000000..d5cdf4bc92 --- /dev/null +++ b/externals/powah/altivec_data.txt @@ -0,0 +1,145 @@ +vabsdub,VX,04,1027 +vabsduh,VX,04,1091 +vabsduw,VX,04,1155 +vaddcuw,VX,04,384 +vaddfp,VX,04,10 +vaddsbs,VX,04,768 +vaddshs,VX,04,832 +vaddsws,VX,04,896 +vaddubm,VX,04,0 +vaddubs,VX,04,512 +vadduhm,VX,04,64 +vadduhs,VX,04,576 +vadduwm,VX,04,128 +vadduws,VX,04,640 +vand,VX,04,1028 +vandc,VX,04,1092 +vavgsb,VX,04,1282 +vavgsh,VX,04,1346 +vavgsw,VX,04,1410 +vavgub,VX,04,1026 +vavguh,VX,04,1090 +vavguw,VX,04,1154 +vcfsx,VDU,04842 +vcfux,VDU,04778 +vcmpbfp,VXR,04,966 +vcmpeqfp,VXR,04,198 +vcmpequb,VXR,04,6 +vcmpequh,VXR,04,70 +vcmpequw,VXR,04,134 +vcmpgefp,VXR,04,454 +vcmpgtfp,VXR,04,710 +vcmpgtsb,VXR,04,774 +vcmpgtsh,VXR,04,838 +vcmpgtsw,VXR,04,902 +vcmpgtub,VXR,04,518 +vcmpgtuh,VXR,04,582 +vcmpgtuw,VXR,04,646 +vctsxs,VDU,04970 +vctuxs,VDU,04906 +vexptefp,VY,04,394 +vlogefp,VY,04,458 +vmaddfp,VXC,46 +vmaxfp,VX,04,1034 +vmaxsb,VX,04,258 +vmaxsh,VX,04,322 +vmaxsw,VX,04,386 +vmaxub,VX,04,2 +vmaxuh,VX,04,66 +vmaxuw,VX,04,130 +vmhaddshs,VXC,32 +vmhraddshs,VXC,33 +vminfp,VX,04,1098 +vminsb,VX,04,770 +vminsh,VX,04,834 +vminsw,VX,04,898 +vminub,VX,04,514 +vminuh,VX,04,578 +vminuw,VX,04,642 +vmladduhm,VXC,34 +vmrghb,VX,04,12 +vmrghh,VX,04,76 +vmrghw,VX,04,140 +vmrglb,VX,04,268 +vmrglh,VX,04,332 +vmrglw,VX,04,396 +vmsummbm,VXC,37 +vmsumshm,VXC,40 +vmsumshs,VXC,41 +vmsumubm,VXC,36 +vmsumuhm,VXC,38 +vmsumuhs,VXC,39 +vmulesb,VX,04,776 +vmulesh,VX,04,840 +vmuleub,VX,04,520 +vmuleuh,VX,04,584 +vmulosb,VX,04,264 +vmulosh,VX,04,328 +vmuloub,VX,04,8 +vmulouh,VX,04,72 +vnmsubfp,VXC,47 +vnor,VX,04,1284 +vor,VX,04,1156 +vperm,VXC,43 +vpkpx,VX,04,782 +vpkshss,VX,04,398 +vpkshus,VX,04,270 +vpkswss,VX,04,462 +vpkswus,VX,04,334 +vpkuhum,VX,04,14 +vpkuhus,VX,04,142 +vpkuwum,VX,04,78 +vpkuwus,VX,04,206 +vrefp,VY,04,266 +vrfim,VY,04,714 +vrfin,VY,04,522 +vrfip,VY,04,650 +vrfiz,VY,04,586 +vrlb,VX,04,4 +vrlh,VX,04,68 +vrlw,VX,04,132 +vrsqrtefp,VY,04,330 +vsel,VXC,42 +vsl,VX,04,452 +vslb,VX,04,260 +vsldoi,VX,04,/ SH 44 +vslh,VX,04,324 +vslo,VX,04,1036 +vslw,VX,04,388 +vspltb,VU,04,524 +vsplth,VU,04,588 +vspltisb,VS,04,780 +vspltish,VS,04,844 +vspltisw,VS,04,908 +vspltw,VSU,04,652 +vsr,VX,04,708 +vsrab,VX,04,772 +vsrah,VX,04,836 +vsraw,VX,04,900 +vsrb,VX,04,516 +vsrh,VX,04,580 +vsro,VX,04,1100 +vsrw,VX,04,644 +vsubcuw,VX,04,1408 +vsubfp,VX,04,74 +vsubsbs,VX,04,1792 +vsubshs,VX,04,1856 +vsubsws,VX,04,1920 +vsububm,VX,04,1024 +vsububs,VX,04,1536 +vsubuhm,VX,04,1088 +vsubuhs,VX,04,1600 +vsubuwm,VX,04,1152 +vsubuws,VX,04,1664 +vsumsws,VX,04,1928 +vsum2sws,VX,04,1672 +vsum4sbs,VX,04,1800 +vsum4shs,VX,04,1608 +vsum4ubs,VX,04,1544 +vupkhpx,VY,04,846 +vupkhsb,VY,04,526 +vupkhsh,VY,04,590 +vupklpx,VY,04,974 +vupklsb,VY,04,654 +vupklsh,VY,04,718 +vxor,VX,04,122 \ No newline at end of file diff --git a/externals/powah/build.sh b/externals/powah/build.sh new file mode 100755 index 0000000000..d629a6b2e1 --- /dev/null +++ b/externals/powah/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +$CC data2code.c -o data2code && ./data2code data.txt >powah_gen_base.hpp +$CC --target=powerpc64le test.S -c -o test && objdump -SC test diff --git a/externals/powah/data.txt b/externals/powah/data.txt new file mode 100644 index 0000000000..c3a9767fb3 --- /dev/null +++ b/externals/powah/data.txt @@ -0,0 +1,222 @@ +add[o][.],Add,XO,31,266 +addc[o][.],Add Carrying,XO,31,10 +adde[o][.],Add Extended,XO,31,138 +addi,Add Immediate,D,14, +addic,Add Immediate Carrying,D,12, +addic.,Add Immediate Carrying and Record,D,13, +addis,Add Immediate Shifted,D,15, +addme[o][.],Add to Minus One Extended,XO,31,234 +addze[o][.],Add to Zero Extended,XO,31,202 +and[.],AND,X,31,28 +andc[.],AND with Complement,X,31,60 +andi.,AND Immediate,D,28, +andis.,AND Immediate Shifted,D,29, +b[l][a],Branch,I,18, +bc[l][a],Branch Conditional,B,16, +bcctr[l],Branch Conditional to Count Register,XL,19,528 +bclr[l],Branch Conditional Link Register,XL,19,16 +cmp,Compare,X,31,0 +cmpi,Compare Immediate,D,11, +cmpl,Compare Logical,X,31,32 +cmpli,Compare Logical Immediate,D,10, +cntlzd,Count Leading Zeros Doubleword,X,31,58 +cntlzw[.],Count Leading Zeros Word,X,31,26 +crand,Condition Register AND,XL,19,257 +crandc,Condition Register AND with Complement,XL,19,129 +creqv,Condition Register Equivalent,XL,19,289 +crnand,Condition Register NAND,XL,19,225 +crnor,Condition Register NOR,XL,19,33 +cror,Condition Register OR,XL,19,449 +crorc,Condition Register OR with Complement,XL,19,417 +crxor,Condition Register XOR,XL,19,193 +dcbf,Data Cache Block Flush,X,31,86 +dcbi,Data Cache Block Invalidate,X,31,470 +dcbst,Data Cache Block Store,X,31,54 +dcbt,Data Cache Block Touch,X,31,278 +dcbtst,Data Cache Block Touch for Store,X,31,246 +dcbz,Data Cache Block Set to Zero,X,31,1014 +divd,Divide Doubleword,XO,31,489 +divdu,Divide Doubleword Unsigned,XO,31,457 +divw[o][.],Divide Word,XO,31,491 +divwu[o][.],Divide Word Unsigned,XO,31,459 +eciwx,External Control in Word Indexed (opt.),X,31,310 +ecowx,External Control out Word Indexed (opt.),X,31,438 +eieio,Enforce In-order Execution of I/O,X,31,854 +eqv[.],Equivalent,X,31,284 +extsb[.],Extend Sign Byte,X,31,954 +extsh[.],Extend Sign Halfword,XO,31,922 +extsw,Extend Sign Word,X,31,986 +fabs[.],Floating Absolute Value,X,63,264 +fadd[.],Floating Add,A,63,21 +fadds[.],Floating Add Single,A,59,21 +fcfid,Floating Convert from Integer Doubleword,X,63,846 +fcmpo,Floating Compare Ordered,X,63,32 +fcmpu,Floating Compare Unordered,XL,63,0 +fctid,Floating Convert to Integer Doubleword,X,63,814 +fctidz,Floating Convert to Integer Doubleword with Round Toward Zero,X,63,815 +fctiw[.],Floating Convert to Integer Word,X,63,14 +fctiwz[.],Floating Convert to Integer Word with Round to Zero,XL,63,15 +fdiv[.],Floating Divide,A,63,18 +fdivs[.],Floating Divide Single,A,59,18 +fmadd[.],Floating Multiply-Add,A,63,29 +fmadds[.],Floating Multiply-Add Single,A,59,29 +fmr[.],Floating Move Register,X,63,72 +fmsub[.],Floating Multiply-Subtract,A,63,28 +fmsubs[.],Floating Multiply-Subtract Single,A,59,28 +fmul[.],Floating Multiply,A,63,25 +fmuls[.],Floating Multiply Single,A,59,25 +fnabs[.],Floating Negative Absolute Value,X,63,136 +fneg[.],Floating Negate,X,63,40 +fnmadd[.],Floating Negative Multiply-Add,A,63,31 +fnmadds[.],Floating Negative Multiply-Add Single,A,59,31 +fnmsub[.],Floating Negative Multiply-Subtract,A,63,30 +fnmsubs[.],Floating Negative Multiply-Subtract Single,A,59,30 +fres[.],Floating Reciprocal Estimate Single (optional),A,59,24 +frsp[.],Floating Round to Single Precision,X,63,12 +frsqrte[.],Floating Reciprocal Square Root Estimate (optional),A,63,26 +fsel[.],Floating-Point Select (optional),A,63,23 +fsub[.],Floating Subtract,A,63,20 +fsubs[.],Floating Subtract Single,A,59,20 +icbi,Instruction Cache Block Invalidate,X,31,982 +isync,Instruction Synchronize,X,19,150 +lbz,Load Byte and Zero,D,34, +lbzu,Load Byte and Zero with Update,D,35, +lbzux,Load Byte and Zero with Update Indexed,X,31,119 +lbzx,Load Byte and Zero Indexed,X,31,87 +ld,Load Doubleword,DS,58,0 +ldarx,Load Doubleword and Reserve Indexed,X,31,84 +ldu,Load Doubleword with Update,DS,58,1 +ldux,Load Doubleword with Update Indexed,X,31,53 +ldx,Load Doubleword Indexed,X,31,21 +lfd,Load Floating-Point Double,D,50, +lfdu,Load Floating-Point Double with Update,D,51, +lfdux,Load Floating-Point Double with Update Indexed,X,31,631 +lfdx,Load Floating-Point Double Indexed,X,31,599 +lfs,Load Floating-Point Single,D,48, +lfsu,Load Floating-Point Single with Update,D,49, +lfsux,Load Floating-Point Single with Update Indexed,X,31,567 +lfsx,Load Floating-Point Single Indexed,X,31,535 +lha,Load Half Algebraic,D,42, +lhau,Load Half Algebraic with Update,D,43, +lhaux,Load Half Algebraic with Update Indexed,X,31,375 +lhax,Load Half Algebraic Indexed,X,31,343 +lhbrx,Load Half Byte-Reversed Indexed,X,31,790 +lhz,Load Half and Zero,D,40, +lhzu,Load Half and Zero with Update,D,41, +lhzux,Load Half and Zero with Update Indexed,X,31,331 +lhzx,Load Half and Zero Indexed,X,31,279 +lmw,Load Multiple Word,D,46, +lswi,Load String Word Immediate,X,31,597 +lswx,Load String Word Indexed,X,31,533 +lwa,Load Word Algebraic,DS,58,2 +lwarx,Load Word and Reserve Indexed,X,31,20 +lwaux,Load Word Algebraic with Update Indexed,X,31,373 +lwax,Load Word Algebraic Indexed,X,31,341 +lwbrx,Load Word Byte-Reversed Indexed,X,31,534 +lwz,Load Word and Zero,D,32, +lwzu,Load Word with Zero Update,D,33, +lwzux,Load Word and Zero with Update Indexed,X,31,55 +lwzx,Load Word and Zero Indexed,X,31,23 +mcrf,Move Condition Register Field,XL,19,0 +mcrfs,Move to Condition Register from FPSCR,X,63,64 +mcrxr,Move to Condition Register from XER,X,31,512 +mfcr,Move from Condition Register,X,31,19 +mffs[.],Move from FPSCR,X,63,583 +mfmsr,Move from Machine State Register,X,31,83 +mfspr,Move from Special-Purpose Register,X,31,339 +mfsr,Move from Segment Register,X,31,595 +mfsrin,Move from Segment Register Indirect,X,31,659 +mtcrf,Move to Condition Register Fields,XFX,31,144 +mtfsb0[.],Move to FPSCR Bit 0,X,63,70 +mtfsb1[.],Move to FPSCR Bit 1,X,63,38 +mtfsf[.],Move to FPSCR Fields,XFL,63,711 +mtfsfi[.],Move to FPSCR Field Immediate,X,63,134 +mtmsr,Move to Machine State Register,X,31,146 +mtspr,Move to Special-Purpose Register,X,31,467 +mtsr,Move to Segment Register,X,31,210 +mtsrin,Move to Segment Register Indirect,X,31,242 +mulhd,Multiply High Doubleword,XO,31,73 +mulhdu,Multiply High Doubleword Unsigned,XO,31,9 +mulhw[.],Multiply High Word,XO,31,75 +mulhwu[.],Multiply High Word Unsigned,XO,31,11 +mulld,Multiply Low Doubleword,XO,31,233 +mulli,Multiply Low Immediate,D,07, +mullw[o][.],Multiply Low Word,XO,31,235 +nand[.],NAND,X,31,476 +neg[o][.],Negate,XO,31,104 +nor[.],NOR,X,31,124 +or[.],OR,X,31,444 +orc[.],OR with Complement,X,31,412 +ori,OR Immediate,D,24, +oris,OR Immediate Shifted,D,25, +rfi,Return from Interrupt,X,19,50 +rldcl,Rotate Left Doubleword then Clear Left,MDS,30,8 +rldcr,Rotate Left Doubleword then Clear Right,MDS,30,9 +rldic,Rotate Left Doubleword Immediate then Clear,MD,30,2 +rldicl,Rotate Left Doubleword Immediate then Clear Left,MD,30,0 +rldicr,Rotate Left Doubleword Immediate then Clear Right,MD,30,1 +rldimi,Rotate Left Doubleword Immediate then Mask Insert,MD,30,3 +rlwimi[.],Rotate Left Word Immediate then Mask Insert,M,20, +rlwinm[.],Rotate Left Word Immediate then AND with Mask,M,21, +rlwnm[.],Rotate Left Word then AND with Mask,M,23, +sc,System Call,SC,17, +si,Subtract Immediate,D,12, +si.,Subtract Immediate and Record,D,13, +slbia,SLB Invalidate All,X,31,498 +slbie,SLB Invalidate Entry,X,31,434 +sld,Shift Left Doubleword,X,31,27 +slw[.],Shift Left Word,X,31,24 +srad,Shift Right Algebraic Doubleword,X,31,794 +sradi,Shift Right Algebraic Doubleword Immediate,XS,31,413 +srd,Shift Right Doubleword,X,31,539 +sraw[.],Shift Right Algebraic Word,X,31,792 +srawi[.],Shift Right Algebraic Word Immediate,X,31,824 +srw[.],Shift Right Word,X,31,536 +stb,Store Byte,D,38, +stbu,Store Byte with Update,D,39, +stbux,Store Byte with Update Indexed,X,31,247 +stbx,Store Byte Indexed,X,31,215 +std,Store Doubleword,DS,62,0 +stdcx,Store Doubleword Conditional Indexed,X,31,214 +stdu,Store Doubleword with Update,DS,62,1 +stdux,Store Doubleword with Update Indexed,X,31,181 +stdx,Store Doubleword Indexed,X,31,149 +stfd,Store Floating-Point Double,D,54, +stfdu,Store Floating-Point Double with Update,D,55, +stfdux,Store Floating-Point Double with Update Indexed,X,31,759 +stfdx,Store Floating-Point Double Indexed,X,31,727 +stfiwx,Store Floating-Point as Integer Word Indexed (optional),X,31,983 +stfs,Store Floating-Point Single,D,52, +stfsu,Store Floating-Point Single with Update,D,53, +stfsux,Store Floating-Point Single with Update Indexed,X,31,695 +stfsx,Store Floating-Point Single Indexed,X,31,663 +sth,Store Half,D,44, +sthbrx,Store Half Byte-Reverse Indexed,X,31,918 +sthu,Store Half with Update,D,45, +sthux,Store Half with Update Indexed,X,31,439 +sthx,Store Half Indexed,X,31,407 +stmw,Store Multiple Word,D,47, +stswi,Store String Word Immediate,X,31,725 +stswx,Store String Word Indexed,X,31,661 +stw,Store,D,36, +stwbrx,Store Word Byte-Reversed Indexed,X,31,662 +stwcx.,Store Word Conditional Indexed,X,31,150 +stwu,Store Word with Update,D,37, +stwux,Store Word with Update Indexed,X,31,183 +stwx,Store Word Indexed,X,31,151 +subf[o][.],Subtract from,XO,31,40 +subfc[o][.],Subtract from Carrying,XO,31,08 +subfe[o][.],Subtract from Extended,XO,31,136 +subfic,Subtract from Immediate Carrying,D,08, +subfme[o][.],Subtract from Minus One Extended,XO,31,232 +subfze[o][.],Subtract from Zero Extended,XO,31,200 +sync,Synchronize,X,31,598 +td,Trap Doubleword,X,31,68 +tdi,Trap Doubleword Immediate,D,2, +tlbie,Translation Look-aside Buffer Invalidate Entry (optional),X,31,306 +tlbsync,Translation Look-aside Buffer Synchronize (optional),X,31,566 +tw,Trap Word,X,31,04 +twi,Trap Word Immediate,D,03, +xor[.],XOR,X,31,316 +xori,XOR Immediate,D,26, +xoris,XOR Immediate Shift,D,27, From 4e1f277432a4da5d229691c09fb269ee6d9c2af3 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 20:00:02 +0000 Subject: [PATCH 39/49] emission focused on branch/bctr --- externals/powah/powah_emit.hpp | 1 + .../src/dynarmic/backend/ppc64/a32_core.h | 1 - .../dynarmic/backend/ppc64/a32_interface.cpp | 1 - .../src/dynarmic/backend/ppc64/a64_core.h | 1 - .../dynarmic/backend/ppc64/a64_interface.cpp | 11 ++- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 6 +- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 77 ++++++++++--------- .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 2 +- .../src/dynarmic/backend/ppc64/reg_alloc.h | 7 +- .../src/dynarmic/backend/ppc64/stack_layout.h | 5 -- 10 files changed, 57 insertions(+), 55 deletions(-) diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 4b6f1d72e6..5af323ec5d 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -373,6 +373,7 @@ struct Context { void MFCTR(GPR const rt) { MFSPR(powah::GPR{9}, rt, powah::GPR{0}); } void MTCTR(GPR const rt) { MTSPR(powah::GPR{9}, rt, powah::GPR{0}); } void BCTRL() { base[offset++] = 0x4e800421; } //BCCTRL(R0, CR0, R0); + void BCTR() { base[offset++] = 0x4e800420; } //BCCTR(R0, CR0, R0); // TODO: PowerPC 11 stuff void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index 19816d4c93..6545a1af4e 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -23,7 +23,6 @@ struct A32JitState { u32 cpsr_nzcv = 0; u32 fpscr = 0; u8 check_bit = 0; - void* run_fn = nullptr; IR::LocationDescriptor GetLocationDescriptor() const { return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index 1f01592005..c99f92dc29 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -73,7 +73,6 @@ struct A32Core final { auto const loc = thread_ctx.GetLocationDescriptor(); auto const entry = process.GetOrEmit(loc); using CodeFn = HaltReason (*)(A32AddressSpace*, A32JitState*, volatile u32*, void*); - thread_ctx.run_fn = (void*)&A32Core::Run; return (CodeFn(entry))(&process, &thread_ctx, halt_reason, reinterpret_cast(&A32Core::Run)); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index 0d5fc6eace..a9226759dd 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -29,7 +29,6 @@ struct A64JitState { u32 fpsr = 0; volatile u32 halt_reason = 0; u8 check_bit = 0; - void* run_fn = nullptr; IR::LocationDescriptor GetLocationDescriptor() const { const u64 fpcr_u64 = u64(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index f07b8ef1be..7573531f8d 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -71,13 +71,18 @@ struct A64AddressSpace final { ankerl::unordered_dense::map block_infos; }; +__attribute__((noinline)) HaltReason test_thunk(A64AddressSpace* a, A64JitState* b, volatile u32* c, void* d) { + printf("%p,%p,%p,%p\n", a, b, c, d); + return HaltReason::UserDefined2; +} + struct A64Core final { static HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { const auto loc = thread_ctx.GetLocationDescriptor(); const auto entry = process.GetOrEmit(loc); - using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void*); - thread_ctx.run_fn = (void*)&A64Core::Run; - return (CodeFn(entry))(&process, &thread_ctx, halt_reason, reinterpret_cast(&A64Core::Run)); + using AbstractCodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void (*fn)()); + using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, AbstractCodeFn fn); + return (CodeFn(entry))(&process, &thread_ctx, halt_reason, AbstractCodeFn(test_thunk)); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 51af0d73b7..cc2fd63a08 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -46,7 +46,10 @@ vrsave Non-volatile 32-bit register constexpr powah::GPR RPROCESS = powah::R3; constexpr powah::GPR RJIT = powah::R4; constexpr powah::GPR RHALTREASON = powah::R5; -constexpr powah::GPR RNZCV = powah::R31; +constexpr powah::GPR RTOCPTR = powah::R6; +// temporals +constexpr powah::GPR RNZCV = powah::R7; +constexpr powah::GPR RCHECKBIT = powah::R8; constexpr powah::GPR ABI_PARAM1 = powah::R3; constexpr powah::GPR ABI_PARAM2 = powah::R4; @@ -55,7 +58,6 @@ constexpr powah::GPR ABI_PARAM4 = powah::R6; // See https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#REG constexpr std::initializer_list GPR_ORDER{ - //6, 7, 8, 9, 10, 11, 12, //volatile // r13 is thread-id 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 //non-volatile }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 38e40af3f5..d58fe5003d 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -159,10 +159,11 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock te auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); - code.LD(tmp, PPC64::RJIT, offsetof(A64JitState, run_fn)); + code.LD(tmp, PPC64::RTOCPTR, 0); code.MTCTR(tmp); - code.BCTRL(); - code.LD(powah::R2, powah::R1, offsetof(StackLayout, sp)); + code.LD(powah::R2, PPC64::RTOCPTR, 8); + code.LD(powah::R11, PPC64::RTOCPTR, 16); + code.BCTR(); } else { auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); @@ -191,7 +192,7 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckBit ter powah::Label const l_else = code.DefineLabel(); powah::Label const l_end = code.DefineLabel(); auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.LD(tmp, powah::R1, offsetof(StackLayout, check_bit)); + code.MR(tmp, PPC64::RCHECKBIT); code.CMPLDI(tmp, 0); code.BEQ(powah::CR0, l_else); // CheckBit == 1 @@ -219,51 +220,53 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf RegAlloc reg_alloc{code}; EmitContext ctx{block, reg_alloc, emit_conf, ebi}; + size_t const stack_size = 112 + ABI_CALLEE_SAVED.size() * 8; auto const start_offset = code.offset; ebi.entry_point = &code.base[start_offset]; + if (!block.empty()) { + code.MFLR(powah::R0); + code.STD(powah::R0, powah::R1, 16); + // Non-volatile saves + std::vector gp_regs{ABI_CALLEE_SAVED}; + for (size_t i = 0; i < gp_regs.size(); ++i) + code.STD(gp_regs[i], powah::R1, -int32_t(gp_regs.size() - i) * 8); + code.STDU(powah::R1, powah::R1, uint32_t(-stack_size)); + code.STD(powah::R2, powah::R1, 40); - code.MFLR(powah::R0); - code.STD(powah::R0, powah::R1, offsetof(StackLayout, lr)); - // Non-volatile saves - std::vector abi_callee_saved{ABI_CALLEE_SAVED}; - for (size_t i = 0; i < abi_callee_saved.size(); ++i) - code.STD(abi_callee_saved[i], powah::R1, -(8 + i * 8)); - code.STDU(powah::R1, powah::R1, -sizeof(StackLayout)); - code.STD(powah::R2, powah::R1, offsetof(StackLayout, sp)); - - for (auto iter = block.begin(); iter != block.end(); ++iter) { - IR::Inst* inst = &*iter; - switch (inst->GetOpcode()) { + for (auto iter = block.begin(); iter != block.end(); ++iter) { + IR::Inst* inst = &*iter; + switch (inst->GetOpcode()) { #define OPCODE(name, type, ...) \ - case IR::Opcode::name: \ - EmitIR(code, ctx, inst); \ - break; + case IR::Opcode::name: \ + EmitIR(code, ctx, inst); \ + break; #define A32OPC(name, type, ...) \ - case IR::Opcode::A32##name: \ - EmitIR(code, ctx, inst); \ - break; + case IR::Opcode::A32##name: \ + EmitIR(code, ctx, inst); \ + break; #define A64OPC(name, type, ...) \ - case IR::Opcode::A64##name: \ - EmitIR(code, ctx, inst); \ - break; + case IR::Opcode::A64##name: \ + EmitIR(code, ctx, inst); \ + break; #include "dynarmic/ir/opcodes.inc" #undef OPCODE #undef A32OPC #undef A64OPC - default: - UNREACHABLE(); + default: + UNREACHABLE(); + } } + + // auto const cycles_to_add = block.CycleCount(); + code.ADDI(powah::R1, powah::R1, stack_size); + for (size_t i = 0; i < gp_regs.size(); ++i) + code.LD(gp_regs[i], powah::R1, -int32_t(gp_regs.size() - i) * 8); + code.LD(powah::R0, powah::R1, 16); + code.MTLR(powah::R0); + EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); + } else { + EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); } - - // auto const cycles_to_add = block.CycleCount(); - EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); - - code.ADDI(powah::R1, powah::R1, sizeof(StackLayout)); - code.LD(powah::R0, powah::R1, offsetof(StackLayout, lr)); - code.MTLR(powah::R0); - for (size_t i = 0; i < abi_callee_saved.size(); ++i) - code.LD(abi_callee_saved[i], powah::R1, -(8 + i * 8)); - code.BLR(); code.ApplyRelocs(); /* 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 b341373d61..efe7c734fe 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -19,7 +19,7 @@ namespace Dynarmic::Backend::PPC64 { template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - code.STD(value, powah::R1, offsetof(StackLayout, check_bit)); + code.MR(PPC64::RCHECKBIT, value); } template<> diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h index a8122bfb92..ff95193ee7 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -49,15 +49,15 @@ struct RegAlloc; /// this basically means that we can use temporals and not need to go thru /// any weird deallocation stuffs :) template struct RegLock { - inline RegLock(RegAlloc& reg_alloc, T const value) noexcept + constexpr RegLock(RegAlloc& reg_alloc, T const value) noexcept : reg_alloc{reg_alloc} , value{value} { SetLock(true); } inline ~RegLock() noexcept { SetLock(false); } - operator T const&() { return value; } - operator T() const { return value; } + constexpr operator T const&() noexcept { return value; } + constexpr operator T() const noexcept { return value; } inline void SetLock(bool v) noexcept; RegAlloc& reg_alloc; const T value; @@ -94,7 +94,6 @@ private: std::array fprs; std::array vprs; std::array spills; - uint32_t lru_counter = 0; }; template<> inline void RegLock::SetLock(bool v) noexcept { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h index d672ccea6b..ec5334154b 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h @@ -12,12 +12,7 @@ namespace Dynarmic::Backend::PPC64 { constexpr size_t SpillCount = 16; struct alignas(16) StackLayout { - u64 resv0; //0 - u64 resv1; //8 - u64 lr; //16 - u64 sp; //24 std::array spill; - u64 check_bit; }; static_assert(sizeof(StackLayout) % 16 == 0); From b30e68a599dd68d6d47d9e726973a65766f6a646 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 14 Jan 2026 20:00:25 +0000 Subject: [PATCH 40/49] cross compile insn, exclude x11 from headless --- docs/CrossCompile.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CrossCompile.md b/docs/CrossCompile.md index d0b0732310..7eeb4b7b67 100644 --- a/docs/CrossCompile.md +++ b/docs/CrossCompile.md @@ -210,7 +210,9 @@ This is a guide for FreeBSD users mainly. Now you got a PowerPC sysroot - quickly decompress it somewhere, say `/home/user/opt/powerpc64le`. Create a toolchain file, for example `powerpc64le-toolchain.cmake`; always [consult the manual](https://man.freebsd.org/cgi/man.cgi?query=cmake-toolchains&sektion=7&manpath=FreeBSD+13.2-RELEASE+and+Ports). -There is a script to automatically do all of this under `./tools/setup-cross-sysroot.sh` +There is a script to automatically do all of this under `./tools/setup-cross-sysroot.sh`. + +Remember to add `-mabi=elfv1` to `CFLAGS`/`CXXFLAGS` otherwise the program will crash. Specify: From 2cc7a94053238ec52b26e6f966495eceb0d3e69d Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 30 Jan 2026 19:22:04 +0000 Subject: [PATCH 41/49] update loicense --- CMakeModules/GentooCross.cmake | 2 +- externals/powah/CMakeLists.txt | 2 +- externals/powah/build.sh | 3 +++ externals/powah/tests.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/code_block.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 2 +- .../src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp | 2 +- .../src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h | 2 +- src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp | 2 +- src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h | 2 +- tools/setup-cross-sysroot.sh | 2 +- 27 files changed, 29 insertions(+), 26 deletions(-) diff --git a/CMakeModules/GentooCross.cmake b/CMakeModules/GentooCross.cmake index 69e9afc69b..7daff8ea2d 100644 --- a/CMakeModules/GentooCross.cmake +++ b/CMakeModules/GentooCross.cmake @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later set(CROSS_TARGET "powerpc64le" CACHE STRING "Cross-compilation target (aarch64, powerpc64le, riscv64, etc)") diff --git a/externals/powah/CMakeLists.txt b/externals/powah/CMakeLists.txt index f5301b2946..4d768251b7 100644 --- a/externals/powah/CMakeLists.txt +++ b/externals/powah/CMakeLists.txt @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later add_library(powah INTERFACE) diff --git a/externals/powah/build.sh b/externals/powah/build.sh index d629a6b2e1..d3420c70b6 100755 --- a/externals/powah/build.sh +++ b/externals/powah/build.sh @@ -1,3 +1,6 @@ #!/bin/sh + +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later $CC data2code.c -o data2code && ./data2code data.txt >powah_gen_base.hpp $CC --target=powerpc64le test.S -c -o test && objdump -SC test diff --git a/externals/powah/tests.cpp b/externals/powah/tests.cpp index 43fff657c8..ce3ea9933c 100644 --- a/externals/powah/tests.cpp +++ b/externals/powah/tests.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index 6545a1af4e..d287f95671 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index c99f92dc29..54e334bbbe 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index a9226759dd..d5aa0b3370 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 7573531f8d..29dc61ef62 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index cc2fd63a08..5924a5c057 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h b/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h index 25a17a400d..c57e34baec 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h index 25c1562785..d8e11e3591 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index d58fe5003d..89eb3f0401 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h index b7e68b71ed..4eed600905 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp index 2b9c77f95c..cd1d4d1f06 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a32.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include 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 efe7c734fe..cd0b4aa1cf 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include 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 24c677c9ff..dd01ee07e5 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 @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp index a8bb06864e..b893a7cc88 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_floating_point.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp index 7db5dbd992..ce1fbf09b4 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_misc.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp index d53b804d73..b6c376345c 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_vector.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp index 9fcb0f0629..3910662df2 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include "dynarmic/interface/exclusive_monitor.h" diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h index 17b1f71517..285bf941a5 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp index 2aa02777f9..8a89941ed9 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h index ff95193ee7..910abf72cb 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h index ec5334154b..55608cd658 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp index 8ce6d40021..759eda74dd 100644 --- a/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #include diff --git a/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h index d2e78cc66f..460024053c 100644 --- a/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h +++ b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #pragma once diff --git a/tools/setup-cross-sysroot.sh b/tools/setup-cross-sysroot.sh index 746197d911..d27ff44481 100755 --- a/tools/setup-cross-sysroot.sh +++ b/tools/setup-cross-sysroot.sh @@ -1,5 +1,5 @@ #!/bin/sh -e -# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later die() { From 9c0d41b55f8624cbb770f6ab7ab734c6903da681 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 25 Feb 2026 08:52:12 +0000 Subject: [PATCH 42/49] update to newer dynarmic changes --- src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp | 5 ++++- src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp | 7 +++++-- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp | 8 ++------ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index 54e334bbbe..356020c7b6 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -10,6 +10,7 @@ #include "dynarmic/common/common_types.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/frontend/A32/translate/a32_translate.h" +#include "dynarmic/frontend/A32/FPSCR.h" #include "dynarmic/interface/A32/config.h" #include "dynarmic/backend/ppc64/a32_core.h" #include "dynarmic/common/atomic.h" @@ -33,7 +34,8 @@ struct A32AddressSpace final { if (auto const it = block_entries.find(desc.Value()); it != block_entries.end()) return it->second; - IR::Block ir_block = A32::Translate(A32::LocationDescriptor{desc}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); + ir_block.Reset(A32::LocationDescriptor{desc}); + A32::Translate(ir_block, A32::LocationDescriptor{desc}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); Optimization::Optimize(ir_block, conf, {}); const EmittedBlockInfo block_info = Emit(std::move(ir_block)); @@ -61,6 +63,7 @@ struct A32AddressSpace final { //UNREACHABLE(); } + IR::Block ir_block = {LocationDescriptor(0, PSR(0), FPSCR(0), false)}; const A32::UserConfig conf; CodeBlock cb; powah::Context as; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 29dc61ef62..b1fc35446f 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -25,7 +25,8 @@ struct A64AddressSpace final { explicit A64AddressSpace(const A64::UserConfig& conf) : conf(conf) , cb(conf.code_cache_size) - , as(cb.ptr(), conf.code_cache_size) { + , as(cb.ptr(), conf.code_cache_size) + { } @@ -35,7 +36,8 @@ struct A64AddressSpace final { auto const get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); }; - IR::Block ir_block = A64::Translate(A64::LocationDescriptor{desc}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); + ir_block.Reset(A64::LocationDescriptor{desc}); + A64::Translate(ir_block, A64::LocationDescriptor{desc}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); Optimization::Optimize(ir_block, conf, {}); fmt::print("IR:\n{}\n", IR::DumpBlock(ir_block)); const EmittedBlockInfo block_info = Emit(std::move(ir_block)); @@ -64,6 +66,7 @@ struct A64AddressSpace final { // UNREACHABLE(); } + IR::Block ir_block = {LocationDescriptor(0, FP::FPCR(0), false)}; const A64::UserConfig conf; CodeBlock cb; powah::Context as; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 89eb3f0401..751ed1c19a 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -146,10 +146,6 @@ void EmitIR(powah::Context&, EmitContext&, IR:: namespace { void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step); -void EmitTerminal(powah::Context&, EmitContext&, IR::Term::Interpret, IR::LocationDescriptor, bool) { - ASSERT(false && "unimp"); -} - void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) { ASSERT(false && "unimp"); } @@ -223,7 +219,7 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf size_t const stack_size = 112 + ABI_CALLEE_SAVED.size() * 8; auto const start_offset = code.offset; ebi.entry_point = &code.base[start_offset]; - if (!block.empty()) { + if (!block.instructions.empty()) { code.MFLR(powah::R0); code.STD(powah::R0, powah::R1, 16); // Non-volatile saves @@ -233,7 +229,7 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf code.STDU(powah::R1, powah::R1, uint32_t(-stack_size)); code.STD(powah::R2, powah::R1, 40); - for (auto iter = block.begin(); iter != block.end(); ++iter) { + for (auto iter = block.instructions.begin(); iter != block.instructions.end(); ++iter) { IR::Inst* inst = &*iter; switch (inst->GetOpcode()) { #define OPCODE(name, type, ...) \ From 5f47a7f06423b37ccbcf174219b624aeb0d5dcf1 Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 31 Mar 2026 04:35:22 +0000 Subject: [PATCH 43/49] fastlink impl --- .../src/dynarmic/backend/ppc64/a64_interface.cpp | 1 + .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index b1fc35446f..5233f3ac66 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include "dynarmic/common/assert.h" diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 751ed1c19a..0f66940339 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -169,7 +169,21 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock te } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { - ASSERT(false && "unimp"); + if (ctx.emit_conf.a64_variant) { + auto const tmp = ctx.reg_alloc.ScratchGpr(); + code.LI(tmp, terminal.next.Value()); + code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); + code.LD(tmp, PPC64::RTOCPTR, 0); + code.MTCTR(tmp); + code.LD(powah::R2, PPC64::RTOCPTR, 8); + code.LD(powah::R11, PPC64::RTOCPTR, 16); + code.BCTR(); + } else { + auto const tmp = ctx.reg_alloc.ScratchGpr(); + code.LI(tmp, terminal.next.Value()); + code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15); + ASSERT(false && "unimp"); + } } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::PopRSBHint, IR::LocationDescriptor, bool) { From 99a65383f1349865c6d4c2220248f5858926992a Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 14 Apr 2026 18:32:28 +0000 Subject: [PATCH 44/49] fixup wrong ARCHITECTURE_powerpc64 --- src/CMakeLists.txt | 2 +- src/core/CMakeLists.txt | 2 +- src/dynarmic/src/dynarmic/common/context.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9c62379d02..34d6d32e2d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,7 +8,7 @@ include_directories(.) # Dynarmic -if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64 OR ARCHITECTURE_powerpc64) AND NOT YUZU_STATIC_ROOM) +if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64 OR ARCHITECTURE_ppc64) AND NOT YUZU_STATIC_ROOM) add_subdirectory(dynarmic) add_library(dynarmic::dynarmic ALIAS dynarmic) endif() diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index bd3d78f7c6..7640eef091 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1241,7 +1241,7 @@ if (HAS_NCE) target_link_libraries(core PRIVATE merry::oaknut) endif() -if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64 OR ARCHITECTURE_powerpc64) +if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_ppc64 OR ARCHITECTURE_powerpc64) target_sources(core PRIVATE arm/dynarmic/arm_dynarmic.h arm/dynarmic/arm_dynarmic_64.cpp diff --git a/src/dynarmic/src/dynarmic/common/context.h b/src/dynarmic/src/dynarmic/common/context.h index 0c18807ce5..727dd41bc7 100644 --- a/src/dynarmic/src/dynarmic/common/context.h +++ b/src/dynarmic/src/dynarmic/common/context.h @@ -148,7 +148,7 @@ # else # error "unknown platform" # endif -#elif defined(ARCHITECTURE_powerpc64) +#elif defined(ARCHITECTURE_ppc64) # if defined(__FreeBSD__) # define CTX_PC (mctx.mc_srr0) # define CTX_SP (mctx.mc_gpr[1]) From d3d26797c17c0ec5795708e92f7b8c15f6d10223 Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 10 Jul 2026 06:09:21 +0000 Subject: [PATCH 45/49] fix ppc --- externals/CMakeLists.txt | 2 +- externals/cmake-modules/DetectArchitecture.cmake | 4 ++-- externals/powah/tests.cpp | 2 +- src/CMakeLists.txt | 2 +- src/core/CMakeLists.txt | 2 +- src/dynarmic/src/dynarmic/backend/exception_handler.h | 6 +++--- .../src/dynarmic/backend/exception_handler_generic.cpp | 2 +- .../src/dynarmic/backend/exception_handler_posix.cpp | 4 ++-- src/dynarmic/src/dynarmic/common/context.h | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index b0cce968ec..a70f62d3f4 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -250,7 +250,7 @@ endif() add_subdirectory(nx_tzdb) # PowerPC emitter -if (ARCHITECTURE_ppc64) +if (ARCHITECTURE_powerpc64) add_subdirectory(powah) endif() diff --git a/externals/cmake-modules/DetectArchitecture.cmake b/externals/cmake-modules/DetectArchitecture.cmake index 105963c8c2..3d6e933d76 100644 --- a/externals/cmake-modules/DetectArchitecture.cmake +++ b/externals/cmake-modules/DetectArchitecture.cmake @@ -166,7 +166,7 @@ detect_architecture_symbols( "_M_MRX000") detect_architecture_symbols( - ARCH ppc64 + ARCH powerpc64 SYMBOLS "__ppc64__" "__powerpc64__" @@ -174,7 +174,7 @@ detect_architecture_symbols( "_M_PPC64") detect_architecture_symbols( - ARCH ppc + ARCH powerpc SYMBOLS "__ppc__" "__ppc" diff --git a/externals/powah/tests.cpp b/externals/powah/tests.cpp index ce3ea9933c..e65f293175 100644 --- a/externals/powah/tests.cpp +++ b/externals/powah/tests.cpp @@ -253,7 +253,7 @@ TEST_CASE("ppc64: functor-1", "[ppc64]") { REQUIRE(data[15] == EB32(0x2000804e)); } -#if defined(ARCHITECTURE_ppc64) +#if defined(ARCHITECTURE_powerpc64) /* 0: d619637c mullw 3, 3, 3 4: 20006378 clrldi 3, 3, 32 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 34d6d32e2d..9c62379d02 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,7 +8,7 @@ include_directories(.) # Dynarmic -if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64 OR ARCHITECTURE_ppc64) AND NOT YUZU_STATIC_ROOM) +if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64 OR ARCHITECTURE_powerpc64) AND NOT YUZU_STATIC_ROOM) add_subdirectory(dynarmic) add_library(dynarmic::dynarmic ALIAS dynarmic) endif() diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 7640eef091..43bdb3d446 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1241,7 +1241,7 @@ if (HAS_NCE) target_link_libraries(core PRIVATE merry::oaknut) endif() -if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_ppc64 OR ARCHITECTURE_powerpc64) +if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_powerpc64 OR ARCHITECTURE_powerpc64) target_sources(core PRIVATE arm/dynarmic/arm_dynarmic.h arm/dynarmic/arm_dynarmic_64.cpp diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler.h b/src/dynarmic/src/dynarmic/backend/exception_handler.h index f854e42c82..772e2c138e 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler.h +++ b/src/dynarmic/src/dynarmic/backend/exception_handler.h @@ -30,7 +30,7 @@ class CodeBlock; namespace Dynarmic::Backend::LoongArch64 { class CodeBlock; } // namespace Dynarmic::Backend::LoongArch64 -#elif defined(ARCHITECTURE_ppc64) +#elif defined(ARCHITECTURE_powerpc64) namespace Dynarmic::Backend::PPC64 { class CodeBlock; } @@ -57,7 +57,7 @@ struct FakeCall { struct FakeCall { u64 call_pc; }; -#elif defined(ARCHITECTURE_ppc64) +#elif defined(ARCHITECTURE_powerpc64) struct FakeCall { }; #else @@ -77,7 +77,7 @@ public: void Register(RV64::CodeBlock& mem, std::size_t mem_size); #elif defined(ARCHITECTURE_loongarch64) void Register(LoongArch64::CodeBlock& mem, std::size_t mem_size); -#elif defined(ARCHITECTURE_ppc64) +#elif defined(ARCHITECTURE_powerpc64) void Register(PPC64::CodeBlock& mem, std::size_t mem_size); #else # error "Invalid architecture" diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp index c18481a688..9e92ff1ffa 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp @@ -24,7 +24,7 @@ void ExceptionHandler::Register(oaknut::CodeBlock&, std::size_t) void ExceptionHandler::Register(RV64::CodeBlock&, std::size_t) #elif defined(ARCHITECTURE_loongarch64) void ExceptionHandler::Register(LoongArch64::CodeBlock&, std::size_t) -#elif defined(ARCHITECTURE_ppc64) +#elif defined(ARCHITECTURE_powerpc64) void ExceptionHandler::Register(PPC64::CodeBlock&, std::size_t) #else # error "Invalid architecture" diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp index 6776fc22b3..c7d766afb7 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp @@ -36,7 +36,7 @@ # include "dynarmic/backend/riscv64/code_block.h" #elif defined(ARCHITECTURE_loongarch64) # include "dynarmic/backend/loongarch64/code_block.h" -#elif defined(ARCHITECTURE_ppc64) +#elif defined(ARCHITECTURE_powerpc64) # include "dynarmic/backend/ppc64/code_block.h" #else # error "Invalid architecture" @@ -208,7 +208,7 @@ void ExceptionHandler::Register(RV64::CodeBlock& mem, std::size_t size) { void ExceptionHandler::Register(LoongArch64::CodeBlock& mem, std::size_t size) { impl = std::make_unique(std::bit_cast(mem.ptr()), size); } -#elif defined(ARCHITECTURE_ppc64) +#elif defined(ARCHITECTURE_powerpc64) void ExceptionHandler::Register(PPC64::CodeBlock& mem, std::size_t size) { impl = std::make_unique(std::bit_cast(mem.ptr()), size); } diff --git a/src/dynarmic/src/dynarmic/common/context.h b/src/dynarmic/src/dynarmic/common/context.h index 727dd41bc7..0c18807ce5 100644 --- a/src/dynarmic/src/dynarmic/common/context.h +++ b/src/dynarmic/src/dynarmic/common/context.h @@ -148,7 +148,7 @@ # else # error "unknown platform" # endif -#elif defined(ARCHITECTURE_ppc64) +#elif defined(ARCHITECTURE_powerpc64) # if defined(__FreeBSD__) # define CTX_PC (mctx.mc_srr0) # define CTX_SP (mctx.mc_gpr[1]) From 2db4c35c54289e043c5ae4568d524e2bbaddb6a8 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 12 Aug 2026 22:02:57 +0000 Subject: [PATCH 46/49] fix ppc build errs as well --- externals/powah/data2code.c | 3 +++ externals/powah/powah_emit.hpp | 3 +++ externals/powah/powah_gen_base.hpp | 3 +++ src/dynarmic/src/dynarmic/CMakeLists.txt | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp | 4 ++-- src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp | 4 ++-- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/code_block.h | 4 ++-- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h | 2 +- .../src/dynarmic/backend/ppc64/emit_ppc64_data_processing.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h | 2 +- src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp | 4 ++-- src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h | 4 ++-- src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h | 2 +- src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp | 2 +- 16 files changed, 27 insertions(+), 18 deletions(-) diff --git a/externals/powah/data2code.c b/externals/powah/data2code.c index 54bc17a1bf..9b262b24ea 100644 --- a/externals/powah/data2code.c +++ b/externals/powah/data2code.c @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + #include #include #include diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 5af323ec5d..3b9577a63d 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + #pragma once #undef NDEBUG diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index 6f3f27f6f0..aa8ea5360b 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // 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); } diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index 1523b0a0b3..66d5507a6d 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -293,7 +293,7 @@ if ("riscv64" IN_LIST ARCHITECTURE) ) message(WARNING "TODO: Incomplete frontend for this host architecture") endif() -if ("ppc64" IN_LIST ARCHITECTURE) +if ("powerpc64" IN_LIST ARCHITECTURE) target_link_libraries(dynarmic PRIVATE powah) target_sources(dynarmic PRIVATE backend/ppc64/abi.h diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp index 356020c7b6..b974750720 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_interface.cpp @@ -6,8 +6,8 @@ #include -#include "dynarmic/common/assert.h" -#include "dynarmic/common/common_types.h" +#include "common/assert.h" +#include "common/common_types.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/frontend/A32/translate/a32_translate.h" #include "dynarmic/frontend/A32/FPSCR.h" diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 5233f3ac66..7b3f9e88da 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -6,8 +6,8 @@ #include #include -#include "dynarmic/common/assert.h" -#include "dynarmic/common/common_types.h" +#include "common/assert.h" +#include "common/common_types.h" #include "dynarmic/frontend/A64/a64_location_descriptor.h" #include "dynarmic/frontend/A64/translate/a64_translate.h" diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 5924a5c057..2989b9ae58 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -4,7 +4,7 @@ #pragma once #include -#include "dynarmic/common/common_types.h" +#include "common/common_types.h" namespace Dynarmic::Backend::PPC64 { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h b/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h index c57e34baec..b5e42f3706 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/code_block.h @@ -8,8 +8,8 @@ #include #include -#include "dynarmic/common/common_types.h" -#include "dynarmic/common/assert.h" +#include "common/common_types.h" +#include "common/assert.h" namespace Dynarmic::Backend::PPC64 { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h index 4eed600905..2138ee158a 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.h @@ -6,7 +6,7 @@ #include #include -#include "dynarmic/common/common_types.h" +#include "common/common_types.h" namespace biscuit { class Assembler; 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 dd01ee07e5..e3b599b31c 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,7 +4,7 @@ #include #include -#include "dynarmic/common/assert.h" +#include "common/assert.h" #include "dynarmic/backend/ppc64/a32_core.h" #include "dynarmic/backend/ppc64/abi.h" #include "dynarmic/backend/ppc64/emit_context.h" diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp index 3910662df2..d0e3142346 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/exclusive_monitor.cpp @@ -3,7 +3,7 @@ #include "dynarmic/interface/exclusive_monitor.h" #include -#include "dynarmic/common/assert.h" +#include "common/assert.h" namespace Dynarmic { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h index 285bf941a5..694d520b6c 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/hostloc.h @@ -3,7 +3,7 @@ #pragma once -#include "dynarmic/common/common_types.h" +#include "common/common_types.h" namespace Dynarmic::Backend::PPC64 { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp index 8a89941ed9..bd35b4af5b 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.cpp @@ -9,8 +9,8 @@ #include "dynarmic/backend/ppc64/reg_alloc.h" #include "dynarmic/backend/ppc64/abi.h" -#include "dynarmic/common/assert.h" -#include "dynarmic/common/common_types.h" +#include "common/assert.h" +#include "common/common_types.h" #include "dynarmic/common/always_false.h" namespace Dynarmic::Backend::PPC64 { diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h index 910abf72cb..6d84b31dda 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/reg_alloc.h @@ -12,8 +12,8 @@ #include #include -#include "dynarmic/common/assert.h" -#include "dynarmic/common/common_types.h" +#include "common/assert.h" +#include "common/common_types.h" #include "dynarmic/backend/ppc64/stack_layout.h" #include "dynarmic/backend/ppc64/hostloc.h" #include "dynarmic/ir/cond.h" diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h index 55608cd658..074fec02c0 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/stack_layout.h @@ -5,7 +5,7 @@ #include -#include "dynarmic/common/common_types.h" +#include "common/common_types.h" namespace Dynarmic::Backend::PPC64 { diff --git a/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp index 759eda74dd..258b10f52b 100644 --- a/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/common/spin_lock_ppc64.cpp @@ -7,7 +7,7 @@ #include "dynarmic/backend/ppc64/abi.h" #include "dynarmic/backend/ppc64/hostloc.h" #include "dynarmic/common/spin_lock.h" -#include "dynarmic/common/assert.h" +#include "common/assert.h" namespace Dynarmic { From b84e63f06b5c7617b75825ce67f61e39b5be446d Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 12 Aug 2026 22:11:07 +0000 Subject: [PATCH 47/49] appropriate new terminals --- .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 36 +++++++++++++++---- .../ppc64/emit_ppc64_data_processing.cpp | 4 +-- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 0f66940339..100558f939 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -144,7 +144,9 @@ void EmitIR(powah::Context&, EmitContext&, IR:: } namespace { -void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step); + +void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step); +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const terminal, IR::LocationDescriptor initial_location, bool is_single_step); void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) { ASSERT(false && "unimp"); @@ -206,11 +208,11 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckBit ter code.CMPLDI(tmp, 0); code.BEQ(powah::CR0, l_else); // CheckBit == 1 - EmitTerminal(code, ctx, terminal.then_, initial_location, is_single_step); + EmitLeafTerminal(code, ctx, terminal.then_, initial_location, is_single_step); code.B(l_end); // CheckBit == 0 code.LABEL(l_else); - EmitTerminal(code, ctx, terminal.else_, initial_location, is_single_step); + EmitLeafTerminal(code, ctx, terminal.else_, initial_location, is_single_step); code.LABEL(l_end); } @@ -218,10 +220,30 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckHalt te ASSERT(false && "unimp"); } -void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - boost::apply_visitor([&](const auto& t) { - EmitTerminal(code, ctx, t, initial_location, is_single_step); - }, terminal); +void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerminal const terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + if (auto const x = std::get_if(&terminal)) + return EmitTerminal(code, ctx, *x, initial_location, is_single_step); + if (auto const x = std::get_if(&terminal)) + return EmitTerminal(code, ctx, *x, initial_location, is_single_step); + if (auto const x = std::get_if(&terminal)) + return EmitTerminal(code, ctx, *x, initial_location, is_single_step); + if (auto const x = std::get_if(&terminal)) + return EmitTerminal(code, ctx, *x, initial_location, is_single_step); + if (auto const x = std::get_if(&terminal)) + return EmitTerminal(code, ctx, *x, initial_location, is_single_step); + UNREACHABLE(); +} + +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + if (auto const x = std::get_if(&terminal)) + return EmitLeafTerminal(code, ctx, *x, initial_location, is_single_step); + if (auto const x = std::get_if(&terminal)) + return EmitTerminal(code, ctx, *x, initial_location, is_single_step); + if (auto const x = std::get_if(&terminal)) + return EmitTerminal(code, ctx, *x, initial_location, is_single_step); + if (auto const x = std::get_if(&terminal)) + return EmitTerminal(code, ctx, *x, initial_location, is_single_step); + UNREACHABLE(); } } 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 e3b599b31c..ce211bbc48 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 @@ -329,7 +329,7 @@ void EmitIR(powah::Context& code, EmitContex // __builtin_rotateright32 template<> -void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { +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(0)); @@ -340,7 +340,7 @@ void EmitIR(powah::Context& code, EmitContext& ctx, I } template<> -void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { +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(0)); From d58ab987949f031228cd6f8a596ac386838bc9d8 Mon Sep 17 00:00:00 2001 From: lizzie Date: Wed, 12 Aug 2026 23:21:09 +0000 Subject: [PATCH 48/49] use common return point to not corrupt regs also use jit state for checkbit :) --- .../src/dynarmic/backend/ppc64/a32_core.h | 2 +- .../src/dynarmic/backend/ppc64/a64_core.h | 2 +- .../dynarmic/backend/ppc64/a64_interface.cpp | 10 +---- src/dynarmic/src/dynarmic/backend/ppc64/abi.h | 1 - .../src/dynarmic/backend/ppc64/emit_context.h | 3 ++ .../src/dynarmic/backend/ppc64/emit_ppc64.cpp | 42 +++++++------------ .../dynarmic/backend/ppc64/emit_ppc64_a64.cpp | 10 +---- 7 files changed, 25 insertions(+), 45 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h index d287f95671..1a3bb9296a 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a32_core.h @@ -22,7 +22,7 @@ struct A32JitState { u32 exclusive_state = 0; u32 cpsr_nzcv = 0; u32 fpscr = 0; - u8 check_bit = 0; + u32 check_bit = 0; IR::LocationDescriptor GetLocationDescriptor() const { return IR::LocationDescriptor{regs[15] | (u64(upper_location_descriptor) << 32)}; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h index d5aa0b3370..d727e0d3ed 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_core.h @@ -28,7 +28,7 @@ struct A64JitState { u32 fpcr = 0; u32 fpsr = 0; volatile u32 halt_reason = 0; - u8 check_bit = 0; + u32 check_bit = 0; IR::LocationDescriptor GetLocationDescriptor() const { const u64 fpcr_u64 = u64(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 7b3f9e88da..86e3e86c0c 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -75,18 +75,12 @@ struct A64AddressSpace final { ankerl::unordered_dense::map block_infos; }; -__attribute__((noinline)) HaltReason test_thunk(A64AddressSpace* a, A64JitState* b, volatile u32* c, void* d) { - printf("%p,%p,%p,%p\n", a, b, c, d); - return HaltReason::UserDefined2; -} - struct A64Core final { + using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void *fn); static HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { const auto loc = thread_ctx.GetLocationDescriptor(); const auto entry = process.GetOrEmit(loc); - using AbstractCodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void (*fn)()); - using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, AbstractCodeFn fn); - return (CodeFn(entry))(&process, &thread_ctx, halt_reason, AbstractCodeFn(test_thunk)); + return (CodeFn(entry))(&process, &thread_ctx, halt_reason, (void*)&A64Core::Run); } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h index 2989b9ae58..937fbcd4a1 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/abi.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/abi.h @@ -49,7 +49,6 @@ constexpr powah::GPR RHALTREASON = powah::R5; constexpr powah::GPR RTOCPTR = powah::R6; // temporals constexpr powah::GPR RNZCV = powah::R7; -constexpr powah::GPR RCHECKBIT = powah::R8; constexpr powah::GPR ABI_PARAM1 = powah::R3; constexpr powah::GPR ABI_PARAM2 = powah::R4; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h b/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h index d8e11e3591..147ccdf0ec 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_context.h @@ -3,6 +3,7 @@ #pragma once +#include #include "dynarmic/backend/ppc64/emit_ppc64.h" #include "dynarmic/backend/ppc64/reg_alloc.h" @@ -19,6 +20,8 @@ struct EmitContext { RegAlloc& reg_alloc; const EmitConfig& emit_conf; EmittedBlockInfo& ebi; + // label used when returning :) + powah::Label l_return; }; } // namespace Dynarmic::Backend::RV64 diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index 100558f939..d070d436c1 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -146,22 +146,24 @@ void EmitIR(powah::Context&, EmitContext&, IR:: namespace { void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step); -void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const terminal, IR::LocationDescriptor initial_location, bool is_single_step); +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step); void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) { ASSERT(false && "unimp"); } +// r3 -> process +// r4 -> thread_ctx +// r5 -> halt_reason +// r6 -> test_thunk void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool) { if (ctx.emit_conf.a64_variant) { auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); - code.LD(tmp, PPC64::RTOCPTR, 0); - code.MTCTR(tmp); - code.LD(powah::R2, PPC64::RTOCPTR, 8); - code.LD(powah::R11, PPC64::RTOCPTR, 16); - code.BCTR(); +// code.MTCTR(powah::R6); +// code.BCTR(); + code.B(ctx.l_return); } else { auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); @@ -170,22 +172,8 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock te } } -void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool) { - if (ctx.emit_conf.a64_variant) { - auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.LI(tmp, terminal.next.Value()); - code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); - code.LD(tmp, PPC64::RTOCPTR, 0); - code.MTCTR(tmp); - code.LD(powah::R2, PPC64::RTOCPTR, 8); - code.LD(powah::R11, PPC64::RTOCPTR, 16); - code.BCTR(); - } else { - auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.LI(tmp, terminal.next.Value()); - code.STW(tmp, PPC64::RJIT, offsetof(A32JitState, regs) + sizeof(u32) * 15); - ASSERT(false && "unimp"); - } +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool is_single_step) { + EmitTerminal(code, ctx, terminal, IR::Term::LinkBlock{terminal.next}, is_single_step); } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::PopRSBHint, IR::LocationDescriptor, bool) { @@ -204,7 +192,7 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckBit ter powah::Label const l_else = code.DefineLabel(); powah::Label const l_end = code.DefineLabel(); auto const tmp = ctx.reg_alloc.ScratchGpr(); - code.MR(tmp, PPC64::RCHECKBIT); + code.LWZ(tmp, PPC64::RJIT, offsetof(A64JitState, check_bit)); code.CMPLDI(tmp, 0); code.BEQ(powah::CR0, l_else); // CheckBit == 1 @@ -220,7 +208,7 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::CheckHalt te ASSERT(false && "unimp"); } -void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerminal const terminal, IR::LocationDescriptor initial_location, bool is_single_step) { +void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) { if (auto const x = std::get_if(&terminal)) return EmitTerminal(code, ctx, *x, initial_location, is_single_step); if (auto const x = std::get_if(&terminal)) @@ -234,7 +222,7 @@ void EmitLeafTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LeafTerm UNREACHABLE(); } -void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const terminal, IR::LocationDescriptor initial_location, bool is_single_step) { +void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) { if (auto const x = std::get_if(&terminal)) return EmitLeafTerminal(code, ctx, *x, initial_location, is_single_step); if (auto const x = std::get_if(&terminal)) @@ -290,15 +278,17 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf } // auto const cycles_to_add = block.CycleCount(); + EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); + code.LABEL(ctx.l_return); code.ADDI(powah::R1, powah::R1, stack_size); for (size_t i = 0; i < gp_regs.size(); ++i) code.LD(gp_regs[i], powah::R1, -int32_t(gp_regs.size() - i) * 8); code.LD(powah::R0, powah::R1, 16); code.MTLR(powah::R0); - EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); } else { EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); } + code.BLR(); code.ApplyRelocs(); /* 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 cd0b4aa1cf..7e7734009d 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64_a64.cpp @@ -19,7 +19,7 @@ namespace Dynarmic::Backend::PPC64 { template<> void EmitIR(powah::Context& code, EmitContext& ctx, IR::Inst* inst) { auto const value = ctx.reg_alloc.UseGpr(inst->GetArg(0)); - code.MR(PPC64::RCHECKBIT, value); + code.STW(value, PPC64::RJIT, offsetof(A64JitState, check_bit)); } template<> @@ -48,14 +48,8 @@ void EmitIR(powah::Context& code, EmitContext& ctx, IR::Ins if (inst->GetArg(0).GetType() == IR::Type::A64Reg) { auto const result = ctx.reg_alloc.ScratchGpr(); // Need to account for endianess here... -#ifdef __ORDER_BIG_ENDIAN__ - constexpr u32 pe_offset64 = 4; -#else - constexpr u32 pe_offset64 = 0; -#endif auto const offs = offsetof(A64JitState, regs) - + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64) - + pe_offset64; + + A64::RegNumber(inst->GetArg(0).GetA64RegRef()) * sizeof(u64); code.LWZ(result, PPC64::RJIT, offs); ctx.reg_alloc.DefineValue(inst, result); } else { From e52e920b1490da9ea4259785b280ff800d17a8e1 Mon Sep 17 00:00:00 2001 From: lizzie Date: Thu, 13 Aug 2026 00:01:15 +0000 Subject: [PATCH 49/49] fix for tests?!?!? --- .../src/dynarmic/backend/ppc64/a64_interface.cpp | 10 +++++++--- src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp | 10 +++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp index 86e3e86c0c..53753673dc 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/a64_interface.cpp @@ -78,9 +78,13 @@ struct A64AddressSpace final { struct A64Core final { using CodeFn = HaltReason (*)(A64AddressSpace*, A64JitState*, volatile u32*, void *fn); static HaltReason Run(A64AddressSpace& process, A64JitState& thread_ctx, volatile u32* halt_reason) { - const auto loc = thread_ctx.GetLocationDescriptor(); - const auto entry = process.GetOrEmit(loc); - return (CodeFn(entry))(&process, &thread_ctx, halt_reason, (void*)&A64Core::Run); + HaltReason hr{}; + do { + const auto loc = thread_ctx.GetLocationDescriptor(); + const auto entry = process.GetOrEmit(loc); + hr = (CodeFn(entry))(&process, &thread_ctx, halt_reason, (void*)&A64Core::Run); + } while (hr == HaltReason(0)); + return hr; } }; diff --git a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp index d070d436c1..3b5e3cc4e3 100644 --- a/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp +++ b/src/dynarmic/src/dynarmic/backend/ppc64/emit_ppc64.cpp @@ -161,8 +161,6 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock te auto const tmp = ctx.reg_alloc.ScratchGpr(); code.LI(tmp, terminal.next.Value()); code.STD(tmp, PPC64::RJIT, offsetof(A64JitState, pc)); -// code.MTCTR(powah::R6); -// code.BCTR(); code.B(ctx.l_return); } else { auto const tmp = ctx.reg_alloc.ScratchGpr(); @@ -173,7 +171,7 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlock te } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool is_single_step) { - EmitTerminal(code, ctx, terminal, IR::Term::LinkBlock{terminal.next}, is_single_step); + EmitTerminal(code, ctx, IR::Term::LinkBlock{terminal.next}, initial_location, is_single_step); } void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::PopRSBHint, IR::LocationDescriptor, bool) { @@ -238,8 +236,7 @@ void EmitTerminal(powah::Context& code, EmitContext& ctx, IR::Term::Terminal con EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConfig& emit_conf) { EmittedBlockInfo ebi; RegAlloc reg_alloc{code}; - EmitContext ctx{block, reg_alloc, emit_conf, ebi}; - + EmitContext ctx{block, reg_alloc, emit_conf, ebi, code.DefineLabel()}; size_t const stack_size = 112 + ABI_CALLEE_SAVED.size() * 8; auto const start_offset = code.offset; ebi.entry_point = &code.base[start_offset]; @@ -285,8 +282,11 @@ EmittedBlockInfo EmitPPC64(powah::Context& code, IR::Block block, const EmitConf code.LD(gp_regs[i], powah::R1, -int32_t(gp_regs.size() - i) * 8); code.LD(powah::R0, powah::R1, 16); code.MTLR(powah::R0); + code.LI(powah::R3, 0); } else { EmitTerminal(code, ctx, ctx.block.GetTerminal(), ctx.block.Location(), false); + code.LABEL(ctx.l_return); + code.LI(powah::R3, 67); //non-zero ret } code.BLR(); code.ApplyRelocs();