2 * $Id: sh4core.in,v 1.7 2007-09-18 09:14:20 nkeynes Exp $
4 * SH4 emulation core, and parent module for all the SH4 peripheral
7 * Copyright (c) 2005 Nathan Keynes.
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.
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.
20 #define MODULE sh4_module
23 #include "sh4/sh4core.h"
24 #include "sh4/sh4mmio.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 #define EXV_EXCEPTION 0x100 /* General exception vector */
38 #define EXV_TLBMISS 0x400 /* TLB-miss exception vector */
39 #define EXV_INTERRUPT 0x600 /* External interrupt vector */
41 /********************** SH4 Module Definition ****************************/
43 uint32_t sh4_run_slice( uint32_t );
45 uint16_t *sh4_icache = NULL;
46 uint32_t sh4_icache_addr = 0;
48 uint32_t sh4_run_slice( uint32_t nanosecs )
53 if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
54 if( sh4r.event_pending < nanosecs ) {
55 sh4r.sh4_state = SH4_STATE_RUNNING;
56 sh4r.slice_cycle = sh4r.event_pending;
60 if( sh4_breakpoint_count == 0 ) {
61 for( ; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
62 if( SH4_EVENT_PENDING() ) {
63 if( sh4r.event_types & PENDING_EVENT ) {
66 /* Eventq execute may (quite likely) deliver an immediate IRQ */
67 if( sh4r.event_types & PENDING_IRQ ) {
68 sh4_accept_interrupt();
71 // sh4_stats_add( sh4r.pc );
72 if( !sh4_execute_instruction() ) {
77 for( ;sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
78 if( SH4_EVENT_PENDING() ) {
79 if( sh4r.event_types & PENDING_EVENT ) {
82 /* Eventq execute may (quite likely) deliver an immediate IRQ */
83 if( sh4r.event_types & PENDING_IRQ ) {
84 sh4_accept_interrupt();
88 if( !sh4_execute_instruction() )
90 #ifdef ENABLE_DEBUG_MODE
91 for( i=0; i<sh4_breakpoint_count; i++ ) {
92 if( sh4_breakpoints[i].address == sh4r.pc ) {
96 if( i != sh4_breakpoint_count ) {
98 if( sh4_breakpoints[i].type == BREAK_ONESHOT )
99 sh4_clear_breakpoint( sh4r.pc, BREAK_ONESHOT );
106 /* If we aborted early, but the cpu is still technically running,
107 * we're doing a hard abort - cut the timeslice back to what we
110 if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
111 nanosecs = sh4r.slice_cycle;
113 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
114 TMU_run_slice( nanosecs );
115 SCIF_run_slice( nanosecs );
120 /********************** SH4 emulation core ****************************/
122 void sh4_set_pc( int pc )
128 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
129 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)
131 #if(SH4_CALLTRACE == 1)
132 #define MAX_CALLSTACK 32
133 static struct call_stack {
135 sh4addr_t target_addr;
136 sh4addr_t stack_pointer;
137 } call_stack[MAX_CALLSTACK];
139 static int call_stack_depth = 0;
140 int sh4_call_trace_on = 0;
142 static inline trace_call( sh4addr_t source, sh4addr_t dest )
144 if( call_stack_depth < MAX_CALLSTACK ) {
145 call_stack[call_stack_depth].call_addr = source;
146 call_stack[call_stack_depth].target_addr = dest;
147 call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
152 static inline trace_return( sh4addr_t source, sh4addr_t dest )
154 if( call_stack_depth > 0 ) {
159 void fprint_stack_trace( FILE *f )
161 int i = call_stack_depth -1;
162 if( i >= MAX_CALLSTACK )
163 i = MAX_CALLSTACK - 1;
164 for( ; i >= 0; i-- ) {
165 fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n",
166 (call_stack_depth - i), call_stack[i].call_addr,
167 call_stack[i].target_addr, call_stack[i].stack_pointer );
171 #define TRACE_CALL( source, dest ) trace_call(source, dest)
172 #define TRACE_RETURN( source, dest ) trace_return(source, dest)
174 #define TRACE_CALL( dest, rts )
175 #define TRACE_RETURN( source, dest )
178 #define RAISE( x, v ) do{ \
179 if( sh4r.vbr == 0 ) { \
180 ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \
181 dreamcast_stop(); return FALSE; \
183 sh4r.spc = sh4r.pc; \
184 sh4r.ssr = sh4_read_sr(); \
185 sh4r.sgr = sh4r.r[15]; \
186 MMIO_WRITE(MMU,EXPEVT,x); \
187 sh4r.pc = sh4r.vbr + v; \
188 sh4r.new_pc = sh4r.pc + 2; \
189 sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
190 if( sh4r.in_delay_slot ) { \
191 sh4r.in_delay_slot = 0; \
195 return TRUE; } while(0)
197 #define MEM_READ_BYTE( addr ) sh4_read_byte(addr)
198 #define MEM_READ_WORD( addr ) sh4_read_word(addr)
199 #define MEM_READ_LONG( addr ) sh4_read_long(addr)
200 #define MEM_WRITE_BYTE( addr, val ) sh4_write_byte(addr, val)
201 #define MEM_WRITE_WORD( addr, val ) sh4_write_word(addr, val)
202 #define MEM_WRITE_LONG( addr, val ) sh4_write_long(addr, val)
204 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
206 #define MEM_FP_READ( addr, reg ) sh4_read_float( addr, reg );
207 #define MEM_FP_WRITE( addr, reg ) sh4_write_float( addr, reg );
209 #define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )
210 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
211 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
212 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
213 #define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
215 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
216 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); dreamcast_stop(); return FALSE; }
217 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)
219 static void sh4_switch_banks( )
223 memcpy( tmp, sh4r.r, sizeof(uint32_t)*8 );
224 memcpy( sh4r.r, sh4r.r_bank, sizeof(uint32_t)*8 );
225 memcpy( sh4r.r_bank, tmp, sizeof(uint32_t)*8 );
228 void sh4_write_sr( uint32_t newval )
230 if( (newval ^ sh4r.sr) & SR_RB )
233 sh4r.t = (newval&SR_T) ? 1 : 0;
234 sh4r.s = (newval&SR_S) ? 1 : 0;
235 sh4r.m = (newval&SR_M) ? 1 : 0;
236 sh4r.q = (newval&SR_Q) ? 1 : 0;
240 static void sh4_write_float( uint32_t addr, int reg )
242 if( IS_FPU_DOUBLESIZE() ) {
244 sh4_write_long( addr, *((uint32_t *)&XF((reg)&0x0E)) );
245 sh4_write_long( addr+4, *((uint32_t *)&XF(reg)) );
247 sh4_write_long( addr, *((uint32_t *)&FR(reg)) );
248 sh4_write_long( addr+4, *((uint32_t *)&FR((reg)|0x01)) );
251 sh4_write_long( addr, *((uint32_t *)&FR((reg))) );
255 static void sh4_read_float( uint32_t addr, int reg )
257 if( IS_FPU_DOUBLESIZE() ) {
259 *((uint32_t *)&XF((reg) & 0x0E)) = sh4_read_long(addr);
260 *((uint32_t *)&XF(reg)) = sh4_read_long(addr+4);
262 *((uint32_t *)&FR(reg)) = sh4_read_long(addr);
263 *((uint32_t *)&FR((reg) | 0x01)) = sh4_read_long(addr+4);
266 *((uint32_t *)&FR(reg)) = sh4_read_long(addr);
270 uint32_t sh4_read_sr( void )
272 /* synchronize sh4r.sr with the various bitflags */
273 sh4r.sr &= SR_MQSTMASK;
274 if( sh4r.t ) sh4r.sr |= SR_T;
275 if( sh4r.s ) sh4r.sr |= SR_S;
276 if( sh4r.m ) sh4r.sr |= SR_M;
277 if( sh4r.q ) sh4r.sr |= SR_Q;
282 * Raise a general CPU exception for the specified exception code.
283 * (NOT for TRAPA or TLB exceptions)
285 gboolean sh4_raise_exception( int code )
287 RAISE( code, EXV_EXCEPTION );
290 gboolean sh4_raise_trap( int trap )
292 MMIO_WRITE( MMU, TRA, trap<<2 );
293 return sh4_raise_exception( EXC_TRAP );
296 gboolean sh4_raise_slot_exception( int normal_code, int slot_code ) {
297 if( sh4r.in_delay_slot ) {
298 return sh4_raise_exception(slot_code);
300 return sh4_raise_exception(normal_code);
304 gboolean sh4_raise_tlb_exception( int code )
306 RAISE( code, EXV_TLBMISS );
309 void sh4_accept_interrupt( void )
311 uint32_t code = intc_accept_interrupt();
312 sh4r.ssr = sh4_read_sr();
314 sh4r.sgr = sh4r.r[15];
315 sh4_write_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
316 MMIO_WRITE( MMU, INTEVT, code );
317 sh4r.pc = sh4r.vbr + 0x600;
318 sh4r.new_pc = sh4r.pc + 2;
319 // WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );
322 gboolean sh4_execute_instruction( void )
332 if( pc > 0xFFFFFF00 ) {
334 syscall_invoke( pc );
335 sh4r.in_delay_slot = 0;
336 pc = sh4r.pc = sh4r.pr;
337 sh4r.new_pc = sh4r.pc + 2;
341 /* Read instruction */
342 uint32_t pageaddr = pc >> 12;
343 if( sh4_icache != NULL && pageaddr == sh4_icache_addr ) {
344 ir = sh4_icache[(pc&0xFFF)>>1];
346 sh4_icache = (uint16_t *)mem_get_page(pc);
347 if( ((uint32_t)sh4_icache) < MAX_IO_REGIONS ) {
348 /* If someone's actually been so daft as to try to execute out of an IO
349 * region, fallback on the full-blown memory read
352 ir = MEM_READ_WORD(pc);
354 sh4_icache_addr = pageaddr;
355 ir = sh4_icache[(pc&0xFFF)>>1];
359 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
360 AND #imm, R0 {: R0 &= imm; :}
361 AND.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & MEM_READ_BYTE(R0 + sh4r.gbr) ); :}
362 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
363 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
364 OR #imm, R0 {: R0 |= imm; :}
365 OR.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | MEM_READ_BYTE(R0 + sh4r.gbr) ); :}
367 tmp = MEM_READ_BYTE( sh4r.r[Rn] );
368 sh4r.t = ( tmp == 0 ? 1 : 0 );
369 MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
371 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
372 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
373 TST.B #imm, @(R0, GBR) {: sh4r.t = ( MEM_READ_BYTE(R0 + sh4r.gbr) & imm ? 0 : 1 ); :}
374 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
375 XOR #imm, R0 {: R0 ^= imm; :}
376 XOR.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ MEM_READ_BYTE(R0 + sh4r.gbr) ); :}
377 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
380 sh4r.t = sh4r.r[Rn] >> 31;
382 sh4r.r[Rn] |= sh4r.t;
385 sh4r.t = sh4r.r[Rn] & 0x00000001;
387 sh4r.r[Rn] |= (sh4r.t << 31);
390 tmp = sh4r.r[Rn] >> 31;
392 sh4r.r[Rn] |= sh4r.t;
396 tmp = sh4r.r[Rn] & 0x00000001;
398 sh4r.r[Rn] |= (sh4r.t << 31 );
403 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
404 else if( (tmp & 0x1F) == 0 )
405 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
407 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
411 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
412 else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
413 else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
416 sh4r.t = sh4r.r[Rn] >> 31;
420 sh4r.t = sh4r.r[Rn] & 0x00000001;
421 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
423 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
424 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
425 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
426 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
427 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
428 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
429 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
430 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
432 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
433 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
434 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
435 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
436 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
437 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
439 CLRT {: sh4r.t = 0; :}
440 SETT {: sh4r.t = 1; :}
441 CLRMAC {: sh4r.mac = 0; :}
442 LDTLB {: /* TODO */ :}
443 CLRS {: sh4r.s = 0; :}
444 SETS {: sh4r.s = 1; :}
445 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
450 if( (tmp & 0xFC000000) == 0xE0000000 ) {
451 sh4_flush_store_queue(tmp);
460 MEM_WRITE_LONG( tmp, R0 );
462 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
463 MOV.W Rm, @(R0, Rn) {:
464 CHECKWALIGN16( R0 + sh4r.r[Rn] );
465 MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
467 MOV.L Rm, @(R0, Rn) {:
468 CHECKWALIGN32( R0 + sh4r.r[Rn] );
469 MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
471 MOV.B @(R0, Rm), Rn {: sh4r.r[Rn] = MEM_READ_BYTE( R0 + sh4r.r[Rm] ); :}
472 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
473 sh4r.r[Rn] = MEM_READ_WORD( R0 + sh4r.r[Rm] );
475 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
476 sh4r.r[Rn] = MEM_READ_LONG( R0 + sh4r.r[Rm] );
478 MOV.L Rm, @(disp, Rn) {:
479 tmp = sh4r.r[Rn] + disp;
480 CHECKWALIGN32( tmp );
481 MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
483 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
484 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
485 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
486 MOV.B Rm, @-Rn {: sh4r.r[Rn] --; MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
487 MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
488 MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
489 MOV.L @(disp, Rm), Rn {:
490 tmp = sh4r.r[Rm] + disp;
491 CHECKRALIGN32( tmp );
492 sh4r.r[Rn] = MEM_READ_LONG( tmp );
494 MOV.B @Rm, Rn {: sh4r.r[Rn] = MEM_READ_BYTE( sh4r.r[Rm] ); :}
495 MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_WORD( sh4r.r[Rm] ); :}
496 MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_LONG( sh4r.r[Rm] ); :}
497 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
498 MOV.B @Rm+, Rn {: sh4r.r[Rn] = MEM_READ_BYTE( sh4r.r[Rm] ); sh4r.r[Rm] ++; :}
499 MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_WORD( sh4r.r[Rm] ); sh4r.r[Rm] += 2; :}
500 MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_LONG( sh4r.r[Rm] ); sh4r.r[Rm] += 4; :}
501 MOV.L @(disp, PC), Rn {:
503 tmp = (pc&0xFFFFFFFC) + disp + 4;
504 sh4r.r[Rn] = MEM_READ_LONG( tmp );
506 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
507 MOV.W R0, @(disp, GBR) {:
508 tmp = sh4r.gbr + disp;
509 CHECKWALIGN16( tmp );
510 MEM_WRITE_WORD( tmp, R0 );
512 MOV.L R0, @(disp, GBR) {:
513 tmp = sh4r.gbr + disp;
514 CHECKWALIGN32( tmp );
515 MEM_WRITE_LONG( tmp, R0 );
517 MOV.B @(disp, GBR), R0 {: R0 = MEM_READ_BYTE( sh4r.gbr + disp ); :}
518 MOV.W @(disp, GBR), R0 {:
519 tmp = sh4r.gbr + disp;
520 CHECKRALIGN16( tmp );
521 R0 = MEM_READ_WORD( tmp );
523 MOV.L @(disp, GBR), R0 {:
524 tmp = sh4r.gbr + disp;
525 CHECKRALIGN32( tmp );
526 R0 = MEM_READ_LONG( tmp );
528 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
529 MOV.W R0, @(disp, Rn) {:
530 tmp = sh4r.r[Rn] + disp;
531 CHECKWALIGN16( tmp );
532 MEM_WRITE_WORD( tmp, R0 );
534 MOV.B @(disp, Rm), R0 {: R0 = MEM_READ_BYTE( sh4r.r[Rm] + disp ); :}
535 MOV.W @(disp, Rm), R0 {:
536 tmp = sh4r.r[Rm] + disp;
537 CHECKRALIGN16( tmp );
538 R0 = MEM_READ_WORD( tmp );
540 MOV.W @(disp, PC), Rn {:
543 sh4r.r[Rn] = MEM_READ_WORD( tmp );
545 MOVA @(disp, PC), R0 {:
547 R0 = (pc&0xFFFFFFFC) + disp + 4;
549 MOV #imm, Rn {: sh4r.r[Rn] = imm; :}
551 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
552 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
553 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
554 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
555 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
556 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
557 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
558 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
560 /* set T = 1 if any byte in RM & RN is the same */
561 tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
562 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
563 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
566 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
567 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
570 sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
571 sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
574 tmp = sh4r.r[Rn] + sh4r.r[Rm];
575 sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
578 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
580 sh4r.q = sh4r.r[Rn]>>31;
581 sh4r.m = sh4r.r[Rm]>>31;
582 sh4r.t = sh4r.q ^ sh4r.m;
585 /* This is derived from the sh4 manual with some simplifications */
586 uint32_t tmp0, tmp1, tmp2, dir;
588 dir = sh4r.q ^ sh4r.m;
589 sh4r.q = (sh4r.r[Rn] >> 31);
591 sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
595 tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
598 tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
600 sh4r.q ^= sh4r.m ^ tmp1;
601 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
603 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
604 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
607 sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
610 CHECKRALIGN16( sh4r.r[Rn] );
611 CHECKRALIGN16( sh4r.r[Rm] );
612 int32_t stmp = SIGNEXT16(MEM_READ_WORD(sh4r.r[Rn]));
614 stmp = stmp * SIGNEXT16(MEM_READ_WORD(sh4r.r[Rm]));
617 int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
618 if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
619 sh4r.mac = 0x000000017FFFFFFFLL;
620 } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
621 sh4r.mac = 0x0000000180000000LL;
623 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
624 ((uint32_t)(sh4r.mac + stmp));
627 sh4r.mac += SIGNEXT32(stmp);
631 CHECKRALIGN32( sh4r.r[Rm] );
632 CHECKRALIGN32( sh4r.r[Rn] );
633 int64_t tmpl = SIGNEXT32(MEM_READ_LONG(sh4r.r[Rn]));
635 tmpl = tmpl * SIGNEXT32(MEM_READ_LONG(sh4r.r[Rm])) + sh4r.mac;
638 /* 48-bit Saturation. Yuch */
639 if( tmpl < (int64_t)0xFFFF800000000000LL )
640 tmpl = 0xFFFF800000000000LL;
641 else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
642 tmpl = 0x00007FFFFFFFFFFFLL;
646 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
647 (sh4r.r[Rm] * sh4r.r[Rn]); :}
649 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
650 (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
653 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
654 (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
657 tmp = 0 - sh4r.r[Rm];
658 sh4r.r[Rn] = tmp - sh4r.t;
659 sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
661 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
662 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
665 sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
666 sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
671 CHECKDEST( pc + 4 + sh4r.r[Rn] );
672 sh4r.in_delay_slot = 1;
673 sh4r.pc = sh4r.new_pc;
674 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
679 CHECKDEST( pc + 4 + sh4r.r[Rn] );
680 sh4r.in_delay_slot = 1;
681 sh4r.pr = sh4r.pc + 4;
682 sh4r.pc = sh4r.new_pc;
683 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
684 TRACE_CALL( pc, sh4r.new_pc );
690 CHECKDEST( sh4r.pc + disp + 4 )
692 sh4r.new_pc = sh4r.pc + 2;
699 CHECKDEST( sh4r.pc + disp + 4 )
701 sh4r.new_pc = sh4r.pc + 2;
708 CHECKDEST( sh4r.pc + disp + 4 )
709 sh4r.in_delay_slot = 1;
710 sh4r.pc = sh4r.new_pc;
711 sh4r.new_pc = pc + disp + 4;
712 sh4r.in_delay_slot = 1;
719 CHECKDEST( sh4r.pc + disp + 4 )
720 sh4r.in_delay_slot = 1;
721 sh4r.pc = sh4r.new_pc;
722 sh4r.new_pc = pc + disp + 4;
728 CHECKDEST( sh4r.pc + disp + 4 );
729 sh4r.in_delay_slot = 1;
730 sh4r.pc = sh4r.new_pc;
731 sh4r.new_pc = pc + 4 + disp;
735 CHECKDEST( sh4r.pc + disp + 4 );
737 sh4r.in_delay_slot = 1;
739 sh4r.pc = sh4r.new_pc;
740 sh4r.new_pc = pc + 4 + disp;
741 TRACE_CALL( pc, sh4r.new_pc );
746 MMIO_WRITE( MMU, TRA, imm<<2 );
748 sh4_raise_exception( EXC_TRAP );
752 CHECKDEST( sh4r.pr );
753 sh4r.in_delay_slot = 1;
754 sh4r.pc = sh4r.new_pc;
755 sh4r.new_pc = sh4r.pr;
756 TRACE_RETURN( pc, sh4r.new_pc );
760 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
761 sh4r.sh4_state = SH4_STATE_STANDBY;
763 sh4r.sh4_state = SH4_STATE_SLEEP;
765 return FALSE; /* Halt CPU */
769 CHECKDEST( sh4r.spc );
771 sh4r.in_delay_slot = 1;
772 sh4r.pc = sh4r.new_pc;
773 sh4r.new_pc = sh4r.spc;
774 sh4_write_sr( sh4r.ssr );
778 CHECKDEST( sh4r.r[Rn] );
780 sh4r.in_delay_slot = 1;
781 sh4r.pc = sh4r.new_pc;
782 sh4r.new_pc = sh4r.r[Rn];
786 CHECKDEST( sh4r.r[Rn] );
788 sh4r.in_delay_slot = 1;
789 sh4r.pc = sh4r.new_pc;
790 sh4r.new_pc = sh4r.r[Rn];
792 TRACE_CALL( pc, sh4r.new_pc );
795 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
798 CHECKWALIGN32( sh4r.r[Rn] );
799 MEM_WRITE_LONG( sh4r.r[Rn], (sh4r.mac>>32) );
804 CHECKWALIGN32( sh4r.r[Rn] );
805 MEM_WRITE_LONG( sh4r.r[Rn], sh4_read_sr() );
808 CHECKRALIGN32( sh4r.r[Rm] );
809 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
810 (((uint64_t)MEM_READ_LONG(sh4r.r[Rm]))<<32);
816 CHECKWALIGN32( sh4r.r[Rm] );
817 sh4_write_sr( MEM_READ_LONG(sh4r.r[Rm]) );
821 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
822 (((uint64_t)sh4r.r[Rm])<<32);
827 sh4_write_sr( sh4r.r[Rm] );
831 sh4r.sgr = sh4r.r[Rm];
835 CHECKRALIGN32( sh4r.r[Rm] );
836 sh4r.sgr = MEM_READ_LONG(sh4r.r[Rm]);
839 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
842 CHECKWALIGN32( sh4r.r[Rn] );
843 MEM_WRITE_LONG( sh4r.r[Rn], (uint32_t)sh4r.mac );
847 CHECKWALIGN32( sh4r.r[Rn] );
848 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.gbr );
851 CHECKRALIGN32( sh4r.r[Rm] );
852 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
853 (uint64_t)((uint32_t)MEM_READ_LONG(sh4r.r[Rm]));
857 CHECKRALIGN32( sh4r.r[Rm] );
858 sh4r.gbr = MEM_READ_LONG(sh4r.r[Rm]);
862 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
863 (uint64_t)((uint32_t)(sh4r.r[Rm]));
865 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
866 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
869 CHECKWALIGN32( sh4r.r[Rn] );
870 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.pr );
875 CHECKWALIGN32( sh4r.r[Rn] );
876 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.vbr );
879 CHECKRALIGN32( sh4r.r[Rm] );
880 sh4r.pr = MEM_READ_LONG( sh4r.r[Rm] );
885 CHECKRALIGN32( sh4r.r[Rm] );
886 sh4r.vbr = MEM_READ_LONG(sh4r.r[Rm]);
889 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
892 sh4r.vbr = sh4r.r[Rm];
896 sh4r.r[Rn] = sh4r.sgr;
901 CHECKWALIGN32( sh4r.r[Rn] );
902 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.sgr );
907 CHECKWALIGN32( sh4r.r[Rn] );
908 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.ssr );
912 CHECKRALIGN32( sh4r.r[Rm] );
913 sh4r.ssr = MEM_READ_LONG(sh4r.r[Rm]);
918 sh4r.ssr = sh4r.r[Rm];
923 CHECKWALIGN32( sh4r.r[Rn] );
924 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.spc );
928 CHECKRALIGN32( sh4r.r[Rm] );
929 sh4r.spc = MEM_READ_LONG(sh4r.r[Rm]);
934 sh4r.spc = sh4r.r[Rm];
936 STS FPUL, Rn {: sh4r.r[Rn] = sh4r.fpul; :}
939 CHECKWALIGN32( sh4r.r[Rn] );
940 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.fpul );
943 CHECKRALIGN32( sh4r.r[Rm] );
944 sh4r.fpul = MEM_READ_LONG(sh4r.r[Rm]);
947 LDS Rm, FPUL {: sh4r.fpul = sh4r.r[Rm]; :}
948 STS FPSCR, Rn {: sh4r.r[Rn] = sh4r.fpscr; :}
951 CHECKWALIGN32( sh4r.r[Rn] );
952 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.fpscr );
955 CHECKRALIGN32( sh4r.r[Rm] );
956 sh4r.fpscr = MEM_READ_LONG(sh4r.r[Rm]);
958 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
961 sh4r.fpscr = sh4r.r[Rm];
962 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
964 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
968 CHECKWALIGN32( sh4r.r[Rn] );
969 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.dbr );
973 CHECKRALIGN32( sh4r.r[Rm] );
974 sh4r.dbr = MEM_READ_LONG(sh4r.r[Rm]);
979 sh4r.dbr = sh4r.r[Rm];
981 STC.L Rm_BANK, @-Rn {:
984 CHECKWALIGN32( sh4r.r[Rn] );
985 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r_bank[Rm_BANK] );
987 LDC.L @Rm+, Rn_BANK {:
989 CHECKRALIGN32( sh4r.r[Rm] );
990 sh4r.r_bank[Rn_BANK] = MEM_READ_LONG( sh4r.r[Rm] );
995 sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
999 sh4r.r[Rn] = sh4_read_sr();
1003 sh4r.r[Rn] = sh4r.gbr;
1007 sh4r.r[Rn] = sh4r.vbr;
1011 sh4r.r[Rn] = sh4r.ssr;
1015 sh4r.r[Rn] = sh4r.spc;
1019 sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
1024 if( IS_FPU_DOUBLEPREC() ) {
1032 if( IS_FPU_DOUBLEPREC() ) {
1041 if( IS_FPU_DOUBLEPREC() ) {
1050 if( IS_FPU_DOUBLEPREC() ) {
1059 if( IS_FPU_DOUBLEPREC() ) {
1060 sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
1062 sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
1068 if( IS_FPU_DOUBLEPREC() ) {
1069 sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
1071 sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
1075 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
1076 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
1077 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
1078 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
1079 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
1080 FMOV FRm, @-Rn {: sh4r.r[Rn] -= FP_WIDTH; MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
1082 if( IS_FPU_DOUBLESIZE() )
1087 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
1088 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
1091 if( IS_FPU_DOUBLEPREC() ) {
1092 if( FRn&1 ) { // No, really...
1093 dtmp = (double)FPULi;
1094 FR(FRn) = *(((float *)&dtmp)+1);
1096 DRF(FRn>>1) = (double)FPULi;
1099 FR(FRn) = (float)FPULi;
1104 if( IS_FPU_DOUBLEPREC() ) {
1107 *(((float *)&dtmp)+1) = FR(FRm);
1111 if( dtmp >= MAX_INTF )
1113 else if( dtmp <= MIN_INTF )
1116 FPULi = (int32_t)dtmp;
1119 if( ftmp >= MAX_INTF )
1121 else if( ftmp <= MIN_INTF )
1124 FPULi = (int32_t)ftmp;
1129 if( IS_FPU_DOUBLEPREC() ) {
1137 if( IS_FPU_DOUBLEPREC() ) {
1138 DR(FRn) = fabs(DR(FRn));
1140 FR(FRn) = fabsf(FR(FRn));
1145 if( IS_FPU_DOUBLEPREC() ) {
1146 DR(FRn) = sqrt(DR(FRn));
1148 FR(FRn) = sqrtf(FR(FRn));
1153 if( IS_FPU_DOUBLEPREC() ) {
1161 if( IS_FPU_DOUBLEPREC() ) {
1167 FMAC FR0, FRm, FRn {:
1169 if( IS_FPU_DOUBLEPREC() ) {
1170 DR(FRn) += DR(FRm)*DR(0);
1172 FR(FRn) += FR(FRm)*FR(0);
1177 sh4r.fpscr ^= FPSCR_FR;
1178 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
1180 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
1183 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1184 DR(FRn) = (double)FPULf;
1189 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1190 FPULf = (float)DR(FRm);
1196 if( !IS_FPU_DOUBLEPREC() ) {
1197 FR(FRn) = 1.0/sqrtf(FR(FRn));
1202 if( !IS_FPU_DOUBLEPREC() ) {
1205 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1206 FR(tmp+1)*FR(tmp2+1) +
1207 FR(tmp+2)*FR(tmp2+2) +
1208 FR(tmp+3)*FR(tmp2+3);
1213 if( !IS_FPU_DOUBLEPREC() ) {
1214 sh4_fsca( FPULi, &(DRF(FRn>>1)) );
1216 float angle = (((float)(FPULi&0xFFFF))/65536.0) * 2 * M_PI;
1217 FR(FRn) = sinf(angle);
1218 FR((FRn)+1) = cosf(angle);
1224 if( !IS_FPU_DOUBLEPREC() ) {
1225 sh4_ftrv(&(DRF(FVn<<1)), &sh4r.fr[((~sh4r.fpscr)&FPSCR_FR)>>21][0]);
1228 float *xf = &sh4r.fr[((~sh4r.fpscr)&FPSCR_FR)>>21][0];
1229 float fv[4] = { FR(tmp), FR(tmp+1), FR(tmp+2), FR(tmp+3) };
1230 FR(tmp) = xf[1] * fv[0] + xf[5]*fv[1] +
1231 xf[9]*fv[2] + xf[13]*fv[3];
1232 FR(tmp+1) = xf[0] * fv[0] + xf[4]*fv[1] +
1233 xf[8]*fv[2] + xf[12]*fv[3];
1234 FR(tmp+2) = xf[3] * fv[0] + xf[7]*fv[1] +
1235 xf[11]*fv[2] + xf[15]*fv[3];
1236 FR(tmp+3) = xf[2] * fv[0] + xf[6]*fv[1] +
1237 xf[10]*fv[2] + xf[14]*fv[3];
1245 sh4r.pc = sh4r.new_pc;
1247 sh4r.in_delay_slot = 0;
.