Browse Source

relocations

Signed-off-by: lizzie <lizzie@eden-emu.dev>
dynarmic-ppc64
lizzie 2 months ago
parent
commit
36c60fab0e
No known key found for this signature in database GPG Key ID: 287378CADCAB13
  1. 44
      externals/powah/data2code.c
  2. 108
      externals/powah/powah_emit.hpp
  3. 60
      externals/powah/powah_gen_base.hpp
  4. 184
      externals/powah/tests.cpp

44
externals/powah/data2code.c

@ -26,20 +26,20 @@ int main(int argc, char *argv[]) {
*opc++ = '\0';
char *sec = strchr(opc, ',');
if (sec) {
struct b_info { const char *s; int o; } infos[] = {
{"",1},
{"LT",1},
{"LE",2},
{"NG",2},
{"EQ",3},
{"GE",1},
{"NL",1},
{"GT",2},
{"NE",3},
{"SO",4},
{"UN",4},
{"NS",4},
{"NU",4},
struct b_info { const char *s; int o; int p; } infos[] = {
{"",1,0},
{"LT",1,12},
{"LE",2,4},
{"NG",2,4},
{"EQ",3,12},
{"GE",1,4},
{"NL",1,4},
{"GT",2,12},
{"NE",3,4},
{"SO",4,12},
{"UN",4,12},
{"NS",4,4},
{"NU",4,4},
};
if (strchr(mem, '[') != NULL) *strchr(mem, '[') = '\0';
@ -103,7 +103,7 @@ int main(int argc, char *argv[]) {
|| !strcmp(mem, "CMP")) {
printf(
"void %s(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) {"
" emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, rb, false); "
" emit_%s(0x%08x, ra, GPR{(bf << 2) | l}, rb, false); "
"}\n"
, mem, form, i_opcode << 26);
} else if (!strcmp(mem, "CNTLZD") || !strcmp(mem, "CNTLZW")
@ -133,26 +133,26 @@ int main(int argc, char *argv[]) {
} else if (!strcmp(form, "I")) {
printf(
"void %s(Label const& i) {"
" emit_reloc_%s(0x%08x, i); "
" emit_reloc_%s(0x%08x, i, false); "
"}\n"
, mem, form, i_opcode << 26);
printf(
"void %sL(Label const& i) {"
" emit_reloc_%s(0x%08x, i); "
" emit_reloc_%s(0x%08x, i, true); "
"}\n"
, mem, form, i_opcode << 26);
} else if (!strcmp(form, "B")) {
for (int i = 0; i < 12; ++i) {
printf(
"void %s%s(CPR const cr, Label const& i) {"
" emit_reloc_%s(0x%08x, cr.index + %i, i, false); "
" emit_reloc_%s(0x%08x, %i, cr.index + %i, i, false); "
"}\n"
, mem, infos[i].s, form, i_opcode << 26, infos[i].o);
, mem, infos[i].s, form, i_opcode << 26, infos[i].p, infos[i].o - 1);
printf(
"void %s%sL(CPR const cr, Label const& i) {"
" emit_reloc_%s(0x%08x, cr.index + %i, i, true); "
" emit_reloc_%s(0x%08x, %i, cr.index + %i, i, true); "
"}\n"
, mem, infos[i].s, form, i_opcode << 26, infos[i].o);
, mem, infos[i].s, form, i_opcode << 26, infos[i].p, infos[i].o - 1);
if (!strcmp(mem, "BC")) mem[1] = '\0';
}
} else if (!strcmp(form, "D")) {
@ -160,7 +160,7 @@ int main(int argc, char *argv[]) {
|| !strcmp(mem, "CMPI")) {
printf(
"void %s(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) {"
" emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, d); "
" emit_%s(0x%08x, ra, GPR{(bf << 2) | l}, d); "
"}\n"
, mem, form, i_opcode << 26);
} else {

108
externals/powah/powah_emit.hpp

@ -110,6 +110,15 @@ constexpr inline CPR CR5{20};
constexpr inline CPR CR6{24};
constexpr inline CPR CR7{28};
enum class RelocKind : uint8_t {
FormB,
FormI,
};
struct RelocInfo {
uint32_t offset;
RelocKind kind;
};
struct Context {
Context() = default;
Context(void* ptr, size_t size)
@ -121,10 +130,26 @@ struct Context {
~Context() = default;
std::vector<uint32_t> labels;
std::vector<std::pair<uint32_t, RelocInfo>> relocs;
Label DefineLabel() {
labels.push_back(0);
return Label{ uint32_t(labels.size()) };
return Label{ uint32_t(labels.size() - 1) };
}
void ApplyRelocs() {
for (auto const [index, info] : relocs) {
assert(labels[index] != 0); //label must have an addr
switch (info.kind) {
case RelocKind::FormB:
base[info.offset] |= bitExt(labels[index] - info.offset, 16, 14);
break;
case RelocKind::FormI:
base[info.offset] |= bitExt(labels[index] - info.offset, 6, 24);
break;
}
}
relocs.clear();
}
void LABEL(Label l) {
@ -155,16 +180,16 @@ struct Context {
return (value & mask) << (32 - (n + offs));
}
void emit_XO(uint32_t op, GPR const rt, GPR const ra, GPR const rb, bool oe, bool rc) {
(void)op;
(void)rt;
(void)ra;
(void)rb;
(void)oe;
(void)rc;
std::abort();
base[offset++] = (op |
bitExt(rt.index, 6, 5)
| bitExt(ra.index, 11, 5)
| bitExt(rb.index, 16, 5)
| bitExt(oe, 21, 1)
| bitExt(rc, 31, 1)
);
}
void emit_D(uint32_t op, GPR const rt, GPR const ra, uint32_t d) {
base[offset++] = __bswap32(op |
base[offset++] = (op |
(op == 0x74000000
? (bitExt(ra.index, 6, 5) | bitExt(rt.index, 11, 5))
: (bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5)))
@ -172,7 +197,7 @@ struct Context {
);
}
void emit_X(uint32_t op, GPR const ra, GPR const rt, GPR const rb, bool rc) {
base[offset++] = __bswap32(op |
base[offset++] = (op |
bitExt(rt.index, 6, 5)
| bitExt(ra.index, 11, 5)
| bitExt(rb.index, 16, 5)
@ -180,7 +205,7 @@ struct Context {
);
}
void emit_XS(uint32_t op, GPR const rt, GPR const ra, uint32_t sh, bool rc) {
base[offset++] = __bswap32(op |
base[offset++] = (op |
bitExt(rt.index, 6, 5)
| bitExt(ra.index, 11, 5)
| bitExt(sh, 16, 5)
@ -188,20 +213,22 @@ struct Context {
| bitExt(rc, 31, 1)
);
}
void emit_reloc_I(uint32_t op, Label const& l) {
(void)op;
(void)l;
std::abort();
void emit_reloc_I(uint32_t op, Label const& l, bool lk) {
relocs.emplace_back(l.index, RelocInfo{ offset, RelocKind::FormI });
base[offset++] = (op |
bitExt(lk, 31, 1)
);
}
void emit_reloc_B(uint32_t op, uint32_t cri, Label const& l, bool lk) {
(void)op;
(void)cri;
(void)l;
(void)lk;
std::abort();
void emit_reloc_B(uint32_t op, uint32_t bo, uint32_t cri, Label const& l, bool lk) {
relocs.emplace_back(l.index, RelocInfo{ offset, RelocKind::FormB });
base[offset++] = (op |
bitExt(bo, 6, 5)
| bitExt(cri, 11, 5)
| bitExt(lk, 31, 1)
);
}
void emit_XL(uint32_t op, uint32_t bt, uint32_t ba, uint32_t bb, bool lk) {
base[offset++] = __bswap32(op |
base[offset++] = (op |
bitExt(bt, 6, 5)
| bitExt(ba, 11, 5)
| bitExt(bb, 16, 5)
@ -209,7 +236,7 @@ struct Context {
);
}
void emit_A(uint32_t op, FPR const frt, FPR const fra, FPR const frb, FPR const frc, bool rc) {
base[offset++] = __bswap32(op |
base[offset++] = (op |
bitExt(frt.index, 6, 5)
| bitExt(fra.index, 11, 5)
| bitExt(frb.index, 16, 5)
@ -219,7 +246,7 @@ struct Context {
}
void emit_DS(uint32_t op, GPR const rt, GPR const ra, uint32_t d) {
//assert(d & 0x03 == 0);
base[offset++] = __bswap32(op |
base[offset++] = (op |
bitExt(rt.index, 6, 5)
| bitExt(ra.index, 11, 5)
| bitExt(d >> 2, 16, 14)
@ -237,7 +264,7 @@ struct Context {
}
void emit_MD(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) {
assert(mb <= 0x3f);
base[offset++] = __bswap32(op |
base[offset++] = (op |
bitExt(ra.index, 6, 5)
| bitExt(rs.index, 11, 5)
| bitExt(rb.index, 16, 5)
@ -247,7 +274,7 @@ struct Context {
}
void emit_MD(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, bool rc) {
assert(sh <= 0x3f && mb <= 0x3f);
base[offset++] = __bswap32(op |
base[offset++] = (op |
bitExt(ra.index, 6, 5)
| bitExt(rs.index, 11, 5)
| ((mb & 0x1f) << 6) | (mb & 0x20)
@ -256,7 +283,7 @@ struct Context {
);
}
void emit_MDS(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) {
base[offset++] = __bswap32(op |
base[offset++] = (op |
bitExt(ra.index, 6, 5)
| bitExt(rs.index, 11, 5)
| bitExt(rb.index, 16, 5)
@ -312,22 +339,27 @@ struct Context {
void CRMOVE(CPR const bx, CPR const by) { CROR(bx, by, by); }
void CRNOT(CPR const bx, CPR const by) { CRNOR(bx, by, by); }
void CMPLDI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index, 1, rx, v); }
void CMPLWI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index, 0, rx, v); }
void CMPLD(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index, 1, rx, ry); }
void CMPLW(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index, 0, rx, ry); }
void CMPLDI(GPR const rx, uint32_t v) { CMPLI(0, 1, rx, v); }
void CMPLWI(GPR const rx, uint32_t v) { CMPLI(0, 0, rx, v); }
void CMPLD(GPR const rx, GPR const ry) { CMPL(0, 1, rx, ry); }
void CMPLW(GPR const rx, GPR const ry) { CMPL(0, 0, rx, ry); }
void CMPLDI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index / 4, 1, rx, v); }
void CMPLWI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index / 4, 0, rx, v); }
void CMPLD(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index / 4, 1, rx, ry); }
void CMPLW(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index / 4, 0, rx, ry); }
void CMPWI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 0, rx, si); }
void CMPW(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 0, rx, ry); }
void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 1, rx, si); }
void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 1, rx, ry); }
void BLR() { BCLR(R0, CR0, R0); }
void CMPWI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index, 0, rx, si); }
void CMPW(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index, 0, rx, ry); }
void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index, 1, rx, si); }
void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index, 1, rx, ry); }
void CMPWI(GPR const rx, uint32_t si) { CMPI(0, 0, rx, si); }
void CMPW(GPR const rx, GPR const ry) { CMP(0, 0, rx, ry); }
void CMPDI(GPR const rx, uint32_t si) { CMPI(0, 1, rx, si); }
void CMPD(GPR const rx, GPR const ry) { CMP(0, 1, rx, ry); }
void BLR() {
base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0);
}
// TODO: PowerPC 11 stuff
void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) {

60
externals/powah/powah_gen_base.hpp

@ -30,32 +30,32 @@ void ANDC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, rt, ra,
void ANDC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, rt, ra, rb, true); }
void ANDI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x70000000, rt, ra, d); }
void ANDIS_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x74000000, rt, ra, d); }
void B(Label const& i) { emit_reloc_I(0x48000000, i); }
void BL(Label const& i) { emit_reloc_I(0x48000000, i); }
void BC(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); }
void BCL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); }
void BLT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); }
void BLTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); }
void BLE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); }
void BLEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); }
void BNG(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); }
void BNGL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); }
void BEQ(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, false); }
void BEQL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, true); }
void BGE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); }
void BGEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); }
void BNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); }
void BNLL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); }
void BGT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); }
void BGTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); }
void BNE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, false); }
void BNEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, true); }
void BSO(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); }
void BSOL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); }
void BUN(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); }
void BUNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); }
void BNS(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); }
void BNSL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); }
void B(Label const& i) { emit_reloc_I(0x48000000, i, false); }
void BL(Label const& i) { emit_reloc_I(0x48000000, i, true); }
void BC(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 0, cr.index + 0, i, false); }
void BCL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 0, cr.index + 0, i, true); }
void BLT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 0, i, false); }
void BLTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 0, i, true); }
void BLE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, false); }
void BLEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, true); }
void BNG(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, false); }
void BNGL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, true); }
void BEQ(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 2, i, false); }
void BEQL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 2, i, true); }
void BGE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, false); }
void BGEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, true); }
void BNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, false); }
void BNLL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, true); }
void BGT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 1, i, false); }
void BGTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 1, i, true); }
void BNE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 2, i, false); }
void BNEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 2, i, true); }
void BSO(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, false); }
void BSOL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, true); }
void BUN(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, false); }
void BUNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, true); }
void BNS(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 3, i, false); }
void BNSL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 3, i, true); }
void BCCTR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, ba.index, bb.index, false); }
void BCCTRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, ba.index, bb.index, true); }
void BCCTR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, cond2offset(ba), bb.index, false); }
@ -64,10 +64,10 @@ void BCLR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.ind
void BCLRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, ba.index, bb.index, true); }
void BCLR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, false); }
void BCLRL(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, true); }
void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); }
void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, GPR{(bf << 2) | l}, ra, d); }
void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); }
void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, GPR{(bf << 2) | l}, ra, d); }
void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, ra, GPR{(bf << 2) | l}, rb, false); }
void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, ra, GPR{(bf << 2) | l}, d); }
void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, ra, GPR{(bf << 2) | l}, rb, false); }
void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, ra, GPR{(bf << 2) | l}, d); }
void CNTLZD(GPR const rt, GPR const ra) { emit_X(0x7c000074, rt, ra, R0, false); }
void CNTLZD_(GPR const rt, GPR const ra) { emit_X(0x7c000074, rt, ra, R0, true); }
void CNTLZW(GPR const rt, GPR const ra) { emit_X(0x7c000034, rt, ra, R0, false); }

