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
24 #include "dreamcast.h"
29 #include "sh4/sh4core.h"
30 #include "sh4/sh4mmio.h"
31 #include "sh4/sh4stat.h"
34 #define SH4_CALLTRACE 1
36 #define MAX_INT 0x7FFFFFFF
37 #define MIN_INT 0x80000000
38 #define MAX_INTF 2147483647.0
39 #define MIN_INTF -2147483648.0
41 /********************** SH4 Module Definition ****************************/
43 uint32_t sh4_emulate_run_slice( uint32_t nanosecs )
47 if( sh4_breakpoint_count == 0 ) {
48 for( ; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
49 if( SH4_EVENT_PENDING() ) {
50 sh4_handle_pending_events();
52 if( !sh4_execute_instruction() ) {
57 for( ;sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
58 if( SH4_EVENT_PENDING() ) {
59 sh4_handle_pending_events();
62 if( !sh4_execute_instruction() )
64 #ifdef ENABLE_DEBUG_MODE
65 for( i=0; i<sh4_breakpoint_count; i++ ) {
66 if( sh4_breakpoints[i].address == sh4r.pc ) {
70 if( i != sh4_breakpoint_count ) {
71 sh4_core_exit( CORE_EXIT_BREAKPOINT );
77 /* If we aborted early, but the cpu is still technically running,
78 * we're doing a hard abort - cut the timeslice back to what we
81 if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
82 nanosecs = sh4r.slice_cycle;
84 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
85 TMU_run_slice( nanosecs );
86 SCIF_run_slice( nanosecs );
91 /********************** SH4 emulation core ****************************/
93 #if(SH4_CALLTRACE == 1)
94 #define MAX_CALLSTACK 32
95 static struct call_stack {
97 sh4addr_t target_addr;
98 sh4addr_t stack_pointer;
99 } call_stack[MAX_CALLSTACK];
101 static int call_stack_depth = 0;
102 int sh4_call_trace_on = 0;
104 static inline void trace_call( sh4addr_t source, sh4addr_t dest )
106 if( call_stack_depth < MAX_CALLSTACK ) {
107 call_stack[call_stack_depth].call_addr = source;
108 call_stack[call_stack_depth].target_addr = dest;
109 call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
114 static inline void trace_return( sh4addr_t source, sh4addr_t dest )
116 if( call_stack_depth > 0 ) {
121 void fprint_stack_trace( FILE *f )
123 int i = call_stack_depth -1;
124 if( i >= MAX_CALLSTACK )
125 i = MAX_CALLSTACK - 1;
126 for( ; i >= 0; i-- ) {
127 fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n",
128 (call_stack_depth - i), call_stack[i].call_addr,
129 call_stack[i].target_addr, call_stack[i].stack_pointer );
133 #define TRACE_CALL( source, dest ) trace_call(source, dest)
134 #define TRACE_RETURN( source, dest ) trace_return(source, dest)
136 #define TRACE_CALL( dest, rts )
137 #define TRACE_RETURN( source, dest )
140 static gboolean FASTCALL sh4_raise_slot_exception( int normal_code, int slot_code ) {
141 if( sh4r.in_delay_slot ) {
142 sh4_raise_exception(slot_code);
144 sh4_raise_exception(normal_code);
150 #define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) { return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL ); }
151 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
152 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
153 #define CHECKRALIGN64(addr) if( (addr)&0x07 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
154 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
155 #define CHECKWALIGN32(addr) if( (addr)&0x03 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
156 #define CHECKWALIGN64(addr) if( (addr)&0x07 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
158 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
159 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }
160 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) { sh4_raise_exception(EXC_SLOT_ILLEGAL); return TRUE; }
162 #define ADDRSPACE (IS_SH4_PRIVMODE() ? sh4_address_space : sh4_user_address_space)
163 #define SQADDRSPACE (IS_SH4_PRIVMODE() ? storequeue_address_space : storequeue_user_address_space)
165 #ifdef HAVE_FRAME_ADDRESS
166 static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }
167 #define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:
168 #define MEM_READ_BYTE( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_byte)((addr), &&except)
169 #define MEM_READ_BYTE_FOR_WRITE( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_byte_for_write)((addr), &&except)
170 #define MEM_READ_WORD( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_word)((addr), &&except)
171 #define MEM_READ_LONG( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_long)((addr), &&except)
172 #define MEM_WRITE_BYTE( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_byte)((addr), (val), &&except)
173 #define MEM_WRITE_WORD( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_word)((addr), (val), &&except)
174 #define MEM_WRITE_LONG( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_long)((addr), (val), &&except)
175 #define MEM_PREFETCH( addr ) ((mem_prefetch_exc_fn_t)ADDRSPACE[(addr)>>12]->prefetch)((addr), &&except)
177 #define INIT_EXCEPTIONS(label)
178 #define MEM_READ_BYTE( addr, val ) val = ADDRSPACE[(addr)>>12]->read_byte(addr)
179 #define MEM_READ_BYTE_FOR_WRITE( addr, val ) val = ADDRSPACE[(addr)>>12]->read_byte_for_write(addr)
180 #define MEM_READ_WORD( addr, val ) val = ADDRSPACE[(addr)>>12]->read_word(addr)
181 #define MEM_READ_LONG( addr, val ) val = ADDRSPACE[(addr)>>12]->read_long(addr)
182 #define MEM_WRITE_BYTE( addr, val ) ADDRSPACE[(addr)>>12]->write_byte(addr, val)
183 #define MEM_WRITE_WORD( addr, val ) ADDRSPACE[(addr)>>12]->write_word(addr, val)
184 #define MEM_WRITE_LONG( addr, val ) ADDRSPACE[(addr)>>12]->write_long(addr, val)
185 #define MEM_PREFETCH( addr ) ADDRSPACE[(addr)>>12]->prefetch(addr)
188 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
190 #define MEM_FP_READ( addr, reg ) \
191 if( IS_FPU_DOUBLESIZE() ) { \
192 CHECKRALIGN64(addr); \
194 MEM_READ_LONG( addr, *((uint32_t *)&XF((reg) & 0x0E)) ); \
195 MEM_READ_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
197 MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
198 MEM_READ_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
201 CHECKRALIGN32(addr); \
202 MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
204 #define MEM_FP_WRITE( addr, reg ) \
205 if( IS_FPU_DOUBLESIZE() ) { \
206 CHECKWALIGN64(addr); \
208 MEM_WRITE_LONG( addr, *((uint32_t *)&XF((reg)&0x0E)) ); \
209 MEM_WRITE_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
211 MEM_WRITE_LONG( addr, *((uint32_t *)&FR(reg)) ); \
212 MEM_WRITE_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
215 CHECKWALIGN32(addr); \
216 MEM_WRITE_LONG(addr, *((uint32_t *)&FR((reg))) ); \
223 * Perform instruction-completion following core exit of a partially completed
224 * instruction. NOTE: This is only allowed on memory writes, operation is not
225 * guaranteed in any other case.
227 void sh4_finalize_instruction( void )
232 if( IS_SYSCALL(sh4r.pc) ) {
235 assert( IS_IN_ICACHE(sh4r.pc) );
236 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
239 * Note - we can't take an exit on a control transfer instruction itself,
240 * which means the exit must have happened in the delay slot. So for these
241 * cases, finalize the delay slot instruction, and re-execute the control transfer.
243 * For delay slots which modify the argument used in the branch instruction,
244 * we pretty much just assume that that can't have already happened in an exit case.
250 sh4_finalize_instruction();
256 sh4_finalize_instruction();
260 /* Note: PR is already set */
262 sh4_finalize_instruction();
266 /* Note: PR is already set */
269 sh4_finalize_instruction();
274 sh4_finalize_instruction();
281 sh4_finalize_instruction();
289 sh4_finalize_instruction();
291 sh4r.new_pc = tmp + 2;
292 sh4r.slice_cycle += sh4_cpu_period;
296 /* Note: PR is already set */
299 sh4_finalize_instruction();
301 sh4r.new_pc = tmp + 2;
302 sh4r.slice_cycle += sh4_cpu_period;
307 sh4_finalize_instruction();
309 sh4r.new_pc = sh4r.pr + 2;
310 sh4r.slice_cycle += sh4_cpu_period;
314 /* SR is already set */
316 sh4_finalize_instruction();
318 sh4r.new_pc = sh4r.pr + 2;
319 sh4r.slice_cycle += sh4_cpu_period;
322 MOV.B Rm, @-Rn {: sh4r.r[Rn]--; :}
323 MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; :}
324 MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; :}
325 MOV.B @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
326 MOV.W @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
327 MOV.L @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
329 sh4r.in_delay_slot = 0;
331 sh4r.new_pc = sh4r.pc+2;
332 sh4r.slice_cycle += sh4_cpu_period;
338 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
339 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }while(0)
342 gboolean sh4_execute_instruction( void )
349 int64_t memtmp; // temporary holder for memory reads
351 INIT_EXCEPTIONS(except)
355 if( pc > 0xFFFFFF00 ) {
357 sh4r.in_delay_slot = 0;
359 sh4r.new_pc = sh4r.pc + 2;
360 syscall_invoke( pc );
365 #ifdef ENABLE_SH4STATS
366 sh4_stats_add_by_pc(sh4r.pc);
369 /* Read instruction */
370 if( !IS_IN_ICACHE(pc) ) {
371 gboolean delay_slot = sh4r.in_delay_slot;
372 if( !mmu_update_icache(pc) ) {
376 // Fault - look for the fault handler
377 if( !mmu_update_icache(sh4r.pc) ) {
378 // double fault - halt
379 ERROR( "Double fault - halting" );
380 sh4_core_exit(CORE_EXIT_HALT);
386 assert( IS_IN_ICACHE(pc) );
387 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
389 /* FIXME: This is a bit of a hack, but the PC of the delay slot should not
390 * be visible until after the instruction has executed (for exception
393 if( sh4r.in_delay_slot ) {
397 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
398 AND #imm, R0 {: R0 &= imm; :}
399 AND.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & tmp ); :}
400 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
401 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
402 OR #imm, R0 {: R0 |= imm; :}
403 OR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | tmp ); :}
405 MEM_READ_BYTE_FOR_WRITE( sh4r.r[Rn], tmp );
406 sh4r.t = ( tmp == 0 ? 1 : 0 );
407 MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
409 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
410 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
411 TST.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); sh4r.t = ( tmp & imm ? 0 : 1 ); :}
412 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
413 XOR #imm, R0 {: R0 ^= imm; :}
414 XOR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ tmp ); :}
415 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
418 sh4r.t = sh4r.r[Rn] >> 31;
420 sh4r.r[Rn] |= sh4r.t;
423 sh4r.t = sh4r.r[Rn] & 0x00000001;
425 sh4r.r[Rn] |= (sh4r.t << 31);
428 tmp = sh4r.r[Rn] >> 31;
430 sh4r.r[Rn] |= sh4r.t;
434 tmp = sh4r.r[Rn] & 0x00000001;
436 sh4r.r[Rn] |= (sh4r.t << 31 );
441 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
442 else if( (tmp & 0x1F) == 0 )
443 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
445 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
449 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
450 else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
451 else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
454 sh4r.t = sh4r.r[Rn] >> 31;
458 sh4r.t = sh4r.r[Rn] & 0x00000001;
459 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
461 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
462 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
463 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
464 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
465 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
466 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
467 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
468 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
470 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
471 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
472 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
473 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
474 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
475 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
477 CLRT {: sh4r.t = 0; :}
478 SETT {: sh4r.t = 1; :}
479 CLRMAC {: sh4r.mac = 0; :}
480 LDTLB {: MMU_ldtlb(); :}
481 CLRS {: sh4r.s = 0; :}
482 SETS {: sh4r.s = 1; :}
483 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
487 MEM_PREFETCH(sh4r.r[Rn]);
495 MEM_WRITE_LONG( tmp, R0 );
497 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
498 MOV.W Rm, @(R0, Rn) {:
499 CHECKWALIGN16( R0 + sh4r.r[Rn] );
500 MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
502 MOV.L Rm, @(R0, Rn) {:
503 CHECKWALIGN32( R0 + sh4r.r[Rn] );
504 MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
506 MOV.B @(R0, Rm), Rn {: MEM_READ_BYTE( R0 + sh4r.r[Rm], sh4r.r[Rn] ); :}
507 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
508 MEM_READ_WORD( R0 + sh4r.r[Rm], sh4r.r[Rn] );
510 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
511 MEM_READ_LONG( R0 + sh4r.r[Rm], sh4r.r[Rn] );
513 MOV.L Rm, @(disp, Rn) {:
514 tmp = sh4r.r[Rn] + disp;
515 CHECKWALIGN32( tmp );
516 MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
518 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
519 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
520 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
521 MOV.B Rm, @-Rn {: MEM_WRITE_BYTE( sh4r.r[Rn]-1, sh4r.r[Rm] ); sh4r.r[Rn]--; :}
522 MOV.W Rm, @-Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn]-2, sh4r.r[Rm] ); sh4r.r[Rn] -= 2; :}
523 MOV.L Rm, @-Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r[Rm] ); sh4r.r[Rn] -= 4; :}
524 MOV.L @(disp, Rm), Rn {:
525 tmp = sh4r.r[Rm] + disp;
526 CHECKRALIGN32( tmp );
527 MEM_READ_LONG( tmp, sh4r.r[Rn] );
529 MOV.B @Rm, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); :}
530 MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); :}
531 MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); :}
532 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
533 MOV.B @Rm+, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
534 MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
535 MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
536 MOV.L @(disp, PC), Rn {:
538 tmp = (pc&0xFFFFFFFC) + disp + 4;
539 MEM_READ_LONG( tmp, sh4r.r[Rn] );
541 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
542 MOV.W R0, @(disp, GBR) {:
543 tmp = sh4r.gbr + disp;
544 CHECKWALIGN16( tmp );
545 MEM_WRITE_WORD( tmp, R0 );
547 MOV.L R0, @(disp, GBR) {:
548 tmp = sh4r.gbr + disp;
549 CHECKWALIGN32( tmp );
550 MEM_WRITE_LONG( tmp, R0 );
552 MOV.B @(disp, GBR), R0 {: MEM_READ_BYTE( sh4r.gbr + disp, R0 ); :}
553 MOV.W @(disp, GBR), R0 {:
554 tmp = sh4r.gbr + disp;
555 CHECKRALIGN16( tmp );
556 MEM_READ_WORD( tmp, R0 );
558 MOV.L @(disp, GBR), R0 {:
559 tmp = sh4r.gbr + disp;
560 CHECKRALIGN32( tmp );
561 MEM_READ_LONG( tmp, R0 );
563 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
564 MOV.W R0, @(disp, Rn) {:
565 tmp = sh4r.r[Rn] + disp;
566 CHECKWALIGN16( tmp );
567 MEM_WRITE_WORD( tmp, R0 );
569 MOV.B @(disp, Rm), R0 {: MEM_READ_BYTE( sh4r.r[Rm] + disp, R0 ); :}
570 MOV.W @(disp, Rm), R0 {:
571 tmp = sh4r.r[Rm] + disp;
572 CHECKRALIGN16( tmp );
573 MEM_READ_WORD( tmp, R0 );
575 MOV.W @(disp, PC), Rn {:
578 MEM_READ_WORD( tmp, sh4r.r[Rn] );
580 MOVA @(disp, PC), R0 {:
582 R0 = (pc&0xFFFFFFFC) + disp + 4;
584 MOV #imm, Rn {: sh4r.r[Rn] = imm; :}
586 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
587 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
588 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
589 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
590 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
591 FMOV FRm, @-Rn {: MEM_FP_WRITE( sh4r.r[Rn] - FP_WIDTH, FRm ); sh4r.r[Rn] -= FP_WIDTH; :}
593 if( IS_FPU_DOUBLESIZE() )
599 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
600 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
601 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
602 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
603 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
604 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
605 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
606 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
608 /* set T = 1 if any byte in RM & RN is the same */
609 tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
610 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
611 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
614 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
615 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
618 sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
619 sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
622 tmp = sh4r.r[Rn] + sh4r.r[Rm];
623 sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
626 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
628 sh4r.q = sh4r.r[Rn]>>31;
629 sh4r.m = sh4r.r[Rm]>>31;
630 sh4r.t = sh4r.q ^ sh4r.m;
633 /* This is derived from the sh4 manual with some simplifications */
634 uint32_t tmp0, tmp1, tmp2, dir;
636 dir = sh4r.q ^ sh4r.m;
637 sh4r.q = (sh4r.r[Rn] >> 31);
639 sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
643 tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
646 tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
648 sh4r.q ^= sh4r.m ^ tmp1;
649 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
651 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
652 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
655 sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
660 CHECKRALIGN16(sh4r.r[Rn]);
661 MEM_READ_WORD( sh4r.r[Rn], tmp );
662 stmp = SIGNEXT16(tmp);
663 MEM_READ_WORD( sh4r.r[Rn]+2, tmp );
664 stmp *= SIGNEXT16(tmp);
667 CHECKRALIGN16( sh4r.r[Rn] );
668 MEM_READ_WORD(sh4r.r[Rn], tmp);
669 stmp = SIGNEXT16(tmp);
670 CHECKRALIGN16( sh4r.r[Rm] );
671 MEM_READ_WORD(sh4r.r[Rm], tmp);
672 stmp = stmp * SIGNEXT16(tmp);
677 int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
678 if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
679 sh4r.mac = 0x000000017FFFFFFFLL;
680 } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
681 sh4r.mac = 0x0000000180000000LL;
683 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
684 ((uint32_t)(sh4r.mac + stmp));
687 sh4r.mac += SIGNEXT32(stmp);
693 CHECKRALIGN32( sh4r.r[Rn] );
694 MEM_READ_LONG(sh4r.r[Rn], tmp);
695 tmpl = SIGNEXT32(tmp);
696 MEM_READ_LONG(sh4r.r[Rn]+4, tmp);
697 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
700 CHECKRALIGN32( sh4r.r[Rm] );
701 CHECKRALIGN32( sh4r.r[Rn] );
702 MEM_READ_LONG(sh4r.r[Rn], tmp);
703 tmpl = SIGNEXT32(tmp);
704 MEM_READ_LONG(sh4r.r[Rm], tmp);
705 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
710 /* 48-bit Saturation. Yuch */
711 if( tmpl < (int64_t)0xFFFF800000000000LL )
712 tmpl = 0xFFFF800000000000LL;
713 else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
714 tmpl = 0x00007FFFFFFFFFFFLL;
718 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
719 (sh4r.r[Rm] * sh4r.r[Rn]); :}
721 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
722 (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
725 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
726 (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
729 tmp = 0 - sh4r.r[Rm];
730 sh4r.r[Rn] = tmp - sh4r.t;
731 sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
733 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
734 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
737 sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
738 sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
741 tmp = sh4r.r[Rn] - sh4r.r[Rm];
742 sh4r.t = ( (sh4r.r[Rn]>>31) != (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
747 CHECKDEST( pc + 4 + sh4r.r[Rn] );
748 sh4r.in_delay_slot = 1;
749 sh4r.pc = sh4r.new_pc;
750 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
755 CHECKDEST( pc + 4 + sh4r.r[Rn] );
756 sh4r.in_delay_slot = 1;
757 sh4r.pr = sh4r.pc + 4;
758 sh4r.pc = sh4r.new_pc;
759 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
760 TRACE_CALL( pc, sh4r.new_pc );
766 CHECKDEST( sh4r.pc + disp + 4 )
768 sh4r.new_pc = sh4r.pc + 2;
775 CHECKDEST( sh4r.pc + disp + 4 )
777 sh4r.new_pc = sh4r.pc + 2;
784 CHECKDEST( sh4r.pc + disp + 4 )
785 sh4r.in_delay_slot = 1;
786 sh4r.pc = sh4r.new_pc;
787 sh4r.new_pc = pc + disp + 4;
788 sh4r.in_delay_slot = 1;
795 CHECKDEST( sh4r.pc + disp + 4 )
796 sh4r.in_delay_slot = 1;
797 sh4r.pc = sh4r.new_pc;
798 sh4r.new_pc = pc + disp + 4;
804 CHECKDEST( sh4r.pc + disp + 4 );
805 sh4r.in_delay_slot = 1;
806 sh4r.pc = sh4r.new_pc;
807 sh4r.new_pc = pc + 4 + disp;
811 CHECKDEST( sh4r.pc + disp + 4 );
813 sh4r.in_delay_slot = 1;
815 sh4r.pc = sh4r.new_pc;
816 sh4r.new_pc = pc + 4 + disp;
817 TRACE_CALL( pc, sh4r.new_pc );
823 sh4_raise_trap( imm );
828 CHECKDEST( sh4r.pr );
829 sh4r.in_delay_slot = 1;
830 sh4r.pc = sh4r.new_pc;
831 sh4r.new_pc = sh4r.pr;
832 TRACE_RETURN( pc, sh4r.new_pc );
836 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
837 sh4r.sh4_state = SH4_STATE_STANDBY;
839 sh4r.sh4_state = SH4_STATE_SLEEP;
841 return FALSE; /* Halt CPU */
845 CHECKDEST( sh4r.spc );
847 sh4r.in_delay_slot = 1;
848 sh4r.pc = sh4r.new_pc;
849 sh4r.new_pc = sh4r.spc;
850 sh4_write_sr( sh4r.ssr );
854 CHECKDEST( sh4r.r[Rn] );
856 sh4r.in_delay_slot = 1;
857 sh4r.pc = sh4r.new_pc;
858 sh4r.new_pc = sh4r.r[Rn];
862 CHECKDEST( sh4r.r[Rn] );
864 sh4r.in_delay_slot = 1;
865 sh4r.pc = sh4r.new_pc;
866 sh4r.new_pc = sh4r.r[Rn];
868 TRACE_CALL( pc, sh4r.new_pc );
871 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
873 CHECKWALIGN32( sh4r.r[Rn] );
874 MEM_WRITE_LONG( sh4r.r[Rn]-4, (sh4r.mac>>32) );
879 CHECKWALIGN32( sh4r.r[Rn] );
880 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4_read_sr() );
884 CHECKRALIGN32( sh4r.r[Rm] );
885 MEM_READ_LONG(sh4r.r[Rm], tmp);
886 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
887 (((uint64_t)tmp)<<32);
893 CHECKWALIGN32( sh4r.r[Rm] );
894 MEM_READ_LONG(sh4r.r[Rm], tmp);
899 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
900 (((uint64_t)sh4r.r[Rm])<<32);
905 sh4_write_sr( sh4r.r[Rm] );
909 sh4r.sgr = sh4r.r[Rm];
913 CHECKRALIGN32( sh4r.r[Rm] );
914 MEM_READ_LONG(sh4r.r[Rm], sh4r.sgr);
917 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
919 CHECKWALIGN32( sh4r.r[Rn] );
920 MEM_WRITE_LONG( sh4r.r[Rn]-4, (uint32_t)sh4r.mac );
924 CHECKWALIGN32( sh4r.r[Rn] );
925 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.gbr );
929 CHECKRALIGN32( sh4r.r[Rm] );
930 MEM_READ_LONG(sh4r.r[Rm], tmp);
931 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
932 (uint64_t)((uint32_t)tmp);
936 CHECKRALIGN32( sh4r.r[Rm] );
937 MEM_READ_LONG(sh4r.r[Rm], sh4r.gbr);
941 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
942 (uint64_t)((uint32_t)(sh4r.r[Rm]));
944 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
945 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
947 CHECKWALIGN32( sh4r.r[Rn] );
948 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.pr );
953 CHECKWALIGN32( sh4r.r[Rn] );
954 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.vbr );
958 CHECKRALIGN32( sh4r.r[Rm] );
959 MEM_READ_LONG( sh4r.r[Rm], sh4r.pr );
964 CHECKRALIGN32( sh4r.r[Rm] );
965 MEM_READ_LONG(sh4r.r[Rm], sh4r.vbr);
968 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
971 sh4r.vbr = sh4r.r[Rm];
975 sh4r.r[Rn] = sh4r.sgr;
979 CHECKWALIGN32( sh4r.r[Rn] );
980 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.sgr );
985 CHECKWALIGN32( sh4r.r[Rn] );
986 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.ssr );
991 CHECKRALIGN32( sh4r.r[Rm] );
992 MEM_READ_LONG(sh4r.r[Rm], sh4r.ssr);
997 sh4r.ssr = sh4r.r[Rm];
1001 CHECKWALIGN32( sh4r.r[Rn] );
1002 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.spc );
1007 CHECKRALIGN32( sh4r.r[Rm] );
1008 MEM_READ_LONG(sh4r.r[Rm], sh4r.spc);
1013 sh4r.spc = sh4r.r[Rm];
1021 CHECKWALIGN32( sh4r.r[Rn] );
1022 MEM_WRITE_LONG( sh4r.r[Rn]-4, FPULi );
1027 CHECKRALIGN32( sh4r.r[Rm] );
1028 MEM_READ_LONG(sh4r.r[Rm], FPULi);
1037 sh4r.r[Rn] = sh4r.fpscr;
1039 STS.L FPSCR, @-Rn {:
1041 CHECKWALIGN32( sh4r.r[Rn] );
1042 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.fpscr );
1045 LDS.L @Rm+, FPSCR {:
1047 CHECKRALIGN32( sh4r.r[Rm] );
1048 MEM_READ_LONG(sh4r.r[Rm], tmp);
1050 sh4_write_fpscr( tmp );
1054 sh4_write_fpscr( sh4r.r[Rm] );
1056 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
1059 CHECKWALIGN32( sh4r.r[Rn] );
1060 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.dbr );
1065 CHECKRALIGN32( sh4r.r[Rm] );
1066 MEM_READ_LONG(sh4r.r[Rm], sh4r.dbr);
1071 sh4r.dbr = sh4r.r[Rm];
1073 STC.L Rm_BANK, @-Rn {:
1075 CHECKWALIGN32( sh4r.r[Rn] );
1076 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r_bank[Rm_BANK] );
1079 LDC.L @Rm+, Rn_BANK {:
1081 CHECKRALIGN32( sh4r.r[Rm] );
1082 MEM_READ_LONG( sh4r.r[Rm], sh4r.r_bank[Rn_BANK] );
1087 sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
1091 sh4r.r[Rn] = sh4_read_sr();
1094 sh4r.r[Rn] = sh4r.gbr;
1098 sh4r.r[Rn] = sh4r.vbr;
1102 sh4r.r[Rn] = sh4r.ssr;
1106 sh4r.r[Rn] = sh4r.spc;
1110 sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
1115 if( IS_FPU_DOUBLEPREC() ) {
1123 if( IS_FPU_DOUBLEPREC() ) {
1132 if( IS_FPU_DOUBLEPREC() ) {
1141 if( IS_FPU_DOUBLEPREC() ) {
1150 if( IS_FPU_DOUBLEPREC() ) {
1151 sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
1153 sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
1159 if( IS_FPU_DOUBLEPREC() ) {
1160 sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
1162 sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
1166 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
1167 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
1170 if( IS_FPU_DOUBLEPREC() ) {
1171 if( FRn&1 ) { // No, really...
1172 dtmp = (double)FPULi;
1173 FR(FRn) = *(((float *)&dtmp)+1);
1175 DRF(FRn>>1) = (double)FPULi;
1178 FR(FRn) = (float)FPULi;
1183 if( IS_FPU_DOUBLEPREC() ) {
1186 *(((float *)&dtmp)+1) = FR(FRm);
1190 if( dtmp >= MAX_INTF )
1192 else if( dtmp <= MIN_INTF )
1195 FPULi = (int32_t)dtmp;
1198 if( ftmp >= MAX_INTF )
1200 else if( ftmp <= MIN_INTF )
1203 FPULi = (int32_t)ftmp;
1208 if( IS_FPU_DOUBLEPREC() ) {
1216 if( IS_FPU_DOUBLEPREC() ) {
1217 DR(FRn) = fabs(DR(FRn));
1219 FR(FRn) = fabsf(FR(FRn));
1224 if( IS_FPU_DOUBLEPREC() ) {
1225 DR(FRn) = sqrt(DR(FRn));
1227 FR(FRn) = sqrtf(FR(FRn));
1232 if( IS_FPU_DOUBLEPREC() ) {
1240 if( IS_FPU_DOUBLEPREC() ) {
1246 FMAC FR0, FRm, FRn {:
1248 if( IS_FPU_DOUBLEPREC() ) {
1249 DR(FRn) += DR(FRm)*DR(0);
1251 FR(FRn) += FR(FRm)*FR(0);
1256 sh4r.fpscr ^= FPSCR_FR;
1257 sh4_switch_fr_banks();
1259 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
1262 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1263 DR(FRn) = (double)FPULf;
1268 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1269 FPULf = (float)DR(FRm);
1275 if( !IS_FPU_DOUBLEPREC() ) {
1276 FR(FRn) = 1.0/sqrt(FR(FRn));
1281 if( !IS_FPU_DOUBLEPREC() ) {
1284 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1285 FR(tmp+1)*FR(tmp2+1) +
1286 FR(tmp+2)*FR(tmp2+2) +
1287 FR(tmp+3)*FR(tmp2+3);
1292 if( !IS_FPU_DOUBLEPREC() ) {
1293 sh4_fsca( FPULi, (float *)&(DRF(FRn>>1)) );
1298 if( !IS_FPU_DOUBLEPREC() ) {
1299 sh4_ftrv((float *)&(DRF(FVn<<1)) );
1306 sh4r.pc = sh4r.new_pc;
1310 sh4r.in_delay_slot = 0;
.