1.1 --- a/src/sh4/sh4core.c Thu Jul 06 08:46:41 2006 +0000
1.2 +++ b/src/sh4/sh4core.c Sun Aug 06 09:43:03 2006 +0000
1.5 - * $Id: sh4core.c,v 1.29 2006-07-06 08:46:41 nkeynes Exp $
1.6 + * $Id: sh4core.c,v 1.30 2006-08-06 09:43:03 nkeynes Exp $
1.8 * SH4 emulation core, and parent module for all the SH4 peripheral
1.11 /* CPU-generated exception code/vector pairs */
1.12 #define EXC_POWER_RESET 0x000 /* vector special */
1.13 #define EXC_MANUAL_RESET 0x020
1.14 +#define EXC_READ_ADDR_ERR 0x0E0
1.15 +#define EXC_WRITE_ADDR_ERR 0x100
1.16 #define EXC_SLOT_ILLEGAL 0x1A0
1.17 #define EXC_ILLEGAL 0x180
1.18 #define EXV_ILLEGAL 0x100
1.19 @@ -282,6 +284,11 @@
1.21 #define CHECK( x, c, v ) if( !x ) RAISE( c, v )
1.22 #define CHECKPRIV() CHECK( IS_SH4_PRIVMODE(), EXC_ILLEGAL, EXV_ILLEGAL )
1.23 +#define CHECKRALIGN16(addr) if( (addr)&0x01 ) RAISE( EXC_READ_ADDR_ERR, EXV_TRAP )
1.24 +#define CHECKRALIGN32(addr) if( (addr)&0x03 ) RAISE( EXC_READ_ADDR_ERR, EXV_TRAP )
1.25 +#define CHECKWALIGN16(addr) if( (addr)&0x01 ) RAISE( EXC_WRITE_ADDR_ERR, EXV_TRAP )
1.26 +#define CHECKWALIGN32(addr) if( (addr)&0x03 ) RAISE( EXC_WRITE_ADDR_ERR, EXV_TRAP )
1.28 #define CHECKFPUEN() CHECK( IS_FPU_ENABLED(), EXC_FPDISABLE, EXV_FPDISABLE )
1.29 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); dreamcast_stop(); return FALSE; }
1.30 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) { RAISE(EXC_SLOT_ILLEGAL,EXV_ILLEGAL); }
1.32 pc = sh4r.pc = sh4r.pr;
1.33 sh4r.new_pc = sh4r.pc + 2;
1.35 + CHECKRALIGN16(pc);
1.36 ir = MEM_READ_WORD(pc);
1.41 case 12:/* MOVCA.L R0, [Rn] */
1.43 + CHECKWALIGN32(tmp);
1.44 MEM_WRITE_LONG( tmp, R0 );
1.47 @@ -495,9 +504,11 @@
1.48 MEM_WRITE_BYTE( R0 + RN(ir), RM(ir) );
1.50 case 5: /* MOV.W Rm, [R0 + Rn] */
1.51 + CHECKWALIGN16( R0 + RN(ir) );
1.52 MEM_WRITE_WORD( R0 + RN(ir), RM(ir) );
1.54 case 6: /* MOV.L Rm, [R0 + Rn] */
1.55 + CHECKWALIGN32( R0 + RN(ir) );
1.56 MEM_WRITE_LONG( R0 + RN(ir), RM(ir) );
1.58 case 7: /* MUL.L Rm, Rn */
1.59 @@ -596,12 +607,16 @@
1.60 RN(ir) = MEM_READ_BYTE( R0 + RM(ir) );
1.62 case 13:/* MOV.W [R0+R%d], R%d */
1.63 + CHECKRALIGN16( R0 + RM(ir) );
1.64 RN(ir) = MEM_READ_WORD( R0 + RM(ir) );
1.66 case 14:/* MOV.L [R0+R%d], R%d */
1.67 + CHECKRALIGN32( R0 + RM(ir) );
1.68 RN(ir) = MEM_READ_LONG( R0 + RM(ir) );
1.70 case 15:/* MAC.L [Rm++], [Rn++] */
1.71 + CHECKRALIGN32( RM(ir) );
1.72 + CHECKRALIGN32( RN(ir) );
1.73 tmpl = ( SIGNEXT32(MEM_READ_LONG(RM(ir))) *
1.74 SIGNEXT32(MEM_READ_LONG(RN(ir))) );
1.78 case 1: /* 0001nnnnmmmmdddd */
1.79 /* MOV.L Rm, [Rn + disp4*4] */
1.80 - MEM_WRITE_LONG( RN(ir) + (DISP4(ir)<<2), RM(ir) );
1.81 + tmp = RN(ir) + (DISP4(ir)<<2);
1.82 + CHECKWALIGN32( tmp );
1.83 + MEM_WRITE_LONG( tmp, RM(ir) );
1.85 case 2: /* 0010nnnnmmmmxxxx */
1.86 switch( ir&0x000F ) {
1.87 @@ -632,9 +649,11 @@
1.88 MEM_WRITE_BYTE( RN(ir), RM(ir) );
1.90 case 1: /* MOV.W Rm, [Rn] */
1.91 - MEM_WRITE_WORD( RN(ir), RM(ir) );
1.92 + CHECKWALIGN16( RN(ir) );
1.93 + MEM_WRITE_WORD( RN(ir), RM(ir) );
1.95 case 2: /* MOV.L Rm, [Rn] */
1.96 + CHECKWALIGN32( RN(ir) );
1.97 MEM_WRITE_LONG( RN(ir), RM(ir) );
1.100 @@ -645,10 +664,12 @@
1.102 case 5: /* MOV.W Rm, [--Rn] */
1.104 + CHECKWALIGN16( RN(ir) );
1.105 MEM_WRITE_WORD( RN(ir), RM(ir) );
1.107 case 6: /* MOV.L Rm, [--Rn] */
1.109 + CHECKWALIGN32( RN(ir) );
1.110 MEM_WRITE_LONG( RN(ir), RM(ir) );
1.112 case 7: /* DIV0S Rm, Rn */
1.113 @@ -770,11 +791,13 @@
1.115 case 0x02: /* STS.L MACH, [--Rn] */
1.117 + CHECKWALIGN32( RN(ir) );
1.118 MEM_WRITE_LONG( RN(ir), (sh4r.mac>>32) );
1.120 case 0x03: /* STC.L SR, [--Rn] */
1.123 + CHECKWALIGN32( RN(ir) );
1.124 MEM_WRITE_LONG( RN(ir), sh4_read_sr() );
1.126 case 0x04: /* ROTL Rn */
1.127 @@ -788,12 +811,14 @@
1.128 RN(ir) |= (sh4r.t << 31);
1.130 case 0x06: /* LDS.L [Rn++], MACH */
1.131 + CHECKRALIGN32( RN(ir) );
1.132 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
1.133 (((uint64_t)MEM_READ_LONG(RN(ir)))<<32);
1.136 case 0x07: /* LDC.L [Rn++], SR */
1.138 + CHECKWALIGN32( RN(ir) );
1.139 sh4_load_sr( MEM_READ_LONG(RN(ir)) );
1.142 @@ -829,21 +854,25 @@
1.144 case 0x12: /* STS.L MACL, [--Rn] */
1.146 + CHECKWALIGN32( RN(ir) );
1.147 MEM_WRITE_LONG( RN(ir), (uint32_t)sh4r.mac );
1.149 case 0x13: /* STC.L GBR, [--Rn] */
1.151 + CHECKWALIGN32( RN(ir) );
1.152 MEM_WRITE_LONG( RN(ir), sh4r.gbr );
1.154 case 0x15: /* CMP/PL Rn */
1.155 sh4r.t = ( ((int32_t)RN(ir)) > 0 ? 1 : 0 );
1.157 case 0x16: /* LDS.L [Rn++], MACL */
1.158 + CHECKRALIGN32( RN(ir) );
1.159 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
1.160 (uint64_t)((uint32_t)MEM_READ_LONG(RN(ir)));
1.163 case 0x17: /* LDC.L [Rn++], GBR */
1.164 + CHECKRALIGN32( RN(ir) );
1.165 sh4r.gbr = MEM_READ_LONG(RN(ir));
1.168 @@ -875,11 +904,13 @@
1.170 case 0x22: /* STS.L PR, [--Rn] */
1.172 + CHECKWALIGN32( RN(ir) );
1.173 MEM_WRITE_LONG( RN(ir), sh4r.pr );
1.175 case 0x23: /* STC.L VBR, [--Rn] */
1.178 + CHECKWALIGN32( RN(ir) );
1.179 MEM_WRITE_LONG( RN(ir), sh4r.vbr );
1.181 case 0x24: /* ROTCL Rn */
1.182 @@ -895,11 +926,13 @@
1.185 case 0x26: /* LDS.L [Rn++], PR */
1.186 + CHECKRALIGN32( RN(ir) );
1.187 sh4r.pr = MEM_READ_LONG( RN(ir) );
1.190 case 0x27: /* LDC.L [Rn++], VBR */
1.192 + CHECKRALIGN32( RN(ir) );
1.193 sh4r.vbr = MEM_READ_LONG(RN(ir));
1.196 @@ -926,15 +959,18 @@
1.197 case 0x32: /* STC.L SGR, [--Rn] */
1.200 + CHECKWALIGN32( RN(ir) );
1.201 MEM_WRITE_LONG( RN(ir), sh4r.sgr );
1.203 case 0x33: /* STC.L SSR, [--Rn] */
1.206 + CHECKWALIGN32( RN(ir) );
1.207 MEM_WRITE_LONG( RN(ir), sh4r.ssr );
1.209 case 0x37: /* LDC.L [Rn++], SSR */
1.211 + CHECKRALIGN32( RN(ir) );
1.212 sh4r.ssr = MEM_READ_LONG(RN(ir));
1.215 @@ -945,10 +981,12 @@
1.216 case 0x43: /* STC.L SPC, [--Rn] */
1.219 + CHECKWALIGN32( RN(ir) );
1.220 MEM_WRITE_LONG( RN(ir), sh4r.spc );
1.222 case 0x47: /* LDC.L [Rn++], SPC */
1.224 + CHECKRALIGN32( RN(ir) );
1.225 sh4r.spc = MEM_READ_LONG(RN(ir));
1.228 @@ -958,9 +996,11 @@
1.230 case 0x52: /* STS.L FPUL, [--Rn] */
1.232 + CHECKWALIGN32( RN(ir) );
1.233 MEM_WRITE_LONG( RN(ir), sh4r.fpul );
1.235 case 0x56: /* LDS.L [Rn++], FPUL */
1.236 + CHECKRALIGN32( RN(ir) );
1.237 sh4r.fpul = MEM_READ_LONG(RN(ir));
1.240 @@ -969,9 +1009,11 @@
1.242 case 0x62: /* STS.L FPSCR, [--Rn] */
1.244 + CHECKWALIGN32( RN(ir) );
1.245 MEM_WRITE_LONG( RN(ir), sh4r.fpscr );
1.247 case 0x66: /* LDS.L [Rn++], FPSCR */
1.248 + CHECKRALIGN32( RN(ir) );
1.249 sh4r.fpscr = MEM_READ_LONG(RN(ir));
1.252 @@ -981,10 +1023,12 @@
1.253 case 0xF2: /* STC.L DBR, [--Rn] */
1.256 + CHECKWALIGN32( RN(ir) );
1.257 MEM_WRITE_LONG( RN(ir), sh4r.dbr );
1.259 case 0xF6: /* LDC.L [Rn++], DBR */
1.261 + CHECKRALIGN32( RN(ir) );
1.262 sh4r.dbr = MEM_READ_LONG(RN(ir));
1.265 @@ -996,11 +1040,13 @@
1.266 case 0xD3: case 0xE3: case 0xF3: /* STC.L Rn_BANK, [--Rn] */
1.269 + CHECKWALIGN32( RN(ir) );
1.270 MEM_WRITE_LONG( RN(ir), RN_BANK(ir) );
1.272 case 0x87: case 0x97: case 0xA7: case 0xB7: case 0xC7:
1.273 case 0xD7: case 0xE7: case 0xF7: /* LDC.L [Rn++], Rn_BANK */
1.275 + CHECKRALIGN32( RN(ir) );
1.276 RN_BANK(ir) = MEM_READ_LONG( RN(ir) );
1.279 @@ -1012,6 +1058,8 @@
1.281 if( (ir&0x000F) == 0x0F ) {
1.282 /* MAC.W [Rm++], [Rn++] */
1.283 + CHECKRALIGN16( RN(ir) );
1.284 + CHECKRALIGN16( RM(ir) );
1.285 tmp = SIGNEXT16(MEM_READ_WORD(RM(ir))) *
1.286 SIGNEXT16(MEM_READ_WORD(RN(ir)));
1.288 @@ -1039,7 +1087,9 @@
1.290 case 5: /* 0101nnnnmmmmdddd */
1.291 /* MOV.L [Rm + disp4*4], Rn */
1.292 - RN(ir) = MEM_READ_LONG( RM(ir) + (DISP4(ir)<<2) );
1.293 + tmp = RM(ir) + (DISP4(ir)<<2);
1.294 + CHECKRALIGN32( tmp );
1.295 + RN(ir) = MEM_READ_LONG( tmp );
1.297 case 6: /* 0110xxxxxxxxxxxx */
1.298 switch( ir&0x000f ) {
1.299 @@ -1047,9 +1097,11 @@
1.300 RN(ir) = MEM_READ_BYTE( RM(ir) );
1.302 case 1: /* MOV.W [Rm], Rn */
1.303 + CHECKRALIGN16( RM(ir) );
1.304 RN(ir) = MEM_READ_WORD( RM(ir) );
1.306 case 2: /* MOV.L [Rm], Rn */
1.307 + CHECKRALIGN32( RM(ir) );
1.308 RN(ir) = MEM_READ_LONG( RM(ir) );
1.310 case 3: /* MOV Rm, Rn */
1.311 @@ -1060,10 +1112,12 @@
1.314 case 5: /* MOV.W [Rm++], Rn */
1.315 + CHECKRALIGN16( RM(ir) );
1.316 RN(ir) = MEM_READ_WORD( RM(ir) );
1.319 case 6: /* MOV.L [Rm++], Rn */
1.320 + CHECKRALIGN32( RM(ir) );
1.321 RN(ir) = MEM_READ_LONG( RM(ir) );
1.324 @@ -1109,13 +1163,17 @@
1.325 MEM_WRITE_BYTE( RM(ir) + DISP4(ir), R0 );
1.327 case 1: /* MOV.W R0, [Rm + disp4*2] */
1.328 - MEM_WRITE_WORD( RM(ir) + (DISP4(ir)<<1), R0 );
1.329 + tmp = RM(ir) + (DISP4(ir)<<1);
1.330 + CHECKWALIGN16( tmp );
1.331 + MEM_WRITE_WORD( tmp, R0 );
1.333 case 4: /* MOV.B [Rm + disp4], R0 */
1.334 R0 = MEM_READ_BYTE( RM(ir) + DISP4(ir) );
1.336 case 5: /* MOV.W [Rm + disp4*2], R0 */
1.337 - R0 = MEM_READ_WORD( RM(ir) + (DISP4(ir)<<1) );
1.338 + tmp = RM(ir) + (DISP4(ir)<<1);
1.339 + CHECKRALIGN16( tmp );
1.340 + R0 = MEM_READ_WORD( tmp );
1.342 case 8: /* CMP/EQ imm, R0 */
1.343 sh4r.t = ( R0 == IMM8(ir) ? 1 : 0 );
1.344 @@ -1164,7 +1222,9 @@
1.346 case 9: /* 1001xxxxxxxxxxxx */
1.347 /* MOV.W [disp8*2 + pc + 4], Rn */
1.348 - RN(ir) = MEM_READ_WORD( pc + 4 + (DISP8(ir)<<1) );
1.349 + tmp = pc + 4 + (DISP8(ir)<<1);
1.350 + CHECKRALIGN16( tmp );
1.351 + RN(ir) = MEM_READ_WORD( tmp );
1.353 case 10:/* 1010dddddddddddd */
1.355 @@ -1190,10 +1250,14 @@
1.356 MEM_WRITE_BYTE( sh4r.gbr + DISP8(ir), R0 );
1.358 case 1: /* MOV.W R0, [GBR + disp8*2] */
1.359 - MEM_WRITE_WORD( sh4r.gbr + (DISP8(ir)<<1), R0 );
1.360 + tmp = sh4r.gbr + (DISP8(ir)<<1);
1.361 + CHECKWALIGN16( tmp );
1.362 + MEM_WRITE_WORD( tmp, R0 );
1.364 case 2: /*MOV.L R0, [GBR + disp8*4] */
1.365 - MEM_WRITE_LONG( sh4r.gbr + (DISP8(ir)<<2), R0 );
1.366 + tmp = sh4r.gbr + (DISP8(ir)<<2);
1.367 + CHECKWALIGN32( tmp );
1.368 + MEM_WRITE_LONG( tmp, R0 );
1.370 case 3: /* TRAPA imm8 */
1.372 @@ -1205,10 +1269,14 @@
1.373 R0 = MEM_READ_BYTE( sh4r.gbr + DISP8(ir) );
1.375 case 5: /* MOV.W [GBR + disp8*2], R0 */
1.376 - R0 = MEM_READ_WORD( sh4r.gbr + (DISP8(ir)<<1) );
1.377 + tmp = sh4r.gbr + (DISP8(ir)<<1);
1.378 + CHECKRALIGN16( tmp );
1.379 + R0 = MEM_READ_WORD( tmp );
1.381 case 6: /* MOV.L [GBR + disp8*4], R0 */
1.382 - R0 = MEM_READ_LONG( sh4r.gbr + (DISP8(ir)<<2) );
1.383 + tmp = sh4r.gbr + (DISP8(ir)<<2);
1.384 + CHECKRALIGN32( tmp );
1.385 + R0 = MEM_READ_LONG( tmp );
1.387 case 7: /* MOVA disp8 + pc&~3 + 4, R0 */
1.388 R0 = (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4;
1.389 @@ -1225,7 +1293,7 @@
1.390 case 11:/* OR imm8, R0 */
1.393 - case 12:/* TST.B imm8, [R0+GBR] */
1.394 + case 12:/* TST.B imm8, [R0+GBR] */
1.395 sh4r.t = ( MEM_READ_BYTE(R0 + sh4r.gbr) & UIMM8(ir) ? 0 : 1 );
1.397 case 13:/* AND.B imm8, [R0+GBR] */
1.398 @@ -1244,7 +1312,9 @@
1.400 case 13:/* 1101nnnndddddddd */
1.401 /* MOV.L [disp8*4 + pc&~3 + 4], Rn */
1.402 - RN(ir) = MEM_READ_LONG( (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4 );
1.403 + tmp = (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4;
1.404 + CHECKRALIGN32( tmp );
1.405 + RN(ir) = MEM_READ_LONG( tmp );
1.407 case 14:/* 1110nnnniiiiiiii */