Implement periodt variant of instructions.

This commit is contained in:
Skyth 2024-09-12 18:59:24 +03:00
parent f8353aa1e2
commit f96d2c2879
4 changed files with 52 additions and 17 deletions

View File

@ -6,7 +6,7 @@
#include <disasm.h> #include <disasm.h>
#include <filesystem> #include <filesystem>
#define TEST_FILE "cond.elf" #define TEST_FILE "add-cond.elf"
int main() int main()
{ {
@ -81,14 +81,13 @@ 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)
{ {
case PPC_INST_ADD: case PPC_INST_ADD:
// TODO: . variant
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 + ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]); std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 + ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; break;
case PPC_INST_ADDI: case PPC_INST_ADDI:
@ -99,7 +98,6 @@ int main()
break; 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)); std::println(f, "\tctx.r{}.s64 = ctx.r{}.s64 + {};", insn.operands[0], insn.operands[1], static_cast<int32_t>(insn.operands[2] << 16));
break; break;
@ -107,23 +105,27 @@ int main()
break; 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]); std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; 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]); std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & ~ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; 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]); std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & {};", insn.operands[0], insn.operands[1], insn.operands[2]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; 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); std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & {};", insn.operands[0], insn.operands[1], insn.operands[2] << 16);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; break;
case PPC_INST_ATTN: case PPC_INST_ATTN:
@ -222,9 +224,21 @@ int main()
break; break;
case PPC_INST_CCTPL: case PPC_INST_CCTPL:
// no op
break;
case PPC_INST_CCTPM: case PPC_INST_CCTPM:
// no op
break;
case PPC_INST_CLRLDI: case PPC_INST_CLRLDI:
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 & 0x{:X};", insn.operands[0], insn.operands[1], (1ull << (64 - insn.operands[2])) - 1);
break;
case PPC_INST_CLRLWI: case PPC_INST_CLRLWI:
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u32 & 0x{:X};", insn.operands[0], insn.operands[1], (1ull << (32 - insn.operands[2])) - 1);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; break;
case PPC_INST_CMPD: case PPC_INST_CMPD:
@ -261,7 +275,11 @@ int main()
case PPC_INST_CNTLZD: case PPC_INST_CNTLZD:
case PPC_INST_CNTLZW: case PPC_INST_CNTLZW:
break;
case PPC_INST_DB16CYC: case PPC_INST_DB16CYC:
// no op
break;
case PPC_INST_DCBF: case PPC_INST_DCBF:
// no op // no op
@ -399,8 +417,9 @@ int main()
break; break;
case PPC_INST_MR: case PPC_INST_MR:
// TODO: . variant
std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64;", insn.operands[0], insn.operands[1]); std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64;", insn.operands[0], insn.operands[1]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; break;
case PPC_INST_MTCR: case PPC_INST_MTCR:
@ -431,8 +450,9 @@ int main()
break; break;
case PPC_INST_MULLW: case PPC_INST_MULLW:
// TODO: . variant
std::println(f, "\tctx.r{}.s64 = ctx.r{}.s32 * ctx.r{}.s32;", insn.operands[0], insn.operands[1], insn.operands[2]); std::println(f, "\tctx.r{}.s64 = ctx.r{}.s32 * ctx.r{}.s32;", insn.operands[0], insn.operands[1], insn.operands[2]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; break;
case PPC_INST_NAND: case PPC_INST_NAND:
@ -440,8 +460,9 @@ int main()
break; 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]); std::println(f, "\tctx.r{}.s64 = -ctx.r{}.s64;", insn.operands[0], insn.operands[1]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; break;
case PPC_INST_NOP: case PPC_INST_NOP:
@ -453,13 +474,15 @@ int main()
break; 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]); std::println(f, "\tctx.r{}.u64 = ~ctx.r{}.u64;", insn.operands[0], insn.operands[1]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; 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]); std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 | ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; break;
case PPC_INST_ORC: case PPC_INST_ORC:
@ -535,8 +558,9 @@ int main()
break; break;
case PPC_INST_SUBF: case PPC_INST_SUBF:
// TODO: . variant
std::println(f, "\tctx.r{}.s64 = ctx.r{}.s64 - ctx.r{}.s64;", insn.operands[0], insn.operands[1], insn.operands[2]); std::println(f, "\tctx.r{}.s64 = ctx.r{}.s64 - ctx.r{}.s64;", insn.operands[0], insn.operands[1], insn.operands[2]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; break;
case PPC_INST_SUBFC: case PPC_INST_SUBFC:
@ -649,8 +673,9 @@ int main()
break; 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]); std::println(f, "\tctx.r{}.u64 = ctx.r{}.u64 ^ ctx.r{}.u64;", insn.operands[0], insn.operands[1], insn.operands[2]);
if (insn.opcode->opcode & 0x1)
std::println(f, "\tctx.cr0.compare<int32_t>(ctx.r{}.s32, 0, ctx.xer);", insn.operands[0]);
break; break;
case PPC_INST_XORI: case PPC_INST_XORI:

View File

@ -7,7 +7,7 @@
#define _byteswap_ushort __builtin_bswap16 #define _byteswap_ushort __builtin_bswap16
#define _byteswap_ulong __builtin_bswap32 #define _byteswap_ulong __builtin_bswap32
#define _byteswap_uint64 __builtin_bswap64 #define _byteswap_uint64 __builtin_bswap64
#define PPC_FUNC extern inline __attribute__((weak,noinline)) #define PPC_FUNC __attribute__((weak,noinline))
#else #else
#define PPC_FUNC __declspec(noinline) #define PPC_FUNC __declspec(noinline)
#endif #endif

View File

@ -0,0 +1,10 @@
int add(int a, int b)
{
int c = a + b;
return c == 0 ? 50000 : c;
}
extern "C" int _start()
{
return add(1, 2);
}

Binary file not shown.