parent
ad422a4f09
commit
0e13cb4d7c
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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, 0, rx, si); }
|
||||
void CMPW(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index, 0, rx, ry); }
|
||||
void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index, 1, rx, si); }
|
||||
void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index, 1, rx, ry); }
|
||||
void CMPWI(GPR const rx, uint32_t si) { CMPI(0, 0, rx, si); }
|
||||
void CMPW(GPR const rx, GPR const ry) { CMP(0, 0, rx, ry); }
|
||||
void CMPDI(GPR const rx, uint32_t si) { CMPI(0, 1, rx, si); }
|
||||
void CMPD(GPR const rx, GPR const ry) { CMP(0, 1, rx, ry); }
|
||||
|
||||
void CMPWI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 0, rx, si); }
|
||||
void CMPW(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 0, rx, ry); }
|
||||
void CMPDI(CPR const cr, GPR const rx, uint32_t si) { CMPI(cr.index / 4, 1, rx, si); }
|
||||
void CMPD(CPR const cr, GPR const rx, GPR const ry) { CMP(cr.index / 4, 1, rx, ry); }
|
||||
|
||||
void BLR() { BCLR(R0, CR0, R0); }
|
||||
void BLR() {
|
||||
base[offset++] = 0x4e800020; //BCLR(R0, CR0, R0);
|
||||
}
|
||||
|
||||
// TODO: PowerPC 11 stuff
|
||||
void ISEL(GPR const rd, GPR const ra, GPR const rb, uint32_t d) {
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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…
Reference in New Issue