Search
lxdream.org :: lxdream/src/sh4/sh4core.in
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4core.in
changeset 758:99ae000d4e09
prev740:dd11269ee48b
next927:17b6b9e245d8
author nkeynes
date Thu Dec 11 23:26:03 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Disable the generational translation cache - I've got no evidence that it
actually helps performance, and it simplifies things to get rid of it (in
particular, translated code doesn't have to worry about being moved now).
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 #define MEM_READ_BYTE( addr, val ) memtmp = mmu_vma_to_phys_read(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { val = sh4_read_byte(memtmp); }
   168 #define MEM_READ_WORD( addr, val ) memtmp = mmu_vma_to_phys_read(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { val = sh4_read_word(memtmp); }
   169 #define MEM_READ_LONG( addr, val ) memtmp = mmu_vma_to_phys_read(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { val = sh4_read_long(memtmp); }
   170 #define MEM_WRITE_BYTE( addr, val ) memtmp = mmu_vma_to_phys_write(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { sh4_write_byte(memtmp, val); }
   171 #define MEM_WRITE_WORD( addr, val ) memtmp = mmu_vma_to_phys_write(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { sh4_write_word(memtmp, val); }
   172 #define MEM_WRITE_LONG( addr, val ) memtmp = mmu_vma_to_phys_write(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { sh4_write_long(memtmp, val); }
   174 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
   176 #define MEM_FP_READ( addr, reg ) \
   177     if( IS_FPU_DOUBLESIZE() ) { \
   178 	CHECKRALIGN64(addr); \
   179 	memtmp = mmu_vma_to_phys_read(addr); \
   180 	if( memtmp == MMU_VMA_ERROR ) { \
   181 	    return TRUE; \
   182 	} else { \
   183 	    if( reg & 1 ) { \
   184                 *((uint32_t *)&XF((reg) & 0x0E)) = sh4_read_long(memtmp); \
   185 	        *((uint32_t *)&XF(reg)) = sh4_read_long(memtmp+4); \
   186 	    } else { \
   187 	        *((uint32_t *)&FR(reg)) = sh4_read_long(memtmp); \
   188 	        *((uint32_t *)&FR((reg) | 0x01)) = sh4_read_long(memtmp+4); \
   189 	    } \
   190 	} \
   191     } else { \
   192         CHECKRALIGN32(addr); \
   193         memtmp = mmu_vma_to_phys_read(addr); \
   194         if( memtmp == MMU_VMA_ERROR ) { \
   195             return TRUE; \
   196         } else { \
   197 	    *((uint32_t *)&FR(reg)) = sh4_read_long(memtmp); \
   198 	} \
   199     }
   200 #define MEM_FP_WRITE( addr, reg ) \
   201     if( IS_FPU_DOUBLESIZE() ) { \
   202         CHECKWALIGN64(addr); \
   203 	memtmp = mmu_vma_to_phys_write(addr); \
   204 	if( memtmp == MMU_VMA_ERROR ) { \
   205 	    return TRUE; \
   206 	} else { \
   207             if( reg & 1 ) { \
   208 	        sh4_write_long( memtmp, *((uint32_t *)&XF((reg)&0x0E)) ); \
   209 	        sh4_write_long( memtmp+4, *((uint32_t *)&XF(reg)) ); \
   210 	    } else { \
   211 	        sh4_write_long( memtmp, *((uint32_t *)&FR(reg)) ); \
   212 	        sh4_write_long( memtmp+4, *((uint32_t *)&FR((reg)|0x01)) ); \
   213 	    } \
   214 	} \
   215     } else { \
   216     	CHECKWALIGN32(addr); \
   217 	memtmp = mmu_vma_to_phys_write(addr); \
   218 	if( memtmp == MMU_VMA_ERROR ) { \
   219 	    return TRUE; \
   220 	} else { \
   221 	    sh4_write_long( memtmp, *((uint32_t *)&FR((reg))) ); \
   222 	} \
   223     }
   225 gboolean sh4_execute_instruction( void )
   226 {
   227     uint32_t pc;
   228     unsigned short ir;
   229     uint32_t tmp;
   230     float ftmp;
   231     double dtmp;
   232     int64_t memtmp; // temporary holder for memory reads
   234 #define R0 sh4r.r[0]
   235     pc = sh4r.pc;
   236     if( pc > 0xFFFFFF00 ) {
   237 	/* SYSCALL Magic */
   238 	syscall_invoke( pc );
   239 	sh4r.in_delay_slot = 0;
   240 	pc = sh4r.pc = sh4r.pr;
   241 	sh4r.new_pc = sh4r.pc + 2;
   242         return TRUE;
   243     }
   244     CHECKRALIGN16(pc);
   246 #ifdef ENABLE_SH4STATS
   247     sh4_stats_add_by_pc(sh4r.pc);
   248 #endif
   250     /* Read instruction */
   251     if( !IS_IN_ICACHE(pc) ) {
   252 	if( !mmu_update_icache(pc) ) {
   253 	    // Fault - look for the fault handler
   254 	    if( !mmu_update_icache(sh4r.pc) ) {
   255 		// double fault - halt
   256 		ERROR( "Double fault - halting" );
   257 		sh4_core_exit(CORE_EXIT_HALT);
   258 		return FALSE;
   259 	    }
   260 	}
   261 	pc = sh4r.pc;
   262     }
   263     assert( IS_IN_ICACHE(pc) );
   264     ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
   265 %%
   266 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
   267 AND #imm, R0 {: R0 &= imm; :}
   268  AND.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & tmp ); :}
   269 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
   270 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
   271 OR #imm, R0  {: R0 |= imm; :}
   272  OR.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | tmp ); :}
   273 TAS.B @Rn {:
   274     MEM_READ_BYTE( sh4r.r[Rn], tmp );
   275     sh4r.t = ( tmp == 0 ? 1 : 0 );
   276     MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
   277 :}
   278 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
   279 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
   280  TST.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); sh4r.t = ( tmp & imm ? 0 : 1 ); :}
   281 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
   282 XOR #imm, R0 {: R0 ^= imm; :}
   283  XOR.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ tmp ); :}
   284 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
   286 ROTL Rn {:
   287     sh4r.t = sh4r.r[Rn] >> 31;
   288     sh4r.r[Rn] <<= 1;
   289     sh4r.r[Rn] |= sh4r.t;
   290 :}
   291 ROTR Rn {:
   292     sh4r.t = sh4r.r[Rn] & 0x00000001;
   293     sh4r.r[Rn] >>= 1;
   294     sh4r.r[Rn] |= (sh4r.t << 31);
   295 :}
   296 ROTCL Rn {:
   297     tmp = sh4r.r[Rn] >> 31;
   298     sh4r.r[Rn] <<= 1;
   299     sh4r.r[Rn] |= sh4r.t;
   300     sh4r.t = tmp;
   301 :}
   302 ROTCR Rn {:
   303     tmp = sh4r.r[Rn] & 0x00000001;
   304     sh4r.r[Rn] >>= 1;
   305     sh4r.r[Rn] |= (sh4r.t << 31 );
   306     sh4r.t = tmp;
   307 :}
   308 SHAD Rm, Rn {:
   309     tmp = sh4r.r[Rm];
   310     if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
   311     else if( (tmp & 0x1F) == 0 )  
   312         sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
   313     else 
   314 	sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
   315 :}
   316 SHLD Rm, Rn {:
   317     tmp = sh4r.r[Rm];
   318     if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
   319     else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
   320     else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
   321 :}
   322 SHAL Rn {:
   323     sh4r.t = sh4r.r[Rn] >> 31;
   324     sh4r.r[Rn] <<= 1;
   325 :}
   326 SHAR Rn {:
   327     sh4r.t = sh4r.r[Rn] & 0x00000001;
   328     sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
   329 :}
   330 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
   331 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
   332 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
   333 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
   334 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
   335 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
   336 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
   337 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
   339 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
   340 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
   341 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
   342 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
   343 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
   344 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
   346 CLRT {: sh4r.t = 0; :}
   347 SETT {: sh4r.t = 1; :}
   348 CLRMAC {: sh4r.mac = 0; :}
   349 LDTLB {: MMU_ldtlb(); :}
   350 CLRS {: sh4r.s = 0; :}
   351 SETS {: sh4r.s = 1; :}
   352 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
   353 NOP {: /* NOP */ :}
   355 PREF @Rn {:
   356      tmp = sh4r.r[Rn];
   357      if( (tmp & 0xFC000000) == 0xE0000000 ) {
   358 	 sh4_flush_store_queue(tmp);
   359      }
   360 :}
   361 OCBI @Rn {: :}
   362 OCBP @Rn {: :}
   363 OCBWB @Rn {: :}
   364 MOVCA.L R0, @Rn {:
   365     tmp = sh4r.r[Rn];
   366     CHECKWALIGN32(tmp);
   367     MEM_WRITE_LONG( tmp, R0 );
   368 :}
   369 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
   370 MOV.W Rm, @(R0, Rn) {: 
   371     CHECKWALIGN16( R0 + sh4r.r[Rn] );
   372     MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
   373 :}
   374 MOV.L Rm, @(R0, Rn) {:
   375     CHECKWALIGN32( R0 + sh4r.r[Rn] );
   376     MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
   377 :}
   378 MOV.B @(R0, Rm), Rn {: MEM_READ_BYTE( R0 + sh4r.r[Rm], sh4r.r[Rn] ); :}
   379 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
   380     MEM_READ_WORD( R0 + sh4r.r[Rm], sh4r.r[Rn] );
   381 :}
   382 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
   383     MEM_READ_LONG( R0 + sh4r.r[Rm], sh4r.r[Rn] );
   384 :}
   385 MOV.L Rm, @(disp, Rn) {:
   386     tmp = sh4r.r[Rn] + disp;
   387     CHECKWALIGN32( tmp );
   388     MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
   389 :}
   390 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
   391 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
   392 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
   393  MOV.B Rm, @-Rn {: MEM_WRITE_BYTE( sh4r.r[Rn]-1, sh4r.r[Rm] ); sh4r.r[Rn]--; :}
   394  MOV.W Rm, @-Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn]-2, sh4r.r[Rm] ); sh4r.r[Rn] -= 2; :}
   395  MOV.L Rm, @-Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r[Rm] ); sh4r.r[Rn] -= 4; :}
   396 MOV.L @(disp, Rm), Rn {:
   397     tmp = sh4r.r[Rm] + disp;
   398     CHECKRALIGN32( tmp );
   399     MEM_READ_LONG( tmp, sh4r.r[Rn] );
   400 :}
   401 MOV.B @Rm, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); :}
   402  MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); :}
   403  MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); :}
   404 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
   405  MOV.B @Rm+, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] ++; :}
   406  MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] += 2; :}
   407  MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] += 4; :}
   408 MOV.L @(disp, PC), Rn {:
   409     CHECKSLOTILLEGAL();
   410     tmp = (pc&0xFFFFFFFC) + disp + 4;
   411     MEM_READ_LONG( tmp, sh4r.r[Rn] );
   412 :}
   413 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
   414 MOV.W R0, @(disp, GBR) {:
   415     tmp = sh4r.gbr + disp;
   416     CHECKWALIGN16( tmp );
   417     MEM_WRITE_WORD( tmp, R0 );
   418 :}
   419 MOV.L R0, @(disp, GBR) {:
   420     tmp = sh4r.gbr + disp;
   421     CHECKWALIGN32( tmp );
   422     MEM_WRITE_LONG( tmp, R0 );
   423 :}
   424  MOV.B @(disp, GBR), R0 {: MEM_READ_BYTE( sh4r.gbr + disp, R0 ); :}
   425 MOV.W @(disp, GBR), R0 {: 
   426     tmp = sh4r.gbr + disp;
   427     CHECKRALIGN16( tmp );
   428     MEM_READ_WORD( tmp, R0 );
   429 :}
   430 MOV.L @(disp, GBR), R0 {:
   431     tmp = sh4r.gbr + disp;
   432     CHECKRALIGN32( tmp );
   433     MEM_READ_LONG( tmp, R0 );
   434 :}
   435 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
   436 MOV.W R0, @(disp, Rn) {: 
   437     tmp = sh4r.r[Rn] + disp;
   438     CHECKWALIGN16( tmp );
   439     MEM_WRITE_WORD( tmp, R0 );
   440 :}
   441  MOV.B @(disp, Rm), R0 {: MEM_READ_BYTE( sh4r.r[Rm] + disp, R0 ); :}
   442 MOV.W @(disp, Rm), R0 {: 
   443     tmp = sh4r.r[Rm] + disp;
   444     CHECKRALIGN16( tmp );
   445     MEM_READ_WORD( tmp, R0 );
   446 :}
   447 MOV.W @(disp, PC), Rn {:
   448     CHECKSLOTILLEGAL();
   449     tmp = pc + 4 + disp;
   450     MEM_READ_WORD( tmp, sh4r.r[Rn] );
   451 :}
   452 MOVA @(disp, PC), R0 {:
   453     CHECKSLOTILLEGAL();
   454     R0 = (pc&0xFFFFFFFC) + disp + 4;
   455 :}
   456 MOV #imm, Rn {:  sh4r.r[Rn] = imm; :}
   458 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
   459 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
   460 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
   461 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
   462 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
   463  FMOV FRm, @-Rn {: MEM_FP_WRITE( sh4r.r[Rn] - FP_WIDTH, FRm ); sh4r.r[Rn] -= FP_WIDTH; :}
   464 FMOV FRm, FRn {: 
   465     if( IS_FPU_DOUBLESIZE() )
   466 	DR(FRn) = DR(FRm);
   467     else
   468 	FR(FRn) = FR(FRm);
   469 :}
   471 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
   472 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
   473 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
   474 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
   475 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
   476 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
   477 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
   478 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
   479 CMP/STR Rm, Rn {: 
   480     /* set T = 1 if any byte in RM & RN is the same */
   481     tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
   482     sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
   483              (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
   484 :}
   486 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
   487 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
   488 ADDC Rm, Rn {:
   489     tmp = sh4r.r[Rn];
   490     sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
   491     sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
   492 :}
   493 ADDV Rm, Rn {:
   494     tmp = sh4r.r[Rn] + sh4r.r[Rm];
   495     sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
   496     sh4r.r[Rn] = tmp;
   497 :}
   498 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
   499 DIV0S Rm, Rn {: 
   500     sh4r.q = sh4r.r[Rn]>>31;
   501     sh4r.m = sh4r.r[Rm]>>31;
   502     sh4r.t = sh4r.q ^ sh4r.m;
   503 :}
   504 DIV1 Rm, Rn {:
   505     /* This is derived from the sh4 manual with some simplifications */
   506     uint32_t tmp0, tmp1, tmp2, dir;
   508     dir = sh4r.q ^ sh4r.m;
   509     sh4r.q = (sh4r.r[Rn] >> 31);
   510     tmp2 = sh4r.r[Rm];
   511     sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
   512     tmp0 = sh4r.r[Rn];
   513     if( dir ) {
   514          sh4r.r[Rn] += tmp2;
   515          tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
   516     } else {
   517          sh4r.r[Rn] -= tmp2;
   518          tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
   519     }
   520     sh4r.q ^= sh4r.m ^ tmp1;
   521     sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
   522 :}
   523 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
   524 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
   525 DT Rn {:
   526     sh4r.r[Rn] --;
   527     sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
   528 :}
   529 MAC.W @Rm+, @Rn+ {:
   530     int32_t stmp;
   531     if( Rm == Rn ) {
   532 	CHECKRALIGN16(sh4r.r[Rn]);
   533 	MEM_READ_WORD( sh4r.r[Rn], tmp );
   534 	stmp = SIGNEXT16(tmp);
   535 	MEM_READ_WORD( sh4r.r[Rn]+2, tmp );
   536 	stmp *= SIGNEXT16(tmp);
   537 	sh4r.r[Rn] += 4;
   538     } else {
   539 	CHECKRALIGN16( sh4r.r[Rn] );
   540 	CHECKRALIGN16( sh4r.r[Rm] );
   541 	MEM_READ_WORD(sh4r.r[Rn], tmp);
   542 	stmp = SIGNEXT16(tmp);
   543 	MEM_READ_WORD(sh4r.r[Rm], tmp);
   544 	stmp = stmp * SIGNEXT16(tmp);
   545 	sh4r.r[Rn] += 2;
   546 	sh4r.r[Rm] += 2;
   547     }
   548     if( sh4r.s ) {
   549 	int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
   550 	if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
   551 	    sh4r.mac = 0x000000017FFFFFFFLL;
   552 	} else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
   553 	    sh4r.mac = 0x0000000180000000LL;
   554 	} else {
   555 	    sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
   556 		((uint32_t)(sh4r.mac + stmp));
   557 	}
   558     } else {
   559 	sh4r.mac += SIGNEXT32(stmp);
   560     }
   561 :}
   562 MAC.L @Rm+, @Rn+ {:
   563     int64_t tmpl;
   564     if( Rm == Rn ) {
   565 	CHECKRALIGN32( sh4r.r[Rn] );
   566 	MEM_READ_LONG(sh4r.r[Rn], tmp);
   567 	tmpl = SIGNEXT32(tmp);
   568 	MEM_READ_LONG(sh4r.r[Rn]+4, tmp);
   569 	tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
   570 	sh4r.r[Rn] += 8;
   571     } else {
   572 	CHECKRALIGN32( sh4r.r[Rm] );
   573 	CHECKRALIGN32( sh4r.r[Rn] );
   574 	MEM_READ_LONG(sh4r.r[Rn], tmp);
   575 	tmpl = SIGNEXT32(tmp);
   576 	MEM_READ_LONG(sh4r.r[Rm], tmp);
   577 	tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
   578 	sh4r.r[Rn] += 4;
   579 	sh4r.r[Rm] += 4;
   580     }
   581     if( sh4r.s ) {
   582         /* 48-bit Saturation. Yuch */
   583         if( tmpl < (int64_t)0xFFFF800000000000LL )
   584             tmpl = 0xFFFF800000000000LL;
   585         else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
   586             tmpl = 0x00007FFFFFFFFFFFLL;
   587     }
   588     sh4r.mac = tmpl;
   589 :}
   590 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
   591                         (sh4r.r[Rm] * sh4r.r[Rn]); :}
   592 MULU.W Rm, Rn {:
   593     sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
   594                (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
   595 :}
   596 MULS.W Rm, Rn {:
   597     sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
   598                (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
   599 :}
   600 NEGC Rm, Rn {:
   601     tmp = 0 - sh4r.r[Rm];
   602     sh4r.r[Rn] = tmp - sh4r.t;
   603     sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
   604 :}
   605 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
   606 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
   607 SUBC Rm, Rn {: 
   608     tmp = sh4r.r[Rn];
   609     sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
   610     sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
   611 :}
   613 BRAF Rn {:
   614      CHECKSLOTILLEGAL();
   615      CHECKDEST( pc + 4 + sh4r.r[Rn] );
   616      sh4r.in_delay_slot = 1;
   617      sh4r.pc = sh4r.new_pc;
   618      sh4r.new_pc = pc + 4 + sh4r.r[Rn];
   619      return TRUE;
   620 :}
   621 BSRF Rn {:
   622      CHECKSLOTILLEGAL();
   623      CHECKDEST( pc + 4 + sh4r.r[Rn] );
   624      sh4r.in_delay_slot = 1;
   625      sh4r.pr = sh4r.pc + 4;
   626      sh4r.pc = sh4r.new_pc;
   627      sh4r.new_pc = pc + 4 + sh4r.r[Rn];
   628      TRACE_CALL( pc, sh4r.new_pc );
   629      return TRUE;
   630 :}
   631 BT disp {:
   632     CHECKSLOTILLEGAL();
   633     if( sh4r.t ) {
   634         CHECKDEST( sh4r.pc + disp + 4 )
   635         sh4r.pc += disp + 4;
   636         sh4r.new_pc = sh4r.pc + 2;
   637         return TRUE;
   638     }
   639 :}
   640 BF disp {:
   641     CHECKSLOTILLEGAL();
   642     if( !sh4r.t ) {
   643         CHECKDEST( sh4r.pc + disp + 4 )
   644         sh4r.pc += disp + 4;
   645         sh4r.new_pc = sh4r.pc + 2;
   646         return TRUE;
   647     }
   648 :}
   649 BT/S disp {:
   650     CHECKSLOTILLEGAL();
   651     if( sh4r.t ) {
   652         CHECKDEST( sh4r.pc + disp + 4 )
   653         sh4r.in_delay_slot = 1;
   654         sh4r.pc = sh4r.new_pc;
   655         sh4r.new_pc = pc + disp + 4;
   656         sh4r.in_delay_slot = 1;
   657         return TRUE;
   658     }
   659 :}
   660 BF/S disp {:
   661     CHECKSLOTILLEGAL();
   662     if( !sh4r.t ) {
   663         CHECKDEST( sh4r.pc + disp + 4 )
   664         sh4r.in_delay_slot = 1;
   665         sh4r.pc = sh4r.new_pc;
   666         sh4r.new_pc = pc + disp + 4;
   667         return TRUE;
   668     }
   669 :}
   670 BRA disp {:
   671     CHECKSLOTILLEGAL();
   672     CHECKDEST( sh4r.pc + disp + 4 );
   673     sh4r.in_delay_slot = 1;
   674     sh4r.pc = sh4r.new_pc;
   675     sh4r.new_pc = pc + 4 + disp;
   676     return TRUE;
   677 :}
   678 BSR disp {:
   679     CHECKDEST( sh4r.pc + disp + 4 );
   680     CHECKSLOTILLEGAL();
   681     sh4r.in_delay_slot = 1;
   682     sh4r.pr = pc + 4;
   683     sh4r.pc = sh4r.new_pc;
   684     sh4r.new_pc = pc + 4 + disp;
   685     TRACE_CALL( pc, sh4r.new_pc );
   686     return TRUE;
   687 :}
   688 TRAPA #imm {:
   689     CHECKSLOTILLEGAL();
   690     sh4r.pc += 2;
   691     sh4_raise_trap( imm );
   692     return TRUE;
   693 :}
   694 RTS {: 
   695     CHECKSLOTILLEGAL();
   696     CHECKDEST( sh4r.pr );
   697     sh4r.in_delay_slot = 1;
   698     sh4r.pc = sh4r.new_pc;
   699     sh4r.new_pc = sh4r.pr;
   700     TRACE_RETURN( pc, sh4r.new_pc );
   701     return TRUE;
   702 :}
   703 SLEEP {:
   704     if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
   705 	sh4r.sh4_state = SH4_STATE_STANDBY;
   706     } else {
   707 	sh4r.sh4_state = SH4_STATE_SLEEP;
   708     }
   709     return FALSE; /* Halt CPU */
   710 :}
   711 RTE {:
   712     CHECKPRIV();
   713     CHECKDEST( sh4r.spc );
   714     CHECKSLOTILLEGAL();
   715     sh4r.in_delay_slot = 1;
   716     sh4r.pc = sh4r.new_pc;
   717     sh4r.new_pc = sh4r.spc;
   718     sh4_write_sr( sh4r.ssr );
   719     return TRUE;
   720 :}
   721 JMP @Rn {:
   722     CHECKDEST( sh4r.r[Rn] );
   723     CHECKSLOTILLEGAL();
   724     sh4r.in_delay_slot = 1;
   725     sh4r.pc = sh4r.new_pc;
   726     sh4r.new_pc = sh4r.r[Rn];
   727     return TRUE;
   728 :}
   729 JSR @Rn {:
   730     CHECKDEST( sh4r.r[Rn] );
   731     CHECKSLOTILLEGAL();
   732     sh4r.in_delay_slot = 1;
   733     sh4r.pc = sh4r.new_pc;
   734     sh4r.new_pc = sh4r.r[Rn];
   735     sh4r.pr = pc + 4;
   736     TRACE_CALL( pc, sh4r.new_pc );
   737     return TRUE;
   738 :}
   739 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
   740 STS.L MACH, @-Rn {:
   741     CHECKWALIGN32( sh4r.r[Rn] );
   742     MEM_WRITE_LONG( sh4r.r[Rn]-4, (sh4r.mac>>32) );
   743     sh4r.r[Rn] -= 4;
   744 :}
   745 STC.L SR, @-Rn {:
   746     CHECKPRIV();
   747     CHECKWALIGN32( sh4r.r[Rn] );
   748     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4_read_sr() );
   749     sh4r.r[Rn] -= 4;
   750 :}
   751 LDS.L @Rm+, MACH {:
   752     CHECKRALIGN32( sh4r.r[Rm] );
   753     MEM_READ_LONG(sh4r.r[Rm], tmp);
   754     sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
   755 	(((uint64_t)tmp)<<32);
   756     sh4r.r[Rm] += 4;
   757 :}
   758 LDC.L @Rm+, SR {:
   759     CHECKSLOTILLEGAL();
   760     CHECKPRIV();
   761     CHECKWALIGN32( sh4r.r[Rm] );
   762     MEM_READ_LONG(sh4r.r[Rm], tmp);
   763     sh4_write_sr( tmp );
   764     sh4r.r[Rm] +=4;
   765 :}
   766 LDS Rm, MACH {:
   767     sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
   768                (((uint64_t)sh4r.r[Rm])<<32);
   769 :}
   770 LDC Rm, SR {:
   771     CHECKSLOTILLEGAL();
   772     CHECKPRIV();
   773     sh4_write_sr( sh4r.r[Rm] );
   774 :}
   775 LDC Rm, SGR {:
   776     CHECKPRIV();
   777     sh4r.sgr = sh4r.r[Rm];
   778 :}
   779 LDC.L @Rm+, SGR {:
   780     CHECKPRIV();
   781     CHECKRALIGN32( sh4r.r[Rm] );
   782     MEM_READ_LONG(sh4r.r[Rm], sh4r.sgr);
   783     sh4r.r[Rm] +=4;
   784 :}
   785 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
   786 STS.L MACL, @-Rn {:
   787     CHECKWALIGN32( sh4r.r[Rn] );
   788     MEM_WRITE_LONG( sh4r.r[Rn]-4, (uint32_t)sh4r.mac );
   789     sh4r.r[Rn] -= 4;
   790 :}
   791 STC.L GBR, @-Rn {:
   792     CHECKWALIGN32( sh4r.r[Rn] );
   793     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.gbr );
   794     sh4r.r[Rn] -= 4;
   795 :}
   796 LDS.L @Rm+, MACL {:
   797     CHECKRALIGN32( sh4r.r[Rm] );
   798     MEM_READ_LONG(sh4r.r[Rm], tmp);
   799     sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
   800                (uint64_t)((uint32_t)tmp);
   801     sh4r.r[Rm] += 4;
   802 :}
   803 LDC.L @Rm+, GBR {:
   804     CHECKRALIGN32( sh4r.r[Rm] );
   805     MEM_READ_LONG(sh4r.r[Rm], sh4r.gbr);
   806     sh4r.r[Rm] +=4;
   807 :}
   808 LDS Rm, MACL {:
   809     sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
   810                (uint64_t)((uint32_t)(sh4r.r[Rm]));
   811 :}
   812 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
   813 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
   814 STS.L PR, @-Rn {:
   815     CHECKWALIGN32( sh4r.r[Rn] );
   816     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.pr );
   817     sh4r.r[Rn] -= 4;
   818 :}
   819 STC.L VBR, @-Rn {:
   820     CHECKPRIV();
   821     CHECKWALIGN32( sh4r.r[Rn] );
   822     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.vbr );
   823     sh4r.r[Rn] -= 4;
   824 :}
   825 LDS.L @Rm+, PR {:
   826     CHECKRALIGN32( sh4r.r[Rm] );
   827     MEM_READ_LONG( sh4r.r[Rm], sh4r.pr );
   828     sh4r.r[Rm] += 4;
   829 :}
   830 LDC.L @Rm+, VBR {:
   831     CHECKPRIV();
   832     CHECKRALIGN32( sh4r.r[Rm] );
   833     MEM_READ_LONG(sh4r.r[Rm], sh4r.vbr);
   834     sh4r.r[Rm] +=4;
   835 :}
   836 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
   837 LDC Rm, VBR {:
   838     CHECKPRIV();
   839     sh4r.vbr = sh4r.r[Rm];
   840 :}
   841 STC SGR, Rn {:
   842     CHECKPRIV();
   843     sh4r.r[Rn] = sh4r.sgr;
   844 :}
   845 STC.L SGR, @-Rn {:
   846     CHECKPRIV();
   847     CHECKWALIGN32( sh4r.r[Rn] );
   848     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.sgr );
   849     sh4r.r[Rn] -= 4;
   850 :}
   851 STC.L SSR, @-Rn {:
   852     CHECKPRIV();
   853     CHECKWALIGN32( sh4r.r[Rn] );
   854     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.ssr );
   855     sh4r.r[Rn] -= 4;
   856 :}
   857 LDC.L @Rm+, SSR {:
   858     CHECKPRIV();
   859     CHECKRALIGN32( sh4r.r[Rm] );
   860     MEM_READ_LONG(sh4r.r[Rm], sh4r.ssr);
   861     sh4r.r[Rm] +=4;
   862 :}
   863 LDC Rm, SSR {:
   864     CHECKPRIV();
   865     sh4r.ssr = sh4r.r[Rm];
   866 :}
   867 STC.L SPC, @-Rn {:
   868     CHECKPRIV();
   869     CHECKWALIGN32( sh4r.r[Rn] );
   870     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.spc );
   871     sh4r.r[Rn] -= 4;
   872 :}
   873 LDC.L @Rm+, SPC {:
   874     CHECKPRIV();
   875     CHECKRALIGN32( sh4r.r[Rm] );
   876     MEM_READ_LONG(sh4r.r[Rm], sh4r.spc);
   877     sh4r.r[Rm] +=4;
   878 :}
   879 LDC Rm, SPC {:
   880     CHECKPRIV();
   881     sh4r.spc = sh4r.r[Rm];
   882 :}
   883 STS FPUL, Rn {: 
   884     CHECKFPUEN();
   885     sh4r.r[Rn] = FPULi; 
   886 :}
   887 STS.L FPUL, @-Rn {:
   888     CHECKFPUEN();
   889     CHECKWALIGN32( sh4r.r[Rn] );
   890     MEM_WRITE_LONG( sh4r.r[Rn]-4, FPULi );
   891     sh4r.r[Rn] -= 4;
   892 :}
   893 LDS.L @Rm+, FPUL {:
   894     CHECKFPUEN();
   895     CHECKRALIGN32( sh4r.r[Rm] );
   896     MEM_READ_LONG(sh4r.r[Rm], FPULi);
   897     sh4r.r[Rm] +=4;
   898 :}
   899 LDS Rm, FPUL {:
   900     CHECKFPUEN();
   901     FPULi = sh4r.r[Rm]; 
   902 :}
   903 STS FPSCR, Rn {: 
   904     CHECKFPUEN();
   905     sh4r.r[Rn] = sh4r.fpscr; 
   906 :}
   907 STS.L FPSCR, @-Rn {:
   908     CHECKFPUEN();
   909     CHECKWALIGN32( sh4r.r[Rn] );
   910     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.fpscr );
   911     sh4r.r[Rn] -= 4;
   912 :}
   913 LDS.L @Rm+, FPSCR {:
   914     CHECKFPUEN();
   915     CHECKRALIGN32( sh4r.r[Rm] );
   916     MEM_READ_LONG(sh4r.r[Rm], tmp);
   917     sh4r.r[Rm] +=4;
   918     sh4_write_fpscr( tmp );
   919 :}
   920 LDS Rm, FPSCR {: 
   921     CHECKFPUEN();
   922     sh4_write_fpscr( sh4r.r[Rm] );
   923 :}
   924 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
   925 STC.L DBR, @-Rn {:
   926     CHECKPRIV();
   927     CHECKWALIGN32( sh4r.r[Rn] );
   928     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.dbr );
   929     sh4r.r[Rn] -= 4;
   930 :}
   931 LDC.L @Rm+, DBR {:
   932     CHECKPRIV();
   933     CHECKRALIGN32( sh4r.r[Rm] );
   934     MEM_READ_LONG(sh4r.r[Rm], sh4r.dbr);
   935     sh4r.r[Rm] +=4;
   936 :}
   937 LDC Rm, DBR {:
   938     CHECKPRIV();
   939     sh4r.dbr = sh4r.r[Rm];
   940 :}
   941 STC.L Rm_BANK, @-Rn {:
   942     CHECKPRIV();
   943     CHECKWALIGN32( sh4r.r[Rn] );
   944     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r_bank[Rm_BANK] );
   945     sh4r.r[Rn] -= 4;
   946 :}
   947 LDC.L @Rm+, Rn_BANK {:
   948     CHECKPRIV();
   949     CHECKRALIGN32( sh4r.r[Rm] );
   950     MEM_READ_LONG( sh4r.r[Rm], sh4r.r_bank[Rn_BANK] );
   951     sh4r.r[Rm] += 4;
   952 :}
   953 LDC Rm, Rn_BANK {:
   954     CHECKPRIV();
   955     sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
   956 :}
   957 STC SR, Rn {: 
   958     CHECKPRIV();
   959     sh4r.r[Rn] = sh4_read_sr();
   960 :}
   961 STC GBR, Rn {:
   962     sh4r.r[Rn] = sh4r.gbr;
   963 :}
   964 STC VBR, Rn {:
   965     CHECKPRIV();
   966     sh4r.r[Rn] = sh4r.vbr;
   967 :}
   968 STC SSR, Rn {:
   969     CHECKPRIV();
   970     sh4r.r[Rn] = sh4r.ssr;
   971 :}
   972 STC SPC, Rn {:
   973     CHECKPRIV();
   974     sh4r.r[Rn] = sh4r.spc;
   975 :}
   976 STC Rm_BANK, Rn {:
   977     CHECKPRIV();
   978     sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
   979 :}
   981 FADD FRm, FRn {:
   982     CHECKFPUEN();
   983     if( IS_FPU_DOUBLEPREC() ) {
   984 	DR(FRn) += DR(FRm);
   985     } else {
   986 	FR(FRn) += FR(FRm);
   987     }
   988 :}
   989 FSUB FRm, FRn {:
   990     CHECKFPUEN();
   991     if( IS_FPU_DOUBLEPREC() ) {
   992 	DR(FRn) -= DR(FRm);
   993     } else {
   994 	FR(FRn) -= FR(FRm);
   995     }
   996 :}
   998 FMUL FRm, FRn {:
   999     CHECKFPUEN();
  1000     if( IS_FPU_DOUBLEPREC() ) {
  1001 	DR(FRn) *= DR(FRm);
  1002     } else {
  1003 	FR(FRn) *= FR(FRm);
  1005 :}
  1007 FDIV FRm, FRn {:
  1008     CHECKFPUEN();
  1009     if( IS_FPU_DOUBLEPREC() ) {
  1010 	DR(FRn) /= DR(FRm);
  1011     } else {
  1012 	FR(FRn) /= FR(FRm);
  1014 :}
  1016 FCMP/EQ FRm, FRn {:
  1017     CHECKFPUEN();
  1018     if( IS_FPU_DOUBLEPREC() ) {
  1019 	sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
  1020     } else {
  1021 	sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
  1023 :}
  1025 FCMP/GT FRm, FRn {:
  1026     CHECKFPUEN();
  1027     if( IS_FPU_DOUBLEPREC() ) {
  1028 	sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
  1029     } else {
  1030 	sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
  1032 :}
  1034 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
  1035 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
  1036 FLOAT FPUL, FRn {: 
  1037     CHECKFPUEN();
  1038     if( IS_FPU_DOUBLEPREC() ) {
  1039 	if( FRn&1 ) { // No, really...
  1040 	    dtmp = (double)FPULi;
  1041 	    FR(FRn) = *(((float *)&dtmp)+1);
  1042 	} else {
  1043 	    DRF(FRn>>1) = (double)FPULi;
  1045     } else {
  1046 	FR(FRn) = (float)FPULi;
  1048 :}
  1049 FTRC FRm, FPUL {:
  1050     CHECKFPUEN();
  1051     if( IS_FPU_DOUBLEPREC() ) {
  1052 	if( FRm&1 ) {
  1053 	    dtmp = 0;
  1054 	    *(((float *)&dtmp)+1) = FR(FRm);
  1055 	} else {
  1056 	    dtmp = DRF(FRm>>1);
  1058         if( dtmp >= MAX_INTF )
  1059             FPULi = MAX_INT;
  1060         else if( dtmp <= MIN_INTF )
  1061             FPULi = MIN_INT;
  1062         else 
  1063             FPULi = (int32_t)dtmp;
  1064     } else {
  1065 	ftmp = FR(FRm);
  1066 	if( ftmp >= MAX_INTF )
  1067 	    FPULi = MAX_INT;
  1068 	else if( ftmp <= MIN_INTF )
  1069 	    FPULi = MIN_INT;
  1070 	else
  1071 	    FPULi = (int32_t)ftmp;
  1073 :}
  1074 FNEG FRn {:
  1075     CHECKFPUEN();
  1076     if( IS_FPU_DOUBLEPREC() ) {
  1077 	DR(FRn) = -DR(FRn);
  1078     } else {
  1079         FR(FRn) = -FR(FRn);
  1081 :}
  1082 FABS FRn {:
  1083     CHECKFPUEN();
  1084     if( IS_FPU_DOUBLEPREC() ) {
  1085 	DR(FRn) = fabs(DR(FRn));
  1086     } else {
  1087         FR(FRn) = fabsf(FR(FRn));
  1089 :}
  1090 FSQRT FRn {:
  1091     CHECKFPUEN();
  1092     if( IS_FPU_DOUBLEPREC() ) {
  1093 	DR(FRn) = sqrt(DR(FRn));
  1094     } else {
  1095         FR(FRn) = sqrtf(FR(FRn));
  1097 :}
  1098 FLDI0 FRn {:
  1099     CHECKFPUEN();
  1100     if( IS_FPU_DOUBLEPREC() ) {
  1101 	DR(FRn) = 0.0;
  1102     } else {
  1103         FR(FRn) = 0.0;
  1105 :}
  1106 FLDI1 FRn {:
  1107     CHECKFPUEN();
  1108     if( IS_FPU_DOUBLEPREC() ) {
  1109 	DR(FRn) = 1.0;
  1110     } else {
  1111         FR(FRn) = 1.0;
  1113 :}
  1114 FMAC FR0, FRm, FRn {:
  1115     CHECKFPUEN();
  1116     if( IS_FPU_DOUBLEPREC() ) {
  1117         DR(FRn) += DR(FRm)*DR(0);
  1118     } else {
  1119 	FR(FRn) += FR(FRm)*FR(0);
  1121 :}
  1122 FRCHG {: 
  1123     CHECKFPUEN(); 
  1124     sh4r.fpscr ^= FPSCR_FR; 
  1125     sh4_switch_fr_banks();
  1126 :}
  1127 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
  1128 FCNVSD FPUL, FRn {:
  1129     CHECKFPUEN();
  1130     if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
  1131 	DR(FRn) = (double)FPULf;
  1133 :}
  1134 FCNVDS FRm, FPUL {:
  1135     CHECKFPUEN();
  1136     if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
  1137 	FPULf = (float)DR(FRm);
  1139 :}
  1141 FSRRA FRn {:
  1142     CHECKFPUEN();
  1143     if( !IS_FPU_DOUBLEPREC() ) {
  1144 	FR(FRn) = 1.0/sqrtf(FR(FRn));
  1146 :}
  1147 FIPR FVm, FVn {:
  1148     CHECKFPUEN();
  1149     if( !IS_FPU_DOUBLEPREC() ) {
  1150         int tmp2 = FVn<<2;
  1151         tmp = FVm<<2;
  1152         FR(tmp2+3) = FR(tmp)*FR(tmp2) +
  1153             FR(tmp+1)*FR(tmp2+1) +
  1154             FR(tmp+2)*FR(tmp2+2) +
  1155             FR(tmp+3)*FR(tmp2+3);
  1157 :}
  1158 FSCA FPUL, FRn {:
  1159     CHECKFPUEN();
  1160     if( !IS_FPU_DOUBLEPREC() ) {
  1161 	sh4_fsca( FPULi, (float *)&(DRF(FRn>>1)) );
  1162 	/*
  1163         float angle = (((float)(FPULi&0xFFFF))/65536.0) * 2 * M_PI;
  1164         FR(FRn) = sinf(angle);
  1165         FR((FRn)+1) = cosf(angle);
  1166 	*/
  1168 :}
  1169 FTRV XMTRX, FVn {:
  1170     CHECKFPUEN();
  1171     if( !IS_FPU_DOUBLEPREC() ) {
  1172 	sh4_ftrv((float *)&(DRF(FVn<<1)) );
  1174 :}
  1175 UNDEF {:
  1176     UNDEF(ir);
  1177 :}
  1178 %%
  1179     sh4r.pc = sh4r.new_pc;
  1180     sh4r.new_pc += 2;
  1181     sh4r.in_delay_slot = 0;
  1182     return TRUE;
.