Search
lxdream.org :: lxdream/src/sh4/sh4core.in
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4core.in
changeset 758:99ae000d4e09
prev740:dd11269ee48b
next927:17b6b9e245d8
author nkeynes
date Thu Dec 11 23:26:03 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Disable the generational translation cache - I've got no evidence that it
actually helps performance, and it simplifies things to get rid of it (in
particular, translated code doesn't have to worry about being moved now).
file annotate diff log raw
nkeynes@359
     1
/**
nkeynes@586
     2
 * $Id$
nkeynes@359
     3
 * 
nkeynes@359
     4
 * SH4 emulation core, and parent module for all the SH4 peripheral
nkeynes@359
     5
 * modules.
nkeynes@359
     6
 *
nkeynes@359
     7
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@359
     8
 *
nkeynes@359
     9
 * This program is free software; you can redistribute it and/or modify
nkeynes@359
    10
 * it under the terms of the GNU General Public License as published by
nkeynes@359
    11
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@359
    12
 * (at your option) any later version.
nkeynes@359
    13
 *
nkeynes@359
    14
 * This program is distributed in the hope that it will be useful,
nkeynes@359
    15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@359
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@359
    17
 * GNU General Public License for more details.
nkeynes@359
    18
 */
nkeynes@359
    19
nkeynes@359
    20
#define MODULE sh4_module
nkeynes@586
    21
#include <assert.h>
nkeynes@359
    22
#include <math.h>
nkeynes@359
    23
#include "dream.h"
nkeynes@430
    24
#include "dreamcast.h"
nkeynes@430
    25
#include "eventq.h"
nkeynes@430
    26
#include "mem.h"
nkeynes@430
    27
#include "clock.h"
nkeynes@430
    28
#include "syscall.h"
nkeynes@359
    29
#include "sh4/sh4core.h"
nkeynes@359
    30
#include "sh4/sh4mmio.h"
nkeynes@671
    31
#include "sh4/sh4stat.h"
nkeynes@359
    32
#include "sh4/intc.h"
nkeynes@359
    33
nkeynes@359
    34
#define SH4_CALLTRACE 1
nkeynes@359
    35
nkeynes@359
    36
#define MAX_INT 0x7FFFFFFF
nkeynes@359
    37
#define MIN_INT 0x80000000
nkeynes@359
    38
#define MAX_INTF 2147483647.0
nkeynes@359
    39
#define MIN_INTF -2147483648.0
nkeynes@359
    40
nkeynes@359
    41
/********************** SH4 Module Definition ****************************/
nkeynes@359
    42
nkeynes@740
    43
uint32_t sh4_emulate_run_slice( uint32_t nanosecs ) 
nkeynes@359
    44
{
nkeynes@359
    45
    int i;
nkeynes@359
    46
nkeynes@359
    47
    if( sh4_breakpoint_count == 0 ) {
nkeynes@359
    48
	for( ; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
nkeynes@359
    49
	    if( SH4_EVENT_PENDING() ) {
nkeynes@359
    50
		if( sh4r.event_types & PENDING_EVENT ) {
nkeynes@359
    51
		    event_execute();
nkeynes@359
    52
		}
nkeynes@359
    53
		/* Eventq execute may (quite likely) deliver an immediate IRQ */
nkeynes@359
    54
		if( sh4r.event_types & PENDING_IRQ ) {
nkeynes@359
    55
		    sh4_accept_interrupt();
nkeynes@359
    56
		}
nkeynes@359
    57
	    }
nkeynes@359
    58
	    if( !sh4_execute_instruction() ) {
nkeynes@359
    59
		break;
nkeynes@359
    60
	    }
nkeynes@359
    61
	}
nkeynes@359
    62
    } else {
nkeynes@359
    63
	for( ;sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
nkeynes@359
    64
	    if( SH4_EVENT_PENDING() ) {
nkeynes@359
    65
		if( sh4r.event_types & PENDING_EVENT ) {
nkeynes@359
    66
		    event_execute();
nkeynes@359
    67
		}
nkeynes@359
    68
		/* Eventq execute may (quite likely) deliver an immediate IRQ */
nkeynes@359
    69
		if( sh4r.event_types & PENDING_IRQ ) {
nkeynes@359
    70
		    sh4_accept_interrupt();
nkeynes@359
    71
		}
nkeynes@359
    72
	    }
nkeynes@359
    73
                 
nkeynes@359
    74
	    if( !sh4_execute_instruction() )
nkeynes@359
    75
		break;
nkeynes@359
    76
#ifdef ENABLE_DEBUG_MODE
nkeynes@359
    77
	    for( i=0; i<sh4_breakpoint_count; i++ ) {
nkeynes@359
    78
		if( sh4_breakpoints[i].address == sh4r.pc ) {
nkeynes@359
    79
		    break;
nkeynes@359
    80
		}
nkeynes@359
    81
	    }
nkeynes@359
    82
	    if( i != sh4_breakpoint_count ) {
nkeynes@740
    83
	    	sh4_core_exit( CORE_EXIT_BREAKPOINT );
nkeynes@359
    84
	    }
nkeynes@359
    85
#endif	
nkeynes@359
    86
	}
nkeynes@359
    87
    }
nkeynes@359
    88
nkeynes@359
    89
    /* If we aborted early, but the cpu is still technically running,
nkeynes@359
    90
     * we're doing a hard abort - cut the timeslice back to what we
nkeynes@359
    91
     * actually executed
nkeynes@359
    92
     */
nkeynes@359
    93
    if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
nkeynes@359
    94
	nanosecs = sh4r.slice_cycle;
nkeynes@359
    95
    }
nkeynes@359
    96
    if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
nkeynes@359
    97
	TMU_run_slice( nanosecs );
nkeynes@359
    98
	SCIF_run_slice( nanosecs );
nkeynes@359
    99
    }
nkeynes@359
   100
    return nanosecs;
nkeynes@359
   101
}
nkeynes@359
   102
nkeynes@359
   103
/********************** SH4 emulation core  ****************************/
nkeynes@359
   104
nkeynes@359
   105
#define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
nkeynes@740
   106
#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }while(0)
nkeynes@359
   107
nkeynes@359
   108
#if(SH4_CALLTRACE == 1)
nkeynes@359
   109
#define MAX_CALLSTACK 32
nkeynes@359
   110
static struct call_stack {
nkeynes@359
   111
    sh4addr_t call_addr;
nkeynes@359
   112
    sh4addr_t target_addr;
nkeynes@359
   113
    sh4addr_t stack_pointer;
nkeynes@359
   114
} call_stack[MAX_CALLSTACK];
nkeynes@359
   115
nkeynes@359
   116
static int call_stack_depth = 0;
nkeynes@359
   117
int sh4_call_trace_on = 0;
nkeynes@359
   118
nkeynes@430
   119
static inline void trace_call( sh4addr_t source, sh4addr_t dest ) 
nkeynes@359
   120
{
nkeynes@359
   121
    if( call_stack_depth < MAX_CALLSTACK ) {
nkeynes@359
   122
	call_stack[call_stack_depth].call_addr = source;
nkeynes@359
   123
	call_stack[call_stack_depth].target_addr = dest;
nkeynes@359
   124
	call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
nkeynes@359
   125
    }
nkeynes@359
   126
    call_stack_depth++;
nkeynes@359
   127
}
nkeynes@359
   128
nkeynes@430
   129
static inline void trace_return( sh4addr_t source, sh4addr_t dest )
nkeynes@359
   130
{
nkeynes@359
   131
    if( call_stack_depth > 0 ) {
nkeynes@359
   132
	call_stack_depth--;
nkeynes@359
   133
    }
nkeynes@359
   134
}
nkeynes@359
   135
nkeynes@359
   136
void fprint_stack_trace( FILE *f )
nkeynes@359
   137
{
nkeynes@359
   138
    int i = call_stack_depth -1;
nkeynes@359
   139
    if( i >= MAX_CALLSTACK )
nkeynes@359
   140
	i = MAX_CALLSTACK - 1;
nkeynes@359
   141
    for( ; i >= 0; i-- ) {
nkeynes@359
   142
	fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n", 
nkeynes@359
   143
		 (call_stack_depth - i), call_stack[i].call_addr,
nkeynes@359
   144
		 call_stack[i].target_addr, call_stack[i].stack_pointer );
nkeynes@359
   145
    }
nkeynes@359
   146
}
nkeynes@359
   147
nkeynes@359
   148
#define TRACE_CALL( source, dest ) trace_call(source, dest)
nkeynes@359
   149
#define TRACE_RETURN( source, dest ) trace_return(source, dest)
nkeynes@359
   150
#else
nkeynes@359
   151
#define TRACE_CALL( dest, rts ) 
nkeynes@359
   152
#define TRACE_RETURN( source, dest )
nkeynes@359
   153
#endif
nkeynes@359
   154
nkeynes@732
   155
#define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )
nkeynes@732
   156
#define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
nkeynes@732
   157
#define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
nkeynes@732
   158
#define CHECKRALIGN64(addr) if( (addr)&0x07 ) return sh4_raise_exception( EXC_DATA_ADDR_READ )
nkeynes@732
   159
#define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
nkeynes@732
   160
#define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
nkeynes@732
   161
#define CHECKWALIGN64(addr) if( (addr)&0x07 ) return sh4_raise_exception( EXC_DATA_ADDR_WRITE )
nkeynes@732
   162
nkeynes@732
   163
#define CHECKFPUEN() if( !IS_FPU_ENABLED() ) { if( ir == 0xFFFD ) { UNDEF(ir); } else { return sh4_raise_slot_exception( EXC_FPU_DISABLED, EXC_SLOT_FPU_DISABLED ); } }
nkeynes@740
   164
#define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_core_exit(CORE_EXIT_HALT); return FALSE; }
nkeynes@732
   165
#define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)
nkeynes@732
   166
nkeynes@586
   167
#define MEM_READ_BYTE( addr, val ) memtmp = mmu_vma_to_phys_read(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { val = sh4_read_byte(memtmp); }
nkeynes@586
   168
