filename | src/sh4/sh4core.c |
changeset | 232:9c8ef78376ed |
prev | 229:f27eb26ccdd2 |
next | 235:880bff11df92 |
author | nkeynes |
date | Tue Sep 26 11:09:13 2006 +0000 (16 years ago) |
permissions | -rw-r--r-- |
last change | Add CHECKSLOTILLEGAL() checks around a few banned delay-slot instructions that were missing it Change CHECKPRIV() to raise slot-illegal on a delay-slot instruction rather than general-illegal (as per the manual) Convert UNDEF() to do the real exception rather than halting the machine Remove a couple of superfluous alignment checks |
file | annotate | diff | log | raw |
1.1 --- a/src/sh4/sh4core.c Mon Sep 25 11:19:42 2006 +00001.2 +++ b/src/sh4/sh4core.c Tue Sep 26 11:09:13 2006 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: sh4core.c,v 1.32 2006-09-25 11:19:42 nkeynes Exp $1.6 + * $Id: sh4core.c,v 1.33 2006-09-26 11:09:13 nkeynes Exp $1.7 *1.8 * SH4 emulation core, and parent module for all the SH4 peripheral1.9 * modules.1.10 @@ -204,7 +204,7 @@1.11 sh4r.new_pc = pc+2;1.12 }1.14 -#define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)1.15 +#define UNDEF(ir) if( sh4r.in_delay_slot ) { RAISE( EXC_SLOT_ILLEGAL, EXV_ILLEGAL, -2 ); } else { RAISE( EXC_ILLEGAL, EXV_ILLEGAL, 0 ); }1.16 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)1.18 #if(SH4_CALLTRACE == 1)1.19 @@ -266,9 +266,11 @@1.20 sh4r.pc = sh4r.vbr + v; \1.21 sh4r.new_pc = sh4r.pc + 2; \1.22 sh4_load_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \1.23 + sh4r.in_delay_slot = 0; \1.24 } \1.25 return TRUE; } while(0)1.26 -1.27 +#define RAISE_SLOTILLEGAL() RAISE( EXC_SLOT_ILLEGAL, EXV_ILLEGAL, -2 )1.28 +#define RAISE_ILLEGAL() RAISE( EXC_ILLEGAL, EXV_ILLEGAL, 0 )1.30 #define MEM_READ_BYTE( addr ) sh4_read_byte(addr)1.31 #define MEM_READ_WORD( addr ) sh4_read_word(addr)1.32 @@ -284,7 +286,7 @@1.33 #define MEM_FP_WRITE( addr, reg ) sh4_write_float( addr, reg );1.35 #define CHECK( x, c, v ) if( !x ) RAISE( c, v, 0 )1.36 -#define CHECKPRIV() CHECK( IS_SH4_PRIVMODE(), EXC_ILLEGAL, EXV_ILLEGAL )1.37 +#define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) { if( sh4r.in_delay_slot ) { RAISE_SLOTILLEGAL(); } else { RAISE_ILLEGAL(); } }1.38 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) RAISE( EXC_READ_ADDR_ERR, EXV_TRAP, 0 )1.39 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) RAISE( EXC_READ_ADDR_ERR, EXV_TRAP, 0 )1.40 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) RAISE( EXC_WRITE_ADDR_ERR, EXV_TRAP, 0 )1.41 @@ -462,8 +464,8 @@1.42 case 3:1.43 switch( (ir&0x00F0)>>4 ) {1.44 case 0: /* BSRF Rn */1.45 + CHECKSLOTILLEGAL();1.46 CHECKDEST( pc + 4 + RN(ir) );1.47 - CHECKSLOTILLEGAL();1.48 sh4r.in_delay_slot = 1;1.49 sh4r.pr = sh4r.pc + 4;1.50 sh4r.pc = sh4r.new_pc;1.51 @@ -471,8 +473,8 @@1.52 TRACE_CALL( pc, sh4r.new_pc );1.53 return TRUE;1.54 case 2: /* BRAF Rn */1.55 + CHECKSLOTILLEGAL();1.56 CHECKDEST( pc + 4 + RN(ir) );1.57 - CHECKSLOTILLEGAL();1.58 sh4r.in_delay_slot = 1;1.59 sh4r.pc = sh4r.new_pc;1.60 sh4r.new_pc = pc + 4 + RN(ir);1.61 @@ -578,8 +580,8 @@1.62 case 11:1.63 switch( (ir&0x0FF0)>>4 ) {1.64 case 0: /* RTS */1.65 + CHECKSLOTILLEGAL();1.66 CHECKDEST( sh4r.pr );1.67 - CHECKSLOTILLEGAL();1.68 sh4r.in_delay_slot = 1;1.69 sh4r.pc = sh4r.new_pc;1.70 sh4r.new_pc = sh4r.pr;1.71 @@ -820,6 +822,7 @@1.72 RN(ir) += 4;1.73 break;1.74 case 0x07: /* LDC.L [Rn++], SR */1.75 + CHECKSLOTILLEGAL();1.76 CHECKPRIV();1.77 CHECKWALIGN32( RN(ir) );1.78 sh4_load_sr( MEM_READ_LONG(RN(ir)) );1.79 @@ -845,6 +848,7 @@1.80 TRACE_CALL( pc, sh4r.new_pc );1.81 return TRUE;1.82 case 0x0E: /* LDC Rn, SR */1.83 + CHECKSLOTILLEGAL();1.84 CHECKPRIV();1.85 sh4_load_sr( RN(ir) );1.86 break;1.87 @@ -1225,14 +1229,14 @@1.88 break;1.89 case 9: /* 1001xxxxxxxxxxxx */1.90 /* MOV.W [disp8*2 + pc + 4], Rn */1.91 + CHECKSLOTILLEGAL();1.92 tmp = pc + 4 + (DISP8(ir)<<1);1.93 - CHECKRALIGN16( tmp );1.94 RN(ir) = MEM_READ_WORD( tmp );1.95 break;1.96 case 10:/* 1010dddddddddddd */1.97 /* BRA disp12 */1.98 + CHECKSLOTILLEGAL()1.99 CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 )1.100 - CHECKSLOTILLEGAL()1.101 sh4r.in_delay_slot = 1;1.102 sh4r.pc = sh4r.new_pc;1.103 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);1.104 @@ -1282,6 +1286,7 @@1.105 R0 = MEM_READ_LONG( tmp );1.106 break;1.107 case 7: /* MOVA disp8 + pc&~3 + 4, R0 */1.108 + CHECKSLOTILLEGAL();1.109 R0 = (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4;1.110 break;1.111 case 8: /* TST imm8, R0 */1.112 @@ -1315,8 +1320,8 @@1.113 break;1.114 case 13:/* 1101nnnndddddddd */1.115 /* MOV.L [disp8*4 + pc&~3 + 4], Rn */1.116 + CHECKSLOTILLEGAL();1.117 tmp = (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4;1.118 - CHECKRALIGN32( tmp );1.119 RN(ir) = MEM_READ_LONG( tmp );1.120 break;1.121 case 14:/* 1110nnnniiiiiiii */
.