filename | src/sh4/sh4core.c |
changeset | 260:c82e26ec0cac |
prev | 246:98054d036a24 |
next | 265:5daf59b7f31b |
author | nkeynes |
date | Wed Jan 03 09:01:51 2007 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Implement the main CRTC registers, along with the sync status register. Timings are now pretty close to the real thing. |
view | annotate | diff | log | raw |
1 /**
2 * $Id: sh4core.c,v 1.36 2007-01-03 09:00:17 nkeynes Exp $
3 *
4 * SH4 emulation core, and parent module for all the SH4 peripheral
5 * modules.
6 *
7 * Copyright (c) 2005 Nathan Keynes.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
20 #define MODULE sh4_module
21 #include <math.h>
22 #include "dream.h"
23 #include "sh4/sh4core.h"
24 #include "sh4/sh4mmio.h"
25 #include "sh4/intc.h"
26 #include "mem.h"
27 #include "clock.h"
28 #include "syscall.h"
30 #define SH4_CALLTRACE 1
32 #define MAX_INT 0x7FFFFFFF
33 #define MIN_INT 0x80000000
34 #define MAX_INTF 2147483647.0
35 #define MIN_INTF -2147483648.0
37 /* CPU-generated exception code/vector pairs */
38 #define EXC_POWER_RESET 0x000 /* vector special */
39 #define EXC_MANUAL_RESET 0x020
40 #define EXC_READ_ADDR_ERR 0x0E0
41 #define EXC_WRITE_ADDR_ERR 0x100
42 #define EXC_SLOT_ILLEGAL 0x1A0
43 #define EXC_ILLEGAL 0x180
44 #define EXC_TRAP 0x160
45 #define EXC_FPDISABLE 0x800
46 #define EXC_SLOT_FPDISABLE 0x820
48 #define EXV_EXCEPTION 0x100 /* General exception vector */
49 #define EXV_TLBMISS 0x400 /* TLB-miss exception vector */
50 #define EXV_INTERRUPT 0x600 /* External interrupt vector */
52 /********************** SH4 Module Definition ****************************/
54 void sh4_init( void );
55 void sh4_reset( void );
56 uint32_t sh4_run_slice( uint32_t );
57 void sh4_start( void );
58 void sh4_stop( void );
59 void sh4_save_state( FILE *f );
60 int sh4_load_state( FILE *f );
62 struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_reset,
63 NULL, sh4_run_slice, sh4_stop,
64 sh4_save_state, sh4_load_state };
66 struct sh4_registers sh4r;
68 void sh4_init(void)
69 {
70 register_io_regions( mmio_list_sh4mmio );
71 mmu_init();
72 sh4_reset();
73 }
75 void sh4_reset(void)
76 {
77 /* zero everything out, for the sake of having a consistent state. */
78 memset( &sh4r, 0, sizeof(sh4r) );
80 /* Resume running if we were halted */
81 sh4r.sh4_state = SH4_STATE_RUNNING;
83 sh4r.pc = 0xA0000000;
84 sh4r.new_pc= 0xA0000002;
85 sh4r.vbr = 0x00000000;
86 sh4r.fpscr = 0x00040001;
87 sh4r.sr = 0x700000F0;
89 /* Mem reset will do this, but if we want to reset _just_ the SH4... */
90 MMIO_WRITE( MMU, EXPEVT, EXC_POWER_RESET );
92 /* Peripheral modules */
93 CPG_reset();
94 INTC_reset();
95 TMU_reset();
96 SCIF_reset();
97 }
99 static struct breakpoint_struct sh4_breakpoints[MAX_BREAKPOINTS];
100 static int sh4_breakpoint_count = 0;
101 static uint16_t *sh4_icache = NULL;
102 static uint32_t sh4_icache_addr = 0;
104 void sh4_set_breakpoint( uint32_t pc, int type )
105 {
106 sh4_breakpoints[sh4_breakpoint_count].address = pc;
107 sh4_breakpoints[sh4_breakpoint_count].type = type;
108 sh4_breakpoint_count++;
109 }
111 gboolean sh4_clear_breakpoint( uint32_t pc, int type )
112 {
113 int i;
115 for( i=0; i<sh4_breakpoint_count; i++ ) {
116 if( sh4_breakpoints[i].address == pc &&
117 sh4_breakpoints[i].type == type ) {
118 while( ++i < sh4_breakpoint_count ) {
119 sh4_breakpoints[i-1].address = sh4_breakpoints[i].address;
120 sh4_breakpoints[i-1].type = sh4_breakpoints[i].type;
121 }
122 sh4_breakpoint_count--;
123 return TRUE;
124 }
125 }
126 return FALSE;
127 }
129 int sh4_get_breakpoint( uint32_t pc )
130 {
131 int i;
132 for( i=0; i<sh4_breakpoint_count; i++ ) {
133 if( sh4_breakpoints[i].address == pc )
134 return sh4_breakpoints[i].type;
135 }
136 return 0;
137 }
139 uint32_t sh4_run_slice( uint32_t nanosecs )
140 {
141 int target = sh4r.icount + nanosecs / sh4_cpu_period;
142 int start = sh4r.icount;
143 int i;
145 if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
146 if( sh4r.int_pending != 0 )
147 sh4r.sh4_state = SH4_STATE_RUNNING;;
148 }
150 if( sh4_breakpoint_count == 0 ) {
151 for( sh4r.slice_cycle = 0; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
152 if( !sh4_execute_instruction() ) {
153 break;
154 }
155 }
156 } else {
158 for( sh4r.slice_cycle = 0; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
159 if( !sh4_execute_instruction() )
160 break;
161 #ifdef ENABLE_DEBUG_MODE
162 for( i=0; i<sh4_breakpoint_count; i++ ) {
163 if( sh4_breakpoints[i].address == sh4r.pc ) {
164 break;
165 }
166 }
167 if( i != sh4_breakpoint_count ) {
168 dreamcast_stop();
169 if( sh4_breakpoints[i].type == BREAK_ONESHOT )
170 sh4_clear_breakpoint( sh4r.pc, BREAK_ONESHOT );
171 break;
172 }
173 #endif
174 }
175 }
177 /* If we aborted early, but the cpu is still technically running,
178 * we're doing a hard abort - cut the timeslice back to what we
179 * actually executed
180 */
181 if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
182 nanosecs = sh4r.slice_cycle;
183 }
184 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
185 TMU_run_slice( nanosecs );
186 SCIF_run_slice( nanosecs );
187 }
188 sh4r.icount += sh4r.slice_cycle / sh4_cpu_period;
189 return nanosecs;
190 }
192 void sh4_stop(void)
193 {
195 }
197 void sh4_save_state( FILE *f )
198 {
199 fwrite( &sh4r, sizeof(sh4r), 1, f );
200 INTC_save_state( f );
201 TMU_save_state( f );
202 SCIF_save_state( f );
203 }
205 int sh4_load_state( FILE * f )
206 {
207 fread( &sh4r, sizeof(sh4r), 1, f );
208 INTC_load_state( f );
209 TMU_load_state( f );
210 return SCIF_load_state( f );
211 }
213 /********************** SH4 emulation core ****************************/
215 void sh4_set_pc( int pc )
216 {
217 sh4r.pc = pc;
218 sh4r.new_pc = pc+2;
219 }
221 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
222 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)
224 #if(SH4_CALLTRACE == 1)
225 #define MAX_CALLSTACK 32
226 static struct call_stack {
227 sh4addr_t call_addr;
228 sh4addr_t target_addr;
229 sh4addr_t stack_pointer;
230 } call_stack[MAX_CALLSTACK];
232 static int call_stack_depth = 0;
233 int sh4_call_trace_on = 0;
235 static inline trace_call( sh4addr_t source, sh4addr_t dest )
236 {
237 if( call_stack_depth < MAX_CALLSTACK ) {
238 call_stack[call_stack_depth].call_addr = source;
239 call_stack[call_stack_depth].target_addr = dest;
240 call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
241 }
242 call_stack_depth++;
243 }
245 static inline trace_return( sh4addr_t source, sh4addr_t dest )
246 {
247 if( call_stack_depth > 0 ) {
248 call_stack_depth--;
249 }
250 }
252 void fprint_stack_trace( FILE *f )
253 {
254 int i = call_stack_depth -1;
255 if( i >= MAX_CALLSTACK )
256 i = MAX_CALLSTACK - 1;
257 for( ; i >= 0; i-- ) {
258 fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n",
259 (call_stack_depth - i), call_stack[i].call_addr,
260 call_stack[i].target_addr, call_stack[i].stack_pointer );
261 }
262 }
264 #define TRACE_CALL( source, dest ) trace_call(source, dest)
265 #define TRACE_RETURN( source, dest ) trace_return(source, dest)
266 #else
267 #define TRACE_CALL( dest, rts )
268 #define TRACE_RETURN( source, dest )
269 #endif
271 #define RAISE( x, v ) do{ \
272 if( sh4r.vbr == 0 ) { \
273 ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \
274 dreamcast_stop(); return FALSE; \
275 } else { \
276 sh4r.spc = sh4r.pc; \
277 sh4r.ssr = sh4_read_sr(); \
278 sh4r.sgr = sh4r.r[15]; \
279 MMIO_WRITE(MMU,EXPEVT,x); \
280 sh4r.pc = sh4r.vbr + v; \
281 sh4r.new_pc = sh4r.pc + 2; \
282 sh4_load_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
283 if( sh4r.in_delay_slot ) { \
284 sh4r.in_delay_slot = 0; \
285 sh4r.spc -= 2; \
286 } \
287 } \
288 return TRUE; } while(0)
290 #define MEM_READ_BYTE( addr ) sh4_read_byte(addr)
291 #define MEM_READ_WORD( addr ) sh4_read_word(addr)
292 #define MEM_READ_LONG( addr ) sh4_read_long(addr)
293 #define MEM_WRITE_BYTE( addr, val ) sh4_write_byte(addr, val)
294 #define MEM_WRITE_WORD( addr, val ) sh4_write_word(addr, val)
295 #define MEM_WRITE_LONG( addr, val ) sh4_write_long(addr, val)
297 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
299 #define MEM_FP_READ( addr, reg ) sh4_read_float( addr, reg );
300 #define MEM_FP_WRITE( addr, reg ) sh4_write_float( addr, reg );
302 #define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )
303 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_READ_ADDR_ERR )
304 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_READ_ADDR_ERR )
305 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_WRITE_ADDR_ERR )
306 #define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_WRITE_ADDR_ERR )
308 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) return sh4_raise_slot_exception( EXC_FPDISABLE, EXC_SLOT_FPDISABLE )
309 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); dreamcast_stop(); return FALSE; }
310 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)
312 static void sh4_switch_banks( )
313 {
314 uint32_t tmp[8];
316 memcpy( tmp, sh4r.r, sizeof(uint32_t)*8 );
317 memcpy( sh4r.r, sh4r.r_bank, sizeof(uint32_t)*8 );
318 memcpy( sh4r.r_bank, tmp, sizeof(uint32_t)*8 );
319 }
321 static void sh4_load_sr( uint32_t newval )
322 {
323 if( (newval ^ sh4r.sr) & SR_RB )
324 sh4_switch_banks();
325 sh4r.sr = newval;
326 sh4r.t = (newval&SR_T) ? 1 : 0;
327 sh4r.s = (newval&SR_S) ? 1 : 0;
328 sh4r.m = (newval&SR_M) ? 1 : 0;
329 sh4r.q = (newval&SR_Q) ? 1 : 0;
330 intc_mask_changed();
331 }
333 static void sh4_write_float( uint32_t addr, int reg )
334 {
335 if( IS_FPU_DOUBLESIZE() ) {
336 if( reg & 1 ) {
337 sh4_write_long( addr, *((uint32_t *)&XF((reg)&0x0E)) );
338 sh4_write_long( addr+4, *((uint32_t *)&XF(reg)) );
339 } else {
340 sh4_write_long( addr, *((uint32_t *)&FR(reg)) );
341 sh4_write_long( addr+4, *((uint32_t *)&FR((reg)|0x01)) );
342 }
343 } else {
344 sh4_write_long( addr, *((uint32_t *)&FR((reg))) );
345 }
346 }
348 static void sh4_read_float( uint32_t addr, int reg )
349 {
350 if( IS_FPU_DOUBLESIZE() ) {
351 if( reg & 1 ) {
352 *((uint32_t *)&XF((reg) & 0x0E)) = sh4_read_long(addr);
353 *((uint32_t *)&XF(reg)) = sh4_read_long(addr+4);
354 } else {
355 *((uint32_t *)&FR(reg)) = sh4_read_long(addr);
356 *((uint32_t *)&FR((reg) | 0x01)) = sh4_read_long(addr+4);
357 }
358 } else {
359 *((uint32_t *)&FR(reg)) = sh4_read_long(addr);
360 }
361 }
363 static uint32_t sh4_read_sr( void )
364 {
365 /* synchronize sh4r.sr with the various bitflags */
366 sh4r.sr &= SR_MQSTMASK;
367 if( sh4r.t ) sh4r.sr |= SR_T;
368 if( sh4r.s ) sh4r.sr |= SR_S;
369 if( sh4r.m ) sh4r.sr |= SR_M;
370 if( sh4r.q ) sh4r.sr |= SR_Q;
371 return sh4r.sr;
372 }
374 /**
375 * Raise a general CPU exception for the specified exception code.
376 * (NOT for TRAPA or TLB exceptions)
377 */
378 gboolean sh4_raise_exception( int code )
379 {
380 RAISE( code, EXV_EXCEPTION );
381 }
383 gboolean sh4_raise_slot_exception( int normal_code, int slot_code ) {
384 if( sh4r.in_delay_slot ) {
385 return sh4_raise_exception(slot_code);
386 } else {
387 return sh4_raise_exception(normal_code);
388 }
389 }
391 gboolean sh4_raise_tlb_exception( int code )
392 {
393 RAISE( code, EXV_TLBMISS );
394 }
396 static void sh4_accept_interrupt( void )
397 {
398 uint32_t code = intc_accept_interrupt();
399 sh4r.ssr = sh4_read_sr();
400 sh4r.spc = sh4r.pc;
401 sh4r.sgr = sh4r.r[15];
402 sh4_load_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
403 MMIO_WRITE( MMU, INTEVT, code );
404 sh4r.pc = sh4r.vbr + 0x600;
405 sh4r.new_pc = sh4r.pc + 2;
406 // WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );
407 }
409 gboolean sh4_execute_instruction( void )
410 {
411 uint32_t pc;
412 unsigned short ir;
413 uint32_t tmp;
414 uint64_t tmpl;
415 float ftmp;
416 double dtmp;
418 #define R0 sh4r.r[0]
419 #define FR0 FR(0)
420 #define DR0 DR(0)
421 #define RN(ir) sh4r.r[(ir&0x0F00)>>8]
422 #define RN_BANK(ir) sh4r.r_bank[(ir&0x0070)>>4]
423 #define RM(ir) sh4r.r[(ir&0x00F0)>>4]
424 #define DISP4(ir) (ir&0x000F) /* 4-bit displacements are *NOT* sign-extended */
425 #define DISP8(ir) (ir&0x00FF)
426 #define PCDISP8(ir) SIGNEXT8(ir&0x00FF)
427 #define IMM8(ir) SIGNEXT8(ir&0x00FF)
428 #define UIMM8(ir) (ir&0x00FF) /* Unsigned immmediate */
429 #define DISP12(ir) SIGNEXT12(ir&0x0FFF)
430 #define FRNn(ir) ((ir&0x0F00)>>8)
431 #define FRMn(ir) ((ir&0x00F0)>>4)
432 #define DRNn(ir) ((ir&0x0E00)>>9)
433 #define DRMn(ir) ((ir&0x00E0)>>5)
434 #define FVN(ir) ((ir&0x0C00)>>8)
435 #define FVM(ir) ((ir&0x0300)>>6)
436 #define FRN(ir) FR(FRNn(ir))
437 #define FRM(ir) FR(FRMn(ir))
438 #define FRNi(ir) (*((uint32_t *)&FR(FRNn(ir))))
439 #define FRMi(ir) (*((uint32_t *)&FR(FRMn(ir))))
440 #define DRN(ir) DRb(DRNn(ir), ir&0x0100)
441 #define DRM(ir) DRb(DRMn(ir),ir&0x0010)
442 #define DRNi(ir) (*((uint64_t *)&DR(FRNn(ir))))
443 #define DRMi(ir) (*((uint64_t *)&DR(FRMn(ir))))
444 #define FPULf *((float *)&sh4r.fpul)
445 #define FPULi (sh4r.fpul)
447 if( SH4_INT_PENDING() )
448 sh4_accept_interrupt();
450 pc = sh4r.pc;
451 if( pc > 0xFFFFFF00 ) {
452 /* SYSCALL Magic */
453 syscall_invoke( pc );
454 sh4r.in_delay_slot = 0;
455 pc = sh4r.pc = sh4r.pr;
456 sh4r.new_pc = sh4r.pc + 2;
457 }
458 CHECKRALIGN16(pc);
460 /* Read instruction */
461 uint32_t pageaddr = pc >> 12;
462 if( sh4_icache != NULL && pageaddr == sh4_icache_addr ) {
463 ir = sh4_icache[(pc&0xFFF)>>1];
464 } else {
465 sh4_icache = (uint16_t *)mem_get_page(pc);
466 if( ((uint32_t)sh4_icache) < MAX_IO_REGIONS ) {
467 /* If someone's actually been so daft as to try to execute out of an IO
468 * region, fallback on the full-blown memory read
469 */
470 sh4_icache = NULL;
471 ir = MEM_READ_WORD(pc);
472 } else {
473 sh4_icache_addr = pageaddr;
474 ir = sh4_icache[(pc&0xFFF)>>1];
475 }
476 }
477 sh4r.icount++;
479 switch( (ir&0xF000)>>12 ) {
480 case 0: /* 0000nnnnmmmmxxxx */
481 switch( ir&0x000F ) {
482 case 2:
483 switch( (ir&0x00F0)>>4 ) {
484 case 0: /* STC SR, Rn */
485 CHECKPRIV();
486 RN(ir) = sh4_read_sr();
487 break;
488 case 1: /* STC GBR, Rn */
489 RN(ir) = sh4r.gbr;
490 break;
491 case 2: /* STC VBR, Rn */
492 CHECKPRIV();
493 RN(ir) = sh4r.vbr;
494 break;
495 case 3: /* STC SSR, Rn */
496 CHECKPRIV();
497 RN(ir) = sh4r.ssr;
498 break;
499 case 4: /* STC SPC, Rn */
500 CHECKPRIV();
501 RN(ir) = sh4r.spc;
502 break;
503 case 8: case 9: case 10: case 11: case 12: case 13:
504 case 14: case 15:/* STC Rm_bank, Rn */
505 CHECKPRIV();
506 RN(ir) = RN_BANK(ir);
507 break;
508 default: UNDEF(ir);
509 }
510 break;
511 case 3:
512 switch( (ir&0x00F0)>>4 ) {
513 case 0: /* BSRF Rn */
514 CHECKSLOTILLEGAL();
515 CHECKDEST( pc + 4 + RN(ir) );
516 sh4r.in_delay_slot = 1;
517 sh4r.pr = sh4r.pc + 4;
518 sh4r.pc = sh4r.new_pc;
519 sh4r.new_pc = pc + 4 + RN(ir);
520 TRACE_CALL( pc, sh4r.new_pc );
521 return TRUE;
522 case 2: /* BRAF Rn */
523 CHECKSLOTILLEGAL();
524 CHECKDEST( pc + 4 + RN(ir) );
525 sh4r.in_delay_slot = 1;
526 sh4r.pc = sh4r.new_pc;
527 sh4r.new_pc = pc + 4 + RN(ir);
528 return TRUE;
529 case 8: /* PREF [Rn] */
530 tmp = RN(ir);
531 if( (tmp & 0xFC000000) == 0xE0000000 ) {
532 /* Store queue operation */
533 int queue = (tmp&0x20)>>2;
534 int32_t *src = &sh4r.store_queue[queue];
535 uint32_t hi = (MMIO_READ( MMU, (queue == 0 ? QACR0 : QACR1) ) & 0x1C) << 24;
536 uint32_t target = tmp&0x03FFFFE0 | hi;
537 mem_copy_to_sh4( target, src, 32 );
538 }
539 break;
540 case 9: /* OCBI [Rn] */
541 case 10:/* OCBP [Rn] */
542 case 11:/* OCBWB [Rn] */
543 /* anything? */
544 break;
545 case 12:/* MOVCA.L R0, [Rn] */
546 tmp = RN(ir);
547 CHECKWALIGN32(tmp);
548 MEM_WRITE_LONG( tmp, R0 );
549 break;
550 default: UNDEF(ir);
551 }
552 break;
553 case 4: /* MOV.B Rm, [R0 + Rn] */
554 MEM_WRITE_BYTE( R0 + RN(ir), RM(ir) );
555 break;
556 case 5: /* MOV.W Rm, [R0 + Rn] */
557 CHECKWALIGN16( R0 + RN(ir) );
558 MEM_WRITE_WORD( R0 + RN(ir), RM(ir) );
559 break;
560 case 6: /* MOV.L Rm, [R0 + Rn] */
561 CHECKWALIGN32( R0 + RN(ir) );
562 MEM_WRITE_LONG( R0 + RN(ir), RM(ir) );
563 break;
564 case 7: /* MUL.L Rm, Rn */
565 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
566 (RM(ir) * RN(ir));
567 break;
568 case 8:
569 switch( (ir&0x0FF0)>>4 ) {
570 case 0: /* CLRT */
571 sh4r.t = 0;
572 break;
573 case 1: /* SETT */
574 sh4r.t = 1;
575 break;
576 case 2: /* CLRMAC */
577 sh4r.mac = 0;
578 break;
579 case 3: /* LDTLB */
580 break;
581 case 4: /* CLRS */
582 sh4r.s = 0;
583 break;
584 case 5: /* SETS */
585 sh4r.s = 1;
586 break;
587 default: UNDEF(ir);
588 }
589 break;
590 case 9:
591 if( (ir&0x00F0) == 0x20 ) /* MOVT Rn */
592 RN(ir) = sh4r.t;
593 else if( ir == 0x0019 ) /* DIV0U */
594 sh4r.m = sh4r.q = sh4r.t = 0;
595 else if( ir == 0x0009 )
596 /* NOP */;
597 else UNDEF(ir);
598 break;
599 case 10:
600 switch( (ir&0x00F0) >> 4 ) {
601 case 0: /* STS MACH, Rn */
602 RN(ir) = sh4r.mac >> 32;
603 break;
604 case 1: /* STS MACL, Rn */
605 RN(ir) = (uint32_t)sh4r.mac;
606 break;
607 case 2: /* STS PR, Rn */
608 RN(ir) = sh4r.pr;
609 break;
610 case 3: /* STC SGR, Rn */
611 CHECKPRIV();
612 RN(ir) = sh4r.sgr;
613 break;
614 case 5:/* STS FPUL, Rn */
615 RN(ir) = sh4r.fpul;
616 break;
617 case 6: /* STS FPSCR, Rn */
618 RN(ir) = sh4r.fpscr;
619 break;
620 case 15:/* STC DBR, Rn */
621 CHECKPRIV();
622 RN(ir) = sh4r.dbr;
623 break;
624 default: UNDEF(ir);
625 }
626 break;
627 case 11:
628 switch( (ir&0x0FF0)>>4 ) {
629 case 0: /* RTS */
630 CHECKSLOTILLEGAL();
631 CHECKDEST( sh4r.pr );
632 sh4r.in_delay_slot = 1;
633 sh4r.pc = sh4r.new_pc;
634 sh4r.new_pc = sh4r.pr;
635 TRACE_RETURN( pc, sh4r.new_pc );
636 return TRUE;
637 case 1: /* SLEEP */
638 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
639 sh4r.sh4_state = SH4_STATE_STANDBY;
640 } else {
641 sh4r.sh4_state = SH4_STATE_SLEEP;
642 }
643 return FALSE; /* Halt CPU */
644 case 2: /* RTE */
645 CHECKPRIV();
646 CHECKDEST( sh4r.spc );
647 CHECKSLOTILLEGAL();
648 sh4r.in_delay_slot = 1;
649 sh4r.pc = sh4r.new_pc;
650 sh4r.new_pc = sh4r.spc;
651 sh4_load_sr( sh4r.ssr );
652 return TRUE;
653 default:UNDEF(ir);
654 }
655 break;
656 case 12:/* MOV.B [R0+R%d], R%d */
657 RN(ir) = MEM_READ_BYTE( R0 + RM(ir) );
658 break;
659 case 13:/* MOV.W [R0+R%d], R%d */
660 CHECKRALIGN16( R0 + RM(ir) );
661 RN(ir) = MEM_READ_WORD( R0 + RM(ir) );
662 break;
663 case 14:/* MOV.L [R0+R%d], R%d */
664 CHECKRALIGN32( R0 + RM(ir) );
665 RN(ir) = MEM_READ_LONG( R0 + RM(ir) );
666 break;
667 case 15:/* MAC.L [Rm++], [Rn++] */
668 CHECKRALIGN32( RM(ir) );
669 CHECKRALIGN32( RN(ir) );
670 tmpl = ( SIGNEXT32(MEM_READ_LONG(RM(ir))) *
671 SIGNEXT32(MEM_READ_LONG(RN(ir))) );
672 if( sh4r.s ) {
673 /* 48-bit Saturation. Yuch */
674 tmpl += SIGNEXT48(sh4r.mac);
675 if( tmpl < 0xFFFF800000000000LL )
676 tmpl = 0xFFFF800000000000LL;
677 else if( tmpl > 0x00007FFFFFFFFFFFLL )
678 tmpl = 0x00007FFFFFFFFFFFLL;
679 sh4r.mac = (sh4r.mac&0xFFFF000000000000LL) |
680 (tmpl&0x0000FFFFFFFFFFFFLL);
681 } else sh4r.mac = tmpl;
683 RM(ir) += 4;
684 RN(ir) += 4;
686 break;
687 default: UNDEF(ir);
688 }
689 break;
690 case 1: /* 0001nnnnmmmmdddd */
691 /* MOV.L Rm, [Rn + disp4*4] */
692 tmp = RN(ir) + (DISP4(ir)<<2);
693 CHECKWALIGN32( tmp );
694 MEM_WRITE_LONG( tmp, RM(ir) );
695 break;
696 case 2: /* 0010nnnnmmmmxxxx */
697 switch( ir&0x000F ) {
698 case 0: /* MOV.B Rm, [Rn] */
699 MEM_WRITE_BYTE( RN(ir), RM(ir) );
700 break;
701 case 1: /* MOV.W Rm, [Rn] */
702 CHECKWALIGN16( RN(ir) );
703 MEM_WRITE_WORD( RN(ir), RM(ir) );
704 break;
705 case 2: /* MOV.L Rm, [Rn] */
706 CHECKWALIGN32( RN(ir) );
707 MEM_WRITE_LONG( RN(ir), RM(ir) );
708 break;
709 case 3: UNDEF(ir);
710 break;
711 case 4: /* MOV.B Rm, [--Rn] */
712 RN(ir) --;
713 MEM_WRITE_BYTE( RN(ir), RM(ir) );
714 break;
715 case 5: /* MOV.W Rm, [--Rn] */
716 RN(ir) -= 2;
717 CHECKWALIGN16( RN(ir) );
718 MEM_WRITE_WORD( RN(ir), RM(ir) );
719 break;
720 case 6: /* MOV.L Rm, [--Rn] */
721 RN(ir) -= 4;
722 CHECKWALIGN32( RN(ir) );
723 MEM_WRITE_LONG( RN(ir), RM(ir) );
724 break;
725 case 7: /* DIV0S Rm, Rn */
726 sh4r.q = RN(ir)>>31;
727 sh4r.m = RM(ir)>>31;
728 sh4r.t = sh4r.q ^ sh4r.m;
729 break;
730 case 8: /* TST Rm, Rn */
731 sh4r.t = (RN(ir)&RM(ir) ? 0 : 1);
732 break;
733 case 9: /* AND Rm, Rn */
734 RN(ir) &= RM(ir);
735 break;
736 case 10:/* XOR Rm, Rn */
737 RN(ir) ^= RM(ir);
738 break;
739 case 11:/* OR Rm, Rn */
740 RN(ir) |= RM(ir);
741 break;
742 case 12:/* CMP/STR Rm, Rn */
743 /* set T = 1 if any byte in RM & RN is the same */
744 tmp = RM(ir) ^ RN(ir);
745 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
746 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
747 break;
748 case 13:/* XTRCT Rm, Rn */
749 RN(ir) = (RN(ir)>>16) | (RM(ir)<<16);
750 break;
751 case 14:/* MULU.W Rm, Rn */
752 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
753 (uint32_t)((RM(ir)&0xFFFF) * (RN(ir)&0xFFFF));
754 break;
755 case 15:/* MULS.W Rm, Rn */
756 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
757 (uint32_t)(SIGNEXT32(RM(ir)&0xFFFF) * SIGNEXT32(RN(ir)&0xFFFF));
758 break;
759 }
760 break;
761 case 3: /* 0011nnnnmmmmxxxx */
762 switch( ir&0x000F ) {
763 case 0: /* CMP/EQ Rm, Rn */
764 sh4r.t = ( RM(ir) == RN(ir) ? 1 : 0 );
765 break;
766 case 2: /* CMP/HS Rm, Rn */
767 sh4r.t = ( RN(ir) >= RM(ir) ? 1 : 0 );
768 break;
769 case 3: /* CMP/GE Rm, Rn */
770 sh4r.t = ( ((int32_t)RN(ir)) >= ((int32_t)RM(ir)) ? 1 : 0 );
771 break;
772 case 4: { /* DIV1 Rm, Rn */
773 /* This is just from the sh4p manual with some
774 * simplifications (someone want to check it's correct? :)
775 * Why they couldn't just provide a real DIV instruction...
776 * Please oh please let the translator batch these things
777 * up into a single DIV... */
778 uint32_t tmp0, tmp1, tmp2, dir;
780 dir = sh4r.q ^ sh4r.m;
781 sh4r.q = (RN(ir) >> 31);
782 tmp2 = RM(ir);
783 RN(ir) = (RN(ir) << 1) | sh4r.t;
784 tmp0 = RN(ir);
785 if( dir ) {
786 RN(ir) += tmp2;
787 tmp1 = (RN(ir)<tmp0 ? 1 : 0 );
788 } else {
789 RN(ir) -= tmp2;
790 tmp1 = (RN(ir)>tmp0 ? 1 : 0 );
791 }
792 sh4r.q ^= sh4r.m ^ tmp1;
793 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
794 break; }
795 case 5: /* DMULU.L Rm, Rn */
796 sh4r.mac = ((uint64_t)RM(ir)) * ((uint64_t)RN(ir));
797 break;
798 case 6: /* CMP/HI Rm, Rn */
799 sh4r.t = ( RN(ir) > RM(ir) ? 1 : 0 );
800 break;
801 case 7: /* CMP/GT Rm, Rn */
802 sh4r.t = ( ((int32_t)RN(ir)) > ((int32_t)RM(ir)) ? 1 : 0 );
803 break;
804 case 8: /* SUB Rm, Rn */
805 RN(ir) -= RM(ir);
806 break;
807 case 10:/* SUBC Rm, Rn */
808 tmp = RN(ir);
809 RN(ir) = RN(ir) - RM(ir) - sh4r.t;
810 sh4r.t = (RN(ir) > tmp || (RN(ir) == tmp && sh4r.t == 1));
811 break;
812 case 11:/* SUBV Rm, Rn */
813 UNIMP(ir);
814 break;
815 case 12:/* ADD Rm, Rn */
816 RN(ir) += RM(ir);
817 break;
818 case 13:/* DMULS.L Rm, Rn */
819 sh4r.mac = SIGNEXT32(RM(ir)) * SIGNEXT32(RN(ir));
820 break;
821 case 14:/* ADDC Rm, Rn */
822 tmp = RN(ir);
823 RN(ir) += RM(ir) + sh4r.t;
824 sh4r.t = ( RN(ir) < tmp || (RN(ir) == tmp && sh4r.t != 0) ? 1 : 0 );
825 break;
826 case 15:/* ADDV Rm, Rn */
827 tmp = RN(ir) + RM(ir);
828 sh4r.t = ( (RN(ir)>>31) == (RM(ir)>>31) && ((RN(ir)>>31) != (tmp>>31)) );
829 RN(ir) = tmp;
830 break;
831 default: UNDEF(ir);
832 }
833 break;
834 case 4: /* 0100nnnnxxxxxxxx */
835 switch( ir&0x00FF ) {
836 case 0x00: /* SHLL Rn */
837 sh4r.t = RN(ir) >> 31;
838 RN(ir) <<= 1;
839 break;
840 case 0x01: /* SHLR Rn */
841 sh4r.t = RN(ir) & 0x00000001;
842 RN(ir) >>= 1;
843 break;
844 case 0x02: /* STS.L MACH, [--Rn] */
845 RN(ir) -= 4;
846 CHECKWALIGN32( RN(ir) );
847 MEM_WRITE_LONG( RN(ir), (sh4r.mac>>32) );
848 break;
849 case 0x03: /* STC.L SR, [--Rn] */
850 CHECKPRIV();
851 RN(ir) -= 4;
852 CHECKWALIGN32( RN(ir) );
853 MEM_WRITE_LONG( RN(ir), sh4_read_sr() );
854 break;
855 case 0x04: /* ROTL Rn */
856 sh4r.t = RN(ir) >> 31;
857 RN(ir) <<= 1;
858 RN(ir) |= sh4r.t;
859 break;
860 case 0x05: /* ROTR Rn */
861 sh4r.t = RN(ir) & 0x00000001;
862 RN(ir) >>= 1;
863 RN(ir) |= (sh4r.t << 31);
864 break;
865 case 0x06: /* LDS.L [Rn++], MACH */
866 CHECKRALIGN32( RN(ir) );
867 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
868 (((uint64_t)MEM_READ_LONG(RN(ir)))<<32);
869 RN(ir) += 4;
870 break;
871 case 0x07: /* LDC.L [Rn++], SR */
872 CHECKSLOTILLEGAL();
873 CHECKPRIV();
874 CHECKWALIGN32( RN(ir) );
875 sh4_load_sr( MEM_READ_LONG(RN(ir)) );
876 RN(ir) +=4;
877 break;
878 case 0x08: /* SHLL2 Rn */
879 RN(ir) <<= 2;
880 break;
881 case 0x09: /* SHLR2 Rn */
882 RN(ir) >>= 2;
883 break;
884 case 0x0A: /* LDS Rn, MACH */
885 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
886 (((uint64_t)RN(ir))<<32);
887 break;
888 case 0x0B: /* JSR [Rn] */
889 CHECKDEST( RN(ir) );
890 CHECKSLOTILLEGAL();
891 sh4r.in_delay_slot = 1;
892 sh4r.pc = sh4r.new_pc;
893 sh4r.new_pc = RN(ir);
894 sh4r.pr = pc + 4;
895 TRACE_CALL( pc, sh4r.new_pc );
896 return TRUE;
897 case 0x0E: /* LDC Rn, SR */
898 CHECKSLOTILLEGAL();
899 CHECKPRIV();
900 sh4_load_sr( RN(ir) );
901 break;
902 case 0x10: /* DT Rn */
903 RN(ir) --;
904 sh4r.t = ( RN(ir) == 0 ? 1 : 0 );
905 break;
906 case 0x11: /* CMP/PZ Rn */
907 sh4r.t = ( ((int32_t)RN(ir)) >= 0 ? 1 : 0 );
908 break;
909 case 0x12: /* STS.L MACL, [--Rn] */
910 RN(ir) -= 4;
911 CHECKWALIGN32( RN(ir) );
912 MEM_WRITE_LONG( RN(ir), (uint32_t)sh4r.mac );
913 break;
914 case 0x13: /* STC.L GBR, [--Rn] */
915 RN(ir) -= 4;
916 CHECKWALIGN32( RN(ir) );
917 MEM_WRITE_LONG( RN(ir), sh4r.gbr );
918 break;
919 case 0x15: /* CMP/PL Rn */
920 sh4r.t = ( ((int32_t)RN(ir)) > 0 ? 1 : 0 );
921 break;
922 case 0x16: /* LDS.L [Rn++], MACL */
923 CHECKRALIGN32( RN(ir) );
924 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
925 (uint64_t)((uint32_t)MEM_READ_LONG(RN(ir)));
926 RN(ir) += 4;
927 break;
928 case 0x17: /* LDC.L [Rn++], GBR */
929 CHECKRALIGN32( RN(ir) );
930 sh4r.gbr = MEM_READ_LONG(RN(ir));
931 RN(ir) +=4;
932 break;
933 case 0x18: /* SHLL8 Rn */
934 RN(ir) <<= 8;
935 break;
936 case 0x19: /* SHLR8 Rn */
937 RN(ir) >>= 8;
938 break;
939 case 0x1A: /* LDS Rn, MACL */
940 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
941 (uint64_t)((uint32_t)(RN(ir)));
942 break;
943 case 0x1B: /* TAS.B [Rn] */
944 tmp = MEM_READ_BYTE( RN(ir) );
945 sh4r.t = ( tmp == 0 ? 1 : 0 );
946 MEM_WRITE_BYTE( RN(ir), tmp | 0x80 );
947 break;
948 case 0x1E: /* LDC Rn, GBR */
949 sh4r.gbr = RN(ir);
950 break;
951 case 0x20: /* SHAL Rn */
952 sh4r.t = RN(ir) >> 31;
953 RN(ir) <<= 1;
954 break;
955 case 0x21: /* SHAR Rn */
956 sh4r.t = RN(ir) & 0x00000001;
957 RN(ir) = ((int32_t)RN(ir)) >> 1;
958 break;
959 case 0x22: /* STS.L PR, [--Rn] */
960 RN(ir) -= 4;
961 CHECKWALIGN32( RN(ir) );
962 MEM_WRITE_LONG( RN(ir), sh4r.pr );
963 break;
964 case 0x23: /* STC.L VBR, [--Rn] */
965 CHECKPRIV();
966 RN(ir) -= 4;
967 CHECKWALIGN32( RN(ir) );
968 MEM_WRITE_LONG( RN(ir), sh4r.vbr );
969 break;
970 case 0x24: /* ROTCL Rn */
971 tmp = RN(ir) >> 31;
972 RN(ir) <<= 1;
973 RN(ir) |= sh4r.t;
974 sh4r.t = tmp;
975 break;
976 case 0x25: /* ROTCR Rn */
977 tmp = RN(ir) & 0x00000001;
978 RN(ir) >>= 1;
979 RN(ir) |= (sh4r.t << 31 );
980 sh4r.t = tmp;
981 break;
982 case 0x26: /* LDS.L [Rn++], PR */
983 CHECKRALIGN32( RN(ir) );
984 sh4r.pr = MEM_READ_LONG( RN(ir) );
985 RN(ir) += 4;
986 break;
987 case 0x27: /* LDC.L [Rn++], VBR */
988 CHECKPRIV();
989 CHECKRALIGN32( RN(ir) );
990 sh4r.vbr = MEM_READ_LONG(RN(ir));
991 RN(ir) +=4;
992 break;
993 case 0x28: /* SHLL16 Rn */
994 RN(ir) <<= 16;
995 break;
996 case 0x29: /* SHLR16 Rn */
997 RN(ir) >>= 16;
998 break;
999 case 0x2A: /* LDS Rn, PR */
1000 sh4r.pr = RN(ir);
1001 break;
1002 case 0x2B: /* JMP [Rn] */
1003 CHECKDEST( RN(ir) );
1004 CHECKSLOTILLEGAL();
1005 sh4r.in_delay_slot = 1;
1006 sh4r.pc = sh4r.new_pc;
1007 sh4r.new_pc = RN(ir);
1008 return TRUE;
1009 case 0x2E: /* LDC Rn, VBR */
1010 CHECKPRIV();
1011 sh4r.vbr = RN(ir);
1012 break;
1013 case 0x32: /* STC.L SGR, [--Rn] */
1014 CHECKPRIV();
1015 RN(ir) -= 4;
1016 CHECKWALIGN32( RN(ir) );
1017 MEM_WRITE_LONG( RN(ir), sh4r.sgr );
1018 break;
1019 case 0x33: /* STC.L SSR, [--Rn] */
1020 CHECKPRIV();
1021 RN(ir) -= 4;
1022 CHECKWALIGN32( RN(ir) );
1023 MEM_WRITE_LONG( RN(ir), sh4r.ssr );
1024 break;
1025 case 0x37: /* LDC.L [Rn++], SSR */
1026 CHECKPRIV();
1027 CHECKRALIGN32( RN(ir) );
1028 sh4r.ssr = MEM_READ_LONG(RN(ir));
1029 RN(ir) +=4;
1030 break;
1031 case 0x3E: /* LDC Rn, SSR */
1032 CHECKPRIV();
1033 sh4r.ssr = RN(ir);
1034 break;
1035 case 0x43: /* STC.L SPC, [--Rn] */
1036 CHECKPRIV();
1037 RN(ir) -= 4;
1038 CHECKWALIGN32( RN(ir) );
1039 MEM_WRITE_LONG( RN(ir), sh4r.spc );
1040 break;
1041 case 0x47: /* LDC.L [Rn++], SPC */
1042 CHECKPRIV();
1043 CHECKRALIGN32( RN(ir) );
1044 sh4r.spc = MEM_READ_LONG(RN(ir));
1045 RN(ir) +=4;
1046 break;
1047 case 0x4E: /* LDC Rn, SPC */
1048 CHECKPRIV();
1049 sh4r.spc = RN(ir);
1050 break;
1051 case 0x52: /* STS.L FPUL, [--Rn] */
1052 RN(ir) -= 4;
1053 CHECKWALIGN32( RN(ir) );
1054 MEM_WRITE_LONG( RN(ir), sh4r.fpul );
1055 break;
1056 case 0x56: /* LDS.L [Rn++], FPUL */
1057 CHECKRALIGN32( RN(ir) );
1058 sh4r.fpul = MEM_READ_LONG(RN(ir));
1059 RN(ir) +=4;
1060 break;
1061 case 0x5A: /* LDS Rn, FPUL */
1062 sh4r.fpul = RN(ir);
1063 break;
1064 case 0x62: /* STS.L FPSCR, [--Rn] */
1065 RN(ir) -= 4;
1066 CHECKWALIGN32( RN(ir) );
1067 MEM_WRITE_LONG( RN(ir), sh4r.fpscr );
1068 break;
1069 case 0x66: /* LDS.L [Rn++], FPSCR */
1070 CHECKRALIGN32( RN(ir) );
1071 sh4r.fpscr = MEM_READ_LONG(RN(ir));
1072 RN(ir) +=4;
1073 break;
1074 case 0x6A: /* LDS Rn, FPSCR */
1075 sh4r.fpscr = RN(ir);
1076 break;
1077 case 0xF2: /* STC.L DBR, [--Rn] */
1078 CHECKPRIV();
1079 RN(ir) -= 4;
1080 CHECKWALIGN32( RN(ir) );
1081 MEM_WRITE_LONG( RN(ir), sh4r.dbr );
1082 break;
1083 case 0xF6: /* LDC.L [Rn++], DBR */
1084 CHECKPRIV();
1085 CHECKRALIGN32( RN(ir) );
1086 sh4r.dbr = MEM_READ_LONG(RN(ir));
1087 RN(ir) +=4;
1088 break;
1089 case 0xFA: /* LDC Rn, DBR */
1090 CHECKPRIV();
1091 sh4r.dbr = RN(ir);
1092 break;
1093 case 0x83: case 0x93: case 0xA3: case 0xB3: case 0xC3:
1094 case 0xD3: case 0xE3: case 0xF3: /* STC.L Rn_BANK, [--Rn] */
1095 CHECKPRIV();
1096 RN(ir) -= 4;
1097 CHECKWALIGN32( RN(ir) );
1098 MEM_WRITE_LONG( RN(ir), RN_BANK(ir) );
1099 break;
1100 case 0x87: case 0x97: case 0xA7: case 0xB7: case 0xC7:
1101 case 0xD7: case 0xE7: case 0xF7: /* LDC.L [Rn++], Rn_BANK */
1102 CHECKPRIV();
1103 CHECKRALIGN32( RN(ir) );
1104 RN_BANK(ir) = MEM_READ_LONG( RN(ir) );
1105 RN(ir) += 4;
1106 break;
1107 case 0x8E: case 0x9E: case 0xAE: case 0xBE: case 0xCE:
1108 case 0xDE: case 0xEE: case 0xFE: /* LDC Rm, Rn_BANK */
1109 CHECKPRIV();
1110 RN_BANK(ir) = RM(ir);
1111 break;
1112 default:
1113 if( (ir&0x000F) == 0x0F ) {
1114 /* MAC.W [Rm++], [Rn++] */
1115 CHECKRALIGN16( RN(ir) );
1116 CHECKRALIGN16( RM(ir) );
1117 tmp = SIGNEXT16(MEM_READ_WORD(RM(ir))) *
1118 SIGNEXT16(MEM_READ_WORD(RN(ir)));
1119 if( sh4r.s ) {
1120 /* FIXME */
1121 UNIMP(ir);
1122 } else sh4r.mac += SIGNEXT32(tmp);
1123 RM(ir) += 2;
1124 RN(ir) += 2;
1125 } else if( (ir&0x000F) == 0x0C ) {
1126 /* SHAD Rm, Rn */
1127 tmp = RM(ir);
1128 if( (tmp & 0x80000000) == 0 ) RN(ir) <<= (tmp&0x1f);
1129 else if( (tmp & 0x1F) == 0 )
1130 RN(ir) = ((int32_t)RN(ir)) >> 31;
1131 else
1132 RN(ir) = ((int32_t)RN(ir)) >> (((~RM(ir)) & 0x1F)+1);
1133 } else if( (ir&0x000F) == 0x0D ) {
1134 /* SHLD Rm, Rn */
1135 tmp = RM(ir);
1136 if( (tmp & 0x80000000) == 0 ) RN(ir) <<= (tmp&0x1f);
1137 else if( (tmp & 0x1F) == 0 ) RN(ir) = 0;
1138 else RN(ir) >>= (((~tmp) & 0x1F)+1);
1139 } else UNDEF(ir);
1140 }
1141 break;
1142 case 5: /* 0101nnnnmmmmdddd */
1143 /* MOV.L [Rm + disp4*4], Rn */
1144 tmp = RM(ir) + (DISP4(ir)<<2);
1145 CHECKRALIGN32( tmp );
1146 RN(ir) = MEM_READ_LONG( tmp );
1147 break;
1148 case 6: /* 0110xxxxxxxxxxxx */
1149 switch( ir&0x000f ) {
1150 case 0: /* MOV.B [Rm], Rn */
1151 RN(ir) = MEM_READ_BYTE( RM(ir) );
1152 break;
1153 case 1: /* MOV.W [Rm], Rn */
1154 CHECKRALIGN16( RM(ir) );
1155 RN(ir) = MEM_READ_WORD( RM(ir) );
1156 break;
1157 case 2: /* MOV.L [Rm], Rn */
1158 CHECKRALIGN32( RM(ir) );
1159 RN(ir) = MEM_READ_LONG( RM(ir) );
1160 break;
1161 case 3: /* MOV Rm, Rn */
1162 RN(ir) = RM(ir);
1163 break;
1164 case 4: /* MOV.B [Rm++], Rn */
1165 RN(ir) = MEM_READ_BYTE( RM(ir) );
1166 RM(ir) ++;
1167 break;
1168 case 5: /* MOV.W [Rm++], Rn */
1169 CHECKRALIGN16( RM(ir) );
1170 RN(ir) = MEM_READ_WORD( RM(ir) );
1171 RM(ir) += 2;
1172 break;
1173 case 6: /* MOV.L [Rm++], Rn */
1174 CHECKRALIGN32( RM(ir) );
1175 RN(ir) = MEM_READ_LONG( RM(ir) );
1176 RM(ir) += 4;
1177 break;
1178 case 7: /* NOT Rm, Rn */
1179 RN(ir) = ~RM(ir);
1180 break;
1181 case 8: /* SWAP.B Rm, Rn */
1182 RN(ir) = (RM(ir)&0xFFFF0000) | ((RM(ir)&0x0000FF00)>>8) |
1183 ((RM(ir)&0x000000FF)<<8);
1184 break;
1185 case 9: /* SWAP.W Rm, Rn */
1186 RN(ir) = (RM(ir)>>16) | (RM(ir)<<16);
1187 break;
1188 case 10:/* NEGC Rm, Rn */
1189 tmp = 0 - RM(ir);
1190 RN(ir) = tmp - sh4r.t;
1191 sh4r.t = ( 0<tmp || tmp<RN(ir) ? 1 : 0 );
1192 break;
1193 case 11:/* NEG Rm, Rn */
1194 RN(ir) = 0 - RM(ir);
1195 break;
1196 case 12:/* EXTU.B Rm, Rn */
1197 RN(ir) = RM(ir)&0x000000FF;
1198 break;
1199 case 13:/* EXTU.W Rm, Rn */
1200 RN(ir) = RM(ir)&0x0000FFFF;
1201 break;
1202 case 14:/* EXTS.B Rm, Rn */
1203 RN(ir) = SIGNEXT8( RM(ir)&0x000000FF );
1204 break;
1205 case 15:/* EXTS.W Rm, Rn */
1206 RN(ir) = SIGNEXT16( RM(ir)&0x0000FFFF );
1207 break;
1208 }
1209 break;
1210 case 7: /* 0111nnnniiiiiiii */
1211 /* ADD imm8, Rn */
1212 RN(ir) += IMM8(ir);
1213 break;
1214 case 8: /* 1000xxxxxxxxxxxx */
1215 switch( (ir&0x0F00) >> 8 ) {
1216 case 0: /* MOV.B R0, [Rm + disp4] */
1217 MEM_WRITE_BYTE( RM(ir) + DISP4(ir), R0 );
1218 break;
1219 case 1: /* MOV.W R0, [Rm + disp4*2] */
1220 tmp = RM(ir) + (DISP4(ir)<<1);
1221 CHECKWALIGN16( tmp );
1222 MEM_WRITE_WORD( tmp, R0 );
1223 break;
1224 case 4: /* MOV.B [Rm + disp4], R0 */
1225 R0 = MEM_READ_BYTE( RM(ir) + DISP4(ir) );
1226 break;
1227 case 5: /* MOV.W [Rm + disp4*2], R0 */
1228 tmp = RM(ir) + (DISP4(ir)<<1);
1229 CHECKRALIGN16( tmp );
1230 R0 = MEM_READ_WORD( tmp );
1231 break;
1232 case 8: /* CMP/EQ imm, R0 */
1233 sh4r.t = ( R0 == IMM8(ir) ? 1 : 0 );
1234 break;
1235 case 9: /* BT disp8 */
1236 CHECKSLOTILLEGAL();
1237 if( sh4r.t ) {
1238 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
1239 sh4r.pc += (PCDISP8(ir)<<1) + 4;
1240 sh4r.new_pc = sh4r.pc + 2;
1241 return TRUE;
1242 }
1243 break;
1244 case 11:/* BF disp8 */
1245 CHECKSLOTILLEGAL();
1246 if( !sh4r.t ) {
1247 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
1248 sh4r.pc += (PCDISP8(ir)<<1) + 4;
1249 sh4r.new_pc = sh4r.pc + 2;
1250 return TRUE;
1251 }
1252 break;
1253 case 13:/* BT/S disp8 */
1254 CHECKSLOTILLEGAL();
1255 if( sh4r.t ) {
1256 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
1257 sh4r.in_delay_slot = 1;
1258 sh4r.pc = sh4r.new_pc;
1259 sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
1260 sh4r.in_delay_slot = 1;
1261 return TRUE;
1262 }
1263 break;
1264 case 15:/* BF/S disp8 */
1265 CHECKSLOTILLEGAL();
1266 if( !sh4r.t ) {
1267 CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
1268 sh4r.in_delay_slot = 1;
1269 sh4r.pc = sh4r.new_pc;
1270 sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
1271 return TRUE;
1272 }
1273 break;
1274 default: UNDEF(ir);
1275 }
1276 break;
1277 case 9: /* 1001xxxxxxxxxxxx */
1278 /* MOV.W [disp8*2 + pc + 4], Rn */
1279 CHECKSLOTILLEGAL();
1280 tmp = pc + 4 + (DISP8(ir)<<1);
1281 RN(ir) = MEM_READ_WORD( tmp );
1282 break;
1283 case 10:/* 1010dddddddddddd */
1284 /* BRA disp12 */
1285 CHECKSLOTILLEGAL();
1286 CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 );
1287 sh4r.in_delay_slot = 1;
1288 sh4r.pc = sh4r.new_pc;
1289 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
1290 return TRUE;
1291 case 11:/* 1011dddddddddddd */
1292 /* BSR disp12 */
1293 CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 );
1294 CHECKSLOTILLEGAL();
1295 sh4r.in_delay_slot = 1;
1296 sh4r.pr = pc + 4;
1297 sh4r.pc = sh4r.new_pc;
1298 sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
1299 TRACE_CALL( pc, sh4r.new_pc );
1300 return TRUE;
1301 case 12:/* 1100xxxxdddddddd */
1302 switch( (ir&0x0F00)>>8 ) {
1303 case 0: /* MOV.B R0, [GBR + disp8] */
1304 MEM_WRITE_BYTE( sh4r.gbr + DISP8(ir), R0 );
1305 break;
1306 case 1: /* MOV.W R0, [GBR + disp8*2] */
1307 tmp = sh4r.gbr + (DISP8(ir)<<1);
1308 CHECKWALIGN16( tmp );
1309 MEM_WRITE_WORD( tmp, R0 );
1310 break;
1311 case 2: /*MOV.L R0, [GBR + disp8*4] */
1312 tmp = sh4r.gbr + (DISP8(ir)<<2);
1313 CHECKWALIGN32( tmp );
1314 MEM_WRITE_LONG( tmp, R0 );
1315 break;
1316 case 3: /* TRAPA imm8 */
1317 CHECKSLOTILLEGAL();
1318 MMIO_WRITE( MMU, TRA, UIMM8(ir)<<2 );
1319 sh4r.pc += 2;
1320 sh4_raise_exception( EXC_TRAP );
1321 break;
1322 case 4: /* MOV.B [GBR + disp8], R0 */
1323 R0 = MEM_READ_BYTE( sh4r.gbr + DISP8(ir) );
1324 break;
1325 case 5: /* MOV.W [GBR + disp8*2], R0 */
1326 tmp = sh4r.gbr + (DISP8(ir)<<1);
1327 CHECKRALIGN16( tmp );
1328 R0 = MEM_READ_WORD( tmp );
1329 break;
1330 case 6: /* MOV.L [GBR + disp8*4], R0 */
1331 tmp = sh4r.gbr + (DISP8(ir)<<2);
1332 CHECKRALIGN32( tmp );
1333 R0 = MEM_READ_LONG( tmp );
1334 break;
1335 case 7: /* MOVA disp8 + pc&~3 + 4, R0 */
1336 CHECKSLOTILLEGAL();
1337 R0 = (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4;
1338 break;
1339 case 8: /* TST imm8, R0 */
1340 sh4r.t = (R0 & UIMM8(ir) ? 0 : 1);
1341 break;
1342 case 9: /* AND imm8, R0 */
1343 R0 &= UIMM8(ir);
1344 break;
1345 case 10:/* XOR imm8, R0 */
1346 R0 ^= UIMM8(ir);
1347 break;
1348 case 11:/* OR imm8, R0 */
1349 R0 |= UIMM8(ir);
1350 break;
1351 case 12:/* TST.B imm8, [R0+GBR] */
1352 sh4r.t = ( MEM_READ_BYTE(R0 + sh4r.gbr) & UIMM8(ir) ? 0 : 1 );
1353 break;
1354 case 13:/* AND.B imm8, [R0+GBR] */
1355 MEM_WRITE_BYTE( R0 + sh4r.gbr,
1356 UIMM8(ir) & MEM_READ_BYTE(R0 + sh4r.gbr) );
1357 break;
1358 case 14:/* XOR.B imm8, [R0+GBR] */
1359 MEM_WRITE_BYTE( R0 + sh4r.gbr,
1360 UIMM8(ir) ^ MEM_READ_BYTE(R0 + sh4r.gbr) );
1361 break;
1362 case 15:/* OR.B imm8, [R0+GBR] */
1363 MEM_WRITE_BYTE( R0 + sh4r.gbr,
1364 UIMM8(ir) | MEM_READ_BYTE(R0 + sh4r.gbr) );
1365 break;
1366 }
1367 break;
1368 case 13:/* 1101nnnndddddddd */
1369 /* MOV.L [disp8*4 + pc&~3 + 4], Rn */
1370 CHECKSLOTILLEGAL();
1371 tmp = (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4;
1372 RN(ir) = MEM_READ_LONG( tmp );
1373 break;
1374 case 14:/* 1110nnnniiiiiiii */
1375 /* MOV imm8, Rn */
1376 RN(ir) = IMM8(ir);
1377 break;
1378 case 15:/* 1111xxxxxxxxxxxx */
1379 CHECKFPUEN();
1380 if( IS_FPU_DOUBLEPREC() ) {
1381 switch( ir&0x000F ) {
1382 case 0: /* FADD FRm, FRn */
1383 DRN(ir) += DRM(ir);
1384 break;
1385 case 1: /* FSUB FRm, FRn */
1386 DRN(ir) -= DRM(ir);
1387 break;
1388 case 2: /* FMUL FRm, FRn */
1389 DRN(ir) = DRN(ir) * DRM(ir);
1390 break;
1391 case 3: /* FDIV FRm, FRn */
1392 DRN(ir) = DRN(ir) / DRM(ir);
1393 break;
1394 case 4: /* FCMP/EQ FRm, FRn */
1395 sh4r.t = ( DRN(ir) == DRM(ir) ? 1 : 0 );
1396 break;
1397 case 5: /* FCMP/GT FRm, FRn */
1398 sh4r.t = ( DRN(ir) > DRM(ir) ? 1 : 0 );
1399 break;
1400 case 6: /* FMOV.S [Rm+R0], FRn */
1401 MEM_FP_READ( RM(ir) + R0, FRNn(ir) );
1402 break;
1403 case 7: /* FMOV.S FRm, [Rn+R0] */
1404 MEM_FP_WRITE( RN(ir) + R0, FRMn(ir) );
1405 break;
1406 case 8: /* FMOV.S [Rm], FRn */
1407 MEM_FP_READ( RM(ir), FRNn(ir) );
1408 break;
1409 case 9: /* FMOV.S [Rm++], FRn */
1410 MEM_FP_READ( RM(ir), FRNn(ir) );
1411 RM(ir) += FP_WIDTH;
1412 break;
1413 case 10:/* FMOV.S FRm, [Rn] */
1414 MEM_FP_WRITE( RN(ir), FRMn(ir) );
1415 break;
1416 case 11:/* FMOV.S FRm, [--Rn] */
1417 RN(ir) -= FP_WIDTH;
1418 MEM_FP_WRITE( RN(ir), FRMn(ir) );
1419 break;
1420 case 12:/* FMOV FRm, FRn */
1421 if( IS_FPU_DOUBLESIZE() )
1422 DRN(ir) = DRM(ir);
1423 else
1424 FRN(ir) = FRM(ir);
1425 break;
1426 case 13:
1427 switch( (ir&0x00F0) >> 4 ) {
1428 case 0: /* FSTS FPUL, FRn */
1429 FRN(ir) = FPULf;
1430 break;
1431 case 1: /* FLDS FRn,FPUL */
1432 FPULf = FRN(ir);
1433 break;
1434 case 2: /* FLOAT FPUL, FRn */
1435 DRN(ir) = (float)FPULi;
1436 break;
1437 case 3: /* FTRC FRn, FPUL */
1438 dtmp = DRN(ir);
1439 if( dtmp >= MAX_INTF )
1440 FPULi = MAX_INT;
1441 else if( dtmp <= MIN_INTF )
1442 FPULi = MIN_INT;
1443 else
1444 FPULi = (int32_t)dtmp;
1445 break;
1446 case 4: /* FNEG FRn */
1447 DRN(ir) = -DRN(ir);
1448 break;
1449 case 5: /* FABS FRn */
1450 DRN(ir) = fabs(DRN(ir));
1451 break;
1452 case 6: /* FSQRT FRn */
1453 DRN(ir) = sqrt(DRN(ir));
1454 break;
1455 case 7: /* FSRRA FRn */
1456 /* NO-OP when PR=1 */
1457 break;
1458 case 8: /* FLDI0 FRn */
1459 DRN(ir) = 0.0;
1460 break;
1461 case 9: /* FLDI1 FRn */
1462 DRN(ir) = 1.0;
1463 break;
1464 case 10: /* FCNVSD FPUL, DRn */
1465 if( ! IS_FPU_DOUBLESIZE() )
1466 DRN(ir) = (double)FPULf;
1467 break;
1468 case 11: /* FCNVDS DRn, FPUL */
1469 if( ! IS_FPU_DOUBLESIZE() )
1470 FPULf = (float)DRN(ir);
1471 break;
1472 case 14:/* FIPR FVm, FVn */
1473 /* NO-OP when PR=1 */
1474 break;
1475 case 15:
1476 if( (ir&0x0300) == 0x0100 ) { /* FTRV XMTRX,FVn */
1477 /* NO-OP when PR=1 */
1478 break;
1479 }
1480 else if( (ir&0x0100) == 0 ) { /* FSCA FPUL, DRn */
1481 /* NO-OP when PR=1 */
1482 break;
1483 }
1484 else if( ir == 0xFBFD ) {
1485 /* FRCHG */
1486 sh4r.fpscr ^= FPSCR_FR;
1487 break;
1488 }
1489 else if( ir == 0xF3FD ) {
1490 /* FSCHG */
1491 sh4r.fpscr ^= FPSCR_SZ;
1492 break;
1493 }
1494 default: UNDEF(ir);
1495 }
1496 break;
1497 case 14:/* FMAC FR0, FRm, FRn */
1498 DRN(ir) += DRM(ir)*DR0;
1499 break;
1500 default: UNDEF(ir);
1501 }
1502 } else { /* Single precision */
1503 switch( ir&0x000F ) {
1504 case 0: /* FADD FRm, FRn */
1505 FRN(ir) += FRM(ir);
1506 break;
1507 case 1: /* FSUB FRm, FRn */
1508 FRN(ir) -= FRM(ir);
1509 break;
1510 case 2: /* FMUL FRm, FRn */
1511 FRN(ir) = FRN(ir) * FRM(ir);
1512 break;
1513 case 3: /* FDIV FRm, FRn */
1514 FRN(ir) = FRN(ir) / FRM(ir);
1515 break;
1516 case 4: /* FCMP/EQ FRm, FRn */
1517 sh4r.t = ( FRN(ir) == FRM(ir) ? 1 : 0 );
1518 break;
1519 case 5: /* FCMP/GT FRm, FRn */
1520 sh4r.t = ( FRN(ir) > FRM(ir) ? 1 : 0 );
1521 break;
1522 case 6: /* FMOV.S [Rm+R0], FRn */
1523 MEM_FP_READ( RM(ir) + R0, FRNn(ir) );
1524 break;
1525 case 7: /* FMOV.S FRm, [Rn+R0] */
1526 MEM_FP_WRITE( RN(ir) + R0, FRMn(ir) );
1527 break;
1528 case 8: /* FMOV.S [Rm], FRn */
1529 MEM_FP_READ( RM(ir), FRNn(ir) );
1530 break;
1531 case 9: /* FMOV.S [Rm++], FRn */
1532 MEM_FP_READ( RM(ir), FRNn(ir) );
1533 RM(ir) += FP_WIDTH;
1534 break;
1535 case 10:/* FMOV.S FRm, [Rn] */
1536 MEM_FP_WRITE( RN(ir), FRMn(ir) );
1537 break;
1538 case 11:/* FMOV.S FRm, [--Rn] */
1539 RN(ir) -= FP_WIDTH;
1540 MEM_FP_WRITE( RN(ir), FRMn(ir) );
1541 break;
1542 case 12:/* FMOV FRm, FRn */
1543 if( IS_FPU_DOUBLESIZE() )
1544 DRN(ir) = DRM(ir);
1545 else
1546 FRN(ir) = FRM(ir);
1547 break;
1548 case 13:
1549 switch( (ir&0x00F0) >> 4 ) {
1550 case 0: /* FSTS FPUL, FRn */
1551 FRN(ir) = FPULf;
1552 break;
1553 case 1: /* FLDS FRn,FPUL */
1554 FPULf = FRN(ir);
1555 break;
1556 case 2: /* FLOAT FPUL, FRn */
1557 FRN(ir) = (float)FPULi;
1558 break;
1559 case 3: /* FTRC FRn, FPUL */
1560 ftmp = FRN(ir);
1561 if( ftmp >= MAX_INTF )
1562 FPULi = MAX_INT;
1563 else if( ftmp <= MIN_INTF )
1564 FPULi = MIN_INT;
1565 else
1566 FPULi = (int32_t)ftmp;
1567 break;
1568 case 4: /* FNEG FRn */
1569 FRN(ir) = -FRN(ir);
1570 break;
1571 case 5: /* FABS FRn */
1572 FRN(ir) = fabsf(FRN(ir));
1573 break;
1574 case 6: /* FSQRT FRn */
1575 FRN(ir) = sqrtf(FRN(ir));
1576 break;
1577 case 7: /* FSRRA FRn */
1578 FRN(ir) = 1.0/sqrtf(FRN(ir));
1579 break;
1580 case 8: /* FLDI0 FRn */
1581 FRN(ir) = 0.0;
1582 break;
1583 case 9: /* FLDI1 FRn */
1584 FRN(ir) = 1.0;
1585 break;
1586 case 10: /* FCNVSD FPUL, DRn */
1587 break;
1588 case 11: /* FCNVDS DRn, FPUL */
1589 break;
1590 case 14:/* FIPR FVm, FVn */
1591 /* FIXME: This is not going to be entirely accurate
1592 * as the SH4 instruction is less precise. Also
1593 * need to check for 0s and infinities.
1594 */
1595 {
1596 int tmp2 = FVN(ir);
1597 tmp = FVM(ir);
1598 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1599 FR(tmp+1)*FR(tmp2+1) +
1600 FR(tmp+2)*FR(tmp2+2) +
1601 FR(tmp+3)*FR(tmp2+3);
1602 break;
1603 }
1604 case 15:
1605 if( (ir&0x0300) == 0x0100 ) { /* FTRV XMTRX,FVn */
1606 tmp = FVN(ir);
1607 float fv[4] = { FR(tmp), FR(tmp+1), FR(tmp+2), FR(tmp+3) };
1608 FR(tmp) = XF(0) * fv[0] + XF(4)*fv[1] +
1609 XF(8)*fv[2] + XF(12)*fv[3];
1610 FR(tmp+1) = XF(1) * fv[0] + XF(5)*fv[1] +
1611 XF(9)*fv[2] + XF(13)*fv[3];
1612 FR(tmp+2) = XF(2) * fv[0] + XF(6)*fv[1] +
1613 XF(10)*fv[2] + XF(14)*fv[3];
1614 FR(tmp+3) = XF(3) * fv[0] + XF(7)*fv[1] +
1615 XF(11)*fv[2] + XF(15)*fv[3];
1616 break;
1617 }
1618 else if( (ir&0x0100) == 0 ) { /* FSCA FPUL, DRn */
1619 float angle = (((float)(short)(FPULi>>16)) +
1620 (((float)(FPULi&0xFFFF))/65536.0)) *
1621 2 * M_PI;
1622 int reg = FRNn(ir);
1623 FR(reg) = sinf(angle);
1624 FR(reg+1) = cosf(angle);
1625 break;
1626 }
1627 else if( ir == 0xFBFD ) {
1628 /* FRCHG */
1629 sh4r.fpscr ^= FPSCR_FR;
1630 break;
1631 }
1632 else if( ir == 0xF3FD ) {
1633 /* FSCHG */
1634 sh4r.fpscr ^= FPSCR_SZ;
1635 break;
1636 }
1637 default: UNDEF(ir);
1638 }
1639 break;
1640 case 14:/* FMAC FR0, FRm, FRn */
1641 FRN(ir) += FRM(ir)*FR0;
1642 break;
1643 default: UNDEF(ir);
1644 }
1645 }
1646 break;
1647 }
1648 sh4r.pc = sh4r.new_pc;
1649 sh4r.new_pc += 2;
1650 sh4r.in_delay_slot = 0;
1651 }
.