Search
lxdream.org :: lxdream/src/sh4/sh4core.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4core.c
changeset 2:42349f6ea216
prev1:eea311cfd33e
next9:2784c7660165
author nkeynes
date Sat Aug 21 06:15:49 2004 +0000 (16 years ago)
permissions -rw-r--r--
last change Commit changes into cvs
file annotate diff log raw
1.1 --- a/src/sh4/sh4core.c Sat Mar 13 00:03:32 2004 +0000
1.2 +++ b/src/sh4/sh4core.c Sat Aug 21 06:15:49 2004 +0000
1.3 @@ -49,7 +49,14 @@
1.4 {
1.5 running = 1;
1.6 while( running && count--) {
1.7 + int pc = sh4r.pc;
1.8 sh4_execute_instruction();
1.9 + /*
1.10 + if( sh4r.pc == 0x8C0C1636 ||
1.11 + sh4r.pc == 0x8C0C1634 ) {
1.12 + WARN( "Branching to %08X from %08X", sh4r.pc, pc );
1.13 + sh4_stop();
1.14 + }*/
1.15 }
1.16 }
1.17
1.18 @@ -61,11 +68,13 @@
1.19 void sh4_runto( uint32_t target_pc, uint32_t count )
1.20 {
1.21 running = 1;
1.22 - do {
1.23 + while( running && count--) {
1.24 sh4_execute_instruction();
1.25 - } while( running && sh4r.pc != target_pc && count-- );
1.26 - if( count == 0 )
1.27 - running = 0;
1.28 + if( sh4r.pc == target_pc ) {
1.29 + running = 0;
1.30 + break;
1.31 + }
1.32 + }
1.33 }
1.34
1.35 #define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_stop(); RAISE( EXC_ILLEGAL, EXV_ILLEGAL ); }while(0)
1.36 @@ -107,6 +116,7 @@
1.37
1.38 #define EXC_POWER_RESET 0x000 /* vector special */
1.39 #define EXC_MANUAL_RESET 0x020
1.40 +#define EXC_SLOT_ILLEGAL 0x1A0
1.41 #define EXC_ILLEGAL 0x180
1.42 #define EXV_ILLEGAL 0x100
1.43 #define EXC_TRAP 0x160
1.44 @@ -118,6 +128,7 @@
1.45 #define CHECKPRIV() CHECK( IS_SH4_PRIVMODE(), EXC_ILLEGAL, EXV_ILLEGAL )
1.46 #define CHECKFPUEN() CHECK( IS_FPU_ENABLED(), EXC_FPDISABLE, EXV_FPDISABLE )
1.47 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_stop(); return; }
1.48 +#define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) { RAISE(EXC_SLOT_ILLEGAL,EXV_ILLEGAL); }
1.49
1.50 static void sh4_switch_banks( )
1.51 {
1.52 @@ -159,7 +170,6 @@
1.53 static void sh4_accept_interrupt( void )
1.54 {
1.55 uint32_t code = intc_accept_interrupt();
1.56 -
1.57 sh4r.ssr = sh4_read_sr();
1.58 sh4r.spc = sh4r.pc;
1.59 sh4r.sgr = sh4r.r[15];
1.60 @@ -167,12 +177,13 @@
1.61 MMIO_WRITE( MMU, INTEVT, code );
1.62 sh4r.pc = sh4r.vbr + 0x600;
1.63 sh4r.new_pc = sh4r.pc + 2;
1.64 + WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );
1.65 }
1.66
1.67 void sh4_execute_instruction( void )
1.68 {
1.69 - int pc = sh4r.pc;
1.70 - unsigned short ir = MEM_READ_WORD(pc);
1.71 + int pc;
1.72 + unsigned short ir;
1.73 uint32_t tmp;
1.74 uint64_t tmpl;
1.75
1.76 @@ -187,8 +198,8 @@
1.77 #define IMM8(ir) SIGNEXT8(ir&0x00FF)
1.78 #define UIMM8(ir) (ir&0x00FF) /* Unsigned immmediate */
1.79 #define DISP12(ir) SIGNEXT12(ir&0x0FFF)
1.80 -#define FVN(ir) ((ir&0x0C00)
1.81 -#define FVM(ir) ((ir&0x0300)>>8)
1.82 +#define FVN(ir) ((ir&0x0C00)>>8)
1.83 +#define FVM(ir) ((ir&0x0300)>>6)
1.84 #define FRN(ir) (FR[(ir&0x0F00)>>8])
1.85 #define FRM(ir) (FR[(ir&0x00F0)>>4])
1.86 #define FRNi(ir) (((uint32_t *)FR)[(ir&0x0F00)>>8])
1.87 @@ -202,8 +213,11 @@
1.88 #define FPULf *((float *)&sh4r.fpul)
1.89 #define FPULi (sh4r.fpul)
1.90
1.91 - if( SH4_INT_PENDING() ) sh4_accept_interrupt();
1.92 + if( SH4_INT_PENDING() )
1.93 + sh4_accept_interrupt();
1.94
1.95 + pc = sh4r.pc;
1.96 + ir = MEM_READ_WORD(pc);
1.97 sh4r.icount++;
1.98
1.99 switch( (ir&0xF000)>>12 ) {
1.100 @@ -242,16 +256,32 @@
1.101 switch( (ir&0x00F0)>>4 ) {
1.102 case 0: /* BSRF Rn */
1.103 CHECKDEST( pc + 4 + RN(ir) );
1.104 + CHECKSLOTILLEGAL();
1.105 + sh4r.in_delay_slot = 1;
1.106 sh4r.pr = sh4r.pc + 4;
1.107 sh4r.pc = sh4r.new_pc;
1.108 sh4r.new_pc = pc + 4 + RN(ir);
1.109 return;
1.110 case 2: /* BRAF Rn */
1.111 CHECKDEST( pc + 4 + RN(ir) );
1.112 + CHECKSLOTILLEGAL();
1.113 + sh4r.in_delay_slot = 1;
1.114 sh4r.pc = sh4r.new_pc;
1.115 sh4r.new_pc = pc + 4 + RN(ir);
1.116 return;
1.117 case 8: /* PREF [Rn] */
1.118 + tmp = RN(ir);
1.119 + if( (tmp & 0xFC000000) == 0xE0000000 ) {
1.120 + /* Store queue operation */
1.121 + int queue = (tmp&0x20)>>2;
1.122 + int32_t *src = &sh4r.store_queue[queue];
1.123 + uint32_t hi = (MMIO_READ( MMU, (queue == 0 ? QACR0 : QACR1) ) & 0x1C) << 24;
1.124 + uint32_t target = tmp&0x03FFFFE0 | hi;
1.125 + mem_copy_to_sh4( target, src, 32 );
1.126 + WARN( "Executed SQ%c => %08X",
1.127 + (queue == 0 ? '0' : '1'), target );
1.128 + }
1.129 + break;
1.130 case 9: /* OCBI [Rn] */
1.131 case 10:/* OCBP [Rn] */
1.132 case 11:/* OCBWB [Rn] */
1.133 @@ -272,7 +302,7 @@
1.134 MEM_WRITE_LONG( R0 + RN(ir), RM(ir) );
1.135 break;
1.136 case 7: /* MUL.L Rm, Rn */
1.137 - sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000) |
1.138 + sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
1.139 (RM(ir) * RN(ir));
1.140 break;
1.141 case 8:
1.142 @@ -338,6 +368,8 @@
1.143 switch( (ir&0x0FF0)>>4 ) {
1.144 case 0: /* RTS */
1.145 CHECKDEST( sh4r.pr );
1.146 + CHECKSLOTILLEGAL();
1.147 + sh4r.in_delay_slot = 1;
1.148 sh4r.pc = sh4r.new_pc;
1.149 sh4r.new_pc = sh4r.pr;
1.150 return;
1.151 @@ -347,9 +379,12 @@
1.152 case 2: /* RTE */
1.153 CHECKPRIV();
1.154 CHECKDEST( sh4r.spc );
1.155 + CHECKSLOTILLEGAL();
1.156 + sh4r.in_delay_slot = 1;
1.157 sh4r.pc = sh4r.new_pc;
1.158 sh4r.new_pc = sh4r.spc;
1.159 sh4_load_sr( sh4r.ssr );
1.160 + WARN( "RTE => %08X", sh4r.new_pc );
1.161 return;
1.162 default:UNDEF(ir);
1.163 }
1.164 @@ -369,12 +404,12 @@
1.165 if( sh4r.s ) {
1.166 /* 48-bit Saturation. Yuch */
1.167 tmpl += SIGNEXT48(sh4r.mac);
1.168 - if( tmpl < 0xFFFF800000000000 )
1.169 - tmpl = 0xFFFF800000000000;
1.170 - else if( tmpl > 0x00007FFFFFFFFFFF )
1.171 - tmpl = 0x00007FFFFFFFFFFF;
1.172 - sh4r.mac = (sh4r.mac&0xFFFF000000000000) |
1.173 - (tmpl&0x0000FFFFFFFFFFFF);
1.174 + if( tmpl < 0xFFFF800000000000LL )
1.175 + tmpl = 0xFFFF800000000000LL;
1.176 + else if( tmpl > 0x00007FFFFFFFFFFFLL )
1.177 + tmpl = 0x00007FFFFFFFFFFFLL;
1.178 + sh4r.mac = (sh4r.mac&0xFFFF000000000000LL) |
1.179 + (tmpl&0x0000FFFFFFFFFFFFLL);
1.180 } else sh4r.mac = tmpl;
1.181
1.182 RM(ir) += 4;
1.183 @@ -440,11 +475,11 @@
1.184 RN(ir) = (RN(ir)>>16) | (RM(ir)<<16);
1.185 break;
1.186 case 14:/* MULU.W Rm, Rn */
1.187 - sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000) |
1.188 + sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
1.189 (uint32_t)((RM(ir)&0xFFFF) * (RN(ir)&0xFFFF));
1.190 break;
1.191 case 15:/* MULS.W Rm, Rn */
1.192 - sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000) |
1.193 + sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
1.194 (uint32_t)(SIGNEXT32(RM(ir)&0xFFFF) * SIGNEXT32(RN(ir)&0xFFFF));
1.195 break;
1.196 }
1.197 @@ -571,6 +606,8 @@
1.198 break;
1.199 case 0x0B: /* JSR [Rn] */
1.200 CHECKDEST( RN(ir) );
1.201 + CHECKSLOTILLEGAL();
1.202 + sh4r.in_delay_slot = 1;
1.203 sh4r.pc = sh4r.new_pc;
1.204 sh4r.new_pc = RN(ir);
1.205 sh4r.pr = pc + 4;
1.206 @@ -598,7 +635,7 @@
1.207 sh4r.t = ( ((int32_t)RN(ir)) > 0 ? 1 : 0 );
1.208 break;
1.209 case 0x16: /* LDS.L [Rn++], MACL */
1.210 - sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000) |
1.211 + sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
1.212 (uint64_t)((uint32_t)MEM_READ_LONG(RN(ir)));
1.213 RN(ir) += 4;
1.214 break;
1.215 @@ -613,7 +650,7 @@
1.216 RN(ir) >>= 8;
1.217 break;
1.218 case 0x1A: /* LDS Rn, MACL */
1.219 - sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000) |
1.220 + sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
1.221 (uint64_t)((uint32_t)(RN(ir)));
1.222 break;
1.223 case 0x1B: /* TAS.B [Rn] */
1.224 @@ -639,7 +676,7 @@
1.225 case 0x23: /* STC.L VBR, [--Rn] */
1.226 CHECKPRIV();
1.227 RN(ir) -= 4;
1.228 - MEM_WRITE_LONG( RN(ir), sh4r.pr );
1.229 + MEM_WRITE_LONG( RN(ir), sh4r.vbr );
1.230 break;
1.231 case 0x24: /* ROTCL Rn */
1.232 tmp = RN(ir) >> 31;
1.233 @@ -673,6 +710,8 @@
1.234 break;
1.235 case 0x2B: /* JMP [Rn] */
1.236 CHECKDEST( RN(ir) );
1.237 + CHECKSLOTILLEGAL();
1.238 + sh4r.in_delay_slot = 1;
1.239 sh4r.pc = sh4r.new_pc;
1.240 sh4r.new_pc = RN(ir);
1.241 return;
1.242 @@ -876,6 +915,7 @@
1.243 sh4r.t = ( R0 == IMM8(ir) ? 1 : 0 );
1.244 break;
1.245 case 9: /* BT disp8 */
1.246 + CHECKSLOTILLEGAL()
1.247 if( sh4r.t ) {
1.248 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
1.249 sh4r.pc += (PCDISP8(ir)<<1) + 4;
1.250 @@ -884,6 +924,7 @@
1.251 }
1.252 break;
1.253 case 11:/* BF disp8 */
1.254 + CHECKSLOTILLEGAL()
1.255 if( !sh4r.t ) {
1.256 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
1.257 sh4r.pc += (PCDISP8(ir)<<1) + 4;
1.258 @@ -892,16 +933,21 @@
1.259 }
1.260 break;
1.261 case 13:/* BT/S disp8 */
1.262 + CHECKSLOTILLEGAL()
1.263 if( sh4r.t ) {
1.264 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
1.265 + sh4r.in_delay_slot = 1;
1.266 sh4r.pc = sh4r.new_pc;
1.267 sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
1.268 + sh4r.in_delay_slot = 1;
1.269 return;
1.270 }
1.271 break;
1.272 case 15:/* BF/S disp8 */
1.273 + CHECKSLOTILLEGAL()
1.274 if( !sh4r.t ) {
1.275 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
1.276 + sh4r.in_delay_slot = 1;
1.277 sh4r.pc = sh4r.new_pc;
1.278 sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
1.279 return;
1.280 @@ -916,13 +962,17 @@
1.281 break;
1.282 case 10:/* 1010dddddddddddd */
1.283 /* BRA disp12 */
1.284 - CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 );
1.285 + CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 )
1.286 + CHECKSLOTILLEGAL()
1.287 + sh4r.in_delay_slot = 1;
1.288 sh4r.pc = sh4r.new_pc;
1.289 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
1.290 return;
1.291 case 11:/* 1011dddddddddddd */
1.292 /* BSR disp12 */
1.293 CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 )
1.294 + CHECKSLOTILLEGAL()
1.295 + sh4r.in_delay_slot = 1;
1.296 sh4r.pr = pc + 4;
1.297 sh4r.pc = sh4r.new_pc;
1.298 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
1.299 @@ -939,6 +989,8 @@
1.300 MEM_WRITE_LONG( sh4r.gbr + (DISP8(ir)<<2), R0 );
1.301 break;
1.302 case 3: /* TRAPA imm8 */
1.303 + CHECKSLOTILLEGAL()
1.304 + sh4r.in_delay_slot = 1;
1.305 MMIO_WRITE( MMU, TRA, UIMM8(ir) );
1.306 sh4r.pc = sh4r.new_pc; /* RAISE ends the instruction */
1.307 sh4r.new_pc += 2;
1.308 @@ -1065,6 +1117,9 @@
1.309 case 6: /* FSQRT FRn */
1.310 FRN(ir) = sqrtf(FRN(ir));
1.311 break;
1.312 + case 7: /* FSRRA FRn */
1.313 + FRN(ir) = 1.0/sqrtf(FRN(ir));
1.314 + break;
1.315 case 8: /* FLDI0 FRn */
1.316 FRN(ir) = 0.0;
1.317 break;
1.318 @@ -1081,20 +1136,55 @@
1.319 FPULf = (float)DRN(ir);
1.320 else UNDEF(ir);
1.321 break;
1.322 - case 14:/* FIPR FVn, FVn */
1.323 - UNIMP(ir);
1.324 + case 14:/* FIPR FVm, FVn */
1.325 + /* FIXME: This is not going to be entirely accurate
1.326 + * as the SH4 instruction is less precise. Also
1.327 + * need to check for 0s and infinities.
1.328 + */
1.329 + {
1.330 + float *fr_bank = FR;
1.331 + int tmp2 = FVN(ir);
1.332 + tmp = FVM(ir);
1.333 + fr_bank[tmp2+3] = fr_bank[tmp]*fr_bank[tmp2] +
1.334 + fr_bank[tmp+1]*fr_bank[tmp2+1] +
1.335 + fr_bank[tmp+2]*fr_bank[tmp2+2] +
1.336 + fr_bank[tmp+3]*fr_bank[tmp2+3];
1.337 break;
1.338 + }
1.339 case 15:
1.340 - if( FVM(ir) == 1 )
1.341 - /* FTRV XMTRX,FVn */
1.342 - UNIMP(ir);
1.343 - else if( ir == 0xFBFD )
1.344 - /* FRCHG */
1.345 + if( (ir&0x0300) == 0x0100 ) { /* FTRV XMTRX,FVn */
1.346 + float *fvout = FR+FVN(ir);
1.347 + float *xm = XF;
1.348 + float fv[4] = { fvout[0], fvout[1], fvout[2], fvout[3] };
1.349 + fvout[0] = xm[0] * fv[0] + xm[4]*fv[1] +
1.350 + xm[8]*fv[2] + xm[12]*fv[3];
1.351 + fvout[1] = xm[1] * fv[0] + xm[5]*fv[1] +
1.352 + xm[9]*fv[2] + xm[13]*fv[3];
1.353 + fvout[2] = xm[2] * fv[0] + xm[6]*fv[1] +
1.354 + xm[10]*fv[2] + xm[14]*fv[3];
1.355 + fvout[3] = xm[3] * fv[0] + xm[7]*fv[1] +
1.356 + xm[11]*fv[2] + xm[15]*fv[3];
1.357 + break;
1.358 + }
1.359 + else if( (ir&0x0100) == 0 ) { /* FSCA FPUL, DRn */
1.360 + float angle = (((float)(short)(FPULi>>16)) +
1.361 + ((float)(FPULi&16)/65536.0)) *
1.362 + 2 * M_PI;
1.363 + int reg = FRNn(ir);
1.364 + FR[reg] = sinf(angle);
1.365 + FR[reg+1] = cosf(angle);
1.366 + break;
1.367 + }
1.368 + else if( ir == 0xFBFD ) {
1.369 + /* FRCHG */
1.370 sh4r.fpscr ^= FPSCR_FR;
1.371 - else if( ir == 0xF3FD )
1.372 + break;
1.373 + }
1.374 + else if( ir == 0xF3FD ) {
1.375 + /* FSCHG */
1.376 sh4r.fpscr ^= FPSCR_SZ;
1.377 - /* FSCHG */
1.378 - break;
1.379 + break;
1.380 + }
1.381 default: UNDEF(ir);
1.382 }
1.383 break;
1.384 @@ -1107,4 +1197,5 @@
1.385 }
1.386 sh4r.pc = sh4r.new_pc;
1.387 sh4r.new_pc += 2;
1.388 + sh4r.in_delay_slot = 0;
1.389 }
.