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 if( sh4r.event_types & PENDING_EVENT ) {
53 /* Eventq execute may (quite likely) deliver an immediate IRQ */
54 if( sh4r.event_types & PENDING_IRQ ) {
55 sh4_accept_interrupt();
58 if( !sh4_execute_instruction() ) {
63 for( ;sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
64 if( SH4_EVENT_PENDING() ) {
65 if( sh4r.event_types & PENDING_EVENT ) {
68 /* Eventq execute may (quite likely) deliver an immediate IRQ */
69 if( sh4r.event_types & PENDING_IRQ ) {
70 sh4_accept_interrupt();
74 if( !sh4_execute_instruction() )
76 #ifdef ENABLE_DEBUG_MODE
77 for( i=0; i<sh4_breakpoint_count; i++ ) {
78 if( sh4_breakpoints[i].address == sh4r.pc ) {
82 if( i != sh4_breakpoint_count ) {
83 sh4_core_exit( CORE_EXIT_BREAKPOINT );
89 /* If we aborted early, but the cpu is still technically running,
90 * we're doing a hard abort - cut the timeslice back to what we
93 if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
94 nanosecs = sh4r.slice_cycle;
96 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
97 TMU_run_slice( nanosecs );
98 SCIF_run_slice( nanosecs );
103 /********************** SH4 emulation core ****************************/
105 #if(SH4_CALLTRACE == 1)
106 #define MAX_CALLSTACK 32
107 static struct call_stack {
109 sh4addr_t target_addr;
110 sh4addr_t stack_pointer;
111 } call_stack[MAX_CALLSTACK];
113 static int call_stack_depth = 0;
114 int sh4_call_trace_on = 0;
116 static inline void trace_call( sh4addr_t source, sh4addr_t dest )
118 if( call_stack_depth < MAX_CALLSTACK ) {
119 call_stack[call_stack_depth].call_addr = source;
120 call_stack[call_stack_depth].target_addr = dest;
121 call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
126 static inline void trace_return( sh4addr_t source, sh4addr_t dest )
128 if( call_stack_depth > 0 ) {
133 void fprint_stack_trace( FILE *f )
135 int i = call_stack_depth -1;
136 if( i >= MAX_CALLSTACK )
137 i = MAX_CALLSTACK - 1;
138 for( ; i >= 0; i-- ) {
139 fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n",
140 (call_stack_depth - i), call_stack[i].call_addr,
141 call_stack[i].target_addr, call_stack[i].stack_pointer );
145 #define TRACE_CALL( source, dest ) trace_call(source, dest)
146 #define TRACE_RETURN( source, dest ) trace_return(source, dest)
148 #define TRACE_CALL( dest, rts )
149 #define TRACE_RETURN( source, dest )
152 static gboolean FASTCALL sh4_raise_slot_exception( int normal_code, int slot_code ) {
153 if( sh4r.in_delay_slot ) {
154 sh4_raise_exception(slot_code);
156 sh4_raise_exception(normal_code);
162 #define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) { return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL ); }
163 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
164 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
165 #define CHECKRALIGN64(addr) if( (addr)&0x07 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
166 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
167 #define CHECKWALIGN32(addr) if( (addr)&0x03 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
168 #define CHECKWALIGN64(addr) if( (addr)&0x07 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
170 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
171 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }
172 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) { sh4_raise_exception(EXC_SLOT_ILLEGAL); return TRUE; }
174 #define ADDRSPACE (IS_SH4_PRIVMODE() ? sh4_address_space : sh4_user_address_space)
175 #define SQADDRSPACE (IS_SH4_PRIVMODE() ? storequeue_address_space : storequeue_user_address_space)
177 #ifdef HAVE_FRAME_ADDRESS
178 static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }
179 #define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:
180 #define MEM_READ_BYTE( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_byte)((addr), &&except)
181 #define MEM_READ_BYTE_FOR_WRITE( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_byte_for_write)((addr), &&except)
182 #define MEM_READ_WORD( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_word)((addr), &&except)
183 #define MEM_READ_LONG( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_long)((addr), &&except)
184 #define MEM_WRITE_BYTE( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_byte)((addr), (val), &&except)
185 #define MEM_WRITE_WORD( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_word)((addr), (val), &&except)
186 #define MEM_WRITE_LONG( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_long)((addr), (val), &&except)
187 #define MEM_PREFETCH( addr ) ((mem_prefetch_exc_fn_t)ADDRSPACE[(addr)>>12]->prefetch)((addr), &&except)
189 #define INIT_EXCEPTIONS(label)
190 #define MEM_READ_BYTE( addr, val ) val = ADDRSPACE[(addr)>>12]->read_byte(addr)
191 #define MEM_READ_BYTE_FOR_WRITE( addr, val ) val = ADDRSPACE[(addr)>>12]->read_byte_for_write(addr)
192 #define MEM_READ_WORD( addr, val ) val = ADDRSPACE[(addr)>>12]->read_word(addr)
193 #define MEM_READ_LONG( addr, val ) val = ADDRSPACE[(addr)>>12]->read_long(addr)
194 #define MEM_WRITE_BYTE( addr, val ) ADDRSPACE[(addr)>>12]->write_byte(addr, val)
195 #define MEM_WRITE_WORD( addr, val ) ADDRSPACE[(addr)>>12]->write_word(addr, val)
196 #define MEM_WRITE_LONG( addr, val ) ADDRSPACE[(addr)>>12]->write_long(addr, val)
197 #define MEM_PREFETCH( addr ) ADDRSPACE[(addr)>>12]->prefetch(addr)
200 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
202 #define MEM_FP_READ( addr, reg ) \
203 if( IS_FPU_DOUBLESIZE() ) { \
204 CHECKRALIGN64(addr); \
206 MEM_READ_LONG( addr, *((uint32_t *)&XF((reg) & 0x0E)) ); \
207 MEM_READ_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
209 MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
210 MEM_READ_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
213 CHECKRALIGN32(addr); \
214 MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
216 #define MEM_FP_WRITE( addr, reg ) \
217 if( IS_FPU_DOUBLESIZE() ) { \
218 CHECKWALIGN64(addr); \
220 MEM_WRITE_LONG( addr, *((uint32_t *)&XF((reg)&0x0E)) ); \
221 MEM_WRITE_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
223 MEM_WRITE_LONG( addr, *((uint32_t *)&FR(reg)) ); \
224 MEM_WRITE_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
227 CHECKWALIGN32(addr); \
228 MEM_WRITE_LONG(addr, *((uint32_t *)&FR((reg))) ); \
235 * Perform instruction-completion following core exit of a partially completed
236 * instruction. NOTE: This is only allowed on memory writes, operation is not
237 * guaranteed in any other case.
239 void sh4_finalize_instruction( void )
244 if( IS_SYSCALL(sh4r.pc) ) {
247 assert( IS_IN_ICACHE(sh4r.pc) );
248 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
251 * Note - we can't take an exit on a control transfer instruction itself,
252 * which means the exit must have happened in the delay slot. So for these
253 * cases, finalize the delay slot instruction, and re-execute the control transfer.
255 * For delay slots which modify the argument used in the branch instruction,
256 * we pretty much just assume that that can't have already happened in an exit case.
262 sh4_finalize_instruction();
268 sh4_finalize_instruction();
272 /* Note: PR is already set */
274 sh4_finalize_instruction();
278 /* Note: PR is already set */
281 sh4_finalize_instruction();
286 sh4_finalize_instruction();
293 sh4_finalize_instruction();
301 sh4_finalize_instruction();
303 sh4r.new_pc = tmp + 2;
304 sh4r.slice_cycle += sh4_cpu_period;
308 /* Note: PR is already set */
311 sh4_finalize_instruction();
313 sh4r.new_pc = tmp + 2;
314 sh4r.slice_cycle += sh4_cpu_period;
319 sh4_finalize_instruction();
321 sh4r.new_pc = sh4r.pr + 2;
322 sh4r.slice_cycle += sh4_cpu_period;
326 /* SR is already set */
328 sh4_finalize_instruction();
330 sh4r.new_pc = sh4r.pr + 2;
331 sh4r.slice_cycle += sh4_cpu_period;
334 MOV.B Rm, @-Rn {: sh4r.r[Rn]--; :}
335 MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; :}
336 MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; :}
337 MOV.B @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
338 MOV.W @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
339 MOV.L @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
341 sh4r.in_delay_slot = 0;
343 sh4r.new_pc = sh4r.pc+2;
344 sh4r.slice_cycle += sh4_cpu_period;
350 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
351 #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)
354 gboolean sh4_execute_instruction( void )
361 int64_t memtmp; // temporary holder for memory reads
363 INIT_EXCEPTIONS(except)
367 if( pc > 0xFFFFFF00 ) {
369 sh4r.in_delay_slot = 0;
371 sh4r.new_pc = sh4r.pc + 2;
372 syscall_invoke( pc );
377 #ifdef ENABLE_SH4STATS
378 sh4_stats_add_by_pc(sh4r.pc);
381 /* Read instruction */
382 if( !IS_IN_ICACHE(pc) ) {
383 gboolean delay_slot = sh4r.in_delay_slot;
384 if( !mmu_update_icache(pc) ) {
388 // Fault - look for the fault handler
389 if( !mmu_update_icache(sh4r.pc) ) {
390 // double fault - halt
391 ERROR( "Double fault - halting" );
392 sh4_core_exit(CORE_EXIT_HALT);
398 assert( IS_IN_ICACHE(pc) );
399 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
401 /* FIXME: This is a bit of a hack, but the PC of the delay slot should not
402 * be visible until after the instruction has executed (for exception
405 if( sh4r.in_delay_slot ) {
409 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
410 AND #imm, R0 {: R0 &= imm; :}
411 AND.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & tmp ); :}
412 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
413 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
414 OR #imm, R0 {: R0 |= imm; :}
415 OR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | tmp ); :}
417 MEM_READ_BYTE_FOR_WRITE( sh4r.r[Rn], tmp );
418 sh4r.t = ( tmp == 0 ? 1 : 0 );
419 MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
421 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
422 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
423 TST.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); sh4r.t = ( tmp & imm ? 0 : 1 ); :}
424 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
425 XOR #imm, R0 {: R0 ^= imm; :}
426 XOR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ tmp ); :}
427 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
430 sh4r.t = sh4r.r[Rn] >> 31;
432 sh4r.r[Rn] |= sh4r.t;
435 sh4r.t = sh4r.r[Rn] & 0x00000001;
437 sh4r.r[Rn] |= (sh4r.t << 31);
440 tmp = sh4r.r[Rn] >> 31;
442 sh4r.r[Rn] |= sh4r.t;
446 tmp = sh4r.r[Rn] & 0x00000001;
448 sh4r.r[Rn] |= (sh4r.t << 31 );
453 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
454 else if( (tmp & 0x1F) == 0 )
455 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
457 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
461 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
462 else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
463 else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
466 sh4r.t = sh4r.r[Rn] >> 31;
470 sh4r.t = sh4r.r[Rn] & 0x00000001;
471 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
473 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
474 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
475 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
476 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
477 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
478 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
479 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
480 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
482 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
483 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
484 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
485 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
486 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
487 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
489 CLRT {: sh4r.t = 0; :}
490 SETT {: sh4r.t = 1; :}
491 CLRMAC {: sh4r.mac = 0; :}
492 LDTLB {: MMU_ldtlb(); :}
493 CLRS {: sh4r.s = 0; :}
494 SETS {: sh4r.s = 1; :}
495 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
499 MEM_PREFETCH(sh4r.r[Rn]);
507 MEM_WRITE_LONG( tmp, R0 );
509 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
510 MOV.W Rm, @(R0, Rn) {:
511 CHECKWALIGN16( R0 + sh4r.r[Rn] );
512 MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
514 MOV.L Rm, @(R0, Rn) {:
515 CHECKWALIGN32( R0 + sh4r.r[Rn] );
516 MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
518 MOV.B @(R0, Rm), Rn {: MEM_READ_BYTE( R0 + sh4r.r[Rm], sh4r.r[Rn] ); :}
519 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
520 MEM_READ_WORD( R0 + sh4r.r[Rm], sh4r.r[Rn] );
522 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
523 MEM_READ_LONG( R0 + sh4r.r[Rm], sh4r.r[Rn] );
525 MOV.L Rm, @(disp, Rn) {:
526 tmp = sh4r.r[Rn] + disp;
527 CHECKWALIGN32( tmp );
528 MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
530 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
531 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
532 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
533 MOV.B Rm, @-Rn {: MEM_WRITE_BYTE( sh4r.r[Rn]-1, sh4r.r[Rm] ); sh4r.r[Rn]--; :}
534 MOV.W Rm, @-Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn]-2, sh4r.r[Rm] ); sh4r.r[Rn] -= 2; :}
535 MOV.L Rm, @-Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r[Rm] ); sh4r.r[Rn] -= 4; :}
536 MOV.L @(disp, Rm), Rn {:
537 tmp = sh4r.r[Rm] + disp;
538 CHECKRALIGN32( tmp );
539 MEM_READ_LONG( tmp, sh4r.r[Rn] );
541 MOV.B @Rm, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); :}
542 MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); :}
543 MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); :}
544 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
545 MOV.B @Rm+, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
546 MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
547 MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
548 MOV.L @(disp, PC), Rn {:
550 tmp = (pc&0xFFFFFFFC) + disp + 4;
551 MEM_READ_LONG( tmp, sh4r.r[Rn] );
553 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
554 MOV.W R0, @(disp, GBR) {:
555 tmp = sh4r.gbr + disp;
556 CHECKWALIGN16( tmp );
557 MEM_WRITE_WORD( tmp, R0 );
559 MOV.L R0, @(disp, GBR) {:
560 tmp = sh4r.gbr + disp;
561 CHECKWALIGN32( tmp );
562 MEM_WRITE_LONG( tmp, R0 );
564 MOV.B @(disp, GBR), R0 {: MEM_READ_BYTE( sh4r.gbr + disp, R0 ); :}
565 MOV.W @(disp, GBR), R0 {:
566 tmp = sh4r.gbr + disp;
567 CHECKRALIGN16( tmp );
568 MEM_READ_WORD( tmp, R0 );
570 MOV.L @(disp, GBR), R0 {:
571 tmp = sh4r.gbr + disp;
572 CHECKRALIGN32( tmp );
573 MEM_READ_LONG( tmp, R0 );
575 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
576 MOV.W R0, @(disp, Rn) {:
577 tmp = sh4r.r[Rn] + disp;
578 CHECKWALIGN16( tmp );
579 MEM_WRITE_WORD( tmp, R0 );
581 MOV.B @(disp, Rm), R0 {: MEM_READ_BYTE( sh4r.r[Rm] + disp, R0 ); :}
582 MOV.W @(disp, Rm), R0 {:
583 tmp = sh4r.r[Rm] + disp;
584 CHECKRALIGN16( tmp );
585 MEM_READ_WORD( tmp, R0 );
587 MOV.W @(disp, PC), Rn {:
590 MEM_READ_WORD( tmp, sh4r.r[Rn] );
592 MOVA @(disp, PC), R0 {:
594 R0 = (pc&0xFFFFFFFC) + disp + 4;
596 MOV #imm, Rn {: sh4r.r[Rn] = imm; :}
598 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
599 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
600 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
601 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
602 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
603 FMOV FRm, @-Rn {: MEM_FP_WRITE( sh4r.r[Rn] - FP_WIDTH, FRm ); sh4r.r[Rn] -= FP_WIDTH; :}
605 if( IS_FPU_DOUBLESIZE() )
611 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
612 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
613 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
614 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
615 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
616 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
617 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
618 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
620 /* set T = 1 if any byte in RM & RN is the same */
621 tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
622 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
623 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
626 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
627 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
630 sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
631 sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
634 tmp = sh4r.r[Rn] + sh4r.r[Rm];
635 sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
638 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
640 sh4r.q = sh4r.r[Rn]>>31;
641 sh4r.m = sh4r.r[Rm]>>31;
642 sh4r.t = sh4r.q ^ sh4r.m;
645 /* This is derived from the sh4 manual with some simplifications */
646 uint32_t tmp0, tmp1, tmp2, dir;
648 dir = sh4r.q ^ sh4r.m;
649 sh4r.q = (sh4r.r[Rn] >> 31);
651 sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
655 tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
658 tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
660 sh4r.q ^= sh4r.m ^ tmp1;
661 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
663 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
664 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
667 sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
672 CHECKRALIGN16(sh4r.r[Rn]);
673 MEM_READ_WORD( sh4r.r[Rn], tmp );
674 stmp = SIGNEXT16(tmp);
675 MEM_READ_WORD( sh4r.r[Rn]+2, tmp );
676 stmp *= SIGNEXT16(tmp);
679 CHECKRALIGN16( sh4r.r[Rn] );
680 CHECKRALIGN16( sh4r.r[Rm] );
681 MEM_READ_WORD(sh4r.r[Rn], tmp);
682 stmp = SIGNEXT16(tmp);
683 MEM_READ_WORD(sh4r.r[Rm], tmp);
684 stmp = stmp * SIGNEXT16(tmp);
689 int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
690 if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
691 sh4r.mac = 0x000000017FFFFFFFLL;
692 } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
693 sh4r.mac = 0x0000000180000000LL;
695 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
696 ((uint32_t)(sh4r.mac + stmp));
699 sh4r.mac += SIGNEXT32(stmp);
705 CHECKRALIGN32( sh4r.r[Rn] );
706 MEM_READ_LONG(sh4r.r[Rn], tmp);
707 tmpl = SIGNEXT32(tmp);
708 MEM_READ_LONG(sh4r.r[Rn]+4, tmp);
709 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
712 CHECKRALIGN32( sh4r.r[Rm] );
713 CHECKRALIGN32( sh4r.r[Rn] );
714 MEM_READ_LONG(sh4r.r[Rn], tmp);
715 tmpl = SIGNEXT32(tmp);
716 MEM_READ_LONG(sh4r.r[Rm], tmp);
717 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
722 /* 48-bit Saturation. Yuch */
723 if( tmpl < (int64_t)0xFFFF800000000000LL )
724 tmpl = 0xFFFF800000000000LL;
725 else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
726 tmpl = 0x00007FFFFFFFFFFFLL;
730 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
731 (sh4r.r[Rm] * sh4r.r[Rn]); :}
733 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
734 (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
737 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
738 (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
741 tmp = 0 - sh4r.r[Rm];
742 sh4r.r[Rn] = tmp - sh4r.t;
743 sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
745 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
746 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
749 sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
750 sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
753 tmp = sh4r.r[Rn] - sh4r.r[Rm];
754 sh4r.t = ( (sh4r.r[Rn]>>31) != (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
759 CHECKDEST( pc + 4 + sh4r.r[Rn] );
760 sh4r.in_delay_slot = 1;
761 sh4r.pc = sh4r.new_pc;
762 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
767 CHECKDEST( pc + 4 + sh4r.r[Rn] );
768 sh4r.in_delay_slot = 1;
769 sh4r.pr = sh4r.pc + 4;
770 sh4r.pc = sh4r.new_pc;
771 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
772 TRACE_CALL( pc, sh4r.new_pc );
778 CHECKDEST( sh4r.pc + disp + 4 )
780 sh4r.new_pc = sh4r.pc + 2;
787 CHECKDEST( sh4r.pc + disp + 4 )
789 sh4r.new_pc = sh4r.pc + 2;
796 CHECKDEST( sh4r.pc + disp + 4 )
797 sh4r.in_delay_slot = 1;
798 sh4r.pc = sh4r.new_pc;
799 sh4r.new_pc = pc + disp + 4;
800 sh4r.in_delay_slot = 1;
807 CHECKDEST( sh4r.pc + disp + 4 )
808 sh4r.in_delay_slot = 1;
809 sh4r.pc = sh4r.new_pc;
810 sh4r.new_pc = pc + disp + 4;
816 CHECKDEST( sh4r.pc + disp + 4 );
817 sh4r.in_delay_slot = 1;
818 sh4r.pc = sh4r.new_pc;
819 sh4r.new_pc = pc + 4 + disp;
823 CHECKDEST( sh4r.pc + disp + 4 );
825 sh4r.in_delay_slot = 1;
827 sh4r.pc = sh4r.new_pc;
828 sh4r.new_pc = pc + 4 + disp;
829 TRACE_CALL( pc, sh4r.new_pc );
835 sh4_raise_trap( imm );
840 CHECKDEST( sh4r.pr );
841 sh4r.in_delay_slot = 1;
842 sh4r.pc = sh4r.new_pc;
843 sh4r.new_pc = sh4r.pr;
844 TRACE_RETURN( pc, sh4r.new_pc );
848 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
849 sh4r.sh4_state = SH4_STATE_STANDBY;
851 sh4r.sh4_state = SH4_STATE_SLEEP;
853 return FALSE; /* Halt CPU */
857 CHECKDEST( sh4r.spc );
859 sh4r.in_delay_slot = 1;
860 sh4r.pc = sh4r.new_pc;
861 sh4r.new_pc = sh4r.spc;
862 sh4_write_sr( sh4r.ssr );
866 CHECKDEST( sh4r.r[Rn] );
868 sh4r.in_delay_slot = 1;
869 sh4r.pc = sh4r.new_pc;
870 sh4r.new_pc = sh4r.r[Rn];
874 CHECKDEST( sh4r.r[Rn] );
876 sh4r.in_delay_slot = 1;
877 sh4r.pc = sh4r.new_pc;
878 sh4r.new_pc = sh4r.r[Rn];
880 TRACE_CALL( pc, sh4r.new_pc );
883 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
885 CHECKWALIGN32( sh4r.r[Rn] );
886 MEM_WRITE_LONG( sh4r.r[Rn]-4, (sh4r.mac>>32) );
891 CHECKWALIGN32( sh4r.r[Rn] );
892 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4_read_sr() );
896 CHECKRALIGN32( sh4r.r[Rm] );
897 MEM_READ_LONG(sh4r.r[Rm], tmp);
898 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
899 (((uint64_t)tmp)<<32);
905 CHECKWALIGN32( sh4r.r[Rm] );
906 MEM_READ_LONG(sh4r.r[Rm], tmp);
911 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
912 (((uint64_t)sh4r.r[Rm])<<32);
917 sh4_write_sr( sh4r.r[Rm] );
921 sh4r.sgr = sh4r.r[Rm];
925 CHECKRALIGN32( sh4r.r[Rm] );
926 MEM_READ_LONG(sh4r.r[Rm], sh4r.sgr);
929 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
931 CHECKWALIGN32( sh4r.r[Rn] );
932 MEM_WRITE_LONG( sh4r.r[Rn]-4, (uint32_t)sh4r.mac );
936 CHECKWALIGN32( sh4r.r[Rn] );
937 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.gbr );
941 CHECKRALIGN32( sh4r.r[Rm] );
942 MEM_READ_LONG(sh4r.r[Rm], tmp);
943 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
944 (uint64_t)((uint32_t)tmp);
948 CHECKRALIGN32( sh4r.r[Rm] );
949 MEM_READ_LONG(sh4r.r[Rm], sh4r.gbr);
953 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
954 (uint64_t)((uint32_t)(sh4r.r[Rm]));
956 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
957 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
959 CHECKWALIGN32( sh4r.r[Rn] );
960 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.pr );
965 CHECKWALIGN32( sh4r.r[Rn] );
966 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.vbr );
970 CHECKRALIGN32( sh4r.r[Rm] );
971 MEM_READ_LONG( sh4r.r[Rm], sh4r.pr );
976 CHECKRALIGN32( sh4r.r[Rm] );
977 MEM_READ_LONG(sh4r.r[Rm], sh4r.vbr);
980 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
983 sh4r.vbr = sh4r.r[Rm];
987 sh4r.r[Rn] = sh4r.sgr;
991 CHECKWALIGN32( sh4r.r[Rn] );
992 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.sgr );
997 CHECKWALIGN32( sh4r.r[Rn] );
998 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.ssr );
1003 CHECKRALIGN32( sh4r.r[Rm] );
1004 MEM_READ_LONG(sh4r.r[Rm], sh4r.ssr);
1009 sh4r.ssr = sh4r.r[Rm];
1013 CHECKWALIGN32( sh4r.r[Rn] );
1014 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.spc );
1019 CHECKRALIGN32( sh4r.r[Rm] );
1020 MEM_READ_LONG(sh4r.r[Rm], sh4r.spc);
1025 sh4r.spc = sh4r.r[Rm];
1033 CHECKWALIGN32( sh4r.r[Rn] );
1034 MEM_WRITE_LONG( sh4r.r[Rn]-4, FPULi );
1039 CHECKRALIGN32( sh4r.r[Rm] );
1040 MEM_READ_LONG(sh4r.r[Rm], FPULi);
1049 sh4r.r[Rn] = sh4r.fpscr;
1051 STS.L FPSCR, @-Rn {:
1053 CHECKWALIGN32( sh4r.r[Rn] );
1054 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.fpscr );
1057 LDS.L @Rm+, FPSCR {:
1059 CHECKRALIGN32( sh4r.r[Rm] );
1060 MEM_READ_LONG(sh4r.r[Rm], tmp);
1062 sh4_write_fpscr( tmp );
1066 sh4_write_fpscr( sh4r.r[Rm] );
1068 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
1071 CHECKWALIGN32( sh4r.r[Rn] );
1072 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.dbr );
1077 CHECKRALIGN32( sh4r.r[Rm] );
1078 MEM_READ_LONG(sh4r.r[Rm], sh4r.dbr);
1083 sh4r.dbr = sh4r.r[Rm];
1085 STC.L Rm_BANK, @-Rn {:
1087 CHECKWALIGN32( sh4r.r[Rn] );
1088 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r_bank[Rm_BANK] );
1091 LDC.L @Rm+, Rn_BANK {:
1093 CHECKRALIGN32( sh4r.r[Rm] );
1094 MEM_READ_LONG( sh4r.r[Rm], sh4r.r_bank[Rn_BANK] );
1099 sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
1103 sh4r.r[Rn] = sh4_read_sr();
1106 sh4r.r[Rn] = sh4r.gbr;
1110 sh4r.r[Rn] = sh4r.vbr;
1114 sh4r.r[Rn] = sh4r.ssr;
1118 sh4r.r[Rn] = sh4r.spc;
1122 sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
1127 if( IS_FPU_DOUBLEPREC() ) {
1135 if( IS_FPU_DOUBLEPREC() ) {
1144 if( IS_FPU_DOUBLEPREC() ) {
1153 if( IS_FPU_DOUBLEPREC() ) {
1162 if( IS_FPU_DOUBLEPREC() ) {
1163 sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
1165 sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
1171 if( IS_FPU_DOUBLEPREC() ) {
1172 sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
1174 sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
1178 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
1179 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
1182 if( IS_FPU_DOUBLEPREC() ) {
1183 if( FRn&1 ) { // No, really...
1184 dtmp = (double)FPULi;
1185 FR(FRn) = *(((float *)&dtmp)+1);
1187 DRF(FRn>>1) = (double)FPULi;
1190 FR(FRn) = (float)FPULi;
1195 if( IS_FPU_DOUBLEPREC() ) {
1198 *(((float *)&dtmp)+1) = FR(FRm);
1202 if( dtmp >= MAX_INTF )
1204 else if( dtmp <= MIN_INTF )
1207 FPULi = (int32_t)dtmp;
1210 if( ftmp >= MAX_INTF )
1212 else if( ftmp <= MIN_INTF )
1215 FPULi = (int32_t)ftmp;
1220 if( IS_FPU_DOUBLEPREC() ) {
1228 if( IS_FPU_DOUBLEPREC() ) {
1229 DR(FRn) = fabs(DR(FRn));
1231 FR(FRn) = fabsf(FR(FRn));
1236 if( IS_FPU_DOUBLEPREC() ) {
1237 DR(FRn) = sqrt(DR(FRn));
1239 FR(FRn) = sqrtf(FR(FRn));
1244 if( IS_FPU_DOUBLEPREC() ) {
1252 if( IS_FPU_DOUBLEPREC() ) {
1258 FMAC FR0, FRm, FRn {:
1260 if( IS_FPU_DOUBLEPREC() ) {
1261 DR(FRn) += DR(FRm)*DR(0);
1263 FR(FRn) += FR(FRm)*FR(0);
1268 sh4r.fpscr ^= FPSCR_FR;
1269 sh4_switch_fr_banks();
1271 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
1274 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1275 DR(FRn) = (double)FPULf;
1280 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1281 FPULf = (float)DR(FRm);
1287 if( !IS_FPU_DOUBLEPREC() ) {
1288 FR(FRn) = 1.0/sqrtf(FR(FRn));
1293 if( !IS_FPU_DOUBLEPREC() ) {
1296 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1297 FR(tmp+1)*FR(tmp2+1) +
1298 FR(tmp+2)*FR(tmp2+2) +
1299 FR(tmp+3)*FR(tmp2+3);
1304 if( !IS_FPU_DOUBLEPREC() ) {
1305 sh4_fsca( FPULi, (float *)&(DRF(FRn>>1)) );
1310 if( !IS_FPU_DOUBLEPREC() ) {
1311 sh4_ftrv((float *)&(DRF(FVn<<1)) );
1318 sh4r.pc = sh4r.new_pc;
1322 sh4r.in_delay_slot = 0;
.