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 #define MEM_READ_BYTE( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_read(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_byte(addrtmp); }
166 #define MEM_READ_BYTE_FOR_WRITE( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_byte_for_write(addrtmp); }
167 #define MEM_READ_WORD( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_read(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_word(addrtmp); }
168 #define MEM_READ_LONG( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_read(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { val = fntmp->read_long(addrtmp); }
169 #define MEM_WRITE_BYTE( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->write_byte(addrtmp,val); }
170 #define MEM_WRITE_WORD( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->write_word(addrtmp,val); }
171 #define MEM_WRITE_LONG( addr, val ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_write(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->write_long(addrtmp,val); }
172 #define MEM_PREFETCH( addr ) addrtmp = addr; if( (fntmp = mmu_get_region_for_vma_prefetch(&addrtmp)) == NULL ) { sh4r.in_delay_slot = 0; return TRUE; } else { fntmp->prefetch(addrtmp); }
174 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
176 #define MEM_FP_READ( addr, reg ) \
177 if( IS_FPU_DOUBLESIZE() ) { \
178 CHECKRALIGN64(addr); \
180 MEM_READ_LONG( addr, *((uint32_t *)&XF((reg) & 0x0E)) ); \
181 MEM_READ_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
183 MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
184 MEM_READ_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
187 CHECKRALIGN32(addr); \
188 MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
190 #define MEM_FP_WRITE( addr, reg ) \
191 if( IS_FPU_DOUBLESIZE() ) { \
192 CHECKWALIGN64(addr); \
194 MEM_WRITE_LONG( addr, *((uint32_t *)&XF((reg)&0x0E)) ); \
195 MEM_WRITE_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
197 MEM_WRITE_LONG( addr, *((uint32_t *)&FR(reg)) ); \
198 MEM_WRITE_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
201 CHECKWALIGN32(addr); \
202 MEM_WRITE_LONG(addr, *((uint32_t *)&FR((reg))) ); \
209 * Perform instruction-completion following core exit of a partially completed
210 * instruction. NOTE: This is only allowed on memory writes, operation is not
211 * guaranteed in any other case.
213 void sh4_finalize_instruction( void )
218 if( IS_SYSCALL(sh4r.pc) ) {
221 assert( IS_IN_ICACHE(sh4r.pc) );
222 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
225 * Note - we can't take an exit on a control transfer instruction itself,
226 * which means the exit must have happened in the delay slot. So for these
227 * cases, finalize the delay slot instruction, and re-execute the control transfer.
229 * For delay slots which modify the argument used in the branch instruction,
230 * we pretty much just assume that that can't have already happened in an exit case.
236 sh4_finalize_instruction();
242 sh4_finalize_instruction();
246 /* Note: PR is already set */
248 sh4_finalize_instruction();
252 /* Note: PR is already set */
255 sh4_finalize_instruction();
260 sh4_finalize_instruction();
267 sh4_finalize_instruction();
275 sh4_finalize_instruction();
277 sh4r.new_pc = tmp + 2;
278 sh4r.slice_cycle += sh4_cpu_period;
282 /* Note: PR is already set */
285 sh4_finalize_instruction();
287 sh4r.new_pc = tmp + 2;
288 sh4r.slice_cycle += sh4_cpu_period;
293 sh4_finalize_instruction();
295 sh4r.new_pc = sh4r.pr + 2;
296 sh4r.slice_cycle += sh4_cpu_period;
300 /* SR is already set */
302 sh4_finalize_instruction();
304 sh4r.new_pc = sh4r.pr + 2;
305 sh4r.slice_cycle += sh4_cpu_period;
308 MOV.B Rm, @-Rn {: sh4r.r[Rn]--; :}
309 MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; :}
310 MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; :}
311 MOV.B @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
312 MOV.W @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
313 MOV.L @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
315 sh4r.in_delay_slot = 0;
317 sh4r.new_pc = sh4r.pc+2;
318 sh4r.slice_cycle += sh4_cpu_period;
324 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
325 #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)
328 gboolean sh4_execute_instruction( void )
335 sh4addr_t addrtmp; // temporary holder for memory addresses
336 mem_region_fn_t fntmp;
341 if( pc > 0xFFFFFF00 ) {
343 sh4r.in_delay_slot = 0;
345 sh4r.new_pc = sh4r.pc + 2;
346 syscall_invoke( pc );
351 #ifdef ENABLE_SH4STATS
352 sh4_stats_add_by_pc(sh4r.pc);
355 /* Read instruction */
356 if( !IS_IN_ICACHE(pc) ) {
357 gboolean delay_slot = sh4r.in_delay_slot;
358 if( !mmu_update_icache(pc) ) {
362 // Fault - look for the fault handler
363 if( !mmu_update_icache(sh4r.pc) ) {
364 // double fault - halt
365 ERROR( "Double fault - halting" );
366 sh4_core_exit(CORE_EXIT_HALT);
372 assert( IS_IN_ICACHE(pc) );
373 ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
375 /* FIXME: This is a bit of a hack, but the PC of the delay slot should not
376 * be visible until after the instruction has executed (for exception
379 if( sh4r.in_delay_slot ) {
383 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
384 AND #imm, R0 {: R0 &= imm; :}
385 AND.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & tmp ); :}
386 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
387 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
388 OR #imm, R0 {: R0 |= imm; :}
389 OR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | tmp ); :}
391 MEM_READ_BYTE_FOR_WRITE( sh4r.r[Rn], tmp );
392 sh4r.t = ( tmp == 0 ? 1 : 0 );
393 MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
395 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
396 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
397 TST.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); sh4r.t = ( tmp & imm ? 0 : 1 ); :}
398 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
399 XOR #imm, R0 {: R0 ^= imm; :}
400 XOR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ tmp ); :}
401 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
404 sh4r.t = sh4r.r[Rn] >> 31;
406 sh4r.r[Rn] |= sh4r.t;
409 sh4r.t = sh4r.r[Rn] & 0x00000001;
411 sh4r.r[Rn] |= (sh4r.t << 31);
414 tmp = sh4r.r[Rn] >> 31;
416 sh4r.r[Rn] |= sh4r.t;
420 tmp = sh4r.r[Rn] & 0x00000001;
422 sh4r.r[Rn] |= (sh4r.t << 31 );
427 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
428 else if( (tmp & 0x1F) == 0 )
429 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
431 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
435 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
436 else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
437 else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
440 sh4r.t = sh4r.r[Rn] >> 31;
444 sh4r.t = sh4r.r[Rn] & 0x00000001;
445 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
447 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
448 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
449 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
450 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
451 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
452 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
453 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
454 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
456 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
457 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
458 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
459 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
460 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
461 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
463 CLRT {: sh4r.t = 0; :}
464 SETT {: sh4r.t = 1; :}
465 CLRMAC {: sh4r.mac = 0; :}
466 LDTLB {: MMU_ldtlb(); :}
467 CLRS {: sh4r.s = 0; :}
468 SETS {: sh4r.s = 1; :}
469 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
473 MEM_PREFETCH(sh4r.r[Rn]);
481 MEM_WRITE_LONG( tmp, R0 );
483 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
484 MOV.W Rm, @(R0, Rn) {:
485 CHECKWALIGN16( R0 + sh4r.r[Rn] );
486 MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
488 MOV.L Rm, @(R0, Rn) {:
489 CHECKWALIGN32( R0 + sh4r.r[Rn] );
490 MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
492 MOV.B @(R0, Rm), Rn {: MEM_READ_BYTE( R0 + sh4r.r[Rm], sh4r.r[Rn] ); :}
493 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
494 MEM_READ_WORD( R0 + sh4r.r[Rm], sh4r.r[Rn] );
496 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
497 MEM_READ_LONG( R0 + sh4r.r[Rm], sh4r.r[Rn] );
499 MOV.L Rm, @(disp, Rn) {:
500 tmp = sh4r.r[Rn] + disp;
501 CHECKWALIGN32( tmp );
502 MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
504 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
505 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
506 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
507 MOV.B Rm, @-Rn {: MEM_WRITE_BYTE( sh4r.r[Rn]-1, sh4r.r[Rm] ); sh4r.r[Rn]--; :}
508 MOV.W Rm, @-Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn]-2, sh4r.r[Rm] ); sh4r.r[Rn] -= 2; :}
509 MOV.L Rm, @-Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r[Rm] ); sh4r.r[Rn] -= 4; :}
510 MOV.L @(disp, Rm), Rn {:
511 tmp = sh4r.r[Rm] + disp;
512 CHECKRALIGN32( tmp );
513 MEM_READ_LONG( tmp, sh4r.r[Rn] );
515 MOV.B @Rm, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); :}
516 MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); :}
517 MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); :}
518 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
519 MOV.B @Rm+, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
520 MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
521 MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
522 MOV.L @(disp, PC), Rn {:
524 tmp = (pc&0xFFFFFFFC) + disp + 4;
525 MEM_READ_LONG( tmp, sh4r.r[Rn] );
527 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
528 MOV.W R0, @(disp, GBR) {:
529 tmp = sh4r.gbr + disp;
530 CHECKWALIGN16( tmp );
531 MEM_WRITE_WORD( tmp, R0 );
533 MOV.L R0, @(disp, GBR) {:
534 tmp = sh4r.gbr + disp;
535 CHECKWALIGN32( tmp );
536 MEM_WRITE_LONG( tmp, R0 );
538 MOV.B @(disp, GBR), R0 {: MEM_READ_BYTE( sh4r.gbr + disp, R0 ); :}
539 MOV.W @(disp, GBR), R0 {:
540 tmp = sh4r.gbr + disp;
541 CHECKRALIGN16( tmp );
542 MEM_READ_WORD( tmp, R0 );
544 MOV.L @(disp, GBR), R0 {:
545 tmp = sh4r.gbr + disp;
546 CHECKRALIGN32( tmp );
547 MEM_READ_LONG( tmp, R0 );
549 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
550 MOV.W R0, @(disp, Rn) {:
551 tmp = sh4r.r[Rn] + disp;
552 CHECKWALIGN16( tmp );
553 MEM_WRITE_WORD( tmp, R0 );
555 MOV.B @(disp, Rm), R0 {: MEM_READ_BYTE( sh4r.r[Rm] + disp, R0 ); :}
556 MOV.W @(disp, Rm), R0 {:
557 tmp = sh4r.r[Rm] + disp;
558 CHECKRALIGN16( tmp );
559 MEM_READ_WORD( tmp, R0 );
561 MOV.W @(disp, PC), Rn {:
564 MEM_READ_WORD( tmp, sh4r.r[Rn] );
566 MOVA @(disp, PC), R0 {:
568 R0 = (pc&0xFFFFFFFC) + disp + 4;
570 MOV #imm, Rn {: sh4r.r[Rn] = imm; :}
572 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
573 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
574 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
575 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
576 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
577 FMOV FRm, @-Rn {: MEM_FP_WRITE( sh4r.r[Rn] - FP_WIDTH, FRm ); sh4r.r[Rn] -= FP_WIDTH; :}
579 if( IS_FPU_DOUBLESIZE() )
585 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
586 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
587 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
588 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
589 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
590 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
591 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
592 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
594 /* set T = 1 if any byte in RM & RN is the same */
595 tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
596 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
597 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
600 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
601 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
604 sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
605 sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
608 tmp = sh4r.r[Rn] + sh4r.r[Rm];
609 sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
612 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
614 sh4r.q = sh4r.r[Rn]>>31;
615 sh4r.m = sh4r.r[Rm]>>31;
616 sh4r.t = sh4r.q ^ sh4r.m;
619 /* This is derived from the sh4 manual with some simplifications */
620 uint32_t tmp0, tmp1, tmp2, dir;
622 dir = sh4r.q ^ sh4r.m;
623 sh4r.q = (sh4r.r[Rn] >> 31);
625 sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
629 tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
632 tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
634 sh4r.q ^= sh4r.m ^ tmp1;
635 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
637 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
638 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
641 sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
646 CHECKRALIGN16(sh4r.r[Rn]);
647 MEM_READ_WORD( sh4r.r[Rn], tmp );
648 stmp = SIGNEXT16(tmp);
649 MEM_READ_WORD( sh4r.r[Rn]+2, tmp );
650 stmp *= SIGNEXT16(tmp);
653 CHECKRALIGN16( sh4r.r[Rn] );
654 MEM_READ_WORD(sh4r.r[Rn], tmp);
655 stmp = SIGNEXT16(tmp);
656 CHECKRALIGN16( sh4r.r[Rm] );
657 MEM_READ_WORD(sh4r.r[Rm], tmp);
658 stmp = stmp * SIGNEXT16(tmp);
663 int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
664 if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
665 sh4r.mac = 0x000000017FFFFFFFLL;
666 } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
667 sh4r.mac = 0x0000000180000000LL;
669 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
670 ((uint32_t)(sh4r.mac + stmp));
673 sh4r.mac += SIGNEXT32(stmp);
679 CHECKRALIGN32( sh4r.r[Rn] );
680 MEM_READ_LONG(sh4r.r[Rn], tmp);
681 tmpl = SIGNEXT32(tmp);
682 MEM_READ_LONG(sh4r.r[Rn]+4, tmp);
683 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
686 CHECKRALIGN32( sh4r.r[Rm] );
687 CHECKRALIGN32( sh4r.r[Rn] );
688 MEM_READ_LONG(sh4r.r[Rn], tmp);
689 tmpl = SIGNEXT32(tmp);
690 MEM_READ_LONG(sh4r.r[Rm], tmp);
691 tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
696 /* 48-bit Saturation. Yuch */
697 if( tmpl < (int64_t)0xFFFF800000000000LL )
698 tmpl = 0xFFFF800000000000LL;
699 else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
700 tmpl = 0x00007FFFFFFFFFFFLL;
704 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
705 (sh4r.r[Rm] * sh4r.r[Rn]); :}
707 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
708 (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
711 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
712 (uint32_t)(SIGNEXT32((int16_t)(sh4r.r[Rm])) * SIGNEXT32((int16_t)(sh4r.r[Rn])));
715 tmp = 0 - sh4r.r[Rm];
716 sh4r.r[Rn] = tmp - sh4r.t;
717 sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
719 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
720 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
723 sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
724 sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
727 tmp = sh4r.r[Rn] - sh4r.r[Rm];
728 sh4r.t = ( (sh4r.r[Rn]>>31) != (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
733 CHECKDEST( pc + 4 + sh4r.r[Rn] );
734 sh4r.in_delay_slot = 1;
735 sh4r.pc = sh4r.new_pc;
736 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
741 CHECKDEST( pc + 4 + sh4r.r[Rn] );
742 sh4r.in_delay_slot = 1;
743 sh4r.pr = sh4r.pc + 4;
744 sh4r.pc = sh4r.new_pc;
745 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
746 TRACE_CALL( pc, sh4r.new_pc );
752 CHECKDEST( sh4r.pc + disp + 4 )
754 sh4r.new_pc = sh4r.pc + 2;
761 CHECKDEST( sh4r.pc + disp + 4 )
763 sh4r.new_pc = sh4r.pc + 2;
770 CHECKDEST( sh4r.pc + disp + 4 )
771 sh4r.in_delay_slot = 1;
772 sh4r.pc = sh4r.new_pc;
773 sh4r.new_pc = pc + disp + 4;
774 sh4r.in_delay_slot = 1;
781 CHECKDEST( sh4r.pc + disp + 4 )
782 sh4r.in_delay_slot = 1;
783 sh4r.pc = sh4r.new_pc;
784 sh4r.new_pc = pc + disp + 4;
790 CHECKDEST( sh4r.pc + disp + 4 );
791 sh4r.in_delay_slot = 1;
792 sh4r.pc = sh4r.new_pc;
793 sh4r.new_pc = pc + 4 + disp;
797 CHECKDEST( sh4r.pc + disp + 4 );
799 sh4r.in_delay_slot = 1;
801 sh4r.pc = sh4r.new_pc;
802 sh4r.new_pc = pc + 4 + disp;
803 TRACE_CALL( pc, sh4r.new_pc );
809 sh4_raise_trap( imm );
814 CHECKDEST( sh4r.pr );
815 sh4r.in_delay_slot = 1;
816 sh4r.pc = sh4r.new_pc;
817 sh4r.new_pc = sh4r.pr;
818 TRACE_RETURN( pc, sh4r.new_pc );
822 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
823 sh4r.sh4_state = SH4_STATE_STANDBY;
825 sh4r.sh4_state = SH4_STATE_SLEEP;
827 return FALSE; /* Halt CPU */
831 CHECKDEST( sh4r.spc );
833 sh4r.in_delay_slot = 1;
834 sh4r.pc = sh4r.new_pc;
835 sh4r.new_pc = sh4r.spc;
836 sh4_write_sr( sh4r.ssr );
840 CHECKDEST( sh4r.r[Rn] );
842 sh4r.in_delay_slot = 1;
843 sh4r.pc = sh4r.new_pc;
844 sh4r.new_pc = sh4r.r[Rn];
848 CHECKDEST( sh4r.r[Rn] );
850 sh4r.in_delay_slot = 1;
851 sh4r.pc = sh4r.new_pc;
852 sh4r.new_pc = sh4r.r[Rn];
854 TRACE_CALL( pc, sh4r.new_pc );
857 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
859 CHECKWALIGN32( sh4r.r[Rn] );
860 MEM_WRITE_LONG( sh4r.r[Rn]-4, (sh4r.mac>>32) );
865 CHECKWALIGN32( sh4r.r[Rn] );
866 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4_read_sr() );
870 CHECKRALIGN32( sh4r.r[Rm] );
871 MEM_READ_LONG(sh4r.r[Rm], tmp);
872 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
873 (((uint64_t)tmp)<<32);
879 CHECKWALIGN32( sh4r.r[Rm] );
880 MEM_READ_LONG(sh4r.r[Rm], tmp);
885 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
886 (((uint64_t)sh4r.r[Rm])<<32);
891 sh4_write_sr( sh4r.r[Rm] );
895 sh4r.sgr = sh4r.r[Rm];
899 CHECKRALIGN32( sh4r.r[Rm] );
900 MEM_READ_LONG(sh4r.r[Rm], sh4r.sgr);
903 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
905 CHECKWALIGN32( sh4r.r[Rn] );
906 MEM_WRITE_LONG( sh4r.r[Rn]-4, (uint32_t)sh4r.mac );
910 CHECKWALIGN32( sh4r.r[Rn] );
911 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.gbr );
915 CHECKRALIGN32( sh4r.r[Rm] );
916 MEM_READ_LONG(sh4r.r[Rm], tmp);
917 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
918 (uint64_t)((uint32_t)tmp);
922 CHECKRALIGN32( sh4r.r[Rm] );
923 MEM_READ_LONG(sh4r.r[Rm], sh4r.gbr);
927 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
928 (uint64_t)((uint32_t)(sh4r.r[Rm]));
930 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
931 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
933 CHECKWALIGN32( sh4r.r[Rn] );
934 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.pr );
939 CHECKWALIGN32( sh4r.r[Rn] );
940 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.vbr );
944 CHECKRALIGN32( sh4r.r[Rm] );
945 MEM_READ_LONG( sh4r.r[Rm], sh4r.pr );
950 CHECKRALIGN32( sh4r.r[Rm] );
951 MEM_READ_LONG(sh4r.r[Rm], sh4r.vbr);
954 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
957 sh4r.vbr = sh4r.r[Rm];
961 sh4r.r[Rn] = sh4r.sgr;
965 CHECKWALIGN32( sh4r.r[Rn] );
966 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.sgr );
971 CHECKWALIGN32( sh4r.r[Rn] );
972 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.ssr );
977 CHECKRALIGN32( sh4r.r[Rm] );
978 MEM_READ_LONG(sh4r.r[Rm], sh4r.ssr);
983 sh4r.ssr = sh4r.r[Rm];
987 CHECKWALIGN32( sh4r.r[Rn] );
988 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.spc );
993 CHECKRALIGN32( sh4r.r[Rm] );
994 MEM_READ_LONG(sh4r.r[Rm], sh4r.spc);
999 sh4r.spc = sh4r.r[Rm];
1007 CHECKWALIGN32( sh4r.r[Rn] );
1008 MEM_WRITE_LONG( sh4r.r[Rn]-4, FPULi );
1013 CHECKRALIGN32( sh4r.r[Rm] );
1014 MEM_READ_LONG(sh4r.r[Rm], FPULi);
1023 sh4r.r[Rn] = sh4r.fpscr;
1025 STS.L FPSCR, @-Rn {:
1027 CHECKWALIGN32( sh4r.r[Rn] );
1028 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.fpscr );
1031 LDS.L @Rm+, FPSCR {:
1033 CHECKRALIGN32( sh4r.r[Rm] );
1034 MEM_READ_LONG(sh4r.r[Rm], tmp);
1036 sh4_write_fpscr( tmp );
1040 sh4_write_fpscr( sh4r.r[Rm] );
1042 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
1045 CHECKWALIGN32( sh4r.r[Rn] );
1046 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.dbr );
1051 CHECKRALIGN32( sh4r.r[Rm] );
1052 MEM_READ_LONG(sh4r.r[Rm], sh4r.dbr);
1057 sh4r.dbr = sh4r.r[Rm];
1059 STC.L Rm_BANK, @-Rn {:
1061 CHECKWALIGN32( sh4r.r[Rn] );
1062 MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r_bank[Rm_BANK] );
1065 LDC.L @Rm+, Rn_BANK {:
1067 CHECKRALIGN32( sh4r.r[Rm] );
1068 MEM_READ_LONG( sh4r.r[Rm], sh4r.r_bank[Rn_BANK] );
1073 sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
1077 sh4r.r[Rn] = sh4_read_sr();
1080 sh4r.r[Rn] = sh4r.gbr;
1084 sh4r.r[Rn] = sh4r.vbr;
1088 sh4r.r[Rn] = sh4r.ssr;
1092 sh4r.r[Rn] = sh4r.spc;
1096 sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
1101 if( IS_FPU_DOUBLEPREC() ) {
1109 if( IS_FPU_DOUBLEPREC() ) {
1118 if( IS_FPU_DOUBLEPREC() ) {
1127 if( IS_FPU_DOUBLEPREC() ) {
1136 if( IS_FPU_DOUBLEPREC() ) {
1137 sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
1139 sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
1145 if( IS_FPU_DOUBLEPREC() ) {
1146 sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
1148 sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
1152 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
1153 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
1156 if( IS_FPU_DOUBLEPREC() ) {
1157 if( FRn&1 ) { // No, really...
1158 dtmp = (double)FPULi;
1159 FR(FRn) = *(((float *)&dtmp)+1);
1161 DRF(FRn>>1) = (double)FPULi;
1164 FR(FRn) = (float)FPULi;
1169 if( IS_FPU_DOUBLEPREC() ) {
1172 *(((float *)&dtmp)+1) = FR(FRm);
1176 if( dtmp >= MAX_INTF )
1178 else if( dtmp <= MIN_INTF )
1181 FPULi = (int32_t)dtmp;
1184 if( ftmp >= MAX_INTF )
1186 else if( ftmp <= MIN_INTF )
1189 FPULi = (int32_t)ftmp;
1194 if( IS_FPU_DOUBLEPREC() ) {
1202 if( IS_FPU_DOUBLEPREC() ) {
1203 DR(FRn) = fabs(DR(FRn));
1205 FR(FRn) = fabsf(FR(FRn));
1210 if( IS_FPU_DOUBLEPREC() ) {
1211 DR(FRn) = sqrt(DR(FRn));
1213 FR(FRn) = sqrtf(FR(FRn));
1218 if( IS_FPU_DOUBLEPREC() ) {
1226 if( IS_FPU_DOUBLEPREC() ) {
1232 FMAC FR0, FRm, FRn {:
1234 if( IS_FPU_DOUBLEPREC() ) {
1235 DR(FRn) += DR(FRm)*DR(0);
1237 FR(FRn) += (double)FR(FRm)*(double)FR(0);
1242 sh4r.fpscr ^= FPSCR_FR;
1243 sh4_switch_fr_banks();
1245 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
1248 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1249 DR(FRn) = (double)FPULf;
1254 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1255 FPULf = (float)DR(FRm);
1261 if( !IS_FPU_DOUBLEPREC() ) {
1262 FR(FRn) = 1.0/sqrt(FR(FRn));
1267 if( !IS_FPU_DOUBLEPREC() ) {
1270 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1271 FR(tmp+1)*FR(tmp2+1) +
1272 FR(tmp+2)*FR(tmp2+2) +
1273 FR(tmp+3)*FR(tmp2+3);
1278 if( !IS_FPU_DOUBLEPREC() ) {
1279 sh4_fsca( FPULi, (float *)&(DRF(FRn>>1)) );
1284 if( !IS_FPU_DOUBLEPREC() ) {
1285 sh4_ftrv((float *)&(DRF(FVn<<1)) );
1292 sh4r.pc = sh4r.new_pc;
1295 sh4r.in_delay_slot = 0;
.