Search
lxdream.org :: lxdream/src/sh4/sh4core.in
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4core.in
changeset 927:17b6b9e245d8
prev758:99ae000d4e09
next939:6f2302afeb89
next953:f4a156508ad1
author nkeynes
date Sat Dec 27 02:59:35 2008 +0000 (15 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Replace fpscr_mask/fpscr flags in xlat_cache_block with a single xlat_sh4_mode,
which tracks the field of the same name in sh4r - actually a little faster this way.
Now depends on SR.MD, FPSCR.PR and FPSCR.SZ (although it doesn't benefit from the SR
flag yet).

Also fixed the failure to check the flags in the common case (code address returned
by previous block) which took away the performance benefits, but oh well.
view annotate diff log raw
     1 /**
     2  * $Id$
     3  * 
     4  * SH4 emulation core, and parent module for all the SH4 peripheral
     5  * modules.
     6  *
     7  * Copyright (c) 2005 Nathan Keynes.
     8  *
     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.
    13  *
    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.
    18  */
    20 #define MODULE sh4_module
    21 #include <assert.h>
    22 #include <math.h>
    23 #include "dream.h"
    24 #include "dreamcast.h"
    25 #include "eventq.h"
    26 #include "mem.h"
    27 #include "clock.h"
    28 #include "syscall.h"
    29 #include "sh4/sh4core.h"
    30 #include "sh4/sh4mmio.h"
    31 #include "sh4/sh4stat.h"
    32 #include "sh4/intc.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 ) 
    44 {
    45     int i;
    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 ) {
    51 		    event_execute();
    52 		}
    53 		/* Eventq execute may (quite likely) deliver an immediate IRQ */
    54 		if( sh4r.event_types & PENDING_IRQ ) {
    55 		    sh4_accept_interrupt();
    56 		}
    57 	    }
    58 	    if( !sh4_execute_instruction() ) {
    59 		break;
    60 	    }
    61 	}
    62     } else {
    63 	for( ;sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
    64 	    if( SH4_EVENT_PENDING() ) {
    65 		if( sh4r.event_types & PENDING_EVENT ) {
    66 		    event_execute();
    67 		}
    68 		/* Eventq execute may (quite likely) deliver an immediate IRQ */
    69 		if( sh4r.event_types & PENDING_IRQ ) {
    70 		    sh4_accept_interrupt();
    71 		}
    72 	    }
    74 	    if( !sh4_execute_instruction() )
    75 		break;
    76 #ifdef ENABLE_DEBUG_MODE
    77 	    for( i=0; i<sh4_breakpoint_count; i++ ) {
    78 		if( sh4_breakpoints[i].address == sh4r.pc ) {
    79 		    break;
    80 		}
    81 	    }
    82 	    if( i != sh4_breakpoint_count ) {
    83 	    	sh4_core_exit( CORE_EXIT_BREAKPOINT );
    84 	    }
    85 #endif	
    86 	}
    87     }
    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
    91      * actually executed
    92      */
    93     if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
    94 	nanosecs = sh4r.slice_cycle;
    95     }
    96     if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
    97 	TMU_run_slice( nanosecs );
    98 	SCIF_run_slice( nanosecs );
    99     }
   100     return nanosecs;
   101 }
   103 /********************** SH4 emulation core  ****************************/
   105 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
   106 #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)
   108 #if(SH4_CALLTRACE == 1)
   109 #define MAX_CALLSTACK 32
   110 static struct call_stack {
   111     sh4addr_t call_addr;
   112     sh4addr_t target_addr;
   113     sh4addr_t stack_pointer;
   114 } call_stack[MAX_CALLSTACK];
   116 static int call_stack_depth = 0;
   117 int sh4_call_trace_on = 0;
   119 static inline void trace_call( sh4addr_t source, sh4addr_t dest ) 
   120 {
   121     if( call_stack_depth < MAX_CALLSTACK ) {
   122 	call_stack[call_stack_depth].call_addr = source;
   123 	call_stack[call_stack_depth].target_addr = dest;
   124 	call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
   125     }
   126     call_stack_depth++;
   127 }
   129 static inline void trace_return( sh4addr_t source, sh4addr_t dest )
   130 {
   131     if( call_stack_depth > 0 ) {
   132 	call_stack_depth--;
   133     }
   134 }
   136 void fprint_stack_trace( FILE *f )
   137 {
   138     int i = call_stack_depth -1;
   139     if( i >= MAX_CALLSTACK )
   140 	i = MAX_CALLSTACK - 1;
   141     for( ; i >= 0; i-- ) {
   142 	fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n", 
   143 		 (call_stack_depth - i), call_stack[i].call_addr,
   144 		 call_stack[i].target_addr, call_stack[i].stack_pointer );
   145     }
   146 }
   148 #define TRACE_CALL( source, dest ) trace_call(source, dest)
   149 #define TRACE_RETURN( source, dest ) trace_return(source, dest)
   150 #else
   151 #define TRACE_CALL( dest, rts ) 
   152 #define TRACE_RETURN( source, dest )
   153 #endif
   155 #define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )
   156 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
   157 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
   158 #define CHECKRALIGN64(addr) if( (addr)&0x07 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
   159 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
   160 #define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
   161 #define CHECKWALIGN64(addr) if( (addr)&0x07 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
   163 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
   164 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }
   165 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)
   167 #ifdef HAVE_FRAME_ADDRESS
   168 static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }
   169 #define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:
   170 #define MMU_TRANSLATE_READ( addr ) memtmp = mmu_vma_to_phys_read(addr, &&except )
   171 #define MMU_TRANSLATE_WRITE( addr ) memtmp = mmu_vma_to_phys_write(addr, &&except )
   172 #else
   173 #define INIT_EXCEPTIONS(label)
   174 #define MMU_TRANSLATE_READ( addr ) if( (memtmp = mmu_vma_to_phys_read(addr)) == MMU_VMA_ERROR ) { return TRUE; }
   175 #define MMU_TRANSLATE_WRITE( addr ) if( (memtmp = mmu_vma_to_phys_write(addr)) == MMU_VMA_ERROR ) { return TRUE; }
   176 #endif
   178 #define MEM_READ_BYTE( addr, val ) MMU_TRANSLATE_READ(addr); val = sh4_read_byte(memtmp)
   179 #define MEM_READ_WORD( addr, val ) MMU_TRANSLATE_READ(addr); val = sh4_read_word(memtmp)
   180 #define MEM_READ_LONG( addr, val ) MMU_TRANSLATE_READ(addr); val = sh4_read_long(memtmp)
   181 #define MEM_WRITE_BYTE( addr, val ) MMU_TRANSLATE_WRITE(addr); sh4_write_byte(memtmp, val) 
   182 #define MEM_WRITE_WORD( addr, val ) MMU_TRANSLATE_WRITE(addr); sh4_write_word(memtmp, val) 
   183 #define MEM_WRITE_LONG( addr, val ) MMU_TRANSLATE_WRITE(addr); sh4_write_long(memtmp, val)
   186 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
   188 #define MEM_FP_READ( addr, reg ) \
   189     if( IS_FPU_DOUBLESIZE() ) { \
   190 	CHECKRALIGN64(addr); \
   191 	MMU_TRANSLATE_READ(addr); \
   192         if( reg & 1 ) { \
   193             *((uint32_t *)&XF((reg) & 0x0E)) = sh4_read_long(memtmp); \
   194             *((uint32_t *)&XF(reg)) = sh4_read_long(memtmp+4); \
   195         } else { \
   196             *((uint32_t *)&FR(reg)) = sh4_read_long(memtmp); \
   197             *((uint32_t *)&FR((reg) | 0x01)) = sh4_read_long(memtmp+4); \
   198 	} \
   199     } else { \
   200         CHECKRALIGN32(addr); \
   201         MMU_TRANSLATE_READ(addr); \
   202         *((uint32_t *)&FR(reg)) = sh4_read_long(memtmp); \
   203     }
   204 #define MEM_FP_WRITE( addr, reg ) \
   205     if( IS_FPU_DOUBLESIZE() ) { \
   206         CHECKWALIGN64(addr); \
   207         MMU_TRANSLATE_WRITE(addr); \
   208         if( reg & 1 ) { \
   209 	    sh4_write_long( memtmp, *((uint32_t *)&XF((reg)&0x0E)) ); \
   210 	    sh4_write_long( memtmp+4, *((uint32_t *)&XF(reg)) ); \
   211         } else { \
   212 	    sh4_write_long( memtmp, *((uint32_t *)&FR(reg)) ); \
   213 	    sh4_write_long( memtmp+4, *((uint32_t *)&FR((reg)|0x01)) ); \
   214 	} \
   215     } else { \
   216     	CHECKWALIGN32(addr); \
   217     	MMU_TRANSLATE_WRITE(addr); \
   218         sh4_write_long( memtmp, *((uint32_t *)&FR((reg))) ); \
   219     }
   221 gboolean sh4_execute_instruction( void )
   222 {
   223     uint32_t pc;
   224     unsigned short ir;
   225     uint32_t tmp;
   226     float ftmp;
   227     double dtmp;
   228     int64_t memtmp; // temporary holder for memory reads
   230     INIT_EXCEPTIONS(except)
   232 #define R0 sh4r.r[0]
   233     pc = sh4r.pc;
   234     if( pc > 0xFFFFFF00 ) {
   235 	/* SYSCALL Magic */
   236 	syscall_invoke( pc );
   237 	sh4r.in_delay_slot = 0;
   238 	pc = sh4r.pc = sh4r.pr;
   239 	sh4r.new_pc = sh4r.pc + 2;
   240         return TRUE;
   241     }
   242     CHECKRALIGN16(pc);
   244 #ifdef ENABLE_SH4STATS
   245     sh4_stats_add_by_pc(sh4r.pc);
   246 #endif
   248     /* Read instruction */
   249     if( !IS_IN_ICACHE(pc) ) {
   250 	if( !mmu_update_icache(pc) ) {
   251 	    // Fault - look for the fault handler
   252 	    if( !mmu_update_icache(sh4r.pc) ) {
   253 		// double fault - halt
   254 		ERROR( "Double fault - halting" );
   255 		sh4_core_exit(CORE_EXIT_HALT);
   256 		return FALSE;
   257 	    }
   258 	}
   259 	pc = sh4r.pc;
   260     }
   261     assert( IS_IN_ICACHE(pc) );
   262     ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
   263 %%
   264 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
   265 AND #imm, R0 {: R0 &= imm; :}
   266  AND.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & tmp ); :}
   267 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
   268 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
   269 OR #imm, R0  {: R0 |= imm; :}
   270  OR.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | tmp ); :}
   271 TAS.B @Rn {:
   272     MEM_READ_BYTE( sh4r.r[Rn], tmp );
   273     sh4r.t = ( tmp == 0 ? 1 : 0 );
   274     MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
   275 :}
   276 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
   277 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
   278  TST.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); sh4r.t = ( tmp & imm ? 0 : 1 ); :}
   279 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
   280 XOR #imm, R0 {: R0 ^= imm; :}
   281  XOR.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ tmp ); :}
   282 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
   284 ROTL Rn {:
   285     sh4r.t = sh4r.r[Rn] >> 31;
   286     sh4r.r[Rn] <<= 1;
   287     sh4r.r[Rn] |= sh4r.t;
   288 :}
   289 ROTR Rn {:
   290     sh4r.t = sh4r.r[Rn] & 0x00000001;
   291     sh4r.r[Rn] >>= 1;
   292     sh4r.r[Rn] |= (sh4r.t << 31);
   293 :}
   294 ROTCL Rn {:
   295     tmp = sh4r.r[Rn] >> 31;
   296     sh4r.r[Rn] <<= 1;
   297     sh4r.r[Rn] |= sh4r.t;
   298     sh4r.t = tmp;
   299 :}
   300 ROTCR Rn {:
   301     tmp = sh4r.r[Rn] & 0x00000001;
   302     sh4r.r[Rn] >>= 1;
   303     sh4r.r[Rn] |= (sh4r.t << 31 );
   304     sh4r.t = tmp;
   305 :}
   306 SHAD Rm, Rn {:
   307     tmp = sh4r.r[Rm];
   308     if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
   309     else if( (tmp & 0x1F) == 0 )  
   310         sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
   311     else 
   312 	sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
   313 :}
   314 SHLD Rm, Rn {:
   315     tmp = sh4r.r[Rm];
   316     if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
   317     else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
   318     else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
   319 :}
   320 SHAL Rn {:
   321     sh4r.t = sh4r.r[Rn] >> 31;
   322     sh4r.r[Rn] <<= 1;
   323 :}
   324 SHAR Rn {:
   325     sh4r.t = sh4r.r[Rn] & 0x00000001;
   326     sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
   327 :}
   328 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
   329 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
   330 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
   331 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
   332 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
   333 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
   334 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
   335 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
   337 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
   338 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
   339 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
   340 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
   341 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
   342 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
   344 CLRT {: sh4r.t = 0; :}
   345 SETT {: sh4r.t = 1; :}
   346 CLRMAC {: sh4r.mac = 0; :}
   347 LDTLB {: MMU_ldtlb(); :}
   348 CLRS {: sh4r.s = 0; :}
   349 SETS {: sh4r.s = 1; :}
   350 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
   351 NOP {: /* NOP */ :}
   353 PREF @Rn {:
   354      tmp = sh4r.r[Rn];
   355      if( (tmp & 0xFC000000) == 0xE0000000 ) {
   356 	 sh4_flush_store_queue(tmp);
   357      }
   358 :}
   359 OCBI @Rn {: :}
   360 OCBP @Rn {: :}
   361 OCBWB @Rn {: :}
   362 MOVCA.L R0, @Rn {:
   363     tmp = sh4r.r[Rn];
   364     CHECKWALIGN32(tmp);
   365     MEM_WRITE_LONG( tmp, R0 );
   366 :}
   367 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
   368 MOV.W Rm, @(R0, Rn) {: 
   369     CHECKWALIGN16( R0 + sh4r.r[Rn] );
   370     MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
   371 :}
   372 MOV.L Rm, @(R0, Rn) {:
   373     CHECKWALIGN32( R0 + sh4r.r[Rn] );
   374     MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
   375 :}
   376 MOV.B @(R0, Rm), Rn {: MEM_READ_BYTE( R0 + sh4r.r[Rm], sh4r.r[Rn] ); :}
   377 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
   378     MEM_READ_WORD( R0 + sh4r.r[Rm], sh4r.r[Rn] );
   379 :}
   380 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
   381     MEM_READ_LONG( R0 + sh4r.r[Rm], sh4r.r[Rn] );
   382 :}
   383 MOV.L Rm, @(disp, Rn) {:
   384     tmp = sh4r.r[Rn] + disp;
   385     CHECKWALIGN32( tmp );
   386     MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
   387 :}
   388 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
   389 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
   390 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
   391  MOV.B Rm, @-Rn {: MEM_WRITE_BYTE( sh4r.r[Rn]-1, sh4r.r[Rm] ); sh4r.r[Rn]--; :}
   392  MOV.W Rm, @-Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn]-2, sh4r.r[Rm] ); sh4r.r[Rn] -= 2; :}
   393  MOV.L Rm, @-Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r[Rm] ); sh4r.r[Rn] -= 4; :}
   394 MOV.L @(disp, Rm), Rn {:
   395     tmp = sh4r.r[Rm] + disp;
   396     CHECKRALIGN32( tmp );
   397     MEM_READ_LONG( tmp, sh4r.r[Rn] );
   398 :}
   399 MOV.B @Rm, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); :}
   400  MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); :}
   401  MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); :}
   402 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
   403  MOV.B @Rm+, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] ++; :}
   404  MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] += 2; :}
   405  MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] += 4; :}
   406 MOV.L @(disp, PC), Rn {:
   407     CHECKSLOTILLEGAL();
   408     tmp = (pc&0xFFFFFFFC) + disp + 4;
   409     MEM_READ_LONG( tmp, sh4r.r[Rn] );
   410 :}
   411 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
   412 MOV.W R0, @(disp, GBR) {:
   413     tmp = sh4r.gbr + disp;
   414     CHECKWALIGN16( tmp );
   415     MEM_WRITE_WORD( tmp, R0 );
   416 :}
   417 MOV.L R0, @(disp, GBR) {:
   418     tmp = sh4r.gbr + disp;
   419     CHECKWALIGN32( tmp );
   420     MEM_WRITE_LONG( tmp, R0 );
   421 :}
   422  MOV.B @(disp, GBR), R0 {: MEM_READ_BYTE( sh4r.gbr + disp, R0 ); :}
   423 MOV.W @(disp, GBR), R0 {: 
   424     tmp = sh4r.gbr + disp;
   425     CHECKRALIGN16( tmp );
   426     MEM_READ_WORD( tmp, R0 );
   427 :}
   428 MOV.L @(disp, GBR), R0 {:
   429     tmp = sh4r.gbr + disp;
   430     CHECKRALIGN32( tmp );
   431     MEM_READ_LONG( tmp, R0 );
   432 :}
   433 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
   434 MOV.W R0, @(disp, Rn) {: 
   435     tmp = sh4r.r[Rn] + disp;
   436     CHECKWALIGN16( tmp );
   437     MEM_WRITE_WORD( tmp, R0 );
   438 :}
   439  MOV.B @(disp, Rm), R0 {: MEM_READ_BYTE( sh4r.r[Rm] + disp, R0 ); :}
   440 MOV.W @(disp, Rm), R0 {: 
   441     tmp = sh4r.r[Rm] + disp;
   442     CHECKRALIGN16( tmp );
   443     MEM_READ_WORD( tmp, R0 );
   444 :}
   445 MOV.W @(disp, PC), Rn {:
   446     CHECKSLOTILLEGAL();
   447     tmp = pc + 4 + disp;
   448     MEM_READ_WORD( tmp, sh4r.r[Rn] );
   449 :}
   450 MOVA @(disp, PC), R0 {:
   451     CHECKSLOTILLEGAL();
   452     R0 = (pc&0xFFFFFFFC) + disp + 4;
   453 :}
   454 MOV #imm, Rn {:  sh4r.r[Rn] = imm; :}
   456 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
   457 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
   458 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
   459 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
   460 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
   461  FMOV FRm, @-Rn {: MEM_FP_WRITE( sh4r.r[Rn] - FP_WIDTH, FRm ); sh4r.r[Rn] -= FP_WIDTH; :}
   462 FMOV FRm, FRn {: 
   463     if( IS_FPU_DOUBLESIZE() )
   464 	DR(FRn) = DR(FRm);
   465     else
   466 	FR(FRn) = FR(FRm);
   467 :}
   469 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
   470 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
   471 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
   472 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
   473 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
   474 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
   475 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
   476 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
   477 CMP/STR Rm, Rn {: 
   478     /* set T = 1 if any byte in RM & RN is the same */
   479     tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
   480     sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
   481              (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
   482 :}
   484 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
   485 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
   486 ADDC Rm, Rn {:
   487     tmp = sh4r.r[Rn];
   488     sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
   489     sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
   490 :}
   491 ADDV Rm, Rn {:
   492     tmp = sh4r.r[Rn] + sh4r.r[Rm];
   493     sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
   494     sh4r.r[Rn] = tmp;
   495 :}
   496 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
   497 DIV0S Rm, Rn {: 
   498     sh4r.q = sh4r.r[Rn]>>31;
   499     sh4r.m = sh4r.r[Rm]>>31;
   500     sh4r.t = sh4r.q ^ sh4r.m;
   501 :}
   502 DIV1 Rm, Rn {:
   503     /* This is derived from the sh4 manual with some simplifications */
   504     uint32_t tmp0, tmp1, tmp2, dir;
   506     dir = sh4r.q ^ sh4r.m;
   507     sh4r.q = (sh4r.r[Rn] >> 31);
   508     tmp2 = sh4r.r[Rm];
   509     sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
   510     tmp0 = sh4r.r[Rn];
   511     if( dir ) {
   512          sh4r.r[Rn] += tmp2;
   513          tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
   514     } else {
   515          sh4r.r[Rn] -= tmp2;
   516          tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
   517     }
   518     sh4r.q ^= sh4r.m ^ tmp1;
   519     sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
   520 :}
   521 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
   522 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
   523 DT Rn {:
   524     sh4r.r[Rn] --;
   525     sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
   526 :}
   527 MAC.W @Rm+, @Rn+ {:
   528     int32_t stmp;
   529     if( Rm == Rn ) {
   530 	CHECKRALIGN16(sh4r.r[Rn]);
   531 	MEM_READ_WORD( sh4r.r[Rn], tmp );
   532 	stmp = SIGNEXT16(tmp);
   533 	MEM_READ_WORD( sh4r.r[Rn]+2, tmp );
   534 	stmp *= SIGNEXT16(tmp);
   535 	sh4r.r[Rn] += 4;
   536     } else {
   537 	CHECKRALIGN16( sh4r.r[Rn] );
   538 	CHECKRALIGN16( sh4r.r[Rm] );
   539 	MEM_READ_WORD(sh4r.r[Rn], tmp);
   540 	stmp = SIGNEXT16(tmp);
   541 	MEM_READ_WORD(sh4r.r[Rm], tmp);
   542 	stmp = stmp * SIGNEXT16(tmp);
   543 	sh4r.r[Rn] += 2;
   544 	sh4r.r[Rm] += 2;
   545     }
   546     if( sh4r.s ) {
   547 	int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
   548 	if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
   549 	    sh4r.mac = 0x000000017FFFFFFFLL;
   550 	} else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
   551 	    sh4r.mac = 0x0000000180000000LL;
   552 	} else {
   553 	    sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
   554 		((uint32_t)(sh4r.mac + stmp));
   555 	}
   556     } else {
   557 	sh4r.mac += SIGNEXT32(stmp);
   558     }
   559 :}
   560 MAC.L @Rm+, @Rn+ {:
   561     int64_t tmpl;
   562     if( Rm == Rn ) {
   563 	CHECKRALIGN32( sh4r.r[Rn] );
   564 	MEM_READ_LONG(sh4r.r[Rn], tmp);
   565 	tmpl = SIGNEXT32(tmp);
   566 	MEM_READ_LONG(sh4r.r[Rn]+4, tmp);
   567 	tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
   568 	sh4r.r[Rn] += 8;
   569     } else {
   570 	CHECKRALIGN32( sh4r.r[Rm] );
   571 	CHECKRALIGN32( sh4r.r[Rn] );
   572 	MEM_READ_LONG(sh4r.r[Rn], tmp);
   573 	tmpl = SIGNEXT32(tmp);
   574 	MEM_READ_LONG(sh4r.r[Rm], tmp);
   575 	tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
   576 	sh4r.r[Rn] += 4;
   577 	sh4r.r[Rm] += 4;
   578     }
   579     if( sh4r.s ) {
   580         /* 48-bit Saturation. Yuch */
   581         if( tmpl < (int64_t)0xFFFF800000000000LL )
   582             tmpl = 0xFFFF800000000000LL;
   583         else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
   584             tmpl = 0x00007FFFFFFFFFFFLL;
   585     }
   586     sh4r.mac = tmpl;
   587 :}
   588 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
   589                         (sh4r.r[Rm] * sh4r.r[Rn]); :}
   590 MULU.W Rm, Rn {:
   591     sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
   592                (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
   593 :}
   594 MULS.W Rm, Rn {:
   595     sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
   596                (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
   597 :}
   598 NEGC Rm, Rn {:
   599     tmp = 0 - sh4r.r[Rm];
   600     sh4r.r[Rn] = tmp - sh4r.t;
   601     sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
   602 :}
   603 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
   604 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
   605 SUBC Rm, Rn {: 
   606     tmp = sh4r.r[Rn];
   607     sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
   608     sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
   609 :}
   611 BRAF Rn {:
   612      CHECKSLOTILLEGAL();
   613      CHECKDEST( pc + 4 + sh4r.r[Rn] );
   614      sh4r.in_delay_slot = 1;
   615      sh4r.pc = sh4r.new_pc;
   616      sh4r.new_pc = pc + 4 + sh4r.r[Rn];
   617      return TRUE;
   618 :}
   619 BSRF Rn {:
   620      CHECKSLOTILLEGAL();
   621      CHECKDEST( pc + 4 + sh4r.r[Rn] );
   622      sh4r.in_delay_slot = 1;
   623      sh4r.pr = sh4r.pc + 4;
   624      sh4r.pc = sh4r.new_pc;
   625      sh4r.new_pc = pc + 4 + sh4r.r[Rn];
   626      TRACE_CALL( pc, sh4r.new_pc );
   627      return TRUE;
   628 :}
   629 BT disp {:
   630     CHECKSLOTILLEGAL();
   631     if( sh4r.t ) {
   632         CHECKDEST( sh4r.pc + disp + 4 )
   633         sh4r.pc += disp + 4;
   634         sh4r.new_pc = sh4r.pc + 2;
   635         return TRUE;
   636     }
   637 :}
   638 BF disp {:
   639     CHECKSLOTILLEGAL();
   640     if( !sh4r.t ) {
   641         CHECKDEST( sh4r.pc + disp + 4 )
   642         sh4r.pc += disp + 4;
   643         sh4r.new_pc = sh4r.pc + 2;
   644         return TRUE;
   645     }
   646 :}
   647 BT/S disp {:
   648     CHECKSLOTILLEGAL();
   649     if( sh4r.t ) {
   650         CHECKDEST( sh4r.pc + disp + 4 )
   651         sh4r.in_delay_slot = 1;
   652         sh4r.pc = sh4r.new_pc;
   653         sh4r.new_pc = pc + disp + 4;
   654         sh4r.in_delay_slot = 1;
   655         return TRUE;
   656     }
   657 :}
   658 BF/S disp {:
   659     CHECKSLOTILLEGAL();
   660     if( !sh4r.t ) {
   661         CHECKDEST( sh4r.pc + disp + 4 )
   662         sh4r.in_delay_slot = 1;
   663         sh4r.pc = sh4r.new_pc;
   664         sh4r.new_pc = pc + disp + 4;
   665         return TRUE;
   666     }
   667 :}
   668 BRA disp {:
   669     CHECKSLOTILLEGAL();
   670     CHECKDEST( sh4r.pc + disp + 4 );
   671     sh4r.in_delay_slot = 1;
   672     sh4r.pc = sh4r.new_pc;
   673     sh4r.new_pc = pc + 4 + disp;
   674     return TRUE;
   675 :}
   676 BSR disp {:
   677     CHECKDEST( sh4r.pc + disp + 4 );
   678     CHECKSLOTILLEGAL();
   679     sh4r.in_delay_slot = 1;
   680     sh4r.pr = pc + 4;
   681     sh4r.pc = sh4r.new_pc;
   682     sh4r.new_pc = pc + 4 + disp;
   683     TRACE_CALL( pc, sh4r.new_pc );
   684     return TRUE;
   685 :}
   686 TRAPA #imm {:
   687     CHECKSLOTILLEGAL();
   688     sh4r.pc += 2;
   689     sh4_raise_trap( imm );
   690     return TRUE;
   691 :}
   692 RTS {: 
   693     CHECKSLOTILLEGAL();
   694     CHECKDEST( sh4r.pr );
   695     sh4r.in_delay_slot = 1;
   696     sh4r.pc = sh4r.new_pc;
   697     sh4r.new_pc = sh4r.pr;
   698     TRACE_RETURN( pc, sh4r.new_pc );
   699     return TRUE;
   700 :}
   701 SLEEP {:
   702     if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
   703 	sh4r.sh4_state = SH4_STATE_STANDBY;
   704     } else {
   705 	sh4r.sh4_state = SH4_STATE_SLEEP;
   706     }
   707     return FALSE; /* Halt CPU */
   708 :}
   709 RTE {:
   710     CHECKPRIV();
   711     CHECKDEST( sh4r.spc );
   712     CHECKSLOTILLEGAL();
   713     sh4r.in_delay_slot = 1;
   714     sh4r.pc = sh4r.new_pc;
   715     sh4r.new_pc = sh4r.spc;
   716     sh4_write_sr( sh4r.ssr );
   717     return TRUE;
   718 :}
   719 JMP @Rn {:
   720     CHECKDEST( sh4r.r[Rn] );
   721     CHECKSLOTILLEGAL();
   722     sh4r.in_delay_slot = 1;
   723     sh4r.pc = sh4r.new_pc;
   724     sh4r.new_pc = sh4r.r[Rn];
   725     return TRUE;
   726 :}
   727 JSR @Rn {:
   728     CHECKDEST( sh4r.r[Rn] );
   729     CHECKSLOTILLEGAL();
   730     sh4r.in_delay_slot = 1;
   731     sh4r.pc = sh4r.new_pc;
   732     sh4r.new_pc = sh4r.r[Rn];
   733     sh4r.pr = pc + 4;
   734     TRACE_CALL( pc, sh4r.new_pc );
   735     return TRUE;
   736 :}
   737 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
   738 STS.L MACH, @-Rn {:
   739     CHECKWALIGN32( sh4r.r[Rn] );
   740     MEM_WRITE_LONG( sh4r.r[Rn]-4, (sh4r.mac>>32) );
   741     sh4r.r[Rn] -= 4;
   742 :}
   743 STC.L SR, @-Rn {:
   744     CHECKPRIV();
   745     CHECKWALIGN32( sh4r.r[Rn] );
   746     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4_read_sr() );
   747     sh4r.r[Rn] -= 4;
   748 :}
   749 LDS.L @Rm+, MACH {:
   750     CHECKRALIGN32( sh4r.r[Rm] );
   751     MEM_READ_LONG(sh4r.r[Rm], tmp);
   752     sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
   753 	(((uint64_t)tmp)<<32);
   754     sh4r.r[Rm] += 4;
   755 :}
   756 LDC.L @Rm+, SR {:
   757     CHECKSLOTILLEGAL();
   758     CHECKPRIV();
   759     CHECKWALIGN32( sh4r.r[Rm] );
   760     MEM_READ_LONG(sh4r.r[Rm], tmp);
   761     sh4_write_sr( tmp );
   762     sh4r.r[Rm] +=4;
   763 :}
   764 LDS Rm, MACH {:
   765     sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
   766                (((uint64_t)sh4r.r[Rm])<<32);
   767 :}
   768 LDC Rm, SR {:
   769     CHECKSLOTILLEGAL();
   770     CHECKPRIV();
   771     sh4_write_sr( sh4r.r[Rm] );
   772 :}
   773 LDC Rm, SGR {:
   774     CHECKPRIV();
   775     sh4r.sgr = sh4r.r[Rm];
   776 :}
   777 LDC.L @Rm+, SGR {:
   778     CHECKPRIV();
   779     CHECKRALIGN32( sh4r.r[Rm] );
   780     MEM_READ_LONG(sh4r.r[Rm], sh4r.sgr);
   781     sh4r.r[Rm] +=4;
   782 :}
   783 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
   784 STS.L MACL, @-Rn {:
   785     CHECKWALIGN32( sh4r.r[Rn] );
   786     MEM_WRITE_LONG( sh4r.r[Rn]-4, (uint32_t)sh4r.mac );
   787     sh4r.r[Rn] -= 4;
   788 :}
   789 STC.L GBR, @-Rn {:
   790     CHECKWALIGN32( sh4r.r[Rn] );
   791     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.gbr );
   792     sh4r.r[Rn] -= 4;
   793 :}
   794 LDS.L @Rm+, MACL {:
   795     CHECKRALIGN32( sh4r.r[Rm] );
   796     MEM_READ_LONG(sh4r.r[Rm], tmp);
   797     sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
   798                (uint64_t)((uint32_t)tmp);
   799     sh4r.r[Rm] += 4;
   800 :}
   801 LDC.L @Rm+, GBR {:
   802     CHECKRALIGN32( sh4r.r[Rm] );
   803     MEM_READ_LONG(sh4r.r[Rm], sh4r.gbr);
   804     sh4r.r[Rm] +=4;
   805 :}
   806 LDS Rm, MACL {:
   807     sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
   808                (uint64_t)((uint32_t)(sh4r.r[Rm]));
   809 :}
   810 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
   811 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
   812 STS.L PR, @-Rn {:
   813     CHECKWALIGN32( sh4r.r[Rn] );
   814     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.pr );
   815     sh4r.r[Rn] -= 4;
   816 :}
   817 STC.L VBR, @-Rn {:
   818     CHECKPRIV();
   819     CHECKWALIGN32( sh4r.r[Rn] );
   820     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.vbr );
   821     sh4r.r[Rn] -= 4;
   822 :}
   823 LDS.L @Rm+, PR {:
   824     CHECKRALIGN32( sh4r.r[Rm] );
   825     MEM_READ_LONG( sh4r.r[Rm], sh4r.pr );
   826     sh4r.r[Rm] += 4;
   827 :}
   828 LDC.L @Rm+, VBR {:
   829     CHECKPRIV();
   830     CHECKRALIGN32( sh4r.r[Rm] );
   831     MEM_READ_LONG(sh4r.r[Rm], sh4r.vbr);
   832     sh4r.r[Rm] +=4;
   833 :}
   834 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
   835 LDC Rm, VBR {:
   836     CHECKPRIV();
   837     sh4r.vbr = sh4r.r[Rm];
   838 :}
   839 STC SGR, Rn {:
   840     CHECKPRIV();
   841     sh4r.r[Rn] = sh4r.sgr;
   842 :}
   843 STC.L SGR, @-Rn {:
   844     CHECKPRIV();
   845     CHECKWALIGN32( sh4r.r[Rn] );
   846     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.sgr );
   847     sh4r.r[Rn] -= 4;
   848 :}
   849 STC.L SSR, @-Rn {:
   850     CHECKPRIV();
   851     CHECKWALIGN32( sh4r.r[Rn] );
   852     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.ssr );
   853     sh4r.r[Rn] -= 4;
   854 :}
   855 LDC.L @Rm+, SSR {:
   856     CHECKPRIV();
   857     CHECKRALIGN32( sh4r.r[Rm] );
   858     MEM_READ_LONG(sh4r.r[Rm], sh4r.ssr);
   859     sh4r.r[Rm] +=4;
   860 :}
   861 LDC Rm, SSR {:
   862     CHECKPRIV();
   863     sh4r.ssr = sh4r.r[Rm];
   864 :}
   865 STC.L SPC, @-Rn {:
   866     CHECKPRIV();
   867     CHECKWALIGN32( sh4r.r[Rn] );
   868     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.spc );
   869     sh4r.r[Rn] -= 4;
   870 :}
   871 LDC.L @Rm+, SPC {:
   872     CHECKPRIV();
   873     CHECKRALIGN32( sh4r.r[Rm] );
   874     MEM_READ_LONG(sh4r.r[Rm], sh4r.spc);
   875     sh4r.r[Rm] +=4;
   876 :}
   877 LDC Rm, SPC {:
   878     CHECKPRIV();
   879     sh4r.spc = sh4r.r[Rm];
   880 :}
   881 STS FPUL, Rn {: 
   882     CHECKFPUEN();
   883     sh4r.r[Rn] = FPULi; 
   884 :}
   885 STS.L FPUL, @-Rn {:
   886     CHECKFPUEN();
   887     CHECKWALIGN32( sh4r.r[Rn] );
   888     MEM_WRITE_LONG( sh4r.r[Rn]-4, FPULi );
   889     sh4r.r[Rn] -= 4;
   890 :}
   891 LDS.L @Rm+, FPUL {:
   892     CHECKFPUEN();
   893     CHECKRALIGN32( sh4r.r[Rm] );
   894     MEM_READ_LONG(sh4r.r[Rm], FPULi);
   895     sh4r.r[Rm] +=4;
   896 :}
   897 LDS Rm, FPUL {:
   898     CHECKFPUEN();
   899     FPULi = sh4r.r[Rm]; 
   900 :}
   901 STS FPSCR, Rn {: 
   902     CHECKFPUEN();
   903     sh4r.r[Rn] = sh4r.fpscr; 
   904 :}
   905 STS.L FPSCR, @-Rn {:
   906     CHECKFPUEN();
   907     CHECKWALIGN32( sh4r.r[Rn] );
   908     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.fpscr );
   909     sh4r.r[Rn] -= 4;
   910 :}
   911 LDS.L @Rm+, FPSCR {:
   912     CHECKFPUEN();
   913     CHECKRALIGN32( sh4r.r[Rm] );
   914     MEM_READ_LONG(sh4r.r[Rm], tmp);
   915     sh4r.r[Rm] +=4;
   916     sh4_write_fpscr( tmp );
   917 :}
   918 LDS Rm, FPSCR {: 
   919     CHECKFPUEN();
   920     sh4_write_fpscr( sh4r.r[Rm] );
   921 :}
   922 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
   923 STC.L DBR, @-Rn {:
   924     CHECKPRIV();
   925     CHECKWALIGN32( sh4r.r[Rn] );
   926     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.dbr );
   927     sh4r.r[Rn] -= 4;
   928 :}
   929 LDC.L @Rm+, DBR {:
   930     CHECKPRIV();
   931     CHECKRALIGN32( sh4r.r[Rm] );
   932     MEM_READ_LONG(sh4r.r[Rm], sh4r.dbr);
   933     sh4r.r[Rm] +=4;
   934 :}
   935 LDC Rm, DBR {:
   936     CHECKPRIV();
   937     sh4r.dbr = sh4r.r[Rm];
   938 :}
   939 STC.L Rm_BANK, @-Rn {:
   940     CHECKPRIV();
   941     CHECKWALIGN32( sh4r.r[Rn] );
   942     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r_bank[Rm_BANK] );
   943     sh4r.r[Rn] -= 4;
   944 :}
   945 LDC.L @Rm+, Rn_BANK {:
   946     CHECKPRIV();
   947     CHECKRALIGN32( sh4r.r[Rm] );
   948     MEM_READ_LONG( sh4r.r[Rm], sh4r.r_bank[Rn_BANK] );
   949     sh4r.r[Rm] += 4;
   950 :}
   951 LDC Rm, Rn_BANK {:
   952     CHECKPRIV();
   953     sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
   954 :}
   955 STC SR, Rn {: 
   956     CHECKPRIV();
   957     sh4r.r[Rn] = sh4_read_sr();
   958 :}
   959 STC GBR, Rn {:
   960     sh4r.r[Rn] = sh4r.gbr;
   961 :}
   962 STC VBR, Rn {:
   963     CHECKPRIV();
   964     sh4r.r[Rn] = sh4r.vbr;
   965 :}
   966 STC SSR, Rn {:
   967     CHECKPRIV();
   968     sh4r.r[Rn] = sh4r.ssr;
   969 :}
   970 STC SPC, Rn {:
   971     CHECKPRIV();
   972     sh4r.r[Rn] = sh4r.spc;
   973 :}
   974 STC Rm_BANK, Rn {:
   975     CHECKPRIV();
   976     sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
   977 :}
   979 FADD FRm, FRn {:
   980     CHECKFPUEN();
   981     if( IS_FPU_DOUBLEPREC() ) {
   982 	DR(FRn) += DR(FRm);
   983     } else {
   984 	FR(FRn) += FR(FRm);
   985     }
   986 :}
   987 FSUB FRm, FRn {:
   988     CHECKFPUEN();
   989     if( IS_FPU_DOUBLEPREC() ) {
   990 	DR(FRn) -= DR(FRm);
   991     } else {
   992 	FR(FRn) -= FR(FRm);
   993     }
   994 :}
   996 FMUL FRm, FRn {:
   997     CHECKFPUEN();
   998     if( IS_FPU_DOUBLEPREC() ) {
   999 	DR(FRn) *= DR(FRm);
  1000     } else {
  1001 	FR(FRn) *= FR(FRm);
  1003 :}
  1005 FDIV FRm, FRn {:
  1006     CHECKFPUEN();
  1007     if( IS_FPU_DOUBLEPREC() ) {
  1008 	DR(FRn) /= DR(FRm);
  1009     } else {
  1010 	FR(FRn) /= FR(FRm);
  1012 :}
  1014 FCMP/EQ FRm, FRn {:
  1015     CHECKFPUEN();
  1016     if( IS_FPU_DOUBLEPREC() ) {
  1017 	sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
  1018     } else {
  1019 	sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
  1021 :}
  1023 FCMP/GT FRm, FRn {:
  1024     CHECKFPUEN();
  1025     if( IS_FPU_DOUBLEPREC() ) {
  1026 	sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
  1027     } else {
  1028 	sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
  1030 :}
  1032 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
  1033 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
  1034 FLOAT FPUL, FRn {: 
  1035     CHECKFPUEN();
  1036     if( IS_FPU_DOUBLEPREC() ) {
  1037 	if( FRn&1 ) { // No, really...
  1038 	    dtmp = (double)FPULi;
  1039 	    FR(FRn) = *(((float *)&dtmp)+1);
  1040 	} else {
  1041 	    DRF(FRn>>1) = (double)FPULi;
  1043     } else {
  1044 	FR(FRn) = (float)FPULi;
  1046 :}
  1047 FTRC FRm, FPUL {:
  1048     CHECKFPUEN();
  1049     if( IS_FPU_DOUBLEPREC() ) {
  1050 	if( FRm&1 ) {
  1051 	    dtmp = 0;
  1052 	    *(((float *)&dtmp)+1) = FR(FRm);
  1053 	} else {
  1054 	    dtmp = DRF(FRm>>1);
  1056         if( dtmp >= MAX_INTF )
  1057             FPULi = MAX_INT;
  1058         else if( dtmp <= MIN_INTF )
  1059             FPULi = MIN_INT;
  1060         else 
  1061             FPULi = (int32_t)dtmp;
  1062     } else {
  1063 	ftmp = FR(FRm);
  1064 	if( ftmp >= MAX_INTF )
  1065 	    FPULi = MAX_INT;
  1066 	else if( ftmp <= MIN_INTF )
  1067 	    FPULi = MIN_INT;
  1068 	else
  1069 	    FPULi = (int32_t)ftmp;
  1071 :}
  1072 FNEG FRn {:
  1073     CHECKFPUEN();
  1074     if( IS_FPU_DOUBLEPREC() ) {
  1075 	DR(FRn) = -DR(FRn);
  1076     } else {
  1077         FR(FRn) = -FR(FRn);
  1079 :}
  1080 FABS FRn {:
  1081     CHECKFPUEN();
  1082     if( IS_FPU_DOUBLEPREC() ) {
  1083 	DR(FRn) = fabs(DR(FRn));
  1084     } else {
  1085         FR(FRn) = fabsf(FR(FRn));
  1087 :}
  1088 FSQRT FRn {:
  1089     CHECKFPUEN();
  1090     if( IS_FPU_DOUBLEPREC() ) {
  1091 	DR(FRn) = sqrt(DR(FRn));
  1092     } else {
  1093         FR(FRn) = sqrtf(FR(FRn));
  1095 :}
  1096 FLDI0 FRn {:
  1097     CHECKFPUEN();
  1098     if( IS_FPU_DOUBLEPREC() ) {
  1099 	DR(FRn) = 0.0;
  1100     } else {
  1101         FR(FRn) = 0.0;
  1103 :}
  1104 FLDI1 FRn {:
  1105     CHECKFPUEN();
  1106     if( IS_FPU_DOUBLEPREC() ) {
  1107 	DR(FRn) = 1.0;
  1108     } else {
  1109         FR(FRn) = 1.0;
  1111 :}
  1112 FMAC FR0, FRm, FRn {:
  1113     CHECKFPUEN();
  1114     if( IS_FPU_DOUBLEPREC() ) {
  1115         DR(FRn) += DR(FRm)*DR(0);
  1116     } else {
  1117 	FR(FRn) += FR(FRm)*FR(0);
  1119 :}
  1120 FRCHG {: 
  1121     CHECKFPUEN(); 
  1122     sh4r.fpscr ^= FPSCR_FR; 
  1123     sh4_switch_fr_banks();
  1124 :}
  1125 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
  1126 FCNVSD FPUL, FRn {:
  1127     CHECKFPUEN();
  1128     if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
  1129 	DR(FRn) = (double)FPULf;
  1131 :}
  1132 FCNVDS FRm, FPUL {:
  1133     CHECKFPUEN();
  1134     if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
  1135 	FPULf = (float)DR(FRm);
  1137 :}
  1139 FSRRA FRn {:
  1140     CHECKFPUEN();
  1141     if( !IS_FPU_DOUBLEPREC() ) {
  1142 	FR(FRn) = 1.0/sqrtf(FR(FRn));
  1144 :}
  1145 FIPR FVm, FVn {:
  1146     CHECKFPUEN();
  1147     if( !IS_FPU_DOUBLEPREC() ) {
  1148         int tmp2 = FVn<<2;
  1149         tmp = FVm<<2;
  1150         FR(tmp2+3) = FR(tmp)*FR(tmp2) +
  1151             FR(tmp+1)*FR(tmp2+1) +
  1152             FR(tmp+2)*FR(tmp2+2) +
  1153             FR(tmp+3)*FR(tmp2+3);
  1155 :}
  1156 FSCA FPUL, FRn {:
  1157     CHECKFPUEN();
  1158     if( !IS_FPU_DOUBLEPREC() ) {
  1159 	sh4_fsca( FPULi, (float *)&(DRF(FRn>>1)) );
  1160 	/*
  1161         float angle = (((float)(FPULi&0xFFFF))/65536.0) * 2 * M_PI;
  1162         FR(FRn) = sinf(angle);
  1163         FR((FRn)+1) = cosf(angle);
  1164 	*/
  1166 :}
  1167 FTRV XMTRX, FVn {:
  1168     CHECKFPUEN();
  1169     if( !IS_FPU_DOUBLEPREC() ) {
  1170 	sh4_ftrv((float *)&(DRF(FVn<<1)) );
  1172 :}
  1173 UNDEF {:
  1174     UNDEF(ir);
  1175 :}
  1176 %%
  1177     sh4r.pc = sh4r.new_pc;
  1178     sh4r.new_pc += 2;
  1180 except:
  1181     sh4r.in_delay_slot = 0;
  1182     return TRUE;
.