filename | src/sh4/sh4core.c |
changeset | 1:eea311cfd33e |
next | 2:42349f6ea216 |
author | nkeynes |
date | Sat Mar 13 00:03:32 2004 +0000 (18 years ago) |
permissions | -rw-r--r-- |
last change | This commit was generated by cvs2svn to compensate for changes in r2, which included commits to RCS files with non-trunk default branches. |
view | annotate | diff | log | raw |
1 #include <math.h>
2 #include "dream.h"
3 #include "sh4core.h"
4 #include "sh4mmio.h"
5 #include "mem.h"
6 #include "intc.h"
8 struct sh4_registers sh4r;
10 static int running = 0;
12 void sh4_init(void)
13 {
14 register_io_regions( mmio_list_sh4mmio );
15 }
17 void sh4_reset(void)
18 {
19 sh4r.pc = 0xA0000000;
20 sh4r.new_pc= 0xA0000002;
21 sh4r.vbr = 0x00000000;
22 sh4r.fpscr = 0x00040001;
23 sh4r.sr = 0x700000F0;
24 sh4r.icount= 0;
25 /* Everything else is undefined anyway, so don't bother setting it */
26 intc_reset();
27 }
29 void sh4_set_pc( int pc )
30 {
31 sh4r.pc = pc;
32 sh4r.new_pc = pc+2;
33 }
35 void sh4_stop(void)
36 {
37 running = 0;
38 }
40 void sh4_run(void)
41 {
42 running = 1;
43 while( running ) {
44 sh4_execute_instruction();
45 }
46 }
48 void sh4_runfor(uint32_t count)
49 {
50 running = 1;
51 while( running && count--) {
52 sh4_execute_instruction();
53 }
54 }
56 int sh4_isrunning(void)
57 {
58 return running;
59 }
61 void sh4_runto( uint32_t target_pc, uint32_t count )
62 {
63 running = 1;
64 do {
65 sh4_execute_instruction();
66 } while( running && sh4r.pc != target_pc && count-- );
67 if( count == 0 )
68 running = 0;
69 }
71 #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)
72 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_stop(); return; }while(0)
74 #define RAISE( x, v ) do{ \
75 if( sh4r.vbr == 0 ) { \
76 ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \
77 sh4_stop(); \
78 } else { \
79 sh4r.spc = sh4r.pc + 2; \
80 sh4r.ssr = sh4_read_sr(); \
81 sh4r.sgr = sh4r.r[15]; \
82 MMIO_WRITE(MMU,EXPEVT,x); \
83 sh4r.pc = sh4r.vbr + v; \
84 sh4r.new_pc = sh4r.pc + 2; \
85 sh4_load_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
86 } \
87 return; } while(0)
89 #define MEM_READ_BYTE( addr ) mem_read_byte(addr)
90 #define MEM_READ_WORD( addr ) mem_read_word(addr)
91 #define MEM_READ_LONG( addr ) mem_read_long(addr)
92 #define MEM_WRITE_BYTE( addr, val ) mem_write_byte(addr, val)
93 #define MEM_WRITE_WORD( addr, val ) mem_write_word(addr, val)
94 #define MEM_WRITE_LONG( addr, val ) mem_write_long(addr, val)
96 #define MEM_FP_READ( addr, reg ) if( IS_FPU_DOUBLESIZE() ) { \
97 ((uint32_t *)FR)[(reg)&0xE0] = mem_read_long(addr); \
98 ((uint32_t *)FR)[(reg)|1] = mem_read_long(addr+4); \
99 } else ((uint32_t *)FR)[reg] = mem_read_long(addr)
101 #define MEM_FP_WRITE( addr, reg ) if( IS_FPU_DOUBLESIZE() ) { \
102 mem_write_long( addr, ((uint32_t *)FR)[(reg)&0xE0] ); \
103 mem_write_long( addr+4, ((uint32_t *)FR)[(reg)|1] ); \
104 } else mem_write_long( addr, ((uint32_t *)FR)[reg] )
106 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
108 #define EXC_POWER_RESET 0x000 /* vector special */
109 #define EXC_MANUAL_RESET 0x020
110 #define EXC_ILLEGAL 0x180
111 #define EXV_ILLEGAL 0x100
112 #define EXC_TRAP 0x160
113 #define EXV_TRAP 0x100
114 #define EXC_FPDISABLE 0x800
115 #define EXV_FPDISABLE 0x100
117 #define CHECK( x, c, v ) if( !x ) RAISE( c, v )
118 #define CHECKPRIV() CHECK( IS_SH4_PRIVMODE(), EXC_ILLEGAL, EXV_ILLEGAL )
119 #define CHECKFPUEN() CHECK( IS_FPU_ENABLED(), EXC_FPDISABLE, EXV_FPDISABLE )
120 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_stop(); return; }
122 static void sh4_switch_banks( )
123 {
124 uint32_t tmp[8];
126 memcpy( tmp, sh4r.r, sizeof(uint32_t)*8 );
127 memcpy( sh4r.r, sh4r.r_bank, sizeof(uint32_t)*8 );
128 memcpy( sh4r.r_bank, tmp, sizeof(uint32_t)*8 );
129 }
131 static void sh4_load_sr( uint32_t newval )
132 {
133 if( (newval ^ sh4r.sr) & SR_RB )
134 sh4_switch_banks();
135 sh4r.sr = newval;
136 sh4r.t = (newval&SR_T) ? 1 : 0;
137 sh4r.s = (newval&SR_S) ? 1 : 0;
138 sh4r.m = (newval&SR_M) ? 1 : 0;
139 sh4r.q = (newval&SR_Q) ? 1 : 0;
140 intc_mask_changed();
141 }
143 static uint32_t sh4_read_sr( void )
144 {
145 /* synchronize sh4r.sr with the various bitflags */
146 sh4r.sr &= SR_MQSTMASK;
147 if( sh4r.t ) sh4r.sr |= SR_T;
148 if( sh4r.s ) sh4r.sr |= SR_S;
149 if( sh4r.m ) sh4r.sr |= SR_M;
150 if( sh4r.q ) sh4r.sr |= SR_Q;
151 return sh4r.sr;
152 }
153 /* function for external use */
154 void sh4_raise_exception( int code, int vector )
155 {
156 RAISE(code, vector);
157 }
159 static void sh4_accept_interrupt( void )
160 {
161 uint32_t code = intc_accept_interrupt();
163 sh4r.ssr = sh4_read_sr();
164 sh4r.spc = sh4r.pc;
165 sh4r.sgr = sh4r.r[15];
166 sh4_load_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
167 MMIO_WRITE( MMU, INTEVT, code );
168 sh4r.pc = sh4r.vbr + 0x600;
169 sh4r.new_pc = sh4r.pc + 2;
170 }
172 void sh4_execute_instruction( void )
173 {
174 int pc = sh4r.pc;
175 unsigned short ir = MEM_READ_WORD(pc);
176 uint32_t tmp;
177 uint64_t tmpl;
179 #define R0 sh4r.r[0]
180 #define FR0 (FR[0])
181 #define RN(ir) sh4r.r[(ir&0x0F00)>>8]
182 #define RN_BANK(ir) sh4r.r_bank[(ir&0x0070)>>4]
183 #define RM(ir) sh4r.r[(ir&0x00F0)>>4]
184 #define DISP4(ir) (ir&0x000F) /* 4-bit displacements are *NOT* sign-extended */
185 #define DISP8(ir) (ir&0x00FF)
186 #define PCDISP8(ir) SIGNEXT8(ir&0x00FF)
187 #define IMM8(ir) SIGNEXT8(ir&0x00FF)
188 #define UIMM8(ir) (ir&0x00FF) /* Unsigned immmediate */
189 #define DISP12(ir) SIGNEXT12(ir&0x0FFF)
190 #define FVN(ir) ((ir&0x0C00)
191 #define FVM(ir) ((ir&0x0300)>>8)
192 #define FRN(ir) (FR[(ir&0x0F00)>>8])
193 #define FRM(ir) (FR[(ir&0x00F0)>>4])
194 #define FRNi(ir) (((uint32_t *)FR)[(ir&0x0F00)>>8])
195 #define FRMi(ir) (((uint32_t *)FR)[(ir&0x00F0)>>4])
196 #define DRN(ir) (((double *)FR)[(ir&0x0E00)>>9])
197 #define DRM(ir) (((double *)FR)[(ir&0x00E0)>>5])
198 #define DRNi(ir) (((uint64_t *)FR)[(ir&0x0E00)>>9])
199 #define DRMi(ir) (((uint64_t *)FR)[(ir&0x00E0)>>5])
200 #define FRNn(ir) ((ir&0x0F00)>>8)
201 #define FRMn(ir) ((ir&0x00F0)>>4)
202 #define FPULf *((float *)&sh4r.fpul)
203 #define FPULi (sh4r.fpul)
205 if( SH4_INT_PENDING() ) sh4_accept_interrupt();
207 sh4r.icount++;
209 switch( (ir&0xF000)>>12 ) {
210 case 0: /* 0000nnnnmmmmxxxx */
211 switch( ir&0x000F ) {
212 case 2:
213 switch( (ir&0x00F0)>>4 ) {
214 case 0: /* STC SR, Rn */
215 CHECKPRIV();
216 RN(ir) = sh4_read_sr();
217 break;
218 case 1: /* STC GBR, Rn */
219 RN(ir) = sh4r.gbr;
220 break;
221 case 2: /* STC VBR, Rn */
222 CHECKPRIV();
223 RN(ir) = sh4r.vbr;
224 break;
225 case 3: /* STC SSR, Rn */
226 CHECKPRIV();
227 RN(ir) = sh4r.ssr;
228 break;
229 case 4: /* STC SPC, Rn */
230 CHECKPRIV();
231 RN(ir) = sh4r.spc;
232 break;
233 case 8: case 9: case 10: case 11: case 12: case 13:
234 case 14: case 15:/* STC Rm_bank, Rn */
235 CHECKPRIV();
236 RN(ir) = RN_BANK(ir);
237 break;
238 default: UNDEF(ir);
239 }
240 break;
241 case 3:
242 switch( (ir&0x00F0)>>4 ) {
243 case 0: /* BSRF Rn */
244 CHECKDEST( pc + 4 + RN(ir) );
245 sh4r.pr = sh4r.pc + 4;
246 sh4r.pc = sh4r.new_pc;
247 sh4r.new_pc = pc + 4 + RN(ir);
248 return;
249 case 2: /* BRAF Rn */
250 CHECKDEST( pc + 4 + RN(ir) );
251 sh4r.pc = sh4r.new_pc;
252 sh4r.new_pc = pc + 4 + RN(ir);
253 return;
254 case 8: /* PREF [Rn] */
255 case 9: /* OCBI [Rn] */
256 case 10:/* OCBP [Rn] */
257 case 11:/* OCBWB [Rn] */
258 /* anything? */
259 break;
260 case 12:/* MOVCA.L R0, [Rn] */
261 UNIMP(ir);
262 default: UNDEF(ir);
263 }
264 break;
265 case 4: /* MOV.B Rm, [R0 + Rn] */
266 MEM_WRITE_BYTE( R0 + RN(ir), RM(ir) );
267 break;
268 case 5: /* MOV.W Rm, [R0 + Rn] */
269 MEM_WRITE_WORD( R0 + RN(ir), RM(ir) );
270 break;
271 case 6: /* MOV.L Rm, [R0 + Rn] */
272 MEM_WRITE_LONG( R0 + RN(ir), RM(ir) );
273 break;
274 case 7: /* MUL.L Rm, Rn */
275 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000) |
276 (RM(ir) * RN(ir));
277 break;
278 case 8:
279 switch( (ir&0x0FF0)>>4 ) {
280 case 0: /* CLRT */
281 sh4r.t = 0;
282 break;
283 case 1: /* SETT */
284 sh4r.t = 1;
285 break;
286 case 2: /* CLRMAC */
287 sh4r.mac = 0;
288 break;
289 case 3: /* LDTLB */
290 break;
291 case 4: /* CLRS */
292 sh4r.s = 0;
293 break;
294 case 5: /* SETS */
295 sh4r.s = 1;
296 break;
297 default: UNDEF(ir);
298 }
299 break;
300 case 9:
301 if( (ir&0x00F0) == 0x20 ) /* MOVT Rn */
302 RN(ir) = sh4r.t;
303 else if( ir == 0x0019 ) /* DIV0U */
304 sh4r.m = sh4r.q = sh4r.t = 0;
305 else if( ir == 0x0009 )
306 /* NOP */;
307 else UNDEF(ir);
308 break;
309 case 10:
310 switch( (ir&0x00F0) >> 4 ) {
311 case 0: /* STS MACH, Rn */
312 RN(ir) = sh4r.mac >> 32;
313 break;
314 case 1: /* STS MACL, Rn */
315 RN(ir) = (uint32_t)sh4r.mac;
316 break;
317 case 2: /* STS PR, Rn */
318 RN(ir) = sh4r.pr;
319 break;
320 case 3: /* STC SGR, Rn */
321 CHECKPRIV();
322 RN(ir) = sh4r.sgr;
323 break;
324 case 5:/* STS FPUL, Rn */
325 RN(ir) = sh4r.fpul;
326 break;
327 case 6: /* STS FPSCR, Rn */
328 RN(ir) = sh4r.fpscr;
329 break;
330 case 15:/* STC DBR, Rn */
331 CHECKPRIV();
332 RN(ir) = sh4r.dbr;
333 break;
334 default: UNDEF(ir);
335 }
336 break;
337 case 11:
338 switch( (ir&0x0FF0)>>4 ) {
339 case 0: /* RTS */
340 CHECKDEST( sh4r.pr );
341 sh4r.pc = sh4r.new_pc;
342 sh4r.new_pc = sh4r.pr;
343 return;
344 case 1: /* SLEEP */
345 running = 0;
346 break;
347 case 2: /* RTE */
348 CHECKPRIV();
349 CHECKDEST( sh4r.spc );
350 sh4r.pc = sh4r.new_pc;
351 sh4r.new_pc = sh4r.spc;
352 sh4_load_sr( sh4r.ssr );
353 return;
354 default:UNDEF(ir);
355 }
356 break;
357 case 12:/* MOV.B [R0+R%d], R%d */
358 RN(ir) = MEM_READ_BYTE( R0 + RM(ir) );
359 break;
360 case 13:/* MOV.W [R0+R%d], R%d */
361 RN(ir) = MEM_READ_WORD( R0 + RM(ir) );
362 break;
363 case 14:/* MOV.L [R0+R%d], R%d */
364 RN(ir) = MEM_READ_LONG( R0 + RM(ir) );
365 break;
366 case 15:/* MAC.L [Rm++], [Rn++] */
367 tmpl = ( SIGNEXT32(MEM_READ_LONG(RM(ir))) *
368 SIGNEXT32(MEM_READ_LONG(RN(ir))) );
369 if( sh4r.s ) {
370 /* 48-bit Saturation. Yuch */
371 tmpl += SIGNEXT48(sh4r.mac);
372 if( tmpl < 0xFFFF800000000000 )
373 tmpl = 0xFFFF800000000000;
374 else if( tmpl > 0x00007FFFFFFFFFFF )
375 tmpl = 0x00007FFFFFFFFFFF;
376 sh4r.mac = (sh4r.mac&0xFFFF000000000000) |
377 (tmpl&0x0000FFFFFFFFFFFF);
378 } else sh4r.mac = tmpl;
380 RM(ir) += 4;
381 RN(ir) += 4;
383 break;
384 default: UNDEF(ir);
385 }
386 break;
387 case 1: /* 0001nnnnmmmmdddd */
388 /* MOV.L Rm, [Rn + disp4*4] */
389 MEM_WRITE_LONG( RN(ir) + (DISP4(ir)<<2), RM(ir) );
390 break;
391 case 2: /* 0010nnnnmmmmxxxx */
392 switch( ir&0x000F ) {
393 case 0: /* MOV.B Rm, [Rn] */
394 MEM_WRITE_BYTE( RN(ir), RM(ir) );
395 break;
396 case 1: /* MOV.W Rm, [Rn] */
397 MEM_WRITE_WORD( RN(ir), RM(ir) );
398 break;
399 case 2: /* MOV.L Rm, [Rn] */
400 MEM_WRITE_LONG( RN(ir), RM(ir) );
401 break;
402 case 3: UNDEF(ir);
403 break;
404 case 4: /* MOV.B Rm, [--Rn] */
405 RN(ir) --;
406 MEM_WRITE_BYTE( RN(ir), RM(ir) );
407 break;
408 case 5: /* MOV.W Rm, [--Rn] */
409 RN(ir) -= 2;
410 MEM_WRITE_WORD( RN(ir), RM(ir) );
411 break;
412 case 6: /* MOV.L Rm, [--Rn] */
413 RN(ir) -= 4;
414 MEM_WRITE_LONG( RN(ir), RM(ir) );
415 break;
416 case 7: /* DIV0S Rm, Rn */
417 sh4r.q = RN(ir)>>31;
418 sh4r.m = RM(ir)>>31;
419 sh4r.t = sh4r.q ^ sh4r.m;
420 break;
421 case 8: /* TST Rm, Rn */
422 sh4r.t = (RN(ir)&RM(ir) ? 0 : 1);
423 break;
424 case 9: /* AND Rm, Rn */
425 RN(ir) &= RM(ir);
426 break;
427 case 10:/* XOR Rm, Rn */
428 RN(ir) ^= RM(ir);
429 break;
430 case 11:/* OR Rm, Rn */
431 RN(ir) |= RM(ir);
432 break;
433 case 12:/* CMP/STR Rm, Rn */
434 /* set T = 1 if any byte in RM & RN is the same */
435 tmp = RM(ir) ^ RN(ir);
436 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
437 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
438 break;
439 case 13:/* XTRCT Rm, Rn */
440 RN(ir) = (RN(ir)>>16) | (RM(ir)<<16);
441 break;
442 case 14:/* MULU.W Rm, Rn */
443 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000) |
444 (uint32_t)((RM(ir)&0xFFFF) * (RN(ir)&0xFFFF));
445 break;
446 case 15:/* MULS.W Rm, Rn */
447 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000) |
448 (uint32_t)(SIGNEXT32(RM(ir)&0xFFFF) * SIGNEXT32(RN(ir)&0xFFFF));
449 break;
450 }
451 break;
452 case 3: /* 0011nnnnmmmmxxxx */
453 switch( ir&0x000F ) {
454 case 0: /* CMP/EQ Rm, Rn */
455 sh4r.t = ( RM(ir) == RN(ir) ? 1 : 0 );
456 break;
457 case 2: /* CMP/HS Rm, Rn */
458 sh4r.t = ( RN(ir) >= RM(ir) ? 1 : 0 );
459 break;
460 case 3: /* CMP/GE Rm, Rn */
461 sh4r.t = ( ((int32_t)RN(ir)) >= ((int32_t)RM(ir)) ? 1 : 0 );
462 break;
463 case 4: { /* DIV1 Rm, Rn */
464 /* This is just from the sh4p manual with some
465 * simplifications (someone want to check it's correct? :)
466 * Why they couldn't just provide a real DIV instruction...
467 * Please oh please let the translator batch these things
468 * up into a single DIV... */
469 uint32_t tmp0, tmp1, tmp2, dir;
471 dir = sh4r.q ^ sh4r.m;
472 sh4r.q = (RN(ir) >> 31);
473 tmp2 = RM(ir);
474 RN(ir) = (RN(ir) << 1) | sh4r.t;
475 tmp0 = RN(ir);
476 if( dir ) {
477 RN(ir) += tmp2;
478 tmp1 = (RN(ir)<tmp0 ? 1 : 0 );
479 } else {
480 RN(ir) -= tmp2;
481 tmp1 = (RN(ir)>tmp0 ? 1 : 0 );
482 }
483 sh4r.q ^= sh4r.m ^ tmp1;
484 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
485 break; }
486 case 5: /* DMULU.L Rm, Rn */
487 sh4r.mac = ((uint64_t)RM(ir)) * ((uint64_t)RN(ir));
488 break;
489 case 6: /* CMP/HI Rm, Rn */
490 sh4r.t = ( RN(ir) > RM(ir) ? 1 : 0 );
491 break;
492 case 7: /* CMP/GT Rm, Rn */
493 sh4r.t = ( ((int32_t)RN(ir)) > ((int32_t)RM(ir)) ? 1 : 0 );
494 break;
495 case 8: /* SUB Rm, Rn */
496 RN(ir) -= RM(ir);
497 break;
498 case 10:/* SUBC Rm, Rn */
499 tmp = RN(ir);
500 RN(ir) = RN(ir) - RM(ir) - sh4r.t;
501 sh4r.t = (RN(ir) > tmp || (RN(ir) == tmp && sh4r.t == 1));
502 break;
503 case 11:/* SUBV Rm, Rn */
504 UNIMP(ir);
505 break;
506 case 12:/* ADD Rm, Rn */
507 RN(ir) += RM(ir);
508 break;
509 case 13:/* DMULS.L Rm, Rn */
510 sh4r.mac = SIGNEXT32(RM(ir)) * SIGNEXT32(RN(ir));
511 break;
512 case 14:/* ADDC Rm, Rn */
513 tmp = RN(ir);
514 RN(ir) += RM(ir) + sh4r.t;
515 sh4r.t = ( RN(ir) < tmp || (RN(ir) == tmp && sh4r.t != 0) ? 1 : 0 );
516 break;
517 case 15:/* ADDV Rm, Rn */
518 UNIMP(ir);
519 break;
520 default: UNDEF(ir);
521 }
522 break;
523 case 4: /* 0100nnnnxxxxxxxx */
524 switch( ir&0x00FF ) {
525 case 0x00: /* SHLL Rn */
526 sh4r.t = RN(ir) >> 31;
527 RN(ir) <<= 1;
528 break;
529 case 0x01: /* SHLR Rn */
530 sh4r.t = RN(ir) & 0x00000001;
531 RN(ir) >>= 1;
532 break;
533 case 0x02: /* STS.L MACH, [--Rn] */
534 RN(ir) -= 4;
535 MEM_WRITE_LONG( RN(ir), (sh4r.mac>>32) );
536 break;
537 case 0x03: /* STC.L SR, [--Rn] */
538 CHECKPRIV();
539 RN(ir) -= 4;
540 MEM_WRITE_LONG( RN(ir), sh4_read_sr() );
541 break;
542 case 0x04: /* ROTL Rn */
543 sh4r.t = RN(ir) >> 31;
544 RN(ir) <<= 1;
545 RN(ir) |= sh4r.t;
546 break;
547 case 0x05: /* ROTR Rn */
548 sh4r.t = RN(ir) & 0x00000001;
549 RN(ir) >>= 1;
550 RN(ir) |= (sh4r.t << 31);
551 break;
552 case 0x06: /* LDS.L [Rn++], MACH */
553 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
554 (((uint64_t)MEM_READ_LONG(RN(ir)))<<32);
555 RN(ir) += 4;
556 break;
557 case 0x07: /* LDC.L [Rn++], SR */
558 CHECKPRIV();
559 sh4_load_sr( MEM_READ_LONG(RN(ir)) );
560 RN(ir) +=4;
561 break;
562 case 0x08: /* SHLL2 Rn */
563 RN(ir) <<= 2;
564 break;
565 case 0x09: /* SHLR2 Rn */
566 RN(ir) >>= 2;
567 break;
568 case 0x0A: /* LDS Rn, MACH */
569 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
570 (((uint64_t)RN(ir))<<32);
571 break;
572 case 0x0B: /* JSR [Rn] */
573 CHECKDEST( RN(ir) );
574 sh4r.pc = sh4r.new_pc;
575 sh4r.new_pc = RN(ir);
576 sh4r.pr = pc + 4;
577 return;
578 case 0x0E: /* LDC Rn, SR */
579 CHECKPRIV();
580 sh4_load_sr( RN(ir) );
581 break;
582 case 0x10: /* DT Rn */
583 RN(ir) --;
584 sh4r.t = ( RN(ir) == 0 ? 1 : 0 );
585 break;
586 case 0x11: /* CMP/PZ Rn */
587 sh4r.t = ( ((int32_t)RN(ir)) >= 0 ? 1 : 0 );
588 break;
589 case 0x12: /* STS.L MACL, [--Rn] */
590 RN(ir) -= 4;
591 MEM_WRITE_LONG( RN(ir), (uint32_t)sh4r.mac );
592 break;
593 case 0x13: /* STC.L GBR, [--Rn] */
594 RN(ir) -= 4;
595 MEM_WRITE_LONG( RN(ir), sh4r.gbr );
596 break;
597 case 0x15: /* CMP/PL Rn */
598 sh4r.t = ( ((int32_t)RN(ir)) > 0 ? 1 : 0 );
599 break;
600 case 0x16: /* LDS.L [Rn++], MACL */
601 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000) |
602 (uint64_t)((uint32_t)MEM_READ_LONG(RN(ir)));
603 RN(ir) += 4;
604 break;
605 case 0x17: /* LDC.L [Rn++], GBR */
606 sh4r.gbr = MEM_READ_LONG(RN(ir));
607 RN(ir) +=4;
608 break;
609 case 0x18: /* SHLL8 Rn */
610 RN(ir) <<= 8;
611 break;
612 case 0x19: /* SHLR8 Rn */
613 RN(ir) >>= 8;
614 break;
615 case 0x1A: /* LDS Rn, MACL */
616 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000) |
617 (uint64_t)((uint32_t)(RN(ir)));
618 break;
619 case 0x1B: /* TAS.B [Rn] */
620 tmp = MEM_READ_BYTE( RN(ir) );
621 sh4r.t = ( tmp == 0 ? 1 : 0 );
622 MEM_WRITE_BYTE( RN(ir), tmp | 0x80 );
623 break;
624 case 0x1E: /* LDC Rn, GBR */
625 sh4r.gbr = RN(ir);
626 break;
627 case 0x20: /* SHAL Rn */
628 sh4r.t = RN(ir) >> 31;
629 RN(ir) <<= 1;
630 break;
631 case 0x21: /* SHAR Rn */
632 sh4r.t = RN(ir) & 0x00000001;
633 RN(ir) = ((int32_t)RN(ir)) >> 1;
634 break;
635 case 0x22: /* STS.L PR, [--Rn] */
636 RN(ir) -= 4;
637 MEM_WRITE_LONG( RN(ir), sh4r.pr );
638 break;
639 case 0x23: /* STC.L VBR, [--Rn] */
640 CHECKPRIV();
641 RN(ir) -= 4;
642 MEM_WRITE_LONG( RN(ir), sh4r.pr );
643 break;
644 case 0x24: /* ROTCL Rn */
645 tmp = RN(ir) >> 31;
646 RN(ir) <<= 1;
647 RN(ir) |= sh4r.t;
648 sh4r.t = tmp;
649 break;
650 case 0x25: /* ROTCR Rn */
651 tmp = RN(ir) & 0x00000001;
652 RN(ir) >>= 1;
653 RN(ir) |= (sh4r.t << 31 );
654 sh4r.t = tmp;
655 break;
656 case 0x26: /* LDS.L [Rn++], PR */
657 sh4r.pr = MEM_READ_LONG( RN(ir) );
658 RN(ir) += 4;
659 break;
660 case 0x27: /* LDC.L [Rn++], VBR */
661 CHECKPRIV();
662 sh4r.vbr = MEM_READ_LONG(RN(ir));
663 RN(ir) +=4;
664 break;
665 case 0x28: /* SHLL16 Rn */
666 RN(ir) <<= 16;
667 break;
668 case 0x29: /* SHLR16 Rn */
669 RN(ir) >>= 16;
670 break;
671 case 0x2A: /* LDS Rn, PR */
672 sh4r.pr = RN(ir);
673 break;
674 case 0x2B: /* JMP [Rn] */
675 CHECKDEST( RN(ir) );
676 sh4r.pc = sh4r.new_pc;
677 sh4r.new_pc = RN(ir);
678 return;
679 case 0x2E: /* LDC Rn, VBR */
680 CHECKPRIV();
681 sh4r.vbr = RN(ir);
682 break;
683 case 0x32: /* STC.L SGR, [--Rn] */
684 CHECKPRIV();
685 RN(ir) -= 4;
686 MEM_WRITE_LONG( RN(ir), sh4r.sgr );
687 break;
688 case 0x33: /* STC.L SSR, [--Rn] */
689 CHECKPRIV();
690 RN(ir) -= 4;
691 MEM_WRITE_LONG( RN(ir), sh4r.ssr );
692 break;
693 case 0x37: /* LDC.L [Rn++], SSR */
694 CHECKPRIV();
695 sh4r.ssr = MEM_READ_LONG(RN(ir));
696 RN(ir) +=4;
697 break;
698 case 0x3E: /* LDC Rn, SSR */
699 CHECKPRIV();
700 sh4r.ssr = RN(ir);
701 break;
702 case 0x43: /* STC.L SPC, [--Rn] */
703 CHECKPRIV();
704 RN(ir) -= 4;
705 MEM_WRITE_LONG( RN(ir), sh4r.spc );
706 break;
707 case 0x47: /* LDC.L [Rn++], SPC */
708 CHECKPRIV();
709 sh4r.spc = MEM_READ_LONG(RN(ir));
710 RN(ir) +=4;
711 break;
712 case 0x4E: /* LDC Rn, SPC */
713 CHECKPRIV();
714 sh4r.spc = RN(ir);
715 break;
716 case 0x52: /* STS.L FPUL, [--Rn] */
717 RN(ir) -= 4;
718 MEM_WRITE_LONG( RN(ir), sh4r.fpul );
719 break;
720 case 0x56: /* LDS.L [Rn++], FPUL */
721 sh4r.fpul = MEM_READ_LONG(RN(ir));
722 RN(ir) +=4;
723 break;
724 case 0x5A: /* LDS Rn, FPUL */
725 sh4r.fpul = RN(ir);
726 break;
727 case 0x62: /* STS.L FPSCR, [--Rn] */
728 RN(ir) -= 4;
729 MEM_WRITE_LONG( RN(ir), sh4r.fpscr );
730 break;
731 case 0x66: /* LDS.L [Rn++], FPSCR */
732 sh4r.fpscr = MEM_READ_LONG(RN(ir));
733 RN(ir) +=4;
734 break;
735 case 0x6A: /* LDS Rn, FPSCR */
736 sh4r.fpscr = RN(ir);
737 break;
738 case 0xF2: /* STC.L DBR, [--Rn] */
739 CHECKPRIV();
740 RN(ir) -= 4;
741 MEM_WRITE_LONG( RN(ir), sh4r.dbr );
742 break;
743 case 0xF6: /* LDC.L [Rn++], DBR */
744 CHECKPRIV();
745 sh4r.dbr = MEM_READ_LONG(RN(ir));
746 RN(ir) +=4;
747 break;
748 case 0xFA: /* LDC Rn, DBR */
749 CHECKPRIV();
750 sh4r.dbr = RN(ir);
751 break;
752 case 0x83: case 0x93: case 0xA3: case 0xB3: case 0xC3:
753 case 0xD3: case 0xE3: case 0xF3: /* STC.L Rn_BANK, [--Rn] */
754 CHECKPRIV();
755 RN(ir) -= 4;
756 MEM_WRITE_LONG( RN(ir), RN_BANK(ir) );
757 break;
758 case 0x87: case 0x97: case 0xA7: case 0xB7: case 0xC7:
759 case 0xD7: case 0xE7: case 0xF7: /* LDC.L [Rn++], Rn_BANK */
760 CHECKPRIV();
761 RN_BANK(ir) = MEM_READ_LONG( RN(ir) );
762 RN(ir) += 4;
763 break;
764 case 0x8E: case 0x9E: case 0xAE: case 0xBE: case 0xCE:
765 case 0xDE: case 0xEE: case 0xFE: /* LDC Rm, Rn_BANK */
766 CHECKPRIV();
767 RN_BANK(ir) = RM(ir);
768 break;
769 default:
770 if( (ir&0x000F) == 0x0F ) {
771 /* MAC.W [Rm++], [Rn++] */
772 tmp = SIGNEXT16(MEM_READ_WORD(RM(ir))) *
773 SIGNEXT16(MEM_READ_WORD(RN(ir)));
774 if( sh4r.s ) {
775 /* FIXME */
776 UNIMP(ir);
777 } else sh4r.mac += SIGNEXT32(tmp);
778 RM(ir) += 2;
779 RN(ir) += 2;
780 } else if( (ir&0x000F) == 0x0C ) {
781 /* SHAD Rm, Rn */
782 tmp = RM(ir);
783 if( (tmp & 0x80000000) == 0 ) RN(ir) <<= (tmp&0x1f);
784 else if( (tmp & 0x1F) == 0 ) ((int32_t)RN(ir)) >>=31;
785 else ((int32_t)RN(ir)) >>= (((~RM(ir)) & 0x1F)+1);
786 } else if( (ir&0x000F) == 0x0D ) {
787 /* SHLD Rm, Rn */
788 tmp = RM(ir);
789 if( (tmp & 0x80000000) == 0 ) RN(ir) <<= (tmp&0x1f);
790 else if( (tmp & 0x1F) == 0 ) RN(ir) = 0;
791 else RN(ir) >>= (((~tmp) & 0x1F)+1);
792 } else UNDEF(ir);
793 }
794 break;
795 case 5: /* 0101nnnnmmmmdddd */
796 /* MOV.L [Rm + disp4*4], Rn */
797 RN(ir) = MEM_READ_LONG( RM(ir) + (DISP4(ir)<<2) );
798 break;
799 case 6: /* 0110xxxxxxxxxxxx */
800 switch( ir&0x000f ) {
801 case 0: /* MOV.B [Rm], Rn */
802 RN(ir) = MEM_READ_BYTE( RM(ir) );
803 break;
804 case 1: /* MOV.W [Rm], Rn */
805 RN(ir) = MEM_READ_WORD( RM(ir) );
806 break;
807 case 2: /* MOV.L [Rm], Rn */
808 RN(ir) = MEM_READ_LONG( RM(ir) );
809 break;
810 case 3: /* MOV Rm, Rn */
811 RN(ir) = RM(ir);
812 break;
813 case 4: /* MOV.B [Rm++], Rn */
814 RN(ir) = MEM_READ_BYTE( RM(ir) );
815 RM(ir) ++;
816 break;
817 case 5: /* MOV.W [Rm++], Rn */
818 RN(ir) = MEM_READ_WORD( RM(ir) );
819 RM(ir) += 2;
820 break;
821 case 6: /* MOV.L [Rm++], Rn */
822 RN(ir) = MEM_READ_LONG( RM(ir) );
823 RM(ir) += 4;
824 break;
825 case 7: /* NOT Rm, Rn */
826 RN(ir) = ~RM(ir);
827 break;
828 case 8: /* SWAP.B Rm, Rn */
829 RN(ir) = (RM(ir)&0xFFFF0000) | ((RM(ir)&0x0000FF00)>>8) |
830 ((RM(ir)&0x000000FF)<<8);
831 break;
832 case 9: /* SWAP.W Rm, Rn */
833 RN(ir) = (RM(ir)>>16) | (RM(ir)<<16);
834 break;
835 case 10:/* NEGC Rm, Rn */
836 tmp = 0 - RM(ir);
837 RN(ir) = tmp - sh4r.t;
838 sh4r.t = ( 0<tmp || tmp<RN(ir) ? 1 : 0 );
839 break;
840 case 11:/* NEG Rm, Rn */
841 RN(ir) = 0 - RM(ir);
842 break;
843 case 12:/* EXTU.B Rm, Rn */
844 RN(ir) = RM(ir)&0x000000FF;
845 break;
846 case 13:/* EXTU.W Rm, Rn */
847 RN(ir) = RM(ir)&0x0000FFFF;
848 break;
849 case 14:/* EXTS.B Rm, Rn */
850 RN(ir) = SIGNEXT8( RM(ir)&0x000000FF );
851 break;
852 case 15:/* EXTS.W Rm, Rn */
853 RN(ir) = SIGNEXT16( RM(ir)&0x0000FFFF );
854 break;
855 }
856 break;
857 case 7: /* 0111nnnniiiiiiii */
858 /* ADD imm8, Rn */
859 RN(ir) += IMM8(ir);
860 break;
861 case 8: /* 1000xxxxxxxxxxxx */
862 switch( (ir&0x0F00) >> 8 ) {
863 case 0: /* MOV.B R0, [Rm + disp4] */
864 MEM_WRITE_BYTE( RM(ir) + DISP4(ir), R0 );
865 break;
866 case 1: /* MOV.W R0, [Rm + disp4*2] */
867 MEM_WRITE_WORD( RM(ir) + (DISP4(ir)<<1), R0 );
868 break;
869 case 4: /* MOV.B [Rm + disp4], R0 */
870 R0 = MEM_READ_BYTE( RM(ir) + DISP4(ir) );
871 break;
872 case 5: /* MOV.W [Rm + disp4*2], R0 */
873 R0 = MEM_READ_WORD( RM(ir) + (DISP4(ir)<<1) );
874 break;
875 case 8: /* CMP/EQ imm, R0 */
876 sh4r.t = ( R0 == IMM8(ir) ? 1 : 0 );
877 break;
878 case 9: /* BT disp8 */
879 if( sh4r.t ) {
880 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
881 sh4r.pc += (PCDISP8(ir)<<1) + 4;
882 sh4r.new_pc = sh4r.pc + 2;
883 return;
884 }
885 break;
886 case 11:/* BF disp8 */
887 if( !sh4r.t ) {
888 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
889 sh4r.pc += (PCDISP8(ir)<<1) + 4;
890 sh4r.new_pc = sh4r.pc + 2;
891 return;
892 }
893 break;
894 case 13:/* BT/S disp8 */
895 if( sh4r.t ) {
896 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
897 sh4r.pc = sh4r.new_pc;
898 sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
899 return;
900 }
901 break;
902 case 15:/* BF/S disp8 */
903 if( !sh4r.t ) {
904 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
905 sh4r.pc = sh4r.new_pc;
906 sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
907 return;
908 }
909 break;
910 default: UNDEF(ir);
911 }
912 break;
913 case 9: /* 1001xxxxxxxxxxxx */
914 /* MOV.W [disp8*2 + pc + 4], Rn */
915 RN(ir) = MEM_READ_WORD( pc + 4 + (DISP8(ir)<<1) );
916 break;
917 case 10:/* 1010dddddddddddd */
918 /* BRA disp12 */
919 CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 );
920 sh4r.pc = sh4r.new_pc;
921 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
922 return;
923 case 11:/* 1011dddddddddddd */
924 /* BSR disp12 */
925 CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 )
926 sh4r.pr = pc + 4;
927 sh4r.pc = sh4r.new_pc;
928 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
929 return;
930 case 12:/* 1100xxxxdddddddd */
931 switch( (ir&0x0F00)>>8 ) {
932 case 0: /* MOV.B R0, [GBR + disp8] */
933 MEM_WRITE_BYTE( sh4r.gbr + DISP8(ir), R0 );
934 break;
935 case 1: /* MOV.W R0, [GBR + disp8*2] */
936 MEM_WRITE_WORD( sh4r.gbr + (DISP8(ir)<<1), R0 );
937 break;
938 case 2: /*MOV.L R0, [GBR + disp8*4] */
939 MEM_WRITE_LONG( sh4r.gbr + (DISP8(ir)<<2), R0 );
940 break;
941 case 3: /* TRAPA imm8 */
942 MMIO_WRITE( MMU, TRA, UIMM8(ir) );
943 sh4r.pc = sh4r.new_pc; /* RAISE ends the instruction */
944 sh4r.new_pc += 2;
945 RAISE( EXC_TRAP, EXV_TRAP );
946 break;
947 case 4: /* MOV.B [GBR + disp8], R0 */
948 R0 = MEM_READ_BYTE( sh4r.gbr + DISP8(ir) );
949 break;
950 case 5: /* MOV.W [GBR + disp8*2], R0 */
951 R0 = MEM_READ_WORD( sh4r.gbr + (DISP8(ir)<<1) );
952 break;
953 case 6: /* MOV.L [GBR + disp8*4], R0 */
954 R0 = MEM_READ_LONG( sh4r.gbr + (DISP8(ir)<<2) );
955 break;
956 case 7: /* MOVA disp8 + pc&~3 + 4, R0 */
957 R0 = (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4;
958 break;
959 case 8: /* TST imm8, R0 */
960 sh4r.t = (R0 & UIMM8(ir) ? 0 : 1);
961 break;
962 case 9: /* AND imm8, R0 */
963 R0 &= UIMM8(ir);
964 break;
965 case 10:/* XOR imm8, R0 */
966 R0 ^= UIMM8(ir);
967 break;
968 case 11:/* OR imm8, R0 */
969 R0 |= UIMM8(ir);
970 break;
971 case 12:/* TST.B imm8, [R0+GBR] */
972 sh4r.t = ( MEM_READ_BYTE(R0 + sh4r.gbr) & UIMM8(ir) ? 0 : 1 );
973 break;
974 case 13:/* AND.B imm8, [R0+GBR] */
975 MEM_WRITE_BYTE( R0 + sh4r.gbr,
976 UIMM8(ir) & MEM_READ_BYTE(R0 + sh4r.gbr) );
977 break;
978 case 14:/* XOR.B imm8, [R0+GBR] */
979 MEM_WRITE_BYTE( R0 + sh4r.gbr,
980 UIMM8(ir) ^ MEM_READ_BYTE(R0 + sh4r.gbr) );
981 break;
982 case 15:/* OR.B imm8, [R0+GBR] */
983 MEM_WRITE_BYTE( R0 + sh4r.gbr,
984 UIMM8(ir) | MEM_READ_BYTE(R0 + sh4r.gbr) );
985 break;
986 }
987 break;
988 case 13:/* 1101nnnndddddddd */
989 /* MOV.L [disp8*4 + pc&~3 + 4], Rn */
990 RN(ir) = MEM_READ_LONG( (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4 );
991 break;
992 case 14:/* 1110nnnniiiiiiii */
993 /* MOV imm8, Rn */
994 RN(ir) = IMM8(ir);
995 break;
996 case 15:/* 1111xxxxxxxxxxxx */
997 CHECKFPUEN();
998 switch( ir&0x000F ) {
999 case 0: /* FADD FRm, FRn */
1000 FRN(ir) += FRM(ir);
1001 break;
1002 case 1: /* FSUB FRm, FRn */
1003 FRN(ir) -= FRM(ir);
1004 break;
1005 case 2: /* FMUL FRm, FRn */
1006 FRN(ir) = FRN(ir) * FRM(ir);
1007 break;
1008 case 3: /* FDIV FRm, FRn */
1009 FRN(ir) = FRN(ir) / FRM(ir);
1010 break;
1011 case 4: /* FCMP/EQ FRm, FRn */
1012 sh4r.t = ( FRN(ir) == FRM(ir) ? 1 : 0 );
1013 break;
1014 case 5: /* FCMP/GT FRm, FRn */
1015 sh4r.t = ( FRN(ir) > FRM(ir) ? 1 : 0 );
1016 break;
1017 case 6: /* FMOV.S [Rm+R0], FRn */
1018 MEM_FP_READ( RM(ir) + R0, FRNn(ir) );
1019 break;
1020 case 7: /* FMOV.S FRm, [Rn+R0] */
1021 MEM_FP_WRITE( RN(ir) + R0, FRMn(ir) );
1022 break;
1023 case 8: /* FMOV.S [Rm], FRn */
1024 MEM_FP_READ( RM(ir), FRNn(ir) );
1025 break;
1026 case 9: /* FMOV.S [Rm++], FRn */
1027 MEM_FP_READ( RM(ir), FRNn(ir) );
1028 RM(ir) += FP_WIDTH;
1029 break;
1030 case 10:/* FMOV.S FRm, [Rn] */
1031 MEM_FP_WRITE( RN(ir), FRMn(ir) );
1032 break;
1033 case 11:/* FMOV.S FRm, [--Rn] */
1034 RN(ir) -= FP_WIDTH;
1035 MEM_FP_WRITE( RN(ir), FRMn(ir) );
1036 break;
1037 case 12:/* FMOV FRm, FRn */
1038 if( IS_FPU_DOUBLESIZE() ) {
1039 DRN(ir) = DRM(ir);
1040 } else {
1041 FRN(ir) = FRM(ir);
1042 }
1043 break;
1044 case 13:
1045 switch( (ir&0x00F0) >> 4 ) {
1046 case 0: /* FSTS FPUL, FRn */
1047 FRN(ir) = FPULf;
1048 break;
1049 case 1: /* FLDS FRn, FPUL */
1050 FPULf = FRN(ir);
1051 break;
1052 case 2: /* FLOAT FPUL, FRn */
1053 FRN(ir) = (float)FPULi;
1054 break;
1055 case 3: /* FTRC FRn, FPUL */
1056 FPULi = (uint32_t)FRN(ir);
1057 /* FIXME: is this sufficient? */
1058 break;
1059 case 4: /* FNEG FRn */
1060 FRN(ir) = -FRN(ir);
1061 break;
1062 case 5: /* FABS FRn */
1063 FRN(ir) = fabsf(FRN(ir));
1064 break;
1065 case 6: /* FSQRT FRn */
1066 FRN(ir) = sqrtf(FRN(ir));
1067 break;
1068 case 8: /* FLDI0 FRn */
1069 FRN(ir) = 0.0;
1070 break;
1071 case 9: /* FLDI1 FRn */
1072 FRN(ir) = 1.0;
1073 break;
1074 case 10: /* FCNVSD FPUL, DRn */
1075 if( IS_FPU_DOUBLEPREC() )
1076 DRN(ir) = (double)FPULf;
1077 else UNDEF(ir);
1078 break;
1079 case 11: /* FCNVDS DRn, FPUL */
1080 if( IS_FPU_DOUBLEPREC() )
1081 FPULf = (float)DRN(ir);
1082 else UNDEF(ir);
1083 break;
1084 case 14:/* FIPR FVn, FVn */
1085 UNIMP(ir);
1086 break;
1087 case 15:
1088 if( FVM(ir) == 1 )
1089 /* FTRV XMTRX,FVn */
1090 UNIMP(ir);
1091 else if( ir == 0xFBFD )
1092 /* FRCHG */
1093 sh4r.fpscr ^= FPSCR_FR;
1094 else if( ir == 0xF3FD )
1095 sh4r.fpscr ^= FPSCR_SZ;
1096 /* FSCHG */
1097 break;
1098 default: UNDEF(ir);
1099 }
1100 break;
1101 case 14:/* FMAC FR0, FRm, FRn */
1102 FRN(ir) += FRM(ir)*FR0;
1103 break;
1104 default: UNDEF(ir);
1105 }
1106 break;
1107 }
1108 sh4r.pc = sh4r.new_pc;
1109 sh4r.new_pc += 2;
1110 }
.