DaKnig / gb_dranspiler

sm83 -> amd64 transpiler

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

gb_recompiler

… is a tool for recompiling (non self modifying) game boy machine code to native machine code statically. this shall provide an interface similar to a sm83 emulator.

Use-case

very fast cpu-only emulation of the gb can be used for unit testing and superoptimization, among other things.

Possible methods to achieve this

… and the pros/cons of this approach:

using libgccjit

pros:

  • portable
  • powerful optimizations

cons:

  • ain’t as fun as asm 😁
  • not sure about cross function optimizations

x86 asm directly

pros:

  • feel smart
  • can keep regs outside memory

cons:

  • none 😁

and thus for now, I will use x86 asm.

How…

The standard System V C ABI passes the first 6 integers via the RDI, RSI, RDX, RCX, R8, R9 registers in this order. If we map them to the gb regs, we will eliminate the need to save the registers in ram after every routine.

the mapping I propose: (letters are sm83 regs, not hex values) EDI : 00 _a 00 _f ESI : 00 _b 00 _c EDX : 00 _d 00 _e ECX : 00 _h 00 _l R8D : 00 00 _sp R9 : pointer to memory array

Because of the construction, PC is known at compile time (or can be passed over the stack, later, for compatibility with self modifying code).

The flags register is not really updated besides when it needs to be- that is between returns. Otherwise one can use the native flags reg, some bitmask test etc. hf, nf are hardly ever used and are hard to compute compared to cf, zf.

Every routine/function is translated into the same function signature on C ABI level:

typedef void (*sm83_func)(uint32_t af, uint32_t bc, uint32_t de, uint32_t hl, uint32_t sp, uint8_t* mem);

any source function is gonna start with a prolog unpacking the regs into host regs with the following mapping:

sm83 | x86 a | al f | flags, ah b | bl c | r9b d | r8b e | dl hl | cx sp | di

mem | si

hl is stored together in one register since it is commonly used as one reg pair.

flags: the n, h are stored in ah at the beginning of the function and later moved or used as required.

Optimizations

An optimization pass can happen to make the code a tiny bit faster. The following optimizations are proposed:

  • code motion to pipeline code better

About

sm83 -> amd64 transpiler


Languages

Language:Rust 100.0%