“Static Recompliation” is the process of turning a binary program built for one instruction set and CPU into equivalent native code for a different architecture. It’s a hot topic lately as news of a static recompilation process for N64 games – turning the original MIPS code into x86 executables for Windows – seemingly promises an entirely new level of features and performance beyond existing emulation techniques. I’ve been interested in the topic since hearing of the StarCraft on ARM recompilation for OpenPandora in 2014, but not looked too much further into the idea until recently. I decided to try my own hand at a static recompiler, where I would be transforming some machine ROM into C source code, then compile that to produce native executables.
First, I’d need a source system to use: The CHIP-8 VM, often considered a good “baby’s first emulator” project. It is an interpreted 8-bit machine, with only 30 opcodes or so, limited graphics and sound capabilities and a lot of tooling available. I began by spending a couple of days implementing the machine in C as a plain “interpreted” emulator, using libcurses to handle keyboard input and display visuals on the terminal. This was useful for getting a feel for the machine, learning about quirks and addressing modes, as well as a benchmarking test. Some of the routines for interfacing the VM with the real hardware (e.g. “print screen”, “check keypress” etc) are theoretically reusable in a recompiled version as well. CHIP-8 emulation is a well-studied topic, I won’t say much more about it here.
With that complete, I turned my attention to the recompilation. If you’d like to see the code I wrote, I’ve placed it in GitHub here:
https://github.com/greg-kennedy/CURSE-8
Inside are the interpreter, and a Perl script “recompile.pl” which turns a .ch8 file into a .c. Compiling this along with “wrapper.c” and linking to libcurses should give a runnable executable of the chip8 program.
Details of approaches to static recompilation follow.
Continue reading