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