Merge pull request #837 from reicast/wip/mmu-exceptions
sh4/mmu: C++ exception based sh4 exception support. Won't run wince yet.
This commit is contained in:
commit
915d6b26d6
|
@ -278,4 +278,4 @@
|
|||
|
||||
#ifdef HOST_NO_AREC
|
||||
#error Dont use HOST_NO_AREC
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -346,24 +346,28 @@ sh4op(i1111_nnnn_mmmm_1011)
|
|||
u32 n = GetN(op);
|
||||
u32 m = GetM(op);
|
||||
|
||||
r[n] -= 4;
|
||||
u32 addr = r[n] - 4;
|
||||
|
||||
WriteMemU32(r[n], fr_hex[m]);
|
||||
WriteMemU32(addr, fr_hex[m]);
|
||||
|
||||
r[n] = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 n = GetN(op);
|
||||
u32 m = GetM(op)>>1;
|
||||
|
||||
r[n] -= 8;
|
||||
u32 addr = r[n] - 8;
|
||||
if (((op >> 4) & 0x1) == 0)
|
||||
{
|
||||
WriteMemU64(r[n] , dr_hex[m]);
|
||||
WriteMemU64(addr, dr_hex[m]);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteMemU64(r[n] , xd_hex[m]);
|
||||
WriteMemU64(addr, xd_hex[m]);
|
||||
}
|
||||
|
||||
r[n] = addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,16 +44,27 @@ void Sh4_int_Run()
|
|||
for (int i=0; i<10000; i++)
|
||||
#endif
|
||||
{
|
||||
do
|
||||
{
|
||||
u32 op=ReadMem16(next_pc);
|
||||
next_pc+=2;
|
||||
#if !defined(NO_MMU)
|
||||
try {
|
||||
#endif
|
||||
do
|
||||
{
|
||||
u32 addr = next_pc;
|
||||
next_pc += 2;
|
||||
u32 op = IReadMem16(addr);
|
||||
|
||||
OpPtr[op](op);
|
||||
l-=CPU_RATIO;
|
||||
} while(l>0);
|
||||
l+=SH4_TIMESLICE;
|
||||
UpdateSystem_INTC();
|
||||
OpPtr[op](op);
|
||||
l -= CPU_RATIO;
|
||||
} while (l > 0);
|
||||
l += SH4_TIMESLICE;
|
||||
UpdateSystem_INTC();
|
||||
#if !defined(NO_MMU)
|
||||
}
|
||||
catch (SH4ThrownException ex) {
|
||||
Do_Exception(ex.epc, ex.expEvn, ex.callVect);
|
||||
l -= CPU_RATIO * 5;
|
||||
}
|
||||
#endif
|
||||
#if !defined(TARGET_BOUNDED_EXECUTION)
|
||||
} while(sh4_int_bCpuRun);
|
||||
|
||||
|
@ -134,17 +145,40 @@ bool Sh4_int_IsCpuRunning()
|
|||
//TODO : Check for valid delayslot instruction
|
||||
void ExecuteDelayslot()
|
||||
{
|
||||
u32 op=IReadMem16(next_pc);
|
||||
next_pc+=2;
|
||||
if (op!=0)
|
||||
ExecuteOpcode(op);
|
||||
#if !defined(NO_MMU)
|
||||
try {
|
||||
#endif
|
||||
u32 addr = next_pc;
|
||||
next_pc += 2;
|
||||
u32 op = IReadMem16(addr);
|
||||
if (op != 0)
|
||||
ExecuteOpcode(op);
|
||||
#if !defined(NO_MMU)
|
||||
}
|
||||
catch (SH4ThrownException ex) {
|
||||
ex.epc -= 2;
|
||||
//printf("Delay slot exception\n");
|
||||
throw ex;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ExecuteDelayslot_RTE()
|
||||
{
|
||||
sr.SetFull(ssr);
|
||||
u32 oldsr = sr.GetFull();
|
||||
|
||||
ExecuteDelayslot();
|
||||
#if !defined(NO_MMU)
|
||||
try {
|
||||
#endif
|
||||
sr.SetFull(ssr);
|
||||
|
||||
ExecuteDelayslot();
|
||||
#if !defined(NO_MMU)
|
||||
}
|
||||
catch (SH4ThrownException ex) {
|
||||
msgboxf("RTE Exception", MBX_ICONERROR);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//General update
|
||||
|
@ -271,4 +305,4 @@ void sh4_int_RaiseExeption(u32 ExeptionCode, u32 VectorAddress)
|
|||
//save reg context
|
||||
SaveSh4Regs(&sh4_ex_SRC);
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
|
|
@ -277,24 +277,10 @@ sh4op(i0010_nnnn_mmmm_0100)
|
|||
//iNimp("mov.b <REG_M>,@-<REG_N>");
|
||||
u32 n = GetN(op);
|
||||
u32 m = GetM(op);
|
||||
//r[n]--;
|
||||
if (n==m)
|
||||
{
|
||||
//printf("Mov.b !!!m==n\n");
|
||||
//return;
|
||||
//
|
||||
WriteMemBOU8(r[n],(u32)-1,r[m]);
|
||||
r[n]--;
|
||||
}
|
||||
else
|
||||
{
|
||||
r[n]--;
|
||||
WriteMemU8(r[n],r[m]);
|
||||
}
|
||||
|
||||
|
||||
//WriteMemoryB(r[n], R(m) & 0xFF);
|
||||
|
||||
|
||||
u32 addr = r[n] - 1;
|
||||
WriteMemBOU8(r[n], (u32)-1, r[m]);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
//mov.w <REG_M>,@-<REG_N>
|
||||
|
@ -303,19 +289,10 @@ sh4op(i0010_nnnn_mmmm_0101)
|
|||
//iNimp("mov.w <REG_M>,@-<REG_N>");
|
||||
u32 n = GetN(op);
|
||||
u32 m = GetM(op);
|
||||
//r[n] -= 2;
|
||||
if (n==m)
|
||||
{
|
||||
//printf("Mov.w !!!m==n\n");
|
||||
//return;
|
||||
WriteMemBOU16(r[n],(u32)-2,r[m]);
|
||||
r[n] -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
r[n] -= 2;
|
||||
WriteMemU16(r[n], r[m]);
|
||||
}
|
||||
|
||||
u32 addr = r[n] - 2;
|
||||
WriteMemU16(addr, r[m]);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
//mov.l <REG_M>,@-<REG_N>
|
||||
|
@ -323,20 +300,10 @@ sh4op(i0010_nnnn_mmmm_0110)
|
|||
{
|
||||
u32 n = GetN(op);
|
||||
u32 m = GetM(op);
|
||||
//r[n] -= 4;
|
||||
if (m==n)
|
||||
{
|
||||
//iNimp(op,"Mov.l !!!m==n");
|
||||
//printf("mov.l <REG_M>,@-<REG_N> !!!m==n\n");
|
||||
//return;
|
||||
WriteMemBOU32(r[n],(u32)-4,r[m]);
|
||||
r[n] -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n],r[m]);
|
||||
}
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr, r[m]);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -346,16 +313,20 @@ sh4op(i0100_nnnn_0101_0010)
|
|||
{
|
||||
//iNimp("sts.l FPUL,@-<REG_N>");
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n], fpul);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr, fpul);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
//sts.l MACH,@-<REG_N>
|
||||
sh4op(i0100_nnnn_0000_0010)
|
||||
{
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n], mac.h);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr, mac.h);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -363,8 +334,10 @@ sh4op(i0100_nnnn_0000_0010)
|
|||
sh4op(i0100_nnnn_0001_0010)
|
||||
{
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n], mac.l);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr, mac.l);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -372,16 +345,20 @@ sh4op(i0100_nnnn_0001_0010)
|
|||
sh4op(i0100_nnnn_0010_0010)
|
||||
{
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n],pr);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr,pr);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
//sts.l DBR,@-<REG_N>
|
||||
sh4op(i0100_nnnn_1111_0010)
|
||||
{
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n],dbr);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr,dbr);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
//stc.l GBR,@-<REG_N>
|
||||
|
@ -389,8 +366,10 @@ sh4op(i0100_nnnn_0001_0011)
|
|||
{
|
||||
//iNimp("stc.l GBR,@-<REG_N>");
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n], gbr);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr, gbr);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -399,8 +378,10 @@ sh4op(i0100_nnnn_0010_0011)
|
|||
{
|
||||
//iNimp("stc.l VBR,@-<REG_N>");
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n], vbr);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr, vbr);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -409,16 +390,20 @@ sh4op(i0100_nnnn_0011_0011)
|
|||
{
|
||||
//iNimp("stc.l SSR,@-<REG_N>");
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n], ssr);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr, ssr);
|
||||
r[n] = addr;
|
||||
}
|
||||
//stc.l SGR,@-<REG_N>
|
||||
sh4op(i0100_nnnn_0011_0010)
|
||||
{
|
||||
//iNimp("stc.l SGR,@-<REG_N>");
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n], sgr);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr, sgr);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -427,8 +412,10 @@ sh4op(i0100_nnnn_0100_0011)
|
|||
{
|
||||
//iNimp("stc.l SPC,@-<REG_N>");
|
||||
u32 n = GetN(op);
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n], spc);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr, spc);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
//stc RM_BANK,@-<REG_N>
|
||||
|
@ -437,8 +424,10 @@ sh4op(i0100_nnnn_1mmm_0011)
|
|||
//iNimp("stc RM_BANK,@-<REG_N>");
|
||||
u32 n = GetN(op);
|
||||
u32 m = GetM(op) & 0x07;
|
||||
r[n] -= 4;
|
||||
WriteMemU32(r[n], r_bank[m]);
|
||||
|
||||
u32 addr = r[n] - 4;
|
||||
WriteMemU32(addr, r_bank[m]);
|
||||
r[n] = addr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -923,10 +912,14 @@ sh4op(i0000_nnnn_0010_0011)
|
|||
//bsrf <REG_N>
|
||||
sh4op(i0000_nnnn_0000_0011)
|
||||
{
|
||||
//TODO: Check pr setting vs real h/w
|
||||
u32 n = GetN(op);
|
||||
u32 newpc = r[n] + next_pc +2;
|
||||
pr = next_pc + 2; //after delayslot
|
||||
u32 newpr = next_pc + 2;
|
||||
|
||||
ExecuteDelayslot(); //WARN : pr and r[n] can change here
|
||||
|
||||
pr = newpr;
|
||||
next_pc = newpc;
|
||||
}
|
||||
|
||||
|
@ -1023,9 +1016,12 @@ sh4op(i1010_iiii_iiii_iiii)
|
|||
// bsr <bdisp12>
|
||||
sh4op(i1011_iiii_iiii_iiii)
|
||||
{
|
||||
pr = next_pc + 2; //return after delayslot
|
||||
//TODO: check pr vs real h/w
|
||||
u32 newpr = next_pc + 2; //return after delayslot
|
||||
u32 newpc = branch_target_s12(op);
|
||||
ExecuteDelayslot();
|
||||
|
||||
pr = newpr;
|
||||
next_pc=newpc;
|
||||
}
|
||||
|
||||
|
@ -1034,7 +1030,7 @@ sh4op(i1100_0011_iiii_iiii)
|
|||
{
|
||||
//printf("trapa 0x%X\n",(GetImm8(op) << 2));
|
||||
CCN_TRA = (GetImm8(op) << 2);
|
||||
Do_Exeption(next_pc,0x160,0x100);
|
||||
Do_Exception(next_pc,0x160,0x100);
|
||||
}
|
||||
|
||||
//jmp @<REG_N>
|
||||
|
@ -1052,9 +1048,12 @@ sh4op(i0100_nnnn_0000_1011)
|
|||
{
|
||||
u32 n = GetN(op);
|
||||
|
||||
pr = next_pc + 2; //return after delayslot
|
||||
//TODO: check pr vs real h/w
|
||||
u32 newpr = next_pc + 2; //return after delayslot
|
||||
u32 newpc= r[n];
|
||||
ExecuteDelayslot(); //r[n]/pr can change here
|
||||
|
||||
pr = newpr;
|
||||
next_pc=newpc;
|
||||
}
|
||||
|
||||
|
@ -1227,7 +1226,7 @@ sh4op(i0000_0000_0000_1001)
|
|||
//ldtlb
|
||||
sh4op(i0000_0000_0011_1000)
|
||||
{
|
||||
printf("ldtlb %d/%d\n",CCN_MMUCR.URC,CCN_MMUCR.URB);
|
||||
//printf("ldtlb %d/%d\n",CCN_MMUCR.URC,CCN_MMUCR.URB);
|
||||
UTLB[CCN_MMUCR.URC].Data=CCN_PTEL;
|
||||
UTLB[CCN_MMUCR.URC].Address=CCN_PTEH;
|
||||
|
||||
|
@ -2210,6 +2209,13 @@ sh4op(i0100_nnnn_0000_1110)
|
|||
//Not implt
|
||||
sh4op(iNotImplemented)
|
||||
{
|
||||
cpu_iNimp(op,"Unknown opcode");
|
||||
#ifndef NO_MMU
|
||||
printf("iNimp %04X\n", op);
|
||||
SH4ThrownException ex = { next_pc - 2, 0x180, 0x100 };
|
||||
throw ex;
|
||||
#else
|
||||
cpu_iNimp(op, "Unknown opcode");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -71,8 +71,8 @@ defining NO_MMU disables the full mmu emulation
|
|||
|
||||
#include "hw/mem/_vmem.h"
|
||||
|
||||
#define printf_mmu
|
||||
#define printf_win32 log
|
||||
#define printf_mmu(...)
|
||||
#define printf_win32(...)
|
||||
|
||||
//SQ fast remap , mailny hackish , assumes 1 mb pages
|
||||
//max 64 mb can be remapped on SQ
|
||||
|
@ -145,8 +145,13 @@ void ITLB_Sync(u32 entry)
|
|||
printf_mmu("ITLB MEM remap %d : 0x%X to 0x%X : %d\n", entry, ITLB[entry].Address.VPN << 10, ITLB[entry].Data.PPN << 10, ITLB[entry].Data.V);
|
||||
}
|
||||
|
||||
void RaiseException(u32 a, u32 b) {
|
||||
void RaiseException(u32 expEvnt, u32 callVect) {
|
||||
#if !defined(NO_MMU)
|
||||
SH4ThrownException ex = { next_pc - 2, expEvnt, callVect };
|
||||
throw ex;
|
||||
#else
|
||||
msgboxf("Can't raise exceptions yet", MBX_ICONERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
u32 mmu_error_TT;
|
||||
|
@ -217,7 +222,7 @@ void mmu_raise_exeption(u32 mmu_error, u32 address, u32 am)
|
|||
RaiseException(0xE0, 0x100);
|
||||
else //IADDERR - Instruction Address Error
|
||||
{
|
||||
printf("MMU_ERROR_BADADDR(i) 0x%X\n", address);
|
||||
printf_mmu("MMU_ERROR_BADADDR(i) 0x%X\n", address);
|
||||
RaiseException(0xE0, 0x100);
|
||||
return;
|
||||
}
|
||||
|
@ -709,4 +714,4 @@ bool mmu_TranslateSQW(u32 adr, u32* out)
|
|||
#endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -16,6 +16,8 @@ extern u32 sq_remap[64];
|
|||
bool UTLB_Sync(u32 entry);
|
||||
void ITLB_Sync(u32 entry);
|
||||
|
||||
bool mmu_match(u32 va, CCN_PTEH_type Address, CCN_PTEL_type Data);
|
||||
|
||||
#if defined(NO_MMU)
|
||||
bool inline mmu_TranslateSQW(u32 addr, u32* mapped) {
|
||||
*mapped = sq_remap[(addr>>20)&0x3F] | (addr & 0xFFFE0);
|
||||
|
|
|
@ -101,4 +101,10 @@ void SetFloatStatusReg();
|
|||
|
||||
|
||||
bool Do_Interrupt(u32 intEvn);
|
||||
bool Do_Exeption(u32 epc, u32 expEvn, u32 CallVect);
|
||||
bool Do_Exception(u32 epc, u32 expEvn, u32 CallVect);
|
||||
|
||||
struct SH4ThrownException {
|
||||
u32 epc;
|
||||
u32 expEvn;
|
||||
u32 callVect;
|
||||
};
|
|
@ -49,7 +49,7 @@ DECL_ALIGN(64) u32 InterruptBit[32] = { 0 };
|
|||
DECL_ALIGN(64) u32 InterruptLevelBit[16] = { 0 };
|
||||
|
||||
bool Do_Interrupt(u32 intEvn);
|
||||
bool Do_Exeption(u32 epc, u32 expEvn, u32 CallVect);
|
||||
bool Do_Exception(u32 epc, u32 expEvn, u32 CallVect);
|
||||
|
||||
u32 interrupt_vpend; // Vector of pending interrupts
|
||||
u32 interrupt_vmask; // Vector of masked interrupts (-1 inhibits all interrupts)
|
||||
|
@ -158,8 +158,9 @@ bool Do_Interrupt(u32 intEvn)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Do_Exeption(u32 epc, u32 expEvn, u32 CallVect)
|
||||
bool Do_Exception(u32 epc, u32 expEvn, u32 CallVect)
|
||||
{
|
||||
verify(sr.BL == 0);
|
||||
CCN_EXPEVT = expEvn;
|
||||
|
||||
ssr = sr.GetFull();
|
||||
|
@ -172,7 +173,7 @@ bool Do_Exeption(u32 epc, u32 expEvn, u32 CallVect)
|
|||
|
||||
next_pc = vbr + CallVect;
|
||||
|
||||
printf("RaiseException: from %08X , pc errh %08X\n", spc, epc);
|
||||
//printf("RaiseException: from %08X , pc errh %08X, %08X vect\n", spc, epc, next_pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ void ResetInterruptMask(InterruptID intr);
|
|||
int UpdateINTC();
|
||||
//extern u32 interrupt_pend; //nonzero if there are pending interrupts
|
||||
|
||||
bool Do_Exeption(u32 lvl, u32 expEvn, u32 CallVect);
|
||||
bool Do_Exception(u32 lvl, u32 expEvn, u32 CallVect);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -345,7 +345,10 @@ void DYNACALL WriteMem_P4(u32 addr,T data)
|
|||
{
|
||||
if (addr&0x80)
|
||||
{
|
||||
printf("Unhandled p4 Write [Unified TLB address array, Associative Write] 0x%x = %x\n",addr,data);
|
||||
#ifdef NO_MMU
|
||||
printf("Unhandled p4 Write [Unified TLB address array, Associative Write] 0x%x = %x\n",addr,data);
|
||||
#endif
|
||||
|
||||
CCN_PTEH_type t;
|
||||
t.reg_data=data;
|
||||
|
||||
|
@ -353,25 +356,26 @@ void DYNACALL WriteMem_P4(u32 addr,T data)
|
|||
|
||||
for (int i=0;i<64;i++)
|
||||
{
|
||||
/*if (mmu_match(va,UTLB[i].Address,UTLB[i].Data))
|
||||
#ifndef NO_MMU
|
||||
if (mmu_match(va,UTLB[i].Address,UTLB[i].Data))
|
||||
{
|
||||
UTLB[i].Data.V=((u32)data>>8)&1;
|
||||
UTLB[i].Data.D=((u32)data>>9)&1;
|
||||
UTLB_Sync(i);
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
for (int i=0;i<4;i++)
|
||||
{
|
||||
/*
|
||||
#ifndef NO_MMU
|
||||
if (mmu_match(va,ITLB[i].Address,ITLB[i].Data))
|
||||
{
|
||||
ITLB[i].Data.V=((u32)data>>8)&1;
|
||||
ITLB[i].Data.D=((u32)data>>9)&1;
|
||||
ITLB_Sync(i);
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue