Search
lxdream.org :: lxdream/src/sh4/sh4.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4.c
changeset 951:63483914846f
prev948:545c85cc56f1
next1067:d3c00ffccfcd
author nkeynes
date Wed Jan 07 05:45:15 2009 +0000 (15 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Tidy up exceptions+resets
Implement manual reset on general exception when SR.BL == 1
file annotate diff log raw
1.1 --- a/src/sh4/sh4.c Wed Jan 07 04:39:04 2009 +0000
1.2 +++ b/src/sh4/sh4.c Wed Jan 07 05:45:15 2009 +0000
1.3 @@ -36,7 +36,7 @@
1.4
1.5 void sh4_init( void );
1.6 void sh4_xlat_init( void );
1.7 -void sh4_reset( void );
1.8 +void sh4_poweron_reset( void );
1.9 void sh4_start( void );
1.10 void sh4_stop( void );
1.11 void sh4_save_state( FILE *f );
1.12 @@ -45,7 +45,7 @@
1.13 uint32_t sh4_run_slice( uint32_t );
1.14 uint32_t sh4_xlat_run_slice( uint32_t );
1.15
1.16 -struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_reset,
1.17 +struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_poweron_reset,
1.18 sh4_start, sh4_run_slice, sh4_stop,
1.19 sh4_save_state, sh4_load_state };
1.20
1.21 @@ -81,7 +81,7 @@
1.22 MMU_init();
1.23 TMU_init();
1.24 xlat_cache_init();
1.25 - sh4_reset();
1.26 + sh4_poweron_reset();
1.27 #ifdef ENABLE_SH4STATS
1.28 sh4_stats_reset();
1.29 #endif
1.30 @@ -92,15 +92,14 @@
1.31 sh4_starting = TRUE;
1.32 }
1.33
1.34 -void sh4_reset(void)
1.35 +void sh4_poweron_reset(void)
1.36 {
1.37 + /* zero everything out, for the sake of having a consistent state. */
1.38 + memset( &sh4r, 0, sizeof(sh4r) );
1.39 if( sh4_use_translator ) {
1.40 xlat_flush_cache();
1.41 }
1.42
1.43 - /* zero everything out, for the sake of having a consistent state. */
1.44 - memset( &sh4r, 0, sizeof(sh4r) );
1.45 -
1.46 /* Resume running if we were halted */
1.47 sh4r.sh4_state = SH4_STATE_RUNNING;
1.48
1.49 @@ -116,14 +115,10 @@
1.50 /* Peripheral modules */
1.51 CPG_reset();
1.52 INTC_reset();
1.53 - MMU_reset();
1.54 PMM_reset();
1.55 TMU_reset();
1.56 SCIF_reset();
1.57 -
1.58 -#ifdef ENABLE_SH4STATS
1.59 - sh4_stats_reset();
1.60 -#endif
1.61 + MMU_reset();
1.62 }
1.63
1.64 void sh4_stop(void)
1.65 @@ -354,79 +349,88 @@
1.66 return sh4r.sr;
1.67 }
1.68
1.69 +/**
1.70 + * Raise a CPU reset exception with the specified exception code.
1.71 + */
1.72 +void FASTCALL sh4_raise_reset( int code )
1.73 +{
1.74 + MMIO_WRITE(MMU,EXPEVT,code);
1.75 + sh4r.vbr = 0x00000000;
1.76 + sh4r.pc = 0xA0000000;
1.77 + sh4r.new_pc = sh4r.pc + 2;
1.78 + sh4r.in_delay_slot = 0;
1.79 + sh4_write_sr( (sh4r.sr|SR_MD|SR_BL|SR_RB|SR_IMASK)&(~SR_FD) );
1.80 +
1.81 + /* Peripheral manual reset (FIXME: incomplete) */
1.82 + INTC_reset();
1.83 + SCIF_reset();
1.84 + MMU_reset();
1.85 +}
1.86
1.87 -
1.88 -#define RAISE( x, v ) do{ \
1.89 - if( sh4r.vbr == 0 ) { \
1.90 - ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \
1.91 - sh4_core_exit(CORE_EXIT_HALT); return FALSE; \
1.92 - } else { \
1.93 - sh4r.spc = sh4r.pc; \
1.94 - sh4r.ssr = sh4_read_sr(); \
1.95 - sh4r.sgr = sh4r.r[15]; \
1.96 - MMIO_WRITE(MMU,EXPEVT,x); \
1.97 - sh4r.pc = sh4r.vbr + v; \
1.98 - sh4r.new_pc = sh4r.pc + 2; \
1.99 - sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
1.100 - sh4r.in_delay_slot = 0; \
1.101 - } \
1.102 - return TRUE; } while(0)
1.103 +void FASTCALL sh4_raise_tlb_multihit( sh4vma_t vpn )
1.104 +{
1.105 + MMIO_WRITE( MMU, TEA, vpn );
1.106 + MMIO_WRITE( MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00)) );
1.107 + sh4_raise_reset( EXC_TLB_MULTI_HIT );
1.108 +}
1.109
1.110 /**
1.111 * Raise a general CPU exception for the specified exception code.
1.112 * (NOT for TRAPA or TLB exceptions)
1.113 */
1.114 -gboolean FASTCALL sh4_raise_exception( int code )
1.115 +void FASTCALL sh4_raise_exception( int code )
1.116 {
1.117 - RAISE( code, EXV_EXCEPTION );
1.118 -}
1.119 -
1.120 -/**
1.121 - * Raise a CPU reset exception with the specified exception code.
1.122 - */
1.123 -gboolean FASTCALL sh4_raise_reset( int code )
1.124 -{
1.125 - // FIXME: reset modules as per "manual reset"
1.126 - sh4_reset();
1.127 - MMIO_WRITE(MMU,EXPEVT,code);
1.128 - sh4r.vbr = 0;
1.129 - sh4r.pc = 0xA0000000;
1.130 - sh4r.new_pc = sh4r.pc + 2;
1.131 - sh4_write_sr( (sh4r.sr|SR_MD|SR_BL|SR_RB|SR_IMASK)
1.132 - &(~SR_FD) );
1.133 - return TRUE;
1.134 -}
1.135 -
1.136 -gboolean FASTCALL sh4_raise_trap( int trap )
1.137 -{
1.138 - MMIO_WRITE( MMU, TRA, trap<<2 );
1.139 - RAISE( EXC_TRAP, EXV_EXCEPTION );
1.140 -}
1.141 -
1.142 -gboolean FASTCALL sh4_raise_slot_exception( int normal_code, int slot_code ) {
1.143 - if( sh4r.in_delay_slot ) {
1.144 - return sh4_raise_exception(slot_code);
1.145 + if( sh4r.sr & SR_BL ) {
1.146 + sh4_raise_reset( EXC_MANUAL_RESET );
1.147 } else {
1.148 - return sh4_raise_exception(normal_code);
1.149 + sh4r.spc = sh4r.pc;
1.150 + sh4r.ssr = sh4_read_sr();
1.151 + sh4r.sgr = sh4r.r[15];
1.152 + MMIO_WRITE(MMU,EXPEVT, code);
1.153 + sh4r.pc = sh4r.vbr + EXV_EXCEPTION;
1.154 + sh4r.new_pc = sh4r.pc + 2;
1.155 + sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
1.156 + sh4r.in_delay_slot = 0;
1.157 }
1.158 }
1.159
1.160 -gboolean FASTCALL sh4_raise_tlb_exception( int code )
1.161 +void FASTCALL sh4_raise_trap( int trap )
1.162 {
1.163 - RAISE( code, EXV_TLBMISS );
1.164 + MMIO_WRITE( MMU, TRA, trap<<2 );
1.165 + MMIO_WRITE( MMU, EXPEVT, EXC_TRAP );
1.166 + sh4r.spc = sh4r.pc;
1.167 + sh4r.ssr = sh4_read_sr();
1.168 + sh4r.sgr = sh4r.r[15];
1.169 + sh4r.pc = sh4r.vbr + EXV_EXCEPTION;
1.170 + sh4r.new_pc = sh4r.pc + 2;
1.171 + sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
1.172 + sh4r.in_delay_slot = 0;
1.173 +}
1.174 +
1.175 +void FASTCALL sh4_raise_tlb_exception( int code, sh4vma_t vpn )
1.176 +{
1.177 + MMIO_WRITE( MMU, TEA, vpn );
1.178 + MMIO_WRITE( MMU, PTEH, ((MMIO_READ(MMU, PTEH) & 0x000003FF) | (vpn&0xFFFFFC00)) );
1.179 + MMIO_WRITE( MMU, EXPEVT, code );
1.180 + sh4r.spc = sh4r.pc;
1.181 + sh4r.ssr = sh4_read_sr();
1.182 + sh4r.sgr = sh4r.r[15];
1.183 + sh4r.pc = sh4r.vbr + EXV_TLBMISS;
1.184 + sh4r.new_pc = sh4r.pc + 2;
1.185 + sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );
1.186 + sh4r.in_delay_slot = 0;
1.187 }
1.188
1.189 void FASTCALL sh4_accept_interrupt( void )
1.190 {
1.191 uint32_t code = intc_accept_interrupt();
1.192 + MMIO_WRITE( MMU, INTEVT, code );
1.193 sh4r.ssr = sh4_read_sr();
1.194 sh4r.spc = sh4r.pc;
1.195 sh4r.sgr = sh4r.r[15];
1.196 sh4_write_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
1.197 - MMIO_WRITE( MMU, INTEVT, code );
1.198 sh4r.pc = sh4r.vbr + 0x600;
1.199 sh4r.new_pc = sh4r.pc + 2;
1.200 - // WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );
1.201 }
1.202
1.203 void FASTCALL signsat48( void )
.