184
externals/powah/tests.cpp

@ -2,16 +2,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include <catch2/catch_test_macros.hpp>
#include <sys/mman.h>
#include "powah_emit.hpp"
#define EB32(X) __bswap32(X)
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);
REQUIRE(data[0] == EB32(0x00004238));
REQUIRE(data[1] == EB32(0x00004c3c));
}
TEST_CASE("ppc64: std/mr", "[ppc64]") {
@ -24,12 +27,12 @@ TEST_CASE("ppc64: std/mr", "[ppc64]") {
ctx.MR(powah::R30, powah::R3);
ctx.RLDICR(powah::R4, powah::R5, 25, 6);
ctx.STD(powah::R28, powah::R1, 160);
REQUIRE(data[0] == 0x900041fb);
REQUIRE(data[1] == 0x78239a7c);
REQUIRE(data[2] == 0xb000c1fb);
REQUIRE(data[3] == 0x781b7e7c);
REQUIRE(data[4] == 0x84c9a478);
REQUIRE(data[5] == 0xa00081fb);
REQUIRE(data[0] == EB32(0x900041fb));
REQUIRE(data[1] == EB32(0x78239a7c));
REQUIRE(data[2] == EB32(0xb000c1fb));
REQUIRE(data[3] == EB32(0x781b7e7c));
REQUIRE(data[4] == EB32(0x84c9a478));
REQUIRE(data[5] == EB32(0xa00081fb));
}
TEST_CASE("ppc64: sldi", "[ppc64]") {
@ -37,7 +40,7 @@ TEST_CASE("ppc64: sldi", "[ppc64]") {
powah::Context ctx(data.data(), data.size());
ctx.SLDI(powah::R3, powah::R5, 37);
REQUIRE(data[0] == 0x862ea378);
REQUIRE(data[0] == EB32(0x862ea378));
}
TEST_CASE("ppc64: rldicr", "[ppc64]") {
@ -48,11 +51,11 @@ TEST_CASE("ppc64: rldicr", "[ppc64]") {
ctx.RLDICR(powah::R1, powah::R1, 0, 1);
ctx.RLDICR(powah::R1, powah::R1, 1, 1);
ctx.RLDICR(powah::R1, powah::R1, 31, 31);
REQUIRE(data[0] == 0x04002178);
REQUIRE(data[1] == 0x04082178);
REQUIRE(data[2] == 0x44002178);
REQUIRE(data[3] == 0x44082178);
REQUIRE(data[4] == 0xc4ff2178);
REQUIRE(data[0] == EB32(0x04002178));
REQUIRE(data[1] == EB32(0x04082178));
REQUIRE(data[2] == EB32(0x44002178));
REQUIRE(data[3] == EB32(0x44082178));
REQUIRE(data[4] == EB32(0xc4ff2178));
}
TEST_CASE("ppc64: mr/or/std", "[ppc64]") {
@ -67,15 +70,15 @@ TEST_CASE("ppc64: mr/or/std", "[ppc64]") {
ctx.OR(powah::R3, powah::R3, powah::R26);
ctx.STD(powah::R3, powah::R1, 56);
ctx.MR(powah::R3, powah::R30);
REQUIRE(data[0] == 0x783bfb7c);
REQUIRE(data[1] == 0x7833dd7c);
REQUIRE(data[2] == 0x7823637c);
REQUIRE(data[3] == 0x78e3847f);
REQUIRE(data[4] == 0x820b014d);
REQUIRE(data[5] == 0x782bb97c);
REQUIRE(data[6] == 0x78d3637c);
REQUIRE(data[7] == 0x380061f8);
REQUIRE(data[8] == 0x78f3c37f);
REQUIRE(data[0] == EB32(0x783bfb7c));
REQUIRE(data[1] == EB32(0x7833dd7c));
REQUIRE(data[2] == EB32(0x7823637c));
REQUIRE(data[3] == EB32(0x78e3847f));
REQUIRE(data[4] == EB32(0x820b014d));
REQUIRE(data[5] == EB32(0x782bb97c));
REQUIRE(data[6] == EB32(0x78d3637c));
REQUIRE(data[7] == EB32(0x380061f8));
REQUIRE(data[8] == EB32(0x78f3c37f));
}
TEST_CASE("ppc64: ld/crand+addi", "[ppc64]") {
@ -93,18 +96,18 @@ TEST_CASE("ppc64: ld/crand+addi", "[ppc64]") {
ctx.ADDI(powah::R5, powah::R5, 1);
ctx.STD(powah::R26, powah::R1, 72);
ctx.STD(powah::R5, powah::R30, 1984);
REQUIRE(data[0] == 0x480081e8);
REQUIRE(data[1] == 0x5000a180);
REQUIRE(data[2] == 0x024a8a4e);
REQUIRE(data[3] == 0x0400c438);
REQUIRE(data[4] == 0xc807a474);
REQUIRE(data[5] == 0xc007bee8);
REQUIRE(data[6] == 0x54006188);
REQUIRE(data[7] == 0x0002da78);
REQUIRE(data[8] == 0x50008190);
REQUIRE(data[9] == 0x0100a538);
REQUIRE(data[10] == 0x480041fb);
REQUIRE(data[11] == 0xc007bef8);
REQUIRE(data[0] == EB32(0x480081e8));
REQUIRE(data[1] == EB32(0x5000a180));
REQUIRE(data[2] == EB32(0x024a8a4e));
REQUIRE(data[3] == EB32(0x0400c438));
REQUIRE(data[4] == EB32(0xc807a474));
REQUIRE(data[5] == EB32(0xc007bee8));
REQUIRE(data[6] == EB32(0x54006188));
REQUIRE(data[7] == EB32(0x0002da78));
REQUIRE(data[8] == EB32(0x50008190));
REQUIRE(data[9] == EB32(0x0100a538));
REQUIRE(data[10] == EB32(0x480041fb));
REQUIRE(data[11] == EB32(0xc007bef8));
}
TEST_CASE("ppc64: rotldi", "[ppc64]") {
@ -123,17 +126,102 @@ TEST_CASE("ppc64: rotldi", "[ppc64]") {
ctx.RLDIMI(powah::R4, powah::R5, 48, 8);
ctx.RLDIMI(powah::R4, powah::R3, 56, 0);
ctx.MR(powah::R3, powah::R4);
REQUIRE(data[0] == 0x00806578);
REQUIRE(data[1] == 0x00406478);
REQUIRE(data[2] == 0x2c44a478);
REQUIRE(data[3] == 0x00c06578);
REQUIRE(data[4] == 0x2c82a478);
REQUIRE(data[5] == 0x02006578);
REQUIRE(data[6] == 0x2cc0a478);
REQUIRE(data[7] == 0x02806578);
REQUIRE(data[8] == 0x0e44a478);
REQUIRE(data[9] == 0x02c06578);
REQUIRE(data[10] == 0x0e82a478);
REQUIRE(data[11] == 0x0ec06478);
REQUIRE(data[12] == 0x7823837c);
REQUIRE(data[0] == EB32(0x00806578));
REQUIRE(data[1] == EB32(0x00406478));
REQUIRE(data[2] == EB32(0x2c44a478));
REQUIRE(data[3] == EB32(0x00c06578));
REQUIRE(data[4] == EB32(0x2c82a478));
REQUIRE(data[5] == EB32(0x02006578));
REQUIRE(data[6] == EB32(0x2cc0a478));
REQUIRE(data[7] == EB32(0x02806578));
REQUIRE(data[8] == EB32(0x0e44a478));
REQUIRE(data[9] == EB32(0x02c06578));
REQUIRE(data[10] == EB32(0x0e82a478));
REQUIRE(data[11] == EB32(0x0ec06478));
REQUIRE(data[12] == EB32(0x7823837c));
}
#if 1 //&& defined(ARCHITECTURE_ppc64)
/*
0: d619637c mullw 3, 3, 3
4: 20006378 clrldi 3, 3, 32
8: 2000804e blr
*/
TEST_CASE("ppc64: live-exec square", "[ppc64]") {
uint32_t* data = (uint32_t*)mmap(nullptr, 4096, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
REQUIRE(data != nullptr);
powah::Context ctx((void*)data, 4096);
ctx.MULLW(powah::R3, powah::R3, powah::R3);
ctx.CLRLDI(powah::R3, powah::R3, 32);
ctx.BLR();
REQUIRE(data[0] == EB32(0xd619637c));
REQUIRE(data[1] == EB32(0x20006378));
REQUIRE(data[2] == EB32(0x2000804e));
auto* fn = (int (*)(int))data;
REQUIRE(fn(4) == 4 * 4);
REQUIRE(fn(8) == 8 * 8);
munmap((void*)data, 4096);
}
/*
int f(int a, int b, int c) {
a += (a > b) ? b - 0xffff : c + 402, b += 2, c &= b*c;
return a * a + b ^ c & b;
}
*/
TEST_CASE("ppc64: live-exec xoralu", "[ppc64]") {
uint32_t* data = (uint32_t*)mmap(nullptr, 4096, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
REQUIRE(data != nullptr);
powah::Context ctx((void*)data, 4096);
powah::Label l_2 = ctx.DefineLabel();
powah::Label l_3 = ctx.DefineLabel();
ctx.CMPW(powah::R3, powah::R4);
ctx.BGT(powah::CR0, l_2);
ctx.ADDI(powah::R6, powah::R5, 402);
ctx.B(l_3);
ctx.LABEL(l_2);
ctx.ADDI(powah::R6, powah::R4, 1);
ctx.ADDIS(powah::R6, powah::R6, -1);
ctx.LABEL(l_3);
ctx.ADDI(powah::R4, powah::R4, 2);
ctx.ADD(powah::R3, powah::R6, powah::R3);
ctx.MULLW(powah::R6, powah::R4, powah::R5);
ctx.MULLW(powah::R3, powah::R3, powah::R3);
ctx.AND(powah::R5, powah::R5, powah::R6);
ctx.ADD(powah::R3, powah::R3, powah::R4);
ctx.AND(powah::R4, powah::R5, powah::R4);
ctx.XOR(powah::R3, powah::R3, powah::R4);
ctx.EXTSW(powah::R3, powah::R3);
ctx.BLR();
ctx.ApplyRelocs();
REQUIRE(data[0] == EB32(0x0020037c));
REQUIRE(data[1] == EB32(0x0c008141));
REQUIRE(data[2] == EB32(0x9201c538));
REQUIRE(data[3] == EB32(0x0c000048));
REQUIRE(data[4] == EB32(0x0100c438));
REQUIRE(data[5] == EB32(0xffffc63c));
REQUIRE(data[6] == EB32(0x02008438));
REQUIRE(data[7] == EB32(0x141a667c));
REQUIRE(data[8] == EB32(0xd629c47c));
REQUIRE(data[9] == EB32(0xd619637c));
REQUIRE(data[10] == EB32(0x3830a57c));
REQUIRE(data[11] == EB32(0x1422637c));
REQUIRE(data[12] == EB32(0x3820a47c));
REQUIRE(data[13] == EB32(0x7822637c));
REQUIRE(data[14] == EB32(0xb407637c));
REQUIRE(data[15] == EB32(0x2000804e));
auto const orig = [](int a, int b, int c) {
a += (a > b) ? b - 0xffff : c + 402, b += 2, c &= b*c;
return a * a + b ^ c & b;
};
auto* fn = (int (*)(int, int, int))data;
REQUIRE(fn(0, 1, 2) == orig(0, 1, 2));
munmap((void*)data, 4096);
}
#endif
Loading…
Cancel
Save