revision 246:98054d036a24
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 246:98054d036a24 |
parent | 245:a1d0655a88d3 |
child | 247:b356d391d02a |
author | nkeynes |
date | Tue Dec 19 09:54:03 2006 +0000 (16 years ago) |
Add slot-illegal instruction checking
![]() | src/sh4/sh4core.c | view | annotate | diff | log | |
![]() | src/sh4/sh4core.h | view | annotate | diff | log |
1.1 --- a/src/sh4/sh4core.c Tue Dec 19 09:52:56 2006 +00001.2 +++ b/src/sh4/sh4core.c Tue Dec 19 09:54:03 2006 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: sh4core.c,v 1.34 2006-12-12 09:20:25 nkeynes Exp $1.6 + * $Id: sh4core.c,v 1.35 2006-12-19 09:54:03 nkeynes Exp $1.7 *1.8 * SH4 emulation core, and parent module for all the SH4 peripheral1.9 * modules.1.10 @@ -41,11 +41,13 @@1.11 #define EXC_WRITE_ADDR_ERR 0x1001.12 #define EXC_SLOT_ILLEGAL 0x1A01.13 #define EXC_ILLEGAL 0x1801.14 -#define EXV_ILLEGAL 0x1001.15 #define EXC_TRAP 0x1601.16 -#define EXV_TRAP 0x1001.17 #define EXC_FPDISABLE 0x8001.18 -#define EXV_FPDISABLE 0x1001.19 +#define EXC_SLOT_FPDISABLE 0x8201.20 +1.21 +#define EXV_EXCEPTION 0x100 /* General exception vector */1.22 +#define EXV_TLBMISS 0x400 /* TLB-miss exception vector */1.23 +#define EXV_INTERRUPT 0x600 /* External interrupt vector */1.25 /********************** SH4 Module Definition ****************************/1.27 @@ -215,7 +217,7 @@1.28 sh4r.new_pc = pc+2;1.29 }1.31 -#define UNDEF(ir) if( sh4r.in_delay_slot ) { RAISE( EXC_SLOT_ILLEGAL, EXV_ILLEGAL, -2 ); } else { RAISE( EXC_ILLEGAL, EXV_ILLEGAL, 0 ); }1.32 +#define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)1.33 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)1.35 #if(SH4_CALLTRACE == 1)1.36 @@ -265,23 +267,24 @@1.37 #define TRACE_RETURN( source, dest )1.38 #endif1.40 -#define RAISE( x, v, pcadj ) do{ \1.41 +#define RAISE( x, v ) do{ \1.42 if( sh4r.vbr == 0 ) { \1.43 ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \1.44 dreamcast_stop(); return FALSE; \1.45 } else { \1.46 - sh4r.spc = sh4r.pc + pcadj; \1.47 + sh4r.spc = sh4r.pc; \1.48 sh4r.ssr = sh4_read_sr(); \1.49 sh4r.sgr = sh4r.r[15]; \1.50 MMIO_WRITE(MMU,EXPEVT,x); \1.51 sh4r.pc = sh4r.vbr + v; \1.52 sh4r.new_pc = sh4r.pc + 2; \1.53 sh4_load_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \1.54 - sh4r.in_delay_slot = 0; \1.55 + if( sh4r.in_delay_slot ) { \1.56 + sh4r.in_delay_slot = 0; \1.57 + sh4r.spc -= 2; \1.58 + } \1.59 } \1.60 return TRUE; } while(0)1.61 -#define RAISE_SLOTILLEGAL() RAISE( EXC_SLOT_ILLEGAL, EXV_ILLEGAL, -2 )1.62 -#define RAISE_ILLEGAL() RAISE( EXC_ILLEGAL, EXV_ILLEGAL, 0 )1.64 #define MEM_READ_BYTE( addr ) sh4_read_byte(addr)1.65 #define MEM_READ_WORD( addr ) sh4_read_word(addr)1.66 @@ -293,19 +296,17 @@1.67 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)1.69 #define MEM_FP_READ( addr, reg ) sh4_read_float( addr, reg );1.70 -1.71 #define MEM_FP_WRITE( addr, reg ) sh4_write_float( addr, reg );1.73 -#define CHECK( x, c, v ) if( !x ) RAISE( c, v, 0 )1.74 -#define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) { if( sh4r.in_delay_slot ) { RAISE_SLOTILLEGAL(); } else { RAISE_ILLEGAL(); } }1.75 -#define CHECKRALIGN16(addr) if( (addr)&0x01 ) RAISE( EXC_READ_ADDR_ERR, EXV_TRAP, 0 )1.76 -#define CHECKRALIGN32(addr) if( (addr)&0x03 ) RAISE( EXC_READ_ADDR_ERR, EXV_TRAP, 0 )1.77 -#define CHECKWALIGN16(addr) if( (addr)&0x01 ) RAISE( EXC_WRITE_ADDR_ERR, EXV_TRAP, 0 )1.78 -#define CHECKWALIGN32(addr) if( (addr)&0x03 ) RAISE( EXC_WRITE_ADDR_ERR, EXV_TRAP, 0 )1.79 +#define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )1.80 +#define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_READ_ADDR_ERR )1.81 +#define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_READ_ADDR_ERR )1.82 +#define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_WRITE_ADDR_ERR )1.83 +#define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_WRITE_ADDR_ERR )1.85 -#define CHECKFPUEN() CHECK( IS_FPU_ENABLED(), EXC_FPDISABLE, EXV_FPDISABLE )1.86 +#define CHECKFPUEN() if( !IS_FPU_ENABLED() ) return sh4_raise_slot_exception( EXC_FPDISABLE, EXC_SLOT_FPDISABLE )1.87 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); dreamcast_stop(); return FALSE; }1.88 -#define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) { RAISE(EXC_SLOT_ILLEGAL,EXV_ILLEGAL, -2); }1.89 +#define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)1.91 static void sh4_switch_banks( )1.92 {1.93 @@ -368,10 +369,27 @@1.94 if( sh4r.q ) sh4r.sr |= SR_Q;1.95 return sh4r.sr;1.96 }1.97 -/* function for external use */1.98 -void sh4_raise_exception( int code, int vector )1.99 +1.100 +/**1.101 + * Raise a general CPU exception for the specified exception code.1.102 + * (NOT for TRAPA or TLB exceptions)1.103 + */1.104 +gboolean sh4_raise_exception( int code )1.105 {1.106 - RAISE(code, vector, 0);1.107 + RAISE( code, EXV_EXCEPTION );1.108 +}1.109 +1.110 +gboolean sh4_raise_slot_exception( int normal_code, int slot_code ) {1.111 + if( sh4r.in_delay_slot ) {1.112 + return sh4_raise_exception(slot_code);1.113 + } else {1.114 + return sh4_raise_exception(normal_code);1.115 + }1.116 +}1.117 +1.118 +gboolean sh4_raise_tlb_exception( int code )1.119 +{1.120 + RAISE( code, EXV_TLBMISS );1.121 }1.123 static void sh4_accept_interrupt( void )1.124 @@ -1214,7 +1232,7 @@1.125 sh4r.t = ( R0 == IMM8(ir) ? 1 : 0 );1.126 break;1.127 case 9: /* BT disp8 */1.128 - CHECKSLOTILLEGAL()1.129 + CHECKSLOTILLEGAL();1.130 if( sh4r.t ) {1.131 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )1.132 sh4r.pc += (PCDISP8(ir)<<1) + 4;1.133 @@ -1223,7 +1241,7 @@1.134 }1.135 break;1.136 case 11:/* BF disp8 */1.137 - CHECKSLOTILLEGAL()1.138 + CHECKSLOTILLEGAL();1.139 if( !sh4r.t ) {1.140 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )1.141 sh4r.pc += (PCDISP8(ir)<<1) + 4;1.142 @@ -1232,7 +1250,7 @@1.143 }1.144 break;1.145 case 13:/* BT/S disp8 */1.146 - CHECKSLOTILLEGAL()1.147 + CHECKSLOTILLEGAL();1.148 if( sh4r.t ) {1.149 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )1.150 sh4r.in_delay_slot = 1;1.151 @@ -1243,7 +1261,7 @@1.152 }1.153 break;1.154 case 15:/* BF/S disp8 */1.155 - CHECKSLOTILLEGAL()1.156 + CHECKSLOTILLEGAL();1.157 if( !sh4r.t ) {1.158 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )1.159 sh4r.in_delay_slot = 1;1.160 @@ -1263,16 +1281,16 @@1.161 break;1.162 case 10:/* 1010dddddddddddd */1.163 /* BRA disp12 */1.164 - CHECKSLOTILLEGAL()1.165 - CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 )1.166 + CHECKSLOTILLEGAL();1.167 + CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 );1.168 sh4r.in_delay_slot = 1;1.169 sh4r.pc = sh4r.new_pc;1.170 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);1.171 return TRUE;1.172 case 11:/* 1011dddddddddddd */1.173 /* BSR disp12 */1.174 - CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 )1.175 - CHECKSLOTILLEGAL()1.176 + CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 );1.177 + CHECKSLOTILLEGAL();1.178 sh4r.in_delay_slot = 1;1.179 sh4r.pr = pc + 4;1.180 sh4r.pc = sh4r.new_pc;1.181 @@ -1295,10 +1313,10 @@1.182 MEM_WRITE_LONG( tmp, R0 );1.183 break;1.184 case 3: /* TRAPA imm8 */1.185 - CHECKSLOTILLEGAL()1.186 - sh4r.in_delay_slot = 1;1.187 + CHECKSLOTILLEGAL();1.188 MMIO_WRITE( MMU, TRA, UIMM8(ir)<<2 );1.189 - RAISE( EXC_TRAP, EXV_TRAP, 2 );1.190 + sh4r.pc += 2;1.191 + sh4_raise_exception( EXC_TRAP );1.192 break;1.193 case 4: /* MOV.B [GBR + disp8], R0 */1.194 R0 = MEM_READ_BYTE( sh4r.gbr + DISP8(ir) );
2.1 --- a/src/sh4/sh4core.h Tue Dec 19 09:52:56 2006 +00002.2 +++ b/src/sh4/sh4core.h Tue Dec 19 09:54:03 2006 +00002.3 @@ -1,5 +1,5 @@2.4 /**2.5 - * $Id: sh4core.h,v 1.13 2006-06-15 10:27:10 nkeynes Exp $2.6 + * $Id: sh4core.h,v 1.14 2006-12-19 09:54:03 nkeynes Exp $2.7 *2.8 * This file defines the internal functions exported/used by the SH4 core,2.9 * except for disassembly functions defined in sh4dasm.h2.10 @@ -87,7 +87,9 @@2.11 void sh4_stop( void );2.12 void sh4_set_pc( int );2.13 gboolean sh4_execute_instruction( void );2.14 -void sh4_raise_exception( int, int );2.15 +gboolean sh4_raise_exception( int );2.16 +gboolean sh4_raise_slot_exception( int, int );2.17 +gboolean sh4_raise_tlb_exception( int );2.18 void sh4_set_breakpoint( uint32_t pc, int type );2.19 gboolean sh4_clear_breakpoint( uint32_t pc, int type );2.20 int sh4_get_breakpoint( uint32_t pc );
.