Search
lxdream.org :: lxdream :: r157:fbe03268ad8a
lxdream 0.9.1
released Jun 29
Download Now
changeset157:fbe03268ad8a
parent156:3b93648a3b07
child158:a0a82246b44e
authornkeynes
dateThu Jun 15 10:27:10 2006 +0000 (14 years ago)
Add preliminary call-stack tracing ability
Fix INTC state save/load/reset
src/sh4/intc.c
src/sh4/sh4core.c
src/sh4/sh4core.h
1.1 --- a/src/sh4/intc.c Thu Jun 15 10:25:45 2006 +0000
1.2 +++ b/src/sh4/intc.c Thu Jun 15 10:27:10 2006 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: intc.c,v 1.5 2006-03-17 12:12:49 nkeynes Exp $
1.6 + * $Id: intc.c,v 1.6 2006-06-15 10:27:10 nkeynes Exp $
1.7 *
1.8 * SH4 onboard interrupt controller (INTC) implementation
1.9 *
1.10 @@ -21,36 +21,36 @@
1.11 #include "sh4core.h"
1.12 #include "intc.h"
1.13
1.14 -int priorities[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
1.15 -
1.16 struct intc_sources_t {
1.17 char *name;
1.18 uint32_t code;
1.19 - int priority;
1.20 -};
1.21 +} intc_sources[INT_NUM_SOURCES] = {
1.22 + { "IRQ0", 0x200 }, { "IRQ1", 0x220 }, { "IRQ2", 0x240 },
1.23 + { "IRQ3", 0x260 }, { "IRQ4", 0x280 }, { "IRQ5", 0x2A0 },
1.24 + { "IRQ6", 0x2C0 }, { "IRQ7", 0x2E0 }, { "IRQ8", 0x300 },
1.25 + { "IRQ9", 0x320 }, { "IRQ10",0x340 }, { "IRQ11",0x360 },
1.26 + { "IRQ12",0x380 }, { "IRQ13",0x3A0 }, { "IRQ14",0x3C0 },
1.27 + { "NMI", 0x1C0 }, { "H-UDI",0x600 }, { "GPIOI",0x620 },
1.28 + { "DMTE0",0x640 }, { "DMTE1",0x660 }, { "DMTE2",0x680 },
1.29 + { "DMTE3",0x6A0 }, { "DMTAE",0x6C0 }, { "TUNI0",0x400 },
1.30 + { "TUNI1",0x420 }, { "TUNI2",0x440 }, { "TICPI2",0x460 },
1.31 + { "RTC_ATI",0x480 },{ "RTC_PRI",0x4A0 },{ "RTC_CUI",0x4C0 },
1.32 + { "SCI_ERI",0x4E0 },{ "SCI_RXI",0x500 },{ "SCI_TXI",0x520 },
1.33 + { "SCI_TEI",0x540 },
1.34 + { "SCIF_ERI",0x700 },{ "SCIF_RXI",0x720, 0 },{ "SCIF_BRI",0x740 },
1.35 + { "SCIF_TXI",0x760 },
1.36 + { "WDT_ITI",0x560 },{ "RCMI",0x580 }, { "ROVI",0x5A0 } };
1.37
1.38 -#define PRIORITY(which) intc_sources[which].priority
1.39 +static int intc_default_priority[INT_NUM_SOURCES] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 16 };
1.40 +
1.41 +#define PRIORITY(which) intc_state.priority[which]
1.42 #define INTCODE(which) intc_sources[which].code
1.43
1.44 -static struct intc_sources_t intc_sources[] = {
1.45 - { "IRQ0", 0x200, 15 }, { "IRQ1", 0x220, 14 }, { "IRQ2", 0x240, 13 },
1.46 - { "IRQ3", 0x260, 12 }, { "IRQ4", 0x280, 11 }, { "IRQ5", 0x2A0, 10 },
1.47 - { "IRQ6", 0x2C0, 9 }, { "IRQ7", 0x2E0, 8 }, { "IRQ8", 0x300, 7 },
1.48 - { "IRQ9", 0x320, 6 }, { "IRQ10",0x340, 5 }, { "IRQ11",0x360, 4 },
1.49 - { "IRQ12",0x380, 3 }, { "IRQ13",0x3A0, 2 }, { "IRQ14",0x3C0, 1 },
1.50 - { "NMI", 0x1C0, 16 }, { "H-UDI",0x600, 0 }, { "GPIOI",0x620, 0 },
1.51 - { "DMTE0",0x640, 0 }, { "DMTE1",0x660, 0 }, { "DMTE2",0x680, 0 },
1.52 - { "DMTE3",0x6A0, 0 }, { "DMTAE",0x6C0, 0 }, { "TUNI0",0x400, 0 },
1.53 - { "TUNI1",0x420, 0 }, { "TUNI2",0x440, 0 }, { "TICPI2",0x460, 0 },
1.54 - { "RTC_ATI",0x480, 0 },{ "RTC_PRI",0x4A0, 0 },{ "RTC_CUI",0x4C0, 0 },
1.55 - { "SCI_ERI",0x4E0, 0 },{ "SCI_RXI",0x500, 0 },{ "SCI_TXI",0x520, 0 },
1.56 - { "SCI_TEI",0x540, 0 },
1.57 - { "SCIF_ERI",0x700, 0 },{ "SCIF_RXI",0x720, 0 },{ "SCIF_BRI",0x740, 0 },
1.58 - { "SCIF_TXI",0x760, 0 },
1.59 - { "WDT_ITI",0x560, 0 },{ "RCMI",0x580, 0 }, { "ROVI",0x5A0, 0 } };
1.60 -
1.61 -int intc_pending[INT_NUM_SOURCES];
1.62 -int intc_num_pending = 0;
1.63 +static struct intc_state {
1.64 + int num_pending;
1.65 + int pending[INT_NUM_SOURCES];
1.66 + int priority[INT_NUM_SOURCES];
1.67 +} intc_state;
1.68
1.69 void mmio_region_INTC_write( uint32_t reg, uint32_t val )
1.70 {
1.71 @@ -98,7 +98,30 @@
1.72 {
1.73 return MMIO_READ( INTC, reg );
1.74 }
1.75 -
1.76 +
1.77 +void INTC_reset()
1.78 +{
1.79 + int i;
1.80 +
1.81 + intc_state.num_pending = 0;
1.82 + for( i=0; i<INT_NUM_SOURCES; i++ )
1.83 + intc_state.priority[i] = intc_default_priority[i];
1.84 + sh4r.int_pending = 0;
1.85 +}
1.86 +
1.87 +
1.88 +void INTC_save_state( FILE *f )
1.89 +{
1.90 + fwrite( &intc_state, sizeof(intc_state), 1, f );
1.91 +}
1.92 +
1.93 +int INTC_load_state( FILE *f )
1.94 +{
1.95 + if( fread(&intc_state, sizeof(intc_state), 1, f) != 1 )
1.96 + return -1;
1.97 + return 0;
1.98 +}
1.99 +
1.100 /* We basically maintain a priority queue here, raise_interrupt adds an entry,
1.101 * accept_interrupt takes it off. At the moment this is does as a simple
1.102 * ordered array, on the basis that in practice there's unlikely to be more
1.103 @@ -113,34 +136,34 @@
1.104 pri = PRIORITY(which);
1.105 if( pri == 0 ) return; /* masked off */
1.106
1.107 - for( i=0; i<intc_num_pending; i++ ) {
1.108 - if( intc_pending[i] == which ) return; /* Don't queue more than once */
1.109 - if( PRIORITY(intc_pending[i]) > pri ||
1.110 - (PRIORITY(intc_pending[i]) == pri &&
1.111 - intc_pending[i] < which))
1.112 + for( i=0; i<intc_state.num_pending; i++ ) {
1.113 + if( intc_state.pending[i] == which ) return; /* Don't queue more than once */
1.114 + if( PRIORITY(intc_state.pending[i]) > pri ||
1.115 + (PRIORITY(intc_state.pending[i]) == pri &&
1.116 + intc_state.pending[i] < which))
1.117 break;
1.118 }
1.119 /* i == insertion point */
1.120 - for( j=intc_num_pending; j > i; j-- )
1.121 - intc_pending[j] = intc_pending[j-1];
1.122 - intc_pending[i] = which;
1.123 + for( j=intc_state.num_pending; j > i; j-- )
1.124 + intc_state.pending[j] = intc_state.pending[j-1];
1.125 + intc_state.pending[i] = which;
1.126
1.127 - if( i == intc_num_pending && (sh4r.sr&SR_BL)==0 && SH4_INTMASK() < pri )
1.128 + if( i == intc_state.num_pending && (sh4r.sr&SR_BL)==0 && SH4_INTMASK() < pri )
1.129 sh4r.int_pending = 1;
1.130
1.131 - intc_num_pending++;
1.132 + intc_state.num_pending++;
1.133 }
1.134
1.135 void intc_clear_interrupt( int which )
1.136 {
1.137 int i;
1.138 - for( i=intc_num_pending-1; i>=0; i-- ) {
1.139 - if( intc_pending[i] == which ) {
1.140 + for( i=intc_state.num_pending-1; i>=0; i-- ) {
1.141 + if( intc_state.pending[i] == which ) {
1.142 /* Shift array contents down */
1.143 - while( i < intc_num_pending-1 ) {
1.144 - intc_pending[i] = intc_pending[++i];
1.145 + while( i < intc_state.num_pending-1 ) {
1.146 + intc_state.pending[i] = intc_state.pending[++i];
1.147 }
1.148 - intc_num_pending--;
1.149 + intc_state.num_pending--;
1.150 intc_mask_changed();
1.151 break;
1.152 }
1.153 @@ -150,14 +173,14 @@
1.154
1.155 uint32_t intc_accept_interrupt( void )
1.156 {
1.157 - assert(intc_num_pending > 0);
1.158 - return INTCODE(intc_pending[intc_num_pending-1]);
1.159 + assert(intc_state.num_pending > 0);
1.160 + return INTCODE(intc_state.pending[intc_state.num_pending-1]);
1.161 }
1.162
1.163 void intc_mask_changed( void )
1.164 {
1.165 - if( intc_num_pending > 0 && (sh4r.sr&SR_BL)==0 &&
1.166 - SH4_INTMASK() < PRIORITY(intc_pending[intc_num_pending-1]) )
1.167 + if( intc_state.num_pending > 0 && (sh4r.sr&SR_BL)==0 &&
1.168 + SH4_INTMASK() < PRIORITY(intc_state.pending[intc_state.num_pending-1]) )
1.169 sh4r.int_pending = 1;
1.170 else sh4r.int_pending = 0;
1.171 }
1.172 @@ -167,9 +190,3 @@
1.173 {
1.174 return intc_sources[code].name;
1.175 }
1.176 -
1.177 -void intc_reset( void )
1.178 -{
1.179 - intc_num_pending = 0;
1.180 - sh4r.int_pending = 0;
1.181 -}
2.1 --- a/src/sh4/sh4core.c Thu Jun 15 10:25:45 2006 +0000
2.2 +++ b/src/sh4/sh4core.c Thu Jun 15 10:27:10 2006 +0000
2.3 @@ -1,5 +1,5 @@
2.4 /**
2.5 - * $Id: sh4core.c,v 1.26 2006-03-22 14:27:40 nkeynes Exp $
2.6 + * $Id: sh4core.c,v 1.27 2006-06-15 10:27:10 nkeynes Exp $
2.7 *
2.8 * SH4 emulation core, and parent module for all the SH4 peripheral
2.9 * modules.
2.10 @@ -27,6 +27,8 @@
2.11 #include "clock.h"
2.12 #include "syscall.h"
2.13
2.14 +#define SH4_CALLTRACE 1
2.15 +
2.16 #define MAX_INT 0x7FFFFFFF
2.17 #define MIN_INT 0x80000000
2.18 #define MAX_INTF 2147483647.0
2.19 @@ -84,7 +86,8 @@
2.20 MMIO_WRITE( MMU, EXPEVT, EXC_POWER_RESET );
2.21
2.22 /* Peripheral modules */
2.23 - intc_reset();
2.24 + INTC_reset();
2.25 + TMU_reset();
2.26 SCIF_reset();
2.27 }
2.28
2.29 @@ -178,6 +181,7 @@
2.30 void sh4_save_state( FILE *f )
2.31 {
2.32 fwrite( &sh4r, sizeof(sh4r), 1, f );
2.33 + INTC_save_state( f );
2.34 TMU_save_state( f );
2.35 SCIF_save_state( f );
2.36 }
2.37 @@ -185,6 +189,7 @@
2.38 int sh4_load_state( FILE * f )
2.39 {
2.40 fread( &sh4r, sizeof(sh4r), 1, f );
2.41 + INTC_load_state( f );
2.42 TMU_load_state( f );
2.43 return SCIF_load_state( f );
2.44 }
2.45 @@ -200,6 +205,53 @@
2.46 #define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)
2.47 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)
2.48
2.49 +#if(SH4_CALLTRACE == 1)
2.50 +#define MAX_CALLSTACK 32
2.51 +static struct call_stack {
2.52 + sh4addr_t call_addr;
2.53 + sh4addr_t target_addr;
2.54 + sh4addr_t stack_pointer;
2.55 +} call_stack[MAX_CALLSTACK];
2.56 +
2.57 +static int call_stack_depth = 0;
2.58 +int sh4_call_trace_on = 0;
2.59 +
2.60 +static inline trace_call( sh4addr_t source, sh4addr_t dest )
2.61 +{
2.62 + if( call_stack_depth < MAX_CALLSTACK ) {
2.63 + call_stack[call_stack_depth].call_addr = source;
2.64 + call_stack[call_stack_depth].target_addr = dest;
2.65 + call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
2.66 + }
2.67 + call_stack_depth++;
2.68 +}
2.69 +
2.70 +static inline trace_return( sh4addr_t source, sh4addr_t dest )
2.71 +{
2.72 + if( call_stack_depth > 0 ) {
2.73 + call_stack_depth--;
2.74 + }
2.75 +}
2.76 +
2.77 +void fprint_stack_trace( FILE *f )
2.78 +{
2.79 + int i = call_stack_depth -1;
2.80 + if( i >= MAX_CALLSTACK )
2.81 + i = MAX_CALLSTACK - 1;
2.82 + for( ; i >= 0; i-- ) {
2.83 + fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n",
2.84 + (call_stack_depth - i), call_stack[i].call_addr,
2.85 + call_stack[i].target_addr, call_stack[i].stack_pointer );
2.86 + }
2.87 +}
2.88 +
2.89 +#define TRACE_CALL( source, dest ) trace_call(source, dest)
2.90 +#define TRACE_RETURN( source, dest ) trace_return(source, dest)
2.91 +#else
2.92 +#define TRACE_CALL( dest, rts )
2.93 +#define TRACE_RETURN( source, dest )
2.94 +#endif
2.95 +
2.96 #define RAISE( x, v ) do{ \
2.97 if( sh4r.vbr == 0 ) { \
2.98 ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \
2.99 @@ -407,6 +459,7 @@
2.100 sh4r.pr = sh4r.pc + 4;
2.101 sh4r.pc = sh4r.new_pc;
2.102 sh4r.new_pc = pc + 4 + RN(ir);
2.103 + TRACE_CALL( pc, sh4r.new_pc );
2.104 return TRUE;
2.105 case 2: /* BRAF Rn */
2.106 CHECKDEST( pc + 4 + RN(ir) );
2.107 @@ -519,6 +572,7 @@
2.108 sh4r.in_delay_slot = 1;
2.109 sh4r.pc = sh4r.new_pc;
2.110 sh4r.new_pc = sh4r.pr;
2.111 + TRACE_RETURN( pc, sh4r.new_pc );
2.112 return TRUE;
2.113 case 1: /* SLEEP */
2.114 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
2.115 @@ -761,6 +815,7 @@
2.116 sh4r.pc = sh4r.new_pc;
2.117 sh4r.new_pc = RN(ir);
2.118 sh4r.pr = pc + 4;
2.119 + TRACE_CALL( pc, sh4r.new_pc );
2.120 return TRUE;
2.121 case 0x0E: /* LDC Rn, SR */
2.122 CHECKPRIV();
2.123 @@ -1128,6 +1183,7 @@
2.124 sh4r.pr = pc + 4;
2.125 sh4r.pc = sh4r.new_pc;
2.126 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
2.127 + TRACE_CALL( pc, sh4r.new_pc );
2.128 return TRUE;
2.129 case 12:/* 1100xxxxdddddddd */
2.130 switch( (ir&0x0F00)>>8 ) {
3.1 --- a/src/sh4/sh4core.h Thu Jun 15 10:25:45 2006 +0000
3.2 +++ b/src/sh4/sh4core.h Thu Jun 15 10:27:10 2006 +0000
3.3 @@ -1,5 +1,5 @@
3.4 /**
3.5 - * $Id: sh4core.h,v 1.12 2006-02-15 12:38:50 nkeynes Exp $
3.6 + * $Id: sh4core.h,v 1.13 2006-06-15 10:27:10 nkeynes Exp $
3.7 *
3.8 * This file defines the internal functions exported/used by the SH4 core,
3.9 * except for disassembly functions defined in sh4dasm.h
3.10 @@ -118,6 +118,9 @@
3.11 void SCIF_run_slice( uint32_t );
3.12 void SCIF_save_state( FILE *f );
3.13 int SCIF_load_state( FILE *f );
3.14 +void INTC_reset( void );
3.15 +void INTC_save_state( FILE *f );
3.16 +int INTC_load_state( FILE *f );
3.17
3.18 #define SIGNEXT4(n) ((((int32_t)(n))<<28)>>28)
3.19 #define SIGNEXT8(n) ((int32_t)((int8_t)(n)))
.