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