#define MEM_READ_WORD( addr, val ) memtmp = mmu_vma_to_phys_read(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { val = sh4_read_word(memtmp); }
nkeynes@586
   169
#define MEM_READ_LONG( addr, val ) memtmp = mmu_vma_to_phys_read(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { val = sh4_read_long(memtmp); }
nkeynes@586
   170
#define MEM_WRITE_BYTE( addr, val ) memtmp = mmu_vma_to_phys_write(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { sh4_write_byte(memtmp, val); }
nkeynes@586
   171
#define MEM_WRITE_WORD( addr, val ) memtmp = mmu_vma_to_phys_write(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { sh4_write_word(memtmp, val); }
nkeynes@586
   172
#define MEM_WRITE_LONG( addr, val ) memtmp = mmu_vma_to_phys_write(addr); if( memtmp == MMU_VMA_ERROR ) { return TRUE; } else { sh4_write_long(memtmp, val); }
nkeynes@359
   173
nkeynes@359
   174
#define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
nkeynes@359
   175
nkeynes@732
   176
#define MEM_FP_READ( addr, reg ) \
nkeynes@732
   177
    if( IS_FPU_DOUBLESIZE() ) { \
nkeynes@732
   178
	CHECKRALIGN64(addr); \
nkeynes@732
   179
	memtmp = mmu_vma_to_phys_read(addr); \
nkeynes@732
   180
	if( memtmp == MMU_VMA_ERROR ) { \
nkeynes@732
   181
	    return TRUE; \
nkeynes@732
   182
	} else { \
nkeynes@732
   183
	    if( reg & 1 ) { \
nkeynes@732
   184
                *((uint32_t *)&XF((reg) & 0x0E)) = sh4_read_long(memtmp); \
nkeynes@732
   185
	        *((uint32_t *)&XF(reg)) = sh4_read_long(memtmp+4); \
nkeynes@732
   186
	    } else { \
nkeynes@732
   187
	        *((uint32_t *)&FR(reg)) = sh4_read_long(memtmp); \
nkeynes@732
   188
	        *((uint32_t *)&FR((reg) | 0x01)) = sh4_read_long(memtmp+4); \
nkeynes@732
   189
	    } \
nkeynes@732
   190
	} \
nkeynes@732
   191
    } else { \
nkeynes@732
   192
        CHECKRALIGN32(addr); \
nkeynes@732
   193
        memtmp = mmu_vma_to_phys_read(addr); \
nkeynes@732
   194
        if( memtmp == MMU_VMA_ERROR ) { \
nkeynes@732
   195
            return TRUE; \
nkeynes@732
   196
        } else { \
nkeynes@732
   197
	    *((uint32_t *)&FR(reg)) = sh4_read_long(memtmp); \
nkeynes@732
   198
	} \
nkeynes@359
   199
    }
nkeynes@732
   200
#define MEM_FP_WRITE( addr, reg ) \
nkeynes@732
   201
    if( IS_FPU_DOUBLESIZE() ) { \
nkeynes@732
   202
        CHECKWALIGN64(addr); \
nkeynes@732
   203
	memtmp = mmu_vma_to_phys_write(addr); \
nkeynes@732
   204
	if( memtmp == MMU_VMA_ERROR ) { \
nkeynes@732
   205
	    return TRUE; \
nkeynes@732
   206
	} else { \
nkeynes@732
   207
            if( reg & 1 ) { \
nkeynes@732
   208
	        sh4_write_long( memtmp, *((uint32_t *)&XF((reg)&0x0E)) ); \
nkeynes@732
   209
	        sh4_write_long( memtmp+4, *((uint32_t *)&XF(reg)) ); \
nkeynes@732
   210
	    } else { \
nkeynes@736
   211
	        sh4_write_long( memtmp, *((uint32_t *)&FR(reg)) ); \
nkeynes@732
   212
	        sh4_write_long( memtmp+4, *((uint32_t *)&FR((reg)|0x01)) ); \
nkeynes@732
   213
	    } \
nkeynes@732
   214
	} \
nkeynes@732
   215
    } else { \
nkeynes@732
   216
    	CHECKWALIGN32(addr); \
nkeynes@732
   217
	memtmp = mmu_vma_to_phys_write(addr); \
nkeynes@732
   218
	if( memtmp == MMU_VMA_ERROR ) { \
nkeynes@732
   219
	    return TRUE; \
nkeynes@732
   220
	} else { \
nkeynes@732
   221
	    sh4_write_long( memtmp, *((uint32_t *)&FR((reg))) ); \
nkeynes@732
   222
	} \
nkeynes@359
   223
    }
nkeynes@359
   224
nkeynes@359
   225
gboolean sh4_execute_instruction( void )
nkeynes@359
   226
{
nkeynes@359
   227
    uint32_t pc;
nkeynes@359
   228
    unsigned short ir;
nkeynes@359
   229
    uint32_t tmp;
nkeynes@359
   230
    float ftmp;
nkeynes@359
   231
    double dtmp;
nkeynes@586
   232
    int64_t memtmp; // temporary holder for memory reads
nkeynes@359
   233
    
nkeynes@359
   234
#define R0 sh4r.r[0]
nkeynes@359
   235
    pc = sh4r.pc;
nkeynes@359
   236
    if( pc > 0xFFFFFF00 ) {
nkeynes@359
   237
	/* SYSCALL Magic */
nkeynes@359
   238
	syscall_invoke( pc );
nkeynes@359
   239
	sh4r.in_delay_slot = 0;
nkeynes@359
   240
	pc = sh4r.pc = sh4r.pr;
nkeynes@359
   241
	sh4r.new_pc = sh4r.pc + 2;
nkeynes@671
   242
        return TRUE;
nkeynes@359
   243
    }
nkeynes@359
   244
    CHECKRALIGN16(pc);
nkeynes@359
   245
nkeynes@671
   246
#ifdef ENABLE_SH4STATS
nkeynes@671
   247
    sh4_stats_add_by_pc(sh4r.pc);
nkeynes@671
   248
#endif
nkeynes@671
   249
nkeynes@359
   250
    /* Read instruction */
nkeynes@586
   251
    if( !IS_IN_ICACHE(pc) ) {
nkeynes@586
   252
	if( !mmu_update_icache(pc) ) {
nkeynes@586
   253
	    // Fault - look for the fault handler
nkeynes@586
   254
	    if( !mmu_update_icache(sh4r.pc) ) {
nkeynes@586
   255
		// double fault - halt
nkeynes@586
   256
		ERROR( "Double fault - halting" );
nkeynes@740
   257
		sh4_core_exit(CORE_EXIT_HALT);
nkeynes@586
   258
		return FALSE;
nkeynes@586
   259
	    }
nkeynes@359
   260
	}
nkeynes@586
   261
	pc = sh4r.pc;
nkeynes@359
   262
    }
nkeynes@586
   263
    assert( IS_IN_ICACHE(pc) );
nkeynes@586
   264
    ir = *(uint16_t *)GET_ICACHE_PTR(sh4r.pc);
nkeynes@359
   265
%%
nkeynes@359
   266
AND Rm, Rn {: sh4r.r[Rn] &= sh4r.r[Rm]; :}
nkeynes@359
   267
AND #imm, R0 {: R0 &= imm; :}
nkeynes@586
   268
 AND.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm & tmp ); :}
nkeynes@359
   269
NOT Rm, Rn {: sh4r.r[Rn] = ~sh4r.r[Rm]; :}
nkeynes@359
   270
OR Rm, Rn {: sh4r.r[Rn] |= sh4r.r[Rm]; :}
nkeynes@359
   271
OR #imm, R0  {: R0 |= imm; :}
nkeynes@586
   272
 OR.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm | tmp ); :}
nkeynes@359
   273
TAS.B @Rn {:
nkeynes@586
   274
    MEM_READ_BYTE( sh4r.r[Rn], tmp );
nkeynes@359
   275
    sh4r.t = ( tmp == 0 ? 1 : 0 );
nkeynes@359
   276
    MEM_WRITE_BYTE( sh4r.r[Rn], tmp | 0x80 );
nkeynes@359
   277
:}
nkeynes@359
   278
TST Rm, Rn {: sh4r.t = (sh4r.r[Rn]&sh4r.r[Rm] ? 0 : 1); :}
nkeynes@359
   279
TST #imm, R0 {: sh4r.t = (R0 & imm ? 0 : 1); :}
nkeynes@586
   280
 TST.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); sh4r.t = ( tmp & imm ? 0 : 1 ); :}
nkeynes@359
   281
XOR Rm, Rn {: sh4r.r[Rn] ^= sh4r.r[Rm]; :}
nkeynes@359
   282
XOR #imm, R0 {: R0 ^= imm; :}
nkeynes@586
   283
 XOR.B #imm, @(R0, GBR) {: MEM_READ_BYTE(R0+sh4r.gbr, tmp); MEM_WRITE_BYTE( R0 + sh4r.gbr, imm ^ tmp ); :}
nkeynes@359
   284
XTRCT Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rn]>>16) | (sh4r.r[Rm]<<16); :}
nkeynes@359
   285
nkeynes@359
   286
ROTL Rn {:
nkeynes@359
   287
    sh4r.t = sh4r.r[Rn] >> 31;
nkeynes@359
   288
    sh4r.r[Rn] <<= 1;
nkeynes@359
   289
    sh4r.r[Rn] |= sh4r.t;
nkeynes@359
   290
:}
nkeynes@359
   291
ROTR Rn {:
nkeynes@359
   292
    sh4r.t = sh4r.r[Rn] & 0x00000001;
nkeynes@359
   293
    sh4r.r[Rn] >>= 1;
nkeynes@359
   294
    sh4r.r[Rn] |= (sh4r.t << 31);
nkeynes@359
   295
:}
nkeynes@359
   296
ROTCL Rn {:
nkeynes@359
   297
    tmp = sh4r.r[Rn] >> 31;
nkeynes@359
   298
    sh4r.r[Rn] <<= 1;
nkeynes@359
   299
    sh4r.r[Rn] |= sh4r.t;
nkeynes@359
   300
    sh4r.t = tmp;
nkeynes@359
   301
:}
nkeynes@359
   302
