diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 18491962b2..9605401176 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -235,6 +235,9 @@ endif() # TZDB (Time Zone Database) add_subdirectory(nx_tzdb) +# PowerPC emitter +add_subdirectory(powah) + if (NOT TARGET LLVM::Demangle) add_library(demangle demangle/ItaniumDemangle.cpp) target_include_directories(demangle PUBLIC ./demangle) 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 2510458812..d82f0e08d6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,11 +7,9 @@ include_directories(.) # Dynarmic -if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)) set(DYNARMIC_IGNORE_ASSERTS ON) add_subdirectory(dynarmic) add_library(dynarmic::dynarmic ALIAS dynarmic) -endif() # CMake seems to only define _DEBUG on Windows set_property(DIRECTORY APPEND PROPERTY diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6a8b9b93b3..4e73d4a35d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1233,7 +1233,7 @@ if (HAS_NCE) target_link_libraries(core PRIVATE merry::oaknut) endif() -if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) +if (TARGET dynarmic::dynarmic) target_sources(core PRIVATE arm/dynarmic/arm_dynarmic.h arm/dynarmic/arm_dynarmic_64.cpp diff --git a/src/core/arm/dynarmic/dynarmic_cp15.cpp b/src/core/arm/dynarmic/dynarmic_cp15.cpp index e3e2d8339d..930647c871 100644 --- a/src/core/arm/dynarmic/dynarmic_cp15.cpp +++ b/src/core/arm/dynarmic/dynarmic_cp15.cpp @@ -59,14 +59,10 @@ CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1 #if defined(_MSC_VER) && defined(ARCHITECTURE_x86_64) _mm_mfence(); _mm_lfence(); -#elif defined(ARCHITECTURE_x86_64) - asm volatile("mfence\n\tlfence\n\t" : : : "memory"); #elif defined(_MSC_VER) && defined(ARCHITECTURE_arm64) _Memory_barrier(); -#elif defined(ARCHITECTURE_arm64) - asm volatile("dsb sy\n\t" : : : "memory"); #else -#error Unsupported architecture + __sync_synchronize(); #endif return 0; }, @@ -78,14 +74,10 @@ CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1 [](void*, std::uint32_t, std::uint32_t) -> std::uint64_t { #if defined(_MSC_VER) && defined(ARCHITECTURE_x86_64) _mm_mfence(); -#elif defined(ARCHITECTURE_x86_64) - asm volatile("mfence\n\t" : : : "memory"); #elif defined(_MSC_VER) && defined(ARCHITECTURE_arm64) _Memory_barrier(); -#elif defined(ARCHITECTURE_arm64) - asm volatile("dmb sy\n\t" : : : "memory"); #else -#error Unsupported architecture + __sync_synchronize(); #endif return 0; }, diff --git a/src/dynarmic/src/dynarmic/CMakeLists.txt b/src/dynarmic/src/dynarmic/CMakeLists.txt index 9575eaab6f..84f4be1d40 100644 --- a/src/dynarmic/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/src/dynarmic/CMakeLists.txt @@ -73,6 +73,7 @@ add_library(dynarmic STATIC frontend/imm.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 @@ -142,10 +143,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 @@ -291,7 +290,31 @@ if ("riscv" IN_LIST ARCHITECTURE) backend/riscv64/a32_interface.cpp backend/riscv64/code_block.h ) - message(FATAL_ERROR "TODO: Unimplemented 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 (WIN32) diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler.h b/src/dynarmic/src/dynarmic/backend/exception_handler.h index cd274b111f..7dee00bce7 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler.h +++ b/src/dynarmic/src/dynarmic/backend/exception_handler.h @@ -18,7 +18,7 @@ #if defined(ARCHITECTURE_x86_64) namespace Dynarmic::Backend::X64 { class BlockOfCode; -} // namespace Dynarmic::Backend::X64 +} #elif defined(ARCHITECTURE_arm64) namespace oaknut { class CodeBlock; @@ -26,7 +26,11 @@ class CodeBlock; #elif defined(ARCHITECTURE_riscv64) namespace Dynarmic::Backend::RV64 { class CodeBlock; -} // namespace Dynarmic::Backend::RV64 +} +#elif defined(ARCHITECTURE_ppc64) +namespace Dynarmic::Backend::PPC64 { +class CodeBlock; +} #else # error "Invalid architecture" #endif @@ -45,6 +49,9 @@ struct FakeCall { #elif defined(ARCHITECTURE_riscv64) struct FakeCall { }; +#elif defined(ARCHITECTURE_ppc64) +struct FakeCall { +}; #else # error "Invalid architecture" #endif @@ -60,6 +67,8 @@ public: void Register(oaknut::CodeBlock& mem, std::size_t mem_size); #elif defined(ARCHITECTURE_riscv64) void Register(RV64::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 23dc294511..a33111c84a 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp @@ -17,20 +17,19 @@ 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_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 9f508f72e5..dd1083532d 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp @@ -26,6 +26,8 @@ # include "dynarmic/backend/arm64/abi.h" #elif defined(ARCHITECTURE_riscv64) # include "dynarmic/backend/riscv64/code_block.h" +#elif defined(ARCHITECTURE_ppc64) +# include "dynarmic/backend/ppc64/code_block.h" #else # error "Invalid architecture" #endif @@ -139,10 +141,8 @@ void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { } } fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC); -#elif defined(ARCHITECTURE_riscv64) - UNREACHABLE(); #else -# error "Invalid architecture" + UNREACHABLE(); #endif struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler->old_sa_segv : &sig_handler->old_sa_bus; @@ -200,6 +200,10 @@ void ExceptionHandler::Register(oaknut::CodeBlock& mem, std::size_t size) { void ExceptionHandler::Register(RV64::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 diff --git a/src/dynarmic/src/dynarmic/common/context.h b/src/dynarmic/src/dynarmic/common/context.h index 941289cb94..28b9df87cd 100644 --- a/src/dynarmic/src/dynarmic/common/context.h +++ b/src/dynarmic/src/dynarmic/common/context.h @@ -51,6 +51,16 @@ [[maybe_unused]] auto& mctx = ucontext->uc_mcontext; \ [[maybe_unused]] const auto fpctx = GetFloatingPointState(mctx); # endif +#elif defined(ARCHITECTURE_ppc64) +# ifdef __OpenBSD__ +# define CTX_DECLARE(raw_context) ucontext_t* ucontext = reinterpret_cast(raw_context); +# else +# define CTX_DECLARE(raw_context) \ + ucontext_t* ucontext = reinterpret_cast(raw_context); \ + [[maybe_unused]] auto& mctx = ucontext->uc_mcontext; +# endif +#else +# error "Invalid architecture" #endif #if defined(ARCHITECTURE_x86_64) @@ -118,8 +128,6 @@ # else # error "Unknown platform" # endif -#else -# error "unimplemented" #endif #ifdef ARCHITECTURE_arm64