Dolphin, the GameCube and Wii emulator - Forums

Full Version: I'd like to make a LLVM JIT for Dolphin, but I don't know where to start
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello guys,

Some time ago I thought it would be fun to JIT-recompile console games using LLVM. I thought LLVM was a cool choice because it's platform-independant, it supports like 10 different architectures (and can fallback to an interpreter if the current architecture is not supported) and has a wide variety of built-in optimization passes.

At first I tried to make a NES emulator; recompiling 6502 code wasn't too hard, but making a decent PPU was a huge bother as this is a tricky piece of hardware, and open-source NES emulators don't make it easier to understand. Debugging it was a pain because the GDB version that ships with Xcode had a tendency to spin forever when I hit a breakpoint with unfavorable conditions in my code.

Anyways, NES emulation is pretty much a mastered topic, and making a JIT recompiler for a 21 MHz CPU is kind of an overkill.

Lately I've been playing games with Dolphin, and I find it quite impressive. Either I've been lucky with the games I picked, or it really works well. However, when playing Super Smash Bros. Melee, I observed that the emulator slows down when there are many (read: more than one) AIs on the field.

I suppose this is because of the CPU core. Seeing it woke up my ambition of making a JIT recompiler for an emulator with LLVM, especially since this time, I (hopefully) wouldn't have to debug anything but the CPU.

I can't say for sure it would be any better than what you have now, but hey.

My problem is that I don't really know where to start. I mean, I figured I have to subclass `CPUCoreBase`, but I still have a lot of interrogations.

First off, the `CPUCoreBase` class.

JIT compilers seem to be ignoring the `SingleStep` method. Am I correct?
There's a `ClearCache` method. Am I expected to cache something? The interpreter doesn't, at least.
Up to where/when should the `Run` method run? From what I see I expect it to run forever (until power off or until a breakpoint is hit). Am I right? Does it mean the CPU runs on its dedicated thread? And does it also mean it is responsible for limiting the game speed?

And then, the architecture in general. I somewhat expected coupling to be more explicit (global variables being accessible anywhere, it's hard to tell what uses what).

I see that CPU engines rely on the global PowerPCState variable. Which state can I expect it to be in when the CPUCoreBase `Init` method is called?

Who else can touch the ppcState variable? In which circumstances would PC change without the CPU knowing?

Those are the ones keeping me from getting really started. As I run into more questions, I'll ask here again I suppose.
nodchip and anusko have already started a LLVM CPU core. It might be worthwhile getting in contact with them.


JIT compilers seem to be ignoring the `SingleStep` method. Am I correct?

Yeah, the SingleStep method is part of the old design. The old design does not work because JIT works with blocks of instructions. The single step is implemented in the dispatcher of the JIT.


There's a `ClearCache` method. Am I expected to cache something?

The JIT block cache is usually cleared here. Sometimes, the PPC will flush its instruction cache and this method will be called.


Up to where/when should the `Run` method run?

From memory, Run executes for X amount of PPC CPU cycles. After that occurs, the emulator processes other stuff like game controllers and audio.


Does it mean the CPU runs on its dedicated thread?

It does not run in its own thread.


And does it also mean it is responsible for limiting the game speed?

Dolphin uses the CPU cycles to regulate the game speed.


I see that CPU engines rely on the global PowerPCState variable. Which state can I expect it to be in when the CPUCoreBase `Init` method is called?

Empty state.


Who else can touch the ppcState variable? In which circumstances would PC change without the CPU knowing?

Probably best to run a search through the code to get this answer.


Those are the ones keeping me from getting really started. As I run into more questions, I'll ask here again I suppose.

ok
so will this speed up games when theres alot of AIs at once?
if so then please make this happen, playing fifa drops my frames like a brick.
Thank you for replying.

@my_rig_is_dust, I can't tell the magnitude of the benefits, but I'd expect everything to run faster if it works. It won't just affect AIs.

(11-25-2010, 12:02 PM)skid Wrote: [ -> ]nodchip and anusko have already started a LLVM CPU core. It might be worthwhile getting in contact with them.
Is the project anywhere online? The SVN repository of Dolphin doesn't have branches as far as I can see.

(11-25-2010, 12:02 PM)skid Wrote: [ -> ]JIT compilers seem to be ignoring the `SingleStep` method. Am I correct?

Yeah, the SingleStep method is part of the old design. The old design does not work because JIT works with blocks of instructions. The single step is implemented in the dispatcher of the JIT.
The dispatcher seems to be an u8* (from JitAsmCommon.h). What's its purpose?

(11-25-2010, 12:02 PM)skid Wrote: [ -> ]Up to where/when should the `Run` method run?

From memory, Run executes for X amount of PPC CPU cycles. After that occurs, the emulator processes other stuff like game controllers and audio.
There's no parameter to Run. The interpreter loops while PowerPC::GetState() returns CPU_RUNNING (the two other values of the enum are CPU_STEPPING and CPU_POWERDOWN), and the JIT gets a reference to a CompiledCode function and runs it.

(11-25-2010, 12:02 PM)skid Wrote: [ -> ]I see that CPU engines rely on the global PowerPCState variable. Which state can I expect it to be in when the CPUCoreBase `Init` method is called?

Empty state.
In other words, all zeroed?

Actually, I'd rather need an overview of the CPU architecture: the context in which methods are used, and the side effects on the global variables they're expected to have.
(11-25-2010, 12:24 PM)zneak Wrote: [ -> ]Is the project anywhere online? The SVN repository of Dolphin doesn't have branches as far as I can see.
The dispatcher seems to be an u8* (from JitAsmCommon.h). What's its purpose?
There's no parameter to Run. The interpreter loops while PowerPC::GetState() returns CPU_RUNNING (the two other values of the enum are CPU_STEPPING and CPU_POWERDOWN), and the JIT gets a reference to a CompiledCode function and runs it.

The Dolphin LLVM is not online as it is half finished. But both of the authors can be contacted via their gmail addresses.

The dispatcher jumps to the compiled block as appropriate for the PC of the PPC.

The dispatcher (which gets called by Run?) will change states once the cycles allocated have been executed.