From 36c60fab0e7842a3718c03b9be2f1c6798c0433a Mon Sep 17 00:00:00 2001 From: lizzie Date: Mon, 3 Nov 2025 00:23:06 +0000 Subject: [PATCH] relocations Signed-off-by: lizzie --- externals/powah/data2code.c | 44 +++---- externals/powah/powah_emit.hpp | 108 +++++++++++------ externals/powah/powah_gen_base.hpp | 60 +++++----- externals/powah/tests.cpp | 184 +++++++++++++++++++++-------- 4 files changed, 258 insertions(+), 138 deletions(-) diff --git a/externals/powah/data2code.c b/externals/powah/data2code.c index 3e6bad32c8..90b94202c7 100644 --- a/externals/powah/data2code.c +++ b/externals/powah/data2code.c @@ -26,20 +26,20 @@ int main(int argc, char *argv[]) { *opc++ = '\0'; char *sec = strchr(opc, ','); if (sec) { - struct b_info { const char *s; int o; } infos[] = { - {"",1}, - {"LT",1}, - {"LE",2}, - {"NG",2}, - {"EQ",3}, - {"GE",1}, - {"NL",1}, - {"GT",2}, - {"NE",3}, - {"SO",4}, - {"UN",4}, - {"NS",4}, - {"NU",4}, + struct b_info { const char *s; int o; int p; } infos[] = { + {"",1,0}, + {"LT",1,12}, + {"LE",2,4}, + {"NG",2,4}, + {"EQ",3,12}, + {"GE",1,4}, + {"NL",1,4}, + {"GT",2,12}, + {"NE",3,4}, + {"SO",4,12}, + {"UN",4,12}, + {"NS",4,4}, + {"NU",4,4}, }; if (strchr(mem, '[') != NULL) *strchr(mem, '[') = '\0'; @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) { || !strcmp(mem, "CMP")) { printf( "void %s(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) {" - " emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, rb, false); " + " emit_%s(0x%08x, ra, GPR{(bf << 2) | l}, rb, false); " "}\n" , mem, form, i_opcode << 26); } else if (!strcmp(mem, "CNTLZD") || !strcmp(mem, "CNTLZW") @@ -133,26 +133,26 @@ int main(int argc, char *argv[]) { } else if (!strcmp(form, "I")) { printf( "void %s(Label const& i) {" - " emit_reloc_%s(0x%08x, i); " + " emit_reloc_%s(0x%08x, i, false); " "}\n" , mem, form, i_opcode << 26); printf( "void %sL(Label const& i) {" - " emit_reloc_%s(0x%08x, i); " + " emit_reloc_%s(0x%08x, i, true); " "}\n" , mem, form, i_opcode << 26); } else if (!strcmp(form, "B")) { for (int i = 0; i < 12; ++i) { printf( "void %s%s(CPR const cr, Label const& i) {" - " emit_reloc_%s(0x%08x, cr.index + %i, i, false); " + " emit_reloc_%s(0x%08x, %i, cr.index + %i, i, false); " "}\n" - , mem, infos[i].s, form, i_opcode << 26, infos[i].o); + , mem, infos[i].s, form, i_opcode << 26, infos[i].p, infos[i].o - 1); printf( "void %s%sL(CPR const cr, Label const& i) {" - " emit_reloc_%s(0x%08x, cr.index + %i, i, true); " + " emit_reloc_%s(0x%08x, %i, cr.index + %i, i, true); " "}\n" - , mem, infos[i].s, form, i_opcode << 26, infos[i].o); + , mem, infos[i].s, form, i_opcode << 26, infos[i].p, infos[i].o - 1); if (!strcmp(mem, "BC")) mem[1] = '\0'; } } else if (!strcmp(form, "D")) { @@ -160,7 +160,7 @@ int main(int argc, char *argv[]) { || !strcmp(mem, "CMPI")) { printf( "void %s(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) {" - " emit_%s(0x%08x, GPR{(bf << 2) | l}, ra, d); " + " emit_%s(0x%08x, ra, GPR{(bf << 2) | l}, d); " "}\n" , mem, form, i_opcode << 26); } else { diff --git a/externals/powah/powah_emit.hpp b/externals/powah/powah_emit.hpp index 82cb2450c9..bc1bfb803b 100644 --- a/externals/powah/powah_emit.hpp +++ b/externals/powah/powah_emit.hpp @@ -110,6 +110,15 @@ constexpr inline CPR CR5{20}; constexpr inline CPR CR6{24}; constexpr inline CPR CR7{28}; +enum class RelocKind : uint8_t { + FormB, + FormI, +}; +struct RelocInfo { + uint32_t offset; + RelocKind kind; +}; + struct Context { Context() = default; Context(void* ptr, size_t size) @@ -121,10 +130,26 @@ struct Context { ~Context() = default; std::vector labels; + std::vector> relocs; Label DefineLabel() { labels.push_back(0); - return Label{ uint32_t(labels.size()) }; + return Label{ uint32_t(labels.size() - 1) }; + } + + void ApplyRelocs() { + for (auto const [index, info] : relocs) { + assert(labels[index] != 0); //label must have an addr + switch (info.kind) { + case RelocKind::FormB: + base[info.offset] |= bitExt(labels[index] - info.offset, 16, 14); + break; + case RelocKind::FormI: + base[info.offset] |= bitExt(labels[index] - info.offset, 6, 24); + break; + } + } + relocs.clear(); } void LABEL(Label l) { @@ -155,16 +180,16 @@ struct Context { return (value & mask) << (32 - (n + offs)); } void emit_XO(uint32_t op, GPR const rt, GPR const ra, GPR const rb, bool oe, bool rc) { - (void)op; - (void)rt; - (void)ra; - (void)rb; - (void)oe; - (void)rc; - std::abort(); + base[offset++] = (op | + bitExt(rt.index, 6, 5) + | bitExt(ra.index, 11, 5) + | bitExt(rb.index, 16, 5) + | bitExt(oe, 21, 1) + | bitExt(rc, 31, 1) + ); } void emit_D(uint32_t op, GPR const rt, GPR const ra, uint32_t d) { - base[offset++] = __bswap32(op | + base[offset++] = (op | (op == 0x74000000 ? (bitExt(ra.index, 6, 5) | bitExt(rt.index, 11, 5)) : (bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5))) @@ -172,7 +197,7 @@ struct Context { ); } void emit_X(uint32_t op, GPR const ra, GPR const rt, GPR const rb, bool rc) { - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5) | bitExt(rb.index, 16, 5) @@ -180,7 +205,7 @@ struct Context { ); } void emit_XS(uint32_t op, GPR const rt, GPR const ra, uint32_t sh, bool rc) { - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5) | bitExt(sh, 16, 5) @@ -188,20 +213,22 @@ struct Context { | bitExt(rc, 31, 1) ); } - void emit_reloc_I(uint32_t op, Label const& l) { - (void)op; - (void)l; - std::abort(); + void emit_reloc_I(uint32_t op, Label const& l, bool lk) { + relocs.emplace_back(l.index, RelocInfo{ offset, RelocKind::FormI }); + base[offset++] = (op | + bitExt(lk, 31, 1) + ); } - void emit_reloc_B(uint32_t op, uint32_t cri, Label const& l, bool lk) { - (void)op; - (void)cri; - (void)l; - (void)lk; - std::abort(); + void emit_reloc_B(uint32_t op, uint32_t bo, uint32_t cri, Label const& l, bool lk) { + relocs.emplace_back(l.index, RelocInfo{ offset, RelocKind::FormB }); + base[offset++] = (op | + bitExt(bo, 6, 5) + | bitExt(cri, 11, 5) + | bitExt(lk, 31, 1) + ); } void emit_XL(uint32_t op, uint32_t bt, uint32_t ba, uint32_t bb, bool lk) { - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(bt, 6, 5) | bitExt(ba, 11, 5) | bitExt(bb, 16, 5) @@ -209,7 +236,7 @@ struct Context { ); } void emit_A(uint32_t op, FPR const frt, FPR const fra, FPR const frb, FPR const frc, bool rc) { - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(frt.index, 6, 5) | bitExt(fra.index, 11, 5) | bitExt(frb.index, 16, 5) @@ -219,7 +246,7 @@ struct Context { } void emit_DS(uint32_t op, GPR const rt, GPR const ra, uint32_t d) { //assert(d & 0x03 == 0); - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(rt.index, 6, 5) | bitExt(ra.index, 11, 5) | bitExt(d >> 2, 16, 14) @@ -237,7 +264,7 @@ struct Context { } void emit_MD(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) { assert(mb <= 0x3f); - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(ra.index, 6, 5) | bitExt(rs.index, 11, 5) | bitExt(rb.index, 16, 5) @@ -247,7 +274,7 @@ struct Context { } void emit_MD(uint32_t op, GPR const rs, GPR const ra, uint32_t sh, uint32_t mb, bool rc) { assert(sh <= 0x3f && mb <= 0x3f); - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(ra.index, 6, 5) | bitExt(rs.index, 11, 5) | ((mb & 0x1f) << 6) | (mb & 0x20) @@ -256,7 +283,7 @@ struct Context { ); } void emit_MDS(uint32_t op, GPR const rs, GPR const ra, GPR const rb, uint32_t mb, bool rc) { - base[offset++] = __bswap32(op | + base[offset++] = (op | bitExt(ra.index, 6, 5) | bitExt(rs.index, 11, 5) | bitExt(rb.index, 16, 5) @@ -312,22 +339,27 @@ struct Context { void CRMOVE(CPR const bx, CPR const by) { CROR(bx, by, by); } void CRNOT(CPR const bx, CPR const by) { CRNOR(bx, by, by); } + void CMPLDI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index, 1, rx, v); } + void CMPLWI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index, 0, rx, v); } + void CMPLD(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index, 1, rx, ry); } + void CMPLW(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index, 0, rx, ry); } void CMPLDI(GPR const rx, uint32_t v) { CMPLI(0, 1, rx, v); } void CMPLWI(GPR const rx, uint32_t v) { CMPLI(0, 0, rx, v); } void CMPLD(GPR const rx, GPR const ry) { CMPL(0, 1, rx, ry); } void CMPLW(GPR const rx, GPR const ry) { CMPL(0, 0, rx, ry); } - void CMPLDI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index / 4, 1, rx, v); } - void CMPLWI(CPR const cr, GPR const rx, uint32_t v) { CMPLI(cr.index / 4, 0, rx, v); } - void CMPLD(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index / 4, 1, rx, ry); } - void CMPLW(CPR const cr, GPR const rx, GPR const ry) { CMPL(cr.index / 4, 0, rx, ry); } - - void CMPWI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 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) { diff --git a/externals/powah/powah_gen_base.hpp b/externals/powah/powah_gen_base.hpp index 7783bf56d6..e7260a3d75 100644 --- a/externals/powah/powah_gen_base.hpp +++ b/externals/powah/powah_gen_base.hpp @@ -30,32 +30,32 @@ void ANDC(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, rt, ra, void ANDC_(GPR const rt, GPR const ra, GPR const rb) { emit_X(0x7c000078, rt, ra, rb, true); } void ANDI_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x70000000, rt, ra, d); } void ANDIS_(GPR const rt, GPR const ra, uint32_t d) { emit_D(0x74000000, rt, ra, d); } -void B(Label const& i) { emit_reloc_I(0x48000000, i); } -void BL(Label const& i) { emit_reloc_I(0x48000000, i); } -void BC(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } -void BCL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } -void BLT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } -void BLTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } -void BLE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); } -void BLEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); } -void BNG(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); } -void BNGL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); } -void BEQ(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, false); } -void BEQL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, true); } -void BGE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } -void BGEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } -void BNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, false); } -void BNLL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 1, i, true); } -void BGT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, false); } -void BGTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 2, i, true); } -void BNE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, false); } -void BNEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 3, i, true); } -void BSO(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); } -void BSOL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); } -void BUN(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); } -void BUNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); } -void BNS(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, false); } -void BNSL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, cr.index + 4, i, true); } +void B(Label const& i) { emit_reloc_I(0x48000000, i, false); } +void BL(Label const& i) { emit_reloc_I(0x48000000, i, true); } +void BC(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 0, cr.index + 0, i, false); } +void BCL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 0, cr.index + 0, i, true); } +void BLT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 0, i, false); } +void BLTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 0, i, true); } +void BLE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, false); } +void BLEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, true); } +void BNG(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, false); } +void BNGL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 1, i, true); } +void BEQ(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 2, i, false); } +void BEQL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 2, i, true); } +void BGE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, false); } +void BGEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, true); } +void BNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, false); } +void BNLL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 0, i, true); } +void BGT(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 1, i, false); } +void BGTL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 1, i, true); } +void BNE(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 2, i, false); } +void BNEL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 2, i, true); } +void BSO(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, false); } +void BSOL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, true); } +void BUN(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, false); } +void BUNL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 12, cr.index + 3, i, true); } +void BNS(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 3, i, false); } +void BNSL(CPR const cr, Label const& i) { emit_reloc_B(0x40000000, 4, cr.index + 3, i, true); } void BCCTR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, ba.index, bb.index, false); } void BCCTRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, ba.index, bb.index, true); } void BCCTR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000420, bt.index, cond2offset(ba), bb.index, false); } @@ -64,10 +64,10 @@ void BCLR(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.ind void BCLRL(GPR const bt, CPR const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, ba.index, bb.index, true); } void BCLR(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, false); } void BCLRL(GPR const bt, Cond const ba, GPR const bb) { emit_XL(0x4c000020, bt.index, cond2offset(ba), bb.index, true); } -void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); } -void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, GPR{(bf << 2) | l}, ra, d); } -void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, GPR{(bf << 2) | l}, ra, rb, false); } -void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, GPR{(bf << 2) | l}, ra, d); } +void CMP(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, ra, GPR{(bf << 2) | l}, rb, false); } +void CMPI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x2c000000, ra, GPR{(bf << 2) | l}, d); } +void CMPL(uint32_t bf, uint32_t l, GPR const ra, GPR const rb) { emit_X(0x7c000000, ra, GPR{(bf << 2) | l}, rb, false); } +void CMPLI(uint32_t bf, uint32_t l, GPR const ra, uint32_t d) { emit_D(0x28000000, ra, GPR{(bf << 2) | l}, d); } void CNTLZD(GPR const rt, GPR const ra) { emit_X(0x7c000074, rt, ra, R0, false); } void CNTLZD_(GPR const rt, GPR const ra) { emit_X(0x7c000074, rt, ra, R0, true); } void CNTLZW(GPR const rt, GPR const ra) { emit_X(0x7c000034, rt, ra, R0, false); } diff --git a/externals/powah/tests.cpp b/externals/powah/tests.cpp index 1ef820afcd..6d555b4f4a 100644 --- a/externals/powah/tests.cpp +++ b/externals/powah/tests.cpp @@ -2,16 +2,19 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include +#include #include "powah_emit.hpp" +#define EB32(X) __bswap32(X) + TEST_CASE("ppc64: addi", "[ppc64]") { std::vector data(64); powah::Context ctx(data.data(), data.size()); ctx.ADDI(powah::R2, powah::R2, 0); ctx.ADDIS(powah::R2, powah::R12, 0); - REQUIRE(data[0] == 0x00004238); - REQUIRE(data[1] == 0x00004c3c); + REQUIRE(data[0] == EB32(0x00004238)); + REQUIRE(data[1] == EB32(0x00004c3c)); } TEST_CASE("ppc64: std/mr", "[ppc64]") { @@ -24,12 +27,12 @@ TEST_CASE("ppc64: std/mr", "[ppc64]") { ctx.MR(powah::R30, powah::R3); ctx.RLDICR(powah::R4, powah::R5, 25, 6); ctx.STD(powah::R28, powah::R1, 160); - REQUIRE(data[0] == 0x900041fb); - REQUIRE(data[1] == 0x78239a7c); - REQUIRE(data[2] == 0xb000c1fb); - REQUIRE(data[3] == 0x781b7e7c); - REQUIRE(data[4] == 0x84c9a478); - REQUIRE(data[5] == 0xa00081fb); + REQUIRE(data[0] == EB32(0x900041fb)); + REQUIRE(data[1] == EB32(0x78239a7c)); + REQUIRE(data[2] == EB32(0xb000c1fb)); + REQUIRE(data[3] == EB32(0x781b7e7c)); + REQUIRE(data[4] == EB32(0x84c9a478)); + REQUIRE(data[5] == EB32(0xa00081fb)); } TEST_CASE("ppc64: sldi", "[ppc64]") { @@ -37,7 +40,7 @@ TEST_CASE("ppc64: sldi", "[ppc64]") { powah::Context ctx(data.data(), data.size()); ctx.SLDI(powah::R3, powah::R5, 37); - REQUIRE(data[0] == 0x862ea378); + REQUIRE(data[0] == EB32(0x862ea378)); } TEST_CASE("ppc64: rldicr", "[ppc64]") { @@ -48,11 +51,11 @@ TEST_CASE("ppc64: rldicr", "[ppc64]") { ctx.RLDICR(powah::R1, powah::R1, 0, 1); ctx.RLDICR(powah::R1, powah::R1, 1, 1); ctx.RLDICR(powah::R1, powah::R1, 31, 31); - REQUIRE(data[0] == 0x04002178); - REQUIRE(data[1] == 0x04082178); - REQUIRE(data[2] == 0x44002178); - REQUIRE(data[3] == 0x44082178); - REQUIRE(data[4] == 0xc4ff2178); + REQUIRE(data[0] == EB32(0x04002178)); + REQUIRE(data[1] == EB32(0x04082178)); + REQUIRE(data[2] == EB32(0x44002178)); + REQUIRE(data[3] == EB32(0x44082178)); + REQUIRE(data[4] == EB32(0xc4ff2178)); } TEST_CASE("ppc64: mr/or/std", "[ppc64]") { @@ -67,15 +70,15 @@ TEST_CASE("ppc64: mr/or/std", "[ppc64]") { ctx.OR(powah::R3, powah::R3, powah::R26); ctx.STD(powah::R3, powah::R1, 56); ctx.MR(powah::R3, powah::R30); - REQUIRE(data[0] == 0x783bfb7c); - REQUIRE(data[1] == 0x7833dd7c); - REQUIRE(data[2] == 0x7823637c); - REQUIRE(data[3] == 0x78e3847f); - REQUIRE(data[4] == 0x820b014d); - REQUIRE(data[5] == 0x782bb97c); - REQUIRE(data[6] == 0x78d3637c); - REQUIRE(data[7] == 0x380061f8); - REQUIRE(data[8] == 0x78f3c37f); + REQUIRE(data[0] == EB32(0x783bfb7c)); + REQUIRE(data[1] == EB32(0x7833dd7c)); + REQUIRE(data[2] == EB32(0x7823637c)); + REQUIRE(data[3] == EB32(0x78e3847f)); + REQUIRE(data[4] == EB32(0x820b014d)); + REQUIRE(data[5] == EB32(0x782bb97c)); + REQUIRE(data[6] == EB32(0x78d3637c)); + REQUIRE(data[7] == EB32(0x380061f8)); + REQUIRE(data[8] == EB32(0x78f3c37f)); } TEST_CASE("ppc64: ld/crand+addi", "[ppc64]") { @@ -93,18 +96,18 @@ TEST_CASE("ppc64: ld/crand+addi", "[ppc64]") { ctx.ADDI(powah::R5, powah::R5, 1); ctx.STD(powah::R26, powah::R1, 72); ctx.STD(powah::R5, powah::R30, 1984); - REQUIRE(data[0] == 0x480081e8); - REQUIRE(data[1] == 0x5000a180); - REQUIRE(data[2] == 0x024a8a4e); - REQUIRE(data[3] == 0x0400c438); - REQUIRE(data[4] == 0xc807a474); - REQUIRE(data[5] == 0xc007bee8); - REQUIRE(data[6] == 0x54006188); - REQUIRE(data[7] == 0x0002da78); - REQUIRE(data[8] == 0x50008190); - REQUIRE(data[9] == 0x0100a538); - REQUIRE(data[10] == 0x480041fb); - REQUIRE(data[11] == 0xc007bef8); + REQUIRE(data[0] == EB32(0x480081e8)); + REQUIRE(data[1] == EB32(0x5000a180)); + REQUIRE(data[2] == EB32(0x024a8a4e)); + REQUIRE(data[3] == EB32(0x0400c438)); + REQUIRE(data[4] == EB32(0xc807a474)); + REQUIRE(data[5] == EB32(0xc007bee8)); + REQUIRE(data[6] == EB32(0x54006188)); + REQUIRE(data[7] == EB32(0x0002da78)); + REQUIRE(data[8] == EB32(0x50008190)); + REQUIRE(data[9] == EB32(0x0100a538)); + REQUIRE(data[10] == EB32(0x480041fb)); + REQUIRE(data[11] == EB32(0xc007bef8)); } TEST_CASE("ppc64: rotldi", "[ppc64]") { @@ -123,17 +126,102 @@ TEST_CASE("ppc64: rotldi", "[ppc64]") { ctx.RLDIMI(powah::R4, powah::R5, 48, 8); ctx.RLDIMI(powah::R4, powah::R3, 56, 0); ctx.MR(powah::R3, powah::R4); - REQUIRE(data[0] == 0x00806578); - REQUIRE(data[1] == 0x00406478); - REQUIRE(data[2] == 0x2c44a478); - REQUIRE(data[3] == 0x00c06578); - REQUIRE(data[4] == 0x2c82a478); - REQUIRE(data[5] == 0x02006578); - REQUIRE(data[6] == 0x2cc0a478); - REQUIRE(data[7] == 0x02806578); - REQUIRE(data[8] == 0x0e44a478); - REQUIRE(data[9] == 0x02c06578); - REQUIRE(data[10] == 0x0e82a478); - REQUIRE(data[11] == 0x0ec06478); - REQUIRE(data[12] == 0x7823837c); + REQUIRE(data[0] == EB32(0x00806578)); + REQUIRE(data[1] == EB32(0x00406478)); + REQUIRE(data[2] == EB32(0x2c44a478)); + REQUIRE(data[3] == EB32(0x00c06578)); + REQUIRE(data[4] == EB32(0x2c82a478)); + REQUIRE(data[5] == EB32(0x02006578)); + REQUIRE(data[6] == EB32(0x2cc0a478)); + REQUIRE(data[7] == EB32(0x02806578)); + REQUIRE(data[8] == EB32(0x0e44a478)); + REQUIRE(data[9] == EB32(0x02c06578)); + REQUIRE(data[10] == EB32(0x0e82a478)); + REQUIRE(data[11] == EB32(0x0ec06478)); + REQUIRE(data[12] == EB32(0x7823837c)); +} + +#if 1 //&& defined(ARCHITECTURE_ppc64) +/* + 0: d619637c mullw 3, 3, 3 + 4: 20006378 clrldi 3, 3, 32 + 8: 2000804e blr +*/ +TEST_CASE("ppc64: live-exec square", "[ppc64]") { + uint32_t* data = (uint32_t*)mmap(nullptr, 4096, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + REQUIRE(data != nullptr); + + powah::Context ctx((void*)data, 4096); + ctx.MULLW(powah::R3, powah::R3, powah::R3); + ctx.CLRLDI(powah::R3, powah::R3, 32); + ctx.BLR(); + REQUIRE(data[0] == EB32(0xd619637c)); + REQUIRE(data[1] == EB32(0x20006378)); + REQUIRE(data[2] == EB32(0x2000804e)); + + auto* fn = (int (*)(int))data; + REQUIRE(fn(4) == 4 * 4); + REQUIRE(fn(8) == 8 * 8); + + munmap((void*)data, 4096); +} + +/* +int f(int a, int b, int c) { + a += (a > b) ? b - 0xffff : c + 402, b += 2, c &= b*c; + return a * a + b ^ c & b; +} +*/ +TEST_CASE("ppc64: live-exec xoralu", "[ppc64]") { + uint32_t* data = (uint32_t*)mmap(nullptr, 4096, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + REQUIRE(data != nullptr); + + powah::Context ctx((void*)data, 4096); + powah::Label l_2 = ctx.DefineLabel(); + powah::Label l_3 = ctx.DefineLabel(); + ctx.CMPW(powah::R3, powah::R4); + ctx.BGT(powah::CR0, l_2); + ctx.ADDI(powah::R6, powah::R5, 402); + ctx.B(l_3); + ctx.LABEL(l_2); + ctx.ADDI(powah::R6, powah::R4, 1); + ctx.ADDIS(powah::R6, powah::R6, -1); + ctx.LABEL(l_3); + ctx.ADDI(powah::R4, powah::R4, 2); + ctx.ADD(powah::R3, powah::R6, powah::R3); + ctx.MULLW(powah::R6, powah::R4, powah::R5); + ctx.MULLW(powah::R3, powah::R3, powah::R3); + ctx.AND(powah::R5, powah::R5, powah::R6); + ctx.ADD(powah::R3, powah::R3, powah::R4); + ctx.AND(powah::R4, powah::R5, powah::R4); + ctx.XOR(powah::R3, powah::R3, powah::R4); + ctx.EXTSW(powah::R3, powah::R3); + ctx.BLR(); + ctx.ApplyRelocs(); + REQUIRE(data[0] == EB32(0x0020037c)); + REQUIRE(data[1] == EB32(0x0c008141)); + REQUIRE(data[2] == EB32(0x9201c538)); + REQUIRE(data[3] == EB32(0x0c000048)); + REQUIRE(data[4] == EB32(0x0100c438)); + REQUIRE(data[5] == EB32(0xffffc63c)); + REQUIRE(data[6] == EB32(0x02008438)); + REQUIRE(data[7] == EB32(0x141a667c)); + REQUIRE(data[8] == EB32(0xd629c47c)); + REQUIRE(data[9] == EB32(0xd619637c)); + REQUIRE(data[10] == EB32(0x3830a57c)); + REQUIRE(data[11] == EB32(0x1422637c)); + REQUIRE(data[12] == EB32(0x3820a47c)); + REQUIRE(data[13] == EB32(0x7822637c)); + REQUIRE(data[14] == EB32(0xb407637c)); + REQUIRE(data[15] == EB32(0x2000804e)); + + auto const orig = [](int a, int b, int c) { + a += (a > b) ? b - 0xffff : c + 402, b += 2, c &= b*c; + return a * a + b ^ c & b; + }; + auto* fn = (int (*)(int, int, int))data; + REQUIRE(fn(0, 1, 2) == orig(0, 1, 2)); + + munmap((void*)data, 4096); } +#endif