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.
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.