Merge branch 'interpreter-fixes' into less-ambitious-timing-rework
This commit is contained in:
commit
f2a02abd16
|
@ -1359,7 +1359,7 @@ bool ARMv4::DataWrite32(u32 addr, u32 val)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ARMv4::DataWrite32S(u32 addr, u32 val, bool dataabort)
|
||||
bool ARMv4::DataWrite32S(u32 addr, u32 val)
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ public:
|
|||
virtual bool DataWrite8(u32 addr, u8 val) = 0;
|
||||
virtual bool DataWrite16(u32 addr, u16 val) = 0;
|
||||
virtual bool DataWrite32(u32 addr, u32 val) = 0;
|
||||
virtual bool DataWrite32S(u32 addr, u32 val, bool dataabort = false) = 0;
|
||||
virtual bool DataWrite32S(u32 addr, u32 val) = 0;
|
||||
|
||||
virtual void AddCycles_C() = 0;
|
||||
virtual void AddCycles_CI(s32 numI) = 0;
|
||||
|
@ -264,7 +264,7 @@ public:
|
|||
bool DataWrite8(u32 addr, u8 val) override;
|
||||
bool DataWrite16(u32 addr, u16 val) override;
|
||||
bool DataWrite32(u32 addr, u32 val) override;
|
||||
bool DataWrite32S(u32 addr, u32 val, bool dataabort = false) override;
|
||||
bool DataWrite32S(u32 addr, u32 val) override;
|
||||
|
||||
template<u8 nregs>
|
||||
void ExecuteStage(u8 rn, u8 rm)
|
||||
|
@ -412,7 +412,7 @@ public:
|
|||
bool DataWrite8(u32 addr, u8 val) override;
|
||||
bool DataWrite16(u32 addr, u16 val) override;
|
||||
bool DataWrite32(u32 addr, u32 val) override;
|
||||
bool DataWrite32S(u32 addr, u32 val, bool dataabort = false) override;
|
||||
bool DataWrite32S(u32 addr, u32 val) override;
|
||||
void AddCycles_C() override;
|
||||
void AddCycles_CI(s32 num) override;
|
||||
void AddCycles_CDI() override;
|
||||
|
|
|
@ -82,10 +82,10 @@ void LoadSingle(ARM* cpu, u8 rd, u8 rn, s32 offset)
|
|||
}
|
||||
|
||||
u32 val;
|
||||
bool dataabort;
|
||||
if constexpr (size == 8) dataabort = !cpu->DataRead8 (addr, &val);
|
||||
if constexpr (size == 16) dataabort = !cpu->DataRead16(addr, &val);
|
||||
if constexpr (size == 32) dataabort = !cpu->DataRead32(addr, &val);
|
||||
bool dabort;
|
||||
if constexpr (size == 8) dabort = !cpu->DataRead8 (addr, &val);
|
||||
if constexpr (size == 16) dabort = !cpu->DataRead16(addr, &val);
|
||||
if constexpr (size == 32) dabort = !cpu->DataRead32(addr, &val);
|
||||
|
||||
if constexpr (writeback == Writeback::Trans)
|
||||
{
|
||||
|
@ -94,8 +94,11 @@ void LoadSingle(ARM* cpu, u8 rd, u8 rn, s32 offset)
|
|||
}
|
||||
|
||||
cpu->AddCycles_CDI();
|
||||
if (dataabort) return;
|
||||
|
||||
if (dabort) [[unlikely]]
|
||||
{
|
||||
((ARMv5*)cpu)->DataAbort();
|
||||
return;
|
||||
}
|
||||
if constexpr (size == 8 && signror) val = (s32)(s8)val;
|
||||
if constexpr (size == 16 && signror) val = (s32)(s16)val;
|
||||
if constexpr (size == 32 && signror) val = ROR(val, ((addr&0x3)<<3));
|
||||
|
@ -128,10 +131,10 @@ void StoreSingle(ARM* cpu, u8 rd, u8 rn, s32 offset)
|
|||
((ARMv5*)cpu)->PU_Map = ((ARMv5*)cpu)->PU_UserMap;
|
||||
}
|
||||
|
||||
bool dataabort;
|
||||
if constexpr (size == 8) dataabort = !cpu->DataWrite8 (addr, storeval);
|
||||
if constexpr (size == 16) dataabort = !cpu->DataWrite16(addr, storeval);
|
||||
if constexpr (size == 32) dataabort = !cpu->DataWrite32(addr, storeval);
|
||||
bool dabort;
|
||||
if constexpr (size == 8) dabort = !cpu->DataWrite8 (addr, storeval);
|
||||
if constexpr (size == 16) dabort = !cpu->DataWrite16(addr, storeval);
|
||||
if constexpr (size == 32) dabort = !cpu->DataWrite32(addr, storeval);
|
||||
|
||||
if constexpr (writeback == Writeback::Trans)
|
||||
{
|
||||
|
@ -140,7 +143,11 @@ void StoreSingle(ARM* cpu, u8 rd, u8 rn, s32 offset)
|
|||
}
|
||||
|
||||
cpu->AddCycles_CD();
|
||||
if (dataabort) return;
|
||||
if (dabort) [[unlikely]]
|
||||
{
|
||||
((ARMv5*)cpu)->DataAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (writeback != Writeback::None) cpu->R[rn] += offset;
|
||||
}
|
||||
|
@ -273,8 +280,12 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||
if (r&1) { A_UNK(cpu); return; } \
|
||||
if (!cpu->DataRead32 (offset , &cpu->R[r ])) {cpu->AddCycles_CDI(); return;} \
|
||||
u32 val; if (!cpu->DataRead32S(offset+4, &val)) {cpu->AddCycles_CDI(); return;} \
|
||||
bool dabort = !cpu->DataRead32(offset, &cpu->R[r]); \
|
||||
u32 val; dabort |= !cpu->DataRead32S(offset+4, &val); \
|
||||
if (dabort) { \
|
||||
cpu->AddCycles_CDI(); \
|
||||
((ARMv5*)cpu)->DataAbort(); \
|
||||
return; } \
|
||||
if (r == 14) cpu->JumpTo(((((ARMv5*)cpu)->CP15Control & (1<<15)) ? (val & ~0x1) : val), cpu->CurInstr & (1<<22)); /* restores cpsr presumably due to shared dna with ldm */ \
|
||||
else cpu->R[r+1] = val; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
|
@ -285,8 +296,12 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||
if (r&1) { A_UNK(cpu); return; } \
|
||||
if (!cpu->DataRead32 (addr , &cpu->R[r ])) {cpu->AddCycles_CDI(); return;} \
|
||||
u32 val; if (!cpu->DataRead32S(addr+4, &val)) {cpu->AddCycles_CDI(); return;} \
|
||||
bool dabort = !cpu->DataRead32(addr, &cpu->R[r]); \
|
||||
u32 val; dabort |= !cpu->DataRead32S(addr+4, &val); \
|
||||
if (dabort) { \
|
||||
cpu->AddCycles_CDI(); \
|
||||
((ARMv5*)cpu)->DataAbort(); \
|
||||
return; } \
|
||||
if (r == 14) cpu->JumpTo(((((ARMv5*)cpu)->CP15Control & (1<<15)) ? (val & ~0x1) : val), cpu->CurInstr & (1<<22)); /* restores cpsr presumably due to shared dna with ldm */ \
|
||||
else cpu->R[r+1] = val; \
|
||||
cpu->AddCycles_CDI(); \
|
||||
|
@ -297,11 +312,13 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||
offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||
if (r&1) { A_UNK(cpu); return; } \
|
||||
bool dataabort = !cpu->DataWrite32(offset, cpu->R[r]); /* yes, this data abort behavior is on purpose */ \
|
||||
bool dabort = !cpu->DataWrite32(offset, cpu->R[r]); /* yes, this data abort behavior is on purpose */ \
|
||||
u32 storeval = cpu->R[r+1]; if (r == 14) storeval+=4; \
|
||||
dataabort |= !cpu->DataWrite32S (offset+4, storeval, dataabort); /* no, i dont understand it either */ \
|
||||
dabort |= !cpu->DataWrite32S (offset+4, storeval); /* no, i dont understand it either */ \
|
||||
cpu->AddCycles_CD(); \
|
||||
if (dataabort) return; \
|
||||
if (dabort) [[unlikely]] { \
|
||||
((ARMv5*)cpu)->DataAbort(); \
|
||||
return; } \
|
||||
if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset;
|
||||
|
||||
#define A_STRD_POST \
|
||||
|
@ -309,11 +326,13 @@ A_IMPLEMENT_WB_LDRSTR(LDRB)
|
|||
u32 addr = cpu->R[(cpu->CurInstr>>16) & 0xF]; \
|
||||
u32 r = (cpu->CurInstr>>12) & 0xF; \
|
||||
if (r&1) { A_UNK(cpu); return; } \
|
||||
bool dataabort = !cpu->DataWrite32(addr, cpu->R[r]); \
|
||||
bool dabort = !cpu->DataWrite32(addr, cpu->R[r]); \
|
||||
u32 storeval = cpu->R[r+1]; if (r == 14) storeval+=4; \
|
||||
dataabort |= !cpu->DataWrite32S (addr+4, storeval, dataabort); \
|
||||
dabort |= !cpu->DataWrite32S (addr+4, storeval); \
|
||||
cpu->AddCycles_CD(); \
|
||||
if (dataabort) return; \
|
||||
if (dabort) [[unlikely]] { \
|
||||
((ARMv5*)cpu)->DataAbort(); \
|
||||
return; } \
|
||||
cpu->R[(cpu->CurInstr>>16) & 0xF] += offset;
|
||||
|
||||
#define A_LDRH \
|
||||
|
@ -381,12 +400,12 @@ inline void SWP(ARM* cpu)
|
|||
|
||||
u32 val;
|
||||
if ((byte ? cpu->DataRead8 (base, &val)
|
||||
: cpu->DataRead32(base, &val)))
|
||||
: cpu->DataRead32(base, &val))) [[likely]]
|
||||
{
|
||||
u32 numD = cpu->DataCycles;
|
||||
|
||||
if ((byte ? cpu->DataWrite8 (base, rm)
|
||||
: cpu->DataWrite32(base, rm)))
|
||||
: cpu->DataWrite32(base, rm))) [[likely]]
|
||||
{
|
||||
// rd only gets updated if both read and write succeed
|
||||
u32 rd = (cpu->CurInstr >> 12) & 0xF;
|
||||
|
@ -396,9 +415,11 @@ inline void SWP(ARM* cpu)
|
|||
if (rd != 15) cpu->R[rd] = val;
|
||||
else if (cpu->Num==1) cpu->JumpTo(val & ~1); // for some reason these jumps don't seem to work on the arm 9?
|
||||
}
|
||||
else ((ARMv5*)cpu)->DataAbort();
|
||||
|
||||
cpu->DataCycles += numD;
|
||||
}
|
||||
else ((ARMv5*)cpu)->DataAbort();
|
||||
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
@ -423,6 +444,7 @@ void A_LDM(ARM* cpu)
|
|||
u32 oldbase = base;
|
||||
u32 preinc = (cpu->CurInstr & (1<<24));
|
||||
bool first = true;
|
||||
bool dabort = false;
|
||||
|
||||
if (!(cpu->CurInstr & (1<<23))) // decrement
|
||||
{
|
||||
|
@ -451,11 +473,12 @@ void A_LDM(ARM* cpu)
|
|||
if (cpu->CurInstr & (1<<i))
|
||||
{
|
||||
if (preinc) base += 4;
|
||||
if (!(first ? cpu->DataRead32 (base, &cpu->R[i])
|
||||
: cpu->DataRead32S(base, &cpu->R[i])))
|
||||
{
|
||||
goto dataabort;
|
||||
}
|
||||
u32 val;
|
||||
dabort |= !(first ? cpu->DataRead32 (base, &val)
|
||||
: cpu->DataRead32S(base, &val));
|
||||
|
||||
// remaining loads still occur but are not written to a reg after a data abort is raised
|
||||
if (!dabort) [[likely]] cpu->R[i] = val;
|
||||
|
||||
first = false;
|
||||
if (!preinc) base += 4;
|
||||
|
@ -466,11 +489,8 @@ void A_LDM(ARM* cpu)
|
|||
if ((cpu->CurInstr & (1<<15)))
|
||||
{
|
||||
if (preinc) base += 4;
|
||||
if (!(first ? cpu->DataRead32 (base, &pc)
|
||||
: cpu->DataRead32S(base, &pc)))
|
||||
{
|
||||
goto dataabort;
|
||||
}
|
||||
dabort |= !(first ? cpu->DataRead32 (base, &pc)
|
||||
: cpu->DataRead32S(base, &pc));
|
||||
|
||||
if (!preinc) base += 4;
|
||||
|
||||
|
@ -482,6 +502,14 @@ void A_LDM(ARM* cpu)
|
|||
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
|
||||
cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true);
|
||||
|
||||
// handle data aborts
|
||||
if (dabort) [[unlikely]]
|
||||
{
|
||||
cpu->AddCycles_CDI();
|
||||
((ARMv5*)cpu)->DataAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
// writeback to base
|
||||
if (cpu->CurInstr & (1<<21))
|
||||
{
|
||||
|
@ -506,19 +534,6 @@ void A_LDM(ARM* cpu)
|
|||
if (cpu->CurInstr & (1<<15))
|
||||
cpu->JumpTo(pc, cpu->CurInstr & (1<<22));
|
||||
|
||||
// jump here if a data abort occurred; writeback is ignored, and any jumps were aborted
|
||||
if (false)
|
||||
{
|
||||
dataabort:
|
||||
|
||||
// switch back to original set of regs
|
||||
if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15)))
|
||||
cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true);
|
||||
|
||||
// restore original value of base in case the reg got written to
|
||||
cpu->R[baseid] = oldbase;
|
||||
}
|
||||
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
@ -529,6 +544,7 @@ void A_STM(ARM* cpu)
|
|||
u32 oldbase = base;
|
||||
u32 preinc = (cpu->CurInstr & (1<<24));
|
||||
bool first = true;
|
||||
bool dabort = false;
|
||||
|
||||
if (!(cpu->CurInstr & (1<<23)))
|
||||
{
|
||||
|
@ -573,11 +589,8 @@ void A_STM(ARM* cpu)
|
|||
|
||||
if (i == 15) val+=4;
|
||||
|
||||
if (!(first ? cpu->DataWrite32 (base, val)
|
||||
: cpu->DataWrite32S(base, val)))
|
||||
{
|
||||
goto dataabort;
|
||||
}
|
||||
dabort |= !(first ? cpu->DataWrite32 (base, val)
|
||||
: cpu->DataWrite32S(base, val));
|
||||
|
||||
first = false;
|
||||
|
||||
|
@ -587,21 +600,20 @@ void A_STM(ARM* cpu)
|
|||
|
||||
if (cpu->CurInstr & (1<<22))
|
||||
cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true);
|
||||
|
||||
// handle data aborts
|
||||
if (dabort) [[unlikely]]
|
||||
{
|
||||
// restore original value of base
|
||||
cpu->R[baseid] = oldbase;
|
||||
cpu->AddCycles_CD();
|
||||
((ARMv5*)cpu)->DataAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cpu->CurInstr & (1<<23)) && (cpu->CurInstr & (1<<21)))
|
||||
cpu->R[baseid] = base;
|
||||
|
||||
// jump here if a data abort occurred
|
||||
if (false)
|
||||
{
|
||||
dataabort:
|
||||
|
||||
if (cpu->CurInstr & (1<<22))
|
||||
cpu->UpdateMode((cpu->CPSR&~0x1F)|0x10, cpu->CPSR, true);
|
||||
|
||||
// restore original value of base
|
||||
cpu->R[baseid] = oldbase;
|
||||
}
|
||||
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
@ -616,9 +628,13 @@ void A_STM(ARM* cpu)
|
|||
void T_LDR_PCREL(ARM* cpu)
|
||||
{
|
||||
u32 addr = (cpu->R[15] & ~0x2) + ((cpu->CurInstr & 0xFF) << 2);
|
||||
cpu->DataRead32(addr, &cpu->R[(cpu->CurInstr >> 8) & 0x7]);
|
||||
bool dabort = !cpu->DataRead32(addr, &cpu->R[(cpu->CurInstr >> 8) & 0x7]);
|
||||
|
||||
cpu->AddCycles_CDI();
|
||||
if (dabort) [[unlikely]]
|
||||
{
|
||||
((ARMv5*)cpu)->DataAbort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -711,6 +727,7 @@ void T_PUSH(ARM* cpu)
|
|||
{
|
||||
int nregs = 0;
|
||||
bool first = true;
|
||||
bool dabort = false;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
|
@ -729,11 +746,9 @@ void T_PUSH(ARM* cpu)
|
|||
{
|
||||
if (cpu->CurInstr & (1<<i))
|
||||
{
|
||||
if (!(first ? cpu->DataWrite32 (base, cpu->R[i])
|
||||
: cpu->DataWrite32S(base, cpu->R[i])))
|
||||
{
|
||||
goto dataabort;
|
||||
}
|
||||
dabort |= !(first ? cpu->DataWrite32 (base, cpu->R[i])
|
||||
: cpu->DataWrite32S(base, cpu->R[i]));
|
||||
|
||||
first = false;
|
||||
base += 4;
|
||||
}
|
||||
|
@ -741,16 +756,19 @@ void T_PUSH(ARM* cpu)
|
|||
|
||||
if (cpu->CurInstr & (1<<8))
|
||||
{
|
||||
if (!(first ? cpu->DataWrite32 (base, cpu->R[14])
|
||||
: cpu->DataWrite32S(base, cpu->R[14])))
|
||||
{
|
||||
goto dataabort;
|
||||
}
|
||||
dabort |= !(first ? cpu->DataWrite32 (base, cpu->R[14])
|
||||
: cpu->DataWrite32S(base, cpu->R[14]));
|
||||
}
|
||||
|
||||
if (dabort) [[unlikely]]
|
||||
{
|
||||
cpu->AddCycles_CD();
|
||||
((ARMv5*)cpu)->DataAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
cpu->R[13] = wbbase;
|
||||
|
||||
dataabort:
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
|
@ -758,16 +776,18 @@ void T_POP(ARM* cpu)
|
|||
{
|
||||
u32 base = cpu->R[13];
|
||||
bool first = true;
|
||||
bool dabort = false;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (cpu->CurInstr & (1<<i))
|
||||
{
|
||||
if (!(first ? cpu->DataRead32 (base, &cpu->R[i])
|
||||
: cpu->DataRead32S(base, &cpu->R[i])))
|
||||
{
|
||||
goto dataabort;
|
||||
}
|
||||
u32 val;
|
||||
dabort |= !(first ? cpu->DataRead32 (base, &val)
|
||||
: cpu->DataRead32S(base, &val));
|
||||
|
||||
if (!dabort) [[likely]] cpu->R[i] = val;
|
||||
|
||||
first = false;
|
||||
base += 4;
|
||||
}
|
||||
|
@ -776,19 +796,25 @@ void T_POP(ARM* cpu)
|
|||
if (cpu->CurInstr & (1<<8))
|
||||
{
|
||||
u32 pc;
|
||||
if (!(first ? cpu->DataRead32 (base, &pc)
|
||||
: cpu->DataRead32S(base, &pc)))
|
||||
{
|
||||
goto dataabort;
|
||||
}
|
||||
dabort |= !(first ? cpu->DataRead32 (base, &pc)
|
||||
: cpu->DataRead32S(base, &pc));
|
||||
|
||||
if (dabort) [[unlikely]] goto dataabort;
|
||||
if (cpu->Num==1 || (((ARMv5*)cpu)->CP15Control & (1<<15))) pc |= 0x1;
|
||||
cpu->JumpTo(pc);
|
||||
base += 4;
|
||||
}
|
||||
|
||||
if (dabort) [[unlikely]]
|
||||
{
|
||||
dataabort:
|
||||
cpu->AddCycles_CDI();
|
||||
((ARMv5*)cpu)->DataAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
cpu->R[13] = base;
|
||||
|
||||
dataabort:
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
@ -796,24 +822,29 @@ void T_STMIA(ARM* cpu)
|
|||
{
|
||||
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
||||
bool first = true;
|
||||
bool dabort = false;
|
||||
|
||||
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])))
|
||||
{
|
||||
goto dataabort;
|
||||
}
|
||||
dabort |= !(first ? cpu->DataWrite32 (base, cpu->R[i])
|
||||
: cpu->DataWrite32S(base, cpu->R[i]));
|
||||
|
||||
first = false;
|
||||
base += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (dabort) [[unlikely]]
|
||||
{
|
||||
cpu->AddCycles_CD();
|
||||
((ARMv5*)cpu)->DataAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: check "Rb included in Rlist" case
|
||||
cpu->R[(cpu->CurInstr >> 8) & 0x7] = base;
|
||||
dataabort:
|
||||
cpu->AddCycles_CD();
|
||||
}
|
||||
|
||||
|
@ -821,25 +852,32 @@ void T_LDMIA(ARM* cpu)
|
|||
{
|
||||
u32 base = cpu->R[(cpu->CurInstr >> 8) & 0x7];
|
||||
bool first = true;
|
||||
bool dabort = false;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (cpu->CurInstr & (1<<i))
|
||||
{
|
||||
if (!(first ? cpu->DataRead32 (base, &cpu->R[i])
|
||||
: cpu->DataRead32S(base, &cpu->R[i])))
|
||||
{
|
||||
goto dataabort;
|
||||
}
|
||||
u32 val;
|
||||
dabort |= !(first ? cpu->DataRead32 (base, &val)
|
||||
: cpu->DataRead32S(base, &val));
|
||||
|
||||
if (!dabort) [[likely]] cpu->R[i] = val;
|
||||
first = false;
|
||||
base += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (dabort) [[unlikely]]
|
||||
{
|
||||
cpu->AddCycles_CDI();
|
||||
((ARMv5*)cpu)->DataAbort();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(cpu->CurInstr & (1<<((cpu->CurInstr >> 8) & 0x7))))
|
||||
cpu->R[(cpu->CurInstr >> 8) & 0x7] = base;
|
||||
|
||||
dataabort:
|
||||
cpu->AddCycles_CDI();
|
||||
}
|
||||
|
||||
|
|
34
src/CP15.cpp
34
src/CP15.cpp
|
@ -830,9 +830,11 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch)
|
|||
bool ARMv5::DataRead8(u32 addr, u32* val)
|
||||
{
|
||||
Store = false;
|
||||
// Data Aborts
|
||||
// Exception is handled in the actual instruction implementation
|
||||
if (!(PU_Map[addr>>12] & 0x01)) [[unlikely]]
|
||||
{
|
||||
DataAbort();
|
||||
DataCycles = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -871,9 +873,11 @@ bool ARMv5::DataRead8(u32 addr, u32* val)
|
|||
bool ARMv5::DataRead16(u32 addr, u32* val)
|
||||
{
|
||||
Store = false;
|
||||
// Data Aborts
|
||||
// Exception is handled in the actual instruction implementation
|
||||
if (!(PU_Map[addr>>12] & 0x01)) [[unlikely]]
|
||||
{
|
||||
DataAbort();
|
||||
DataCycles = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -914,9 +918,11 @@ bool ARMv5::DataRead16(u32 addr, u32* val)
|
|||
bool ARMv5::DataRead32(u32 addr, u32* val)
|
||||
{
|
||||
Store = false;
|
||||
// Data Aborts
|
||||
// Exception is handled in the actual instruction implementation
|
||||
if (!(PU_Map[addr>>12] & 0x01)) [[unlikely]]
|
||||
{
|
||||
DataAbort();
|
||||
DataCycles = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -956,9 +962,11 @@ bool ARMv5::DataRead32(u32 addr, u32* val)
|
|||
|
||||
bool ARMv5::DataRead32S(u32 addr, u32* val)
|
||||
{
|
||||
// Data Aborts
|
||||
// Exception is handled in the actual instruction implementation
|
||||
if (!(PU_Map[addr>>12] & 0x01)) [[unlikely]]
|
||||
{
|
||||
DataAbort();
|
||||
DataCycles += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1000,9 +1008,11 @@ bool ARMv5::DataRead32S(u32 addr, u32* val)
|
|||
bool ARMv5::DataWrite8(u32 addr, u8 val)
|
||||
{
|
||||
Store = true;
|
||||
// Data Aborts
|
||||
// Exception is handled in the actual instruction implementation
|
||||
if (!(PU_Map[addr>>12] & 0x02)) [[unlikely]]
|
||||
{
|
||||
DataAbort();
|
||||
DataCycles = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1043,9 +1053,11 @@ bool ARMv5::DataWrite8(u32 addr, u8 val)
|
|||
bool ARMv5::DataWrite16(u32 addr, u16 val)
|
||||
{
|
||||
Store = true;
|
||||
// Data Aborts
|
||||
// Exception is handled in the actual instruction implementation
|
||||
if (!(PU_Map[addr>>12] & 0x02)) [[unlikely]]
|
||||
{
|
||||
DataAbort();
|
||||
DataCycles = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1088,9 +1100,11 @@ bool ARMv5::DataWrite16(u32 addr, u16 val)
|
|||
bool ARMv5::DataWrite32(u32 addr, u32 val)
|
||||
{
|
||||
Store = true;
|
||||
// Data Aborts
|
||||
// Exception is handled in the actual instruction implementation
|
||||
if (!(PU_Map[addr>>12] & 0x02)) [[unlikely]]
|
||||
{
|
||||
DataAbort();
|
||||
DataCycles = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1130,11 +1144,13 @@ bool ARMv5::DataWrite32(u32 addr, u32 val)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ARMv5::DataWrite32S(u32 addr, u32 val, bool dataabort)
|
||||
bool ARMv5::DataWrite32S(u32 addr, u32 val)
|
||||
{
|
||||
// Data Aborts
|
||||
// Exception is handled in the actual instruction implementation
|
||||
if (!(PU_Map[addr>>12] & 0x02)) [[unlikely]]
|
||||
{
|
||||
if (!dataabort) DataAbort();
|
||||
DataCycles += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue