Search
lxdream.org :: lxdream/src/sh4/sh4.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4.c
changeset 401:f79327f39818
prev378:f10fbdd4e24b
next412:d58e4d69de16
author nkeynes
date Thu Sep 20 08:37:19 2007 +0000 (16 years ago)
permissions -rw-r--r--
last change Move support routines to sh4.c
file annotate diff log raw
1.1 --- a/src/sh4/sh4.c Wed Sep 12 09:20:38 2007 +0000
1.2 +++ b/src/sh4/sh4.c Thu Sep 20 08:37:19 2007 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: sh4.c,v 1.1 2007-09-12 09:20:38 nkeynes Exp $
1.6 + * $Id: sh4.c,v 1.2 2007-09-20 08:37:19 nkeynes Exp $
1.7 *
1.8 * SH4 parent module for all CPU modes and SH4 peripheral
1.9 * modules.
1.10 @@ -27,6 +27,10 @@
1.11 #include "clock.h"
1.12 #include "syscall.h"
1.13
1.14 +#define EXV_EXCEPTION 0x100 /* General exception vector */
1.15 +#define EXV_TLBMISS 0x400 /* TLB-miss exception vector */
1.16 +#define EXV_INTERRUPT 0x600 /* External interrupt vector */
1.17 +
1.18 void sh4_init( void );
1.19 void sh4_reset( void );
1.20 void sh4_start( void );
1.21 @@ -87,6 +91,7 @@
1.22 MMU_reset();
1.23 TMU_reset();
1.24 SCIF_reset();
1.25 + sh4_stats_reset();
1.26 }
1.27
1.28 void sh4_stop(void)
1.29 @@ -96,6 +101,12 @@
1.30
1.31 void sh4_save_state( FILE *f )
1.32 {
1.33 + if( sh4_module.run_time_slice == sh4_xlat_run_slice ) {
1.34 + /* If we were running with the translator, update new_pc and in_delay_slot */
1.35 + sh4r.new_pc = sh4r.pc+2;
1.36 + sh4r.in_delay_slot = FALSE;
1.37 + }
1.38 +
1.39 fwrite( &sh4r, sizeof(sh4r), 1, f );
1.40 MMU_save_state( f );
1.41 INTC_save_state( f );
1.42 @@ -148,3 +159,147 @@
1.43 return 0;
1.44 }
1.45
1.46 +void sh4_set_pc( int pc )
1.47 +{
1.48 + sh4r.pc = pc;
1.49 + sh4r.new_pc = pc+2;
1.50 +}
1.51 +
1.52 +
1.53 +/******************************* Support methods ***************************/
1.54 +
1.55 +static void sh4_switch_banks( )
1.56 +{
1.57 + uint32_t tmp[8];
1.58 +
1.59 + memcpy( tmp, sh4r.r, sizeof(uint32_t)*8 );
1.60 + memcpy( sh4r.r, sh4r.r_bank, sizeof(uint32_t)*8 );
1.61 + memcpy( sh4r.r_bank, tmp, sizeof(uint32_t)*8 );
1.62 +}
1.63 +
1.64 +void sh4_write_sr( uint32_t newval )
1.65 +{
1.66 + if( (newval ^ sh4r.sr) & SR_RB )
1.67 + sh4_switch_banks();
1.68 + sh4r.sr = newval;
1.69 + sh4r.t = (newval&SR_T) ? 1 : 0;
1.70 + sh4r.s = (newval&SR_S) ? 1 : 0;
1.71 + sh4r.m = (newval&SR_M) ? 1 : 0;
1.72 + sh4r.q = (newval&SR_Q) ? 1 : 0;
1.73 + intc_mask_changed();
1.74 +}
1.75 +
1.76 +uint32_t sh4_read_sr( void )
1.77 +{
1.78 + /* synchronize sh4r.sr with the various bitflags */
1.79 + sh4r.sr &= SR_MQSTMASK;
1.80 + if( sh4r.t ) sh4r.sr |= SR_T;
1.81 + if( sh4r.s ) sh4r.sr |= SR_S;
1.82 + if( sh4r.m ) sh4r.sr |= SR_M;
1.83 + if( sh4r.q ) sh4r.sr |= SR_Q;
1.84 + return sh4r.sr;
1.85 +}
1.86 +
1.87 +
1.88 +
1.89 +#define RAISE( x, v ) do{ \
1.90 + if( sh4r.vbr == 0 ) { \
1.91 + ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \
1.92 + dreamcast_stop(); return FALSE; \
1.93 + } else { \
1.94 + sh4r.spc = sh4r.pc; \
1.95 + sh4r.ssr = sh4_read_sr(); \
1.96 + sh4r.sgr = sh4r.r[15]; \
1.97 + MMIO_WRITE(MMU,EXPEVT,x); \
1.98 + sh4r.pc = sh4r.vbr + v; \
1.99 + sh4r.new_pc = sh4r.pc + 2; \
1.100 + sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
1.101 + if( sh4r.in_delay_slot ) { \
1.102 + sh4r.in_delay_slot = 0; \
1.103 + sh4r.spc -= 2; \
1.104 + } \
1.105 + } \
1.106 + return TRUE; } while(0)
1.107 +
1.108 +/**
1.109 + * Raise a general CPU exception for the specified exception code.
1.110 + * (NOT for TRAPA or TLB exceptions)
1.111 + */
1.112 +gboolean sh4_raise_exception( int code )
1.113 +{
1.114 + RAISE( code, EXV_EXCEPTION );
1.115 +}
1.116 +
1.117 +gboolean sh4_raise_trap( int trap )
1.118 +{
1.119 + MMIO_WRITE( MMU, TRA, trap<<2 );
1.120 + return sh4_raise_exception( EXC_TRAP );
1.121 +}
1.122 +
1.123 +gboolean sh4_raise_slot_exception( int normal_code, int slot_code ) {
1.124 + if( sh4r.in_delay_slot ) {
1.125 + return sh4_raise_exception(slot_code);
1.126 + } else {
1.127 + return sh4_raise_exception(normal_code);
1.128 + }
1.129 +}
1.130 +
1.131 +gboolean sh4_raise_tlb_exception( int code )
1.132 +{
1.133 + RAISE( code, EXV_TLBMISS );
1.134 +}
1.135 +
1.136 +void sh4_accept_interrupt( void )
1.137 +{
1.138 + uint32_t code = intc_accept_interrupt();
1.139 + sh4r.ssr = sh4_read_sr();
1.140 + sh4r.spc = sh4r.pc;
1.141 + sh4r.sgr = sh4r.r[15];
1.142 + sh4_write_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
1.143 + MMIO_WRITE( MMU, INTEVT, code );
1.144 + sh4r.pc = sh4r.vbr + 0x600;
1.145 + sh4r.new_pc = sh4r.pc + 2;
1.146 + // WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );
1.147 +}
1.148 +
1.149 +void signsat48( void )
1.150 +{
1.151 + if( ((int64_t)sh4r.mac) < (int64_t)0xFFFF800000000000LL )
1.152 + sh4r.mac = 0xFFFF800000000000LL;
1.153 + else if( ((int64_t)sh4r.mac) > (int64_t)0x00007FFFFFFFFFFFLL )
1.154 + sh4r.mac = 0x00007FFFFFFFFFFFLL;
1.155 +}
1.156 +
1.157 +void sh4_fsca( uint32_t anglei, float *fr )
1.158 +{
1.159 + float angle = (((float)(anglei&0xFFFF))/65536.0) * 2 * M_PI;
1.160 + *fr++ = cosf(angle);
1.161 + *fr = sinf(angle);
1.162 +}
1.163 +
1.164 +void sh4_sleep(void)
1.165 +{
1.166 + if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
1.167 + sh4r.sh4_state = SH4_STATE_STANDBY;
1.168 + } else {
1.169 + sh4r.sh4_state = SH4_STATE_SLEEP;
1.170 + }
1.171 +}
1.172 +
1.173 +/**
1.174 + * Compute the matrix tranform of fv given the matrix xf.
1.175 + * Both fv and xf are word-swapped as per the sh4r.fr banks
1.176 + */
1.177 +void sh4_ftrv( float *target, float *xf )
1.178 +{
1.179 + float fv[4] = { target[1], target[0], target[3], target[2] };
1.180 + target[1] = xf[1] * fv[0] + xf[5]*fv[1] +
1.181 + xf[9]*fv[2] + xf[13]*fv[3];
1.182 + target[0] = xf[0] * fv[0] + xf[4]*fv[1] +
1.183 + xf[8]*fv[2] + xf[12]*fv[3];
1.184 + target[3] = xf[3] * fv[0] + xf[7]*fv[1] +
1.185 + xf[11]*fv[2] + xf[15]*fv[3];
1.186 + target[2] = xf[2] * fv[0] + xf[6]*fv[1] +
1.187 + xf[10]*fv[2] + xf[14]*fv[3];
1.188 +}
1.189 +
.