ROTCR Rn {:
nkeynes@359
   303
    tmp = sh4r.r[Rn] & 0x00000001;
nkeynes@359
   304
    sh4r.r[Rn] >>= 1;
nkeynes@359
   305
    sh4r.r[Rn] |= (sh4r.t << 31 );
nkeynes@359
   306
    sh4r.t = tmp;
nkeynes@359
   307
:}
nkeynes@359
   308
SHAD Rm, Rn {:
nkeynes@359
   309
    tmp = sh4r.r[Rm];
nkeynes@359
   310
    if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
nkeynes@359
   311
    else if( (tmp & 0x1F) == 0 )  
nkeynes@359
   312
        sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 31;
nkeynes@359
   313
    else 
nkeynes@359
   314
	sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> (((~sh4r.r[Rm]) & 0x1F)+1);
nkeynes@359
   315
:}
nkeynes@359
   316
SHLD Rm, Rn {:
nkeynes@359
   317
    tmp = sh4r.r[Rm];
nkeynes@359
   318
    if( (tmp & 0x80000000) == 0 ) sh4r.r[Rn] <<= (tmp&0x1f);
nkeynes@359
   319
    else if( (tmp & 0x1F) == 0 ) sh4r.r[Rn] = 0;
nkeynes@359
   320
    else sh4r.r[Rn] >>= (((~tmp) & 0x1F)+1);
nkeynes@359
   321
:}
nkeynes@359
   322
SHAL Rn {:
nkeynes@359
   323
    sh4r.t = sh4r.r[Rn] >> 31;
nkeynes@359
   324
    sh4r.r[Rn] <<= 1;
nkeynes@359
   325
:}
nkeynes@359
   326
SHAR Rn {:
nkeynes@359
   327
    sh4r.t = sh4r.r[Rn] & 0x00000001;
nkeynes@359
   328
    sh4r.r[Rn] = ((int32_t)sh4r.r[Rn]) >> 1;
nkeynes@359
   329
:}
nkeynes@359
   330
SHLL Rn {: sh4r.t = sh4r.r[Rn] >> 31; sh4r.r[Rn] <<= 1; :}
nkeynes@359
   331
SHLR Rn {: sh4r.t = sh4r.r[Rn] & 0x00000001; sh4r.r[Rn] >>= 1; :}
nkeynes@359
   332
SHLL2 Rn {: sh4r.r[Rn] <<= 2; :}
nkeynes@359
   333
SHLR2 Rn {: sh4r.r[Rn] >>= 2; :}
nkeynes@359
   334
SHLL8 Rn {: sh4r.r[Rn] <<= 8; :}
nkeynes@359
   335
SHLR8 Rn {: sh4r.r[Rn] >>= 8; :}
nkeynes@359
   336
SHLL16 Rn {: sh4r.r[Rn] <<= 16; :}
nkeynes@359
   337
SHLR16 Rn {: sh4r.r[Rn] >>= 16; :}
nkeynes@359
   338
nkeynes@359
   339
EXTU.B Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x000000FF; :}
nkeynes@359
   340
EXTU.W Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]&0x0000FFFF; :}
nkeynes@359
   341
EXTS.B Rm, Rn {: sh4r.r[Rn] = SIGNEXT8( sh4r.r[Rm]&0x000000FF ); :}
nkeynes@359
   342
EXTS.W Rm, Rn {: sh4r.r[Rn] = SIGNEXT16( sh4r.r[Rm]&0x0000FFFF ); :}
nkeynes@359
   343
SWAP.B Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]&0xFFFF0000) | ((sh4r.r[Rm]&0x0000FF00)>>8) | ((sh4r.r[Rm]&0x000000FF)<<8); :}
nkeynes@359
   344
SWAP.W Rm, Rn {: sh4r.r[Rn] = (sh4r.r[Rm]>>16) | (sh4r.r[Rm]<<16); :}
nkeynes@359
   345
nkeynes@359
   346
CLRT {: sh4r.t = 0; :}
nkeynes@359
   347
SETT {: sh4r.t = 1; :}
nkeynes@359
   348
CLRMAC {: sh4r.mac = 0; :}
nkeynes@550
   349
LDTLB {: MMU_ldtlb(); :}
nkeynes@359
   350
CLRS {: sh4r.s = 0; :}
nkeynes@359
   351
SETS {: sh4r.s = 1; :}
nkeynes@359
   352
MOVT Rn {: sh4r.r[Rn] = sh4r.t; :}
nkeynes@359
   353
NOP {: /* NOP */ :}
nkeynes@359
   354
nkeynes@359
   355
PREF @Rn {:
nkeynes@359
   356
     tmp = sh4r.r[Rn];
nkeynes@359
   357
     if( (tmp & 0xFC000000) == 0xE0000000 ) {
nkeynes@369
   358
	 sh4_flush_store_queue(tmp);
nkeynes@359
   359
     }
nkeynes@359
   360
:}
nkeynes@359
   361
OCBI @Rn {: :}
nkeynes@359
   362
OCBP @Rn {: :}
nkeynes@359
   363
OCBWB @Rn {: :}
nkeynes@359
   364
MOVCA.L R0, @Rn {:
nkeynes@359
   365
    tmp = sh4r.r[Rn];
nkeynes@359
   366
    CHECKWALIGN32(tmp);
nkeynes@359
   367
    MEM_WRITE_LONG( tmp, R0 );
nkeynes@359
   368
:}
nkeynes@359
   369
MOV.B Rm, @(R0, Rn) {: MEM_WRITE_BYTE( R0 + sh4r.r[Rn], sh4r.r[Rm] ); :}
nkeynes@359
   370
MOV.W Rm, @(R0, Rn) {: 
nkeynes@359
   371
    CHECKWALIGN16( R0 + sh4r.r[Rn] );
nkeynes@359
   372
    MEM_WRITE_WORD( R0 + sh4r.r[Rn], sh4r.r[Rm] );
nkeynes@359
   373
:}
nkeynes@359
   374
MOV.L Rm, @(R0, Rn) {:
nkeynes@359
   375
    CHECKWALIGN32( R0 + sh4r.r[Rn] );
nkeynes@359
   376
    MEM_WRITE_LONG( R0 + sh4r.r[Rn], sh4r.r[Rm] );
nkeynes@359
   377
:}
nkeynes@586
   378
MOV.B @(R0, Rm), Rn {: MEM_READ_BYTE( R0 + sh4r.r[Rm], sh4r.r[Rn] ); :}
nkeynes@359
   379
MOV.W @(R0, Rm), Rn {: CHECKRALIGN16( R0 + sh4r.r[Rm] );
nkeynes@586
   380
    MEM_READ_WORD( R0 + sh4r.r[Rm], sh4r.r[Rn] );
nkeynes@359
   381
:}
nkeynes@359
   382
MOV.L @(R0, Rm), Rn {: CHECKRALIGN32( R0 + sh4r.r[Rm] );
nkeynes@586
   383
    MEM_READ_LONG( R0 + sh4r.r[Rm], sh4r.r[Rn] );
nkeynes@359
   384
:}
nkeynes@359
   385
MOV.L Rm, @(disp, Rn) {:
nkeynes@359
   386
    tmp = sh4r.r[Rn] + disp;
nkeynes@359
   387
    CHECKWALIGN32( tmp );
nkeynes@359
   388
    MEM_WRITE_LONG( tmp, sh4r.r[Rm] );
nkeynes@359
   389
:}
nkeynes@359
   390
MOV.B Rm, @Rn {: MEM_WRITE_BYTE( sh4r.r[Rn], sh4r.r[Rm] ); :}
nkeynes@359
   391
MOV.W Rm, @Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn], sh4r.r[Rm] ); :}
nkeynes@359
   392
MOV.L Rm, @Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn], sh4r.r[Rm] ); :}
nkeynes@587
   393
 MOV.B Rm, @-Rn {: MEM_WRITE_BYTE( sh4r.r[Rn]-1, sh4r.r[Rm] ); sh4r.r[Rn]--; :}
nkeynes@587
   394
 MOV.W Rm, @-Rn {: CHECKWALIGN16( sh4r.r[Rn] ); MEM_WRITE_WORD( sh4r.r[Rn]-2, sh4r.r[Rm] ); sh4r.r[Rn] -= 2; :}
nkeynes@587
   395
 MOV.L Rm, @-Rn {: CHECKWALIGN32( sh4r.r[Rn] ); MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r[Rm] ); sh4r.r[Rn] -= 4; :}
nkeynes@359
   396
MOV.L @(disp, Rm), Rn {:
nkeynes@359
   397
    tmp = sh4r.r[Rm] + disp;
nkeynes@359
   398
    CHECKRALIGN32( tmp );
nkeynes@586
   399
    MEM_READ_LONG( tmp, sh4r.r[Rn] );
nkeynes@359
   400
:}
nkeynes@586
   401
MOV.B @Rm, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); :}
nkeynes@586
   402
 MOV.W @Rm, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); :}
nkeynes@586
   403
 MOV.L @Rm, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); :}
nkeynes@359
   404
MOV Rm, Rn {: sh4r.r[Rn] = sh4r.r[Rm]; :}
nkeynes@586
   405
 MOV.B @Rm+, Rn {: MEM_READ_BYTE( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] ++; :}
nkeynes@586
   406
 MOV.W @Rm+, Rn {: CHECKRALIGN16( sh4r.r[Rm] ); MEM_READ_WORD( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] += 2; :}
nkeynes@586
   407
 MOV.L @Rm+, Rn {: CHECKRALIGN32( sh4r.r[Rm] ); MEM_READ_LONG( sh4r.r[Rm], sh4r.r[Rn] ); sh4r.r[Rm] += 4; :}
nkeynes@359
   408
MOV.L @(disp, PC), Rn {:
nkeynes@359
   409
    CHECKSLOTILLEGAL();
nkeynes@359
   410
    tmp = (pc&0xFFFFFFFC) + disp + 4;
nkeynes@586
   411
    MEM_READ_LONG( tmp, sh4r.r[Rn] );
nkeynes@359
   412
:}
nkeynes@359
   413
