diff options
Diffstat (limited to 'src/ARMJIT.h')
-rw-r--r-- | src/ARMJIT.h | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/ARMJIT.h b/src/ARMJIT.h new file mode 100644 index 0000000..d718295 --- /dev/null +++ b/src/ARMJIT.h @@ -0,0 +1,140 @@ +#ifndef ARMJIT_H +#define ARMJIT_H + +#include "types.h" + +#include <string.h> + +#include "ARM.h" +#include "ARM_InstrInfo.h" + +namespace ARMJIT +{ + +typedef u32 (*CompiledBlock)(); + +class RegCache +{ + +static const int NativeRegAllocOrder[]; +static const int NativeRegsCount; + +}; + +struct FetchedInstr +{ + u32 A_Reg(int pos) const + { + return (Instr >> pos) & 0xF; + } + + u32 T_Reg(int pos) const + { + return (Instr >> pos) & 0x7; + } + + u32 Cond() const + { + return Instr >> 28; + } + + u32 Instr; + u32 NextInstr[2]; + + u8 CodeCycles; + + ARMInstrInfo::Info Info; +}; + +/* + Copied from DeSmuME + Some names where changed to match the nomenclature of melonDS + + Since it's nowhere explained and atleast I needed some time to get behind it, + here's a summary on how it works: + more or less all memory locations from which code can be executed are + represented by an array of function pointers, which point to null or + a function which executes a block instructions starting from there. + + The most significant 4 bits of each address is ignored. This 28 bit space is + divided into 0x4000 16 KB blocks, each of which a pointer to the relevant + place inside the before mentioned arrays. Only half of the bytes need to be + addressed (ARM address are aligned to 4, Thumb addresses to a 2 byte boundary). + + In case a memory write hits mapped memory, the function block at this + address is set to null, so it's recompiled the next time it's executed. + + This method has disadvantages, namely that only writing to the + first instruction of a block marks it as invalid and that memory remapping + (SWRAM and VRAM) isn't taken into account. +*/ + +struct BlockCache +{ + CompiledBlock* AddrMapping[2][0x4000] = {0}; + + CompiledBlock MainRAM[16*1024*1024/2]; + CompiledBlock SWRAM[0x8000/2]; // Shared working RAM + CompiledBlock ARM9_ITCM[0x8000/2]; + CompiledBlock ARM9_LCDC[0xA4000/2]; + CompiledBlock ARM9_BIOS[0x8000/2]; + CompiledBlock ARM7_BIOS[0x4000/2]; + CompiledBlock ARM7_WRAM[0x10000/2]; // dedicated ARM7 WRAM + CompiledBlock ARM7_WIRAM[0x10000/2]; // Wifi + CompiledBlock ARM7_WVRAM[0x40000/2]; // VRAM allocated as Working RAM +}; + +extern BlockCache cache; + +inline bool IsMapped(u32 num, u32 addr) +{ + return cache.AddrMapping[num][(addr & 0xFFFFFFF) >> 14]; +} + +inline CompiledBlock LookUpBlock(u32 num, u32 addr) +{ + return cache.AddrMapping[num][(addr & 0xFFFFFFF) >> 14][(addr & 0x3FFF) >> 1]; +} + +inline void Invalidate16(u32 num, u32 addr) +{ + if (IsMapped(num, addr)) + cache.AddrMapping[num][(addr & 0xFFFFFFF) >> 14][(addr & 0x3FFF) >> 1] = NULL; +} + +inline void Invalidate32(u32 num, u32 addr) +{ + if (IsMapped(num, addr)) + { + CompiledBlock* page = cache.AddrMapping[num][(addr & 0xFFFFFFF) >> 14]; + page[(addr & 0x3FFF) >> 1] = NULL; + page[((addr + 2) & 0x3FFF) >> 1] = NULL; + } +} + +inline void InsertBlock(u32 num, u32 addr, CompiledBlock func) +{ + cache.AddrMapping[num][(addr & 0xFFFFFFF) >> 14][(addr & 0x3FFF) >> 1] = func; +} + +inline void ResetBlocks() +{ + memset(cache.MainRAM, 0, sizeof(cache.MainRAM)); + memset(cache.SWRAM, 0, sizeof(cache.SWRAM)); + memset(cache.ARM9_BIOS, 0, sizeof(cache.ARM9_BIOS)); + memset(cache.ARM9_ITCM, 0, sizeof(cache.ARM9_ITCM)); + memset(cache.ARM9_LCDC, 0, sizeof(cache.ARM9_LCDC)); + memset(cache.ARM7_BIOS, 0, sizeof(cache.ARM7_BIOS)); + memset(cache.ARM7_WIRAM, 0, sizeof(cache.ARM7_WIRAM)); + memset(cache.ARM7_WRAM, 0, sizeof(cache.ARM7_WRAM)); + memset(cache.ARM7_WVRAM, 0, sizeof(cache.ARM7_WVRAM)); +} + +void Init(); +void DeInit(); + +CompiledBlock CompileBlock(ARM* cpu); + +} + +#endif
\ No newline at end of file |