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 Mon Dec 15 10:44:56 2008 +0000 (11 years ago)
permissions -rw-r--r--
last change Add return-address-modifying exception return code to mmu TLB lookups (a little bit faster)
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;
.