MOV.B R0, @(disp, GBR) {: MEM_WRITE_BYTE( sh4r.gbr + disp, R0 ); :}
nkeynes@359
   414
MOV.W R0, @(disp, GBR) {:
nkeynes@359
   415
    tmp = sh4r.gbr + disp;
nkeynes@359
   416
    CHECKWALIGN16( tmp );
nkeynes@359
   417
    MEM_WRITE_WORD( tmp, R0 );
nkeynes@359
   418
:}
nkeynes@359
   419
MOV.L R0, @(disp, GBR) {:
nkeynes@359
   420
    tmp = sh4r.gbr + disp;
nkeynes@359
   421
    CHECKWALIGN32( tmp );
nkeynes@359
   422
    MEM_WRITE_LONG( tmp, R0 );
nkeynes@359
   423
:}
nkeynes@586
   424
 MOV.B @(disp, GBR), R0 {: MEM_READ_BYTE( sh4r.gbr + disp, R0 ); :}
nkeynes@359
   425
MOV.W @(disp, GBR), R0 {: 
nkeynes@359
   426
    tmp = sh4r.gbr + disp;
nkeynes@359
   427
    CHECKRALIGN16( tmp );
nkeynes@586
   428
    MEM_READ_WORD( tmp, R0 );
nkeynes@359
   429
:}
nkeynes@359
   430
MOV.L @(disp, GBR), R0 {:
nkeynes@359
   431
    tmp = sh4r.gbr + disp;
nkeynes@359
   432
    CHECKRALIGN32( tmp );
nkeynes@586
   433
    MEM_READ_LONG( tmp, R0 );
nkeynes@359
   434
:}
nkeynes@359
   435
MOV.B R0, @(disp, Rn) {: MEM_WRITE_BYTE( sh4r.r[Rn] + disp, R0 ); :}
nkeynes@359
   436
MOV.W R0, @(disp, Rn) {: 
nkeynes@359
   437
    tmp = sh4r.r[Rn] + disp;
nkeynes@359
   438
    CHECKWALIGN16( tmp );
nkeynes@359
   439
    MEM_WRITE_WORD( tmp, R0 );
nkeynes@359
   440
:}
nkeynes@586
   441
 MOV.B @(disp, Rm), R0 {: MEM_READ_BYTE( sh4r.r[Rm] + disp, R0 ); :}
nkeynes@359
   442
MOV.W @(disp, Rm), R0 {: 
nkeynes@359
   443
    tmp = sh4r.r[Rm] + disp;
nkeynes@359
   444
    CHECKRALIGN16( tmp );
nkeynes@586
   445
    MEM_READ_WORD( tmp, R0 );
nkeynes@359
   446
:}
nkeynes@359
   447
MOV.W @(disp, PC), Rn {:
nkeynes@359
   448
    CHECKSLOTILLEGAL();
nkeynes@359
   449
    tmp = pc + 4 + disp;
nkeynes@586
   450
    MEM_READ_WORD( tmp, sh4r.r[Rn] );
nkeynes@359
   451
:}
nkeynes@359
   452
MOVA @(disp, PC), R0 {:
nkeynes@359
   453
    CHECKSLOTILLEGAL();
nkeynes@359
   454
    R0 = (pc&0xFFFFFFFC) + disp + 4;
nkeynes@359
   455
:}
nkeynes@359
   456
MOV #imm, Rn {:  sh4r.r[Rn] = imm; :}
nkeynes@359
   457
nkeynes@732
   458
FMOV @(R0, Rm), FRn {: MEM_FP_READ( sh4r.r[Rm] + R0, FRn ); :}
nkeynes@732
   459
FMOV FRm, @(R0, Rn) {: MEM_FP_WRITE( sh4r.r[Rn] + R0, FRm ); :}
nkeynes@732
   460
FMOV @Rm, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); :}
nkeynes@732
   461
FMOV @Rm+, FRn {: MEM_FP_READ( sh4r.r[Rm], FRn ); sh4r.r[Rm] += FP_WIDTH; :}
nkeynes@732
   462
FMOV FRm, @Rn {: MEM_FP_WRITE( sh4r.r[Rn], FRm ); :}
nkeynes@732
   463
 FMOV FRm, @-Rn {: MEM_FP_WRITE( sh4r.r[Rn] - FP_WIDTH, FRm ); sh4r.r[Rn] -= FP_WIDTH; :}
nkeynes@732
   464
FMOV FRm, FRn {: 
nkeynes@732
   465
    if( IS_FPU_DOUBLESIZE() )
nkeynes@732
   466
	DR(FRn) = DR(FRm);
nkeynes@732
   467
    else
nkeynes@732
   468
	FR(FRn) = FR(FRm);
nkeynes@732
   469
:}
nkeynes@732
   470
nkeynes@359
   471
CMP/EQ #imm, R0 {: sh4r.t = ( R0 == imm ? 1 : 0 ); :}
nkeynes@359
   472
CMP/EQ Rm, Rn {: sh4r.t = ( sh4r.r[Rm] == sh4r.r[Rn] ? 1 : 0 ); :}
nkeynes@359
   473
CMP/GE Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
nkeynes@359
   474
CMP/GT Rm, Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > ((int32_t)sh4r.r[Rm]) ? 1 : 0 ); :}
nkeynes@359
   475
CMP/HI Rm, Rn {: sh4r.t = ( sh4r.r[Rn] > sh4r.r[Rm] ? 1 : 0 ); :}
nkeynes@359
   476
CMP/HS Rm, Rn {: sh4r.t = ( sh4r.r[Rn] >= sh4r.r[Rm] ? 1 : 0 ); :}
nkeynes@359
   477
CMP/PL Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) > 0 ? 1 : 0 ); :}
nkeynes@359
   478
CMP/PZ Rn {: sh4r.t = ( ((int32_t)sh4r.r[Rn]) >= 0 ? 1 : 0 ); :}
nkeynes@359
   479
