Browse Source

skeleton for ppc64

Signed-off-by: lizzie <lizzie@eden-emu.dev>
dynarmic-ppc64
lizzie 2 months ago
parent
commit
81cb00c4ec
No known key found for this signature in database GPG Key ID: 287378CADCAB13
  1. 3
      externals/CMakeLists.txt
  2. 9
      externals/powah/CMakeLists.txt
  3. 273
      externals/powah/data2code.c
  4. 339
      externals/powah/powah_emit.hpp
  5. 464
      externals/powah/powah_gen_base.hpp
  6. 139
      externals/powah/tests.cpp
  7. 2
      src/CMakeLists.txt
  8. 2
      src/core/CMakeLists.txt
  9. 12
      src/core/arm/dynarmic/dynarmic_cp15.cpp
  10. 29
      src/dynarmic/src/dynarmic/CMakeLists.txt
  11. 13
      src/dynarmic/src/dynarmic/backend/exception_handler.h
  12. 17
      src/dynarmic/src/dynarmic/backend/exception_handler_generic.cpp
  13. 10
      src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp
  14. 12
      src/dynarmic/src/dynarmic/common/context.h

3
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)

9
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)

273
externals/powah/data2code.c

@ -0,0 +1,273 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
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;
}

339
externals/powah/powah_emit.hpp

@ -0,0 +1,339 @@
#pragma once
#undef NDEBUG
#include <cstdint>
#include <cstddef>
#include <cassert>
#include <ranges>
#include <bit>
#include <utility>
//#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<uint32_t*>(ptr)}
, offset{0}
, size{uint32_t(size)} {
}
~Context() = default;
std::vector<uint32_t> 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;
};
}

464
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); }

139
externals/powah/tests.cpp

@ -0,0 +1,139 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <catch2/catch_test_macros.hpp>
#include "powah_emit.hpp"
TEST_CASE("ppc64: addi", "[ppc64]") {
std::vector<uint32_t> 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<uint32_t> 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<uint32_t> 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<uint32_t> 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<uint32_t> 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<uint32_t> 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<uint32_t> 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);
}

2
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

2
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

12
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;
},

29
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)

13
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

17
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;

10
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<Impl>(std::bit_cast<u64>(mem.ptr<u64>()), size);
}
#elif defined(ARCHITECTURE_ppc64)
void ExceptionHandler::Register(PPC64::CodeBlock& mem, std::size_t size) {
impl = std::make_unique<Impl>(std::bit_cast<u64>(mem.ptr<u64>()), size);
}
#else
# error "Invalid architecture"
#endif

12
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<ucontext_t*>(raw_context);
# else
# define CTX_DECLARE(raw_context) \
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(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

Loading…
Cancel
Save