Search
lxdream.org :: lxdream :: r208:ad290228eea1
lxdream 0.9.1
released Jun 29
Download Now
changeset208:ad290228eea1
parent207:135a2dc75b10
child209:ff67a7b9aa17
authornkeynes
dateSun Aug 06 09:43:03 2006 +0000 (14 years ago)
Add alignment checks
src/sh4/sh4core.c
1.1 --- a/src/sh4/sh4core.c Sun Aug 06 08:44:48 2006 +0000
1.2 +++ b/src/sh4/sh4core.c Sun Aug 06 09:43:03 2006 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
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.7 *
1.8 * SH4 emulation core, and parent module for all the SH4 peripheral
1.9 * modules.
1.10 @@ -37,6 +37,8 @@
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.20
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.27 +
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.31 @@ -415,6 +422,7 @@
1.32 pc = sh4r.pc = sh4r.pr;
1.33 sh4r.new_pc = sh4r.pc + 2;
1.34 }
1.35 + CHECKRALIGN16(pc);
1.36 ir = MEM_READ_WORD(pc);
1.37 sh4r.icount++;
1.38
1.39 @@ -486,6 +494,7 @@
1.40 break;
1.41 case 12:/* MOVCA.L R0, [Rn] */
1.42 tmp = RN(ir);
1.43 + CHECKWALIGN32(tmp);
1.44 MEM_WRITE_LONG( tmp, R0 );
1.45 break;
1.46 default: UNDEF(ir);
1.47 @@ -495,9 +504,11 @@
1.48 MEM_WRITE_BYTE( R0 + RN(ir), RM(ir) );
1.49 break;
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.53 break;
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.57 break;
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.61 break;
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.65 break;
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.69 break;
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.75 if( sh4r.s ) {
1.76 @@ -624,7 +639,9 @@
1.77 break;
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.84 break;
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.89 break;
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.94 break;
1.95 case 2: /* MOV.L Rm, [Rn] */
1.96 + CHECKWALIGN32( RN(ir) );
1.97 MEM_WRITE_LONG( RN(ir), RM(ir) );
1.98 break;
1.99 case 3: UNDEF(ir);
1.100 @@ -645,10 +664,12 @@
1.101 break;
1.102 case 5: /* MOV.W Rm, [--Rn] */
1.103 RN(ir) -= 2;
1.104 + CHECKWALIGN16( RN(ir) );
1.105 MEM_WRITE_WORD( RN(ir), RM(ir) );
1.106 break;
1.107 case 6: /* MOV.L Rm, [--Rn] */
1.108 RN(ir) -= 4;
1.109 + CHECKWALIGN32( RN(ir) );
1.110 MEM_WRITE_LONG( RN(ir), RM(ir) );
1.111 break;
1.112 case 7: /* DIV0S Rm, Rn */
1.113 @@ -770,11 +791,13 @@
1.114 break;
1.115 case 0x02: /* STS.L MACH, [--Rn] */
1.116 RN(ir) -= 4;
1.117 + CHECKWALIGN32( RN(ir) );
1.118 MEM_WRITE_LONG( RN(ir), (sh4r.mac>>32) );
1.119 break;
1.120 case 0x03: /* STC.L SR, [--Rn] */
1.121 CHECKPRIV();
1.122 RN(ir) -= 4;
1.123 + CHECKWALIGN32( RN(ir) );
1.124 MEM_WRITE_LONG( RN(ir), sh4_read_sr() );
1.125 break;
1.126 case 0x04: /* ROTL Rn */
1.127 @@ -788,12 +811,14 @@
1.128 RN(ir) |= (sh4r.t << 31);
1.129 break;
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.134 RN(ir) += 4;
1.135 break;
1.136 case 0x07: /* LDC.L [Rn++], SR */
1.137 CHECKPRIV();
1.138 + CHECKWALIGN32( RN(ir) );
1.139 sh4_load_sr( MEM_READ_LONG(RN(ir)) );
1.140 RN(ir) +=4;
1.141 break;
1.142 @@ -829,21 +854,25 @@
1.143 break;
1.144 case 0x12: /* STS.L MACL, [--Rn] */
1.145 RN(ir) -= 4;
1.146 + CHECKWALIGN32( RN(ir) );
1.147 MEM_WRITE_LONG( RN(ir), (uint32_t)sh4r.mac );
1.148 break;
1.149 case 0x13: /* STC.L GBR, [--Rn] */
1.150 RN(ir) -= 4;
1.151 + CHECKWALIGN32( RN(ir) );
1.152 MEM_WRITE_LONG( RN(ir), sh4r.gbr );
1.153 break;
1.154 case 0x15: /* CMP/PL Rn */
1.155 sh4r.t = ( ((int32_t)RN(ir)) > 0 ? 1 : 0 );
1.156 break;
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.161 RN(ir) += 4;
1.162 break;
1.163 case 0x17: /* LDC.L [Rn++], GBR */
1.164 + CHECKRALIGN32( RN(ir) );
1.165 sh4r.gbr = MEM_READ_LONG(RN(ir));
1.166 RN(ir) +=4;
1.167 break;
1.168 @@ -875,11 +904,13 @@
1.169 break;
1.170 case 0x22: /* STS.L PR, [--Rn] */
1.171 RN(ir) -= 4;
1.172 + CHECKWALIGN32( RN(ir) );
1.173 MEM_WRITE_LONG( RN(ir), sh4r.pr );
1.174 break;
1.175 case 0x23: /* STC.L VBR, [--Rn] */
1.176 CHECKPRIV();
1.177 RN(ir) -= 4;
1.178 + CHECKWALIGN32( RN(ir) );
1.179 MEM_WRITE_LONG( RN(ir), sh4r.vbr );
1.180 break;
1.181 case 0x24: /* ROTCL Rn */
1.182 @@ -895,11 +926,13 @@
1.183 sh4r.t = tmp;
1.184 break;
1.185 case 0x26: /* LDS.L [Rn++], PR */
1.186 + CHECKRALIGN32( RN(ir) );
1.187 sh4r.pr = MEM_READ_LONG( RN(ir) );
1.188 RN(ir) += 4;
1.189 break;
1.190 case 0x27: /* LDC.L [Rn++], VBR */
1.191 CHECKPRIV();
1.192 + CHECKRALIGN32( RN(ir) );
1.193 sh4r.vbr = MEM_READ_LONG(RN(ir));
1.194 RN(ir) +=4;
1.195 break;
1.196 @@ -926,15 +959,18 @@
1.197 case 0x32: /* STC.L SGR, [--Rn] */
1.198 CHECKPRIV();
1.199 RN(ir) -= 4;
1.200 + CHECKWALIGN32( RN(ir) );
1.201 MEM_WRITE_LONG( RN(ir), sh4r.sgr );
1.202 break;
1.203 case 0x33: /* STC.L SSR, [--Rn] */
1.204 CHECKPRIV();
1.205 RN(ir) -= 4;
1.206 + CHECKWALIGN32( RN(ir) );
1.207 MEM_WRITE_LONG( RN(ir), sh4r.ssr );
1.208 break;
1.209 case 0x37: /* LDC.L [Rn++], SSR */
1.210 CHECKPRIV();
1.211 + CHECKRALIGN32( RN(ir) );
1.212 sh4r.ssr = MEM_READ_LONG(RN(ir));
1.213 RN(ir) +=4;
1.214 break;
1.215 @@ -945,10 +981,12 @@
1.216 case 0x43: /* STC.L SPC, [--Rn] */
1.217 CHECKPRIV();
1.218 RN(ir) -= 4;
1.219 + CHECKWALIGN32( RN(ir) );
1.220 MEM_WRITE_LONG( RN(ir), sh4r.spc );
1.221 break;
1.222 case 0x47: /* LDC.L [Rn++], SPC */
1.223 CHECKPRIV();
1.224 + CHECKRALIGN32( RN(ir) );
1.225 sh4r.spc = MEM_READ_LONG(RN(ir));
1.226 RN(ir) +=4;
1.227 break;
1.228 @@ -958,9 +996,11 @@
1.229 break;
1.230 case 0x52: /* STS.L FPUL, [--Rn] */
1.231 RN(ir) -= 4;
1.232 + CHECKWALIGN32( RN(ir) );
1.233 MEM_WRITE_LONG( RN(ir), sh4r.fpul );
1.234 break;
1.235 case 0x56: /* LDS.L [Rn++], FPUL */
1.236 + CHECKRALIGN32( RN(ir) );
1.237 sh4r.fpul = MEM_READ_LONG(RN(ir));
1.238 RN(ir) +=4;
1.239 break;
1.240 @@ -969,9 +1009,11 @@
1.241 break;
1.242 case 0x62: /* STS.L FPSCR, [--Rn] */
1.243 RN(ir) -= 4;
1.244 + CHECKWALIGN32( RN(ir) );
1.245 MEM_WRITE_LONG( RN(ir), sh4r.fpscr );
1.246 break;
1.247 case 0x66: /* LDS.L [Rn++], FPSCR */
1.248 + CHECKRALIGN32( RN(ir) );
1.249 sh4r.fpscr = MEM_READ_LONG(RN(ir));
1.250 RN(ir) +=4;
1.251 break;
1.252 @@ -981,10 +1023,12 @@
1.253 case 0xF2: /* STC.L DBR, [--Rn] */
1.254 CHECKPRIV();
1.255 RN(ir) -= 4;
1.256 + CHECKWALIGN32( RN(ir) );
1.257 MEM_WRITE_LONG( RN(ir), sh4r.dbr );
1.258 break;
1.259 case 0xF6: /* LDC.L [Rn++], DBR */
1.260 CHECKPRIV();
1.261 + CHECKRALIGN32( RN(ir) );
1.262 sh4r.dbr = MEM_READ_LONG(RN(ir));
1.263 RN(ir) +=4;
1.264 break;
1.265 @@ -996,11 +1040,13 @@
1.266 case 0xD3: case 0xE3: case 0xF3: /* STC.L Rn_BANK, [--Rn] */
1.267 CHECKPRIV();
1.268 RN(ir) -= 4;
1.269 + CHECKWALIGN32( RN(ir) );
1.270 MEM_WRITE_LONG( RN(ir), RN_BANK(ir) );
1.271 break;
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.274 CHECKPRIV();
1.275 + CHECKRALIGN32( RN(ir) );
1.276 RN_BANK(ir) = MEM_READ_LONG( RN(ir) );
1.277 RN(ir) += 4;
1.278 break;
1.279 @@ -1012,6 +1058,8 @@
1.280 default:
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.287 if( sh4r.s ) {
1.288 @@ -1039,7 +1087,9 @@
1.289 break;
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.296 break;
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.301 break;
1.302 case 1: /* MOV.W [Rm], Rn */
1.303 + CHECKRALIGN16( RM(ir) );
1.304 RN(ir) = MEM_READ_WORD( RM(ir) );
1.305 break;
1.306 case 2: /* MOV.L [Rm], Rn */
1.307 + CHECKRALIGN32( RM(ir) );
1.308 RN(ir) = MEM_READ_LONG( RM(ir) );
1.309 break;
1.310 case 3: /* MOV Rm, Rn */
1.311 @@ -1060,10 +1112,12 @@
1.312 RM(ir) ++;
1.313 break;
1.314 case 5: /* MOV.W [Rm++], Rn */
1.315 + CHECKRALIGN16( RM(ir) );
1.316 RN(ir) = MEM_READ_WORD( RM(ir) );
1.317 RM(ir) += 2;
1.318 break;
1.319 case 6: /* MOV.L [Rm++], Rn */
1.320 + CHECKRALIGN32( RM(ir) );
1.321 RN(ir) = MEM_READ_LONG( RM(ir) );
1.322 RM(ir) += 4;
1.323 break;
1.324 @@ -1109,13 +1163,17 @@
1.325 MEM_WRITE_BYTE( RM(ir) + DISP4(ir), R0 );
1.326 break;
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.332 break;
1.333 case 4: /* MOV.B [Rm + disp4], R0 */
1.334 R0 = MEM_READ_BYTE( RM(ir) + DISP4(ir) );
1.335 break;
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.341 break;
1.342 case 8: /* CMP/EQ imm, R0 */
1.343 sh4r.t = ( R0 == IMM8(ir) ? 1 : 0 );
1.344 @@ -1164,7 +1222,9 @@
1.345 break;
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.352 break;
1.353 case 10:/* 1010dddddddddddd */
1.354 /* BRA disp12 */
1.355 @@ -1190,10 +1250,14 @@
1.356 MEM_WRITE_BYTE( sh4r.gbr + DISP8(ir), R0 );
1.357 break;
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.363 break;
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.369 break;
1.370 case 3: /* TRAPA imm8 */
1.371 CHECKSLOTILLEGAL()
1.372 @@ -1205,10 +1269,14 @@
1.373 R0 = MEM_READ_BYTE( sh4r.gbr + DISP8(ir) );
1.374 break;
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.380 break;
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.386 break;
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.391 R0 |= UIMM8(ir);
1.392 break;
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.396 break;
1.397 case 13:/* AND.B imm8, [R0+GBR] */
1.398 @@ -1244,7 +1312,9 @@
1.399 break;
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.406 break;
1.407 case 14:/* 1110nnnniiiiiiii */
1.408 /* MOV imm8, Rn */
.