CMP/STR Rm, Rn {: 
nkeynes@359
   480
    /* set T = 1 if any byte in RM & RN is the same */
nkeynes@359
   481
    tmp = sh4r.r[Rm] ^ sh4r.r[Rn];
nkeynes@359
   482
    sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
nkeynes@359
   483
             (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
nkeynes@359
   484
:}
nkeynes@359
   485
nkeynes@359
   486
ADD Rm, Rn {: sh4r.r[Rn] += sh4r.r[Rm]; :}
nkeynes@359
   487
ADD #imm, Rn {: sh4r.r[Rn] += imm; :}
nkeynes@359
   488
ADDC Rm, Rn {:
nkeynes@359
   489
    tmp = sh4r.r[Rn];
nkeynes@359
   490
    sh4r.r[Rn] += sh4r.r[Rm] + sh4r.t;
nkeynes@359
   491
    sh4r.t = ( sh4r.r[Rn] < tmp || (sh4r.r[Rn] == tmp && sh4r.t != 0) ? 1 : 0 );
nkeynes@359
   492
:}
nkeynes@359
   493
ADDV Rm, Rn {:
nkeynes@359
   494
    tmp = sh4r.r[Rn] + sh4r.r[Rm];
nkeynes@359
   495
    sh4r.t = ( (sh4r.r[Rn]>>31) == (sh4r.r[Rm]>>31) && ((sh4r.r[Rn]>>31) != (tmp>>31)) );
nkeynes@359
   496
    sh4r.r[Rn] = tmp;
nkeynes@359
   497
:}
nkeynes@359
   498
DIV0U {: sh4r.m = sh4r.q = sh4r.t = 0; :}
nkeynes@359
   499
DIV0S Rm, Rn {: 
nkeynes@359
   500
    sh4r.q = sh4r.r[Rn]>>31;
nkeynes@359
   501
    sh4r.m = sh4r.r[Rm]>>31;
nkeynes@359
   502
    sh4r.t = sh4r.q ^ sh4r.m;
nkeynes@359
   503
:}
nkeynes@359
   504
DIV1 Rm, Rn {:
nkeynes@384
   505
    /* This is derived from the sh4 manual with some simplifications */
nkeynes@359
   506
    uint32_t tmp0, tmp1, tmp2, dir;
nkeynes@359
   507
nkeynes@359
   508
    dir = sh4r.q ^ sh4r.m;
nkeynes@359
   509
    sh4r.q = (sh4r.r[Rn] >> 31);
nkeynes@359
   510
    tmp2 = sh4r.r[Rm];
nkeynes@359
   511
    sh4r.r[Rn] = (sh4r.r[Rn] << 1) | sh4r.t;
nkeynes@359
   512
    tmp0 = sh4r.r[Rn];
nkeynes@359
   513
    if( dir ) {
nkeynes@359
   514
         sh4r.r[Rn] += tmp2;
nkeynes@359
   515
         tmp1 = (sh4r.r[Rn]<tmp0 ? 1 : 0 );
nkeynes@359
   516
    } else {
nkeynes@359
   517
         sh4r.r[Rn] -= tmp2;
nkeynes@359
   518
         tmp1 = (sh4r.r[Rn]>tmp0 ? 1 : 0 );
nkeynes@359
   519
    }
nkeynes@359
   520
    sh4r.q ^= sh4r.m ^ tmp1;
nkeynes@359
   521
    sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
nkeynes@359
   522
:}
nkeynes@359
   523
DMULS.L Rm, Rn {: sh4r.mac = SIGNEXT32(sh4r.r[Rm]) * SIGNEXT32(sh4r.r[Rn]); :}
nkeynes@359
   524
DMULU.L Rm, Rn {: sh4r.mac = ((uint64_t)sh4r.r[Rm]) * ((uint64_t)sh4r.r[Rn]); :}
nkeynes@359
   525
DT Rn {:
nkeynes@359
   526
    sh4r.r[Rn] --;
nkeynes@359
   527
    sh4r.t = ( sh4r.r[Rn] == 0 ? 1 : 0 );
nkeynes@359
   528
:}
nkeynes@359
   529
MAC.W @Rm+, @Rn+ {:
nkeynes@587
   530
    int32_t stmp;
nkeynes@587
   531
    if( Rm == Rn ) {
nkeynes@587
   532
	CHECKRALIGN16(sh4r.r[Rn]);
nkeynes@587
   533
	MEM_READ_WORD( sh4r.r[Rn], tmp );
nkeynes@587
   534
	stmp = SIGNEXT16(tmp);
nkeynes@587
   535
	MEM_READ_WORD( sh4r.r[Rn]+2, tmp );
nkeynes@587
   536
	stmp *= SIGNEXT16(tmp);
nkeynes@587
   537
	sh4r.r[Rn] += 4;
nkeynes@587
   538
    } else {
nkeynes@587
   539
	CHECKRALIGN16( sh4r.r[Rn] );
nkeynes@587
   540
	CHECKRALIGN16( sh4r.r[Rm] );
nkeynes@587
   541
	MEM_READ_WORD(sh4r.r[Rn], tmp);
nkeynes@587
   542
	stmp = SIGNEXT16(tmp);
nkeynes@587
   543
	MEM_READ_WORD(sh4r.r[Rm], tmp);
nkeynes@587
   544
	stmp = stmp * SIGNEXT16(tmp);
nkeynes@587
   545
	sh4r.r[Rn] += 2;
nkeynes@587
   546
	sh4r.r[Rm] += 2;
nkeynes@587
   547
    }
nkeynes@359
   548
    if( sh4r.s ) {
nkeynes@359
   549
	int64_t tmpl = (int64_t)((int32_t)sh4r.mac) + (int64_t)stmp;
nkeynes@359
   550
	if( tmpl > (int64_t)0x000000007FFFFFFFLL ) {
nkeynes@359
   551
	    sh4r.mac = 0x000000017FFFFFFFLL;
nkeynes@359
   552
	} else if( tmpl < (int64_t)0xFFFFFFFF80000000LL ) {
nkeynes@359
   553
	    sh4r.mac = 0x0000000180000000LL;
nkeynes@359
   554
	} else {
nkeynes@359
   555
	    sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
nkeynes@359
   556
		((uint32_t)(sh4r.mac + stmp));
nkeynes@359
   557
	}
nkeynes@359
   558
    } else {
nkeynes@359
   559
	sh4r.mac += SIGNEXT32(stmp);
nkeynes@359
   560
    }
nkeynes@359
   561
:}
nkeynes@359
   562
MAC.L @Rm+, @Rn+ {:
nkeynes@587
   563
    int64_t tmpl;
nkeynes@587
   564
    if( Rm == Rn ) {
nkeynes@587
   565
	CHECKRALIGN32( sh4r.r[Rn] );
nkeynes@587
   566
	MEM_READ_LONG(sh4r.r[Rn], tmp);
nkeynes@587
   567
	tmpl = SIGNEXT32(tmp);
nkeynes@587
   568
	MEM_READ_LONG(sh4r.r[Rn]+4, tmp);
nkeynes@587
   569
	tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
nkeynes@587
   570
	sh4r.r[Rn] += 8;
nkeynes@587
   571
    } else {
nkeynes@587
   572
	CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@587
   573
	CHECKRALIGN32( sh4r.r[Rn] );
nkeynes@587
   574
	MEM_READ_LONG(sh4r.r[Rn], tmp);
nkeynes@587
   575
	tmpl = SIGNEXT32(tmp);
nkeynes@587
   576
	MEM_READ_LONG(sh4r.r[Rm], tmp);
nkeynes@587
   577
	tmpl = tmpl * SIGNEXT32(tmp) + sh4r.mac;
nkeynes@587
   578
	sh4r.r[Rn] += 4;
nkeynes@587
   579
	sh4r.r[Rm] += 4;
nkeynes@587
   580
    }
nkeynes@359
   581
    if( sh4r.s ) {
nkeynes@359
   582
        /* 48-bit Saturation. Yuch */
nkeynes@359
   583
        if( tmpl < (int64_t)0xFFFF800000000000LL )
nkeynes@359
   584
            tmpl = 0xFFFF800000000000LL;
nkeynes@359
   585
        else if( tmpl > (int64_t)0x00007FFFFFFFFFFFLL )
nkeynes@359
   586
            tmpl = 0x00007FFFFFFFFFFFLL;
nkeynes@359
   587
    }
nkeynes@359
   588
    sh4r.mac = tmpl;
nkeynes@359
   589
:}
nkeynes@359
   590
MUL.L Rm, Rn {: sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
nkeynes@359
   591
                        (sh4r.r[Rm] * sh4r.r[Rn]); :}
nkeynes@359
   592
MULU.W Rm, Rn {:
nkeynes@359
   593
    sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
nkeynes@359
   594
               (uint32_t)((sh4r.r[Rm]&0xFFFF) * (sh4r.r[Rn]&0xFFFF));
nkeynes@359
   595
:}
nkeynes@359
   596
MULS.W Rm, Rn {:
nkeynes@359
   597
    sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
nkeynes@359
   598
               (uint32_t)(SIGNEXT32(sh4r.r[Rm]&0xFFFF) * SIGNEXT32(sh4r.r[Rn]&0xFFFF));
nkeynes@359
   599
:}
nkeynes@359
   600
NEGC Rm, Rn {:
nkeynes@359
   601
    tmp = 0 - sh4r.r[Rm];
nkeynes@359
   602
    sh4r.r[Rn] = tmp - sh4r.t;
nkeynes@359
   603
    sh4r.t = ( 0<tmp || tmp<sh4r.r[Rn] ? 1 : 0 );
nkeynes@359
   604
:}
nkeynes@359
   605
NEG Rm, Rn {: sh4r.r[Rn] = 0 - sh4r.r[Rm]; :}
nkeynes@359
   606
SUB Rm, Rn {: sh4r.r[Rn] -= sh4r.r[Rm]; :}
nkeynes@359
   607
SUBC Rm, Rn {: 
nkeynes@359
   608
    tmp = sh4r.r[Rn];
nkeynes@359
   609
    sh4r.r[Rn] = sh4r.r[Rn] - sh4r.r[Rm] - sh4r.t;
nkeynes@359
   610
    sh4r.t = (sh4r.r[Rn] > tmp || (sh4r.r[Rn] == tmp && sh4r.t == 1));
nkeynes@359
   611
:}
nkeynes@359
   612
nkeynes@359
   613
BRAF Rn {:
nkeynes@359
   614
     CHECKSLOTILLEGAL();
nkeynes@359
   615
     CHECKDEST( pc + 4 + sh4r.r[Rn] );
nkeynes@359
   616
     sh4r.in_delay_slot = 1;
nkeynes@359
   617
     sh4r.pc = sh4r.new_pc;
nkeynes@359
   618
     sh4r.new_pc = pc + 4 + sh4r.r[Rn];
nkeynes@359
   619
     return TRUE;
nkeynes@359
   620
:}
nkeynes@359
   621
BSRF Rn {:
nkeynes@359
   622
     CHECKSLOTILLEGAL();
nkeynes@359
   623
     CHECKDEST( pc + 4 + sh4r.r[Rn] );
nkeynes@359
   624
     sh4r.in_delay_slot = 1;
nkeynes@359
   625
     sh4r.pr = sh4r.pc + 4;
nkeynes@359
   626
     sh4r.pc = sh4r.new_pc;
nkeynes@359
   627
     sh4r.new_pc = pc + 4 + sh4r.r[Rn];
nkeynes@359
   628
     TRACE_CALL( pc, sh4r.new_pc );
nkeynes@359
   629
     return TRUE;
nkeynes@359
   630
:}
nkeynes@359
   631
BT disp {:
nkeynes@359
   632
    CHECKSLOTILLEGAL();
nkeynes@359
   633
    if( sh4r.t ) {
nkeynes@359
   634
        CHECKDEST( sh4r.pc + disp + 4 )
nkeynes@359
   635
        sh4r.pc += disp + 4;
nkeynes@359
   636
        sh4r.new_pc = sh4r.pc + 2;
nkeynes@359
   637
        return TRUE;
nkeynes@359
   638
    }
nkeynes@359
   639
:}
nkeynes@359
   640
BF disp {:
nkeynes@359
   641
    CHECKSLOTILLEGAL();
nkeynes@359
   642
    if( !sh4r.t ) {
nkeynes@359
   643
        CHECKDEST( sh4r.pc + disp + 4 )
nkeynes@359
   644
        sh4r.pc += disp + 4;
nkeynes@359
   645
        sh4r.new_pc = sh4r.pc + 2;
nkeynes@359
   646
        return TRUE;
nkeynes@359
   647
    }
nkeynes@359
   648
:}
nkeynes@359
   649
BT/S disp {:
nkeynes@359
   650
    CHECKSLOTILLEGAL();
nkeynes@359
   651
    if( sh4r.t ) {
nkeynes@359
   652
        CHECKDEST( sh4r.pc + disp + 4 )
nkeynes@359
   653
        sh4r.in_delay_slot = 1;
nkeynes@359
   654
        sh4r.pc = sh4r.new_pc;
nkeynes@359
   655
        sh4r.new_pc = pc + disp + 4;
nkeynes@359
   656
        sh4r.in_delay_slot = 1;
nkeynes@359
   657
        return TRUE;
nkeynes@359
   658
    }
nkeynes@359
   659
:}
nkeynes@359
   660
BF/S disp {:
nkeynes@359
   661
    CHECKSLOTILLEGAL();
nkeynes@359
   662
    if( !sh4r.t ) {
nkeynes@359
   663
        CHECKDEST( sh4r.pc + disp + 4 )
nkeynes@359
   664
        sh4r.in_delay_slot = 1;
nkeynes@359
   665
        sh4r.pc = sh4r.new_pc;
nkeynes@359
   666
        sh4r.new_pc = pc + disp + 4;
nkeynes@359
   667
        return TRUE;
nkeynes@359
   668
    }
nkeynes@359
   669
:}
nkeynes@359
   670
BRA disp {:
nkeynes@359
   671
    CHECKSLOTILLEGAL();
nkeynes@359
   672
    CHECKDEST( sh4r.pc + disp + 4 );
nkeynes@359
   673
    sh4r.in_delay_slot = 1;
nkeynes@359
   674
    sh4r.pc = sh4r.new_pc;
nkeynes@359
   675
    sh4r.new_pc = pc + 4 + disp;
nkeynes@359
   676
    return TRUE;
nkeynes@359
   677
:}
nkeynes@359
   678
BSR disp {:
nkeynes@359
   679
    CHECKDEST( sh4r.pc + disp + 4 );
nkeynes@359
   680
    CHECKSLOTILLEGAL();
nkeynes@359
   681
    sh4r.in_delay_slot = 1;
nkeynes@359
   682
    sh4r.pr = pc + 4;
nkeynes@359
   683
    sh4r.pc = sh4r.new_pc;
nkeynes@359
   684
    sh4r.new_pc = pc + 4 + disp;
nkeynes@359
   685
    TRACE_CALL( pc, sh4r.new_pc );
nkeynes@359
   686
    return TRUE;
nkeynes@359
   687
:}
nkeynes@359
   688
TRAPA #imm {:
nkeynes@359
   689
    CHECKSLOTILLEGAL();
nkeynes@359
   690
    sh4r.pc += 2;
nkeynes@586
   691
    sh4_raise_trap( imm );
nkeynes@586
   692
    return TRUE;
nkeynes@359
   693
:}
nkeynes@359
   694
