Search
lxdream.org :: lxdream :: r951:63483914846f
lxdream 0.9.1
released Jun 29
Download Now
changeset951:63483914846f lxdream-mem
parent950:cc1e88104360
child952:18e579840923
authornkeynes
dateWed Jan 07 05:45:15 2009 +0000 (15 years ago)
branchlxdream-mem
Tidy up exceptions+resets
Implement manual reset on general exception when SR.BL == 1
src/dreamcast.c
src/sh4/mmu.c
src/sh4/sh4.c
src/sh4/sh4core.h
src/sh4/sh4core.in
src/test/testsh4x86.c
1.1 --- a/src/dreamcast.c Wed Jan 07 04:54:32 2009 +0000
1.2 +++ b/src/dreamcast.c Wed Jan 07 05:45:15 2009 +0000
1.3 @@ -277,6 +277,7 @@
1.4 dreamcast_program_name = g_strdup(name);
1.5 dreamcast_entry_point = entry_point;
1.6 sh4_set_pc(entry_point);
1.7 + sh4_write_sr( sh4_read_sr() & (~SR_BL) ); /* Unmask interrupts */
1.8 bios_install();
1.9 dcload_install();
1.10 gui_update_state();
2.1 --- a/src/sh4/mmu.c Wed Jan 07 04:54:32 2009 +0000
2.2 +++ b/src/sh4/mmu.c Wed Jan 07 05:45:15 2009 +0000
2.3 @@ -27,18 +27,12 @@
2.4 #include "mem.h"
2.5 #include "mmu.h"
2.6
2.7 -#define RAISE_TLB_ERROR(code, vpn) \
2.8 - MMIO_WRITE(MMU, TEA, vpn); \
2.9 - MMIO_WRITE(MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00))); \
2.10 - sh4_raise_tlb_exception(code);
2.11 +#define RAISE_TLB_ERROR(code, vpn) sh4_raise_tlb_exception(code, vpn)
2.12 #define RAISE_MEM_ERROR(code, vpn) \
2.13 MMIO_WRITE(MMU, TEA, vpn); \
2.14 MMIO_WRITE(MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00))); \
2.15 sh4_raise_exception(code);
2.16 -#define RAISE_TLB_MULTIHIT_ERROR(vpn) \
2.17 - sh4_raise_reset(EXC_TLB_MULTI_HIT); \
2.18 - MMIO_WRITE(MMU, TEA, vpn); \
2.19 - MMIO_WRITE(MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00)));
2.20 +#define RAISE_TLB_MULTIHIT_ERROR(vpn) sh4_raise_tlb_multihit(vpn)
2.21
2.22 /* An entry is a 1K entry if it's one of the mmu_utlb_1k_pages entries */
2.23 #define IS_1K_PAGE_ENTRY(ent) ( ((uintptr_t)(((struct utlb_1k_entry *)ent) - &mmu_utlb_1k_pages[0])) < UTLB_ENTRY_COUNT )
2.24 @@ -1418,24 +1412,18 @@
2.25
2.26 static int32_t FASTCALL tlb_multi_hit_read( sh4addr_t addr, void *exc )
2.27 {
2.28 - MMIO_WRITE(MMU, TEA, addr);
2.29 - MMIO_WRITE(MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (addr&0xFFFFFC00)));
2.30 - sh4_raise_reset(EXC_TLB_MULTI_HIT);
2.31 + sh4_raise_tlb_multihit(addr);
2.32 EXCEPTION_EXIT();
2.33 }
2.34
2.35 static int32_t FASTCALL tlb_multi_hit_read_burst( unsigned char *dest, sh4addr_t addr, void *exc )
2.36 {
2.37 - MMIO_WRITE(MMU, TEA, addr);
2.38 - MMIO_WRITE(MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (addr&0xFFFFFC00)));
2.39 - sh4_raise_reset(EXC_TLB_MULTI_HIT);
2.40 + sh4_raise_tlb_multihit(addr);
2.41 EXCEPTION_EXIT();
2.42 }
2.43 static void FASTCALL tlb_multi_hit_write( sh4addr_t addr, uint32_t val, void *exc )
2.44 {
2.45 - MMIO_WRITE(MMU, TEA, addr);
2.46 - MMIO_WRITE(MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (addr&0xFFFFFC00)));
2.47 - sh4_raise_reset(EXC_TLB_MULTI_HIT);
2.48 + sh4_raise_tlb_multihit(addr);
2.49 EXCEPTION_EXIT();
2.50 }
2.51
3.1 --- a/src/sh4/sh4.c Wed Jan 07 04:54:32 2009 +0000
3.2 +++ b/src/sh4/sh4.c Wed Jan 07 05:45:15 2009 +0000
3.3 @@ -36,7 +36,7 @@
3.4
3.5 void sh4_init( void );
3.6 void sh4_xlat_init( void );
3.7 -void sh4_reset( void );
3.8 +void sh4_poweron_reset( void );
3.9 void sh4_start( void );
3.10 void sh4_stop( void );
3.11 void sh4_save_state( FILE *f );
3.12 @@ -45,7 +45,7 @@
3.13 uint32_t sh4_run_slice( uint32_t );
3.14 uint32_t sh4_xlat_run_slice( uint32_t );
3.15
3.16 -struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_reset,
3.17 +struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_poweron_reset,
3.18 sh4_start, sh4_run_slice, sh4_stop,
3.19 sh4_save_state, sh4_load_state };
3.20
3.21 @@ -81,7 +81,7 @@
3.22 MMU_init();
3.23 TMU_init();
3.24 xlat_cache_init();
3.25 - sh4_reset();
3.26 + sh4_poweron_reset();
3.27 #ifdef ENABLE_SH4STATS
3.28 sh4_stats_reset();
3.29 #endif
3.30 @@ -92,15 +92,14 @@
3.31 sh4_starting = TRUE;
3.32 }
3.33
3.34 -void sh4_reset(void)
3.35 +void sh4_poweron_reset(void)
3.36 {
3.37 + /* zero everything out, for the sake of having a consistent state. */
3.38 + memset( &sh4r, 0, sizeof(sh4r) );
3.39 if( sh4_use_translator ) {
3.40 xlat_flush_cache();
3.41 }
3.42
3.43 - /* zero everything out, for the sake of having a consistent state. */
3.44 - memset( &sh4r, 0, sizeof(sh4r) );
3.45 -
3.46 /* Resume running if we were halted */
3.47 sh4r.sh4_state = SH4_STATE_RUNNING;
3.48
3.49 @@ -116,14 +115,10 @@
3.50 /* Peripheral modules */
3.51 CPG_reset();
3.52 INTC_reset();
3.53 - MMU_reset();
3.54 PMM_reset();
3.55 TMU_reset();
3.56 SCIF_reset();
3.57 -
3.58 -#ifdef ENABLE_SH4STATS
3.59 - sh4_stats_reset();
3.60 -#endif
3.61 + MMU_reset();
3.62 }
3.63
3.64 void sh4_stop(void)
3.65 @@ -354,79 +349,88 @@
3.66 return sh4r.sr;
3.67 }
3.68
3.69 +/**
3.70 + * Raise a CPU reset exception with the specified exception code.
3.71 + */
3.72 +void FASTCALL sh4_raise_reset( int code )
3.73 +{
3.74 + MMIO_WRITE(MMU,EXPEVT,code);
3.75 + sh4r.vbr = 0x00000000;
3.76 + sh4r.pc = 0xA0000000;
3.77 + sh4r.new_pc = sh4r.pc + 2;
3.78 + sh4r.in_delay_slot = 0;
3.79 + sh4_write_sr( (sh4r.sr|SR_MD|SR_BL|SR_RB|SR_IMASK)&(~SR_FD) );
3.80 +
3.81 + /* Peripheral manual reset (FIXME: incomplete) */
3.82 + INTC_reset();
3.83 + SCIF_reset();
3.84 + MMU_reset();
3.85 +}
3.86
3.87 -
3.88 -#define RAISE( x, v ) do{ \
3.89 - if( sh4r.vbr == 0 ) { \
3.90 - ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \
3.91 - sh4_core_exit(CORE_EXIT_HALT); return FALSE; \
3.92 - } else { \
3.93 - sh4r.spc = sh4r.pc; \
3.94 - sh4r.ssr = sh4_read_sr(); \
3.95 - sh4r.sgr = sh4r.r[15]; \
3.96 - MMIO_WRITE(MMU,EXPEVT,x); \
3.97 - sh4r.pc = sh4r.vbr + v; \
3.98 - sh4r.new_pc = sh4r.pc + 2; \
3.99 - sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
3.100 - sh4r.in_delay_slot = 0; \
3.101 - } \
3.102 - return TRUE; } while(0)
3.103 +void FASTCALL sh4_raise_tlb_multihit( sh4vma_t vpn )
3.104 +{
3.105 + MMIO_WRITE( MMU, TEA, vpn );
3.106 + MMIO_WRITE( MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00)) );
3.107 + sh4_raise_reset( EXC_TLB_MULTI_HIT );
3.108 +}
3.109
3.110 /**
3.111 * Raise a general CPU exception for the specified exception code.
3.112 * (NOT for TRAPA or TLB exceptions)
3.113 */
3.114 -gboolean FASTCALL sh4_raise_exception( int code )
3.115 +void FASTCALL sh4_raise_exception( int code )
3.116 {
3.117 - RAISE( code, EXV_EXCEPTION );
3.118 -}
3.119 -
3.120 -/**
3.121 - * Raise a CPU reset exception with the specified exception code.
3.122 - */
3.123 -gboolean FASTCALL sh4_raise_reset( int code )
3.124 -{
3.125 - // FIXME: reset modules as per "manual reset"
3.126 - sh4_reset();
3.127 - MMIO_WRITE(MMU,EXPEVT,code);
3.128 - sh4r.vbr = 0;
3.129 - sh4r.pc = 0xA0000000;
3.130 - sh4r.new_pc = sh4r.pc + 2;
3.131 - sh4_write_sr( (sh4r.sr|SR_MD|SR_BL|SR_RB|SR_IMASK)
3.132 - &(~SR_FD) );
3.133 - return TRUE;
3.134 -}
3.135 -
3.136 -gboolean FASTCALL sh4_raise_trap( int trap )
3.137 -{
3.138 - MMIO_WRITE( MMU, TRA, trap<<2 );
3.139 - RAISE( EXC_TRAP, EXV_EXCEPTION );
3.140 -}
3.141 -
3.142 -gboolean FASTCALL sh4_raise_slot_exception( int normal_code, int slot_code ) {
3.143 - if( sh4r.in_delay_slot ) {
3.144 - return sh4_raise_exception(slot_code);
3.145 + if( sh4r.sr & SR_BL ) {
3.146 + sh4_raise_reset( EXC_MANUAL_RESET );
3.147 } else {
3.148 - return sh4_raise_exception(normal_code);
3.149 + sh4r.spc = sh4r.pc;
3.150 + sh4r.ssr = sh4_read_sr();
3.151 + sh4r.sgr = sh4r.r[15];
3.152 + MMIO_WRITE(MMU,EXPEVT, code);
3.153 + sh4r.pc = sh4r.vbr + EXV_EXCEPTION;
3.154 + sh4r.new_pc = sh4r.pc + 2;
3.155 + sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
3.156 + sh4r.in_delay_slot = 0;
3.157 }
3.158 }
3.159
3.160 -gboolean FASTCALL sh4_raise_tlb_exception( int code )
3.161 +void FASTCALL sh4_raise_trap( int trap )
3.162 {
3.163 - RAISE( code, EXV_TLBMISS );
3.164 + MMIO_WRITE( MMU, TRA, trap<<2 );
3.165 + MMIO_WRITE( MMU, EXPEVT, EXC_TRAP );
3.166 + sh4r.spc = sh4r.pc;
3.167 + sh4r.ssr = sh4_read_sr();
3.168 + sh4r.sgr = sh4r.r[15];
3.169 + sh4r.pc = sh4r.vbr + EXV_EXCEPTION;
3.170 + sh4r.new_pc = sh4r.pc + 2;
3.171 + sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
3.172 + sh4r.in_delay_slot = 0;
3.173 +}
3.174 +
3.175 +void FASTCALL sh4_raise_tlb_exception( int code, sh4vma_t vpn )
3.176 +{
3.177 + MMIO_WRITE( MMU, TEA, vpn );
3.178 + MMIO_WRITE( MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00)) );
3.179 + MMIO_WRITE( MMU, EXPEVT, code );
3.180 + sh4r.spc = sh4r.pc;
3.181 + sh4r.ssr = sh4_read_sr();
3.182 + sh4r.sgr = sh4r.r[15];
3.183 + sh4r.pc = sh4r.vbr + EXV_TLBMISS;
3.184 + sh4r.new_pc = sh4r.pc + 2;
3.185 + sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
3.186 + sh4r.in_delay_slot = 0;
3.187 }
3.188
3.189 void FASTCALL sh4_accept_interrupt( void )
3.190 {
3.191 uint32_t code = intc_accept_interrupt();
3.192 + MMIO_WRITE( MMU, INTEVT, code );
3.193 sh4r.ssr = sh4_read_sr();
3.194 sh4r.spc = sh4r.pc;
3.195 sh4r.sgr = sh4r.r[15];
3.196 sh4_write_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
3.197 - MMIO_WRITE( MMU, INTEVT, code );
3.198 sh4r.pc = sh4r.vbr + 0x600;
3.199 sh4r.new_pc = sh4r.pc + 2;
3.200 - // WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );
3.201 }
3.202
3.203 void FASTCALL signsat48( void )
4.1 --- a/src/sh4/sh4core.h Wed Jan 07 04:54:32 2009 +0000
4.2 +++ b/src/sh4/sh4core.h Wed Jan 07 05:45:15 2009 +0000
4.3 @@ -232,11 +232,11 @@
4.4 #define EXV_TLBMISS 0x400 /* TLB-miss exception vector */
4.5 #define EXV_INTERRUPT 0x600 /* External interrupt vector */
4.6
4.7 -gboolean FASTCALL sh4_raise_exception( int );
4.8 -gboolean FASTCALL sh4_raise_reset( int );
4.9 -gboolean FASTCALL sh4_raise_trap( int );
4.10 -gboolean FASTCALL sh4_raise_slot_exception( int, int );
4.11 -gboolean FASTCALL sh4_raise_tlb_exception( int );
4.12 +void FASTCALL sh4_raise_exception( int );
4.13 +void FASTCALL sh4_raise_reset( int );
4.14 +void FASTCALL sh4_raise_trap( int );
4.15 +void FASTCALL sh4_raise_tlb_exception( int, sh4vma_t );
4.16 +void FASTCALL sh4_raise_tlb_multihit( sh4vma_t );
4.17 void FASTCALL sh4_accept_interrupt( void );
4.18
4.19 /**
5.1 --- a/src/sh4/sh4core.in Wed Jan 07 04:54:32 2009 +0000
5.2 +++ b/src/sh4/sh4core.in Wed Jan 07 05:45:15 2009 +0000
5.3 @@ -149,17 +149,27 @@
5.4 #define TRACE_RETURN( source, dest )
5.5 #endif
5.6
5.7 -#define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )
5.8 -#define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
5.9 -#define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
5.10 -#define CHECKRALIGN64(addr) if( (addr)&0x07 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
5.11 -#define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
5.12 -#define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
5.13 -#define CHECKWALIGN64(addr) if( (addr)&0x07 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
5.14 +static gboolean FASTCALL sh4_raise_slot_exception( int normal_code, int slot_code ) {
5.15 + if( sh4r.in_delay_slot ) {
5.16 + sh4_raise_exception(slot_code);
5.17 + } else {
5.18 + sh4_raise_exception(normal_code);
5.19 + }
5.20 + return TRUE;
5.21 +}
5.22 +
5.23 +
5.24 +#define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) { return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL ); }
5.25 +#define CHECKRALIGN16(addr) if( (addr)&0x01 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
5.26 +#define CHECKRALIGN32(addr) if( (addr)&0x03 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
5.27 +#define CHECKRALIGN64(addr) if( (addr)&0x07 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
5.28 +#define CHECKWALIGN16(addr) if( (addr)&0x01 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
5.29 +#define CHECKWALIGN32(addr) if( (addr)&0x03 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
5.30 +#define CHECKWALIGN64(addr) if( (addr)&0x07 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
5.31
5.32 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
5.33 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }
5.34 -#define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)
5.35 +#define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) { sh4_raise_exception(EXC_SLOT_ILLEGAL); return TRUE; }
5.36
5.37 #define ADDRSPACE (IS_SH4_PRIVMODE() ? sh4_address_space : sh4_user_address_space)
5.38 #define SQADDRSPACE (IS_SH4_PRIVMODE() ? storequeue_address_space : storequeue_user_address_space)
6.1 --- a/src/test/testsh4x86.c Wed Jan 07 04:54:32 2009 +0000
6.2 +++ b/src/test/testsh4x86.c Wed Jan 07 05:45:15 2009 +0000
6.3 @@ -98,10 +98,11 @@
6.4 void syscall_invoke( uint32_t val ) { }
6.5 void dreamcast_stop() {}
6.6 void dreamcast_reset() {}
6.7 -gboolean FASTCALL sh4_raise_reset( int exc ) { return TRUE; }
6.8 -gboolean FASTCALL sh4_raise_exception( int exc ) { return TRUE; }
6.9 -gboolean FASTCALL sh4_raise_tlb_exception( int exc ) { return TRUE; }
6.10 -gboolean FASTCALL sh4_raise_trap( int exc ) { return TRUE; }
6.11 +void FASTCALL sh4_raise_reset( int exc ) { }
6.12 +void FASTCALL sh4_raise_exception( int exc ) { }
6.13 +void FASTCALL sh4_raise_tlb_exception( int exc, sh4vma_t vma ) { }
6.14 +void FASTCALL sh4_raise_tlb_multihit( sh4vma_t vma) { }
6.15 +void FASTCALL sh4_raise_trap( int exc ) { }
6.16 void FASTCALL sh4_flush_store_queue( sh4addr_t addr ) { }
6.17 void FASTCALL sh4_flush_store_queue_mmu( sh4addr_t addr, void *exc ) { }
6.18 uint32_t sh4_sleep_run_slice(uint32_t nanosecs) { return nanosecs; }
.