Search
lxdream.org :: lxdream/src/sh4/sh4core.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4core.c
changeset 27:1ef09a52cd1e
prev23:1ec3acd0594d
next30:89b30313d757
author nkeynes
date Sun Dec 25 01:28:39 2005 +0000 (14 years ago)
permissions -rw-r--r--
last change Refactor all the GUI bits out of the main directory (except for a couple
lingering temporarily in loader.c
Fix a few timeslice issues
file annotate diff log raw
1.1 --- a/src/sh4/sh4core.c Fri Dec 23 11:44:55 2005 +0000
1.2 +++ b/src/sh4/sh4core.c Sun Dec 25 01:28:39 2005 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: sh4core.c,v 1.9 2005-12-23 11:44:55 nkeynes Exp $
1.6 + * $Id: sh4core.c,v 1.10 2005-12-25 01:28:39 nkeynes Exp $
1.7 *
1.8 * SH4 emulation core, and parent module for all the SH4 peripheral
1.9 * modules.
1.10 @@ -26,6 +26,17 @@
1.11 #include "clock.h"
1.12 #include "intc.h"
1.13
1.14 +/* CPU-generated exception code/vector pairs */
1.15 +#define EXC_POWER_RESET 0x000 /* vector special */
1.16 +#define EXC_MANUAL_RESET 0x020
1.17 +#define EXC_SLOT_ILLEGAL 0x1A0
1.18 +#define EXC_ILLEGAL 0x180
1.19 +#define EXV_ILLEGAL 0x100
1.20 +#define EXC_TRAP 0x160
1.21 +#define EXV_TRAP 0x100
1.22 +#define EXC_FPDISABLE 0x800
1.23 +#define EXV_FPDISABLE 0x100
1.24 +
1.25 uint32_t sh4_freq = SH4_BASE_RATE;
1.26 uint32_t sh4_bus_freq = SH4_BASE_RATE;
1.27 uint32_t sh4_peripheral_freq = SH4_BASE_RATE / 2;
1.28 @@ -34,7 +45,7 @@
1.29
1.30 void sh4_init( void );
1.31 void sh4_reset( void );
1.32 -void sh4_run_slice( int );
1.33 +int sh4_run_slice( int );
1.34 void sh4_start( void );
1.35 void sh4_stop( void );
1.36 void sh4_save_state( FILE *f );
1.37 @@ -45,41 +56,65 @@
1.38 sh4_save_state, sh4_load_state };
1.39
1.40 struct sh4_registers sh4r;
1.41 -static int running = 0;
1.42
1.43 void sh4_init(void)
1.44 {
1.45 register_io_regions( mmio_list_sh4mmio );
1.46 mmu_init();
1.47 + sh4_reset();
1.48 }
1.49
1.50 void sh4_reset(void)
1.51 {
1.52 /* zero everything out, for the sake of having a consistent state. */
1.53 memset( &sh4r, 0, sizeof(sh4r) );
1.54 +
1.55 + /* Resume running if we were halted */
1.56 + sh4r.sh4_state = SH4_STATE_RUNNING;
1.57 +
1.58 sh4r.pc = 0xA0000000;
1.59 sh4r.new_pc= 0xA0000002;
1.60 sh4r.vbr = 0x00000000;
1.61 sh4r.fpscr = 0x00040001;
1.62 sh4r.sr = 0x700000F0;
1.63 +
1.64 + /* Mem reset will do this, but if we want to reset _just_ the SH4... */
1.65 + MMIO_WRITE( MMU, EXPEVT, EXC_POWER_RESET );
1.66 +
1.67 + /* Peripheral modules */
1.68 intc_reset();
1.69 }
1.70
1.71 -void sh4_run_slice( int microsecs )
1.72 +int sh4_run_slice( int microsecs )
1.73 {
1.74 - int count = sh4_freq * microsecs;
1.75 + int target = sh4r.icount + sh4_freq * microsecs;
1.76 + int start = sh4r.icount;
1.77 int i;
1.78
1.79 - for( i=0; i<count; i++ ) {
1.80 - sh4_execute_instruction();
1.81 + if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
1.82 + if( sh4r.int_pending != 0 )
1.83 + sh4r.sh4_state = SH4_STATE_RUNNING;;
1.84 }
1.85 - TMU_run_slice( microsecs );
1.86 - SCIF_run_slice( microsecs );
1.87 +
1.88 + while( sh4r.icount < target && sh4r.sh4_state == SH4_STATE_RUNNING ) {
1.89 + sh4r.icount++;
1.90 + if( !sh4_execute_instruction() )
1.91 + break;
1.92 + }
1.93 + if( target != sh4r.icount ) {
1.94 + /* Halted - compute time actually executed */
1.95 + microsecs = (sh4r.icount - start) / sh4_freq;
1.96 + }
1.97 + if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
1.98 + TMU_run_slice( microsecs );
1.99 + SCIF_run_slice( microsecs );
1.100 + }
1.101 + return microsecs;
1.102 }
1.103
1.104 void sh4_stop(void)
1.105 {
1.106 - running = 0;
1.107 +
1.108 }
1.109
1.110 void sh4_save_state( FILE *f )
1.111 @@ -94,14 +129,6 @@
1.112 return SCIF_load_state( f );
1.113 }
1.114
1.115 -void sh4_run(void)
1.116 -{
1.117 - running = 1;
1.118 - while( running ) {
1.119 - sh4_execute_instruction();
1.120 - }
1.121 -}
1.122 -
1.123 /********************** SH4 emulation core ****************************/
1.124
1.125 void sh4_set_pc( int pc )
1.126 @@ -115,40 +142,8 @@
1.127
1.128 }
1.129
1.130 -void sh4_runfor(uint32_t count)
1.131 -{
1.132 - running = 1;
1.133 - while( running && count--) {
1.134 - int pc = sh4r.pc;
1.135 - sh4_execute_instruction();
1.136 - /*
1.137 - if( sh4r.pc == 0x8C0C1636 ||
1.138 - sh4r.pc == 0x8C0C1634 ) {
1.139 - WARN( "Branching to %08X from %08X", sh4r.pc, pc );
1.140 - sh4_stop();
1.141 - }*/
1.142 - }
1.143 -}
1.144 -
1.145 -int sh4_isrunning(void)
1.146 -{
1.147 - return running;
1.148 -}
1.149 -
1.150 -void sh4_runto( uint32_t target_pc, uint32_t count )
1.151 -{
1.152 - running = 1;
1.153 - while( running && count--) {
1.154 - sh4_execute_instruction();
1.155 - if( sh4r.pc == target_pc ) {
1.156 - running = 0;
1.157 - break;
1.158 - }
1.159 - }
1.160 -}
1.161 -
1.162 -#define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_stop(); RAISE( EXC_ILLEGAL, EXV_ILLEGAL ); }while(0)
1.163 -#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_stop(); return; }while(0)
1.164 +#define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", sh4r.pc, ir ); RAISE( EXC_ILLEGAL, EXV_ILLEGAL ); }while(0)
1.165 +#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)
1.166
1.167 #define RAISE( x, v ) do{ \
1.168 if( sh4r.vbr == 0 ) { \
1.169 @@ -163,7 +158,7 @@
1.170 sh4r.new_pc = sh4r.pc + 2; \
1.171 sh4_load_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
1.172 } \
1.173 - return; } while(0)
1.174 + return TRUE; } while(0)
1.175
1.176 #define MEM_READ_BYTE( addr ) sh4_read_byte(addr)
1.177 #define MEM_READ_WORD( addr ) sh4_read_word(addr)
1.178 @@ -184,16 +179,6 @@
1.179
1.180 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
1.181
1.182 -#define EXC_POWER_RESET 0x000 /* vector special */
1.183 -#define EXC_MANUAL_RESET 0x020
1.184 -#define EXC_SLOT_ILLEGAL 0x1A0
1.185 -#define EXC_ILLEGAL 0x180
1.186 -#define EXV_ILLEGAL 0x100
1.187 -#define EXC_TRAP 0x160
1.188 -#define EXV_TRAP 0x100
1.189 -#define EXC_FPDISABLE 0x800
1.190 -#define EXV_FPDISABLE 0x100
1.191 -
1.192 #define CHECK( x, c, v ) if( !x ) RAISE( c, v )
1.193 #define CHECKPRIV() CHECK( IS_SH4_PRIVMODE(), EXC_ILLEGAL, EXV_ILLEGAL )
1.194 #define CHECKFPUEN() CHECK( IS_FPU_ENABLED(), EXC_FPDISABLE, EXV_FPDISABLE )
1.195 @@ -250,7 +235,7 @@
1.196 WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );
1.197 }
1.198
1.199 -void sh4_execute_instruction( void )
1.200 +gboolean sh4_execute_instruction( void )
1.201 {
1.202 int pc;
1.203 unsigned short ir;
1.204 @@ -331,14 +316,14 @@
1.205 sh4r.pr = sh4r.pc + 4;
1.206 sh4r.pc = sh4r.new_pc;
1.207 sh4r.new_pc = pc + 4 + RN(ir);
1.208 - return;
1.209 + return TRUE;
1.210 case 2: /* BRAF Rn */
1.211 CHECKDEST( pc + 4 + RN(ir) );
1.212 CHECKSLOTILLEGAL();
1.213 sh4r.in_delay_slot = 1;
1.214 sh4r.pc = sh4r.new_pc;
1.215 sh4r.new_pc = pc + 4 + RN(ir);
1.216 - return;
1.217 + return TRUE;
1.218 case 8: /* PREF [Rn] */
1.219 tmp = RN(ir);
1.220 if( (tmp & 0xFC000000) == 0xE0000000 ) {
1.221 @@ -442,10 +427,14 @@
1.222 sh4r.in_delay_slot = 1;
1.223 sh4r.pc = sh4r.new_pc;
1.224 sh4r.new_pc = sh4r.pr;
1.225 - return;
1.226 + return TRUE;
1.227 case 1: /* SLEEP */
1.228 - running = 0;
1.229 - break;
1.230 + if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
1.231 + sh4r.sh4_state = SH4_STATE_STANDBY;
1.232 + } else {
1.233 + sh4r.sh4_state = SH4_STATE_SLEEP;
1.234 + }
1.235 + return FALSE; /* Halt CPU */
1.236 case 2: /* RTE */
1.237 CHECKPRIV();
1.238 CHECKDEST( sh4r.spc );
1.239 @@ -455,7 +444,7 @@
1.240 sh4r.new_pc = sh4r.spc;
1.241 sh4_load_sr( sh4r.ssr );
1.242 WARN( "RTE => %08X", sh4r.new_pc );
1.243 - return;
1.244 + return TRUE;
1.245 default:UNDEF(ir);
1.246 }
1.247 break;
1.248 @@ -681,7 +670,7 @@
1.249 sh4r.pc = sh4r.new_pc;
1.250 sh4r.new_pc = RN(ir);
1.251 sh4r.pr = pc + 4;
1.252 - return;
1.253 + return TRUE;
1.254 case 0x0E: /* LDC Rn, SR */
1.255 CHECKPRIV();
1.256 sh4_load_sr( RN(ir) );
1.257 @@ -784,7 +773,7 @@
1.258 sh4r.in_delay_slot = 1;
1.259 sh4r.pc = sh4r.new_pc;
1.260 sh4r.new_pc = RN(ir);
1.261 - return;
1.262 + return TRUE;
1.263 case 0x2E: /* LDC Rn, VBR */
1.264 CHECKPRIV();
1.265 sh4r.vbr = RN(ir);
1.266 @@ -992,7 +981,7 @@
1.267 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
1.268 sh4r.pc += (PCDISP8(ir)<<1) + 4;
1.269 sh4r.new_pc = sh4r.pc + 2;
1.270 - return;
1.271 + return TRUE;
1.272 }
1.273 break;
1.274 case 11:/* BF disp8 */
1.275 @@ -1001,7 +990,7 @@
1.276 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
1.277 sh4r.pc += (PCDISP8(ir)<<1) + 4;
1.278 sh4r.new_pc = sh4r.pc + 2;
1.279 - return;
1.280 + return TRUE;
1.281 }
1.282 break;
1.283 case 13:/* BT/S disp8 */
1.284 @@ -1012,7 +1001,7 @@
1.285 sh4r.pc = sh4r.new_pc;
1.286 sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
1.287 sh4r.in_delay_slot = 1;
1.288 - return;
1.289 + return TRUE;
1.290 }
1.291 break;
1.292 case 15:/* BF/S disp8 */
1.293 @@ -1022,7 +1011,7 @@
1.294 sh4r.in_delay_slot = 1;
1.295 sh4r.pc = sh4r.new_pc;
1.296 sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
1.297 - return;
1.298 + return TRUE;
1.299 }
1.300 break;
1.301 default: UNDEF(ir);
1.302 @@ -1039,7 +1028,7 @@
1.303 sh4r.in_delay_slot = 1;
1.304 sh4r.pc = sh4r.new_pc;
1.305 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
1.306 - return;
1.307 + return TRUE;
1.308 case 11:/* 1011dddddddddddd */
1.309 /* BSR disp12 */
1.310 CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 )
1.311 @@ -1048,7 +1037,7 @@
1.312 sh4r.pr = pc + 4;
1.313 sh4r.pc = sh4r.new_pc;
1.314 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
1.315 - return;
1.316 + return TRUE;
1.317 case 12:/* 1100xxxxdddddddd */
1.318 switch( (ir&0x0F00)>>8 ) {
1.319 case 0: /* MOV.B R0, [GBR + disp8] */
.