Implement some instructions.

This commit is contained in:
Skyth 2024-09-10 23:16:21 +03:00
parent 57ebe48cf7
commit 28e6ba92f8
2 changed files with 138 additions and 12 deletions

View File

@ -6,7 +6,7 @@
#include <disasm.h> #include <disasm.h>
#include <filesystem> #include <filesystem>
#define TEST_FILE "add.elf" #define TEST_FILE "cond.elf"
int main() int main()
{ {
@ -69,6 +69,10 @@ int main()
ppc_insn insn; ppc_insn insn;
while (base < end) while (base < end)
{ {
auto block = fn.SearchBlock(base);
if (block != -1 && (fn.base + fn.blocks[block].base) == base)
std::println(f, "loc_{:X}:", base);
ppc::Disassemble(data, 4, base, insn); ppc::Disassemble(data, 4, base, insn);
base += 4; base += 4;
@ -79,6 +83,8 @@ int main()
} }
else else
{ {
// TODO: need to handle instructions that treat r0 as 0
std::println(f, "\t// {:x} {} {}", base - 4, insn.opcode->name, insn.op_str); std::println(f, "\t// {:x} {} {}", base - 4, insn.opcode->name, insn.op_str);
switch (insn.opcode->id) switch (insn.opcode->id)
{ {
@ -88,17 +94,44 @@ int main()
break; break;
case PPC_INST_ADDI: case PPC_INST_ADDI:
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 + {};", insn.operands[0], insn.operands[1], insn.operands[2]); std::println(f, "\tctx.r{}.s64 = ctx.r{}.s64 + {};", insn.operands[0], insn.operands[1], static_cast<int32_t>(insn.operands[2]));
break; break;
case PPC_INST_ADDIC: case PPC_INST_ADDIC:
break;
case PPC_INST_ADDIS: case PPC_INST_ADDIS:
// TODO: validate the sign extend
std::println(f, "\tctx.r{}.s64 = ctx.r{}.s64 + {};", insn.operands[0], insn.operands[1], static_cast<int32_t>(insn.operands[2] << 16));
break;
case PPC_INST_ADDZE: case PPC_INST_ADDZE:
break;
case PPC_INST_AND: case PPC_INST_AND:
// TODO: . variant
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_ANDC: case PPC_INST_ANDC:
// TODO: . variant
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & ~ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_ANDI: case PPC_INST_ANDI:
// TODO: . variant
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & {};", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_ANDIS: case PPC_INST_ANDIS:
// TODO: . variant
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & {};", insn.operands[0], insn.operands[1], insn.operands[2] << 16);
break;
case PPC_INST_ATTN: case PPC_INST_ATTN:
// undefined instruction
break;
case PPC_INST_B: case PPC_INST_B:
case PPC_INST_BCTR: case PPC_INST_BCTR:
case PPC_INST_BCTRL: case PPC_INST_BCTRL:
@ -159,8 +192,15 @@ int main()
case PPC_INST_CNTLZD: case PPC_INST_CNTLZD:
case PPC_INST_CNTLZW: case PPC_INST_CNTLZW:
case PPC_INST_DB16CYC: case PPC_INST_DB16CYC:
case PPC_INST_DCBF: case PPC_INST_DCBF:
// no op
break;
case PPC_INST_DCBT: case PPC_INST_DCBT:
// no op
break;
case PPC_INST_DCBTST: case PPC_INST_DCBTST:
case PPC_INST_DCBZ: case PPC_INST_DCBZ:
case PPC_INST_DCBZL: case PPC_INST_DCBZL:
@ -168,7 +208,12 @@ int main()
case PPC_INST_DIVDU: case PPC_INST_DIVDU:
case PPC_INST_DIVW: case PPC_INST_DIVW:
case PPC_INST_DIVWU: case PPC_INST_DIVWU:
break;
case PPC_INST_EIEIO: case PPC_INST_EIEIO:
// no op
break;
case PPC_INST_EXTSB: case PPC_INST_EXTSB:
case PPC_INST_EXTSH: case PPC_INST_EXTSH:
case PPC_INST_EXTSW: case PPC_INST_EXTSW:
@ -201,10 +246,26 @@ int main()
case PPC_INST_FSQRTS: case PPC_INST_FSQRTS:
case PPC_INST_FSUB: case PPC_INST_FSUB:
case PPC_INST_FSUBS: case PPC_INST_FSUBS:
break;
case PPC_INST_LBZ: case PPC_INST_LBZ:
std::println(f, "\tctx.r{}.u64 = PPC_LOAD_U8({} + ctx.r{}.u32);", insn.operands[0], int32_t(insn.operands[1]), insn.operands[2]);
break;
case PPC_INST_LBZU: case PPC_INST_LBZU:
std::println(f, "\tea = {} + ctx.r{}.u32;", int32_t(insn.operands[1]), insn.operands[2]);
std::println(f, "\tctx.r{}.u64 = PPC_LOAD_U8(ea);", insn.operands[0]);
std::println(f, "\tctx.r{}.u64 = ea;", insn.operands[2]);
break;
case PPC_INST_LBZX: case PPC_INST_LBZX:
std::println(f, "\tctx.r{}.u64 = PPC_LOAD_U8(ctx.r{}.u32 + ctx.r{}.u32);", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_LD: case PPC_INST_LD:
std::println(f, "\tctx.r{}.u64 = PPC_LOAD_U64({} + ctx.r{}.u32);", insn.operands[0], int32_t(insn.operands[1]), insn.operands[2]);
break;
case PPC_INST_LDARX: case PPC_INST_LDARX:
case PPC_INST_LDU: case PPC_INST_LDU:
case PPC_INST_LDX: case PPC_INST_LDX:
@ -219,10 +280,15 @@ int main()
break; break;
case PPC_INST_LI: case PPC_INST_LI:
std::println(f, "\tctx.r{}.u64 = {};", insn.operands[0], insn.operands[1]); // TODO: validate the sign extend
std::println(f, "\tctx.r{}.s64 = {};", insn.operands[0], int32_t(insn.operands[1]));
break; break;
case PPC_INST_LIS: case PPC_INST_LIS:
// TODO: validate the sign extend
std::println(f, "\tctx.r{}.s64 = {};", insn.operands[0], int32_t(insn.operands[1] << 16));
break;
case PPC_INST_LVEWX: case PPC_INST_LVEWX:
case PPC_INST_LVEWX128: case PPC_INST_LVEWX128:
case PPC_INST_LVLX: case PPC_INST_LVLX:
@ -237,7 +303,10 @@ int main()
case PPC_INST_LWARX: case PPC_INST_LWARX:
case PPC_INST_LWAX: case PPC_INST_LWAX:
case PPC_INST_LWBRX: case PPC_INST_LWBRX:
break;
case PPC_INST_LWSYNC: case PPC_INST_LWSYNC:
// no op
break; break;
case PPC_INST_LWZ: case PPC_INST_LWZ:
@ -280,17 +349,54 @@ int main()
case PPC_INST_MULHW: case PPC_INST_MULHW:
case PPC_INST_MULHWU: case PPC_INST_MULHWU:
case PPC_INST_MULLD: case PPC_INST_MULLD:
break;
case PPC_INST_MULLI: case PPC_INST_MULLI:
std::println(f, "\tctx.r{}.s64 = ctx.r{}.s64 * {};", insn.operands[0], insn.operands[1], static_cast<int32_t>(insn.operands[2]));
break;
case PPC_INST_MULLW: case PPC_INST_MULLW:
break;
case PPC_INST_NAND: case PPC_INST_NAND:
std::println(f, "\tctx.r{}.u64 = ~(ctx.r{}.u64 & ctx.r{}.u64);", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_NEG: case PPC_INST_NEG:
// TODO: . variant
std::println(f, "\tctx.r{}.s64 = -ctx.r{}.s64;", insn.operands[0], insn.operands[1]);
break;
case PPC_INST_NOP: case PPC_INST_NOP:
// no op
break;
case PPC_INST_NOR: case PPC_INST_NOR:
std::println(f, "\tctx.r{}.u64 = ~(ctx.r{}.u64 | ctx.r{}.u64);", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_NOT: case PPC_INST_NOT:
// TODO: . variant
std::println(f, "\tctx.r{}.u64 = ~ctx.r{}.u64;", insn.operands[0], insn.operands[1]);
break;
case PPC_INST_OR: case PPC_INST_OR:
// TODO: . variant
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 | ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_ORC: case PPC_INST_ORC:
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 | ~ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_ORI: case PPC_INST_ORI:
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 | {}", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_ORIS: case PPC_INST_ORIS:
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 | {}", insn.operands[0], insn.operands[1], insn.operands[2] << 16);
break;
case PPC_INST_RLDICL: case PPC_INST_RLDICL:
case PPC_INST_RLDICR: case PPC_INST_RLDICR:
case PPC_INST_RLDIMI: case PPC_INST_RLDIMI:
@ -457,9 +563,19 @@ int main()
case PPC_INST_VUPKLSH: case PPC_INST_VUPKLSH:
case PPC_INST_VXOR: case PPC_INST_VXOR:
case PPC_INST_VXOR128: case PPC_INST_VXOR128:
break;
case PPC_INST_XOR: case PPC_INST_XOR:
// TODO: . variant
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 ^ ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_XORI: case PPC_INST_XORI:
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 ^ {};", insn.operands[0], insn.operands[1], insn.operands[2]);
break;
case PPC_INST_XORIS: case PPC_INST_XORIS:
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 ^ {};", insn.operands[0], insn.operands[1], insn.operands[2] << 16);
break; break;
} }
} }

View File

@ -9,10 +9,12 @@
#define _byteswap_uint64 __builtin_bswap64 #define _byteswap_uint64 __builtin_bswap64
#endif #endif
#define PPC_LOAD_U8(x) *(uint8_t*)(base + (x))
#define PPC_LOAD_U16(x) _byteswap_ushort(*(uint16_t*)(base + (x))) #define PPC_LOAD_U16(x) _byteswap_ushort(*(uint16_t*)(base + (x)))
#define PPC_LOAD_U32(x) _byteswap_ulong(*(uint32_t*)(base + (x))) #define PPC_LOAD_U32(x) _byteswap_ulong(*(uint32_t*)(base + (x)))
#define PPC_LOAD_U64(x) _byteswap_uint64(*(uint64_t*)(base + (x))) #define PPC_LOAD_U64(x) _byteswap_uint64(*(uint64_t*)(base + (x)))
#define PPC_STORE_U8(x, y) *(uint8_t*)(base + (x)) = (y)
#define PPC_STORE_U16(x, y) *(uint16_t*)(base + (x)) = _byteswap_ushort(y) #define PPC_STORE_U16(x, y) *(uint16_t*)(base + (x)) = _byteswap_ushort(y)
#define PPC_STORE_U32(x, y) *(uint32_t*)(base + (x)) = _byteswap_ulong(y) #define PPC_STORE_U32(x, y) *(uint32_t*)(base + (x)) = _byteswap_ulong(y)
#define PPC_STORE_U64(x, y) *(uint64_t*)(base + (x)) = _byteswap_uint64(y) #define PPC_STORE_U64(x, y) *(uint64_t*)(base + (x)) = _byteswap_uint64(y)
@ -34,6 +36,14 @@ struct PPCRegister
}; };
}; };
struct PPCCRRegister
{
uint8_t lt;
uint8_t gt;
uint8_t eq;
uint8_t so;
};
typedef float float128[4]; typedef float float128[4];
struct PPCContext struct PPCContext
@ -45,16 +55,16 @@ struct PPCContext
{ {
struct struct
{ {
uint32_t cr0; PPCCRRegister cr0;
uint32_t cr1; PPCCRRegister cr1;
uint32_t cr2; PPCCRRegister cr2;
uint32_t cr3; PPCCRRegister cr3;
uint32_t cr4; PPCCRRegister cr4;
uint32_t cr5; PPCCRRegister cr5;
uint32_t cr6; PPCCRRegister cr6;
uint32_t cr7; PPCCRRegister cr7;
}; };
uint32_t cr[8]; PPCCRRegister cr[8];
}; };
union union