Search
lxdream.org :: lxdream :: r617:476a717a54f3
lxdream 0.9.1
released Jun 29
Download Now
changeset617:476a717a54f3
parent616:527ab167712b
child618:3ade50e8603c
authornkeynes
dateTue Jan 29 10:39:56 2008 +0000 (12 years ago)
Start getting SLEEP into order
src/sh4/sh4.c
src/sh4/sh4core.c
src/sh4/sh4core.h
src/sh4/sh4core.in
src/sh4/sh4trans.c
src/sh4/sh4trans.h
src/sh4/xltcache.c
1.1 --- a/src/sh4/sh4.c Tue Jan 29 10:38:34 2008 +0000
1.2 +++ b/src/sh4/sh4.c Tue Jan 29 10:39:56 2008 +0000
1.3 @@ -19,6 +19,7 @@
1.4
1.5 #define MODULE sh4_module
1.6 #include <math.h>
1.7 +#include <assert.h>
1.8 #include "dream.h"
1.9 #include "dreamcast.h"
1.10 #include "sh4/sh4core.h"
1.11 @@ -26,6 +27,7 @@
1.12 #include "sh4/intc.h"
1.13 #include "sh4/xltcache.h"
1.14 #include "sh4/sh4stat.h"
1.15 +#include "sh4/sh4trans.h"
1.16 #include "mem.h"
1.17 #include "clock.h"
1.18 #include "syscall.h"
1.19 @@ -332,16 +334,80 @@
1.20 *fr = sinf(angle);
1.21 }
1.22
1.23 +/**
1.24 + * Enter sleep mode (eg by executing a SLEEP instruction).
1.25 + * Sets sh4_state appropriately and ensures any stopping peripheral modules
1.26 + * are up to date.
1.27 + */
1.28 void sh4_sleep(void)
1.29 {
1.30 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
1.31 sh4r.sh4_state = SH4_STATE_STANDBY;
1.32 + /* Bring all running peripheral modules up to date, and then halt them. */
1.33 + TMU_run_slice( sh4r.slice_cycle );
1.34 + SCIF_run_slice( sh4r.slice_cycle );
1.35 } else {
1.36 - sh4r.sh4_state = SH4_STATE_SLEEP;
1.37 + if( MMIO_READ( CPG, STBCR2 ) & 0x80 ) {
1.38 + sh4r.sh4_state = SH4_STATE_DEEP_SLEEP;
1.39 + /* Halt DMAC but other peripherals still running */
1.40 +
1.41 + } else {
1.42 + sh4r.sh4_state = SH4_STATE_SLEEP;
1.43 + }
1.44 + }
1.45 + if( sh4_xlat_is_running() ) {
1.46 + sh4_translate_exit( XLAT_EXIT_SLEEP );
1.47 }
1.48 }
1.49
1.50 /**
1.51 + * Wakeup following sleep mode (IRQ or reset). Sets state back to running,
1.52 + * and restarts any peripheral devices that were stopped.
1.53 + */
1.54 +void sh4_wakeup(void)
1.55 +{
1.56 + switch( sh4r.sh4_state ) {
1.57 + case SH4_STATE_STANDBY:
1.58 + break;
1.59 + case SH4_STATE_DEEP_SLEEP:
1.60 + break;
1.61 + case SH4_STATE_SLEEP:
1.62 + break;
1.63 + }
1.64 + sh4r.sh4_state = SH4_STATE_RUNNING;
1.65 +}
1.66 +
1.67 +/**
1.68 + * Run a time slice (or portion of a timeslice) while the SH4 is sleeping.
1.69 + * Returns when either the SH4 wakes up (interrupt received) or the end of
1.70 + * the slice is reached. Updates sh4.slice_cycle with the exit time and
1.71 + * returns the same value.
1.72 + */
1.73 +uint32_t sh4_sleep_run_slice( uint32_t nanosecs )
1.74 +{
1.75 + int sleep_state = sh4r.sh4_state;
1.76 + assert( sleep_state != SH4_STATE_RUNNING );
1.77 + while( sh4r.event_pending < nanosecs ) {
1.78 + sh4r.slice_cycle = sh4r.event_pending;
1.79 + if( sh4r.event_types & PENDING_EVENT ) {
1.80 + event_execute();
1.81 + }
1.82 + if( sh4r.event_types & PENDING_IRQ ) {
1.83 + sh4_wakeup();
1.84 + nanosecs = sh4r.event_pending;
1.85 + break;
1.86 + }
1.87 + }
1.88 + sh4r.slice_cycle = nanosecs;
1.89 + if( sleep_state != SH4_STATE_STANDBY ) {
1.90 + TMU_run_slice( nanosecs );
1.91 + SCIF_run_slice( nanosecs );
1.92 + }
1.93 + return sh4r.slice_cycle;
1.94 +}
1.95 +
1.96 +
1.97 +/**
1.98 * Compute the matrix tranform of fv given the matrix xf.
1.99 * Both fv and xf are word-swapped as per the sh4r.fr banks
1.100 */
2.1 --- a/src/sh4/sh4core.c Tue Jan 29 10:38:34 2008 +0000
2.2 +++ b/src/sh4/sh4core.c Tue Jan 29 10:39:56 2008 +0000
2.3 @@ -45,10 +45,7 @@
2.4 sh4r.slice_cycle = 0;
2.5
2.6 if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
2.7 - if( sh4r.event_pending < nanosecs ) {
2.8 - sh4r.sh4_state = SH4_STATE_RUNNING;
2.9 - sh4r.slice_cycle = sh4r.event_pending;
2.10 - }
2.11 + sh4_sleep_run_slice(nanosecs);
2.12 }
2.13
2.14 if( sh4_breakpoint_count == 0 ) {
3.1 --- a/src/sh4/sh4core.h Tue Jan 29 10:38:34 2008 +0000
3.2 +++ b/src/sh4/sh4core.h Tue Jan 29 10:39:56 2008 +0000
3.3 @@ -77,6 +77,9 @@
3.4 void sh4_reset( void );
3.5 void sh4_run( void );
3.6 void sh4_stop( void );
3.7 +uint32_t sh4_run_slice( uint32_t nanos ); // Run single timeslice using emulator
3.8 +uint32_t sh4_xlat_run_slice( uint32_t nanos ); // Run single timeslice using translator
3.9 +uint32_t sh4_sleep_run_slice( uint32_t nanos ); // Run single timeslice while the CPU is asleep
3.10
3.11 /* SH4 peripheral module functions */
3.12 void CPG_reset( void );
4.1 --- a/src/sh4/sh4core.in Tue Jan 29 10:38:34 2008 +0000
4.2 +++ b/src/sh4/sh4core.in Tue Jan 29 10:39:56 2008 +0000
4.3 @@ -45,10 +45,7 @@
4.4 sh4r.slice_cycle = 0;
4.5
4.6 if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
4.7 - if( sh4r.event_pending < nanosecs ) {
4.8 - sh4r.sh4_state = SH4_STATE_RUNNING;
4.9 - sh4r.slice_cycle = sh4r.event_pending;
4.10 - }
4.11 + sh4_sleep_run_slice(nanosecs);
4.12 }
4.13
4.14 if( sh4_breakpoint_count == 0 ) {
5.1 --- a/src/sh4/sh4trans.c Tue Jan 29 10:38:34 2008 +0000
5.2 +++ b/src/sh4/sh4trans.c Tue Jan 29 10:39:56 2008 +0000
5.3 @@ -42,10 +42,7 @@
5.4 sh4r.slice_cycle = 0;
5.5
5.6 if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
5.7 - if( sh4r.event_pending < nanosecs ) {
5.8 - sh4r.sh4_state = SH4_STATE_RUNNING;
5.9 - sh4r.slice_cycle = sh4r.event_pending;
5.10 - }
5.11 + sh4_sleep_run_slice(nanosecs);
5.12 }
5.13
5.14 switch( setjmp(xlat_jmp_buf) ) {
5.15 @@ -62,6 +59,9 @@
5.16 case XLAT_EXIT_SYSRESET:
5.17 dreamcast_reset();
5.18 break;
5.19 + case XLAT_EXIT_SLEEP:
5.20 + sh4_sleep_run_slice(nanosecs);
5.21 + break;
5.22 }
5.23
5.24 xlat_running = TRUE;
5.25 @@ -162,6 +162,10 @@
5.26 }
5.27 } while( !done );
5.28 pc += (done - 2);
5.29 +
5.30 + // Add end-of-block recovery for post-instruction checks
5.31 + sh4_translate_add_recovery( (pc - start)>>1 );
5.32 +
5.33 int epilogue_size = sh4_translate_end_block_size();
5.34 uint32_t recovery_size = sizeof(struct xlat_recovery_record)*xlat_recovery_posn;
5.35 uint32_t finalsize = xlat_output - xlat_current_block->code + epilogue_size + recovery_size;
6.1 --- a/src/sh4/sh4trans.h Tue Jan 29 10:38:34 2008 +0000
6.2 +++ b/src/sh4/sh4trans.h Tue Jan 29 10:39:56 2008 +0000
6.3 @@ -57,6 +57,11 @@
6.4 #define XLAT_EXIT_SYSRESET 4
6.5
6.6 /**
6.7 + * Translation flag - exit the current block and continue after the next IRQ.
6.8 + */
6.9 +#define XLAT_EXIT_SLEEP 5
6.10 +
6.11 +/**
6.12 */
6.13 uint32_t sh4_xlat_run_slice( uint32_t nanosecs );
6.14
7.1 --- a/src/sh4/xltcache.c Tue Jan 29 10:38:34 2008 +0000
7.2 +++ b/src/sh4/xltcache.c Tue Jan 29 10:39:56 2008 +0000
7.3 @@ -217,7 +217,7 @@
7.4 xlat_recovery_record_t records = (xlat_recovery_record_t)(&block->code[block->recover_table_offset]);
7.5 uint32_t posn;
7.6 if( recover_after ) {
7.7 - if( records[count-1].xlat_offset <= pc_offset ) {
7.8 + if( records[count-1].xlat_offset < pc_offset ) {
7.9 return NULL;
7.10 }
7.11 for( posn=count-1; posn > 0; posn-- ) {
.