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