RTS {: 
nkeynes@359
   695
    CHECKSLOTILLEGAL();
nkeynes@359
   696
    CHECKDEST( sh4r.pr );
nkeynes@359
   697
    sh4r.in_delay_slot = 1;
nkeynes@359
   698
    sh4r.pc = sh4r.new_pc;
nkeynes@359
   699
    sh4r.new_pc = sh4r.pr;
nkeynes@359
   700
    TRACE_RETURN( pc, sh4r.new_pc );
nkeynes@359
   701
    return TRUE;
nkeynes@359
   702
:}
nkeynes@359
   703
SLEEP {:
nkeynes@359
   704
    if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
nkeynes@359
   705
	sh4r.sh4_state = SH4_STATE_STANDBY;
nkeynes@359
   706
    } else {
nkeynes@359
   707
	sh4r.sh4_state = SH4_STATE_SLEEP;
nkeynes@359
   708
    }
nkeynes@359
   709
    return FALSE; /* Halt CPU */
nkeynes@359
   710
:}
nkeynes@359
   711
RTE {:
nkeynes@359
   712
    CHECKPRIV();
nkeynes@359
   713
    CHECKDEST( sh4r.spc );
nkeynes@359
   714
    CHECKSLOTILLEGAL();
nkeynes@359
   715
    sh4r.in_delay_slot = 1;
nkeynes@359
   716
    sh4r.pc = sh4r.new_pc;
nkeynes@359
   717
    sh4r.new_pc = sh4r.spc;
nkeynes@374
   718
    sh4_write_sr( sh4r.ssr );
nkeynes@359
   719
    return TRUE;
nkeynes@359
   720
:}
nkeynes@359
   721
JMP @Rn {:
nkeynes@359
   722
    CHECKDEST( sh4r.r[Rn] );
nkeynes@359
   723
    CHECKSLOTILLEGAL();
nkeynes@359
   724
    sh4r.in_delay_slot = 1;
nkeynes@359
   725
    sh4r.pc = sh4r.new_pc;
nkeynes@359
   726
    sh4r.new_pc = sh4r.r[Rn];
nkeynes@359
   727
    return TRUE;
nkeynes@359
   728
:}
nkeynes@359
   729
JSR @Rn {:
nkeynes@359
   730
    CHECKDEST( sh4r.r[Rn] );
nkeynes@359
   731
    CHECKSLOTILLEGAL();
nkeynes@359
   732
    sh4r.in_delay_slot = 1;
nkeynes@359
   733
    sh4r.pc = sh4r.new_pc;
nkeynes@359
   734
    sh4r.new_pc = sh4r.r[Rn];
nkeynes@359
   735
    sh4r.pr = pc + 4;
nkeynes@359
   736
    TRACE_CALL( pc, sh4r.new_pc );
nkeynes@359
   737
    return TRUE;
nkeynes@359
   738
:}
nkeynes@359
   739
STS MACH, Rn {: sh4r.r[Rn] = (sh4r.mac>>32); :}
nkeynes@359
   740
STS.L MACH, @-Rn {:
nkeynes@587
   741
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   742
    MEM_WRITE_LONG( sh4r.r[Rn]-4, (sh4r.mac>>32) );
nkeynes@359
   743
    sh4r.r[Rn] -= 4;
nkeynes@359
   744
:}
nkeynes@359
   745
STC.L SR, @-Rn {:
nkeynes@359
   746
    CHECKPRIV();
nkeynes@587
   747
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   748
    MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4_read_sr() );
nkeynes@359
   749
    sh4r.r[Rn] -= 4;
nkeynes@359
   750
:}
nkeynes@359
   751
LDS.L @Rm+, MACH {:
nkeynes@359
   752
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@586
   753
    MEM_READ_LONG(sh4r.r[Rm], tmp);
nkeynes@359
   754
    sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
nkeynes@586
   755
	(((uint64_t)tmp)<<32);
nkeynes@359
   756
    sh4r.r[Rm] += 4;
nkeynes@359
   757
:}
nkeynes@359
   758
LDC.L @Rm+, SR {:
nkeynes@359
   759
    CHECKSLOTILLEGAL();
nkeynes@359
   760
    CHECKPRIV();
nkeynes@359
   761
    CHECKWALIGN32( sh4r.r[Rm] );
nkeynes@586
   762
    MEM_READ_LONG(sh4r.r[Rm], tmp);
nkeynes@586
   763
    sh4_write_sr( tmp );
nkeynes@359
   764
    sh4r.r[Rm] +=4;
nkeynes@359
   765
:}
nkeynes@359
   766
LDS Rm, MACH {:
nkeynes@359
   767
    sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
nkeynes@359
   768
               (((uint64_t)sh4r.r[Rm])<<32);
nkeynes@359
   769
:}
nkeynes@359
   770
LDC Rm, SR {:
nkeynes@359
   771
    CHECKSLOTILLEGAL();
nkeynes@359
   772
    CHECKPRIV();
nkeynes@374
   773
    sh4_write_sr( sh4r.r[Rm] );
nkeynes@359
   774
:}
nkeynes@359
   775
LDC Rm, SGR {:
nkeynes@359
   776
    CHECKPRIV();
nkeynes@359
   777
    sh4r.sgr = sh4r.r[Rm];
nkeynes@359
   778
:}
nkeynes@359
   779
LDC.L @Rm+, SGR {:
nkeynes@359
   780
    CHECKPRIV();
nkeynes@359
   781
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@586
   782
    MEM_READ_LONG(sh4r.r[Rm], sh4r.sgr);
nkeynes@359
   783
    sh4r.r[Rm] +=4;
nkeynes@359
   784
:}
nkeynes@359
   785
STS MACL, Rn {: sh4r.r[Rn] = (uint32_t)sh4r.mac; :}
nkeynes@359
   786
STS.L MACL, @-Rn {:
nkeynes@587
   787
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   788
    MEM_WRITE_LONG( sh4r.r[Rn]-4, (uint32_t)sh4r.mac );
nkeynes@359
   789
    sh4r.r[Rn] -= 4;
nkeynes@359
   790
:}
nkeynes@359
   791
STC.L GBR, @-Rn {:
nkeynes@587
   792
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   793
    MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.gbr );
nkeynes@359
   794
    sh4r.r[Rn] -= 4;
nkeynes@359
   795
:}
nkeynes@359
   796
LDS.L @Rm+, MACL {:
nkeynes@359
   797
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@586
   798
    MEM_READ_LONG(sh4r.r[Rm], tmp);
nkeynes@359
   799
    sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
nkeynes@586
   800
               (uint64_t)((uint32_t)tmp);
nkeynes@359
   801
    sh4r.r[Rm] += 4;
nkeynes@359
   802
:}
nkeynes@359
   803
LDC.L @Rm+, GBR {:
nkeynes@359
   804
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@586
   805
    MEM_READ_LONG(sh4r.r[Rm], sh4r.gbr);
nkeynes@359
   806
    sh4r.r[Rm] +=4;
nkeynes@359
   807
:}
nkeynes@359
   808
LDS Rm, MACL {:
nkeynes@359
   809
    sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
nkeynes@359
   810
               (uint64_t)((uint32_t)(sh4r.r[Rm]));
nkeynes@359
   811
:}
nkeynes@359
   812
LDC Rm, GBR {: sh4r.gbr = sh4r.r[Rm]; :}
nkeynes@359
   813
STS PR, Rn {: sh4r.r[Rn] = sh4r.pr; :}
nkeynes@359
   814
STS.L PR, @-Rn {:
nkeynes@587
   815
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   816
    MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.pr );
nkeynes@359
   817
    sh4r.r[Rn] -= 4;
nkeynes@359
   818
:}
nkeynes@359
   819
STC.L VBR, @-Rn {:
nkeynes@359
   820
    CHECKPRIV();
nkeynes@587
   821
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   822
    MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.vbr );
nkeynes@359
   823
    sh4r.r[Rn] -= 4;
nkeynes@359
   824
:}
nkeynes@359
   825
LDS.L @Rm+, PR {:
nkeynes@359
   826
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@586
   827
    MEM_READ_LONG( sh4r.r[Rm], sh4r.pr );
nkeynes@359
   828
    sh4r.r[Rm] += 4;
nkeynes@359
   829
:}
nkeynes@359
   830
LDC.L @Rm+, VBR {:
nkeynes@359
   831
    CHECKPRIV();
nkeynes@359
   832
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@586
   833
    MEM_READ_LONG(sh4r.r[Rm], sh4r.vbr);
nkeynes@359
   834
    sh4r.r[Rm] +=4;
nkeynes@359
   835
:}
nkeynes@359
   836
