implement correct/guess interlocks for remaining instructions

This commit is contained in:
Jaklyy 2024-06-16 20:44:55 -04:00
parent debaaa0425
commit 5b37ca70d1
3 changed files with 168 additions and 133 deletions

View File

@ -1180,9 +1180,9 @@ void A_QDSUB(ARM* cpu)
void T_LSL_IMM(ARM* cpu)
void T_LSL_IMM(ARM* cpu) // verify interlock
{
u32 op = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 op = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 s = (cpu->CurInstr >> 6) & 0x1F;
LSL_IMM_S(op, s);
cpu->R[cpu->CurInstr & 0x7] = op;
@ -1191,9 +1191,9 @@ void T_LSL_IMM(ARM* cpu)
cpu->AddCycles_C();
}
void T_LSR_IMM(ARM* cpu)
void T_LSR_IMM(ARM* cpu) // verify interlock
{
u32 op = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 op = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 s = (cpu->CurInstr >> 6) & 0x1F;
LSR_IMM_S(op, s);
cpu->R[cpu->CurInstr & 0x7] = op;
@ -1202,9 +1202,9 @@ void T_LSR_IMM(ARM* cpu)
cpu->AddCycles_C();
}
void T_ASR_IMM(ARM* cpu)
void T_ASR_IMM(ARM* cpu) // verify interlock
{
u32 op = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 op = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 s = (cpu->CurInstr >> 6) & 0x1F;
ASR_IMM_S(op, s);
cpu->R[cpu->CurInstr & 0x7] = op;
@ -1215,8 +1215,8 @@ void T_ASR_IMM(ARM* cpu)
void T_ADD_REG_(ARM* cpu)
{
u32 a = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 6) & 0x7];
u32 a = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 6) & 0x7);
u32 res = a + b;
cpu->R[cpu->CurInstr & 0x7] = res;
cpu->SetNZCV(res & 0x80000000,
@ -1228,8 +1228,8 @@ void T_ADD_REG_(ARM* cpu)
void T_SUB_REG_(ARM* cpu)
{
u32 a = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 6) & 0x7];
u32 a = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 6) & 0x7);
u32 res = a - b;
cpu->R[cpu->CurInstr & 0x7] = res;
cpu->SetNZCV(res & 0x80000000,
@ -1239,9 +1239,9 @@ void T_SUB_REG_(ARM* cpu)
cpu->AddCycles_C();
}
void T_ADD_IMM_(ARM* cpu)
void T_ADD_IMM_(ARM* cpu) // verify interlock
{
u32 a = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 b = (cpu->CurInstr >> 6) & 0x7;
u32 res = a + b;
cpu->R[cpu->CurInstr & 0x7] = res;
@ -1252,9 +1252,9 @@ void T_ADD_IMM_(ARM* cpu)
cpu->AddCycles_C();
}
void T_SUB_IMM_(ARM* cpu)
void T_SUB_IMM_(ARM* cpu) // verify interlock
{
u32 a = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 b = (cpu->CurInstr >> 6) & 0x7;
u32 res = a - b;
cpu->R[cpu->CurInstr & 0x7] = res;
@ -1265,7 +1265,7 @@ void T_SUB_IMM_(ARM* cpu)
cpu->AddCycles_C();
}
void T_MOV_IMM(ARM* cpu)
void T_MOV_IMM(ARM* cpu) // verify interlock
{
u32 b = cpu->CurInstr & 0xFF;
cpu->R[(cpu->CurInstr >> 8) & 0x7] = b;
@ -1274,7 +1274,7 @@ void T_MOV_IMM(ARM* cpu)
cpu->AddCycles_C();
}
void T_CMP_IMM(ARM* cpu)
void T_CMP_IMM(ARM* cpu) // verify interlock
{
u32 a = cpu->R[(cpu->CurInstr >> 8) & 0x7];
u32 b = cpu->CurInstr & 0xFF;
@ -1286,9 +1286,9 @@ void T_CMP_IMM(ARM* cpu)
cpu->AddCycles_C();
}
void T_ADD_IMM(ARM* cpu)
void T_ADD_IMM(ARM* cpu) // verify interlock
{
u32 a = cpu->R[(cpu->CurInstr >> 8) & 0x7];
u32 a = cpu->GetReg((cpu->CurInstr >> 8) & 0x7);
u32 b = cpu->CurInstr & 0xFF;
u32 res = a + b;
cpu->R[(cpu->CurInstr >> 8) & 0x7] = res;
@ -1299,9 +1299,9 @@ void T_ADD_IMM(ARM* cpu)
cpu->AddCycles_C();
}
void T_SUB_IMM(ARM* cpu)
void T_SUB_IMM(ARM* cpu) // verify interlock
{
u32 a = cpu->R[(cpu->CurInstr >> 8) & 0x7];
u32 a = cpu->GetReg((cpu->CurInstr >> 8) & 0x7);
u32 b = cpu->CurInstr & 0xFF;
u32 res = a - b;
cpu->R[(cpu->CurInstr >> 8) & 0x7] = res;
@ -1315,8 +1315,8 @@ void T_SUB_IMM(ARM* cpu)
void T_AND_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg(cpu->CurInstr & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res = a & b;
cpu->R[cpu->CurInstr & 0x7] = res;
cpu->SetNZ(res & 0x80000000,
@ -1326,8 +1326,8 @@ void T_AND_REG(ARM* cpu)
void T_EOR_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg(cpu->CurInstr & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res = a ^ b;
cpu->R[cpu->CurInstr & 0x7] = res;
cpu->SetNZ(res & 0x80000000,
@ -1337,8 +1337,8 @@ void T_EOR_REG(ARM* cpu)
void T_LSL_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7] & 0xFF;
u32 a = cpu->GetReg(cpu->CurInstr & 0x7, 1);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) & 0xFF;
LSL_REG_S(a, b);
cpu->R[cpu->CurInstr & 0x7] = a;
cpu->SetNZ(a & 0x80000000,
@ -1348,8 +1348,8 @@ void T_LSL_REG(ARM* cpu)
void T_LSR_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7] & 0xFF;
u32 a = cpu->GetReg(cpu->CurInstr & 0x7, 1);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) & 0xFF;
LSR_REG_S(a, b);
cpu->R[cpu->CurInstr & 0x7] = a;
cpu->SetNZ(a & 0x80000000,
@ -1359,8 +1359,8 @@ void T_LSR_REG(ARM* cpu)
void T_ASR_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7] & 0xFF;
u32 a = cpu->GetReg(cpu->CurInstr & 0x7, 1);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) & 0xFF;
ASR_REG_S(a, b);
cpu->R[cpu->CurInstr & 0x7] = a;
cpu->SetNZ(a & 0x80000000,
@ -1370,8 +1370,8 @@ void T_ASR_REG(ARM* cpu)
void T_ADC_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg(cpu->CurInstr & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res_tmp = a + b;
u32 carry = (cpu->CPSR&0x20000000 ? 1:0);
u32 res = res_tmp + carry;
@ -1385,8 +1385,8 @@ void T_ADC_REG(ARM* cpu)
void T_SBC_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg(cpu->CurInstr & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res_tmp = a - b;
u32 carry = (cpu->CPSR&0x20000000 ? 0:1);
u32 res = res_tmp - carry;
@ -1400,8 +1400,8 @@ void T_SBC_REG(ARM* cpu)
void T_ROR_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7] & 0xFF;
u32 a = cpu->GetReg(cpu->CurInstr & 0x7, 1);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) & 0xFF;
ROR_REG_S(a, b);
cpu->R[cpu->CurInstr & 0x7] = a;
cpu->SetNZ(a & 0x80000000,
@ -1411,8 +1411,8 @@ void T_ROR_REG(ARM* cpu)
void T_TST_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg(cpu->CurInstr & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res = a & b;
cpu->SetNZ(res & 0x80000000,
!res);
@ -1421,7 +1421,7 @@ void T_TST_REG(ARM* cpu)
void T_NEG_REG(ARM* cpu)
{
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res = -b;
cpu->R[cpu->CurInstr & 0x7] = res;
cpu->SetNZCV(res & 0x80000000,
@ -1433,8 +1433,8 @@ void T_NEG_REG(ARM* cpu)
void T_CMP_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg(cpu->CurInstr & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res = a - b;
cpu->SetNZCV(res & 0x80000000,
!res,
@ -1445,8 +1445,8 @@ void T_CMP_REG(ARM* cpu)
void T_CMN_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg(cpu->CurInstr & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res = a + b;
cpu->SetNZCV(res & 0x80000000,
!res,
@ -1457,8 +1457,8 @@ void T_CMN_REG(ARM* cpu)
void T_ORR_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg(cpu->CurInstr & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res = a | b;
cpu->R[cpu->CurInstr & 0x7] = res;
cpu->SetNZ(res & 0x80000000,
@ -1468,8 +1468,8 @@ void T_ORR_REG(ARM* cpu)
void T_MUL_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg(cpu->CurInstr & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res = a * b;
cpu->R[cpu->CurInstr & 0x7] = res;
cpu->SetNZ(res & 0x80000000,
@ -1493,8 +1493,8 @@ void T_MUL_REG(ARM* cpu)
void T_BIC_REG(ARM* cpu)
{
u32 a = cpu->R[cpu->CurInstr & 0x7];
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 a = cpu->GetReg(cpu->CurInstr & 0x7);
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res = a & ~b;
cpu->R[cpu->CurInstr & 0x7] = res;
cpu->SetNZ(res & 0x80000000,
@ -1504,7 +1504,7 @@ void T_BIC_REG(ARM* cpu)
void T_MVN_REG(ARM* cpu)
{
u32 b = cpu->R[(cpu->CurInstr >> 3) & 0x7];
u32 b = cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 res = ~b;
cpu->R[cpu->CurInstr & 0x7] = res;
cpu->SetNZ(res & 0x80000000,
@ -1516,13 +1516,13 @@ void T_MVN_REG(ARM* cpu)
// TODO: check those when MSBs and MSBd are cleared
// GBAtek says it's not allowed, but it works atleast on the ARM9
void T_ADD_HIREG(ARM* cpu)
void T_ADD_HIREG(ARM* cpu) // verify interlock
{
u32 rd = (cpu->CurInstr & 0x7) | ((cpu->CurInstr >> 4) & 0x8);
u32 rs = (cpu->CurInstr >> 3) & 0xF;
u32 a = cpu->R[rd];
u32 b = cpu->R[rs];
u32 a = cpu->GetReg(rd);
u32 b = cpu->GetReg(rs);
cpu->AddCycles_C();
@ -1536,13 +1536,13 @@ void T_ADD_HIREG(ARM* cpu)
}
}
void T_CMP_HIREG(ARM* cpu)
void T_CMP_HIREG(ARM* cpu) // verify interlock
{
u32 rd = (cpu->CurInstr & 0x7) | ((cpu->CurInstr >> 4) & 0x8);
u32 rs = (cpu->CurInstr >> 3) & 0xF;
u32 a = cpu->R[rd];
u32 b = cpu->R[rs];
u32 a = cpu->GetReg(rd);
u32 b = cpu->GetReg(rs);
u32 res = a - b;
cpu->SetNZCV(res & 0x80000000,
@ -1552,7 +1552,7 @@ void T_CMP_HIREG(ARM* cpu)
cpu->AddCycles_C();
}
void T_MOV_HIREG(ARM* cpu)
void T_MOV_HIREG(ARM* cpu) // verify interlock
{
u32 rd = (cpu->CurInstr & 0x7) | ((cpu->CurInstr >> 4) & 0x8);
u32 rs = (cpu->CurInstr >> 3) & 0xF;
@ -1561,11 +1561,11 @@ void T_MOV_HIREG(ARM* cpu)
if (rd == 15)
{
cpu->JumpTo(cpu->R[rs] | 1);
cpu->JumpTo(cpu->GetReg(rs) | 1);
}
else
{
cpu->R[rd] = cpu->R[rs];
cpu->R[rd] = cpu->GetReg(rs);
}
// nocash-style debugging hook
@ -1582,25 +1582,25 @@ void T_MOV_HIREG(ARM* cpu)
}
void T_ADD_PCREL(ARM* cpu)
void T_ADD_PCREL(ARM* cpu) // verify interlock
{
u32 val = cpu->R[15] & ~2;
u32 val = cpu->GetReg(15) & ~2;
val += ((cpu->CurInstr & 0xFF) << 2);
cpu->R[(cpu->CurInstr >> 8) & 0x7] = val;
cpu->AddCycles_C();
}
void T_ADD_SPREL(ARM* cpu)
void T_ADD_SPREL(ARM* cpu) // verify interlock
{
u32 val = cpu->R[13];
u32 val = cpu->GetReg(13);
val += ((cpu->CurInstr & 0xFF) << 2);
cpu->R[(cpu->CurInstr >> 8) & 0x7] = val;
cpu->AddCycles_C();
}
void T_ADD_SP(ARM* cpu)
void T_ADD_SP(ARM* cpu) // verify interlock
{
u32 val = cpu->R[13];
u32 val = cpu->GetReg(13);
if (cpu->CurInstr & (1<<7))
val -= ((cpu->CurInstr & 0x7F) << 2);
else

View File

@ -46,15 +46,15 @@ void A_BLX_IMM(ARM* cpu)
cpu->JumpTo(cpu->R[15] + offset + 1);
}
void A_BX(ARM* cpu)
void A_BX(ARM* cpu) // verify interlock
{
cpu->JumpTo(cpu->R[cpu->CurInstr & 0xF]);
cpu->JumpTo(cpu->GetReg(cpu->CurInstr & 0xF));
}
void A_BLX_REG(ARM* cpu)
void A_BLX_REG(ARM* cpu) // verify interlock
{
u32 lr = cpu->R[15] - 4;
cpu->JumpTo(cpu->R[cpu->CurInstr & 0xF]);
cpu->JumpTo(cpu->GetReg(cpu->CurInstr & 0xF));
cpu->R[14] = lr;
}
@ -71,12 +71,12 @@ void T_BCOND(ARM* cpu)
cpu->AddCycles_C();
}
void T_BX(ARM* cpu)
void T_BX(ARM* cpu) // verify interlock
{
cpu->JumpTo(cpu->R[(cpu->CurInstr >> 3) & 0xF]);
cpu->JumpTo(cpu->GetReg((cpu->CurInstr >> 3) & 0xF));
}
void T_BLX_REG(ARM* cpu)
void T_BLX_REG(ARM* cpu) // verify interlock
{
if (cpu->Num==1)
{
@ -85,7 +85,7 @@ void T_BLX_REG(ARM* cpu)
}
u32 lr = cpu->R[15] - 1;
cpu->JumpTo(cpu->R[(cpu->CurInstr >> 3) & 0xF]);
cpu->JumpTo(cpu->GetReg((cpu->CurInstr >> 3) & 0xF));
cpu->R[14] = lr;
}

View File

@ -469,15 +469,17 @@ void A_SWP(ARM* cpu)
{
cpu->R[rd] = ROR(val, 8*(base&0x3));
u32 cycles;
if (base & 3) // add an extra interlock cycle when doing a misaligned load from a non-itcm address (checkme: does it matter whether you're executing from there?)
if (cpu->Num == 0)
{
if (cpu->Num == 1) cycles = 2; // checkme
else cycles = ((base < ((ARMv5*)cpu)->ITCMSize) && ((cpu->R[15]-8) < ((ARMv5*)cpu)->ITCMSize)) ? 1 : 2;
}
else cycles = 1;
u32 cycles;
if (base & 3) // add an extra interlock cycle when doing a misaligned load from a non-itcm address (checkme: does it matter whether you're executing from there?)
{
cycles = ((base < ((ARMv5*)cpu)->ITCMSize) && ((cpu->R[15]-8) < ((ARMv5*)cpu)->ITCMSize)) ? 1 : 2;
}
else cycles = 1;
cpu->SetCycles_L(rd, cycles, cpu->ILT_Norm);
cpu->SetCycles_L(rd, cycles, cpu->ILT_Norm);
}
}
else if (cpu->Num == 1) // for some reason these jumps don't work on the arm 9?
cpu->JumpTo(ROR(val, 8*(base&0x3)) & ~1, cpu->ILT_Norm);
@ -508,11 +510,8 @@ void A_SWPB(ARM* cpu)
cpu->R[rd] = val;
// add an extra interlock cycle when doing a load from a non-itcm address (checkme: does it matter whether you're executing from there?)
u32 cycles;
if (cpu->Num == 1) cycles = 2; // checkme
else cycles = ((base < ((ARMv5*)cpu)->ITCMSize) && ((cpu->R[15]-8) < ((ARMv5*)cpu)->ITCMSize)) ? 1 : 2;
cpu->SetCycles_L(rd, cycles, cpu->ILT_Norm);
if (cpu->Num == 0)
cpu->SetCycles_L(rd, ((base < ((ARMv5*)cpu)->ITCMSize) && ((cpu->R[15]-8) < ((ARMv5*)cpu)->ITCMSize)) ? 1 : 2, cpu->ILT_Norm);
}
else if (cpu->Num == 1)// for some reason these jumps don't work on the arm 9?
cpu->JumpTo(val & ~1);
@ -594,11 +593,14 @@ void A_LDM(ARM* cpu)
{
cpu->AddCycles_CDI();
u32 lastbase = base;
if (!preinc) lastbase -= 4;
// no interlock occurs when loading from itcm (checkme: does it matter whether you're executing from there?)
if ((((ARMv5*)cpu)->ITCMSize < lastbase) && ((cpu->R[15]-8) > ((ARMv5*)cpu)->ITCMSize) && (cpu->CurInstr & (0x7FFF >> (15 - lastreg))))
cpu->SetCycles_L(lastreg, 1, cpu->ILT_Norm);
if (cpu->Num == 0)
{
u32 lastbase = base;
if (!preinc) lastbase -= 4;
// no interlock occurs when loading from itcm (checkme: does it matter whether you're executing from there?)
if ((((ARMv5*)cpu)->ITCMSize < lastbase) && ((cpu->R[15]-8) > ((ARMv5*)cpu)->ITCMSize) && (cpu->CurInstr & (0x7FFF >> (15 - lastreg))))
cpu->SetCycles_L(lastreg, 1, cpu->ILT_Norm);
}
}
// switch back to previous regs
@ -736,160 +738,170 @@ void A_STM(ARM* cpu)
void T_LDR_PCREL(ARM* cpu)
void T_LDR_PCREL(ARM* cpu) // verify interlock
{
u32 addr = (cpu->R[15] & ~0x2) + ((cpu->CurInstr & 0xFF) << 2);
u32 addr = (cpu->GetReg(15) & ~0x2) + ((cpu->CurInstr & 0xFF) << 2);
cpu->DataRead32(addr, &cpu->R[(cpu->CurInstr >> 8) & 0x7]);
cpu->AddCycles_CDI();
cpu->SetCycles_L(cpu->R[(cpu->CurInstr >> 8) & 0x7], 1, cpu->ILT_Norm); // checkme? ROR?
}
void T_STR_REG(ARM* cpu)
void T_STR_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
cpu->DataWrite32(addr, cpu->R[cpu->CurInstr & 0x7]);
u32 addr = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) + cpu->GetReg((cpu->CurInstr >> 6) & 0x7);
cpu->DataWrite32(addr, cpu->GetReg(cpu->CurInstr & 0x7, 1));
cpu->AddCycles_CD();
}
void T_STRB_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
cpu->DataWrite8(addr, cpu->R[cpu->CurInstr & 0x7]);
u32 addr = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) + cpu->GetReg((cpu->CurInstr >> 6) & 0x7);
cpu->DataWrite8(addr, cpu->GetReg(cpu->CurInstr & 0x7, 1));
cpu->AddCycles_CD();
}
void T_LDR_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
u32 addr = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) + cpu->GetReg((cpu->CurInstr >> 6) & 0x7);
u32 val;
if (cpu->DataRead32(addr, &val))
cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(addr&0x3));
cpu->AddCycles_CDI();
cpu->SetCycles_L(cpu->R[cpu->CurInstr & 0x7], (addr & 3) ? 2 : 1, cpu->ILT_Norm);
}
void T_LDRB_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
u32 addr = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) + cpu->GetReg((cpu->CurInstr >> 6) & 0x7);
cpu->DataRead8(addr, &cpu->R[cpu->CurInstr & 0x7]);
cpu->AddCycles_CDI();
cpu->SetCycles_L(cpu->R[cpu->CurInstr & 0x7], 2, cpu->ILT_Norm);
}
void T_STRH_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
cpu->DataWrite16(addr, cpu->R[cpu->CurInstr & 0x7]);
u32 addr = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) + cpu->GetReg((cpu->CurInstr >> 6) & 0x7);
cpu->DataWrite16(addr, cpu->GetReg(cpu->CurInstr & 0x7, 1));
cpu->AddCycles_CD();
}
void T_LDRSB_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
u32 addr = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) + cpu->GetReg((cpu->CurInstr >> 6) & 0x7);
if (cpu->DataRead8(addr, &cpu->R[cpu->CurInstr & 0x7]))
cpu->R[cpu->CurInstr & 0x7] = (s32)(s8)cpu->R[cpu->CurInstr & 0x7];
cpu->AddCycles_CDI();
cpu->SetCycles_L(cpu->R[cpu->CurInstr & 0x7], 2, cpu->ILT_Norm);
}
void T_LDRH_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
u32 addr = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) + cpu->GetReg((cpu->CurInstr >> 6) & 0x7);
cpu->DataRead16(addr, &cpu->R[cpu->CurInstr & 0x7]);
cpu->AddCycles_CDI();
cpu->SetCycles_L(cpu->R[cpu->CurInstr & 0x7], 2, cpu->ILT_Norm);
}
void T_LDRSH_REG(ARM* cpu)
{
u32 addr = cpu->R[(cpu->CurInstr >> 3) & 0x7] + cpu->R[(cpu->CurInstr >> 6) & 0x7];
u32 addr = cpu->GetReg((cpu->CurInstr >> 3) & 0x7) + cpu->GetReg((cpu->CurInstr >> 6) & 0x7);
if (cpu->DataRead16(addr, &cpu->R[cpu->CurInstr & 0x7]))
cpu->R[cpu->CurInstr & 0x7] = (s32)(s16)cpu->R[cpu->CurInstr & 0x7];
cpu->AddCycles_CDI();
cpu->SetCycles_L(cpu->R[cpu->CurInstr & 0x7], 2, cpu->ILT_Norm);
}
void T_STR_IMM(ARM* cpu)
void T_STR_IMM(ARM* cpu) // verify interlock
{
u32 offset = (cpu->CurInstr >> 4) & 0x7C;
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
offset += cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
cpu->DataWrite32(offset, cpu->R[cpu->CurInstr & 0x7]);
cpu->DataWrite32(offset, cpu->GetReg(cpu->CurInstr & 0x7, 1));
cpu->AddCycles_CD();
}
void T_LDR_IMM(ARM* cpu)
void T_LDR_IMM(ARM* cpu) // verify interlock
{
u32 offset = (cpu->CurInstr >> 4) & 0x7C;
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
offset += cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
u32 val;
if (cpu->DataRead32(offset, &val))
cpu->R[cpu->CurInstr & 0x7] = ROR(val, 8*(offset&0x3));
cpu->AddCycles_CDI();
cpu->SetCycles_L(cpu->R[cpu->CurInstr & 0x7], (offset & 3) ? 2 : 1, cpu->ILT_Norm);
}
void T_STRB_IMM(ARM* cpu)
void T_STRB_IMM(ARM* cpu) // verify interlock
{
u32 offset = (cpu->CurInstr >> 6) & 0x1F;
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
offset += cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
cpu->DataWrite8(offset, cpu->R[cpu->CurInstr & 0x7]);
cpu->DataWrite8(offset, cpu->GetReg(cpu->CurInstr & 0x7, 1));
cpu->AddCycles_CD();
}
void T_LDRB_IMM(ARM* cpu)
void T_LDRB_IMM(ARM* cpu) // verify interlock
{
u32 offset = (cpu->CurInstr >> 6) & 0x1F;
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
offset += cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
cpu->DataRead8(offset, &cpu->R[cpu->CurInstr & 0x7]);
cpu->AddCycles_CDI();
cpu->SetCycles_L(cpu->R[cpu->CurInstr & 0x7], 2, cpu->ILT_Norm);
}
void T_STRH_IMM(ARM* cpu)
void T_STRH_IMM(ARM* cpu) // verify interlock
{
u32 offset = (cpu->CurInstr >> 5) & 0x3E;
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
offset += cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
cpu->DataWrite16(offset, cpu->R[cpu->CurInstr & 0x7]);
cpu->DataWrite16(offset, cpu->GetReg(cpu->CurInstr & 0x7, 1));
cpu->AddCycles_CD();
}
void T_LDRH_IMM(ARM* cpu)
void T_LDRH_IMM(ARM* cpu) // verify interlock
{
u32 offset = (cpu->CurInstr >> 5) & 0x3E;
offset += cpu->R[(cpu->CurInstr >> 3) & 0x7];
offset += cpu->GetReg((cpu->CurInstr >> 3) & 0x7);
cpu->DataRead16(offset, &cpu->R[cpu->CurInstr & 0x7]);
cpu->AddCycles_CDI();
cpu->SetCycles_L(cpu->R[cpu->CurInstr & 0x7], 2, cpu->ILT_Norm);
}
void T_STR_SPREL(ARM* cpu)
void T_STR_SPREL(ARM* cpu) // verify interlock
{
u32 offset = (cpu->CurInstr << 2) & 0x3FC;
offset += cpu->R[13];
offset += cpu->GetReg(13);
cpu->DataWrite32(offset, cpu->R[(cpu->CurInstr >> 8) & 0x7]);
cpu->DataWrite32(offset, cpu->GetReg((cpu->CurInstr >> 8) & 0x7, 1));
cpu->AddCycles_CD();
}
void T_LDR_SPREL(ARM* cpu)
void T_LDR_SPREL(ARM* cpu) // verify interlock
{
u32 offset = (cpu->CurInstr << 2) & 0x3FC;
offset += cpu->R[13];
offset += cpu->GetReg(13);
cpu->DataRead32(offset, &cpu->R[(cpu->CurInstr >> 8) & 0x7]);
cpu->AddCycles_CDI();
cpu->SetCycles_L(cpu->R[(cpu->CurInstr >> 8) & 0x7], 1, cpu->ILT_Norm); // checkme? ROR?
}
@ -907,7 +919,7 @@ void T_PUSH(ARM* cpu)
if (cpu->CurInstr & (1<<8))
nregs++;
u32 base = cpu->R[13];
u32 base = cpu->GetReg(13);
base -= (nregs<<2);
u32 wbbase = base;
@ -915,8 +927,8 @@ void T_PUSH(ARM* cpu)
{
if (cpu->CurInstr & (1<<i))
{
if (!(first ? cpu->DataWrite32 (base, cpu->R[i])
: cpu->DataWrite32S(base, cpu->R[i])))
if (!(first ? cpu->DataWrite32 (base, cpu->GetReg(i, 1))
: cpu->DataWrite32S(base, cpu->GetReg(i, 1)))) // verify interlock
{
goto dataabort;
}
@ -940,10 +952,11 @@ void T_PUSH(ARM* cpu)
cpu->AddCycles_CD();
}
void T_POP(ARM* cpu)
void T_POP(ARM* cpu) // verify interlock
{
u32 base = cpu->R[13];
u32 base = cpu->GetReg(13);
bool first = true;
u32 lastreg = 0;
for (int i = 0; i < 8; i++)
{
@ -974,21 +987,30 @@ void T_POP(ARM* cpu)
cpu->R[13] = base;
if (cpu->Num == 0)
{
u32 lastbase = base - 4;
// no interlock occurs when loading from itcm (checkme: does it matter whether you're executing from there?)
if ((((ARMv5*)cpu)->ITCMSize < lastbase) && ((cpu->R[15]-8) > ((ARMv5*)cpu)->ITCMSize) && (cpu->CurInstr & (0x7FFF >> (15 - lastreg))))
cpu->SetCycles_L(lastreg, 1, cpu->ILT_Norm);
}
return;
dataabort:
cpu->AddCycles_CDI();
}
void T_STMIA(ARM* cpu)
{
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
u32 base = cpu->GetReg((cpu->CurInstr >> 8) & 0x7);
bool first = true;
for (int i = 0; i < 8; i++)
{
if (cpu->CurInstr & (1<<i))
{
if (!(first ? cpu->DataWrite32 (base, cpu->R[i])
: cpu->DataWrite32S(base, cpu->R[i])))
if (!(first ? cpu->DataWrite32 (base, cpu->GetReg(i, 1))
: cpu->DataWrite32S(base, cpu->GetReg(i, 1))))
{
goto dataabort;
}
@ -1005,8 +1027,9 @@ void T_STMIA(ARM* cpu)
void T_LDMIA(ARM* cpu)
{
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
u32 base = cpu->GetReg((cpu->CurInstr >> 8) & 0x7);
bool first = true;
u32 lastreg = 0;
for (int i = 0; i < 8; i++)
{
@ -1019,11 +1042,23 @@ void T_LDMIA(ARM* cpu)
}
first = false;
base += 4;
lastreg = i;
}
}
if (!(cpu->CurInstr & (1<<((cpu->CurInstr >> 8) & 0x7))))
cpu->R[(cpu->CurInstr >> 8) & 0x7] = base;
cpu->AddCycles_CDI();
if (cpu->Num == 0)
{
u32 lastbase = base - 4;
// no interlock occurs when loading from itcm (checkme: does it matter whether you're executing from there?)
if ((((ARMv5*)cpu)->ITCMSize < lastbase) && ((cpu->R[15]-8) > ((ARMv5*)cpu)->ITCMSize) && (cpu->CurInstr & (0x7FFF >> (15 - lastreg))))
cpu->SetCycles_L(lastreg, 1, cpu->ILT_Norm);
}
return;
dataabort:
cpu->AddCycles_CDI();