Search
lxdream.org :: lxdream/src/sh4/sh4x86.in
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4x86.in
changeset 408:af496b734734
prev401:f79327f39818
next409:549e00835448
author nkeynes
date Fri Sep 28 07:27:20 2007 +0000 (12 years ago)
permissions -rw-r--r--
last change Change block signature to return pointer to next block (if known)
Rewrite block-exit code
view annotate diff log raw
     1 /**
     2  * $Id: sh4x86.in,v 1.16 2007-09-28 07:27:20 nkeynes Exp $
     3  * 
     4  * SH4 => x86 translation. This version does no real optimization, it just
     5  * outputs straight-line x86 code - it mainly exists to provide a baseline
     6  * to test the optimizing versions against.
     7  *
     8  * Copyright (c) 2007 Nathan Keynes.
     9  *
    10  * This program is free software; you can redistribute it and/or modify
    11  * it under the terms of the GNU General Public License as published by
    12  * the Free Software Foundation; either version 2 of the License, or
    13  * (at your option) any later version.
    14  *
    15  * This program is distributed in the hope that it will be useful,
    16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    18  * GNU General Public License for more details.
    19  */
    21 #include <assert.h>
    22 #include <math.h>
    24 #ifndef NDEBUG
    25 #define DEBUG_JUMPS 1
    26 #endif
    28 #include "sh4/sh4core.h"
    29 #include "sh4/sh4trans.h"
    30 #include "sh4/sh4mmio.h"
    31 #include "sh4/x86op.h"
    32 #include "clock.h"
    34 #define DEFAULT_BACKPATCH_SIZE 4096
    36 /** 
    37  * Struct to manage internal translation state. This state is not saved -
    38  * it is only valid between calls to sh4_translate_begin_block() and
    39  * sh4_translate_end_block()
    40  */
    41 struct sh4_x86_state {
    42     gboolean in_delay_slot;
    43     gboolean priv_checked; /* true if we've already checked the cpu mode. */
    44     gboolean fpuen_checked; /* true if we've already checked fpu enabled. */
    45     uint32_t block_start_pc;
    47     /* Allocated memory for the (block-wide) back-patch list */
    48     uint32_t **backpatch_list;
    49     uint32_t backpatch_posn;
    50     uint32_t backpatch_size;
    51 };
    53 #define EXIT_DATA_ADDR_READ 0
    54 #define EXIT_DATA_ADDR_WRITE 7
    55 #define EXIT_ILLEGAL 14
    56 #define EXIT_SLOT_ILLEGAL 21
    57 #define EXIT_FPU_DISABLED 28
    58 #define EXIT_SLOT_FPU_DISABLED 35
    60 static struct sh4_x86_state sh4_x86;
    62 static uint32_t max_int = 0x7FFFFFFF;
    63 static uint32_t min_int = 0x80000000;
    64 static uint32_t save_fcw; /* save value for fpu control word */
    65 static uint32_t trunc_fcw = 0x0F7F; /* fcw value for truncation mode */
    67 void sh4_x86_init()
    68 {
    69     sh4_x86.backpatch_list = malloc(DEFAULT_BACKPATCH_SIZE);
    70     sh4_x86.backpatch_size = DEFAULT_BACKPATCH_SIZE / sizeof(uint32_t *);
    71 }
    74 static void sh4_x86_add_backpatch( uint8_t *ptr )
    75 {
    76     if( sh4_x86.backpatch_posn == sh4_x86.backpatch_size ) {
    77 	sh4_x86.backpatch_size <<= 1;
    78 	sh4_x86.backpatch_list = realloc( sh4_x86.backpatch_list, sh4_x86.backpatch_size * sizeof(uint32_t *) );
    79 	assert( sh4_x86.backpatch_list != NULL );
    80     }
    81     sh4_x86.backpatch_list[sh4_x86.backpatch_posn++] = (uint32_t *)ptr;
    82 }
    84 static void sh4_x86_do_backpatch( uint8_t *reloc_base )
    85 {
    86     unsigned int i;
    87     for( i=0; i<sh4_x86.backpatch_posn; i++ ) {
    88 	*sh4_x86.backpatch_list[i] += (reloc_base - ((uint8_t *)sh4_x86.backpatch_list[i]) - 4);
    89     }
    90 }
    92 /**
    93  * Emit an instruction to load an SH4 reg into a real register
    94  */
    95 static inline void load_reg( int x86reg, int sh4reg ) 
    96 {
    97     /* mov [bp+n], reg */
    98     OP(0x8B);
    99     OP(0x45 + (x86reg<<3));
   100     OP(REG_OFFSET(r[sh4reg]));
   101 }
   103 static inline void load_reg16s( int x86reg, int sh4reg )
   104 {
   105     OP(0x0F);
   106     OP(0xBF);
   107     MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
   108 }
   110 static inline void load_reg16u( int x86reg, int sh4reg )
   111 {
   112     OP(0x0F);
   113     OP(0xB7);
   114     MODRM_r32_sh4r(x86reg, REG_OFFSET(r[sh4reg]));
   116 }
   118 #define load_spreg( x86reg, regoff ) MOV_sh4r_r32( regoff, x86reg )
   119 #define store_spreg( x86reg, regoff ) MOV_r32_sh4r( x86reg, regoff )
   120 /**
   121  * Emit an instruction to load an immediate value into a register
   122  */
   123 static inline void load_imm32( int x86reg, uint32_t value ) {
   124     /* mov #value, reg */
   125     OP(0xB8 + x86reg);
   126     OP32(value);
   127 }
   129 /**
   130  * Emit an instruction to store an SH4 reg (RN)
   131  */
   132 void static inline store_reg( int x86reg, int sh4reg ) {
   133     /* mov reg, [bp+n] */
   134     OP(0x89);
   135     OP(0x45 + (x86reg<<3));
   136     OP(REG_OFFSET(r[sh4reg]));
   137 }
   139 #define load_fr_bank(bankreg) load_spreg( bankreg, REG_OFFSET(fr_bank))
   141 /**
   142  * Load an FR register (single-precision floating point) into an integer x86
   143  * register (eg for register-to-register moves)
   144  */
   145 void static inline load_fr( int bankreg, int x86reg, int frm )
   146 {
   147     OP(0x8B); OP(0x40+bankreg+(x86reg<<3)); OP((frm^1)<<2);
   148 }
   150 /**
   151  * Store an FR register (single-precision floating point) into an integer x86
   152  * register (eg for register-to-register moves)
   153  */
   154 void static inline store_fr( int bankreg, int x86reg, int frn )
   155 {
   156     OP(0x89);  OP(0x40+bankreg+(x86reg<<3)); OP((frn^1)<<2);
   157 }
   160 /**
   161  * Load a pointer to the back fp back into the specified x86 register. The
   162  * bankreg must have been previously loaded with FPSCR.
   163  * NB: 12 bytes
   164  */
   165 static inline void load_xf_bank( int bankreg )
   166 {
   167     NOT_r32( bankreg );
   168     SHR_imm8_r32( (21 - 6), bankreg ); // Extract bit 21 then *64 for bank size
   169     AND_imm8s_r32( 0x40, bankreg );    // Complete extraction
   170     OP(0x8D); OP(0x44+(bankreg<<3)); OP(0x28+bankreg); OP(REG_OFFSET(fr)); // LEA [ebp+bankreg+disp], bankreg
   171 }
   173 /**
   174  * Update the fr_bank pointer based on the current fpscr value.
   175  */
   176 static inline void update_fr_bank( int fpscrreg )
   177 {
   178     SHR_imm8_r32( (21 - 6), fpscrreg ); // Extract bit 21 then *64 for bank size
   179     AND_imm8s_r32( 0x40, fpscrreg );    // Complete extraction
   180     OP(0x8D); OP(0x44+(fpscrreg<<3)); OP(0x28+fpscrreg); OP(REG_OFFSET(fr)); // LEA [ebp+fpscrreg+disp], fpscrreg
   181     store_spreg( fpscrreg, REG_OFFSET(fr_bank) );
   182 }
   183 /**
   184  * Push FPUL (as a 32-bit float) onto the FPU stack
   185  */
   186 static inline void push_fpul( )
   187 {
   188     OP(0xD9); OP(0x45); OP(R_FPUL);
   189 }
   191 /**
   192  * Pop FPUL (as a 32-bit float) from the FPU stack
   193  */
   194 static inline void pop_fpul( )
   195 {
   196     OP(0xD9); OP(0x5D); OP(R_FPUL);
   197 }
   199 /**
   200  * Push a 32-bit float onto the FPU stack, with bankreg previously loaded
   201  * with the location of the current fp bank.
   202  */
   203 static inline void push_fr( int bankreg, int frm ) 
   204 {
   205     OP(0xD9); OP(0x40 + bankreg); OP((frm^1)<<2);  // FLD.S [bankreg + frm^1*4]
   206 }
   208 /**
   209  * Pop a 32-bit float from the FPU stack and store it back into the fp bank, 
   210  * with bankreg previously loaded with the location of the current fp bank.
   211  */
   212 static inline void pop_fr( int bankreg, int frm )
   213 {
   214     OP(0xD9); OP(0x58 + bankreg); OP((frm^1)<<2); // FST.S [bankreg + frm^1*4]
   215 }
   217 /**
   218  * Push a 64-bit double onto the FPU stack, with bankreg previously loaded
   219  * with the location of the current fp bank.
   220  */
   221 static inline void push_dr( int bankreg, int frm )
   222 {
   223     OP(0xDD); OP(0x40 + bankreg); OP(frm<<2); // FLD.D [bankreg + frm*4]
   224 }
   226 static inline void pop_dr( int bankreg, int frm )
   227 {
   228     OP(0xDD); OP(0x58 + bankreg); OP(frm<<2); // FST.D [bankreg + frm*4]
   229 }
   231 /**
   232  * Note: clobbers EAX to make the indirect call - this isn't usually
   233  * a problem since the callee will usually clobber it anyway.
   234  */
   235 static inline void call_func0( void *ptr )
   236 {
   237     load_imm32(R_EAX, (uint32_t)ptr);
   238     CALL_r32(R_EAX);
   239 }
   241 static inline void call_func1( void *ptr, int arg1 )
   242 {
   243     PUSH_r32(arg1);
   244     call_func0(ptr);
   245     ADD_imm8s_r32( 4, R_ESP );
   246 }
   248 static inline void call_func2( void *ptr, int arg1, int arg2 )
   249 {
   250     PUSH_r32(arg2);
   251     PUSH_r32(arg1);
   252     call_func0(ptr);
   253     ADD_imm8s_r32( 8, R_ESP );
   254 }
   256 /**
   257  * Write a double (64-bit) value into memory, with the first word in arg2a, and
   258  * the second in arg2b
   259  * NB: 30 bytes
   260  */
   261 static inline void MEM_WRITE_DOUBLE( int addr, int arg2a, int arg2b )
   262 {
   263     ADD_imm8s_r32( 4, addr );
   264     PUSH_r32(arg2b);
   265     PUSH_r32(addr);
   266     ADD_imm8s_r32( -4, addr );
   267     PUSH_r32(arg2a);
   268     PUSH_r32(addr);
   269     call_func0(sh4_write_long);
   270     ADD_imm8s_r32( 8, R_ESP );
   271     call_func0(sh4_write_long);
   272     ADD_imm8s_r32( 8, R_ESP );
   273 }
   275 /**
   276  * Read a double (64-bit) value from memory, writing the first word into arg2a
   277  * and the second into arg2b. The addr must not be in EAX
   278  * NB: 27 bytes
   279  */
   280 static inline void MEM_READ_DOUBLE( int addr, int arg2a, int arg2b )
   281 {
   282     PUSH_r32(addr);
   283     call_func0(sh4_read_long);
   284     POP_r32(addr);
   285     PUSH_r32(R_EAX);
   286     ADD_imm8s_r32( 4, addr );
   287     PUSH_r32(addr);
   288     call_func0(sh4_read_long);
   289     ADD_imm8s_r32( 4, R_ESP );
   290     MOV_r32_r32( R_EAX, arg2b );
   291     POP_r32(arg2a);
   292 }
   294 /* Exception checks - Note that all exception checks will clobber EAX */
   295 static void check_priv( )
   296 {
   297     if( !sh4_x86.priv_checked ) {
   298 	sh4_x86.priv_checked = TRUE;
   299 	load_spreg( R_EAX, R_SR );
   300 	AND_imm32_r32( SR_MD, R_EAX );
   301 	if( sh4_x86.in_delay_slot ) {
   302 	    JE_exit( EXIT_SLOT_ILLEGAL );
   303 	} else {
   304 	    JE_exit( EXIT_ILLEGAL );
   305 	}
   306     }
   307 }
   309 static void check_fpuen( )
   310 {
   311     if( !sh4_x86.fpuen_checked ) {
   312 	sh4_x86.fpuen_checked = TRUE;
   313 	load_spreg( R_EAX, R_SR );
   314 	AND_imm32_r32( SR_FD, R_EAX );
   315 	if( sh4_x86.in_delay_slot ) {
   316 	    JNE_exit(EXIT_SLOT_FPU_DISABLED);
   317 	} else {
   318 	    JNE_exit(EXIT_FPU_DISABLED);
   319 	}
   320     }
   321 }
   323 static void check_ralign16( int x86reg )
   324 {
   325     TEST_imm32_r32( 0x00000001, x86reg );
   326     JNE_exit(EXIT_DATA_ADDR_READ);
   327 }
   329 static void check_walign16( int x86reg )
   330 {
   331     TEST_imm32_r32( 0x00000001, x86reg );
   332     JNE_exit(EXIT_DATA_ADDR_WRITE);
   333 }
   335 static void check_ralign32( int x86reg )
   336 {
   337     TEST_imm32_r32( 0x00000003, x86reg );
   338     JNE_exit(EXIT_DATA_ADDR_READ);
   339 }
   340 static void check_walign32( int x86reg )
   341 {
   342     TEST_imm32_r32( 0x00000003, x86reg );
   343     JNE_exit(EXIT_DATA_ADDR_WRITE);
   344 }
   346 #define UNDEF()
   347 #define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
   348 #define MEM_READ_BYTE( addr_reg, value_reg ) call_func1(sh4_read_byte, addr_reg ); MEM_RESULT(value_reg)
   349 #define MEM_READ_WORD( addr_reg, value_reg ) call_func1(sh4_read_word, addr_reg ); MEM_RESULT(value_reg)
   350 #define MEM_READ_LONG( addr_reg, value_reg ) call_func1(sh4_read_long, addr_reg ); MEM_RESULT(value_reg)
   351 #define MEM_WRITE_BYTE( addr_reg, value_reg ) call_func2(sh4_write_byte, addr_reg, value_reg)
   352 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
   353 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
   355 #define SLOTILLEGAL() JMP_exit(EXIT_SLOT_ILLEGAL); sh4_x86.in_delay_slot = FALSE; return 1;
   359 /**
   360  * Emit the 'start of block' assembly. Sets up the stack frame and save
   361  * SI/DI as required
   362  */
   363 void sh4_translate_begin_block( sh4addr_t pc ) 
   364 {
   365     PUSH_r32(R_EBP);
   366     /* mov &sh4r, ebp */
   367     load_imm32( R_EBP, (uint32_t)&sh4r );
   368     PUSH_r32(R_ESI);
   369     XOR_r32_r32(R_ESI, R_ESI);
   371     sh4_x86.in_delay_slot = FALSE;
   372     sh4_x86.priv_checked = FALSE;
   373     sh4_x86.fpuen_checked = FALSE;
   374     sh4_x86.backpatch_posn = 0;
   375     sh4_x86.block_start_pc = pc;
   376 }
   378 /**
   379  * Exit the block to an absolute PC
   380  * Bytes: 30
   381  */
   382 void exit_block( sh4addr_t pc, sh4addr_t endpc )
   383 {
   384     load_imm32( R_ECX, pc );                            // 5
   385     store_spreg( R_ECX, REG_OFFSET(pc) );               // 3
   386     MOV_moff32_EAX( (uint32_t)xlat_get_lut_entry(pc) ); // 5
   387     AND_imm8s_r32( 0xFC, R_EAX ); // 3
   388     load_imm32( R_ECX, ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
   389     ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) );     // 6
   390     POP_r32(R_ESI);
   391     POP_r32(R_EBP);
   392     RET();
   393 }
   395 /**
   396  * Exit the block with sh4r.pc already written
   397  * Bytes: 16
   398  */
   399 void exit_block_pcset( pc )
   400 {
   401     XOR_r32_r32( R_EAX, R_EAX );                       // 2
   402     load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
   403     ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) );    // 6
   404     POP_r32(R_ESI);
   405     POP_r32(R_EBP);
   406     RET();
   407 }
   409 /**
   410  * Write the block trailer (exception handling block)
   411  */
   412 void sh4_translate_end_block( sh4addr_t pc ) {
   413     if( sh4_x86.backpatch_posn != 0 ) {
   414 	uint8_t *end_ptr = xlat_output;
   415 	// Exception termination. Jump block for various exception codes:
   416 	PUSH_imm32( EXC_DATA_ADDR_READ );
   417 	JMP_rel8( 33, target1 );
   418 	PUSH_imm32( EXC_DATA_ADDR_WRITE );
   419 	JMP_rel8( 26, target2 );
   420 	PUSH_imm32( EXC_ILLEGAL );
   421 	JMP_rel8( 19, target3 );
   422 	PUSH_imm32( EXC_SLOT_ILLEGAL ); 
   423 	JMP_rel8( 12, target4 );
   424 	PUSH_imm32( EXC_FPU_DISABLED ); 
   425 	JMP_rel8( 5, target5 );
   426 	PUSH_imm32( EXC_SLOT_FPU_DISABLED );
   427 	// target
   428 	JMP_TARGET(target1);
   429 	JMP_TARGET(target2);
   430 	JMP_TARGET(target3);
   431 	JMP_TARGET(target4);
   432 	JMP_TARGET(target5);
   433 	load_spreg( R_ECX, REG_OFFSET(pc) );
   434 	ADD_r32_r32( R_ESI, R_ECX );
   435 	ADD_r32_r32( R_ESI, R_ECX );
   436 	store_spreg( R_ECX, REG_OFFSET(pc) );
   437 	MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );
   438 	load_spreg( R_ECX, REG_OFFSET(slice_cycle) );
   439 	MUL_r32( R_ESI );
   440 	ADD_r32_r32( R_EAX, R_ECX );
   441 	store_spreg( R_ECX, REG_OFFSET(slice_cycle) );
   443 	load_imm32( R_EAX, (uint32_t)sh4_raise_exception ); // 6
   444 	CALL_r32( R_EAX ); // 2
   445 	ADD_imm8s_r32( 4, R_ESP );
   446 	XOR_r32_r32( R_EAX, R_EAX );
   447 	POP_r32(R_ESI);
   448 	POP_r32(R_EBP);
   449 	RET();
   451 	sh4_x86_do_backpatch( end_ptr );
   452     }
   454 }
   457 extern uint16_t *sh4_icache;
   458 extern uint32_t sh4_icache_addr;
   460 /**
   461  * Translate a single instruction. Delayed branches are handled specially
   462  * by translating both branch and delayed instruction as a single unit (as
   463  * 
   464  *
   465  * @return true if the instruction marks the end of a basic block
   466  * (eg a branch or 
   467  */
   468 uint32_t sh4_x86_translate_instruction( sh4addr_t pc )
   469 {
   470     uint32_t ir;
   471     /* Read instruction */
   472     uint32_t pageaddr = pc >> 12;
   473     if( sh4_icache != NULL && pageaddr == sh4_icache_addr ) {
   474 	ir = sh4_icache[(pc&0xFFF)>>1];
   475     } else {
   476 	sh4_icache = (uint16_t *)mem_get_page(pc);
   477 	if( ((uint32_t)sh4_icache) < MAX_IO_REGIONS ) {
   478 	    /* If someone's actually been so daft as to try to execute out of an IO
   479 	     * region, fallback on the full-blown memory read
   480 	     */
   481 	    sh4_icache = NULL;
   482 	    ir = sh4_read_word(pc);
   483 	} else {
   484 	    sh4_icache_addr = pageaddr;
   485 	    ir = sh4_icache[(pc&0xFFF)>>1];
   486 	}
   487     }
   489 %%
   490 /* ALU operations */
   491 ADD Rm, Rn {:
   492     load_reg( R_EAX, Rm );
   493     load_reg( R_ECX, Rn );
   494     ADD_r32_r32( R_EAX, R_ECX );
   495     store_reg( R_ECX, Rn );
   496 :}
   497 ADD #imm, Rn {:  
   498     load_reg( R_EAX, Rn );
   499     ADD_imm8s_r32( imm, R_EAX );
   500     store_reg( R_EAX, Rn );
   501 :}
   502 ADDC Rm, Rn {:
   503     load_reg( R_EAX, Rm );
   504     load_reg( R_ECX, Rn );
   505     LDC_t();
   506     ADC_r32_r32( R_EAX, R_ECX );
   507     store_reg( R_ECX, Rn );
   508     SETC_t();
   509 :}
   510 ADDV Rm, Rn {:
   511     load_reg( R_EAX, Rm );
   512     load_reg( R_ECX, Rn );
   513     ADD_r32_r32( R_EAX, R_ECX );
   514     store_reg( R_ECX, Rn );
   515     SETO_t();
   516 :}
   517 AND Rm, Rn {:
   518     load_reg( R_EAX, Rm );
   519     load_reg( R_ECX, Rn );
   520     AND_r32_r32( R_EAX, R_ECX );
   521     store_reg( R_ECX, Rn );
   522 :}
   523 AND #imm, R0 {:  
   524     load_reg( R_EAX, 0 );
   525     AND_imm32_r32(imm, R_EAX); 
   526     store_reg( R_EAX, 0 );
   527 :}
   528 AND.B #imm, @(R0, GBR) {: 
   529     load_reg( R_EAX, 0 );
   530     load_spreg( R_ECX, R_GBR );
   531     ADD_r32_r32( R_EAX, R_ECX );
   532     PUSH_r32(R_ECX);
   533     call_func0(sh4_read_byte);
   534     POP_r32(R_ECX);
   535     AND_imm32_r32(imm, R_EAX );
   536     MEM_WRITE_BYTE( R_ECX, R_EAX );
   537 :}
   538 CMP/EQ Rm, Rn {:  
   539     load_reg( R_EAX, Rm );
   540     load_reg( R_ECX, Rn );
   541     CMP_r32_r32( R_EAX, R_ECX );
   542     SETE_t();
   543 :}
   544 CMP/EQ #imm, R0 {:  
   545     load_reg( R_EAX, 0 );
   546     CMP_imm8s_r32(imm, R_EAX);
   547     SETE_t();
   548 :}
   549 CMP/GE Rm, Rn {:  
   550     load_reg( R_EAX, Rm );
   551     load_reg( R_ECX, Rn );
   552     CMP_r32_r32( R_EAX, R_ECX );
   553     SETGE_t();
   554 :}
   555 CMP/GT Rm, Rn {: 
   556     load_reg( R_EAX, Rm );
   557     load_reg( R_ECX, Rn );
   558     CMP_r32_r32( R_EAX, R_ECX );
   559     SETG_t();
   560 :}
   561 CMP/HI Rm, Rn {:  
   562     load_reg( R_EAX, Rm );
   563     load_reg( R_ECX, Rn );
   564     CMP_r32_r32( R_EAX, R_ECX );
   565     SETA_t();
   566 :}
   567 CMP/HS Rm, Rn {: 
   568     load_reg( R_EAX, Rm );
   569     load_reg( R_ECX, Rn );
   570     CMP_r32_r32( R_EAX, R_ECX );
   571     SETAE_t();
   572  :}
   573 CMP/PL Rn {: 
   574     load_reg( R_EAX, Rn );
   575     CMP_imm8s_r32( 0, R_EAX );
   576     SETG_t();
   577 :}
   578 CMP/PZ Rn {:  
   579     load_reg( R_EAX, Rn );
   580     CMP_imm8s_r32( 0, R_EAX );
   581     SETGE_t();
   582 :}
   583 CMP/STR Rm, Rn {:  
   584     load_reg( R_EAX, Rm );
   585     load_reg( R_ECX, Rn );
   586     XOR_r32_r32( R_ECX, R_EAX );
   587     TEST_r8_r8( R_AL, R_AL );
   588     JE_rel8(13, target1);
   589     TEST_r8_r8( R_AH, R_AH ); // 2
   590     JE_rel8(9, target2);
   591     SHR_imm8_r32( 16, R_EAX ); // 3
   592     TEST_r8_r8( R_AL, R_AL ); // 2
   593     JE_rel8(2, target3);
   594     TEST_r8_r8( R_AH, R_AH ); // 2
   595     JMP_TARGET(target1);
   596     JMP_TARGET(target2);
   597     JMP_TARGET(target3);
   598     SETE_t();
   599 :}
   600 DIV0S Rm, Rn {:
   601     load_reg( R_EAX, Rm );
   602     load_reg( R_ECX, Rn );
   603     SHR_imm8_r32( 31, R_EAX );
   604     SHR_imm8_r32( 31, R_ECX );
   605     store_spreg( R_EAX, R_M );
   606     store_spreg( R_ECX, R_Q );
   607     CMP_r32_r32( R_EAX, R_ECX );
   608     SETNE_t();
   609 :}
   610 DIV0U {:  
   611     XOR_r32_r32( R_EAX, R_EAX );
   612     store_spreg( R_EAX, R_Q );
   613     store_spreg( R_EAX, R_M );
   614     store_spreg( R_EAX, R_T );
   615 :}
   616 DIV1 Rm, Rn {:
   617     load_spreg( R_ECX, R_M );
   618     load_reg( R_EAX, Rn );
   619     LDC_t();
   620     RCL1_r32( R_EAX );
   621     SETC_r8( R_DL ); // Q'
   622     CMP_sh4r_r32( R_Q, R_ECX );
   623     JE_rel8(5, mqequal);
   624     ADD_sh4r_r32( REG_OFFSET(r[Rm]), R_EAX );
   625     JMP_rel8(3, end);
   626     JMP_TARGET(mqequal);
   627     SUB_sh4r_r32( REG_OFFSET(r[Rm]), R_EAX );
   628     JMP_TARGET(end);
   629     store_reg( R_EAX, Rn ); // Done with Rn now
   630     SETC_r8(R_AL); // tmp1
   631     XOR_r8_r8( R_DL, R_AL ); // Q' = Q ^ tmp1
   632     XOR_r8_r8( R_AL, R_CL ); // Q'' = Q' ^ M
   633     store_spreg( R_ECX, R_Q );
   634     XOR_imm8s_r32( 1, R_AL );   // T = !Q'
   635     MOVZX_r8_r32( R_AL, R_EAX );
   636     store_spreg( R_EAX, R_T );
   637 :}
   638 DMULS.L Rm, Rn {:  
   639     load_reg( R_EAX, Rm );
   640     load_reg( R_ECX, Rn );
   641     IMUL_r32(R_ECX);
   642     store_spreg( R_EDX, R_MACH );
   643     store_spreg( R_EAX, R_MACL );
   644 :}
   645 DMULU.L Rm, Rn {:  
   646     load_reg( R_EAX, Rm );
   647     load_reg( R_ECX, Rn );
   648     MUL_r32(R_ECX);
   649     store_spreg( R_EDX, R_MACH );
   650     store_spreg( R_EAX, R_MACL );    
   651 :}
   652 DT Rn {:  
   653     load_reg( R_EAX, Rn );
   654     ADD_imm8s_r32( -1, R_EAX );
   655     store_reg( R_EAX, Rn );
   656     SETE_t();
   657 :}
   658 EXTS.B Rm, Rn {:  
   659     load_reg( R_EAX, Rm );
   660     MOVSX_r8_r32( R_EAX, R_EAX );
   661     store_reg( R_EAX, Rn );
   662 :}
   663 EXTS.W Rm, Rn {:  
   664     load_reg( R_EAX, Rm );
   665     MOVSX_r16_r32( R_EAX, R_EAX );
   666     store_reg( R_EAX, Rn );
   667 :}
   668 EXTU.B Rm, Rn {:  
   669     load_reg( R_EAX, Rm );
   670     MOVZX_r8_r32( R_EAX, R_EAX );
   671     store_reg( R_EAX, Rn );
   672 :}
   673 EXTU.W Rm, Rn {:  
   674     load_reg( R_EAX, Rm );
   675     MOVZX_r16_r32( R_EAX, R_EAX );
   676     store_reg( R_EAX, Rn );
   677 :}
   678 MAC.L @Rm+, @Rn+ {:  
   679     load_reg( R_ECX, Rm );
   680     check_ralign32( R_ECX );
   681     load_reg( R_ECX, Rn );
   682     check_ralign32( R_ECX );
   683     ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rn]) );
   684     MEM_READ_LONG( R_ECX, R_EAX );
   685     PUSH_r32( R_EAX );
   686     load_reg( R_ECX, Rm );
   687     ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
   688     MEM_READ_LONG( R_ECX, R_EAX );
   689     POP_r32( R_ECX );
   690     IMUL_r32( R_ECX );
   691     ADD_r32_sh4r( R_EAX, R_MACL );
   692     ADC_r32_sh4r( R_EDX, R_MACH );
   694     load_spreg( R_ECX, R_S );
   695     TEST_r32_r32(R_ECX, R_ECX);
   696     JE_rel8( 7, nosat );
   697     call_func0( signsat48 );
   698     JMP_TARGET( nosat );
   699 :}
   700 MAC.W @Rm+, @Rn+ {:  
   701     load_reg( R_ECX, Rm );
   702     check_ralign16( R_ECX );
   703     load_reg( R_ECX, Rn );
   704     check_ralign16( R_ECX );
   705     ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rn]) );
   706     MEM_READ_WORD( R_ECX, R_EAX );
   707     PUSH_r32( R_EAX );
   708     load_reg( R_ECX, Rm );
   709     ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rm]) );
   710     MEM_READ_WORD( R_ECX, R_EAX );
   711     POP_r32( R_ECX );
   712     IMUL_r32( R_ECX );
   714     load_spreg( R_ECX, R_S );
   715     TEST_r32_r32( R_ECX, R_ECX );
   716     JE_rel8( 47, nosat );
   718     ADD_r32_sh4r( R_EAX, R_MACL );  // 6
   719     JNO_rel8( 51, end );            // 2
   720     load_imm32( R_EDX, 1 );         // 5
   721     store_spreg( R_EDX, R_MACH );   // 6
   722     JS_rel8( 13, positive );        // 2
   723     load_imm32( R_EAX, 0x80000000 );// 5
   724     store_spreg( R_EAX, R_MACL );   // 6
   725     JMP_rel8( 25, end2 );           // 2
   727     JMP_TARGET(positive);
   728     load_imm32( R_EAX, 0x7FFFFFFF );// 5
   729     store_spreg( R_EAX, R_MACL );   // 6
   730     JMP_rel8( 12, end3);            // 2
   732     JMP_TARGET(nosat);
   733     ADD_r32_sh4r( R_EAX, R_MACL );  // 6
   734     ADC_r32_sh4r( R_EDX, R_MACH );  // 6
   735     JMP_TARGET(end);
   736     JMP_TARGET(end2);
   737     JMP_TARGET(end3);
   738 :}
   739 MOVT Rn {:  
   740     load_spreg( R_EAX, R_T );
   741     store_reg( R_EAX, Rn );
   742 :}
   743 MUL.L Rm, Rn {:  
   744     load_reg( R_EAX, Rm );
   745     load_reg( R_ECX, Rn );
   746     MUL_r32( R_ECX );
   747     store_spreg( R_EAX, R_MACL );
   748 :}
   749 MULS.W Rm, Rn {:
   750     load_reg16s( R_EAX, Rm );
   751     load_reg16s( R_ECX, Rn );
   752     MUL_r32( R_ECX );
   753     store_spreg( R_EAX, R_MACL );
   754 :}
   755 MULU.W Rm, Rn {:  
   756     load_reg16u( R_EAX, Rm );
   757     load_reg16u( R_ECX, Rn );
   758     MUL_r32( R_ECX );
   759     store_spreg( R_EAX, R_MACL );
   760 :}
   761 NEG Rm, Rn {:
   762     load_reg( R_EAX, Rm );
   763     NEG_r32( R_EAX );
   764     store_reg( R_EAX, Rn );
   765 :}
   766 NEGC Rm, Rn {:  
   767     load_reg( R_EAX, Rm );
   768     XOR_r32_r32( R_ECX, R_ECX );
   769     LDC_t();
   770     SBB_r32_r32( R_EAX, R_ECX );
   771     store_reg( R_ECX, Rn );
   772     SETC_t();
   773 :}
   774 NOT Rm, Rn {:  
   775     load_reg( R_EAX, Rm );
   776     NOT_r32( R_EAX );
   777     store_reg( R_EAX, Rn );
   778 :}
   779 OR Rm, Rn {:  
   780     load_reg( R_EAX, Rm );
   781     load_reg( R_ECX, Rn );
   782     OR_r32_r32( R_EAX, R_ECX );
   783     store_reg( R_ECX, Rn );
   784 :}
   785 OR #imm, R0 {:
   786     load_reg( R_EAX, 0 );
   787     OR_imm32_r32(imm, R_EAX);
   788     store_reg( R_EAX, 0 );
   789 :}
   790 OR.B #imm, @(R0, GBR) {:  
   791     load_reg( R_EAX, 0 );
   792     load_spreg( R_ECX, R_GBR );
   793     ADD_r32_r32( R_EAX, R_ECX );
   794     PUSH_r32(R_ECX);
   795     call_func0(sh4_read_byte);
   796     POP_r32(R_ECX);
   797     OR_imm32_r32(imm, R_EAX );
   798     MEM_WRITE_BYTE( R_ECX, R_EAX );
   799 :}
   800 ROTCL Rn {:
   801     load_reg( R_EAX, Rn );
   802     LDC_t();
   803     RCL1_r32( R_EAX );
   804     store_reg( R_EAX, Rn );
   805     SETC_t();
   806 :}
   807 ROTCR Rn {:  
   808     load_reg( R_EAX, Rn );
   809     LDC_t();
   810     RCR1_r32( R_EAX );
   811     store_reg( R_EAX, Rn );
   812     SETC_t();
   813 :}
   814 ROTL Rn {:  
   815     load_reg( R_EAX, Rn );
   816     ROL1_r32( R_EAX );
   817     store_reg( R_EAX, Rn );
   818     SETC_t();
   819 :}
   820 ROTR Rn {:  
   821     load_reg( R_EAX, Rn );
   822     ROR1_r32( R_EAX );
   823     store_reg( R_EAX, Rn );
   824     SETC_t();
   825 :}
   826 SHAD Rm, Rn {:
   827     /* Annoyingly enough, not directly convertible */
   828     load_reg( R_EAX, Rn );
   829     load_reg( R_ECX, Rm );
   830     CMP_imm32_r32( 0, R_ECX );
   831     JGE_rel8(16, doshl);
   833     NEG_r32( R_ECX );      // 2
   834     AND_imm8_r8( 0x1F, R_CL ); // 3
   835     JE_rel8( 4, emptysar);     // 2
   836     SAR_r32_CL( R_EAX );       // 2
   837     JMP_rel8(10, end);          // 2
   839     JMP_TARGET(emptysar);
   840     SAR_imm8_r32(31, R_EAX );  // 3
   841     JMP_rel8(5, end2);
   843     JMP_TARGET(doshl);
   844     AND_imm8_r8( 0x1F, R_CL ); // 3
   845     SHL_r32_CL( R_EAX );       // 2
   846     JMP_TARGET(end);
   847     JMP_TARGET(end2);
   848     store_reg( R_EAX, Rn );
   849 :}
   850 SHLD Rm, Rn {:  
   851     load_reg( R_EAX, Rn );
   852     load_reg( R_ECX, Rm );
   853     CMP_imm32_r32( 0, R_ECX );
   854     JGE_rel8(15, doshl);
   856     NEG_r32( R_ECX );      // 2
   857     AND_imm8_r8( 0x1F, R_CL ); // 3
   858     JE_rel8( 4, emptyshr );
   859     SHR_r32_CL( R_EAX );       // 2
   860     JMP_rel8(9, end);          // 2
   862     JMP_TARGET(emptyshr);
   863     XOR_r32_r32( R_EAX, R_EAX );
   864     JMP_rel8(5, end2);
   866     JMP_TARGET(doshl);
   867     AND_imm8_r8( 0x1F, R_CL ); // 3
   868     SHL_r32_CL( R_EAX );       // 2
   869     JMP_TARGET(end);
   870     JMP_TARGET(end2);
   871     store_reg( R_EAX, Rn );
   872 :}
   873 SHAL Rn {: 
   874     load_reg( R_EAX, Rn );
   875     SHL1_r32( R_EAX );
   876     SETC_t();
   877     store_reg( R_EAX, Rn );
   878 :}
   879 SHAR Rn {:  
   880     load_reg( R_EAX, Rn );
   881     SAR1_r32( R_EAX );
   882     SETC_t();
   883     store_reg( R_EAX, Rn );
   884 :}
   885 SHLL Rn {:  
   886     load_reg( R_EAX, Rn );
   887     SHL1_r32( R_EAX );
   888     SETC_t();
   889     store_reg( R_EAX, Rn );
   890 :}
   891 SHLL2 Rn {:
   892     load_reg( R_EAX, Rn );
   893     SHL_imm8_r32( 2, R_EAX );
   894     store_reg( R_EAX, Rn );
   895 :}
   896 SHLL8 Rn {:  
   897     load_reg( R_EAX, Rn );
   898     SHL_imm8_r32( 8, R_EAX );
   899     store_reg( R_EAX, Rn );
   900 :}
   901 SHLL16 Rn {:  
   902     load_reg( R_EAX, Rn );
   903     SHL_imm8_r32( 16, R_EAX );
   904     store_reg( R_EAX, Rn );
   905 :}
   906 SHLR Rn {:  
   907     load_reg( R_EAX, Rn );
   908     SHR1_r32( R_EAX );
   909     SETC_t();
   910     store_reg( R_EAX, Rn );
   911 :}
   912 SHLR2 Rn {:  
   913     load_reg( R_EAX, Rn );
   914     SHR_imm8_r32( 2, R_EAX );
   915     store_reg( R_EAX, Rn );
   916 :}
   917 SHLR8 Rn {:  
   918     load_reg( R_EAX, Rn );
   919     SHR_imm8_r32( 8, R_EAX );
   920     store_reg( R_EAX, Rn );
   921 :}
   922 SHLR16 Rn {:  
   923     load_reg( R_EAX, Rn );
   924     SHR_imm8_r32( 16, R_EAX );
   925     store_reg( R_EAX, Rn );
   926 :}
   927 SUB Rm, Rn {:  
   928     load_reg( R_EAX, Rm );
   929     load_reg( R_ECX, Rn );
   930     SUB_r32_r32( R_EAX, R_ECX );
   931     store_reg( R_ECX, Rn );
   932 :}
   933 SUBC Rm, Rn {:  
   934     load_reg( R_EAX, Rm );
   935     load_reg( R_ECX, Rn );
   936     LDC_t();
   937     SBB_r32_r32( R_EAX, R_ECX );
   938     store_reg( R_ECX, Rn );
   939     SETC_t();
   940 :}
   941 SUBV Rm, Rn {:  
   942     load_reg( R_EAX, Rm );
   943     load_reg( R_ECX, Rn );
   944     SUB_r32_r32( R_EAX, R_ECX );
   945     store_reg( R_ECX, Rn );
   946     SETO_t();
   947 :}
   948 SWAP.B Rm, Rn {:  
   949     load_reg( R_EAX, Rm );
   950     XCHG_r8_r8( R_AL, R_AH );
   951     store_reg( R_EAX, Rn );
   952 :}
   953 SWAP.W Rm, Rn {:  
   954     load_reg( R_EAX, Rm );
   955     MOV_r32_r32( R_EAX, R_ECX );
   956     SHL_imm8_r32( 16, R_ECX );
   957     SHR_imm8_r32( 16, R_EAX );
   958     OR_r32_r32( R_EAX, R_ECX );
   959     store_reg( R_ECX, Rn );
   960 :}
   961 TAS.B @Rn {:  
   962     load_reg( R_ECX, Rn );
   963     MEM_READ_BYTE( R_ECX, R_EAX );
   964     TEST_r8_r8( R_AL, R_AL );
   965     SETE_t();
   966     OR_imm8_r8( 0x80, R_AL );
   967     load_reg( R_ECX, Rn );
   968     MEM_WRITE_BYTE( R_ECX, R_EAX );
   969 :}
   970 TST Rm, Rn {:  
   971     load_reg( R_EAX, Rm );
   972     load_reg( R_ECX, Rn );
   973     TEST_r32_r32( R_EAX, R_ECX );
   974     SETE_t();
   975 :}
   976 TST #imm, R0 {:  
   977     load_reg( R_EAX, 0 );
   978     TEST_imm32_r32( imm, R_EAX );
   979     SETE_t();
   980 :}
   981 TST.B #imm, @(R0, GBR) {:  
   982     load_reg( R_EAX, 0);
   983     load_reg( R_ECX, R_GBR);
   984     ADD_r32_r32( R_EAX, R_ECX );
   985     MEM_READ_BYTE( R_ECX, R_EAX );
   986     TEST_imm8_r8( imm, R_AL );
   987     SETE_t();
   988 :}
   989 XOR Rm, Rn {:  
   990     load_reg( R_EAX, Rm );
   991     load_reg( R_ECX, Rn );
   992     XOR_r32_r32( R_EAX, R_ECX );
   993     store_reg( R_ECX, Rn );
   994 :}
   995 XOR #imm, R0 {:  
   996     load_reg( R_EAX, 0 );
   997     XOR_imm32_r32( imm, R_EAX );
   998     store_reg( R_EAX, 0 );
   999 :}
  1000 XOR.B #imm, @(R0, GBR) {:  
  1001     load_reg( R_EAX, 0 );
  1002     load_spreg( R_ECX, R_GBR );
  1003     ADD_r32_r32( R_EAX, R_ECX );
  1004     PUSH_r32(R_ECX);
  1005     call_func0(sh4_read_byte);
  1006     POP_r32(R_ECX);
  1007     XOR_imm32_r32( imm, R_EAX );
  1008     MEM_WRITE_BYTE( R_ECX, R_EAX );
  1009 :}
  1010 XTRCT Rm, Rn {:
  1011     load_reg( R_EAX, Rm );
  1012     load_reg( R_ECX, Rn );
  1013     SHL_imm8_r32( 16, R_EAX );
  1014     SHR_imm8_r32( 16, R_ECX );
  1015     OR_r32_r32( R_EAX, R_ECX );
  1016     store_reg( R_ECX, Rn );
  1017 :}
  1019 /* Data move instructions */
  1020 MOV Rm, Rn {:  
  1021     load_reg( R_EAX, Rm );
  1022     store_reg( R_EAX, Rn );
  1023 :}
  1024 MOV #imm, Rn {:  
  1025     load_imm32( R_EAX, imm );
  1026     store_reg( R_EAX, Rn );
  1027 :}
  1028 MOV.B Rm, @Rn {:  
  1029     load_reg( R_EAX, Rm );
  1030     load_reg( R_ECX, Rn );
  1031     MEM_WRITE_BYTE( R_ECX, R_EAX );
  1032 :}
  1033 MOV.B Rm, @-Rn {:  
  1034     load_reg( R_EAX, Rm );
  1035     load_reg( R_ECX, Rn );
  1036     ADD_imm8s_r32( -1, R_ECX );
  1037     store_reg( R_ECX, Rn );
  1038     MEM_WRITE_BYTE( R_ECX, R_EAX );
  1039 :}
  1040 MOV.B Rm, @(R0, Rn) {:  
  1041     load_reg( R_EAX, 0 );
  1042     load_reg( R_ECX, Rn );
  1043     ADD_r32_r32( R_EAX, R_ECX );
  1044     load_reg( R_EAX, Rm );
  1045     MEM_WRITE_BYTE( R_ECX, R_EAX );
  1046 :}
  1047 MOV.B R0, @(disp, GBR) {:  
  1048     load_reg( R_EAX, 0 );
  1049     load_spreg( R_ECX, R_GBR );
  1050     ADD_imm32_r32( disp, R_ECX );
  1051     MEM_WRITE_BYTE( R_ECX, R_EAX );
  1052 :}
  1053 MOV.B R0, @(disp, Rn) {:  
  1054     load_reg( R_EAX, 0 );
  1055     load_reg( R_ECX, Rn );
  1056     ADD_imm32_r32( disp, R_ECX );
  1057     MEM_WRITE_BYTE( R_ECX, R_EAX );
  1058 :}
  1059 MOV.B @Rm, Rn {:  
  1060     load_reg( R_ECX, Rm );
  1061     MEM_READ_BYTE( R_ECX, R_EAX );
  1062     store_reg( R_EAX, Rn );
  1063 :}
  1064 MOV.B @Rm+, Rn {:  
  1065     load_reg( R_ECX, Rm );
  1066     MOV_r32_r32( R_ECX, R_EAX );
  1067     ADD_imm8s_r32( 1, R_EAX );
  1068     store_reg( R_EAX, Rm );
  1069     MEM_READ_BYTE( R_ECX, R_EAX );
  1070     store_reg( R_EAX, Rn );
  1071 :}
  1072 MOV.B @(R0, Rm), Rn {:  
  1073     load_reg( R_EAX, 0 );
  1074     load_reg( R_ECX, Rm );
  1075     ADD_r32_r32( R_EAX, R_ECX );
  1076     MEM_READ_BYTE( R_ECX, R_EAX );
  1077     store_reg( R_EAX, Rn );
  1078 :}
  1079 MOV.B @(disp, GBR), R0 {:  
  1080     load_spreg( R_ECX, R_GBR );
  1081     ADD_imm32_r32( disp, R_ECX );
  1082     MEM_READ_BYTE( R_ECX, R_EAX );
  1083     store_reg( R_EAX, 0 );
  1084 :}
  1085 MOV.B @(disp, Rm), R0 {:  
  1086     load_reg( R_ECX, Rm );
  1087     ADD_imm32_r32( disp, R_ECX );
  1088     MEM_READ_BYTE( R_ECX, R_EAX );
  1089     store_reg( R_EAX, 0 );
  1090 :}
  1091 MOV.L Rm, @Rn {:
  1092     load_reg( R_EAX, Rm );
  1093     load_reg( R_ECX, Rn );
  1094     check_walign32(R_ECX);
  1095     MEM_WRITE_LONG( R_ECX, R_EAX );
  1096 :}
  1097 MOV.L Rm, @-Rn {:  
  1098     load_reg( R_EAX, Rm );
  1099     load_reg( R_ECX, Rn );
  1100     check_walign32( R_ECX );
  1101     ADD_imm8s_r32( -4, R_ECX );
  1102     store_reg( R_ECX, Rn );
  1103     MEM_WRITE_LONG( R_ECX, R_EAX );
  1104 :}
  1105 MOV.L Rm, @(R0, Rn) {:  
  1106     load_reg( R_EAX, 0 );
  1107     load_reg( R_ECX, Rn );
  1108     ADD_r32_r32( R_EAX, R_ECX );
  1109     check_walign32( R_ECX );
  1110     load_reg( R_EAX, Rm );
  1111     MEM_WRITE_LONG( R_ECX, R_EAX );
  1112 :}
  1113 MOV.L R0, @(disp, GBR) {:  
  1114     load_spreg( R_ECX, R_GBR );
  1115     load_reg( R_EAX, 0 );
  1116     ADD_imm32_r32( disp, R_ECX );
  1117     check_walign32( R_ECX );
  1118     MEM_WRITE_LONG( R_ECX, R_EAX );
  1119 :}
  1120 MOV.L Rm, @(disp, Rn) {:  
  1121     load_reg( R_ECX, Rn );
  1122     load_reg( R_EAX, Rm );
  1123     ADD_imm32_r32( disp, R_ECX );
  1124     check_walign32( R_ECX );
  1125     MEM_WRITE_LONG( R_ECX, R_EAX );
  1126 :}
  1127 MOV.L @Rm, Rn {:  
  1128     load_reg( R_ECX, Rm );
  1129     check_ralign32( R_ECX );
  1130     MEM_READ_LONG( R_ECX, R_EAX );
  1131     store_reg( R_EAX, Rn );
  1132 :}
  1133 MOV.L @Rm+, Rn {:  
  1134     load_reg( R_EAX, Rm );
  1135     check_ralign32( R_EAX );
  1136     MOV_r32_r32( R_EAX, R_ECX );
  1137     ADD_imm8s_r32( 4, R_EAX );
  1138     store_reg( R_EAX, Rm );
  1139     MEM_READ_LONG( R_ECX, R_EAX );
  1140     store_reg( R_EAX, Rn );
  1141 :}
  1142 MOV.L @(R0, Rm), Rn {:  
  1143     load_reg( R_EAX, 0 );
  1144     load_reg( R_ECX, Rm );
  1145     ADD_r32_r32( R_EAX, R_ECX );
  1146     check_ralign32( R_ECX );
  1147     MEM_READ_LONG( R_ECX, R_EAX );
  1148     store_reg( R_EAX, Rn );
  1149 :}
  1150 MOV.L @(disp, GBR), R0 {:
  1151     load_spreg( R_ECX, R_GBR );
  1152     ADD_imm32_r32( disp, R_ECX );
  1153     check_ralign32( R_ECX );
  1154     MEM_READ_LONG( R_ECX, R_EAX );
  1155     store_reg( R_EAX, 0 );
  1156 :}
  1157 MOV.L @(disp, PC), Rn {:  
  1158     if( sh4_x86.in_delay_slot ) {
  1159 	SLOTILLEGAL();
  1160     } else {
  1161 	uint32_t target = (pc & 0xFFFFFFFC) + disp + 4;
  1162 	char *ptr = mem_get_region(target);
  1163 	if( ptr != NULL ) {
  1164 	    MOV_moff32_EAX( (uint32_t)ptr );
  1165 	} else {
  1166 	    load_imm32( R_ECX, target );
  1167 	    MEM_READ_LONG( R_ECX, R_EAX );
  1169 	store_reg( R_EAX, Rn );
  1171 :}
  1172 MOV.L @(disp, Rm), Rn {:  
  1173     load_reg( R_ECX, Rm );
  1174     ADD_imm8s_r32( disp, R_ECX );
  1175     check_ralign32( R_ECX );
  1176     MEM_READ_LONG( R_ECX, R_EAX );
  1177     store_reg( R_EAX, Rn );
  1178 :}
  1179 MOV.W Rm, @Rn {:  
  1180     load_reg( R_ECX, Rn );
  1181     check_walign16( R_ECX );
  1182     load_reg( R_EAX, Rm );
  1183     MEM_WRITE_WORD( R_ECX, R_EAX );
  1184 :}
  1185 MOV.W Rm, @-Rn {:  
  1186     load_reg( R_ECX, Rn );
  1187     check_walign16( R_ECX );
  1188     load_reg( R_EAX, Rm );
  1189     ADD_imm8s_r32( -2, R_ECX );
  1190     store_reg( R_ECX, Rn );
  1191     MEM_WRITE_WORD( R_ECX, R_EAX );
  1192 :}
  1193 MOV.W Rm, @(R0, Rn) {:  
  1194     load_reg( R_EAX, 0 );
  1195     load_reg( R_ECX, Rn );
  1196     ADD_r32_r32( R_EAX, R_ECX );
  1197     check_walign16( R_ECX );
  1198     load_reg( R_EAX, Rm );
  1199     MEM_WRITE_WORD( R_ECX, R_EAX );
  1200 :}
  1201 MOV.W R0, @(disp, GBR) {:  
  1202     load_spreg( R_ECX, R_GBR );
  1203     load_reg( R_EAX, 0 );
  1204     ADD_imm32_r32( disp, R_ECX );
  1205     check_walign16( R_ECX );
  1206     MEM_WRITE_WORD( R_ECX, R_EAX );
  1207 :}
  1208 MOV.W R0, @(disp, Rn) {:  
  1209     load_reg( R_ECX, Rn );
  1210     load_reg( R_EAX, 0 );
  1211     ADD_imm32_r32( disp, R_ECX );
  1212     check_walign16( R_ECX );
  1213     MEM_WRITE_WORD( R_ECX, R_EAX );
  1214 :}
  1215 MOV.W @Rm, Rn {:  
  1216     load_reg( R_ECX, Rm );
  1217     check_ralign16( R_ECX );
  1218     MEM_READ_WORD( R_ECX, R_EAX );
  1219     store_reg( R_EAX, Rn );
  1220 :}
  1221 MOV.W @Rm+, Rn {:  
  1222     load_reg( R_EAX, Rm );
  1223     check_ralign16( R_EAX );
  1224     MOV_r32_r32( R_EAX, R_ECX );
  1225     ADD_imm8s_r32( 2, R_EAX );
  1226     store_reg( R_EAX, Rm );
  1227     MEM_READ_WORD( R_ECX, R_EAX );
  1228     store_reg( R_EAX, Rn );
  1229 :}
  1230 MOV.W @(R0, Rm), Rn {:  
  1231     load_reg( R_EAX, 0 );
  1232     load_reg( R_ECX, Rm );
  1233     ADD_r32_r32( R_EAX, R_ECX );
  1234     check_ralign16( R_ECX );
  1235     MEM_READ_WORD( R_ECX, R_EAX );
  1236     store_reg( R_EAX, Rn );
  1237 :}
  1238 MOV.W @(disp, GBR), R0 {:  
  1239     load_spreg( R_ECX, R_GBR );
  1240     ADD_imm32_r32( disp, R_ECX );
  1241     check_ralign16( R_ECX );
  1242     MEM_READ_WORD( R_ECX, R_EAX );
  1243     store_reg( R_EAX, 0 );
  1244 :}
  1245 MOV.W @(disp, PC), Rn {:  
  1246     if( sh4_x86.in_delay_slot ) {
  1247 	SLOTILLEGAL();
  1248     } else {
  1249 	load_imm32( R_ECX, pc + disp + 4 );
  1250 	MEM_READ_WORD( R_ECX, R_EAX );
  1251 	store_reg( R_EAX, Rn );
  1253 :}
  1254 MOV.W @(disp, Rm), R0 {:  
  1255     load_reg( R_ECX, Rm );
  1256     ADD_imm32_r32( disp, R_ECX );
  1257     check_ralign16( R_ECX );
  1258     MEM_READ_WORD( R_ECX, R_EAX );
  1259     store_reg( R_EAX, 0 );
  1260 :}
  1261 MOVA @(disp, PC), R0 {:  
  1262     if( sh4_x86.in_delay_slot ) {
  1263 	SLOTILLEGAL();
  1264     } else {
  1265 	load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
  1266 	store_reg( R_ECX, 0 );
  1268 :}
  1269 MOVCA.L R0, @Rn {:  
  1270     load_reg( R_EAX, 0 );
  1271     load_reg( R_ECX, Rn );
  1272     check_walign32( R_ECX );
  1273     MEM_WRITE_LONG( R_ECX, R_EAX );
  1274 :}
  1276 /* Control transfer instructions */
  1277 BF disp {:
  1278     if( sh4_x86.in_delay_slot ) {
  1279 	SLOTILLEGAL();
  1280     } else {
  1281 	CMP_imm8s_sh4r( 0, R_T );
  1282 	JNE_rel8( 30, nottaken );
  1283 	exit_block( disp + pc + 4, pc+2 );
  1284 	JMP_TARGET(nottaken);
  1285 	exit_block( pc + 2, pc + 2 );
  1286 	return 2;
  1288 :}
  1289 BF/S disp {:
  1290     if( sh4_x86.in_delay_slot ) {
  1291 	SLOTILLEGAL();
  1292     } else {
  1293 	sh4_x86.in_delay_slot = TRUE;
  1294 	CMP_imm8s_sh4r( 0, R_T );
  1295 	OP(0x0F); OP(0x85); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JNE rel32
  1296 	sh4_x86_translate_instruction(pc+2);
  1297 	exit_block( disp + pc + 4, pc+4 );
  1298 	// not taken
  1299 	*patch = (xlat_output - ((uint8_t *)patch)) - 4;
  1300 	sh4_x86_translate_instruction(pc+2);
  1301 	exit_block( pc + 4, pc+4 );
  1302 	return 4;
  1304 :}
  1305 BRA disp {:  
  1306     if( sh4_x86.in_delay_slot ) {
  1307 	SLOTILLEGAL();
  1308     } else {
  1309 	sh4_x86.in_delay_slot = TRUE;
  1310 	sh4_x86_translate_instruction( pc + 2 );
  1311 	exit_block( disp + pc + 4, pc+4 );
  1312 	return 4;
  1314 :}
  1315 BRAF Rn {:  
  1316     if( sh4_x86.in_delay_slot ) {
  1317 	SLOTILLEGAL();
  1318     } else {
  1319 	load_reg( R_EAX, Rn );
  1320 	ADD_imm32_r32( pc + 4, R_EAX );
  1321 	store_spreg( R_EAX, REG_OFFSET(pc) );
  1322 	sh4_x86.in_delay_slot = TRUE;
  1323 	sh4_x86_translate_instruction( pc + 2 );
  1324 	exit_block_pcset(pc+2);
  1325 	return 4;
  1327 :}
  1328 BSR disp {:  
  1329     if( sh4_x86.in_delay_slot ) {
  1330 	SLOTILLEGAL();
  1331     } else {
  1332 	load_imm32( R_EAX, pc + 4 );
  1333 	store_spreg( R_EAX, R_PR );
  1334 	sh4_x86.in_delay_slot = TRUE;
  1335 	sh4_x86_translate_instruction( pc + 2 );
  1336 	exit_block( disp + pc + 4, pc+4 );
  1337 	return 4;
  1339 :}
  1340 BSRF Rn {:  
  1341     if( sh4_x86.in_delay_slot ) {
  1342 	SLOTILLEGAL();
  1343     } else {
  1344 	load_imm32( R_ECX, pc + 4 );
  1345 	store_spreg( R_ECX, R_PR );
  1346 	ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_ECX );
  1347 	store_spreg( R_ECX, REG_OFFSET(pc) );
  1348 	sh4_x86.in_delay_slot = TRUE;
  1349 	sh4_x86_translate_instruction( pc + 2 );
  1350 	exit_block_pcset(pc+2);
  1351 	return 4;
  1353 :}
  1354 BT disp {:
  1355     if( sh4_x86.in_delay_slot ) {
  1356 	SLOTILLEGAL();
  1357     } else {
  1358 	CMP_imm8s_sh4r( 0, R_T );
  1359 	JE_rel8( 30, nottaken );
  1360 	exit_block( disp + pc + 4, pc+2 );
  1361 	JMP_TARGET(nottaken);
  1362 	exit_block( pc + 2, pc+2 );
  1363 	return 2;
  1365 :}
  1366 BT/S disp {:
  1367     if( sh4_x86.in_delay_slot ) {
  1368 	SLOTILLEGAL();
  1369     } else {
  1370 	sh4_x86.in_delay_slot = TRUE;
  1371 	CMP_imm8s_sh4r( 0, R_T );
  1372 	OP(0x0F); OP(0x84); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JE rel32
  1373 	sh4_x86_translate_instruction(pc+2);
  1374 	exit_block( disp + pc + 4, pc+4 );
  1375 	// not taken
  1376 	*patch = (xlat_output - ((uint8_t *)patch)) - 4;
  1377 	sh4_x86_translate_instruction(pc+2);
  1378 	exit_block( pc + 4, pc+4 );
  1379 	return 4;
  1381 :}
  1382 JMP @Rn {:  
  1383     if( sh4_x86.in_delay_slot ) {
  1384 	SLOTILLEGAL();
  1385     } else {
  1386 	load_reg( R_ECX, Rn );
  1387 	store_spreg( R_ECX, REG_OFFSET(pc) );
  1388 	sh4_x86.in_delay_slot = TRUE;
  1389 	sh4_x86_translate_instruction(pc+2);
  1390 	exit_block_pcset(pc+2);
  1391 	return 4;
  1393 :}
  1394 JSR @Rn {:  
  1395     if( sh4_x86.in_delay_slot ) {
  1396 	SLOTILLEGAL();
  1397     } else {
  1398 	load_imm32( R_EAX, pc + 4 );
  1399 	store_spreg( R_EAX, R_PR );
  1400 	load_reg( R_ECX, Rn );
  1401 	store_spreg( R_ECX, REG_OFFSET(pc) );
  1402 	sh4_x86.in_delay_slot = TRUE;
  1403 	sh4_x86_translate_instruction(pc+2);
  1404 	exit_block_pcset(pc+2);
  1405 	return 4;
  1407 :}
  1408 RTE {:  
  1409     if( sh4_x86.in_delay_slot ) {
  1410 	SLOTILLEGAL();
  1411     } else {
  1412 	check_priv();
  1413 	load_spreg( R_ECX, R_SPC );
  1414 	store_spreg( R_ECX, REG_OFFSET(pc) );
  1415 	load_spreg( R_EAX, R_SSR );
  1416 	call_func1( sh4_write_sr, R_EAX );
  1417 	sh4_x86.in_delay_slot = TRUE;
  1418 	sh4_x86.priv_checked = FALSE;
  1419 	sh4_x86.fpuen_checked = FALSE;
  1420 	sh4_x86_translate_instruction(pc+2);
  1421 	exit_block_pcset(pc+2);
  1422 	return 4;
  1424 :}
  1425 RTS {:  
  1426     if( sh4_x86.in_delay_slot ) {
  1427 	SLOTILLEGAL();
  1428     } else {
  1429 	load_spreg( R_ECX, R_PR );
  1430 	store_spreg( R_ECX, REG_OFFSET(pc) );
  1431 	sh4_x86.in_delay_slot = TRUE;
  1432 	sh4_x86_translate_instruction(pc+2);
  1433 	exit_block_pcset(pc+2);
  1434 	return 4;
  1436 :}
  1437 TRAPA #imm {:  
  1438     if( sh4_x86.in_delay_slot ) {
  1439 	SLOTILLEGAL();
  1440     } else {
  1441 	PUSH_imm32( imm );
  1442 	call_func0( sh4_raise_trap );
  1443 	ADD_imm8s_r32( 4, R_ESP );
  1444 	exit_block_pcset(pc);
  1445 	return 2;
  1447 :}
  1448 UNDEF {:  
  1449     if( sh4_x86.in_delay_slot ) {
  1450 	SLOTILLEGAL();
  1451     } else {
  1452 	JMP_exit(EXIT_ILLEGAL);
  1453 	return 2;
  1455 :}
  1457 CLRMAC {:  
  1458     XOR_r32_r32(R_EAX, R_EAX);
  1459     store_spreg( R_EAX, R_MACL );
  1460     store_spreg( R_EAX, R_MACH );
  1461 :}
  1462 CLRS {:
  1463     CLC();
  1464     SETC_sh4r(R_S);
  1465 :}
  1466 CLRT {:  
  1467     CLC();
  1468     SETC_t();
  1469 :}
  1470 SETS {:  
  1471     STC();
  1472     SETC_sh4r(R_S);
  1473 :}
  1474 SETT {:  
  1475     STC();
  1476     SETC_t();
  1477 :}
  1479 /* Floating point moves */
  1480 FMOV FRm, FRn {:  
  1481     /* As horrible as this looks, it's actually covering 5 separate cases:
  1482      * 1. 32-bit fr-to-fr (PR=0)
  1483      * 2. 64-bit dr-to-dr (PR=1, FRm&1 == 0, FRn&1 == 0 )
  1484      * 3. 64-bit dr-to-xd (PR=1, FRm&1 == 0, FRn&1 == 1 )
  1485      * 4. 64-bit xd-to-dr (PR=1, FRm&1 == 1, FRn&1 == 0 )
  1486      * 5. 64-bit xd-to-xd (PR=1, FRm&1 == 1, FRn&1 == 1 )
  1487      */
  1488     check_fpuen();
  1489     load_spreg( R_ECX, R_FPSCR );
  1490     load_fr_bank( R_EDX );
  1491     TEST_imm32_r32( FPSCR_SZ, R_ECX );
  1492     JNE_rel8(8, doublesize);
  1493     load_fr( R_EDX, R_EAX, FRm ); // PR=0 branch
  1494     store_fr( R_EDX, R_EAX, FRn );
  1495     if( FRm&1 ) {
  1496 	JMP_rel8(24, end);
  1497 	JMP_TARGET(doublesize);
  1498 	load_xf_bank( R_ECX ); 
  1499 	load_fr( R_ECX, R_EAX, FRm-1 );
  1500 	if( FRn&1 ) {
  1501 	    load_fr( R_ECX, R_EDX, FRm );
  1502 	    store_fr( R_ECX, R_EAX, FRn-1 );
  1503 	    store_fr( R_ECX, R_EDX, FRn );
  1504 	} else /* FRn&1 == 0 */ {
  1505 	    load_fr( R_ECX, R_ECX, FRm );
  1506 	    store_fr( R_EDX, R_EAX, FRn );
  1507 	    store_fr( R_EDX, R_ECX, FRn+1 );
  1509 	JMP_TARGET(end);
  1510     } else /* FRm&1 == 0 */ {
  1511 	if( FRn&1 ) {
  1512 	    JMP_rel8(24, end);
  1513 	    load_xf_bank( R_ECX );
  1514 	    load_fr( R_EDX, R_EAX, FRm );
  1515 	    load_fr( R_EDX, R_EDX, FRm+1 );
  1516 	    store_fr( R_ECX, R_EAX, FRn-1 );
  1517 	    store_fr( R_ECX, R_EDX, FRn );
  1518 	    JMP_TARGET(end);
  1519 	} else /* FRn&1 == 0 */ {
  1520 	    JMP_rel8(12, end);
  1521 	    load_fr( R_EDX, R_EAX, FRm );
  1522 	    load_fr( R_EDX, R_ECX, FRm+1 );
  1523 	    store_fr( R_EDX, R_EAX, FRn );
  1524 	    store_fr( R_EDX, R_ECX, FRn+1 );
  1525 	    JMP_TARGET(end);
  1528 :}
  1529 FMOV FRm, @Rn {:  
  1530     check_fpuen();
  1531     load_reg( R_EDX, Rn );
  1532     check_walign32( R_EDX );
  1533     load_spreg( R_ECX, R_FPSCR );
  1534     TEST_imm32_r32( FPSCR_SZ, R_ECX );
  1535     JNE_rel8(20, doublesize);
  1536     load_fr_bank( R_ECX );
  1537     load_fr( R_ECX, R_EAX, FRm );
  1538     MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
  1539     if( FRm&1 ) {
  1540 	JMP_rel8( 48, end );
  1541 	JMP_TARGET(doublesize);
  1542 	load_xf_bank( R_ECX );
  1543 	load_fr( R_ECX, R_EAX, FRm&0x0E );
  1544 	load_fr( R_ECX, R_ECX, FRm|0x01 );
  1545 	MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
  1546 	JMP_TARGET(end);
  1547     } else {
  1548 	JMP_rel8( 39, end );
  1549 	JMP_TARGET(doublesize);
  1550 	load_fr_bank( R_ECX );
  1551 	load_fr( R_ECX, R_EAX, FRm&0x0E );
  1552 	load_fr( R_ECX, R_ECX, FRm|0x01 );
  1553 	MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
  1554 	JMP_TARGET(end);
  1556 :}
  1557 FMOV @Rm, FRn {:  
  1558     check_fpuen();
  1559     load_reg( R_EDX, Rm );
  1560     check_ralign32( R_EDX );
  1561     load_spreg( R_ECX, R_FPSCR );
  1562     TEST_imm32_r32( FPSCR_SZ, R_ECX );
  1563     JNE_rel8(19, doublesize);
  1564     MEM_READ_LONG( R_EDX, R_EAX );
  1565     load_fr_bank( R_ECX );
  1566     store_fr( R_ECX, R_EAX, FRn );
  1567     if( FRn&1 ) {
  1568 	JMP_rel8(48, end);
  1569 	JMP_TARGET(doublesize);
  1570 	MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
  1571 	load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
  1572 	load_xf_bank( R_ECX );
  1573 	store_fr( R_ECX, R_EAX, FRn&0x0E );
  1574 	store_fr( R_ECX, R_EDX, FRn|0x01 );
  1575 	JMP_TARGET(end);
  1576     } else {
  1577 	JMP_rel8(36, end);
  1578 	JMP_TARGET(doublesize);
  1579 	MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
  1580 	load_fr_bank( R_ECX );
  1581 	store_fr( R_ECX, R_EAX, FRn&0x0E );
  1582 	store_fr( R_ECX, R_EDX, FRn|0x01 );
  1583 	JMP_TARGET(end);
  1585 :}
  1586 FMOV FRm, @-Rn {:  
  1587     check_fpuen();
  1588     load_reg( R_EDX, Rn );
  1589     check_walign32( R_EDX );
  1590     load_spreg( R_ECX, R_FPSCR );
  1591     TEST_imm32_r32( FPSCR_SZ, R_ECX );
  1592     JNE_rel8(26, doublesize);
  1593     load_fr_bank( R_ECX );
  1594     load_fr( R_ECX, R_EAX, FRm );
  1595     ADD_imm8s_r32(-4,R_EDX);
  1596     store_reg( R_EDX, Rn );
  1597     MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
  1598     if( FRm&1 ) {
  1599 	JMP_rel8( 54, end );
  1600 	JMP_TARGET(doublesize);
  1601 	load_xf_bank( R_ECX );
  1602 	load_fr( R_ECX, R_EAX, FRm&0x0E );
  1603 	load_fr( R_ECX, R_ECX, FRm|0x01 );
  1604 	ADD_imm8s_r32(-8,R_EDX);
  1605 	store_reg( R_EDX, Rn );
  1606 	MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
  1607 	JMP_TARGET(end);
  1608     } else {
  1609 	JMP_rel8( 45, end );
  1610 	JMP_TARGET(doublesize);
  1611 	load_fr_bank( R_ECX );
  1612 	load_fr( R_ECX, R_EAX, FRm&0x0E );
  1613 	load_fr( R_ECX, R_ECX, FRm|0x01 );
  1614 	ADD_imm8s_r32(-8,R_EDX);
  1615 	store_reg( R_EDX, Rn );
  1616 	MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
  1617 	JMP_TARGET(end);
  1619 :}
  1620 FMOV @Rm+, FRn {:  
  1621     check_fpuen();
  1622     load_reg( R_EDX, Rm );
  1623     check_ralign32( R_EDX );
  1624     MOV_r32_r32( R_EDX, R_EAX );
  1625     load_spreg( R_ECX, R_FPSCR );
  1626     TEST_imm32_r32( FPSCR_SZ, R_ECX );
  1627     JNE_rel8(25, doublesize);
  1628     ADD_imm8s_r32( 4, R_EAX );
  1629     store_reg( R_EAX, Rm );
  1630     MEM_READ_LONG( R_EDX, R_EAX );
  1631     load_fr_bank( R_ECX );
  1632     store_fr( R_ECX, R_EAX, FRn );
  1633     if( FRn&1 ) {
  1634 	JMP_rel8(54, end);
  1635 	JMP_TARGET(doublesize);
  1636 	ADD_imm8s_r32( 8, R_EAX );
  1637 	store_reg(R_EAX, Rm);
  1638 	MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
  1639 	load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
  1640 	load_xf_bank( R_ECX );
  1641 	store_fr( R_ECX, R_EAX, FRn&0x0E );
  1642 	store_fr( R_ECX, R_EDX, FRn|0x01 );
  1643 	JMP_TARGET(end);
  1644     } else {
  1645 	JMP_rel8(42, end);
  1646 	ADD_imm8s_r32( 8, R_EAX );
  1647 	store_reg(R_EAX, Rm);
  1648 	MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
  1649 	load_fr_bank( R_ECX );
  1650 	store_fr( R_ECX, R_EAX, FRn&0x0E );
  1651 	store_fr( R_ECX, R_EDX, FRn|0x01 );
  1652 	JMP_TARGET(end);
  1654 :}
  1655 FMOV FRm, @(R0, Rn) {:  
  1656     check_fpuen();
  1657     load_reg( R_EDX, Rn );
  1658     ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
  1659     check_walign32( R_EDX );
  1660     load_spreg( R_ECX, R_FPSCR );
  1661     TEST_imm32_r32( FPSCR_SZ, R_ECX );
  1662     JNE_rel8(20, doublesize);
  1663     load_fr_bank( R_ECX );
  1664     load_fr( R_ECX, R_EAX, FRm );
  1665     MEM_WRITE_LONG( R_EDX, R_EAX ); // 12
  1666     if( FRm&1 ) {
  1667 	JMP_rel8( 48, end );
  1668 	JMP_TARGET(doublesize);
  1669 	load_xf_bank( R_ECX );
  1670 	load_fr( R_ECX, R_EAX, FRm&0x0E );
  1671 	load_fr( R_ECX, R_ECX, FRm|0x01 );
  1672 	MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
  1673 	JMP_TARGET(end);
  1674     } else {
  1675 	JMP_rel8( 39, end );
  1676 	JMP_TARGET(doublesize);
  1677 	load_fr_bank( R_ECX );
  1678 	load_fr( R_ECX, R_EAX, FRm&0x0E );
  1679 	load_fr( R_ECX, R_ECX, FRm|0x01 );
  1680 	MEM_WRITE_DOUBLE( R_EDX, R_EAX, R_ECX );
  1681 	JMP_TARGET(end);
  1683 :}
  1684 FMOV @(R0, Rm), FRn {:  
  1685     check_fpuen();
  1686     load_reg( R_EDX, Rm );
  1687     ADD_sh4r_r32( REG_OFFSET(r[0]), R_EDX );
  1688     check_ralign32( R_EDX );
  1689     load_spreg( R_ECX, R_FPSCR );
  1690     TEST_imm32_r32( FPSCR_SZ, R_ECX );
  1691     JNE_rel8(19, doublesize);
  1692     MEM_READ_LONG( R_EDX, R_EAX );
  1693     load_fr_bank( R_ECX );
  1694     store_fr( R_ECX, R_EAX, FRn );
  1695     if( FRn&1 ) {
  1696 	JMP_rel8(48, end);
  1697 	JMP_TARGET(doublesize);
  1698 	MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
  1699 	load_spreg( R_ECX, R_FPSCR ); // assume read_long clobbered it
  1700 	load_xf_bank( R_ECX );
  1701 	store_fr( R_ECX, R_EAX, FRn&0x0E );
  1702 	store_fr( R_ECX, R_EDX, FRn|0x01 );
  1703 	JMP_TARGET(end);
  1704     } else {
  1705 	JMP_rel8(36, end);
  1706 	JMP_TARGET(doublesize);
  1707 	MEM_READ_DOUBLE( R_EDX, R_EAX, R_EDX );
  1708 	load_fr_bank( R_ECX );
  1709 	store_fr( R_ECX, R_EAX, FRn&0x0E );
  1710 	store_fr( R_ECX, R_EDX, FRn|0x01 );
  1711 	JMP_TARGET(end);
  1713 :}
  1714 FLDI0 FRn {:  /* IFF PR=0 */
  1715     check_fpuen();
  1716     load_spreg( R_ECX, R_FPSCR );
  1717     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1718     JNE_rel8(8, end);
  1719     XOR_r32_r32( R_EAX, R_EAX );
  1720     load_spreg( R_ECX, REG_OFFSET(fr_bank) );
  1721     store_fr( R_ECX, R_EAX, FRn );
  1722     JMP_TARGET(end);
  1723 :}
  1724 FLDI1 FRn {:  /* IFF PR=0 */
  1725     check_fpuen();
  1726     load_spreg( R_ECX, R_FPSCR );
  1727     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1728     JNE_rel8(11, end);
  1729     load_imm32(R_EAX, 0x3F800000);
  1730     load_spreg( R_ECX, REG_OFFSET(fr_bank) );
  1731     store_fr( R_ECX, R_EAX, FRn );
  1732     JMP_TARGET(end);
  1733 :}
  1735 FLOAT FPUL, FRn {:  
  1736     check_fpuen();
  1737     load_spreg( R_ECX, R_FPSCR );
  1738     load_spreg(R_EDX, REG_OFFSET(fr_bank));
  1739     FILD_sh4r(R_FPUL);
  1740     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1741     JNE_rel8(5, doubleprec);
  1742     pop_fr( R_EDX, FRn );
  1743     JMP_rel8(3, end);
  1744     JMP_TARGET(doubleprec);
  1745     pop_dr( R_EDX, FRn );
  1746     JMP_TARGET(end);
  1747 :}
  1748 FTRC FRm, FPUL {:  
  1749     check_fpuen();
  1750     load_spreg( R_ECX, R_FPSCR );
  1751     load_fr_bank( R_EDX );
  1752     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1753     JNE_rel8(5, doubleprec);
  1754     push_fr( R_EDX, FRm );
  1755     JMP_rel8(3, doop);
  1756     JMP_TARGET(doubleprec);
  1757     push_dr( R_EDX, FRm );
  1758     JMP_TARGET( doop );
  1759     load_imm32( R_ECX, (uint32_t)&max_int );
  1760     FILD_r32ind( R_ECX );
  1761     FCOMIP_st(1);
  1762     JNA_rel8( 32, sat );
  1763     load_imm32( R_ECX, (uint32_t)&min_int );  // 5
  1764     FILD_r32ind( R_ECX );           // 2
  1765     FCOMIP_st(1);                   // 2
  1766     JAE_rel8( 21, sat2 );            // 2
  1767     load_imm32( R_EAX, (uint32_t)&save_fcw );
  1768     FNSTCW_r32ind( R_EAX );
  1769     load_imm32( R_EDX, (uint32_t)&trunc_fcw );
  1770     FLDCW_r32ind( R_EDX );
  1771     FISTP_sh4r(R_FPUL);             // 3
  1772     FLDCW_r32ind( R_EAX );
  1773     JMP_rel8( 9, end );             // 2
  1775     JMP_TARGET(sat);
  1776     JMP_TARGET(sat2);
  1777     MOV_r32ind_r32( R_ECX, R_ECX ); // 2
  1778     store_spreg( R_ECX, R_FPUL );
  1779     FPOP_st();
  1780     JMP_TARGET(end);
  1781 :}
  1782 FLDS FRm, FPUL {:  
  1783     check_fpuen();
  1784     load_fr_bank( R_ECX );
  1785     load_fr( R_ECX, R_EAX, FRm );
  1786     store_spreg( R_EAX, R_FPUL );
  1787 :}
  1788 FSTS FPUL, FRn {:  
  1789     check_fpuen();
  1790     load_fr_bank( R_ECX );
  1791     load_spreg( R_EAX, R_FPUL );
  1792     store_fr( R_ECX, R_EAX, FRn );
  1793 :}
  1794 FCNVDS FRm, FPUL {:  
  1795     check_fpuen();
  1796     load_spreg( R_ECX, R_FPSCR );
  1797     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1798     JE_rel8(9, end); // only when PR=1
  1799     load_fr_bank( R_ECX );
  1800     push_dr( R_ECX, FRm );
  1801     pop_fpul();
  1802     JMP_TARGET(end);
  1803 :}
  1804 FCNVSD FPUL, FRn {:  
  1805     check_fpuen();
  1806     load_spreg( R_ECX, R_FPSCR );
  1807     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1808     JE_rel8(9, end); // only when PR=1
  1809     load_fr_bank( R_ECX );
  1810     push_fpul();
  1811     pop_dr( R_ECX, FRn );
  1812     JMP_TARGET(end);
  1813 :}
  1815 /* Floating point instructions */
  1816 FABS FRn {:  
  1817     check_fpuen();
  1818     load_spreg( R_ECX, R_FPSCR );
  1819     load_fr_bank( R_EDX );
  1820     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1821     JNE_rel8(10, doubleprec);
  1822     push_fr(R_EDX, FRn); // 3
  1823     FABS_st0(); // 2
  1824     pop_fr( R_EDX, FRn); //3
  1825     JMP_rel8(8,end); // 2
  1826     JMP_TARGET(doubleprec);
  1827     push_dr(R_EDX, FRn);
  1828     FABS_st0();
  1829     pop_dr(R_EDX, FRn);
  1830     JMP_TARGET(end);
  1831 :}
  1832 FADD FRm, FRn {:  
  1833     check_fpuen();
  1834     load_spreg( R_ECX, R_FPSCR );
  1835     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1836     load_fr_bank( R_EDX );
  1837     JNE_rel8(13,doubleprec);
  1838     push_fr(R_EDX, FRm);
  1839     push_fr(R_EDX, FRn);
  1840     FADDP_st(1);
  1841     pop_fr(R_EDX, FRn);
  1842     JMP_rel8(11,end);
  1843     JMP_TARGET(doubleprec);
  1844     push_dr(R_EDX, FRm);
  1845     push_dr(R_EDX, FRn);
  1846     FADDP_st(1);
  1847     pop_dr(R_EDX, FRn);
  1848     JMP_TARGET(end);
  1849 :}
  1850 FDIV FRm, FRn {:  
  1851     check_fpuen();
  1852     load_spreg( R_ECX, R_FPSCR );
  1853     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1854     load_fr_bank( R_EDX );
  1855     JNE_rel8(13, doubleprec);
  1856     push_fr(R_EDX, FRn);
  1857     push_fr(R_EDX, FRm);
  1858     FDIVP_st(1);
  1859     pop_fr(R_EDX, FRn);
  1860     JMP_rel8(11, end);
  1861     JMP_TARGET(doubleprec);
  1862     push_dr(R_EDX, FRn);
  1863     push_dr(R_EDX, FRm);
  1864     FDIVP_st(1);
  1865     pop_dr(R_EDX, FRn);
  1866     JMP_TARGET(end);
  1867 :}
  1868 FMAC FR0, FRm, FRn {:  
  1869     check_fpuen();
  1870     load_spreg( R_ECX, R_FPSCR );
  1871     load_spreg( R_EDX, REG_OFFSET(fr_bank));
  1872     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1873     JNE_rel8(18, doubleprec);
  1874     push_fr( R_EDX, 0 );
  1875     push_fr( R_EDX, FRm );
  1876     FMULP_st(1);
  1877     push_fr( R_EDX, FRn );
  1878     FADDP_st(1);
  1879     pop_fr( R_EDX, FRn );
  1880     JMP_rel8(16, end);
  1881     JMP_TARGET(doubleprec);
  1882     push_dr( R_EDX, 0 );
  1883     push_dr( R_EDX, FRm );
  1884     FMULP_st(1);
  1885     push_dr( R_EDX, FRn );
  1886     FADDP_st(1);
  1887     pop_dr( R_EDX, FRn );
  1888     JMP_TARGET(end);
  1889 :}
  1891 FMUL FRm, FRn {:  
  1892     check_fpuen();
  1893     load_spreg( R_ECX, R_FPSCR );
  1894     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1895     load_fr_bank( R_EDX );
  1896     JNE_rel8(13, doubleprec);
  1897     push_fr(R_EDX, FRm);
  1898     push_fr(R_EDX, FRn);
  1899     FMULP_st(1);
  1900     pop_fr(R_EDX, FRn);
  1901     JMP_rel8(11, end);
  1902     JMP_TARGET(doubleprec);
  1903     push_dr(R_EDX, FRm);
  1904     push_dr(R_EDX, FRn);
  1905     FMULP_st(1);
  1906     pop_dr(R_EDX, FRn);
  1907     JMP_TARGET(end);
  1908 :}
  1909 FNEG FRn {:  
  1910     check_fpuen();
  1911     load_spreg( R_ECX, R_FPSCR );
  1912     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1913     load_fr_bank( R_EDX );
  1914     JNE_rel8(10, doubleprec);
  1915     push_fr(R_EDX, FRn);
  1916     FCHS_st0();
  1917     pop_fr(R_EDX, FRn);
  1918     JMP_rel8(8, end);
  1919     JMP_TARGET(doubleprec);
  1920     push_dr(R_EDX, FRn);
  1921     FCHS_st0();
  1922     pop_dr(R_EDX, FRn);
  1923     JMP_TARGET(end);
  1924 :}
  1925 FSRRA FRn {:  
  1926     check_fpuen();
  1927     load_spreg( R_ECX, R_FPSCR );
  1928     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1929     load_fr_bank( R_EDX );
  1930     JNE_rel8(12, end); // PR=0 only
  1931     FLD1_st0();
  1932     push_fr(R_EDX, FRn);
  1933     FSQRT_st0();
  1934     FDIVP_st(1);
  1935     pop_fr(R_EDX, FRn);
  1936     JMP_TARGET(end);
  1937 :}
  1938 FSQRT FRn {:  
  1939     check_fpuen();
  1940     load_spreg( R_ECX, R_FPSCR );
  1941     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1942     load_fr_bank( R_EDX );
  1943     JNE_rel8(10, doubleprec);
  1944     push_fr(R_EDX, FRn);
  1945     FSQRT_st0();
  1946     pop_fr(R_EDX, FRn);
  1947     JMP_rel8(8, end);
  1948     JMP_TARGET(doubleprec);
  1949     push_dr(R_EDX, FRn);
  1950     FSQRT_st0();
  1951     pop_dr(R_EDX, FRn);
  1952     JMP_TARGET(end);
  1953 :}
  1954 FSUB FRm, FRn {:  
  1955     check_fpuen();
  1956     load_spreg( R_ECX, R_FPSCR );
  1957     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1958     load_fr_bank( R_EDX );
  1959     JNE_rel8(13, doubleprec);
  1960     push_fr(R_EDX, FRn);
  1961     push_fr(R_EDX, FRm);
  1962     FSUBP_st(1);
  1963     pop_fr(R_EDX, FRn);
  1964     JMP_rel8(11, end);
  1965     JMP_TARGET(doubleprec);
  1966     push_dr(R_EDX, FRn);
  1967     push_dr(R_EDX, FRm);
  1968     FSUBP_st(1);
  1969     pop_dr(R_EDX, FRn);
  1970     JMP_TARGET(end);
  1971 :}
  1973 FCMP/EQ FRm, FRn {:  
  1974     check_fpuen();
  1975     load_spreg( R_ECX, R_FPSCR );
  1976     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1977     load_fr_bank( R_EDX );
  1978     JNE_rel8(8, doubleprec);
  1979     push_fr(R_EDX, FRm);
  1980     push_fr(R_EDX, FRn);
  1981     JMP_rel8(6, end);
  1982     JMP_TARGET(doubleprec);
  1983     push_dr(R_EDX, FRm);
  1984     push_dr(R_EDX, FRn);
  1985     JMP_TARGET(end);
  1986     FCOMIP_st(1);
  1987     SETE_t();
  1988     FPOP_st();
  1989 :}
  1990 FCMP/GT FRm, FRn {:  
  1991     check_fpuen();
  1992     load_spreg( R_ECX, R_FPSCR );
  1993     TEST_imm32_r32( FPSCR_PR, R_ECX );
  1994     load_fr_bank( R_EDX );
  1995     JNE_rel8(8, doubleprec);
  1996     push_fr(R_EDX, FRm);
  1997     push_fr(R_EDX, FRn);
  1998     JMP_rel8(6, end);
  1999     JMP_TARGET(doubleprec);
  2000     push_dr(R_EDX, FRm);
  2001     push_dr(R_EDX, FRn);
  2002     JMP_TARGET(end);
  2003     FCOMIP_st(1);
  2004     SETA_t();
  2005     FPOP_st();
  2006 :}
  2008 FSCA FPUL, FRn {:  
  2009     check_fpuen();
  2010     load_spreg( R_ECX, R_FPSCR );
  2011     TEST_imm32_r32( FPSCR_PR, R_ECX );
  2012     JNE_rel8( 21, doubleprec );
  2013     load_fr_bank( R_ECX );
  2014     ADD_imm8s_r32( (FRn&0x0E)<<2, R_ECX );
  2015     load_spreg( R_EDX, R_FPUL );
  2016     call_func2( sh4_fsca, R_EDX, R_ECX );
  2017     JMP_TARGET(doubleprec);
  2018 :}
  2019 FIPR FVm, FVn {:  
  2020     check_fpuen();
  2021     load_spreg( R_ECX, R_FPSCR );
  2022     TEST_imm32_r32( FPSCR_PR, R_ECX );
  2023     JNE_rel8(44, doubleprec);
  2025     load_fr_bank( R_ECX );
  2026     push_fr( R_ECX, FVm<<2 );
  2027     push_fr( R_ECX, FVn<<2 );
  2028     FMULP_st(1);
  2029     push_fr( R_ECX, (FVm<<2)+1);
  2030     push_fr( R_ECX, (FVn<<2)+1);
  2031     FMULP_st(1);
  2032     FADDP_st(1);
  2033     push_fr( R_ECX, (FVm<<2)+2);
  2034     push_fr( R_ECX, (FVn<<2)+2);
  2035     FMULP_st(1);
  2036     FADDP_st(1);
  2037     push_fr( R_ECX, (FVm<<2)+3);
  2038     push_fr( R_ECX, (FVn<<2)+3);
  2039     FMULP_st(1);
  2040     FADDP_st(1);
  2041     pop_fr( R_ECX, (FVn<<2)+3);
  2042     JMP_TARGET(doubleprec);
  2043 :}
  2044 FTRV XMTRX, FVn {:  
  2045     check_fpuen();
  2046     load_spreg( R_ECX, R_FPSCR );
  2047     TEST_imm32_r32( FPSCR_PR, R_ECX );
  2048     JNE_rel8( 30, doubleprec );
  2049     load_fr_bank( R_EDX );                 // 3
  2050     ADD_imm8s_r32( FVn<<4, R_EDX );        // 3
  2051     load_xf_bank( R_ECX );                 // 12
  2052     call_func2( sh4_ftrv, R_EDX, R_ECX );  // 12
  2053     JMP_TARGET(doubleprec);
  2054 :}
  2056 FRCHG {:  
  2057     check_fpuen();
  2058     load_spreg( R_ECX, R_FPSCR );
  2059     XOR_imm32_r32( FPSCR_FR, R_ECX );
  2060     store_spreg( R_ECX, R_FPSCR );
  2061     update_fr_bank( R_ECX );
  2062 :}
  2063 FSCHG {:  
  2064     check_fpuen();
  2065     load_spreg( R_ECX, R_FPSCR );
  2066     XOR_imm32_r32( FPSCR_SZ, R_ECX );
  2067     store_spreg( R_ECX, R_FPSCR );
  2068 :}
  2070 /* Processor control instructions */
  2071 LDC Rm, SR {:
  2072     if( sh4_x86.in_delay_slot ) {
  2073 	SLOTILLEGAL();
  2074     } else {
  2075 	check_priv();
  2076 	load_reg( R_EAX, Rm );
  2077 	call_func1( sh4_write_sr, R_EAX );
  2078 	sh4_x86.priv_checked = FALSE;
  2079 	sh4_x86.fpuen_checked = FALSE;
  2081 :}
  2082 LDC Rm, GBR {: 
  2083     load_reg( R_EAX, Rm );
  2084     store_spreg( R_EAX, R_GBR );
  2085 :}
  2086 LDC Rm, VBR {:  
  2087     check_priv();
  2088     load_reg( R_EAX, Rm );
  2089     store_spreg( R_EAX, R_VBR );
  2090 :}
  2091 LDC Rm, SSR {:  
  2092     check_priv();
  2093     load_reg( R_EAX, Rm );
  2094     store_spreg( R_EAX, R_SSR );
  2095 :}
  2096 LDC Rm, SGR {:  
  2097     check_priv();
  2098     load_reg( R_EAX, Rm );
  2099     store_spreg( R_EAX, R_SGR );
  2100 :}
  2101 LDC Rm, SPC {:  
  2102     check_priv();
  2103     load_reg( R_EAX, Rm );
  2104     store_spreg( R_EAX, R_SPC );
  2105 :}
  2106 LDC Rm, DBR {:  
  2107     check_priv();
  2108     load_reg( R_EAX, Rm );
  2109     store_spreg( R_EAX, R_DBR );
  2110 :}
  2111 LDC Rm, Rn_BANK {:  
  2112     check_priv();
  2113     load_reg( R_EAX, Rm );
  2114     store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
  2115 :}
  2116 LDC.L @Rm+, GBR {:  
  2117     load_reg( R_EAX, Rm );
  2118     check_ralign32( R_EAX );
  2119     MOV_r32_r32( R_EAX, R_ECX );
  2120     ADD_imm8s_r32( 4, R_EAX );
  2121     store_reg( R_EAX, Rm );
  2122     MEM_READ_LONG( R_ECX, R_EAX );
  2123     store_spreg( R_EAX, R_GBR );
  2124 :}
  2125 LDC.L @Rm+, SR {:
  2126     if( sh4_x86.in_delay_slot ) {
  2127 	SLOTILLEGAL();
  2128     } else {
  2129 	check_priv();
  2130 	load_reg( R_EAX, Rm );
  2131 	check_ralign32( R_EAX );
  2132 	MOV_r32_r32( R_EAX, R_ECX );
  2133 	ADD_imm8s_r32( 4, R_EAX );
  2134 	store_reg( R_EAX, Rm );
  2135 	MEM_READ_LONG( R_ECX, R_EAX );
  2136 	call_func1( sh4_write_sr, R_EAX );
  2137 	sh4_x86.priv_checked = FALSE;
  2138 	sh4_x86.fpuen_checked = FALSE;
  2140 :}
  2141 LDC.L @Rm+, VBR {:  
  2142     check_priv();
  2143     load_reg( R_EAX, Rm );
  2144     check_ralign32( R_EAX );
  2145     MOV_r32_r32( R_EAX, R_ECX );
  2146     ADD_imm8s_r32( 4, R_EAX );
  2147     store_reg( R_EAX, Rm );
  2148     MEM_READ_LONG( R_ECX, R_EAX );
  2149     store_spreg( R_EAX, R_VBR );
  2150 :}
  2151 LDC.L @Rm+, SSR {:
  2152     check_priv();
  2153     load_reg( R_EAX, Rm );
  2154     MOV_r32_r32( R_EAX, R_ECX );
  2155     ADD_imm8s_r32( 4, R_EAX );
  2156     store_reg( R_EAX, Rm );
  2157     MEM_READ_LONG( R_ECX, R_EAX );
  2158     store_spreg( R_EAX, R_SSR );
  2159 :}
  2160 LDC.L @Rm+, SGR {:  
  2161     check_priv();
  2162     load_reg( R_EAX, Rm );
  2163     check_ralign32( R_EAX );
  2164     MOV_r32_r32( R_EAX, R_ECX );
  2165     ADD_imm8s_r32( 4, R_EAX );
  2166     store_reg( R_EAX, Rm );
  2167     MEM_READ_LONG( R_ECX, R_EAX );
  2168     store_spreg( R_EAX, R_SGR );
  2169 :}
  2170 LDC.L @Rm+, SPC {:  
  2171     check_priv();
  2172     load_reg( R_EAX, Rm );
  2173     check_ralign32( R_EAX );
  2174     MOV_r32_r32( R_EAX, R_ECX );
  2175     ADD_imm8s_r32( 4, R_EAX );
  2176     store_reg( R_EAX, Rm );
  2177     MEM_READ_LONG( R_ECX, R_EAX );
  2178     store_spreg( R_EAX, R_SPC );
  2179 :}
  2180 LDC.L @Rm+, DBR {:  
  2181     check_priv();
  2182     load_reg( R_EAX, Rm );
  2183     check_ralign32( R_EAX );
  2184     MOV_r32_r32( R_EAX, R_ECX );
  2185     ADD_imm8s_r32( 4, R_EAX );
  2186     store_reg( R_EAX, Rm );
  2187     MEM_READ_LONG( R_ECX, R_EAX );
  2188     store_spreg( R_EAX, R_DBR );
  2189 :}
  2190 LDC.L @Rm+, Rn_BANK {:  
  2191     check_priv();
  2192     load_reg( R_EAX, Rm );
  2193     check_ralign32( R_EAX );
  2194     MOV_r32_r32( R_EAX, R_ECX );
  2195     ADD_imm8s_r32( 4, R_EAX );
  2196     store_reg( R_EAX, Rm );
  2197     MEM_READ_LONG( R_ECX, R_EAX );
  2198     store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
  2199 :}
  2200 LDS Rm, FPSCR {:  
  2201     load_reg( R_EAX, Rm );
  2202     store_spreg( R_EAX, R_FPSCR );
  2203     update_fr_bank( R_EAX );
  2204 :}
  2205 LDS.L @Rm+, FPSCR {:  
  2206     load_reg( R_EAX, Rm );
  2207     check_ralign32( R_EAX );
  2208     MOV_r32_r32( R_EAX, R_ECX );
  2209     ADD_imm8s_r32( 4, R_EAX );
  2210     store_reg( R_EAX, Rm );
  2211     MEM_READ_LONG( R_ECX, R_EAX );
  2212     store_spreg( R_EAX, R_FPSCR );
  2213     update_fr_bank( R_EAX );
  2214 :}
  2215 LDS Rm, FPUL {:  
  2216     load_reg( R_EAX, Rm );
  2217     store_spreg( R_EAX, R_FPUL );
  2218 :}
  2219 LDS.L @Rm+, FPUL {:  
  2220     load_reg( R_EAX, Rm );
  2221     check_ralign32( R_EAX );
  2222     MOV_r32_r32( R_EAX, R_ECX );
  2223     ADD_imm8s_r32( 4, R_EAX );
  2224     store_reg( R_EAX, Rm );
  2225     MEM_READ_LONG( R_ECX, R_EAX );
  2226     store_spreg( R_EAX, R_FPUL );
  2227 :}
  2228 LDS Rm, MACH {: 
  2229     load_reg( R_EAX, Rm );
  2230     store_spreg( R_EAX, R_MACH );
  2231 :}
  2232 LDS.L @Rm+, MACH {:  
  2233     load_reg( R_EAX, Rm );
  2234     check_ralign32( R_EAX );
  2235     MOV_r32_r32( R_EAX, R_ECX );
  2236     ADD_imm8s_r32( 4, R_EAX );
  2237     store_reg( R_EAX, Rm );
  2238     MEM_READ_LONG( R_ECX, R_EAX );
  2239     store_spreg( R_EAX, R_MACH );
  2240 :}
  2241 LDS Rm, MACL {:  
  2242     load_reg( R_EAX, Rm );
  2243     store_spreg( R_EAX, R_MACL );
  2244 :}
  2245 LDS.L @Rm+, MACL {:  
  2246     load_reg( R_EAX, Rm );
  2247     check_ralign32( R_EAX );
  2248     MOV_r32_r32( R_EAX, R_ECX );
  2249     ADD_imm8s_r32( 4, R_EAX );
  2250     store_reg( R_EAX, Rm );
  2251     MEM_READ_LONG( R_ECX, R_EAX );
  2252     store_spreg( R_EAX, R_MACL );
  2253 :}
  2254 LDS Rm, PR {:  
  2255     load_reg( R_EAX, Rm );
  2256     store_spreg( R_EAX, R_PR );
  2257 :}
  2258 LDS.L @Rm+, PR {:  
  2259     load_reg( R_EAX, Rm );
  2260     check_ralign32( R_EAX );
  2261     MOV_r32_r32( R_EAX, R_ECX );
  2262     ADD_imm8s_r32( 4, R_EAX );
  2263     store_reg( R_EAX, Rm );
  2264     MEM_READ_LONG( R_ECX, R_EAX );
  2265     store_spreg( R_EAX, R_PR );
  2266 :}
  2267 LDTLB {:  :}
  2268 OCBI @Rn {:  :}
  2269 OCBP @Rn {:  :}
  2270 OCBWB @Rn {:  :}
  2271 PREF @Rn {:
  2272     load_reg( R_EAX, Rn );
  2273     PUSH_r32( R_EAX );
  2274     AND_imm32_r32( 0xFC000000, R_EAX );
  2275     CMP_imm32_r32( 0xE0000000, R_EAX );
  2276     JNE_rel8(7, end);
  2277     call_func0( sh4_flush_store_queue );
  2278     JMP_TARGET(end);
  2279     ADD_imm8s_r32( 4, R_ESP );
  2280 :}
  2281 SLEEP {: 
  2282     check_priv();
  2283     call_func0( sh4_sleep );
  2284     sh4_x86.in_delay_slot = FALSE;
  2285     INC_r32(R_ESI);
  2286     exit_block(pc+2, pc+2);
  2287     return 2;
  2288 :}
  2289 STC SR, Rn {:
  2290     check_priv();
  2291     call_func0(sh4_read_sr);
  2292     store_reg( R_EAX, Rn );
  2293 :}
  2294 STC GBR, Rn {:  
  2295     load_spreg( R_EAX, R_GBR );
  2296     store_reg( R_EAX, Rn );
  2297 :}
  2298 STC VBR, Rn {:  
  2299     check_priv();
  2300     load_spreg( R_EAX, R_VBR );
  2301     store_reg( R_EAX, Rn );
  2302 :}
  2303 STC SSR, Rn {:  
  2304     check_priv();
  2305     load_spreg( R_EAX, R_SSR );
  2306     store_reg( R_EAX, Rn );
  2307 :}
  2308 STC SPC, Rn {:  
  2309     check_priv();
  2310     load_spreg( R_EAX, R_SPC );
  2311     store_reg( R_EAX, Rn );
  2312 :}
  2313 STC SGR, Rn {:  
  2314     check_priv();
  2315     load_spreg( R_EAX, R_SGR );
  2316     store_reg( R_EAX, Rn );
  2317 :}
  2318 STC DBR, Rn {:  
  2319     check_priv();
  2320     load_spreg( R_EAX, R_DBR );
  2321     store_reg( R_EAX, Rn );
  2322 :}
  2323 STC Rm_BANK, Rn {:
  2324     check_priv();
  2325     load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
  2326     store_reg( R_EAX, Rn );
  2327 :}
  2328 STC.L SR, @-Rn {:
  2329     check_priv();
  2330     call_func0( sh4_read_sr );
  2331     load_reg( R_ECX, Rn );
  2332     check_walign32( R_ECX );
  2333     ADD_imm8s_r32( -4, R_ECX );
  2334     store_reg( R_ECX, Rn );
  2335     MEM_WRITE_LONG( R_ECX, R_EAX );
  2336 :}
  2337 STC.L VBR, @-Rn {:  
  2338     check_priv();
  2339     load_reg( R_ECX, Rn );
  2340     check_walign32( R_ECX );
  2341     ADD_imm8s_r32( -4, R_ECX );
  2342     store_reg( R_ECX, Rn );
  2343     load_spreg( R_EAX, R_VBR );
  2344     MEM_WRITE_LONG( R_ECX, R_EAX );
  2345 :}
  2346 STC.L SSR, @-Rn {:  
  2347     check_priv();
  2348     load_reg( R_ECX, Rn );
  2349     check_walign32( R_ECX );
  2350     ADD_imm8s_r32( -4, R_ECX );
  2351     store_reg( R_ECX, Rn );
  2352     load_spreg( R_EAX, R_SSR );
  2353     MEM_WRITE_LONG( R_ECX, R_EAX );
  2354 :}
  2355 STC.L SPC, @-Rn {:  
  2356     check_priv();
  2357     load_reg( R_ECX, Rn );
  2358     check_walign32( R_ECX );
  2359     ADD_imm8s_r32( -4, R_ECX );
  2360     store_reg( R_ECX, Rn );
  2361     load_spreg( R_EAX, R_SPC );
  2362     MEM_WRITE_LONG( R_ECX, R_EAX );
  2363 :}
  2364 STC.L SGR, @-Rn {:  
  2365     check_priv();
  2366     load_reg( R_ECX, Rn );
  2367     check_walign32( R_ECX );
  2368     ADD_imm8s_r32( -4, R_ECX );
  2369     store_reg( R_ECX, Rn );
  2370     load_spreg( R_EAX, R_SGR );
  2371     MEM_WRITE_LONG( R_ECX, R_EAX );
  2372 :}
  2373 STC.L DBR, @-Rn {:  
  2374     check_priv();
  2375     load_reg( R_ECX, Rn );
  2376     check_walign32( R_ECX );
  2377     ADD_imm8s_r32( -4, R_ECX );
  2378     store_reg( R_ECX, Rn );
  2379     load_spreg( R_EAX, R_DBR );
  2380     MEM_WRITE_LONG( R_ECX, R_EAX );
  2381 :}
  2382 STC.L Rm_BANK, @-Rn {:  
  2383     check_priv();
  2384     load_reg( R_ECX, Rn );
  2385     check_walign32( R_ECX );
  2386     ADD_imm8s_r32( -4, R_ECX );
  2387     store_reg( R_ECX, Rn );
  2388     load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
  2389     MEM_WRITE_LONG( R_ECX, R_EAX );
  2390 :}
  2391 STC.L GBR, @-Rn {:  
  2392     load_reg( R_ECX, Rn );
  2393     check_walign32( R_ECX );
  2394     ADD_imm8s_r32( -4, R_ECX );
  2395     store_reg( R_ECX, Rn );
  2396     load_spreg( R_EAX, R_GBR );
  2397     MEM_WRITE_LONG( R_ECX, R_EAX );
  2398 :}
  2399 STS FPSCR, Rn {:  
  2400     load_spreg( R_EAX, R_FPSCR );
  2401     store_reg( R_EAX, Rn );
  2402 :}
  2403 STS.L FPSCR, @-Rn {:  
  2404     load_reg( R_ECX, Rn );
  2405     check_walign32( R_ECX );
  2406     ADD_imm8s_r32( -4, R_ECX );
  2407     store_reg( R_ECX, Rn );
  2408     load_spreg( R_EAX, R_FPSCR );
  2409     MEM_WRITE_LONG( R_ECX, R_EAX );
  2410 :}
  2411 STS FPUL, Rn {:  
  2412     load_spreg( R_EAX, R_FPUL );
  2413     store_reg( R_EAX, Rn );
  2414 :}
  2415 STS.L FPUL, @-Rn {:  
  2416     load_reg( R_ECX, Rn );
  2417     check_walign32( R_ECX );
  2418     ADD_imm8s_r32( -4, R_ECX );
  2419     store_reg( R_ECX, Rn );
  2420     load_spreg( R_EAX, R_FPUL );
  2421     MEM_WRITE_LONG( R_ECX, R_EAX );
  2422 :}
  2423 STS MACH, Rn {:  
  2424     load_spreg( R_EAX, R_MACH );
  2425     store_reg( R_EAX, Rn );
  2426 :}
  2427 STS.L MACH, @-Rn {:  
  2428     load_reg( R_ECX, Rn );
  2429     check_walign32( R_ECX );
  2430     ADD_imm8s_r32( -4, R_ECX );
  2431     store_reg( R_ECX, Rn );
  2432     load_spreg( R_EAX, R_MACH );
  2433     MEM_WRITE_LONG( R_ECX, R_EAX );
  2434 :}
  2435 STS MACL, Rn {:  
  2436     load_spreg( R_EAX, R_MACL );
  2437     store_reg( R_EAX, Rn );
  2438 :}
  2439 STS.L MACL, @-Rn {:  
  2440     load_reg( R_ECX, Rn );
  2441     check_walign32( R_ECX );
  2442     ADD_imm8s_r32( -4, R_ECX );
  2443     store_reg( R_ECX, Rn );
  2444     load_spreg( R_EAX, R_MACL );
  2445     MEM_WRITE_LONG( R_ECX, R_EAX );
  2446 :}
  2447 STS PR, Rn {:  
  2448     load_spreg( R_EAX, R_PR );
  2449     store_reg( R_EAX, Rn );
  2450 :}
  2451 STS.L PR, @-Rn {:  
  2452     load_reg( R_ECX, Rn );
  2453     check_walign32( R_ECX );
  2454     ADD_imm8s_r32( -4, R_ECX );
  2455     store_reg( R_ECX, Rn );
  2456     load_spreg( R_EAX, R_PR );
  2457     MEM_WRITE_LONG( R_ECX, R_EAX );
  2458 :}
  2460 NOP {: /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */ :}
  2461 %%
  2462     if( sh4_x86.in_delay_slot ) {
  2463 	ADD_imm8s_r32(2,R_ESI);
  2464 	sh4_x86.in_delay_slot = FALSE;
  2465     } else {
  2466 	INC_r32(R_ESI);
  2468     return 0;
.