LDS Rm, PR {: sh4r.pr = sh4r.r[Rm]; :}
nkeynes@359
   837
LDC Rm, VBR {:
nkeynes@359
   838
    CHECKPRIV();
nkeynes@359
   839
    sh4r.vbr = sh4r.r[Rm];
nkeynes@359
   840
:}
nkeynes@359
   841
STC SGR, Rn {:
nkeynes@359
   842
    CHECKPRIV();
nkeynes@359
   843
    sh4r.r[Rn] = sh4r.sgr;
nkeynes@359
   844
:}
nkeynes@359
   845
STC.L SGR, @-Rn {:
nkeynes@359
   846
    CHECKPRIV();
nkeynes@587
   847
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   848
    MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.sgr );
nkeynes@359
   849
    sh4r.r[Rn] -= 4;
nkeynes@359
   850
:}
nkeynes@359
   851
STC.L SSR, @-Rn {:
nkeynes@359
   852
    CHECKPRIV();
nkeynes@587
   853
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   854
    MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.ssr );
nkeynes@359
   855
    sh4r.r[Rn] -= 4;
nkeynes@359
   856
:}
nkeynes@359
   857
LDC.L @Rm+, SSR {:
nkeynes@359
   858
    CHECKPRIV();
nkeynes@359
   859
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@586
   860
    MEM_READ_LONG(sh4r.r[Rm], sh4r.ssr);
nkeynes@359
   861
    sh4r.r[Rm] +=4;
nkeynes@359
   862
:}
nkeynes@359
   863
LDC Rm, SSR {:
nkeynes@359
   864
    CHECKPRIV();
nkeynes@359
   865
    sh4r.ssr = sh4r.r[Rm];
nkeynes@359
   866
:}
nkeynes@359
   867
STC.L SPC, @-Rn {:
nkeynes@359
   868
    CHECKPRIV();
nkeynes@587
   869
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   870
    MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.spc );
nkeynes@359
   871
    sh4r.r[Rn] -= 4;
nkeynes@359
   872
:}
nkeynes@359
   873
LDC.L @Rm+, SPC {:
nkeynes@359
   874
    CHECKPRIV();
nkeynes@359
   875
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@586
   876
    MEM_READ_LONG(sh4r.r[Rm], sh4r.spc);
nkeynes@359
   877
    sh4r.r[Rm] +=4;
nkeynes@359
   878
:}
nkeynes@359
   879
LDC Rm, SPC {:
nkeynes@359
   880
    CHECKPRIV();
nkeynes@359
   881
    sh4r.spc = sh4r.r[Rm];
nkeynes@359
   882
:}
nkeynes@626
   883
STS FPUL, Rn {: 
nkeynes@626
   884
    CHECKFPUEN();
nkeynes@669
   885
    sh4r.r[Rn] = FPULi; 
nkeynes@626
   886
:}
nkeynes@359
   887
STS.L FPUL, @-Rn {:
nkeynes@626
   888
    CHECKFPUEN();
nkeynes@587
   889
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@669
   890
    MEM_WRITE_LONG( sh4r.r[Rn]-4, FPULi );
nkeynes@359
   891
    sh4r.r[Rn] -= 4;
nkeynes@359
   892
:}
nkeynes@359
   893
LDS.L @Rm+, FPUL {:
nkeynes@626
   894
    CHECKFPUEN();
nkeynes@359
   895
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@669
   896
    MEM_READ_LONG(sh4r.r[Rm], FPULi);
nkeynes@359
   897
    sh4r.r[Rm] +=4;
nkeynes@359
   898
:}
nkeynes@626
   899
LDS Rm, FPUL {:
nkeynes@626
   900
    CHECKFPUEN();
nkeynes@669
   901
    FPULi = sh4r.r[Rm]; 
nkeynes@626
   902
:}
nkeynes@626
   903
STS FPSCR, Rn {: 
nkeynes@626
   904
    CHECKFPUEN();
nkeynes@626
   905
    sh4r.r[Rn] = sh4r.fpscr; 
nkeynes@626
   906
:}
nkeynes@359
   907
STS.L FPSCR, @-Rn {:
nkeynes@626
   908
    CHECKFPUEN();
nkeynes@587
   909
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   910
    MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.fpscr );
nkeynes@359
   911
    sh4r.r[Rn] -= 4;
nkeynes@359
   912
:}
nkeynes@359
   913
LDS.L @Rm+, FPSCR {:
nkeynes@626
   914
    CHECKFPUEN();
nkeynes@359
   915
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@669
   916
    MEM_READ_LONG(sh4r.r[Rm], tmp);
nkeynes@359
   917
    sh4r.r[Rm] +=4;
nkeynes@669
   918
    sh4_write_fpscr( tmp );
nkeynes@359
   919
:}
nkeynes@374
   920
LDS Rm, FPSCR {: 
nkeynes@626
   921
    CHECKFPUEN();
nkeynes@669
   922
    sh4_write_fpscr( sh4r.r[Rm] );
nkeynes@374
   923
:}
nkeynes@359
   924
STC DBR, Rn {: CHECKPRIV(); sh4r.r[Rn] = sh4r.dbr; :}
nkeynes@359
   925
STC.L DBR, @-Rn {:
nkeynes@359
   926
    CHECKPRIV();
nkeynes@587
   927
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   928
    MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.dbr );
nkeynes@359
   929
    sh4r.r[Rn] -= 4;
nkeynes@359
   930
:}
nkeynes@359
   931
LDC.L @Rm+, DBR {:
nkeynes@359
   932
    CHECKPRIV();
nkeynes@359
   933
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@586
   934
    MEM_READ_LONG(sh4r.r[Rm], sh4r.dbr);
nkeynes@359
   935
    sh4r.r[Rm] +=4;
nkeynes@359
   936
:}
nkeynes@359
   937
LDC Rm, DBR {:
nkeynes@359
   938
    CHECKPRIV();
nkeynes@359
   939
    sh4r.dbr = sh4r.r[Rm];
nkeynes@359
   940
:}
nkeynes@359
   941
STC.L Rm_BANK, @-Rn {:
nkeynes@359
   942
    CHECKPRIV();
nkeynes@587
   943
    CHECKWALIGN32( sh4r.r[Rn] );
nkeynes@587
   944
    MEM_WRITE_LONG( sh4r.r[Rn]-4, sh4r.r_bank[Rm_BANK] );
nkeynes@359
   945
    sh4r.r[Rn] -= 4;
nkeynes@359
   946
:}
nkeynes@359
   947
LDC.L @Rm+, Rn_BANK {:
nkeynes@359
   948
    CHECKPRIV();
nkeynes@359
   949
    CHECKRALIGN32( sh4r.r[Rm] );
nkeynes@586
   950
    MEM_READ_LONG( sh4r.r[Rm], sh4r.r_bank[Rn_BANK] );
nkeynes@359
   951
    sh4r.r[Rm] += 4;
nkeynes@359
   952
:}
nkeynes@359
   953
LDC Rm, Rn_BANK {:
nkeynes@359
   954
    CHECKPRIV();
nkeynes@359
   955
    sh4r.r_bank[Rn_BANK] = sh4r.r[Rm];
nkeynes@359
   956
:}
nkeynes@359
   957
STC SR, Rn {: 
nkeynes@359
   958
    CHECKPRIV();
nkeynes@359
   959
    sh4r.r[Rn] = sh4_read_sr();
nkeynes@359
   960
:}
nkeynes@359
   961
STC GBR, Rn {:
nkeynes@359
   962
    sh4r.r[Rn] = sh4r.gbr;
nkeynes@359
   963
:}
nkeynes@359
   964
STC VBR, Rn {:
nkeynes@359
   965
    CHECKPRIV();
nkeynes@359
   966
    sh4r.r[Rn] = sh4r.vbr;
nkeynes@359
   967
:}
nkeynes@359
   968
STC SSR, Rn {:
nkeynes@359
   969
    CHECKPRIV();
nkeynes@359
   970
    sh4r.r[Rn] = sh4r.ssr;
nkeynes@359
   971
:}
nkeynes@359
   972
STC SPC, Rn {:
nkeynes@359
   973
    CHECKPRIV();
nkeynes@359
   974
    sh4r.r[Rn] = sh4r.spc;
nkeynes@359
   975
:}
nkeynes@359
   976
STC Rm_BANK, Rn {:
nkeynes@359
   977
    CHECKPRIV();
nkeynes@359
   978
    sh4r.r[Rn] = sh4r.r_bank[Rm_BANK];
nkeynes@359
   979
:}
nkeynes@359
   980
nkeynes@359
   981
FADD FRm, FRn {:
nkeynes@359
   982
    CHECKFPUEN();
nkeynes@359
   983
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
   984
	DR(FRn) += DR(FRm);
nkeynes@359
   985
    } else {
nkeynes@359
   986
	FR(FRn) += FR(FRm);
nkeynes@359
   987
    }
nkeynes@359
   988
:}
nkeynes@359
   989
FSUB FRm, FRn {:
nkeynes@359
   990
    CHECKFPUEN();
nkeynes@359
   991
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
   992
	DR(FRn) -= DR(FRm);
nkeynes@359
   993
    } else {
nkeynes@359
   994
	FR(FRn) -= FR(FRm);
nkeynes@359
   995
    }
nkeynes@359
   996
:}
nkeynes@359
   997
nkeynes@359
   998
FMUL FRm, FRn {:
nkeynes@359
   999
    CHECKFPUEN();
nkeynes@359
  1000
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1001
	DR(FRn) *= DR(FRm);
nkeynes@359
  1002
    } else {
nkeynes@359
  1003
	FR(FRn) *= FR(FRm);
nkeynes@359
  1004
    }
nkeynes@359
  1005
:}
nkeynes@359
  1006
nkeynes@359
  1007
FDIV FRm, FRn {:
nkeynes@359
  1008
    CHECKFPUEN();
nkeynes@359
  1009
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1010
	DR(FRn) /= DR(FRm);
nkeynes@359
  1011
    } else {
nkeynes@359
  1012
	FR(FRn) /= FR(FRm);
nkeynes@359
  1013
    }
