2 * $Id: sh4core.in,v 1.10 2007-11-04 08:49:18 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 "dreamcast.h"
28 #include "sh4/sh4core.h"
29 #include "sh4/sh4mmio.h"
32 #define SH4_CALLTRACE 1
34 #define MAX_INT 0x7FFFFFFF
35 #define MIN_INT 0x80000000
36 #define MAX_INTF 2147483647.0
37 #define MIN_INTF -2147483648.0
39 /********************** SH4 Module Definition ****************************/
41 uint16_t *sh4_icache = NULL;
42 uint32_t sh4_icache_addr = 0;
44 uint32_t sh4_run_slice( uint32_t nanosecs )
49 if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
50 if( sh4r.event_pending < nanosecs ) {
51 sh4r.sh4_state = SH4_STATE_RUNNING;
52 sh4r.slice_cycle = sh4r.event_pending;
56 if( sh4_breakpoint_count == 0 ) {
57 for( ; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
58 if( SH4_EVENT_PENDING() ) {
59 if( sh4r.event_types & PENDING_EVENT ) {
62 /* Eventq execute may (quite likely) deliver an immediate IRQ */
63 if( sh4r.event_types & PENDING_IRQ ) {
64 sh4_accept_interrupt();
67 if( !sh4_execute_instruction() ) {
72 for( ;sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
73 if( SH4_EVENT_PENDING() ) {
74 if( sh4r.event_types & PENDING_EVENT ) {
77 /* Eventq execute may (quite likely) deliver an immediate IRQ */
78 if( sh4r.event_types & PENDING_IRQ ) {
79 sh4_accept_interrupt();
83 if( !sh4_execute_instruction() )
85 #ifdef ENABLE_DEBUG_MODE
86 for( i=0; i<sh4_breakpoint_count; i++ ) {
87 if( sh4_breakpoints[i].address == sh4r.pc ) {
91 if( i != sh4_breakpoint_count ) {
93 if( sh4_breakpoints[i].type == BREAK_ONESHOT )
94 sh4_clear_breakpoint( sh4r.pc, BREAK_ONESHOT );
101 /* If we aborted early, but the cpu is still technically running,
102 * we're doing a hard abort - cut the timeslice back to what we
105 if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
106 nanosecs = sh4r.slice_cycle;
108 if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
109 TMU_run_slice( nanosecs );
110 SCIF_run_slice( nanosecs );
115 /********************** SH4 emulation core ****************************/
117 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
118 #define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)
120 #if(SH4_CALLTRACE == 1)
121 #define MAX_CALLSTACK 32
122 static struct call_stack {
124 sh4addr_t target_addr;
125 sh4addr_t stack_pointer;
126 } call_stack[MAX_CALLSTACK];
128 static int call_stack_depth = 0;
129 int sh4_call_trace_on = 0;
131 static inline void trace_call( sh4addr_t source, sh4addr_t dest )
133 if( call_stack_depth < MAX_CALLSTACK ) {
134 call_stack[call_stack_depth].call_addr = source;
135 call_stack[call_stack_depth].target_addr = dest;
136 call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
141 static inline void trace_return( sh4addr_t source, sh4addr_t dest )
143 if( call_stack_depth > 0 ) {
148 void fprint_stack_trace( FILE *f )
150 int i = call_stack_depth -1;
151 if( i >= MAX_CALLSTACK )
152 i = MAX_CALLSTACK - 1;
153 for( ; i >= 0; i-- ) {
154 fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n",
155 (call_stack_depth - i), call_stack[i].call_addr,
156 call_stack[i].target_addr, call_stack[i].stack_pointer );
160 #define TRACE_CALL( source, dest ) trace_call(source, dest)
161 #define TRACE_RETURN( source, dest ) trace_return(source, dest)
163 #define TRACE_CALL( dest, rts )
164 #define TRACE_RETURN( source, dest )
167 #define MEM_READ_BYTE( addr ) sh4_read_byte(addr)
168 #define MEM_READ_WORD( addr ) sh4_read_word(addr)
169 #define MEM_READ_LONG( addr ) sh4_read_long(addr)
170 #define MEM_WRITE_BYTE( addr, val ) sh4_write_byte(addr, val)
171 #define MEM_WRITE_WORD( addr, val ) sh4_write_word(addr, val)
172 #define MEM_WRITE_LONG( addr, val ) sh4_write_long(addr, val)
174 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
176 #define MEM_FP_READ( addr, reg ) sh4_read_float( addr, reg );
177 #define MEM_FP_WRITE( addr, reg ) sh4_write_float( addr, reg );
179 #define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )
180 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
181 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
182 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
183 #define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
185 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
186 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); dreamcast_stop(); return FALSE; }
187 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)
189 static void sh4_write_float( uint32_t addr, int reg )
191 if( IS_FPU_DOUBLESIZE() ) {
193 sh4_write_long( addr, *((uint32_t *)&XF((reg)&0x0E)) );
194 sh4_write_long( addr+4, *((uint32_t *)&XF(reg)) );
196 sh4_write_long( addr, *((uint32_t *)&FR(reg)) );
197 sh4_write_long( addr+4, *((uint32_t *)&FR((reg)|0x01)) );
200 sh4_write_long( addr, *((uint32_t *)&FR((reg))) );
204 static void sh4_read_float( uint32_t addr, int reg )
206 if( IS_FPU_DOUBLESIZE() ) {
208 *((uint32_t *)&XF((reg) & 0x0E)) = sh4_read_long(addr);
209 *((uint32_t *)&XF(reg)) = sh4_read_long(addr+4);
211 *((uint32_t *)&FR(reg)) = sh4_read_long(addr);
212 *((uint32_t *)&FR((reg) | 0x01)) = sh4_read_long(addr+4);
215 *((uint32_t *)&FR(reg)) = sh4_read_long(addr);
219 gboolean sh4_execute_instruction( void )
229 if( pc > 0xFFFFFF00 ) {
231 syscall_invoke( pc );
232 sh4r.in_delay_slot = 0;
233 pc = sh4r.pc = sh4r.pr;
234 sh4r.new_pc = sh4r.pc + 2;
238 /* Read instruction */
239 uint32_t pageaddr = pc >> 12;
240 if( sh4_icache != NULL && pageaddr == sh4_icache_addr ) {
241 ir = sh4_icache[(pc&0xFFF)>>1];
243 sh4_icache = (uint16_t *)mem_get_page(pc);
244 if( ((uintptr_t)sh4_icache) < MAX_IO_REGIONS ) {
245 /* If someone's actually been so daft as to try to execute out of an IO
246 * region, fallback on the full-blown memory read
249 ir = MEM_READ_WORD(pc);
251 sh4_icache_addr = pageaddr;
252 ir = sh4_icache[(pc&0xFFF)>>1];
256 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
257 AND #imm, R0 {: R0 &= imm; :}
258 AND.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & MEM_READ_BYTE(R0 + sh4r.gbr) ); :}
259 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
260 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
261 OR #imm, R0 {: R0 |= imm; :}
262 OR.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | MEM_READ_BYTE(R0 + sh4r.gbr) ); :}
264 tmp = MEM_READ_BYTE( sh4r.r[Rn] );
265 sh4r.t = ( tmp == 0 ? 1 : 0 );
266 MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
268 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
269 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
270 TST.B #imm, @(R0, GBR) {: sh4r.t = ( MEM_READ_BYTE(R0 + sh4r.gbr) & imm ? 0 : 1 ); :}
271 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
272 XOR #imm, R0 {: R0 ^= imm; :}
273 XOR.B #imm, @(R0, GBR) {: MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ MEM_READ_BYTE(R0 + sh4r.gbr) ); :}
274 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
277 sh4r.t = sh4r.r[Rn] >> 31;
279 sh4r.r[Rn] |= sh4r.t;
282 sh4r.t = sh4r.r[Rn] & 0x00000001;
284 sh4r.r[Rn] |= (sh4r.t << 31);
287 tmp = sh4r.r[Rn] >> 31;
289 sh4r.r[Rn] |= sh4r.t;
293 tmp = sh4r.r[Rn] & 0x00000001;
295 sh4r.r[Rn] |= (sh4r.t << 31 );
300 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
301 else if( (tmp & 0x1F) == 0 )
302 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
304 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
308 if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
309 else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
310 else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
313 sh4r.t = sh4r.r[Rn] >> 31;
317 sh4r.t = sh4r.r[Rn] & 0x00000001;
318 sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
320 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
321 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
322 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
323 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
324 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
325 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
326 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
327 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
329 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
330 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
331 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
332 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
333 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
334 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
336 CLRT {: sh4r.t = 0; :}
337 SETT {: sh4r.t = 1; :}
338 CLRMAC {: sh4r.mac = 0; :}
339 LDTLB {: /* TODO */ :}
340 CLRS {: sh4r.s = 0; :}
341 SETS {: sh4r.s = 1; :}
342 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
347 if( (tmp & 0xFC000000) == 0xE0000000 ) {
348 sh4_flush_store_queue(tmp);
357 MEM_WRITE_LONG( tmp, R0 );
359 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
360 MOV.W Rm, @(R0, Rn) {:
361 CHECKWALIGN16( R0 + sh4r.r[Rn] );
362 MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
364 MOV.L Rm, @(R0, Rn) {:
365 CHECKWALIGN32( R0 + sh4r.r[Rn] );
366 MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
368 MOV.B @(R0, Rm), Rn {: sh4r.r[Rn] = MEM_READ_BYTE( R0 + sh4r.r[Rm] ); :}
369 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
370 sh4r.r[Rn] = MEM_READ_WORD( R0 + sh4r.r[Rm] );
372 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
373 sh4r.r[Rn] = MEM_READ_LONG( R0 + sh4r.r[Rm] );
375 MOV.L Rm, @(disp, Rn) {:
376 tmp = sh4r.r[Rn] + disp;
377 CHECKWALIGN32( tmp );
378 MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
380 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
381 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
382 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
383 MOV.B Rm, @-Rn {: sh4r.r[Rn] --; MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
384 MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
385 MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
386 MOV.L @(disp, Rm), Rn {:
387 tmp = sh4r.r[Rm] + disp;
388 CHECKRALIGN32( tmp );
389 sh4r.r[Rn] = MEM_READ_LONG( tmp );
391 MOV.B @Rm, Rn {: sh4r.r[Rn] = MEM_READ_BYTE( sh4r.r[Rm] ); :}
392 MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_WORD( sh4r.r[Rm] ); :}
393 MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_LONG( sh4r.r[Rm] ); :}
394 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
395 MOV.B @Rm+, Rn {: sh4r.r[Rn] = MEM_READ_BYTE( sh4r.r[Rm] ); sh4r.r[Rm] ++; :}
396 MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_WORD( sh4r.r[Rm] ); sh4r.r[Rm] += 2; :}
397 MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); sh4r.r[Rn] = MEM_READ_LONG( sh4r.r[Rm] ); sh4r.r[Rm] += 4; :}
398 MOV.L @(disp, PC), Rn {:
400 tmp = (pc&0xFFFFFFFC) + disp + 4;
401 sh4r.r[Rn] = MEM_READ_LONG( tmp );
403 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
404 MOV.W R0, @(disp, GBR) {:
405 tmp = sh4r.gbr + disp;
406 CHECKWALIGN16( tmp );
407 MEM_WRITE_WORD( tmp, R0 );
409 MOV.L R0, @(disp, GBR) {:
410 tmp = sh4r.gbr + disp;
411 CHECKWALIGN32( tmp );
412 MEM_WRITE_LONG( tmp, R0 );
414 MOV.B @(disp, GBR), R0 {: R0 = MEM_READ_BYTE( sh4r.gbr + disp ); :}
415 MOV.W @(disp, GBR), R0 {:
416 tmp = sh4r.gbr + disp;
417 CHECKRALIGN16( tmp );
418 R0 = MEM_READ_WORD( tmp );
420 MOV.L @(disp, GBR), R0 {:
421 tmp = sh4r.gbr + disp;
422 CHECKRALIGN32( tmp );
423 R0 = MEM_READ_LONG( tmp );
425 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
426 MOV.W R0, @(disp, Rn) {:
427 tmp = sh4r.r[Rn] + disp;
428 CHECKWALIGN16( tmp );
429 MEM_WRITE_WORD( tmp, R0 );
431 MOV.B @(disp, Rm), R0 {: R0 = MEM_READ_BYTE( sh4r.r[Rm] + disp ); :}
432 MOV.W @(disp, Rm), R0 {:
433 tmp = sh4r.r[Rm] + disp;
434 CHECKRALIGN16( tmp );
435 R0 = MEM_READ_WORD( tmp );
437 MOV.W @(disp, PC), Rn {:
440 sh4r.r[Rn] = MEM_READ_WORD( tmp );
442 MOVA @(disp, PC), R0 {:
444 R0 = (pc&0xFFFFFFFC) + disp + 4;
446 MOV #imm, Rn {: sh4r.r[Rn] = imm; :}
448 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
449 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
450 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
451 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
452 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
453 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
454 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
455 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
457 /* set T = 1 if any byte in RM & RN is the same */
458 tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
459 sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
460 (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
463 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
464 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
467 sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
468 sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
471 tmp = sh4r.r[Rn] + sh4r.r[Rm];
472 sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
475 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
477 sh4r.q = sh4r.r[Rn]>>31;
478 sh4r.m = sh4r.r[Rm]>>31;
479 sh4r.t = sh4r.q ^ sh4r.m;
482 /* This is derived from the sh4 manual with some simplifications */
483 uint32_t tmp0, tmp1, tmp2, dir;
485 dir = sh4r.q ^ sh4r.m;
486 sh4r.q = (sh4r.r[Rn] >> 31);
488 sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
492 tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
495 tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
497 sh4r.q ^= sh4r.m ^ tmp1;
498 sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
500 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
501 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
504 sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
507 CHECKRALIGN16( sh4r.r[Rn] );
508 CHECKRALIGN16( sh4r.r[Rm] );
509 int32_t stmp = SIGNEXT16(MEM_READ_WORD(sh4r.r[Rn]));
511 stmp = stmp * SIGNEXT16(MEM_READ_WORD(sh4r.r[Rm]));
514 int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
515 if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
516 sh4r.mac = 0x000000017FFFFFFFLL;
517 } else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
518 sh4r.mac = 0x0000000180000000LL;
520 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
521 ((uint32_t)(sh4r.mac + stmp));
524 sh4r.mac += SIGNEXT32(stmp);
528 CHECKRALIGN32( sh4r.r[Rm] );
529 CHECKRALIGN32( sh4r.r[Rn] );
530 int64_t tmpl = SIGNEXT32(MEM_READ_LONG(sh4r.r[Rn]));
532 tmpl = tmpl * SIGNEXT32(MEM_READ_LONG(sh4r.r[Rm])) + sh4r.mac;
535 /* 48-bit Saturation. Yuch */
536 if( tmpl < (int64_t)0xFFFF800000000000LL )
537 tmpl = 0xFFFF800000000000LL;
538 else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
539 tmpl = 0x00007FFFFFFFFFFFLL;
543 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
544 (sh4r.r[Rm] * sh4r.r[Rn]); :}
546 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
547 (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
550 sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
551 (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
554 tmp = 0 - sh4r.r[Rm];
555 sh4r.r[Rn] = tmp - sh4r.t;
556 sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
558 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
559 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
562 sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
563 sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
568 CHECKDEST( pc + 4 + sh4r.r[Rn] );
569 sh4r.in_delay_slot = 1;
570 sh4r.pc = sh4r.new_pc;
571 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
576 CHECKDEST( pc + 4 + sh4r.r[Rn] );
577 sh4r.in_delay_slot = 1;
578 sh4r.pr = sh4r.pc + 4;
579 sh4r.pc = sh4r.new_pc;
580 sh4r.new_pc = pc + 4 + sh4r.r[Rn];
581 TRACE_CALL( pc, sh4r.new_pc );
587 CHECKDEST( sh4r.pc + disp + 4 )
589 sh4r.new_pc = sh4r.pc + 2;
596 CHECKDEST( sh4r.pc + disp + 4 )
598 sh4r.new_pc = sh4r.pc + 2;
605 CHECKDEST( sh4r.pc + disp + 4 )
606 sh4r.in_delay_slot = 1;
607 sh4r.pc = sh4r.new_pc;
608 sh4r.new_pc = pc + disp + 4;
609 sh4r.in_delay_slot = 1;
616 CHECKDEST( sh4r.pc + disp + 4 )
617 sh4r.in_delay_slot = 1;
618 sh4r.pc = sh4r.new_pc;
619 sh4r.new_pc = pc + disp + 4;
625 CHECKDEST( sh4r.pc + disp + 4 );
626 sh4r.in_delay_slot = 1;
627 sh4r.pc = sh4r.new_pc;
628 sh4r.new_pc = pc + 4 + disp;
632 CHECKDEST( sh4r.pc + disp + 4 );
634 sh4r.in_delay_slot = 1;
636 sh4r.pc = sh4r.new_pc;
637 sh4r.new_pc = pc + 4 + disp;
638 TRACE_CALL( pc, sh4r.new_pc );
643 MMIO_WRITE( MMU, TRA, imm<<2 );
645 sh4_raise_exception( EXC_TRAP );
649 CHECKDEST( sh4r.pr );
650 sh4r.in_delay_slot = 1;
651 sh4r.pc = sh4r.new_pc;
652 sh4r.new_pc = sh4r.pr;
653 TRACE_RETURN( pc, sh4r.new_pc );
657 if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
658 sh4r.sh4_state = SH4_STATE_STANDBY;
660 sh4r.sh4_state = SH4_STATE_SLEEP;
662 return FALSE; /* Halt CPU */
666 CHECKDEST( sh4r.spc );
668 sh4r.in_delay_slot = 1;
669 sh4r.pc = sh4r.new_pc;
670 sh4r.new_pc = sh4r.spc;
671 sh4_write_sr( sh4r.ssr );
675 CHECKDEST( sh4r.r[Rn] );
677 sh4r.in_delay_slot = 1;
678 sh4r.pc = sh4r.new_pc;
679 sh4r.new_pc = sh4r.r[Rn];
683 CHECKDEST( sh4r.r[Rn] );
685 sh4r.in_delay_slot = 1;
686 sh4r.pc = sh4r.new_pc;
687 sh4r.new_pc = sh4r.r[Rn];
689 TRACE_CALL( pc, sh4r.new_pc );
692 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
695 CHECKWALIGN32( sh4r.r[Rn] );
696 MEM_WRITE_LONG( sh4r.r[Rn], (sh4r.mac>>32) );
701 CHECKWALIGN32( sh4r.r[Rn] );
702 MEM_WRITE_LONG( sh4r.r[Rn], sh4_read_sr() );
705 CHECKRALIGN32( sh4r.r[Rm] );
706 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
707 (((uint64_t)MEM_READ_LONG(sh4r.r[Rm]))<<32);
713 CHECKWALIGN32( sh4r.r[Rm] );
714 sh4_write_sr( MEM_READ_LONG(sh4r.r[Rm]) );
718 sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
719 (((uint64_t)sh4r.r[Rm])<<32);
724 sh4_write_sr( sh4r.r[Rm] );
728 sh4r.sgr = sh4r.r[Rm];
732 CHECKRALIGN32( sh4r.r[Rm] );
733 sh4r.sgr = MEM_READ_LONG(sh4r.r[Rm]);
736 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
739 CHECKWALIGN32( sh4r.r[Rn] );
740 MEM_WRITE_LONG( sh4r.r[Rn], (uint32_t)sh4r.mac );
744 CHECKWALIGN32( sh4r.r[Rn] );
745 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.gbr );
748 CHECKRALIGN32( sh4r.r[Rm] );
749 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
750 (uint64_t)((uint32_t)MEM_READ_LONG(sh4r.r[Rm]));
754 CHECKRALIGN32( sh4r.r[Rm] );
755 sh4r.gbr = MEM_READ_LONG(sh4r.r[Rm]);
759 sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
760 (uint64_t)((uint32_t)(sh4r.r[Rm]));
762 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
763 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
766 CHECKWALIGN32( sh4r.r[Rn] );
767 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.pr );
772 CHECKWALIGN32( sh4r.r[Rn] );
773 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.vbr );
776 CHECKRALIGN32( sh4r.r[Rm] );
777 sh4r.pr = MEM_READ_LONG( sh4r.r[Rm] );
782 CHECKRALIGN32( sh4r.r[Rm] );
783 sh4r.vbr = MEM_READ_LONG(sh4r.r[Rm]);
786 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
789 sh4r.vbr = sh4r.r[Rm];
793 sh4r.r[Rn] = sh4r.sgr;
798 CHECKWALIGN32( sh4r.r[Rn] );
799 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.sgr );
804 CHECKWALIGN32( sh4r.r[Rn] );
805 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.ssr );
809 CHECKRALIGN32( sh4r.r[Rm] );
810 sh4r.ssr = MEM_READ_LONG(sh4r.r[Rm]);
815 sh4r.ssr = sh4r.r[Rm];
820 CHECKWALIGN32( sh4r.r[Rn] );
821 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.spc );
825 CHECKRALIGN32( sh4r.r[Rm] );
826 sh4r.spc = MEM_READ_LONG(sh4r.r[Rm]);
831 sh4r.spc = sh4r.r[Rm];
833 STS FPUL, Rn {: sh4r.r[Rn] = sh4r.fpul; :}
836 CHECKWALIGN32( sh4r.r[Rn] );
837 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.fpul );
840 CHECKRALIGN32( sh4r.r[Rm] );
841 sh4r.fpul = MEM_READ_LONG(sh4r.r[Rm]);
844 LDS Rm, FPUL {: sh4r.fpul = sh4r.r[Rm]; :}
845 STS FPSCR, Rn {: sh4r.r[Rn] = sh4r.fpscr; :}
848 CHECKWALIGN32( sh4r.r[Rn] );
849 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.fpscr );
852 CHECKRALIGN32( sh4r.r[Rm] );
853 sh4r.fpscr = MEM_READ_LONG(sh4r.r[Rm]);
855 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
858 sh4r.fpscr = sh4r.r[Rm];
859 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
861 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
865 CHECKWALIGN32( sh4r.r[Rn] );
866 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.dbr );
870 CHECKRALIGN32( sh4r.r[Rm] );
871 sh4r.dbr = MEM_READ_LONG(sh4r.r[Rm]);
876 sh4r.dbr = sh4r.r[Rm];
878 STC.L Rm_BANK, @-Rn {:
881 CHECKWALIGN32( sh4r.r[Rn] );
882 MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r_bank[Rm_BANK] );
884 LDC.L @Rm+, Rn_BANK {:
886 CHECKRALIGN32( sh4r.r[Rm] );
887 sh4r.r_bank[Rn_BANK] = MEM_READ_LONG( sh4r.r[Rm] );
892 sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
896 sh4r.r[Rn] = sh4_read_sr();
900 sh4r.r[Rn] = sh4r.gbr;
904 sh4r.r[Rn] = sh4r.vbr;
908 sh4r.r[Rn] = sh4r.ssr;
912 sh4r.r[Rn] = sh4r.spc;
916 sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
921 if( IS_FPU_DOUBLEPREC() ) {
929 if( IS_FPU_DOUBLEPREC() ) {
938 if( IS_FPU_DOUBLEPREC() ) {
947 if( IS_FPU_DOUBLEPREC() ) {
956 if( IS_FPU_DOUBLEPREC() ) {
957 sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
959 sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
965 if( IS_FPU_DOUBLEPREC() ) {
966 sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
968 sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
972 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
973 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
974 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
975 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
976 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
977 FMOV FRm, @-Rn {: sh4r.r[Rn] -= FP_WIDTH; MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
979 if( IS_FPU_DOUBLESIZE() )
984 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
985 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
988 if( IS_FPU_DOUBLEPREC() ) {
989 if( FRn&1 ) { // No, really...
990 dtmp = (double)FPULi;
991 FR(FRn) = *(((float *)&dtmp)+1);
993 DRF(FRn>>1) = (double)FPULi;
996 FR(FRn) = (float)FPULi;
1001 if( IS_FPU_DOUBLEPREC() ) {
1004 *(((float *)&dtmp)+1) = FR(FRm);
1008 if( dtmp >= MAX_INTF )
1010 else if( dtmp <= MIN_INTF )
1013 FPULi = (int32_t)dtmp;
1016 if( ftmp >= MAX_INTF )
1018 else if( ftmp <= MIN_INTF )
1021 FPULi = (int32_t)ftmp;
1026 if( IS_FPU_DOUBLEPREC() ) {
1034 if( IS_FPU_DOUBLEPREC() ) {
1035 DR(FRn) = fabs(DR(FRn));
1037 FR(FRn) = fabsf(FR(FRn));
1042 if( IS_FPU_DOUBLEPREC() ) {
1043 DR(FRn) = sqrt(DR(FRn));
1045 FR(FRn) = sqrtf(FR(FRn));
1050 if( IS_FPU_DOUBLEPREC() ) {
1058 if( IS_FPU_DOUBLEPREC() ) {
1064 FMAC FR0, FRm, FRn {:
1066 if( IS_FPU_DOUBLEPREC() ) {
1067 DR(FRn) += DR(FRm)*DR(0);
1069 FR(FRn) += FR(FRm)*FR(0);
1074 sh4r.fpscr ^= FPSCR_FR;
1075 sh4r.fr_bank = &sh4r.fr[(sh4r.fpscr&FPSCR_FR)>>21][0];
1077 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
1080 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1081 DR(FRn) = (double)FPULf;
1086 if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
1087 FPULf = (float)DR(FRm);
1093 if( !IS_FPU_DOUBLEPREC() ) {
1094 FR(FRn) = 1.0/sqrtf(FR(FRn));
1099 if( !IS_FPU_DOUBLEPREC() ) {
1102 FR(tmp2+3) = FR(tmp)*FR(tmp2) +
1103 FR(tmp+1)*FR(tmp2+1) +
1104 FR(tmp+2)*FR(tmp2+2) +
1105 FR(tmp+3)*FR(tmp2+3);
1110 if( !IS_FPU_DOUBLEPREC() ) {
1111 sh4_fsca( FPULi, &(DRF(FRn>>1)) );
1113 float angle = (((float)(FPULi&0xFFFF))/65536.0) * 2 * M_PI;
1114 FR(FRn) = sinf(angle);
1115 FR((FRn)+1) = cosf(angle);
1121 if( !IS_FPU_DOUBLEPREC() ) {
1122 sh4_ftrv(&(DRF(FVn<<1)), &sh4r.fr[((~sh4r.fpscr)&FPSCR_FR)>>21][0]);
1125 float *xf = &sh4r.fr[((~sh4r.fpscr)&FPSCR_FR)>>21][0];
1126 float fv[4] = { FR(tmp), FR(tmp+1), FR(tmp+2), FR(tmp+3) };
1127 FR(tmp) = xf[1] * fv[0] + xf[5]*fv[1] +
1128 xf[9]*fv[2] + xf[13]*fv[3];
1129 FR(tmp+1) = xf[0] * fv[0] + xf[4]*fv[1] +
1130 xf[8]*fv[2] + xf[12]*fv[3];
1131 FR(tmp+2) = xf[3] * fv[0] + xf[7]*fv[1] +
1132 xf[11]*fv[2] + xf[15]*fv[3];
1133 FR(tmp+3) = xf[2] * fv[0] + xf[6]*fv[1] +
1134 xf[10]*fv[2] + xf[14]*fv[3];
1142 sh4r.pc = sh4r.new_pc;
1144 sh4r.in_delay_slot = 0;
.