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