nkeynes@359
  1014
:}
nkeynes@359
  1015
nkeynes@359
  1016
FCMP/EQ FRm, FRn {:
nkeynes@359
  1017
    CHECKFPUEN();
nkeynes@359
  1018
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1019
	sh4r.t = ( DR(FRn) == DR(FRm) ? 1 : 0 );
nkeynes@359
  1020
    } else {
nkeynes@359
  1021
	sh4r.t = ( FR(FRn) == FR(FRm) ? 1 : 0 );
nkeynes@359
  1022
    }
nkeynes@359
  1023
:}
nkeynes@359
  1024
nkeynes@359
  1025
FCMP/GT FRm, FRn {:
nkeynes@359
  1026
    CHECKFPUEN();
nkeynes@359
  1027
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1028
	sh4r.t = ( DR(FRn) > DR(FRm) ? 1 : 0 );
nkeynes@359
  1029
    } else {
nkeynes@359
  1030
	sh4r.t = ( FR(FRn) > FR(FRm) ? 1 : 0 );
nkeynes@359
  1031
    }
nkeynes@359
  1032
:}
nkeynes@359
  1033
nkeynes@359
  1034
FSTS FPUL, FRn {: CHECKFPUEN(); FR(FRn) = FPULf; :}
nkeynes@359
  1035
FLDS FRm, FPUL {: CHECKFPUEN(); FPULf = FR(FRm); :}
nkeynes@359
  1036
FLOAT FPUL, FRn {: 
nkeynes@359
  1037
    CHECKFPUEN();
nkeynes@374
  1038
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@374
  1039
	if( FRn&1 ) { // No, really...
nkeynes@374
  1040
	    dtmp = (double)FPULi;
nkeynes@374
  1041
	    FR(FRn) = *(((float *)&dtmp)+1);
nkeynes@374
  1042
	} else {
nkeynes@374
  1043
	    DRF(FRn>>1) = (double)FPULi;
nkeynes@374
  1044
	}
nkeynes@374
  1045
    } else {
nkeynes@359
  1046
	FR(FRn) = (float)FPULi;
nkeynes@374
  1047
    }
nkeynes@359
  1048
:}
nkeynes@359
  1049
FTRC FRm, FPUL {:
nkeynes@359
  1050
    CHECKFPUEN();
nkeynes@359
  1051
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@374
  1052
	if( FRm&1 ) {
nkeynes@374
  1053
	    dtmp = 0;
nkeynes@374
  1054
	    *(((float *)&dtmp)+1) = FR(FRm);
nkeynes@374
  1055
	} else {
nkeynes@374
  1056
	    dtmp = DRF(FRm>>1);
nkeynes@374
  1057
	}
nkeynes@359
  1058
        if( dtmp >= MAX_INTF )
nkeynes@359
  1059
            FPULi = MAX_INT;
nkeynes@359
  1060
        else if( dtmp <= MIN_INTF )
nkeynes@359
  1061
            FPULi = MIN_INT;
nkeynes@359
  1062
        else 
nkeynes@359
  1063
            FPULi = (int32_t)dtmp;
nkeynes@359
  1064
    } else {
nkeynes@359
  1065
	ftmp = FR(FRm);
nkeynes@359
  1066
	if( ftmp >= MAX_INTF )
nkeynes@359
  1067
	    FPULi = MAX_INT;
nkeynes@359
  1068
	else if( ftmp <= MIN_INTF )
nkeynes@359
  1069
	    FPULi = MIN_INT;
nkeynes@359
  1070
	else
nkeynes@359
  1071
	    FPULi = (int32_t)ftmp;
nkeynes@359
  1072
    }
nkeynes@359
  1073
:}
nkeynes@359
  1074
FNEG FRn {:
nkeynes@359
  1075
    CHECKFPUEN();
nkeynes@359
  1076
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1077
	DR(FRn) = -DR(FRn);
nkeynes@359
  1078
    } else {
nkeynes@359
  1079
        FR(FRn) = -FR(FRn);
nkeynes@359
  1080
    }
nkeynes@359
  1081
:}
nkeynes@359
  1082
FABS FRn {:
nkeynes@359
  1083
    CHECKFPUEN();
nkeynes@359
  1084
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1085
	DR(FRn) = fabs(DR(FRn));
nkeynes@359
  1086
    } else {
nkeynes@359
  1087
        FR(FRn) = fabsf(FR(FRn));
nkeynes@359
  1088
    }
nkeynes@359
  1089
:}
nkeynes@359
  1090
FSQRT FRn {:
nkeynes@359
  1091
    CHECKFPUEN();
nkeynes@359
  1092
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1093
	DR(FRn) = sqrt(DR(FRn));
nkeynes@359
  1094
    } else {
nkeynes@359
  1095
        FR(FRn) = sqrtf(FR(FRn));
nkeynes@359
  1096
    }
nkeynes@359
  1097
:}
nkeynes@359
  1098
FLDI0 FRn {:
nkeynes@359
  1099
    CHECKFPUEN();
nkeynes@359
  1100
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1101
	DR(FRn) = 0.0;
nkeynes@359
  1102
    } else {
nkeynes@359
  1103
        FR(FRn) = 0.0;
nkeynes@359
  1104
    }
nkeynes@359
  1105
:}
nkeynes@359
  1106
FLDI1 FRn {:
nkeynes@359
  1107
    CHECKFPUEN();
nkeynes@359
  1108
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1109
	DR(FRn) = 1.0;
nkeynes@359
  1110
    } else {
nkeynes@359
  1111
        FR(FRn) = 1.0;
nkeynes@359
  1112
    }
nkeynes@359
  1113
:}
nkeynes@359
  1114
FMAC FR0, FRm, FRn {:
nkeynes@359
  1115
    CHECKFPUEN();
nkeynes@359
  1116
    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1117
        DR(FRn) += DR(FRm)*DR(0);
nkeynes@359
  1118
    } else {
nkeynes@359
  1119
	FR(FRn) += FR(FRm)*FR(0);
nkeynes@359
  1120
    }
nkeynes@359
  1121
:}
nkeynes@374
  1122
FRCHG {: 
nkeynes@374
  1123
    CHECKFPUEN(); 
nkeynes@374
  1124
    sh4r.fpscr ^= FPSCR_FR; 
nkeynes@669
  1125
    sh4_switch_fr_banks();
nkeynes@374
  1126
:}
nkeynes@359
  1127
FSCHG {: CHECKFPUEN(); sh4r.fpscr ^= FPSCR_SZ; :}
nkeynes@359
  1128
FCNVSD FPUL, FRn {:
nkeynes@359
  1129
    CHECKFPUEN();
nkeynes@359
  1130
    if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
nkeynes@359
  1131
	DR(FRn) = (double)FPULf;
nkeynes@359
  1132
    }
nkeynes@359
  1133
:}
nkeynes@359
  1134
FCNVDS FRm, FPUL {:
nkeynes@359
  1135
    CHECKFPUEN();
nkeynes@359
  1136
    if( IS_FPU_DOUBLEPREC() && !IS_FPU_DOUBLESIZE() ) {
nkeynes@359
  1137
	FPULf = (float)DR(FRm);
nkeynes@359
  1138
    }
nkeynes@359
  1139
:}
nkeynes@359
  1140
nkeynes@359
  1141
FSRRA FRn {:
nkeynes@359
  1142
    CHECKFPUEN();
nkeynes@359
  1143
    if( !IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1144
	FR(FRn) = 1.0/sqrtf(FR(FRn));
nkeynes@359
  1145
    }
nkeynes@359
  1146
:}
nkeynes@359
  1147
FIPR FVm, FVn {:
nkeynes@359
  1148
    CHECKFPUEN();
nkeynes@359
  1149
    if( !IS_FPU_DOUBLEPREC() ) {
nkeynes@359
  1150
        int tmp2 = FVn<<2;
nkeynes@359
  1151
        tmp = FVm<<2;
nkeynes@359
  1152
        FR(tmp2+3) = FR(tmp)*FR(tmp2) +
nkeynes@359
  1153
            FR(tmp+1)*FR(tmp2+1) +
nkeynes@359
  1154
            FR(tmp+2)*FR(tmp2+2) +
nkeynes@359
  1155
            FR(tmp+3)*FR(tmp2+3);
nkeynes@359
  1156
    }
nkeynes@359
  1157
:}
nkeynes@359
  1158
FSCA FPUL, FRn {:
nkeynes@359
  1159
    CHECKFPUEN();
nkeynes@359
  1160
    if( !IS_FPU_DOUBLEPREC() ) {
nkeynes@758
  1161
	sh4_fsca( FPULi, (float *)&(DRF(FRn>>1)) );
nkeynes@391
  1162
	/*
nkeynes@359
  1163
        float angle = (((float)(FPULi&0xFFFF))/65536.0) * 2 * M_PI;
nkeynes@359
  1164
        FR(FRn) = sinf(angle);
nkeynes@359
  1165
        FR((FRn)+1) = cosf(angle);
nkeynes@391
  1166
	*/
nkeynes@359
  1167
    }
nkeynes@359
  1168
:}
nkeynes@359
  1169
FTRV XMTRX, FVn {:
nkeynes@359
  1170
    CHECKFPUEN();
nkeynes@359
  1171
    if( !IS_FPU_DOUBLEPREC() ) {
nkeynes@758
  1172
	sh4_ftrv((float *)&(DRF(FVn<<1)) );
nkeynes@359
  1173
    }
nkeynes@359
  1174
:}
nkeynes@359
  1175
UNDEF {:
nkeynes@359
  1176
    UNDEF(ir);
nkeynes@359
  1177
:}
nkeynes@359
  1178
%%
nkeynes@359
  1179
    sh4r.pc = sh4r.new_pc;
nkeynes@359
  1180
    sh4r.new_pc += 2;
nkeynes@359
  1181
    sh4r.in_delay_slot = 0;
nkeynes@359
  1182
    return TRUE;
nkeynes@359
  1183
}
.