aboutsummaryrefslogtreecommitdiff
path: root/src/ARMJIT.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ARMJIT.h')
-rw-r--r--src/ARMJIT.h140
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