So this summer I thought I'd take it upon myself to begin my very first emulation project-- I am writing a dynamic recompiling SNES emulator for the PSP.
I didn't quite realize when I started how ambitious this project is. A few quarters ago I took a computer organization course that dealt with MIPS, so I thought I'd be relatively prepared to jump into this. I was particularly confident since I choose to (initially, at least) take a dictionary-type translation approach. No real profiling or optimization at first. I just want something that works for now.
I now see that even without some crazy profiler/optimization utility, this is not a trivial undertaking and I'm at the point where I could really use some advice from people who have a good understanding of how this all works.
So, my first problem I guess. I spent the past two or so weeks writing "emit" functions (for example, emit_lda() ) that spit out MIPS-encoded instructions that perform 65c816-equivalent operations according to the address mode of interest. This weekend I wrote a MIPS disassembler/interpreter and they seem to do what they're supposed to do. However, these functions more or less assume that all ROM and and RAM data are stored contiguously in memory. After reading a little more about the SNES memory map (I'm only implementing LoROM support at the moment), I realize that this approach won't really work.
The way I see it, I have two options:
1) Allocate a huge wad of memory. Cut the ROM data up into 32k chunks and distribute them according to their proper bank locations (the first 32k chunk would be located at 00.8000, the second at 01.8000, etc. ).
2) Go the typical route of writing read/writemem() functions.
The obvious problem with #1 is that I'd be using a ton of memory, and then any writes to mirrored memory would have to be duplicated. #2 seems like it'd be the clear alternative, but the 65c816->MIPS translation already yields an approximate 1:20 instruction ratio. I want to avoid any unecessary function calls or additional code generation, and I figured the method might lend itself to an elegant solution of some kind. But maybe not?
Suggestions are greatly appreciated.
I didn't quite realize when I started how ambitious this project is. A few quarters ago I took a computer organization course that dealt with MIPS, so I thought I'd be relatively prepared to jump into this. I was particularly confident since I choose to (initially, at least) take a dictionary-type translation approach. No real profiling or optimization at first. I just want something that works for now.
I now see that even without some crazy profiler/optimization utility, this is not a trivial undertaking and I'm at the point where I could really use some advice from people who have a good understanding of how this all works.
So, my first problem I guess. I spent the past two or so weeks writing "emit" functions (for example, emit_lda() ) that spit out MIPS-encoded instructions that perform 65c816-equivalent operations according to the address mode of interest. This weekend I wrote a MIPS disassembler/interpreter and they seem to do what they're supposed to do. However, these functions more or less assume that all ROM and and RAM data are stored contiguously in memory. After reading a little more about the SNES memory map (I'm only implementing LoROM support at the moment), I realize that this approach won't really work.
The way I see it, I have two options:
1) Allocate a huge wad of memory. Cut the ROM data up into 32k chunks and distribute them according to their proper bank locations (the first 32k chunk would be located at 00.8000, the second at 01.8000, etc. ).
2) Go the typical route of writing read/writemem() functions.
The obvious problem with #1 is that I'd be using a ton of memory, and then any writes to mirrored memory would have to be duplicated. #2 seems like it'd be the clear alternative, but the 65c816->MIPS translation already yields an approximate 1:20 instruction ratio. I want to avoid any unecessary function calls or additional code generation, and I figured the method might lend itself to an elegant solution of some kind. But maybe not?
Suggestions are greatly appreciated.
Last edited: