filename | src/sh4/sh4core.c |
changeset | 27:1ef09a52cd1e |
prev | 23:1ec3acd0594d |
next | 30:89b30313d757 |
author | nkeynes |
date | Sun Dec 25 01:28:39 2005 +0000 (15 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 +00001.2 +++ b/src/sh4/sh4core.c Sun Dec 25 01:28:39 2005 +00001.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 peripheral1.9 * modules.1.10 @@ -26,6 +26,17 @@1.11 #include "clock.h"1.12 #include "intc.h"1.14 +/* CPU-generated exception code/vector pairs */1.15 +#define EXC_POWER_RESET 0x000 /* vector special */1.16 +#define EXC_MANUAL_RESET 0x0201.17 +#define EXC_SLOT_ILLEGAL 0x1A01.18 +#define EXC_ILLEGAL 0x1801.19 +#define EXV_ILLEGAL 0x1001.20 +#define EXC_TRAP 0x1601.21 +#define EXV_TRAP 0x1001.22 +#define EXC_FPDISABLE 0x8001.23 +#define EXV_FPDISABLE 0x1001.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.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.40 struct sh4_registers sh4r;1.41 -static int running = 0;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.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.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.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.104 void sh4_stop(void)1.105 {1.106 - running = 0;1.107 +1.108 }1.110 void sh4_save_state( FILE *f )1.111 @@ -94,14 +129,6 @@1.112 return SCIF_load_state( f );1.113 }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.125 void sh4_set_pc( int pc )1.126 @@ -115,40 +142,8 @@1.128 }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.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.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.180 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)1.182 -#define EXC_POWER_RESET 0x000 /* vector special */1.183 -#define EXC_MANUAL_RESET 0x0201.184 -#define EXC_SLOT_ILLEGAL 0x1A01.185 -#define EXC_ILLEGAL 0x1801.186 -#define EXV_ILLEGAL 0x1001.187 -#define EXC_TRAP 0x1601.188 -#define EXV_TRAP 0x1001.189 -#define EXC_FPDISABLE 0x8001.190 -#define EXV_FPDISABLE 0x1001.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.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] */
.