diff --git a/core/build.h b/core/build.h index 7aee3b931..9bae011cc 100755 --- a/core/build.h +++ b/core/build.h @@ -115,7 +115,7 @@ */ -#define NO_MMU +//#define NO_MMU #define DC_PLATFORM_MASK 7 #define DC_PLATFORM_DREAMCAST 0 /* Works, for the most part */ diff --git a/core/hw/sh4/interpr/sh4_fpu.cpp b/core/hw/sh4/interpr/sh4_fpu.cpp index c7a5c4091..aa6acaec7 100644 --- a/core/hw/sh4/interpr/sh4_fpu.cpp +++ b/core/hw/sh4/interpr/sh4_fpu.cpp @@ -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; } } diff --git a/core/hw/sh4/interpr/sh4_interpreter.cpp b/core/hw/sh4/interpr/sh4_interpreter.cpp index 7c87bb70e..9af108827 100644 --- a/core/hw/sh4/interpr/sh4_interpreter.cpp +++ b/core/hw/sh4/interpr/sh4_interpreter.cpp @@ -44,16 +44,23 @@ void Sh4_int_Run() for (int i=0; i<10000; i++) #endif { - do - { - u32 op=ReadMem16(next_pc); - next_pc+=2; + try { + 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(); + } + catch (SH4ThrownException ex) { + Do_Exeption(ex.epc, ex.expEvn, ex.callVect); + l -= CPU_RATIO * 5; + } #if !defined(TARGET_BOUNDED_EXECUTION) } while(sh4_int_bCpuRun); @@ -134,17 +141,33 @@ 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); + try { + u32 addr = next_pc; + next_pc += 2; + u32 op = IReadMem16(addr); + if (op != 0) + ExecuteOpcode(op); + } + catch (SH4ThrownException ex) { + ex.epc -= 2; + printf("Delay slot exception\n"); + throw ex; + } } void ExecuteDelayslot_RTE() { - sr.SetFull(ssr); + u32 oldsr = sr.GetFull(); - ExecuteDelayslot(); + try { + + sr.SetFull(ssr); + + ExecuteDelayslot(); + } + catch (SH4ThrownException ex) { + msgboxf("RTE Exception", MBX_ICONERROR); + } } //General update diff --git a/core/hw/sh4/interpr/sh4_opcodes.cpp b/core/hw/sh4/interpr/sh4_opcodes.cpp index e6323652c..4effeff56 100644 --- a/core/hw/sh4/interpr/sh4_opcodes.cpp +++ b/core/hw/sh4/interpr/sh4_opcodes.cpp @@ -277,24 +277,10 @@ sh4op(i0010_nnnn_mmmm_0100) //iNimp("mov.b ,@-"); 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 ,@- @@ -303,19 +289,10 @@ sh4op(i0010_nnnn_mmmm_0101) //iNimp("mov.w ,@-"); 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 ,@- @@ -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 ,@- !!!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,@-"); 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,@- 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,@- 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,@- @@ -389,8 +366,10 @@ sh4op(i0100_nnnn_0001_0011) { //iNimp("stc.l GBR,@-"); 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,@-"); 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,@-"); 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,@- sh4op(i0100_nnnn_0011_0010) { //iNimp("stc.l SGR,@-"); 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,@-"); 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,@- @@ -437,8 +424,10 @@ sh4op(i0100_nnnn_1mmm_0011) //iNimp("stc RM_BANK,@-"); 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 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 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; } @@ -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; } @@ -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 + } diff --git a/core/hw/sh4/modules/mmu.cpp b/core/hw/sh4/modules/mmu.cpp index 77a5e5b2d..f5e10c405 100644 --- a/core/hw/sh4/modules/mmu.cpp +++ b/core/hw/sh4/modules/mmu.cpp @@ -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,10 @@ 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) { - msgboxf("Can't raise exceptions yet", MBX_ICONERROR); +void RaiseException(u32 expEvnt, u32 callVect) { + SH4ThrownException ex = { next_pc - 2, expEvnt, callVect }; + throw ex; + //msgboxf("Can't raise exceptions yet", MBX_ICONERROR); } u32 mmu_error_TT; @@ -217,7 +219,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; } diff --git a/core/hw/sh4/modules/mmu.h b/core/hw/sh4/modules/mmu.h index 48d8ae7bd..36e5f7ead 100644 --- a/core/hw/sh4/modules/mmu.h +++ b/core/hw/sh4/modules/mmu.h @@ -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); diff --git a/core/hw/sh4/sh4_core.h b/core/hw/sh4/sh4_core.h index 1adfaeb9d..1b3931781 100644 --- a/core/hw/sh4/sh4_core.h +++ b/core/hw/sh4/sh4_core.h @@ -101,4 +101,10 @@ void SetFloatStatusReg(); bool Do_Interrupt(u32 intEvn); -bool Do_Exeption(u32 epc, u32 expEvn, u32 CallVect); \ No newline at end of file +bool Do_Exeption(u32 epc, u32 expEvn, u32 CallVect); + +struct SH4ThrownException { + u32 epc; + u32 expEvn; + u32 callVect; +}; \ No newline at end of file diff --git a/core/hw/sh4/sh4_interrupts.cpp b/core/hw/sh4/sh4_interrupts.cpp index 25b42a5e1..d874cebea 100644 --- a/core/hw/sh4/sh4_interrupts.cpp +++ b/core/hw/sh4/sh4_interrupts.cpp @@ -172,7 +172,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; } diff --git a/core/hw/sh4/sh4_mmr.cpp b/core/hw/sh4/sh4_mmr.cpp index 11972f7e3..c01b47120 100644 --- a/core/hw/sh4/sh4_mmr.cpp +++ b/core/hw/sh4/sh4_mmr.cpp @@ -353,25 +353,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