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