aboutsummaryrefslogtreecommitdiff
path: root/src/ARMJIT_x64/ARMJIT_LoadStore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ARMJIT_x64/ARMJIT_LoadStore.cpp')
-rw-r--r--src/ARMJIT_x64/ARMJIT_LoadStore.cpp116
1 files changed, 80 insertions, 36 deletions
diff --git a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp
index 69b324c..8fbcafd 100644
--- a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp
+++ b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp
@@ -1,7 +1,5 @@
#include "ARMJIT_Compiler.h"
-#include "../GPU.h"
-#include "../Wifi.h"
using namespace Gen;
@@ -362,7 +360,7 @@ void* Compiler::Gen_MemoryRoutineSeq9(bool store, bool preinc)
CMP(32, R(ABI_PARAM3), Imm8(1));
FixupBranch skipSequential = J_CC(CC_E);
SUB(32, R(ABI_PARAM3), Imm8(1));
- IMUL(32, R(ABI_PARAM3));
+ IMUL(32, RSCRATCH, R(ABI_PARAM3));
ADD(32, R(ABI_PARAM2), R(RSCRATCH));
SetJumpTarget(skipSequential);
@@ -413,10 +411,11 @@ void* Compiler::Gen_MemoryRoutineSeq7(bool store, bool preinc, bool codeMainRAM)
POP(ABI_PARAM4);
POP(ABI_PARAM3);
+ // TODO: optimise this
CMP(32, R(ABI_PARAM3), Imm8(1));
FixupBranch skipSequential = J_CC(CC_E);
SUB(32, R(ABI_PARAM3), Imm8(1));
- IMUL(32, R(ABI_PARAM3));
+ IMUL(32, RSCRATCH, R(ABI_PARAM3));
ADD(32, R(ABI_PARAM2), R(RSCRATCH));
SetJumpTarget(skipSequential);
@@ -458,25 +457,35 @@ void Compiler::Comp_MemAccess(OpArg rd, bool signExtend, bool store, int size)
}
}
-s32 Compiler::Comp_MemAccessBlock(OpArg rb, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode)
+void printStuff2(u32 a, u32 b)
{
+ printf("b %x %x\n", a, b);
+}
+
+s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode)
+{
+ FILE* f;
+ const u8* start = GetCodePtr();
+
int regsCount = regs.Count();
if (decrement)
{
- MOV_sum(32, ABI_PARAM1, rb, Imm32(-regsCount * 4));
+ MOV_sum(32, ABI_PARAM1, MapReg(rn), Imm32(-regsCount * 4));
preinc ^= true;
}
else
- MOV(32, R(ABI_PARAM1), rb);
+ MOV(32, R(ABI_PARAM1), MapReg(rn));
+
+ s32 offset = (regsCount * 4) * (decrement ? -1 : 1);
- MOV(32, R(ABI_PARAM3), Imm32(regsCount));
- u32 cycles = Num
+ u32 cycles = Num
? NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]
: (R15 & 0x2 ? 0 : CurInstr.CodeCycles);
MOV(32, R(ABI_PARAM4), Imm32(cycles));
if (!store)
{
+ MOV(32, R(ABI_PARAM3), Imm32(regsCount));
SUB(32, R(RSP), regsCount < 16 ? Imm8(regsCount * 8) : Imm32(regsCount * 8));
MOV(64, R(ABI_PARAM2), R(RSP));
@@ -484,20 +493,29 @@ s32 Compiler::Comp_MemAccessBlock(OpArg rb, BitSet16 regs, bool store, bool prei
? MemoryFuncsSeq9[0][preinc]
: MemoryFuncsSeq7[0][preinc][CodeRegion == 0x02]);
+ bool firstUserMode = true;
for (int reg = 15; reg >= 0; reg--)
{
if (regs[reg])
{
- /*if (usermode && reg >= 8 && reg < 15)
+ if (usermode && reg >= 8 && reg < 15)
{
- MOV(32, R(RSCRATCH2), R(RCPSR));
- AND(32, R(RSCRATCH2), Imm8(0x1F));
- // (RSCRATCH2 - 0x11) * 8 + squeezePointer(userModeOffsets) + (reg - 8), algebra is great!
- MOVZX(32, 8, RSCRATCH2, MScaled(RSCRATCH2, SCALE_8, squeezePointer(userModeOffsets) - 0x10 * 8 + (reg - 8)));
- POP(RSCRATCH);
- MOV(32, MRegSum(RCPU, RSCRATCH2), R(RSCRATCH));
+ if (firstUserMode)
+ {
+ MOV(32, R(RSCRATCH), R(RCPSR));
+ AND(32, R(RSCRATCH), Imm8(0x1F));
+ firstUserMode = false;
+ }
+ MOV(32, R(ABI_PARAM2), Imm32(reg - 8));
+ POP(ABI_PARAM3);
+ CALL(WriteBanked);
+ FixupBranch sucessfulWritten = J_CC(CC_NC);
+ if (RegCache.Mapping[reg] != INVALID_REG && RegCache.DirtyRegs & (1 << reg))
+ MOV(32, R(RegCache.Mapping[reg]), R(ABI_PARAM3));
+ SaveReg(reg, ABI_PARAM3);
+ SetJumpTarget(sucessfulWritten);
}
- else */if (RegCache.Mapping[reg] == INVALID_REG)
+ else if (RegCache.Mapping[reg] == INVALID_REG)
{
assert(reg != 15);
@@ -516,32 +534,48 @@ s32 Compiler::Comp_MemAccessBlock(OpArg rb, BitSet16 regs, bool store, bool prei
if (regs[15])
{
if (Num == 1)
- OR(32, MapReg(15), Imm8(1));
+ {
+ if (Thumb)
+ OR(32, MapReg(15), Imm8(1));
+ else
+ AND(32, MapReg(15), Imm8(0xFE));
+ }
Comp_JumpTo(MapReg(15).GetSimpleReg(), usermode);
}
}
else
{
+ bool firstUserMode = true;
for (int reg : regs)
{
- /*if (usermode && reg >= 8 && reg < 15)
+ if (usermode && reg >= 8 && reg < 15)
{
- MOV(32, R(RSCRATCH), R(RCPSR));
- AND(32, R(RSCRATCH), Imm8(0x1F));
- // (RSCRATCH2 - 0x11) * 8 + squeezePointer(userModeOffsets) + (reg - 8), algebra is great!
- MOVZX(32, 8, RSCRATCH, MScaled(RSCRATCH, SCALE_8, squeezePointer(userModeOffsets) - 0x10 * 8 + (reg - 8)));
- MOV(32, R(RSCRATCH), MRegSum(RCPU, RSCRATCH));
- PUSH(RSCRATCH);
+ if (firstUserMode)
+ {
+ MOV(32, R(RSCRATCH), R(RCPSR));
+ AND(32, R(RSCRATCH), Imm8(0x1F));
+ firstUserMode = false;
+ }
+ if (RegCache.Mapping[reg] == INVALID_REG)
+ LoadReg(reg, ABI_PARAM3);
+ else
+ MOV(32, R(ABI_PARAM3), R(RegCache.Mapping[reg]));
+ MOV(32, R(ABI_PARAM2), Imm32(reg - 8));
+ CALL(ReadBanked);
+ PUSH(ABI_PARAM3);
}
- else */if (RegCache.Mapping[reg] == INVALID_REG)
+ else if (RegCache.Mapping[reg] == INVALID_REG)
{
LoadReg(reg, RSCRATCH);
PUSH(RSCRATCH);
}
else
+ {
PUSH(MapReg(reg).GetSimpleReg());
+ }
}
MOV(64, R(ABI_PARAM2), R(RSP));
+ MOV(32, R(ABI_PARAM3), Imm32(regsCount));
CALL(Num == 0
? MemoryFuncsSeq9[1][preinc]
@@ -550,7 +584,14 @@ s32 Compiler::Comp_MemAccessBlock(OpArg rb, BitSet16 regs, bool store, bool prei
ADD(32, R(RSP), regsCount < 16 ? Imm8(regsCount * 8) : Imm32(regsCount * 8));
}
- return (regsCount * 4) * (decrement ? -1 : 1);
+ if (usermode && !store)
+ {
+ f= fopen("ldm", "a");
+ fwrite(start, GetCodePtr() - start, 1, f);
+ fclose(f);
+ }
+
+ return offset;
}
OpArg Compiler::A_Comp_GetMemWBOffset()
@@ -697,16 +738,20 @@ void Compiler::A_Comp_LDM_STM()
{
BitSet16 regs(CurInstr.Instr & 0xFFFF);
- bool load = (CurInstr.Instr >> 20) & 1;
- bool pre = (CurInstr.Instr >> 24) & 1;
- bool add = (CurInstr.Instr >> 23) & 1;
- bool writeback = (CurInstr.Instr >> 21) & 1;
- bool usermode = (CurInstr.Instr >> 22) & 1;
+ bool load = CurInstr.Instr & (1 << 20);
+ bool pre = CurInstr.Instr & (1 << 24);
+ bool add = CurInstr.Instr & (1 << 23);
+ bool writeback = CurInstr.Instr & (1 << 21);
+ bool usermode = CurInstr.Instr & (1 << 22);
OpArg rn = MapReg(CurInstr.A_Reg(16));
- s32 offset = Comp_MemAccessBlock(rn, regs, !load, pre, !add, false);
+ s32 offset = Comp_MemAccessBlock(CurInstr.A_Reg(16), regs, !load, pre, !add, usermode);
+ if (load && writeback && regs[CurInstr.A_Reg(16)])
+ writeback = Num == 0
+ ? (!(regs & ~BitSet16(1 << CurInstr.A_Reg(16)))) || (regs & ~BitSet16((2 << CurInstr.A_Reg(16)) - 1))
+ : false;
if (writeback)
ADD(32, rn, offset >= INT8_MIN && offset < INT8_MAX ? Imm8(offset) : Imm32(offset));
}
@@ -789,8 +834,7 @@ void Compiler::T_Comp_PUSH_POP()
}
OpArg sp = MapReg(13);
-
- s32 offset = Comp_MemAccessBlock(sp, regs, !load, !load, !load, false);
+ s32 offset = Comp_MemAccessBlock(13, regs, !load, !load, !load, false);
ADD(32, sp, Imm8(offset)); // offset will be always be in range since PUSH accesses 9 regs max
}
@@ -801,7 +845,7 @@ void Compiler::T_Comp_LDMIA_STMIA()
OpArg rb = MapReg(CurInstr.T_Reg(8));
bool load = CurInstr.Instr & (1 << 11);
- s32 offset = Comp_MemAccessBlock(rb, regs, !load, false, false, false);
+ s32 offset = Comp_MemAccessBlock(CurInstr.T_Reg(8), regs, !load, false, false, false);
if (!load || !regs[CurInstr.T_Reg(8)])
ADD(32, rb, Imm8(offset));