Search
lxdream.org :: lxdream/src/sh4/sh4core.in
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4core.in
changeset 1125:9dd5dee45db9
prev1103:de9ad2c0cf56
next1187:266e7a1bae90
author nkeynes
date Mon Sep 13 10:13:42 2010 +1000 (10 years ago)
permissions -rw-r--r--
last change Implement shadow-execution 'core' to run translator + interpreter side by
side (for testing)
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/mmu.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 #if(SH4_CALLTRACE == 1)
   106 #define MAX_CALLSTACK 32
   107 static struct call_stack {
   108     sh4addr_t call_addr;
   109     sh4addr_t target_addr;
   110     sh4addr_t stack_pointer;
   111 } call_stack[MAX_CALLSTACK];
   113 static int call_stack_depth = 0;
   114 int sh4_call_trace_on = 0;
   116 static inline void trace_call( sh4addr_t source, sh4addr_t dest ) 
   117 {
   118     if( call_stack_depth < MAX_CALLSTACK ) {
   119 	call_stack[call_stack_depth].call_addr = source;
   120 	call_stack[call_stack_depth].target_addr = dest;
   121 	call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
   122     }
   123     call_stack_depth++;
   124 }
   126 static inline void trace_return( sh4addr_t source, sh4addr_t dest )
   127 {
   128     if( call_stack_depth > 0 ) {
   129 	call_stack_depth--;
   130     }
   131 }
   133 void fprint_stack_trace( FILE *f )
   134 {
   135     int i = call_stack_depth -1;
   136     if( i >= MAX_CALLSTACK )
   137 	i = MAX_CALLSTACK - 1;
   138     for( ; i >= 0; i-- ) {
   139 	fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n", 
   140 		 (call_stack_depth - i), call_stack[i].call_addr,
   141 		 call_stack[i].target_addr, call_stack[i].stack_pointer );
   142     }
   143 }
   145 #define TRACE_CALL( source, dest ) trace_call(source, dest)
   146 #define TRACE_RETURN( source, dest ) trace_return(source, dest)
   147 #else
   148 #define TRACE_CALL( dest, rts ) 
   149 #define TRACE_RETURN( source, dest )
   150 #endif
   152 static gboolean FASTCALL sh4_raise_slot_exception( int normal_code, int slot_code ) {
   153     if( sh4r.in_delay_slot ) {
   154         sh4_raise_exception(slot_code);
   155     } else {
   156         sh4_raise_exception(normal_code);
   157     }
   158     return TRUE;
   159 }
   162 #define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) { return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL ); }
   163 #define CHECKRALIGN16(addr) if( (addr)&0x01 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
   164 #define CHECKRALIGN32(addr) if( (addr)&0x03 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
   165 #define CHECKRALIGN64(addr) if( (addr)&0x07 ) { sh4_raise_exception( EXC_DATA_ADDR_READ ); return TRUE; }
   166 #define CHECKWALIGN16(addr) if( (addr)&0x01 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
   167 #define CHECKWALIGN32(addr) if( (addr)&0x03 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
   168 #define CHECKWALIGN64(addr) if( (addr)&0x07 ) { sh4_raise_exception( EXC_DATA_ADDR_WRITE ); return TRUE; }
   170 #define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
   171 #define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }
   172 #define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) { sh4_raise_exception(EXC_SLOT_ILLEGAL); return TRUE; }
   174 #define ADDRSPACE (IS_SH4_PRIVMODE() ? sh4_address_space : sh4_user_address_space)
   175 #define SQADDRSPACE (IS_SH4_PRIVMODE() ? storequeue_address_space : storequeue_user_address_space)
   177 #ifdef HAVE_FRAME_ADDRESS
   178 static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }
   179 #define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:
   180 #define MEM_READ_BYTE( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_byte)((addr), &&except)
   181 #define MEM_READ_BYTE_FOR_WRITE( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_byte_for_write)((addr), &&except)
   182 #define MEM_READ_WORD( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_word)((addr), &&except)
   183 #define MEM_READ_LONG( addr, val ) val = ((mem_read_exc_fn_t)ADDRSPACE[(addr)>>12]->read_long)((addr), &&except)
   184 #define MEM_WRITE_BYTE( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_byte)((addr), (val), &&except)
   185 #define MEM_WRITE_WORD( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_word)((addr), (val), &&except)
   186 #define MEM_WRITE_LONG( addr, val ) ((mem_write_exc_fn_t)ADDRSPACE[(addr)>>12]->write_long)((addr), (val), &&except)
   187 #define MEM_PREFETCH( addr ) ((mem_prefetch_exc_fn_t)ADDRSPACE[(addr)>>12]->prefetch)((addr), &&except)
   188 #else
   189 #define INIT_EXCEPTIONS(label)
   190 #define MEM_READ_BYTE( addr, val ) val = ADDRSPACE[(addr)>>12]->read_byte(addr)
   191 #define MEM_READ_BYTE_FOR_WRITE( addr, val ) val = ADDRSPACE[(addr)>>12]->read_byte_for_write(addr)
   192 #define MEM_READ_WORD( addr, val ) val = ADDRSPACE[(addr)>>12]->read_word(addr)
   193 #define MEM_READ_LONG( addr, val ) val = ADDRSPACE[(addr)>>12]->read_long(addr)
   194 #define MEM_WRITE_BYTE( addr, val ) ADDRSPACE[(addr)>>12]->write_byte(addr, val)
   195 #define MEM_WRITE_WORD( addr, val ) ADDRSPACE[(addr)>>12]->write_word(addr, val)
   196 #define MEM_WRITE_LONG( addr, val ) ADDRSPACE[(addr)>>12]->write_long(addr, val)
   197 #define MEM_PREFETCH( addr ) ADDRSPACE[(addr)>>12]->prefetch(addr)
   198 #endif
   200 #define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
   202 #define MEM_FP_READ( addr, reg ) \
   203     if( IS_FPU_DOUBLESIZE() ) { \
   204 	CHECKRALIGN64(addr); \
   205         if( reg & 1 ) { \
   206             MEM_READ_LONG( addr, *((uint32_t *)&XF((reg) & 0x0E)) ); \
   207             MEM_READ_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
   208         } else { \
   209             MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
   210             MEM_READ_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
   211 	} \
   212     } else { \
   213         CHECKRALIGN32(addr); \
   214         MEM_READ_LONG( addr, *((uint32_t *)&FR(reg)) ); \
   215     }
   216 #define MEM_FP_WRITE( addr, reg ) \
   217     if( IS_FPU_DOUBLESIZE() ) { \
   218         CHECKWALIGN64(addr); \
   219         if( reg & 1 ) { \
   220 	    MEM_WRITE_LONG( addr, *((uint32_t *)&XF((reg)&0x0E)) ); \
   221 	    MEM_WRITE_LONG( addr+4, *((uint32_t *)&XF(reg)) ); \
   222         } else { \
   223 	    MEM_WRITE_LONG( addr, *((uint32_t *)&FR(reg)) ); \
   224 	    MEM_WRITE_LONG( addr+4, *((uint32_t *)&FR((reg)|0x01)) ); \
   225 	} \
   226     } else { \
   227     	CHECKWALIGN32(addr); \
   228         MEM_WRITE_LONG(addr, *((uint32_t *)&FR((reg))) ); \
   229     }
   231 #define UNDEF(ir)
   232 #define UNIMP(ir)
   234 /**
   235  * Perform instruction-completion following core exit of a partially completed
   236  * instruction. NOTE: This is only allowed on memory writes, operation is not
   237  * guaranteed in any other case.
   238  */
   239 void sh4_finalize_instruction( void )
   240 {
   241     unsigned short ir;
   242     uint32_t tmp;
   244     if( IS_SYSCALL(sh4r.pc) ) {
   245         return;
   246     }
   247     assert( IS_IN_ICACHE(sh4r.pc) );
   248     ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
   250     /**
   251      * Note - we can't take an exit on a control transfer instruction itself,
   252      * which means the exit must have happened in the delay slot. So for these
   253      * cases, finalize the delay slot instruction, and re-execute the control transfer.
   254      *
   255      * For delay slots which modify the argument used in the branch instruction,
   256      * we pretty much just assume that that can't have already happened in an exit case.
   257      */
   259 %%
   260 BRA disp {: 
   261     sh4r.pc += 2; 
   262     sh4_finalize_instruction(); 
   263     sh4r.pc += disp;
   264 :}
   265 BRAF Rn {: 
   266     sh4r.pc += 2; 
   267     tmp = sh4r.r[Rn];
   268     sh4_finalize_instruction(); 
   269     sh4r.pc += tmp;
   270 :}
   271 BSR disp {: 
   272     /* Note: PR is already set */ 
   273     sh4r.pc += 2;
   274     sh4_finalize_instruction();
   275     sh4r.pc += disp;
   276 :}
   277 BSRF Rn {:
   278     /* Note: PR is already set */ 
   279     sh4r.pc += 2;
   280     tmp = sh4r.r[Rn];
   281     sh4_finalize_instruction();
   282     sh4r.pc += tmp;
   283 :}
   284 BF/S disp {: 
   285     sh4r.pc += 2;
   286     sh4_finalize_instruction();
   287     if( !sh4r.t ) {
   288         sh4r.pc += disp;
   289     }
   290 :}
   291 BT/S disp {: 
   292     sh4r.pc += 2;
   293     sh4_finalize_instruction();
   294     if( sh4r.t ) {
   295         sh4r.pc += disp;
   296     }
   297 :}
   298 JMP @Rn {:
   299     sh4r.pc += 2;
   300     tmp = sh4r.r[Rn];
   301     sh4_finalize_instruction();
   302     sh4r.pc = tmp;
   303     sh4r.new_pc = tmp + 2;
   304     sh4r.slice_cycle += sh4_cpu_period;
   305     return;
   306 :}
   307 JSR @Rn {: 
   308     /* Note: PR is already set */ 
   309     sh4r.pc += 2;
   310     tmp = sh4r.r[Rn];
   311     sh4_finalize_instruction();
   312     sh4r.pc = tmp;
   313     sh4r.new_pc = tmp + 2;
   314     sh4r.slice_cycle += sh4_cpu_period;
   315     return;
   316 :}
   317 RTS {: 
   318     sh4r.pc += 2;
   319     sh4_finalize_instruction();
   320     sh4r.pc = sh4r.pr;
   321     sh4r.new_pc = sh4r.pr + 2;
   322     sh4r.slice_cycle += sh4_cpu_period;
   323     return;
   324 :}
   325 RTE {: 
   326     /* SR is already set */
   327     sh4r.pc += 2;
   328     sh4_finalize_instruction();
   329     sh4r.pc = sh4r.spc;
   330     sh4r.new_pc = sh4r.pr + 2;
   331     sh4r.slice_cycle += sh4_cpu_period;
   332     return;
   333 :}
   334 MOV.B Rm, @-Rn {: sh4r.r[Rn]--; :}
   335 MOV.W Rm, @-Rn {: sh4r.r[Rn] -= 2; :}
   336 MOV.L Rm, @-Rn {: sh4r.r[Rn] -= 4; :}
   337 MOV.B @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] ++;  } :}
   338 MOV.W @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
   339 MOV.L @Rm+, Rn {: if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
   340 %%
   341     sh4r.in_delay_slot = 0;
   342     sh4r.pc += 2;
   343     sh4r.new_pc = sh4r.pc+2;
   344     sh4r.slice_cycle += sh4_cpu_period;
   345 }
   347 #undef UNDEF
   348 #undef UNIMP
   350 #define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
   351 #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)
   354 gboolean sh4_execute_instruction( void )
   355 {
   356     uint32_t pc;
   357     unsigned short ir;
   358     uint32_t tmp;
   359     float ftmp;
   360     double dtmp;
   361     int64_t memtmp; // temporary holder for memory reads
   363     INIT_EXCEPTIONS(except)
   365 #define R0 sh4r.r[0]
   366     pc = sh4r.pc;
   367     if( pc > 0xFFFFFF00 ) {
   368 	/* SYSCALL Magic */
   369         sh4r.in_delay_slot = 0;
   370         sh4r.pc = sh4r.pr;
   371         sh4r.new_pc = sh4r.pc + 2;
   372 	syscall_invoke( pc );
   373         return TRUE;
   374     }
   375     CHECKRALIGN16(pc);
   377 #ifdef ENABLE_SH4STATS
   378     sh4_stats_add_by_pc(sh4r.pc);
   379 #endif
   381     /* Read instruction */
   382     if( !IS_IN_ICACHE(pc) ) {
   383         gboolean delay_slot = sh4r.in_delay_slot;
   384 	if( !mmu_update_icache(pc) ) {
   385 	    if( delay_slot ) {
   386 	        sh4r.spc -= 2;
   387 	    }
   388 	    // Fault - look for the fault handler
   389 	    if( !mmu_update_icache(sh4r.pc) ) {
   390 		// double fault - halt
   391 		ERROR( "Double fault - halting" );
   392 		sh4_core_exit(CORE_EXIT_HALT);
   393 		return FALSE;
   394 	    }
   395 	}
   396 	pc = sh4r.pc;
   397     }
   398     assert( IS_IN_ICACHE(pc) );
   399     ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
   401     /* FIXME: This is a bit of a hack, but the PC of the delay slot should not
   402      * be visible until after the instruction has executed (for exception 
   403      * correctness)
   404      */
   405     if( sh4r.in_delay_slot ) {
   406     	sh4r.pc -= 2;
   407     }
   408 %%
   409 AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
   410 AND #imm, R0 {: R0 &= imm; :}
   411  AND.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & tmp ); :}
   412 NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
   413 OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
   414 OR #imm, R0  {: R0 |= imm; :}
   415  OR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | tmp ); :}
   416 TAS.B @Rn {:
   417     MEM_READ_BYTE_FOR_WRITE( sh4r.r[Rn], tmp );
   418     sh4r.t = ( tmp == 0 ? 1 : 0 );
   419     MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
   420 :}
   421 TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
   422 TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
   423  TST.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); sh4r.t = ( tmp & imm ? 0 : 1 ); :}
   424 XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
   425 XOR #imm, R0 {: R0 ^= imm; :}
   426  XOR.B #imm, @(R0, GBR) {: MEM_READ_BYTE_FOR_WRITE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ tmp ); :}
   427 XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
   429 ROTL Rn {:
   430     sh4r.t = sh4r.r[Rn] >> 31;
   431     sh4r.r[Rn] <<= 1;
   432     sh4r.r[Rn] |= sh4r.t;
   433 :}
   434 ROTR Rn {:
   435     sh4r.t = sh4r.r[Rn] & 0x00000001;
   436     sh4r.r[Rn] >>= 1;
   437     sh4r.r[Rn] |= (sh4r.t << 31);
   438 :}
   439 ROTCL Rn {:
   440     tmp = sh4r.r[Rn] >> 31;
   441     sh4r.r[Rn] <<= 1;
   442     sh4r.r[Rn] |= sh4r.t;
   443     sh4r.t = tmp;
   444 :}
   445 ROTCR Rn {:
   446     tmp = sh4r.r[Rn] & 0x00000001;
   447     sh4r.r[Rn] >>= 1;
   448     sh4r.r[Rn] |= (sh4r.t << 31 );
   449     sh4r.t = tmp;
   450 :}
   451 SHAD Rm, Rn {:
   452     tmp = sh4r.r[Rm];
   453     if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
   454     else if( (tmp & 0x1F) == 0 )  
   455         sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
   456     else 
   457 	sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
   458 :}
   459 SHLD Rm, Rn {:
   460     tmp = sh4r.r[Rm];
   461     if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
   462     else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
   463     else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
   464 :}
   465 SHAL Rn {:
   466     sh4r.t = sh4r.r[Rn] >> 31;
   467     sh4r.r[Rn] <<= 1;
   468 :}
   469 SHAR Rn {:
   470     sh4r.t = sh4r.r[Rn] & 0x00000001;
   471     sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
   472 :}
   473 SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
   474 SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
   475 SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
   476 SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
   477 SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
   478 SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
   479 SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
   480 SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
   482 EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
   483 EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
   484 EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
   485 EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
   486 SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
   487 SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
   489 CLRT {: sh4r.t = 0; :}
   490 SETT {: sh4r.t = 1; :}
   491 CLRMAC {: sh4r.mac = 0; :}
   492 LDTLB {: MMU_ldtlb(); :}
   493 CLRS {: sh4r.s = 0; :}
   494 SETS {: sh4r.s = 1; :}
   495 MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
   496 NOP {: /* NOP */ :}
   498 PREF @Rn {:
   499     MEM_PREFETCH(sh4r.r[Rn]);
   500 :}
   501 OCBI @Rn {: :}
   502 OCBP @Rn {: :}
   503 OCBWB @Rn {: :}
   504 MOVCA.L R0, @Rn {:
   505     tmp = sh4r.r[Rn];
   506     CHECKWALIGN32(tmp);
   507     MEM_WRITE_LONG( tmp, R0 );
   508 :}
   509 MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
   510 MOV.W Rm, @(R0, Rn) {: 
   511     CHECKWALIGN16( R0 + sh4r.r[Rn] );
   512     MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
   513 :}
   514 MOV.L Rm, @(R0, Rn) {:
   515     CHECKWALIGN32( R0 + sh4r.r[Rn] );
   516     MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
   517 :}
   518 MOV.B @(R0, Rm), Rn {: MEM_READ_BYTE( R0 + sh4r.r[Rm], sh4r.r[Rn] ); :}
   519 MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
   520     MEM_READ_WORD( R0 + sh4r.r[Rm], sh4r.r[Rn] );
   521 :}
   522 MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
   523     MEM_READ_LONG( R0 + sh4r.r[Rm], sh4r.r[Rn] );
   524 :}
   525 MOV.L Rm, @(disp, Rn) {:
   526     tmp = sh4r.r[Rn] + disp;
   527     CHECKWALIGN32( tmp );
   528     MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
   529 :}
   530 MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
   531 MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
   532 MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
   533  MOV.B Rm, @-Rn {: MEM_WRITE_BYTE( sh4r.r[Rn]-1, sh4r.r[Rm] ); sh4r.r[Rn]--; :}
   534  MOV.W Rm, @-Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn]-2, sh4r.r[Rm] ); sh4r.r[Rn] -= 2; :}
   535  MOV.L Rm, @-Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r[Rm] ); sh4r.r[Rn] -= 4; :}
   536 MOV.L @(disp, Rm), Rn {:
   537     tmp = sh4r.r[Rm] + disp;
   538     CHECKRALIGN32( tmp );
   539     MEM_READ_LONG( tmp, sh4r.r[Rn] );
   540 :}
   541 MOV.B @Rm, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); :}
   542  MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); :}
   543  MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); :}
   544 MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
   545  MOV.B @Rm+, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] ++; } :}
   546  MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 2; } :}
   547  MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); if( Rm != Rn ) { sh4r.r[Rm] += 4; } :}
   548 MOV.L @(disp, PC), Rn {:
   549     CHECKSLOTILLEGAL();
   550     tmp = (pc&0xFFFFFFFC) + disp + 4;
   551     MEM_READ_LONG( tmp, sh4r.r[Rn] );
   552 :}
   553 MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
   554 MOV.W R0, @(disp, GBR) {:
   555     tmp = sh4r.gbr + disp;
   556     CHECKWALIGN16( tmp );
   557     MEM_WRITE_WORD( tmp, R0 );
   558 :}
   559 MOV.L R0, @(disp, GBR) {:
   560     tmp = sh4r.gbr + disp;
   561     CHECKWALIGN32( tmp );
   562     MEM_WRITE_LONG( tmp, R0 );
   563 :}
   564  MOV.B @(disp, GBR), R0 {: MEM_READ_BYTE( sh4r.gbr + disp, R0 ); :}
   565 MOV.W @(disp, GBR), R0 {: 
   566     tmp = sh4r.gbr + disp;
   567     CHECKRALIGN16( tmp );
   568     MEM_READ_WORD( tmp, R0 );
   569 :}
   570 MOV.L @(disp, GBR), R0 {:
   571     tmp = sh4r.gbr + disp;
   572     CHECKRALIGN32( tmp );
   573     MEM_READ_LONG( tmp, R0 );
   574 :}
   575 MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
   576 MOV.W R0, @(disp, Rn) {: 
   577     tmp = sh4r.r[Rn] + disp;
   578     CHECKWALIGN16( tmp );
   579     MEM_WRITE_WORD( tmp, R0 );
   580 :}
   581  MOV.B @(disp, Rm), R0 {: MEM_READ_BYTE( sh4r.r[Rm] + disp, R0 ); :}
   582 MOV.W @(disp, Rm), R0 {: 
   583     tmp = sh4r.r[Rm] + disp;
   584     CHECKRALIGN16( tmp );
   585     MEM_READ_WORD( tmp, R0 );
   586 :}
   587 MOV.W @(disp, PC), Rn {:
   588     CHECKSLOTILLEGAL();
   589     tmp = pc + 4 + disp;
   590     MEM_READ_WORD( tmp, sh4r.r[Rn] );
   591 :}
   592 MOVA @(disp, PC), R0 {:
   593     CHECKSLOTILLEGAL();
   594     R0 = (pc&0xFFFFFFFC) + disp + 4;
   595 :}
   596 MOV #imm, Rn {:  sh4r.r[Rn] = imm; :}
   598 FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
   599 FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
   600 FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
   601 FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
   602 FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
   603  FMOV FRm, @-Rn {: MEM_FP_WRITE( sh4r.r[Rn] - FP_WIDTH, FRm ); sh4r.r[Rn] -= FP_WIDTH; :}
   604 FMOV FRm, FRn {: 
   605     if( IS_FPU_DOUBLESIZE() )
   606 	DR(FRn) = DR(FRm);
   607     else
   608 	FR(FRn) = FR(FRm);
   609 :}
   611 CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
   612 CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
   613 CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
   614 CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
   615 CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
   616 CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
   617 CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
   618 CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
   619 CMP/STR Rm, Rn {: 
   620     /* set T = 1 if any byte in RM & RN is the same */
   621     tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
   622     sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
   623              (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
   624 :}
   626 ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
   627 ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
   628 ADDC Rm, Rn {:
   629     tmp = sh4r.r[Rn];
   630     sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
   631     sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
   632 :}
   633 ADDV Rm, Rn {:
   634     tmp = sh4r.r[Rn] + sh4r.r[Rm];
   635     sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
   636     sh4r.r[Rn] = tmp;
   637 :}
   638 DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
   639 DIV0S Rm, Rn {: 
   640     sh4r.q = sh4r.r[Rn]>>31;
   641     sh4r.m = sh4r.r[Rm]>>31;
   642     sh4r.t = sh4r.q ^ sh4r.m;
   643 :}
   644 DIV1 Rm, Rn {:
   645     /* This is derived from the sh4 manual with some simplifications */
   646     uint32_t tmp0, tmp1, tmp2, dir;
   648     dir = sh4r.q ^ sh4r.m;
   649     sh4r.q = (sh4r.r[Rn] >> 31);
   650     tmp2 = sh4r.r[Rm];
   651     sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
   652     tmp0 = sh4r.r[Rn];
   653     if( dir ) {
   654          sh4r.r[Rn] += tmp2;
   655          tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
   656     } else {
   657          sh4r.r[Rn] -= tmp2;
   658          tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
   659     }
   660     sh4r.q ^= sh4r.m ^ tmp1;
   661     sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
   662 :}
   663 DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
   664 DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
   665 DT Rn {:
   666     sh4r.r[Rn] --;
   667     sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
   668 :}
   669 MAC.W @Rm+, @Rn+ {:
   670     int32_t stmp;
   671     if( Rm == Rn ) {
   672 	CHECKRALIGN16(sh4r.r[Rn]);
   673 	MEM_READ_WORD( sh4r.r[Rn], tmp );
   674 	stmp = SIGNEXT16(tmp);
   675 	MEM_READ_WORD( sh4r.r[Rn]+2, tmp );
   676 	stmp *= SIGNEXT16(tmp);
   677 	sh4r.r[Rn] += 4;
   678     } else {
   679 	CHECKRALIGN16( sh4r.r[Rn] );
   680 	CHECKRALIGN16( sh4r.r[Rm] );
   681 	MEM_READ_WORD(sh4r.r[Rn], tmp);
   682 	stmp = SIGNEXT16(tmp);
   683 	MEM_READ_WORD(sh4r.r[Rm], tmp);
   684 	stmp = stmp * SIGNEXT16(tmp);
   685 	sh4r.r[Rn] += 2;
   686 	sh4r.r[Rm] += 2;
   687     }
   688     if( sh4r.s ) {
   689 	int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
   690 	if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
   691 	    sh4r.mac = 0x000000017FFFFFFFLL;
   692 	} else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
   693 	    sh4r.mac = 0x0000000180000000LL;
   694 	} else {
   695 	    sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
   696 		((uint32_t)(sh4r.mac + stmp));
   697 	}
   698     } else {
   699 	sh4r.mac += SIGNEXT32(stmp);
   700     }
   701 :}
   702 MAC.L @Rm+, @Rn+ {:
   703     int64_t tmpl;
   704     if( Rm == Rn ) {
   705 	CHECKRALIGN32( sh4r.r[Rn] );
   706 	MEM_READ_LONG(sh4r.r[Rn], tmp);
   707 	tmpl = SIGNEXT32(tmp);
   708 	MEM_READ_LONG(sh4r.r[Rn]+4, tmp);
   709 	tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
   710 	sh4r.r[Rn] += 8;
   711     } else {
   712 	CHECKRALIGN32( sh4r.r[Rm] );
   713 	CHECKRALIGN32( sh4r.r[Rn] );
   714 	MEM_READ_LONG(sh4r.r[Rn], tmp);
   715 	tmpl = SIGNEXT32(tmp);
   716 	MEM_READ_LONG(sh4r.r[Rm], tmp);
   717 	tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
   718 	sh4r.r[Rn] += 4;
   719 	sh4r.r[Rm] += 4;
   720     }
   721     if( sh4r.s ) {
   722         /* 48-bit Saturation. Yuch */
   723         if( tmpl < (int64_t)0xFFFF800000000000LL )
   724             tmpl = 0xFFFF800000000000LL;
   725         else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
   726             tmpl = 0x00007FFFFFFFFFFFLL;
   727     }
   728     sh4r.mac = tmpl;
   729 :}
   730 MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
   731                         (sh4r.r[Rm] * sh4r.r[Rn]); :}
   732 MULU.W Rm, Rn {:
   733     sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
   734                (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
   735 :}
   736 MULS.W Rm, Rn {:
   737     sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
   738                (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
   739 :}
   740 NEGC Rm, Rn {:
   741     tmp = 0 - sh4r.r[Rm];
   742     sh4r.r[Rn] = tmp - sh4r.t;
   743     sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
   744 :}
   745 NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
   746 SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
   747 SUBC Rm, Rn {: 
   748     tmp = sh4r.r[Rn];
   749     sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
   750     sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
   751 :}
   752 SUBV Rm, Rn {:
   753     tmp = sh4r.r[Rn] - sh4r.r[Rm];
   754     sh4r.t = ( (sh4r.r[Rn]>>31) != (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
   755     sh4r.r[Rn] = tmp;
   756 :}
   757 BRAF Rn {:
   758      CHECKSLOTILLEGAL();
   759      CHECKDEST( pc + 4 + sh4r.r[Rn] );
   760      sh4r.in_delay_slot = 1;
   761      sh4r.pc = sh4r.new_pc;
   762      sh4r.new_pc = pc + 4 + sh4r.r[Rn];
   763      return TRUE;
   764 :}
   765 BSRF Rn {:
   766      CHECKSLOTILLEGAL();
   767      CHECKDEST( pc + 4 + sh4r.r[Rn] );
   768      sh4r.in_delay_slot = 1;
   769      sh4r.pr = sh4r.pc + 4;
   770      sh4r.pc = sh4r.new_pc;
   771      sh4r.new_pc = pc + 4 + sh4r.r[Rn];
   772      TRACE_CALL( pc, sh4r.new_pc );
   773      return TRUE;
   774 :}
   775 BT disp {:
   776     CHECKSLOTILLEGAL();
   777     if( sh4r.t ) {
   778         CHECKDEST( sh4r.pc + disp + 4 )
   779         sh4r.pc += disp + 4;
   780         sh4r.new_pc = sh4r.pc + 2;
   781         return TRUE;
   782     }
   783 :}
   784 BF disp {:
   785     CHECKSLOTILLEGAL();
   786     if( !sh4r.t ) {
   787         CHECKDEST( sh4r.pc + disp + 4 )
   788         sh4r.pc += disp + 4;
   789         sh4r.new_pc = sh4r.pc + 2;
   790         return TRUE;
   791     }
   792 :}
   793 BT/S disp {:
   794     CHECKSLOTILLEGAL();
   795     if( sh4r.t ) {
   796         CHECKDEST( sh4r.pc + disp + 4 )
   797         sh4r.in_delay_slot = 1;
   798         sh4r.pc = sh4r.new_pc;
   799         sh4r.new_pc = pc + disp + 4;
   800         sh4r.in_delay_slot = 1;
   801         return TRUE;
   802     }
   803 :}
   804 BF/S disp {:
   805     CHECKSLOTILLEGAL();
   806     if( !sh4r.t ) {
   807         CHECKDEST( sh4r.pc + disp + 4 )
   808         sh4r.in_delay_slot = 1;
   809         sh4r.pc = sh4r.new_pc;
   810         sh4r.new_pc = pc + disp + 4;
   811         return TRUE;
   812     }
   813 :}
   814 BRA disp {:
   815     CHECKSLOTILLEGAL();
   816     CHECKDEST( sh4r.pc + disp + 4 );
   817     sh4r.in_delay_slot = 1;
   818     sh4r.pc = sh4r.new_pc;
   819     sh4r.new_pc = pc + 4 + disp;
   820     return TRUE;
   821 :}
   822 BSR disp {:
   823     CHECKDEST( sh4r.pc + disp + 4 );
   824     CHECKSLOTILLEGAL();
   825     sh4r.in_delay_slot = 1;
   826     sh4r.pr = pc + 4;
   827     sh4r.pc = sh4r.new_pc;
   828     sh4r.new_pc = pc + 4 + disp;
   829     TRACE_CALL( pc, sh4r.new_pc );
   830     return TRUE;
   831 :}
   832 TRAPA #imm {:
   833     CHECKSLOTILLEGAL();
   834     sh4r.pc += 2;
   835     sh4_raise_trap( imm );
   836     return TRUE;
   837 :}
   838 RTS {: 
   839     CHECKSLOTILLEGAL();
   840     CHECKDEST( sh4r.pr );
   841     sh4r.in_delay_slot = 1;
   842     sh4r.pc = sh4r.new_pc;
   843     sh4r.new_pc = sh4r.pr;
   844     TRACE_RETURN( pc, sh4r.new_pc );
   845     return TRUE;
   846 :}
   847 SLEEP {:
   848     if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
   849 	sh4r.sh4_state = SH4_STATE_STANDBY;
   850     } else {
   851 	sh4r.sh4_state = SH4_STATE_SLEEP;
   852     }
   853     return FALSE; /* Halt CPU */
   854 :}
   855 RTE {:
   856     CHECKPRIV();
   857     CHECKDEST( sh4r.spc );
   858     CHECKSLOTILLEGAL();
   859     sh4r.in_delay_slot = 1;
   860     sh4r.pc = sh4r.new_pc;
   861     sh4r.new_pc = sh4r.spc;
   862     sh4_write_sr( sh4r.ssr );
   863     return TRUE;
   864 :}
   865 JMP @Rn {:
   866     CHECKDEST( sh4r.r[Rn] );
   867     CHECKSLOTILLEGAL();
   868     sh4r.in_delay_slot = 1;
   869     sh4r.pc = sh4r.new_pc;
   870     sh4r.new_pc = sh4r.r[Rn];
   871     return TRUE;
   872 :}
   873 JSR @Rn {:
   874     CHECKDEST( sh4r.r[Rn] );
   875     CHECKSLOTILLEGAL();
   876     sh4r.in_delay_slot = 1;
   877     sh4r.pc = sh4r.new_pc;
   878     sh4r.new_pc = sh4r.r[Rn];
   879     sh4r.pr = pc + 4;
   880     TRACE_CALL( pc, sh4r.new_pc );
   881     return TRUE;
   882 :}
   883 STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
   884 STS.L MACH, @-Rn {:
   885     CHECKWALIGN32( sh4r.r[Rn] );
   886     MEM_WRITE_LONG( sh4r.r[Rn]-4, (sh4r.mac>>32) );
   887     sh4r.r[Rn] -= 4;
   888 :}
   889 STC.L SR, @-Rn {:
   890     CHECKPRIV();
   891     CHECKWALIGN32( sh4r.r[Rn] );
   892     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4_read_sr() );
   893     sh4r.r[Rn] -= 4;
   894 :}
   895 LDS.L @Rm+, MACH {:
   896     CHECKRALIGN32( sh4r.r[Rm] );
   897     MEM_READ_LONG(sh4r.r[Rm], tmp);
   898     sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
   899 	(((uint64_t)tmp)<<32);
   900     sh4r.r[Rm] += 4;
   901 :}
   902 LDC.L @Rm+, SR {:
   903     CHECKSLOTILLEGAL();
   904     CHECKPRIV();
   905     CHECKWALIGN32( sh4r.r[Rm] );
   906     MEM_READ_LONG(sh4r.r[Rm], tmp);
   907     sh4_write_sr( tmp );
   908     sh4r.r[Rm] +=4;
   909 :}
   910 LDS Rm, MACH {:
   911     sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
   912                (((uint64_t)sh4r.r[Rm])<<32);
   913 :}
   914 LDC Rm, SR {:
   915     CHECKSLOTILLEGAL();
   916     CHECKPRIV();
   917     sh4_write_sr( sh4r.r[Rm] );
   918 :}
   919 LDC Rm, SGR {:
   920     CHECKPRIV();
   921     sh4r.sgr = sh4r.r[Rm];
   922 :}
   923 LDC.L @Rm+, SGR {:
   924     CHECKPRIV();
   925     CHECKRALIGN32( sh4r.r[Rm] );
   926     MEM_READ_LONG(sh4r.r[Rm], sh4r.sgr);
   927     sh4r.r[Rm] +=4;
   928 :}
   929 STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
   930 STS.L MACL, @-Rn {:
   931     CHECKWALIGN32( sh4r.r[Rn] );
   932     MEM_WRITE_LONG( sh4r.r[Rn]-4, (uint32_t)sh4r.mac );
   933     sh4r.r[Rn] -= 4;
   934 :}
   935 STC.L GBR, @-Rn {:
   936     CHECKWALIGN32( sh4r.r[Rn] );
   937     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.gbr );
   938     sh4r.r[Rn] -= 4;
   939 :}
   940 LDS.L @Rm+, MACL {:
   941     CHECKRALIGN32( sh4r.r[Rm] );
   942     MEM_READ_LONG(sh4r.r[Rm], tmp);
   943     sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
   944                (uint64_t)((uint32_t)tmp);
   945     sh4r.r[Rm] += 4;
   946 :}
   947 LDC.L @Rm+, GBR {:
   948     CHECKRALIGN32( sh4r.r[Rm] );
   949     MEM_READ_LONG(sh4r.r[Rm], sh4r.gbr);
   950     sh4r.r[Rm] +=4;
   951 :}
   952 LDS Rm, MACL {:
   953     sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
   954                (uint64_t)((uint32_t)(sh4r.r[Rm]));
   955 :}
   956 LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
   957 STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
   958 STS.L PR, @-Rn {:
   959     CHECKWALIGN32( sh4r.r[Rn] );
   960     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.pr );
   961     sh4r.r[Rn] -= 4;
   962 :}
   963 STC.L VBR, @-Rn {:
   964     CHECKPRIV();
   965     CHECKWALIGN32( sh4r.r[Rn] );
   966     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.vbr );
   967     sh4r.r[Rn] -= 4;
   968 :}
   969 LDS.L @Rm+, PR {:
   970     CHECKRALIGN32( sh4r.r[Rm] );
   971     MEM_READ_LONG( sh4r.r[Rm], sh4r.pr );
   972     sh4r.r[Rm] += 4;
   973 :}
   974 LDC.L @Rm+, VBR {:
   975     CHECKPRIV();
   976     CHECKRALIGN32( sh4r.r[Rm] );
   977     MEM_READ_LONG(sh4r.r[Rm], sh4r.vbr);
   978     sh4r.r[Rm] +=4;
   979 :}
   980 LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
   981 LDC Rm, VBR {:
   982     CHECKPRIV();
   983     sh4r.vbr = sh4r.r[Rm];
   984 :}
   985 STC SGR, Rn {:
   986     CHECKPRIV();
   987     sh4r.r[Rn] = sh4r.sgr;
   988 :}
   989 STC.L SGR, @-Rn {:
   990     CHECKPRIV();
   991     CHECKWALIGN32( sh4r.r[Rn] );
   992     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.sgr );
   993     sh4r.r[Rn] -= 4;
   994 :}
   995 STC.L SSR, @-Rn {:
   996     CHECKPRIV();
   997     CHECKWALIGN32( sh4r.r[Rn] );
   998     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.ssr );
   999     sh4r.r[Rn] -= 4;
  1000 :}
  1001 LDC.L @Rm+, SSR {:
  1002     CHECKPRIV();
  1003     CHECKRALIGN32( sh4r.r[Rm] );
  1004     MEM_READ_LONG(sh4r.r[Rm], sh4r.ssr);
  1005     sh4r.r[Rm] +=4;
  1006 :}
  1007 LDC Rm, SSR {:
  1008     CHECKPRIV();
  1009     sh4r.ssr = sh4r.r[Rm];
  1010 :}
  1011 STC.L SPC, @-Rn {:
  1012     CHECKPRIV();
  1013     CHECKWALIGN32( sh4r.r[Rn] );
  1014     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.spc );
  1015     sh4r.r[Rn] -= 4;
  1016 :}
  1017 LDC.L @Rm+, SPC {:
  1018     CHECKPRIV();
  1019     CHECKRALIGN32( sh4r.r[Rm] );
  1020     MEM_READ_LONG(sh4r.r[Rm], sh4r.spc);
  1021     sh4r.r[Rm] +=4;
  1022 :}
  1023 LDC Rm, SPC {:
  1024     CHECKPRIV();
  1025     sh4r.spc = sh4r.r[Rm];
  1026 :}
  1027 STS FPUL, Rn {: 
  1028     CHECKFPUEN();
  1029     sh4r.r[Rn] = FPULi; 
  1030 :}
  1031 STS.L FPUL, @-Rn {:
  1032     CHECKFPUEN();
  1033     CHECKWALIGN32( sh4r.r[Rn] );
  1034     MEM_WRITE_LONG( sh4r.r[Rn]-4, FPULi );
  1035     sh4r.r[Rn] -= 4;
  1036 :}
  1037 LDS.L @Rm+, FPUL {:
  1038     CHECKFPUEN();
  1039     CHECKRALIGN32( sh4r.r[Rm] );
  1040     MEM_READ_LONG(sh4r.r[Rm], FPULi);
  1041     sh4r.r[Rm] +=4;
  1042 :}
  1043 LDS Rm, FPUL {:
  1044     CHECKFPUEN();
  1045     FPULi = sh4r.r[Rm]; 
  1046 :}
  1047 STS FPSCR, Rn {: 
  1048     CHECKFPUEN();
  1049     sh4r.r[Rn] = sh4r.fpscr; 
  1050 :}
  1051 STS.L FPSCR, @-Rn {:
  1052     CHECKFPUEN();
  1053     CHECKWALIGN32( sh4r.r[Rn] );
  1054     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.fpscr );
  1055     sh4r.r[Rn] -= 4;
  1056 :}
  1057 LDS.L @Rm+, FPSCR {:
  1058     CHECKFPUEN();
  1059     CHECKRALIGN32( sh4r.r[Rm] );
  1060     MEM_READ_LONG(sh4r.r[Rm], tmp);
  1061     sh4r.r[Rm] +=4;
  1062     sh4_write_fpscr( tmp );
  1063 :}
  1064 LDS Rm, FPSCR {: 
  1065     CHECKFPUEN();
  1066     sh4_write_fpscr( sh4r.r[Rm] );
  1067 :}
  1068 STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
  1069 STC.L DBR, @-Rn {:
  1070     CHECKPRIV();
  1071     CHECKWALIGN32( sh4r.r[Rn] );
  1072     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.dbr );
  1073     sh4r.r[Rn] -= 4;
  1074 :}
  1075 LDC.L @Rm+, DBR {:
  1076     CHECKPRIV();
  1077     CHECKRALIGN32( sh4r.r[Rm] );
  1078     MEM_READ_LONG(sh4r.r[Rm], sh4r.dbr);
  1079     sh4r.r[Rm] +=4;
  1080 :}
  1081 LDC Rm, DBR {:
  1082     CHECKPRIV();
  1083     sh4r.dbr = sh4r.r[Rm];
  1084 :}
  1085 STC.L Rm_BANK, @-Rn {:
  1086     CHECKPRIV();
  1087     CHECKWALIGN32( sh4r.r[Rn] );
  1088     MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r_bank[Rm_BANK] );
  1089     sh4r.r[Rn] -= 4;
  1090 :}
  1091 LDC.L @Rm+, Rn_BANK {:
  1092     CHECKPRIV();
  1093     CHECKRALIGN32( sh4r.r[Rm] );
  1094     MEM_READ_LONG( sh4r.r[Rm], sh4r.r_bank[Rn_BANK] );
  1095     sh4r.r[Rm] += 4;
  1096 :}
  1097 LDC Rm, Rn_BANK {:
  1098     CHECKPRIV();
  1099     sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
  1100 :}
  1101 STC SR, Rn {: 
  1102     CHECKPRIV();
  1103     sh4r.r[Rn] = sh4_read_sr();
  1104 :}
  1105 STC GBR, Rn {:
  1106     sh4r.r[Rn] = sh4r.gbr;
  1107 :}
  1108 STC VBR, Rn {:
  1109     CHECKPRIV();
  1110     sh4r.r[Rn] = sh4r.vbr;
  1111 :}
  1112 STC SSR, Rn {:
  1113     CHECKPRIV();
  1114     sh4r.r[Rn] = sh4r.ssr;
  1115 :}
  1116 STC SPC, Rn {:
  1117     CHECKPRIV();
  1118     sh4r.r[Rn] = sh4r.spc;
  1119 :}
  1120 STC Rm_BANK, Rn {:
  1121     CHECKPRIV();
  1122     sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
  1123 :}
  1125 FADD FRm, FRn {:
  1126     CHECKFPUEN();
  1127     if( IS_FPU_DOUBLEPREC() ) {
  1128 	DR(FRn) += DR(FRm);
  1129     } else {
  1130 	FR(FRn) += FR(FRm);
  1132 :}
  1133 FSUB FRm, FRn {:
  1134     CHECKFPUEN();
  1135     if( IS_FPU_DOUBLEPREC() ) {
  1136 	DR(FRn) -= DR(FRm);
  1137     } else {
  1138 	FR(FRn) -= FR(FRm);
  1140 :}
  1142 FMUL FRm, FRn {:
  1143     CHECKFPUEN();
  1144     if( IS_FPU_DOUBLEPREC() ) {
  1145 	DR(FRn) *= DR(FRm);
  1146     } else {
  1147 	FR(FRn) *= FR(FRm);
  1149 :}
  1151 FDIV FRm, FRn {:
  1152     CHECKFPUEN();
  1153     if( IS_FPU_DOUBLEPREC() ) {
  1154 	DR(FRn) /= DR(FRm);
  1155     } else {
  1156 	FR(FRn) /= FR(FRm);
  1158 :}
  1160 FCMP/EQ FRm, FRn {:
  1161     CHECKFPUEN();
  1162     if( IS_FPU_DOUBLEPREC() ) {
  1163 	sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
  1164     } else {
  1165 	sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
  1167 :}
  1169 FCMP/GT FRm, FRn {:
  1170     CHECKFPUEN();
  1171     if( IS_FPU_DOUBLEPREC() ) {
  1172 	sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
  1173     } else {
  1174 	sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
  1176 :}
  1178 FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
  1179 FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
  1180 FLOAT FPUL, FRn {: 
  1181     CHECKFPUEN();
  1182     if( IS_FPU_DOUBLEPREC() ) {
  1183 	if( FRn&1 ) { // No, really...
  1184 	    dtmp = (double)FPULi;
  1185 	    FR(FRn) = *(((float *)&dtmp)+1);
  1186 	} else {
  1187 	    DRF(FRn>>1) = (double)FPULi;
  1189     } else {
  1190 	FR(FRn) = (float)FPULi;
  1192 :}
  1193 FTRC FRm, FPUL {:
  1194     CHECKFPUEN();
  1195     if( IS_FPU_DOUBLEPREC() ) {
  1196 	if( FRm&1 ) {
  1197 	    dtmp = 0;
  1198 	    *(((float *)&dtmp)+1) = FR(FRm);
  1199 	} else {
  1200 	    dtmp = DRF(FRm>>1);
  1202         if( dtmp >= MAX_INTF )
  1203             FPULi = MAX_INT;
  1204         else if( dtmp <= MIN_INTF )
  1205             FPULi = MIN_INT;
  1206         else 
  1207             FPULi = (int32_t)dtmp;
  1208     } else {
  1209 	ftmp = FR(FRm);
  1210 	if( ftmp >= MAX_INTF )
  1211 	    FPULi = MAX_INT;
  1212 	else if( ftmp <= MIN_INTF )
  1213 	    FPULi = MIN_INT;
  1214 	else
  1215 	    FPULi = (int32_t)ftmp;
  1217 :}
  1218 FNEG FRn {:
  1219     CHECKFPUEN();
  1220     if( IS_FPU_DOUBLEPREC() ) {
  1221 	DR(FRn) = -DR(FRn);
  1222     } else {
  1223         FR(FRn) = -FR(FRn);
  1225 :}
  1226 FABS FRn {:
  1227     CHECKFPUEN();
  1228     if( IS_FPU_DOUBLEPREC() ) {
  1229 	DR(FRn) = fabs(DR(FRn));
  1230     } else {
  1231         FR(FRn) = fabsf(FR(FRn));
  1233 :}
  1234 FSQRT FRn {:
  1235     CHECKFPUEN();
  1236     if( IS_FPU_DOUBLEPREC() ) {
  1237 	DR(FRn) = sqrt(DR(FRn));
  1238     } else {
  1239         FR(FRn) = sqrtf(FR(FRn));
  1241 :}
  1242 FLDI0 FRn {:
  1243     CHECKFPUEN();
  1244     if( IS_FPU_DOUBLEPREC() ) {
  1245 	DR(FRn) = 0.0;
  1246     } else {
  1247         FR(FRn) = 0.0;
  1249 :}
  1250 FLDI1 FRn {:
  1251     CHECKFPUEN();
  1252     if( IS_FPU_DOUBLEPREC() ) {
  1253 	DR(FRn) = 1.0;
  1254     } else {
  1255         FR(FRn) = 1.0;
  1257 :}
  1258 FMAC FR0, FRm, FRn {:
  1259     CHECKFPUEN();
  1260     if( IS_FPU_DOUBLEPREC() ) {
  1261         DR(FRn) += DR(FRm)*DR(0);
  1262     } else {
  1263 	FR(FRn) += FR(FRm)*FR(0);
  1265 :}
  1266 FRCHG {: 
  1267     CHECKFPUEN(); 
  1268     sh4r.fpscr ^= FPSCR_FR; 
  1269     sh4_switch_fr_banks();
  1270 :}
  1271 FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
  1272 FCNVSD FPUL, FRn {:
  1273     CHECKFPUEN();
  1274     if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
  1275 	DR(FRn) = (double)FPULf;
  1277 :}
  1278 FCNVDS FRm, FPUL {:
  1279     CHECKFPUEN();
  1280     if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
  1281 	FPULf = (float)DR(FRm);
  1283 :}
  1285 FSRRA FRn {:
  1286     CHECKFPUEN();
  1287     if( !IS_FPU_DOUBLEPREC() ) {
  1288 	FR(FRn) = 1.0/sqrtf(FR(FRn));
  1290 :}
  1291 FIPR FVm, FVn {:
  1292     CHECKFPUEN();
  1293     if( !IS_FPU_DOUBLEPREC() ) {
  1294         int tmp2 = FVn<<2;
  1295         tmp = FVm<<2;
  1296         FR(tmp2+3) = FR(tmp)*FR(tmp2) +
  1297             FR(tmp+1)*FR(tmp2+1) +
  1298             FR(tmp+2)*FR(tmp2+2) +
  1299             FR(tmp+3)*FR(tmp2+3);
  1301 :}
  1302 FSCA FPUL, FRn {:
  1303     CHECKFPUEN();
  1304     if( !IS_FPU_DOUBLEPREC() ) {
  1305 	sh4_fsca( FPULi, (float *)&(DRF(FRn>>1)) );
  1307 :}
  1308 FTRV XMTRX, FVn {:
  1309     CHECKFPUEN();
  1310     if( !IS_FPU_DOUBLEPREC() ) {
  1311 	sh4_ftrv((float *)&(DRF(FVn<<1)) );
  1313 :}
  1314 UNDEF {:
  1315     UNDEF(ir);
  1316 :}
  1317 %%
  1318     sh4r.pc = sh4r.new_pc;
  1319     sh4r.new_pc += 2;
  1321 except:
  1322     sh4r.in_delay_slot = 0;
  1323     return TRUE;
.