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