Search
lxdream.org :: lxdream/src/sh4/sh4core.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4core.c
changeset 260:c82e26ec0cac
prev246:98054d036a24
next265:5daf59b7f31b
author nkeynes
date Wed Jan 03 09:00:17 2007 +0000 (13 years ago)
permissions -rw-r--r--
last change Adjust timers when they're read rather than waiting until the next time
slice. Also temporarily cut the CPU time by 4.
Initialize the FRQCR register to 0x0E0A for convenience
file annotate diff log raw
nkeynes@23
     1
/**
nkeynes@260
     2
 * $Id: sh4core.c,v 1.36 2007-01-03 09:00:17 nkeynes Exp $
nkeynes@23
     3
 * 
nkeynes@23
     4
 * SH4 emulation core, and parent module for all the SH4 peripheral
nkeynes@23
     5
 * modules.
nkeynes@23
     6
 *
nkeynes@23
     7
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@23
     8
 *
nkeynes@23
     9
 * This program is free software; you can redistribute it and/or modify
nkeynes@23
    10
 * it under the terms of the GNU General Public License as published by
nkeynes@23
    11
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@23
    12
 * (at your option) any later version.
nkeynes@23
    13
 *
nkeynes@23
    14
 * This program is distributed in the hope that it will be useful,
nkeynes@23
    15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@23
    16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@23
    17
 * GNU General Public License for more details.
nkeynes@23
    18
 */
nkeynes@23
    19
nkeynes@35
    20
#define MODULE sh4_module
nkeynes@1
    21
#include <math.h>
nkeynes@1
    22
#include "dream.h"
nkeynes@84
    23
#include "sh4/sh4core.h"
nkeynes@84
    24
#include "sh4/sh4mmio.h"
nkeynes@84
    25
#include "sh4/intc.h"
nkeynes@1
    26
#include "mem.h"
nkeynes@23
    27
#include "clock.h"
nkeynes@102
    28
#include "syscall.h"
nkeynes@1
    29
nkeynes@157
    30
#define SH4_CALLTRACE 1
nkeynes@157
    31
nkeynes@123
    32
#define MAX_INT 0x7FFFFFFF
nkeynes@123
    33
#define MIN_INT 0x80000000
nkeynes@123
    34
#define MAX_INTF 2147483647.0
nkeynes@123
    35
#define MIN_INTF -2147483648.0
nkeynes@123
    36
nkeynes@27
    37
/* CPU-generated exception code/vector pairs */
nkeynes@27
    38
#define EXC_POWER_RESET  0x000 /* vector special */
nkeynes@27
    39
#define EXC_MANUAL_RESET 0x020
nkeynes@208
    40
#define EXC_READ_ADDR_ERR 0x0E0
nkeynes@208
    41
#define EXC_WRITE_ADDR_ERR 0x100
nkeynes@27
    42
#define EXC_SLOT_ILLEGAL 0x1A0
nkeynes@27
    43
#define EXC_ILLEGAL      0x180
nkeynes@27
    44
#define EXC_TRAP         0x160
nkeynes@27
    45
#define EXC_FPDISABLE    0x800
nkeynes@246
    46
#define EXC_SLOT_FPDISABLE 0x820
nkeynes@246
    47
nkeynes@246
    48
#define EXV_EXCEPTION    0x100  /* General exception vector */
nkeynes@246
    49
#define EXV_TLBMISS      0x400  /* TLB-miss exception vector */
nkeynes@246
    50
#define EXV_INTERRUPT    0x600  /* External interrupt vector */
nkeynes@27
    51
nkeynes@23
    52
/********************** SH4 Module Definition ****************************/
nkeynes@23
    53
nkeynes@23
    54
void sh4_init( void );
nkeynes@23
    55
void sh4_reset( void );
nkeynes@30
    56
uint32_t sh4_run_slice( uint32_t );
nkeynes@23
    57
void sh4_start( void );
nkeynes@23
    58
void sh4_stop( void );
nkeynes@23
    59
void sh4_save_state( FILE *f );
nkeynes@23
    60
int sh4_load_state( FILE *f );
nkeynes@16
    61
nkeynes@15
    62
struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_reset, 
nkeynes@23
    63
				       NULL, sh4_run_slice, sh4_stop,
nkeynes@23
    64
				       sh4_save_state, sh4_load_state };
nkeynes@15
    65
nkeynes@1
    66
struct sh4_registers sh4r;
nkeynes@1
    67
nkeynes@1
    68
void sh4_init(void)
nkeynes@1
    69
{
nkeynes@1
    70
    register_io_regions( mmio_list_sh4mmio );
nkeynes@10
    71
    mmu_init();
nkeynes@27
    72
    sh4_reset();
nkeynes@1
    73
}
nkeynes@1
    74
nkeynes@1
    75
void sh4_reset(void)
nkeynes@1
    76
{
nkeynes@19
    77
    /* zero everything out, for the sake of having a consistent state. */
nkeynes@19
    78
    memset( &sh4r, 0, sizeof(sh4r) );
nkeynes@27
    79
nkeynes@27
    80
    /* Resume running if we were halted */
nkeynes@27
    81
    sh4r.sh4_state = SH4_STATE_RUNNING;
nkeynes@27
    82
nkeynes@1
    83
    sh4r.pc    = 0xA0000000;
nkeynes@1
    84
    sh4r.new_pc= 0xA0000002;
nkeynes@1
    85
    sh4r.vbr   = 0x00000000;
nkeynes@1
    86
    sh4r.fpscr = 0x00040001;
nkeynes@1
    87
    sh4r.sr    = 0x700000F0;
nkeynes@27
    88
nkeynes@27
    89
    /* Mem reset will do this, but if we want to reset _just_ the SH4... */
nkeynes@27
    90
    MMIO_WRITE( MMU, EXPEVT, EXC_POWER_RESET );
nkeynes@27
    91
nkeynes@27
    92
    /* Peripheral modules */
nkeynes@260
    93
    CPG_reset();
nkeynes@157
    94
    INTC_reset();
nkeynes@157
    95
    TMU_reset();
nkeynes@32
    96
    SCIF_reset();
nkeynes@1
    97
}
nkeynes@1
    98
nkeynes@43
    99
static struct breakpoint_struct sh4_breakpoints[MAX_BREAKPOINTS];
nkeynes@43
   100
static int sh4_breakpoint_count = 0;
nkeynes@235
   101
static uint16_t *sh4_icache = NULL;
nkeynes@235
   102
static uint32_t sh4_icache_addr = 0;
nkeynes@43
   103
nkeynes@43
   104
void sh4_set_breakpoint( uint32_t pc, int type )
nkeynes@43
   105
{
nkeynes@43
   106
    sh4_breakpoints[sh4_breakpoint_count].address = pc;
nkeynes@43
   107
    sh4_breakpoints[sh4_breakpoint_count].type = type;
nkeynes@43
   108
    sh4_breakpoint_count++;
nkeynes@43
   109
}
nkeynes@43
   110
nkeynes@43
   111
gboolean sh4_clear_breakpoint( uint32_t pc, int type )
nkeynes@43
   112
{
nkeynes@43
   113
    int i;
nkeynes@43
   114
nkeynes@43
   115
    for( i=0; i<sh4_breakpoint_count; i++ ) {
nkeynes@43
   116
	if( sh4_breakpoints[i].address == pc && 
nkeynes@43
   117
	    sh4_breakpoints[i].type == type ) {
nkeynes@43
   118
	    while( ++i < sh4_breakpoint_count ) {
nkeynes@43
   119
		sh4_breakpoints[i-1].address = sh4_breakpoints[i].address;
nkeynes@43
   120
		sh4_breakpoints[i-1].type = sh4_breakpoints[i].type;
nkeynes@43
   121
	    }
nkeynes@43
   122
	    sh4_breakpoint_count--;
nkeynes@43
   123
	    return TRUE;
nkeynes@43
   124
	}
nkeynes@43
   125
    }
nkeynes@43
   126
    return FALSE;
nkeynes@43
   127
}
nkeynes@43
   128
nkeynes@43
   129
int sh4_get_breakpoint( uint32_t pc )
nkeynes@43
   130
{
nkeynes@43
   131
    int i;
nkeynes@43
   132
    for( i=0; i<sh4_breakpoint_count; i++ ) {
nkeynes@43
   133
	if( sh4_breakpoints[i].address == pc )
nkeynes@43
   134
	    return sh4_breakpoints[i].type;
nkeynes@43
   135
    }
nkeynes@43
   136
    return 0;
nkeynes@43
   137
}
nkeynes@43
   138
nkeynes@30
   139
uint32_t sh4_run_slice( uint32_t nanosecs ) 
nkeynes@1
   140
{
nkeynes@30
   141
    int target = sh4r.icount + nanosecs / sh4_cpu_period;
nkeynes@27
   142
    int start = sh4r.icount;
nkeynes@23
   143
    int i;
nkeynes@23
   144
nkeynes@27
   145
    if( sh4r.sh4_state != SH4_STATE_RUNNING ) {
nkeynes@27
   146
	if( sh4r.int_pending != 0 )
nkeynes@27
   147
	    sh4r.sh4_state = SH4_STATE_RUNNING;;
nkeynes@23
   148
    }
nkeynes@27
   149
nkeynes@235
   150
    if( sh4_breakpoint_count == 0 ) {
nkeynes@235
   151
	for( sh4r.slice_cycle = 0; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
nkeynes@235
   152
	    if( !sh4_execute_instruction() ) {
nkeynes@43
   153
		break;
nkeynes@43
   154
	    }
nkeynes@43
   155
	}
nkeynes@235
   156
    } else {
nkeynes@235
   157
nkeynes@235
   158
	for( sh4r.slice_cycle = 0; sh4r.slice_cycle < nanosecs; sh4r.slice_cycle += sh4_cpu_period ) {
nkeynes@235
   159
	    if( !sh4_execute_instruction() )
nkeynes@235
   160
		break;
nkeynes@235
   161
#ifdef ENABLE_DEBUG_MODE
nkeynes@235
   162
	    for( i=0; i<sh4_breakpoint_count; i++ ) {
nkeynes@235
   163
		if( sh4_breakpoints[i].address == sh4r.pc ) {
nkeynes@235
   164
		    break;
nkeynes@235
   165
		}
nkeynes@235
   166
	    }
nkeynes@235
   167
	    if( i != sh4_breakpoint_count ) {
nkeynes@235
   168
		dreamcast_stop();
nkeynes@235
   169
		if( sh4_breakpoints[i].type == BREAK_ONESHOT )
nkeynes@235
   170
		    sh4_clear_breakpoint( sh4r.pc, BREAK_ONESHOT );
nkeynes@235
   171
		break;
nkeynes@235
   172
	    }
nkeynes@235
   173
#endif	
nkeynes@43
   174
	}
nkeynes@27
   175
    }
nkeynes@30
   176
nkeynes@30
   177
    /* If we aborted early, but the cpu is still technically running,
nkeynes@30
   178
     * we're doing a hard abort - cut the timeslice back to what we
nkeynes@30
   179
     * actually executed
nkeynes@30
   180
     */
nkeynes@53
   181
    if( sh4r.slice_cycle != nanosecs && sh4r.sh4_state == SH4_STATE_RUNNING ) {
nkeynes@53
   182
	nanosecs = sh4r.slice_cycle;
nkeynes@27
   183
    }
nkeynes@27
   184
    if( sh4r.sh4_state != SH4_STATE_STANDBY ) {
nkeynes@30
   185
	TMU_run_slice( nanosecs );
nkeynes@30
   186
	SCIF_run_slice( nanosecs );
nkeynes@27
   187
    }
nkeynes@53
   188
    sh4r.icount += sh4r.slice_cycle / sh4_cpu_period;
nkeynes@30
   189
    return nanosecs;
nkeynes@1
   190
}
nkeynes@1
   191
nkeynes@1
   192
void sh4_stop(void)
nkeynes@1
   193
{
nkeynes@27
   194
nkeynes@1
   195
}
nkeynes@1
   196
nkeynes@23
   197
void sh4_save_state( FILE *f )
nkeynes@16
   198
{
nkeynes@16
   199
    fwrite( &sh4r, sizeof(sh4r), 1, f );
nkeynes@157
   200
    INTC_save_state( f );
nkeynes@53
   201
    TMU_save_state( f );
nkeynes@23
   202
    SCIF_save_state( f );
nkeynes@16
   203
}
nkeynes@16
   204
nkeynes@23
   205
int sh4_load_state( FILE * f )
nkeynes@16
   206
{
nkeynes@18
   207
    fread( &sh4r, sizeof(sh4r), 1, f );
nkeynes@157
   208
    INTC_load_state( f );
nkeynes@53
   209
    TMU_load_state( f );
nkeynes@23
   210
    return SCIF_load_state( f );
nkeynes@16
   211
}
nkeynes@16
   212
nkeynes@23
   213
/********************** SH4 emulation core  ****************************/
nkeynes@23
   214
nkeynes@23
   215
void sh4_set_pc( int pc )
nkeynes@23
   216
{
nkeynes@23
   217
    sh4r.pc = pc;
nkeynes@23
   218
    sh4r.new_pc = pc+2;
nkeynes@23
   219
}
nkeynes@23
   220
nkeynes@246
   221
#define UNDEF(ir) return sh4_raise_slot_exception(EXC_ILLEGAL, EXC_SLOT_ILLEGAL)
nkeynes@27
   222
#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); dreamcast_stop(); return FALSE; }while(0)
nkeynes@1
   223
nkeynes@157
   224
#if(SH4_CALLTRACE == 1)
nkeynes@157
   225
#define MAX_CALLSTACK 32
nkeynes@157
   226
static struct call_stack {
nkeynes@157
   227
    sh4addr_t call_addr;
nkeynes@157
   228
    sh4addr_t target_addr;
nkeynes@157
   229
    sh4addr_t stack_pointer;
nkeynes@157
   230
} call_stack[MAX_CALLSTACK];
nkeynes@157
   231
nkeynes@157
   232
static int call_stack_depth = 0;
nkeynes@157
   233
int sh4_call_trace_on = 0;
nkeynes@157
   234
nkeynes@157
   235
static inline trace_call( sh4addr_t source, sh4addr_t dest ) 
nkeynes@157
   236
{
nkeynes@157
   237
    if( call_stack_depth < MAX_CALLSTACK ) {
nkeynes@157
   238
	call_stack[call_stack_depth].call_addr = source;
nkeynes@157
   239
	call_stack[call_stack_depth].target_addr = dest;
nkeynes@157
   240
	call_stack[call_stack_depth].stack_pointer = sh4r.r[15];
nkeynes@157
   241
    }
nkeynes@157
   242
    call_stack_depth++;
nkeynes@157
   243
}
nkeynes@157
   244
nkeynes@157
   245
static inline trace_return( sh4addr_t source, sh4addr_t dest )
nkeynes@157
   246
{
nkeynes@157
   247
    if( call_stack_depth > 0 ) {
nkeynes@157
   248
	call_stack_depth--;
nkeynes@157
   249
    }
nkeynes@157
   250
}
nkeynes@157
   251
nkeynes@157
   252
void fprint_stack_trace( FILE *f )
nkeynes@157
   253
{
nkeynes@157
   254
    int i = call_stack_depth -1;
nkeynes@157
   255
    if( i >= MAX_CALLSTACK )
nkeynes@157
   256
	i = MAX_CALLSTACK - 1;
nkeynes@157
   257
    for( ; i >= 0; i-- ) {
nkeynes@157
   258
	fprintf( f, "%d. Call from %08X => %08X, SP=%08X\n", 
nkeynes@157
   259
		 (call_stack_depth - i), call_stack[i].call_addr,
nkeynes@157
   260
		 call_stack[i].target_addr, call_stack[i].stack_pointer );
nkeynes@157
   261
    }
nkeynes@157
   262
}
nkeynes@157
   263
nkeynes@157
   264
#define TRACE_CALL( source, dest ) trace_call(source, dest)
nkeynes@157
   265
#define TRACE_RETURN( source, dest ) trace_return(source, dest)
nkeynes@157
   266
#else
nkeynes@157
   267
#define TRACE_CALL( dest, rts ) 
nkeynes@157
   268
#define TRACE_RETURN( source, dest )
nkeynes@157
   269
#endif
nkeynes@157
   270
nkeynes@246
   271
#define RAISE( x, v ) do{			\
nkeynes@1
   272
    if( sh4r.vbr == 0 ) { \
nkeynes@1
   273
        ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \
nkeynes@104
   274
        dreamcast_stop(); return FALSE;	\
nkeynes@1
   275
    } else { \
nkeynes@246
   276
        sh4r.spc = sh4r.pc;	\
nkeynes@1
   277
        sh4r.ssr = sh4_read_sr(); \
nkeynes@1
   278
        sh4r.sgr = sh4r.r[15]; \
nkeynes@1
   279
        MMIO_WRITE(MMU,EXPEVT,x); \
nkeynes@1
   280
        sh4r.pc = sh4r.vbr + v; \
nkeynes@1
   281
        sh4r.new_pc = sh4r.pc + 2; \
nkeynes@1
   282
        sh4_load_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
nkeynes@246
   283
	if( sh4r.in_delay_slot ) { \
nkeynes@246
   284
	    sh4r.in_delay_slot = 0; \
nkeynes@246
   285
	    sh4r.spc -= 2; \
nkeynes@246
   286
	} \
nkeynes@1
   287
    } \
nkeynes@27
   288
    return TRUE; } while(0)
nkeynes@229
   289
nkeynes@10
   290
#define MEM_READ_BYTE( addr ) sh4_read_byte(addr)
nkeynes@10
   291
#define MEM_READ_WORD( addr ) sh4_read_word(addr)
nkeynes@10
   292
#define MEM_READ_LONG( addr ) sh4_read_long(addr)
nkeynes@10
   293
#define MEM_WRITE_BYTE( addr, val ) sh4_write_byte(addr, val)
nkeynes@10
   294
#define MEM_WRITE_WORD( addr, val ) sh4_write_word(addr, val)
nkeynes@10
   295
#define MEM_WRITE_LONG( addr, val ) sh4_write_long(addr, val)
nkeynes@1
   296
nkeynes@1
   297
#define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
nkeynes@1
   298
nkeynes@124
   299
#define MEM_FP_READ( addr, reg ) sh4_read_float( addr, reg );
nkeynes@124
   300
#define MEM_FP_WRITE( addr, reg ) sh4_write_float( addr, reg );
nkeynes@84
   301
nkeynes@246
   302
#define CHECKPRIV() if( !IS_SH4_PRIVMODE() ) return sh4_raise_slot_exception( EXC_ILLEGAL, EXC_SLOT_ILLEGAL )
nkeynes@246
   303
#define CHECKRALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_READ_ADDR_ERR )
nkeynes@246
   304
#define CHECKRALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_READ_ADDR_ERR )
nkeynes@246
   305
#define CHECKWALIGN16(addr) if( (addr)&0x01 ) return sh4_raise_exception( EXC_WRITE_ADDR_ERR )
nkeynes@246
   306
#define CHECKWALIGN32(addr) if( (addr)&0x03 ) return sh4_raise_exception( EXC_WRITE_ADDR_ERR )
nkeynes@208
   307
nkeynes@246
   308
#define CHECKFPUEN() if( !IS_FPU_ENABLED() ) return sh4_raise_slot_exception( EXC_FPDISABLE, EXC_SLOT_FPDISABLE )
nkeynes@84
   309
#define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); dreamcast_stop(); return FALSE; }
nkeynes@246
   310
#define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) return sh4_raise_exception(EXC_SLOT_ILLEGAL)
nkeynes@1
   311
nkeynes@1
   312
static void sh4_switch_banks( )
nkeynes@1
   313
{
nkeynes@1
   314
    uint32_t tmp[8];
nkeynes@1
   315
nkeynes@1
   316
    memcpy( tmp, sh4r.r, sizeof(uint32_t)*8 );
nkeynes@1
   317
    memcpy( sh4r.r, sh4r.r_bank, sizeof(uint32_t)*8 );
nkeynes@1
   318
    memcpy( sh4r.r_bank, tmp, sizeof(uint32_t)*8 );
nkeynes@1
   319
}
nkeynes@1
   320
nkeynes@1
   321
static void sh4_load_sr( uint32_t newval )
nkeynes@1
   322
{
nkeynes@1
   323
    if( (newval ^ sh4r.sr) & SR_RB )
nkeynes@1
   324
        sh4_switch_banks();
nkeynes@1
   325
    sh4r.sr = newval;
nkeynes@1
   326
    sh4r.t = (newval&SR_T) ? 1 : 0;
nkeynes@1
   327
    sh4r.s = (newval&SR_S) ? 1 : 0;
nkeynes@1
   328
    sh4r.m = (newval&SR_M) ? 1 : 0;
nkeynes@1
   329
    sh4r.q = (newval&SR_Q) ? 1 : 0;
nkeynes@1
   330
    intc_mask_changed();
nkeynes@1
   331
}
nkeynes@1
   332
nkeynes@124
   333
static void sh4_write_float( uint32_t addr, int reg )
nkeynes@124
   334
{
nkeynes@124
   335
    if( IS_FPU_DOUBLESIZE() ) {
nkeynes@124
   336
	if( reg & 1 ) {
nkeynes@124
   337
	    sh4_write_long( addr, *((uint32_t *)&XF((reg)&0x0E)) );
nkeynes@124
   338
	    sh4_write_long( addr+4, *((uint32_t *)&XF(reg)) );
nkeynes@124
   339
	} else {
nkeynes@124
   340
	    sh4_write_long( addr, *((uint32_t *)&FR(reg)) ); 
nkeynes@124
   341
	    sh4_write_long( addr+4, *((uint32_t *)&FR((reg)|0x01)) );
nkeynes@124
   342
	}
nkeynes@124
   343
    } else {
nkeynes@124
   344
	sh4_write_long( addr, *((uint32_t *)&FR((reg))) );
nkeynes@124
   345
    }
nkeynes@124
   346
}
nkeynes@124
   347
nkeynes@124
   348
static void sh4_read_float( uint32_t addr, int reg )
nkeynes@124
   349
{
nkeynes@124
   350
    if( IS_FPU_DOUBLESIZE() ) {
nkeynes@124
   351
	if( reg & 1 ) {
nkeynes@124
   352
	    *((uint32_t *)&XF((reg) & 0x0E)) = sh4_read_long(addr);
nkeynes@124
   353
	    *((uint32_t *)&XF(reg)) = sh4_read_long(addr+4);
nkeynes@124
   354
	} else {
nkeynes@124
   355
	    *((uint32_t *)&FR(reg)) = sh4_read_long(addr);
nkeynes@124
   356
	    *((uint32_t *)&FR((reg) | 0x01)) = sh4_read_long(addr+4);
nkeynes@124
   357
	}
nkeynes@124
   358
    } else {
nkeynes@124
   359
	*((uint32_t *)&FR(reg)) = sh4_read_long(addr);
nkeynes@124
   360
    }
nkeynes@124
   361
}
nkeynes@124
   362
nkeynes@1
   363
static uint32_t sh4_read_sr( void )
nkeynes@1
   364
{
nkeynes@1
   365
    /* synchronize sh4r.sr with the various bitflags */
nkeynes@1
   366
    sh4r.sr &= SR_MQSTMASK;
nkeynes@1
   367
    if( sh4r.t ) sh4r.sr |= SR_T;
nkeynes@1
   368
    if( sh4r.s ) sh4r.sr |= SR_S;
nkeynes@1
   369
    if( sh4r.m ) sh4r.sr |= SR_M;
nkeynes@1
   370
    if( sh4r.q ) sh4r.sr |= SR_Q;
nkeynes@1
   371
    return sh4r.sr;
nkeynes@1
   372
}
nkeynes@246
   373
nkeynes@246
   374
/**
nkeynes@246
   375
 * Raise a general CPU exception for the specified exception code.
nkeynes@246
   376
 * (NOT for TRAPA or TLB exceptions)
nkeynes@246
   377
 */
nkeynes@246
   378
gboolean sh4_raise_exception( int code )
nkeynes@1
   379
{
nkeynes@246
   380
    RAISE( code, EXV_EXCEPTION );
nkeynes@246
   381
}
nkeynes@246
   382
nkeynes@246
   383
gboolean sh4_raise_slot_exception( int normal_code, int slot_code ) {
nkeynes@246
   384
    if( sh4r.in_delay_slot ) {
nkeynes@246
   385
	return sh4_raise_exception(slot_code);
nkeynes@246
   386
    } else {
nkeynes@246
   387
	return sh4_raise_exception(normal_code);
nkeynes@246
   388
    }
nkeynes@246
   389
}
nkeynes@246
   390
nkeynes@246
   391
gboolean sh4_raise_tlb_exception( int code )
nkeynes@246
   392
{
nkeynes@246
   393
    RAISE( code, EXV_TLBMISS );
nkeynes@1
   394
}
nkeynes@1
   395
nkeynes@1
   396
static void sh4_accept_interrupt( void )
nkeynes@1
   397
{
nkeynes@1
   398
    uint32_t code = intc_accept_interrupt();
nkeynes@1
   399
    sh4r.ssr = sh4_read_sr();
nkeynes@1
   400
    sh4r.spc = sh4r.pc;
nkeynes@1
   401
    sh4r.sgr = sh4r.r[15];
nkeynes@1
   402
    sh4_load_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
nkeynes@1
   403
    MMIO_WRITE( MMU, INTEVT, code );
nkeynes@1
   404
    sh4r.pc = sh4r.vbr + 0x600;
nkeynes@1
   405
    sh4r.new_pc = sh4r.pc + 2;
nkeynes@92
   406
    //    WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );
nkeynes@1
   407
}
nkeynes@1
   408
nkeynes@27
   409
gboolean sh4_execute_instruction( void )
nkeynes@1
   410
{
nkeynes@84
   411
    uint32_t pc;
nkeynes@2
   412
    unsigned short ir;
nkeynes@1
   413
    uint32_t tmp;
nkeynes@1
   414
    uint64_t tmpl;
nkeynes@123
   415
    float ftmp;
nkeynes@123
   416
    double dtmp;
nkeynes@1
   417
    
nkeynes@1
   418
#define R0 sh4r.r[0]
nkeynes@84
   419
#define FR0 FR(0)
nkeynes@84
   420
#define DR0 DR(0)
nkeynes@1
   421
#define RN(ir) sh4r.r[(ir&0x0F00)>>8]
nkeynes@1
   422
#define RN_BANK(ir) sh4r.r_bank[(ir&0x0070)>>4]
nkeynes@1
   423
#define RM(ir) sh4r.r[(ir&0x00F0)>>4]
nkeynes@1
   424
#define DISP4(ir) (ir&0x000F) /* 4-bit displacements are *NOT* sign-extended */
nkeynes@1
   425
#define DISP8(ir) (ir&0x00FF)
nkeynes@1
   426
#define PCDISP8(ir) SIGNEXT8(ir&0x00FF)
nkeynes@1
   427
#define IMM8(ir) SIGNEXT8(ir&0x00FF)
nkeynes@1
   428
#define UIMM8(ir) (ir&0x00FF) /* Unsigned immmediate */
nkeynes@1
   429
#define DISP12(ir) SIGNEXT12(ir&0x0FFF)
nkeynes@84
   430
#define FRNn(ir) ((ir&0x0F00)>>8)
nkeynes@84
   431
#define FRMn(ir) ((ir&0x00F0)>>4)
nkeynes@84
   432
#define DRNn(ir) ((ir&0x0E00)>>9)
nkeynes@84
   433
#define DRMn(ir) ((ir&0x00E0)>>5)
nkeynes@2
   434
#define FVN(ir) ((ir&0x0C00)>>8)
nkeynes@2
   435
#define FVM(ir) ((ir&0x0300)>>6)
nkeynes@84
   436
#define FRN(ir) FR(FRNn(ir))
nkeynes@84
   437
#define FRM(ir) FR(FRMn(ir))
nkeynes@84
   438
#define FRNi(ir) (*((uint32_t *)&FR(FRNn(ir))))
nkeynes@84
   439
#define FRMi(ir) (*((uint32_t *)&FR(FRMn(ir))))
nkeynes@95
   440
#define DRN(ir) DRb(DRNn(ir), ir&0x0100)
nkeynes@95
   441
#define DRM(ir) DRb(DRMn(ir),ir&0x0010)
nkeynes@84
   442
#define DRNi(ir) (*((uint64_t *)&DR(FRNn(ir))))
nkeynes@84
   443
#define DRMi(ir) (*((uint64_t *)&DR(FRMn(ir))))
nkeynes@1
   444
#define FPULf   *((float *)&sh4r.fpul)
nkeynes@1
   445
#define FPULi    (sh4r.fpul)
nkeynes@1
   446
nkeynes@2
   447
    if( SH4_INT_PENDING() ) 
nkeynes@2
   448
        sh4_accept_interrupt();
nkeynes@1
   449
                 
nkeynes@2
   450
    pc = sh4r.pc;
nkeynes@84
   451
    if( pc > 0xFFFFFF00 ) {
nkeynes@84
   452
	/* SYSCALL Magic */
nkeynes@102
   453
	syscall_invoke( pc );
nkeynes@104
   454
	sh4r.in_delay_slot = 0;
nkeynes@84
   455
	pc = sh4r.pc = sh4r.pr;
nkeynes@84
   456
	sh4r.new_pc = sh4r.pc + 2;
nkeynes@84
   457
    }
nkeynes@208
   458
    CHECKRALIGN16(pc);
nkeynes@235
   459
nkeynes@235
   460
    /* Read instruction */
nkeynes@235
   461
    uint32_t pageaddr = pc >> 12;
nkeynes@235
   462
    if( sh4_icache != NULL && pageaddr == sh4_icache_addr ) {
nkeynes@235
   463
	ir = sh4_icache[(pc&0xFFF)>>1];
nkeynes@235
   464
    } else {
nkeynes@235
   465
	sh4_icache = (uint16_t *)mem_get_page(pc);
nkeynes@235
   466
	if( ((uint32_t)sh4_icache) < MAX_IO_REGIONS ) {
nkeynes@235
   467
	    /* If someone's actually been so daft as to try to execute out of an IO
nkeynes@235
   468
	     * region, fallback on the full-blown memory read
nkeynes@235
   469
	     */
nkeynes@235
   470
	    sh4_icache = NULL;
nkeynes@235
   471
	    ir = MEM_READ_WORD(pc);
nkeynes@235
   472
	} else {
nkeynes@235
   473
	    sh4_icache_addr = pageaddr;
nkeynes@235
   474
	    ir = sh4_icache[(pc&0xFFF)>>1];
nkeynes@235
   475
	}
nkeynes@235
   476
    }
nkeynes@1
   477
    sh4r.icount++;
nkeynes@1
   478
    
nkeynes@1
   479
    switch( (ir&0xF000)>>12 ) {
nkeynes@1
   480
        case 0: /* 0000nnnnmmmmxxxx */
nkeynes@1
   481
            switch( ir&0x000F ) {
nkeynes@1
   482
                case 2:
nkeynes@1
   483
                    switch( (ir&0x00F0)>>4 ) {
nkeynes@1
   484
                        case 0: /* STC     SR, Rn */
nkeynes@1
   485
                            CHECKPRIV();
nkeynes@1
   486
                            RN(ir) = sh4_read_sr();
nkeynes@1
   487
                            break;
nkeynes@1
   488
                        case 1: /* STC     GBR, Rn */
nkeynes@1
   489
                            RN(ir) = sh4r.gbr;
nkeynes@1
   490
                            break;
nkeynes@1
   491
                        case 2: /* STC     VBR, Rn */
nkeynes@1
   492
                            CHECKPRIV();
nkeynes@1
   493
                            RN(ir) = sh4r.vbr;
nkeynes@1
   494
                            break;
nkeynes@1
   495
                        case 3: /* STC     SSR, Rn */
nkeynes@1
   496
                            CHECKPRIV();
nkeynes@1
   497
                            RN(ir) = sh4r.ssr;
nkeynes@1
   498
                            break;
nkeynes@1
   499
                        case 4: /* STC     SPC, Rn */
nkeynes@1
   500
                            CHECKPRIV();
nkeynes@1
   501
                            RN(ir) = sh4r.spc;
nkeynes@1
   502
                            break;
nkeynes@1
   503
                        case 8: case 9: case 10: case 11: case 12: case 13:
nkeynes@1
   504
                        case 14: case 15:/* STC     Rm_bank, Rn */
nkeynes@1
   505
                            CHECKPRIV();
nkeynes@1
   506
                            RN(ir) = RN_BANK(ir);
nkeynes@1
   507
                            break;
nkeynes@1
   508
                        default: UNDEF(ir);
nkeynes@1
   509
                    }
nkeynes@1
   510
                    break;
nkeynes@1
   511
                case 3:
nkeynes@1
   512
                    switch( (ir&0x00F0)>>4 ) {
nkeynes@1
   513
                        case 0: /* BSRF    Rn */
nkeynes@232
   514
                            CHECKSLOTILLEGAL();
nkeynes@1
   515
                            CHECKDEST( pc + 4 + RN(ir) );
nkeynes@2
   516
                            sh4r.in_delay_slot = 1;
nkeynes@1
   517
                            sh4r.pr = sh4r.pc + 4;
nkeynes@1
   518
                            sh4r.pc = sh4r.new_pc;
nkeynes@1
   519
                            sh4r.new_pc = pc + 4 + RN(ir);
nkeynes@157
   520
			    TRACE_CALL( pc, sh4r.new_pc );
nkeynes@27
   521
                            return TRUE;
nkeynes@1
   522
                        case 2: /* BRAF    Rn */
nkeynes@232
   523
                            CHECKSLOTILLEGAL();
nkeynes@1
   524
                            CHECKDEST( pc + 4 + RN(ir) );
nkeynes@2
   525
                            sh4r.in_delay_slot = 1;
nkeynes@1
   526
                            sh4r.pc = sh4r.new_pc;
nkeynes@1
   527
                            sh4r.new_pc = pc + 4 + RN(ir);
nkeynes@27
   528
                            return TRUE;
nkeynes@1
   529
                        case 8: /* PREF    [Rn] */
nkeynes@2
   530
                            tmp = RN(ir);
nkeynes@2
   531
                            if( (tmp & 0xFC000000) == 0xE0000000 ) {
nkeynes@2
   532
                                /* Store queue operation */
nkeynes@2
   533
                                int queue = (tmp&0x20)>>2;
nkeynes@2
   534
                                int32_t *src = &sh4r.store_queue[queue];
nkeynes@2
   535
                                uint32_t hi = (MMIO_READ( MMU, (queue == 0 ? QACR0 : QACR1) ) & 0x1C) << 24;
nkeynes@2
   536
                                uint32_t target = tmp&0x03FFFFE0 | hi;
nkeynes@2
   537
                                mem_copy_to_sh4( target, src, 32 );
nkeynes@2
   538
                            }
nkeynes@2
   539
                            break;
nkeynes@1
   540
                        case 9: /* OCBI    [Rn] */
nkeynes@1
   541
                        case 10:/* OCBP    [Rn] */
nkeynes@1
   542
                        case 11:/* OCBWB   [Rn] */
nkeynes@1
   543
                            /* anything? */
nkeynes@1
   544
                            break;
nkeynes@1
   545
                        case 12:/* MOVCA.L R0, [Rn] */
nkeynes@164
   546
			    tmp = RN(ir);
nkeynes@208
   547
			    CHECKWALIGN32(tmp);
nkeynes@164
   548
			    MEM_WRITE_LONG( tmp, R0 );
nkeynes@164
   549
			    break;
nkeynes@1
   550
                        default: UNDEF(ir);
nkeynes@1
   551
                    }
nkeynes@1
   552
                    break;
nkeynes@1
   553
                case 4: /* MOV.B   Rm, [R0 + Rn] */
nkeynes@1
   554
                    MEM_WRITE_BYTE( R0 + RN(ir), RM(ir) );
nkeynes@1
   555
                    break;
nkeynes@1
   556
                case 5: /* MOV.W   Rm, [R0 + Rn] */
nkeynes@208
   557
		    CHECKWALIGN16( R0 + RN(ir) );
nkeynes@1
   558
                    MEM_WRITE_WORD( R0 + RN(ir), RM(ir) );
nkeynes@1
   559
                    break;
nkeynes@1
   560
                case 6: /* MOV.L   Rm, [R0 + Rn] */
nkeynes@208
   561
		    CHECKWALIGN32( R0 + RN(ir) );
nkeynes@1
   562
                    MEM_WRITE_LONG( R0 + RN(ir), RM(ir) );
nkeynes@1
   563
                    break;
nkeynes@1
   564
                case 7: /* MUL.L   Rm, Rn */
nkeynes@2
   565
                    sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
nkeynes@1
   566
                        (RM(ir) * RN(ir));
nkeynes@1
   567
                    break;
nkeynes@1
   568
                case 8: 
nkeynes@1
   569
                    switch( (ir&0x0FF0)>>4 ) {
nkeynes@1
   570
                        case 0: /* CLRT    */
nkeynes@1
   571
                            sh4r.t = 0;
nkeynes@1
   572
                            break;
nkeynes@1
   573
                        case 1: /* SETT    */
nkeynes@1
   574
                            sh4r.t = 1;
nkeynes@1
   575
                            break;
nkeynes@1
   576
                        case 2: /* CLRMAC  */
nkeynes@1
   577
                            sh4r.mac = 0;
nkeynes@1
   578
                            break;
nkeynes@1
   579
                        case 3: /* LDTLB   */
nkeynes@1
   580
                            break;
nkeynes@1
   581
                        case 4: /* CLRS    */
nkeynes@1
   582
                            sh4r.s = 0;
nkeynes@1
   583
                            break;
nkeynes@1
   584
                        case 5: /* SETS    */
nkeynes@1
   585
                            sh4r.s = 1;
nkeynes@1
   586
                            break;
nkeynes@1
   587
                        default: UNDEF(ir);
nkeynes@1
   588
                    }
nkeynes@1
   589
                    break;
nkeynes@1
   590
                case 9: 
nkeynes@1
   591
                    if( (ir&0x00F0) == 0x20 ) /* MOVT    Rn */
nkeynes@1
   592
                        RN(ir) = sh4r.t;
nkeynes@1
   593
                    else if( ir == 0x0019 ) /* DIV0U   */
nkeynes@1
   594
                        sh4r.m = sh4r.q = sh4r.t = 0;
nkeynes@1
   595
                    else if( ir == 0x0009 )
nkeynes@1
   596
                        /* NOP     */;
nkeynes@1
   597
                    else UNDEF(ir);
nkeynes@1
   598
                    break;
nkeynes@1
   599
                case 10:
nkeynes@1
   600
                    switch( (ir&0x00F0) >> 4 ) {
nkeynes@1
   601
                        case 0: /* STS     MACH, Rn */
nkeynes@1
   602
                            RN(ir) = sh4r.mac >> 32;
nkeynes@1
   603
                            break;
nkeynes@1
   604
                        case 1: /* STS     MACL, Rn */
nkeynes@1
   605
                            RN(ir) = (uint32_t)sh4r.mac;
nkeynes@1
   606
                            break;
nkeynes@1
   607
                        case 2: /* STS     PR, Rn */
nkeynes@1
   608
                            RN(ir) = sh4r.pr;
nkeynes@1
   609
                            break;
nkeynes@1
   610
                        case 3: /* STC     SGR, Rn */
nkeynes@1
   611
                            CHECKPRIV();
nkeynes@1
   612
                            RN(ir) = sh4r.sgr;
nkeynes@1
   613
                            break;
nkeynes@1
   614
                        case 5:/* STS      FPUL, Rn */
nkeynes@1
   615
                            RN(ir) = sh4r.fpul;
nkeynes@1
   616
                            break;
nkeynes@1
   617
                        case 6: /* STS     FPSCR, Rn */
nkeynes@1
   618
                            RN(ir) = sh4r.fpscr;
nkeynes@1
   619
                            break;
nkeynes@1
   620
                        case 15:/* STC     DBR, Rn */
nkeynes@1
   621
                            CHECKPRIV();
nkeynes@1
   622
                            RN(ir) = sh4r.dbr;
nkeynes@1
   623
                            break;
nkeynes@1
   624
                        default: UNDEF(ir);
nkeynes@1
   625
                    }
nkeynes@1
   626
                    break;
nkeynes@1
   627
                case 11:
nkeynes@1
   628
                    switch( (ir&0x0FF0)>>4 ) {
nkeynes@1
   629
                        case 0: /* RTS     */
nkeynes@232
   630
                            CHECKSLOTILLEGAL();
nkeynes@1
   631
                            CHECKDEST( sh4r.pr );
nkeynes@2
   632
                            sh4r.in_delay_slot = 1;
nkeynes@1
   633
                            sh4r.pc = sh4r.new_pc;
nkeynes@1
   634
                            sh4r.new_pc = sh4r.pr;
nkeynes@157
   635
                            TRACE_RETURN( pc, sh4r.new_pc );
nkeynes@27
   636
                            return TRUE;
nkeynes@1
   637
                        case 1: /* SLEEP   */
nkeynes@27
   638
			    if( MMIO_READ( CPG, STBCR ) & 0x80 ) {
nkeynes@27
   639
				sh4r.sh4_state = SH4_STATE_STANDBY;
nkeynes@27
   640
			    } else {
nkeynes@27
   641
				sh4r.sh4_state = SH4_STATE_SLEEP;
nkeynes@27
   642
			    }
nkeynes@27
   643
			    return FALSE; /* Halt CPU */
nkeynes@1
   644
                        case 2: /* RTE     */
nkeynes@1
   645
                            CHECKPRIV();
nkeynes@1
   646
                            CHECKDEST( sh4r.spc );
nkeynes@2
   647
                            CHECKSLOTILLEGAL();
nkeynes@2
   648
                            sh4r.in_delay_slot = 1;
nkeynes@1
   649
                            sh4r.pc = sh4r.new_pc;
nkeynes@1
   650
                            sh4r.new_pc = sh4r.spc;
nkeynes@1
   651
                            sh4_load_sr( sh4r.ssr );
nkeynes@27
   652
                            return TRUE;
nkeynes@1
   653
                        default:UNDEF(ir);
nkeynes@1
   654
                    }
nkeynes@1
   655
                    break;
nkeynes@1
   656
                case 12:/* MOV.B   [R0+R%d], R%d */
nkeynes@1
   657
                    RN(ir) = MEM_READ_BYTE( R0 + RM(ir) );
nkeynes@1
   658
                    break;
nkeynes@1
   659
                case 13:/* MOV.W   [R0+R%d], R%d */
nkeynes@208
   660
		    CHECKRALIGN16( R0 + RM(ir) );
nkeynes@1
   661
                    RN(ir) = MEM_READ_WORD( R0 + RM(ir) );
nkeynes@1
   662
                    break;
nkeynes@1
   663
                case 14:/* MOV.L   [R0+R%d], R%d */
nkeynes@208
   664
		    CHECKRALIGN32( R0 + RM(ir) );
nkeynes@1
   665
                    RN(ir) = MEM_READ_LONG( R0 + RM(ir) );
nkeynes@1
   666
                    break;
nkeynes@1
   667
                case 15:/* MAC.L   [Rm++], [Rn++] */
nkeynes@208
   668
		    CHECKRALIGN32( RM(ir) );
nkeynes@208
   669
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
   670
                    tmpl = ( SIGNEXT32(MEM_READ_LONG(RM(ir))) *
nkeynes@1
   671
                                  SIGNEXT32(MEM_READ_LONG(RN(ir))) );
nkeynes@1
   672
                    if( sh4r.s ) {
nkeynes@1
   673
                        /* 48-bit Saturation. Yuch */
nkeynes@1
   674
                        tmpl += SIGNEXT48(sh4r.mac);
nkeynes@2
   675
                        if( tmpl < 0xFFFF800000000000LL )
nkeynes@2
   676
                            tmpl = 0xFFFF800000000000LL;
nkeynes@2
   677
                        else if( tmpl > 0x00007FFFFFFFFFFFLL )
nkeynes@2
   678
                            tmpl = 0x00007FFFFFFFFFFFLL;
nkeynes@2
   679
                        sh4r.mac = (sh4r.mac&0xFFFF000000000000LL) |
nkeynes@2
   680
                            (tmpl&0x0000FFFFFFFFFFFFLL);
nkeynes@1
   681
                    } else sh4r.mac = tmpl;
nkeynes@1
   682
                    
nkeynes@1
   683
                    RM(ir) += 4;
nkeynes@1
   684
                    RN(ir) += 4;
nkeynes@1
   685
                    
nkeynes@1
   686
                    break;
nkeynes@1
   687
                default: UNDEF(ir);
nkeynes@1
   688
            }
nkeynes@1
   689
            break;
nkeynes@1
   690
        case 1: /* 0001nnnnmmmmdddd */
nkeynes@1
   691
            /* MOV.L   Rm, [Rn + disp4*4] */
nkeynes@208
   692
	    tmp = RN(ir) + (DISP4(ir)<<2);
nkeynes@208
   693
	    CHECKWALIGN32( tmp );
nkeynes@208
   694
            MEM_WRITE_LONG( tmp, RM(ir) );
nkeynes@1
   695
            break;
nkeynes@1
   696
        case 2: /* 0010nnnnmmmmxxxx */
nkeynes@1
   697
            switch( ir&0x000F ) {
nkeynes@1
   698
                case 0: /* MOV.B   Rm, [Rn] */
nkeynes@1
   699
                    MEM_WRITE_BYTE( RN(ir), RM(ir) );
nkeynes@1
   700
                    break;
nkeynes@1
   701
                case 1: /* MOV.W   Rm, [Rn] */
nkeynes@208
   702
               	    CHECKWALIGN16( RN(ir) );
nkeynes@208
   703
		    MEM_WRITE_WORD( RN(ir), RM(ir) );
nkeynes@1
   704
                    break;
nkeynes@1
   705
                case 2: /* MOV.L   Rm, [Rn] */
nkeynes@208
   706
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
   707
                    MEM_WRITE_LONG( RN(ir), RM(ir) );
nkeynes@1
   708
                    break;
nkeynes@1
   709
                case 3: UNDEF(ir);
nkeynes@1
   710
                    break;
nkeynes@1
   711
                case 4: /* MOV.B   Rm, [--Rn] */
nkeynes@1
   712
                    RN(ir) --;
nkeynes@1
   713
                    MEM_WRITE_BYTE( RN(ir), RM(ir) );
nkeynes@1
   714
                    break;
nkeynes@1
   715
                case 5: /* MOV.W   Rm, [--Rn] */
nkeynes@1
   716
                    RN(ir) -= 2;
nkeynes@208
   717
		    CHECKWALIGN16( RN(ir) );
nkeynes@1
   718
                    MEM_WRITE_WORD( RN(ir), RM(ir) );
nkeynes@1
   719
                    break;
nkeynes@1
   720
                case 6: /* MOV.L   Rm, [--Rn] */
nkeynes@1
   721
                    RN(ir) -= 4;
nkeynes@208
   722
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
   723
                    MEM_WRITE_LONG( RN(ir), RM(ir) );
nkeynes@1
   724
                    break;
nkeynes@1
   725
                case 7: /* DIV0S   Rm, Rn */
nkeynes@1
   726
                    sh4r.q = RN(ir)>>31;
nkeynes@1
   727
                    sh4r.m = RM(ir)>>31;
nkeynes@1
   728
                    sh4r.t = sh4r.q ^ sh4r.m;
nkeynes@1
   729
                    break;
nkeynes@1
   730
                case 8: /* TST     Rm, Rn */
nkeynes@1
   731
                    sh4r.t = (RN(ir)&RM(ir) ? 0 : 1);
nkeynes@1
   732
                    break;
nkeynes@1
   733
                case 9: /* AND     Rm, Rn */
nkeynes@1
   734
                    RN(ir) &= RM(ir);
nkeynes@1
   735
                    break;
nkeynes@1
   736
                case 10:/* XOR     Rm, Rn */
nkeynes@1
   737
                    RN(ir) ^= RM(ir);
nkeynes@1
   738
                    break;
nkeynes@1
   739
                case 11:/* OR      Rm, Rn */
nkeynes@1
   740
                    RN(ir) |= RM(ir);
nkeynes@1
   741
                    break;
nkeynes@1
   742
                case 12:/* CMP/STR Rm, Rn */
nkeynes@1
   743
                    /* set T = 1 if any byte in RM & RN is the same */
nkeynes@1
   744
                    tmp = RM(ir) ^ RN(ir);
nkeynes@1
   745
                    sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
nkeynes@1
   746
                              (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
nkeynes@1
   747
                    break;
nkeynes@1
   748
                case 13:/* XTRCT   Rm, Rn */
nkeynes@1
   749
                    RN(ir) = (RN(ir)>>16) | (RM(ir)<<16);
nkeynes@1
   750
                    break;
nkeynes@1
   751
                case 14:/* MULU.W  Rm, Rn */
nkeynes@2
   752
                    sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
nkeynes@1
   753
                        (uint32_t)((RM(ir)&0xFFFF) * (RN(ir)&0xFFFF));
nkeynes@1
   754
                    break;
nkeynes@1
   755
                case 15:/* MULS.W  Rm, Rn */
nkeynes@2
   756
                    sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
nkeynes@1
   757
                        (uint32_t)(SIGNEXT32(RM(ir)&0xFFFF) * SIGNEXT32(RN(ir)&0xFFFF));
nkeynes@1
   758
                    break;
nkeynes@1
   759
            }
nkeynes@1
   760
            break;
nkeynes@1
   761
        case 3: /* 0011nnnnmmmmxxxx */
nkeynes@1
   762
            switch( ir&0x000F ) {
nkeynes@1
   763
                case 0: /* CMP/EQ  Rm, Rn */
nkeynes@1
   764
                    sh4r.t = ( RM(ir) == RN(ir) ? 1 : 0 );
nkeynes@1
   765
                    break;
nkeynes@1
   766
                case 2: /* CMP/HS  Rm, Rn */
nkeynes@1
   767
                    sh4r.t = ( RN(ir) >= RM(ir) ? 1 : 0 );
nkeynes@1
   768
                    break;
nkeynes@1
   769
                case 3: /* CMP/GE  Rm, Rn */
nkeynes@1
   770
                    sh4r.t = ( ((int32_t)RN(ir)) >= ((int32_t)RM(ir)) ? 1 : 0 );
nkeynes@1
   771
                    break;
nkeynes@1
   772
                case 4: { /* DIV1    Rm, Rn */
nkeynes@1
   773
                    /* This is just from the sh4p manual with some
nkeynes@1
   774
                     * simplifications (someone want to check it's correct? :)
nkeynes@1
   775
                     * Why they couldn't just provide a real DIV instruction...
nkeynes@1
   776
                     * Please oh please let the translator batch these things
nkeynes@1
   777
                     * up into a single DIV... */
nkeynes@1
   778
                    uint32_t tmp0, tmp1, tmp2, dir;
nkeynes@1
   779
nkeynes@1
   780
                    dir = sh4r.q ^ sh4r.m;
nkeynes@1
   781
                    sh4r.q = (RN(ir) >> 31);
nkeynes@1
   782
                    tmp2 = RM(ir);
nkeynes@1
   783
                    RN(ir) = (RN(ir) << 1) | sh4r.t;
nkeynes@1
   784
                    tmp0 = RN(ir);
nkeynes@1
   785
                    if( dir ) {
nkeynes@1
   786
                        RN(ir) += tmp2;
nkeynes@1
   787
                        tmp1 = (RN(ir)<tmp0 ? 1 : 0 );
nkeynes@1
   788
                    } else {
nkeynes@1
   789
                        RN(ir) -= tmp2;
nkeynes@1
   790
                        tmp1 = (RN(ir)>tmp0 ? 1 : 0 );
nkeynes@1
   791
                    }
nkeynes@1
   792
                    sh4r.q ^= sh4r.m ^ tmp1;
nkeynes@1
   793
                    sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
nkeynes@1
   794
                    break; }
nkeynes@1
   795
                case 5: /* DMULU.L Rm, Rn */
nkeynes@1
   796
                    sh4r.mac = ((uint64_t)RM(ir)) * ((uint64_t)RN(ir));
nkeynes@1
   797
                    break;
nkeynes@1
   798
                case 6: /* CMP/HI  Rm, Rn */
nkeynes@1
   799
                    sh4r.t = ( RN(ir) > RM(ir) ? 1 : 0 );
nkeynes@1
   800
                    break;
nkeynes@1
   801
                case 7: /* CMP/GT  Rm, Rn */
nkeynes@1
   802
                    sh4r.t = ( ((int32_t)RN(ir)) > ((int32_t)RM(ir)) ? 1 : 0 );
nkeynes@1
   803
                    break;
nkeynes@1
   804
                case 8: /* SUB     Rm, Rn */
nkeynes@1
   805
                    RN(ir) -= RM(ir);
nkeynes@1
   806
                    break;
nkeynes@1
   807
                case 10:/* SUBC    Rm, Rn */
nkeynes@1
   808
                    tmp = RN(ir);
nkeynes@1
   809
                    RN(ir) = RN(ir) - RM(ir) - sh4r.t;
nkeynes@1
   810
                    sh4r.t = (RN(ir) > tmp || (RN(ir) == tmp && sh4r.t == 1));
nkeynes@1
   811
                    break;
nkeynes@1
   812
                case 11:/* SUBV    Rm, Rn */
nkeynes@1
   813
                    UNIMP(ir);
nkeynes@1
   814
                    break;
nkeynes@1
   815
                case 12:/* ADD     Rm, Rn */
nkeynes@1
   816
                    RN(ir) += RM(ir);
nkeynes@1
   817
                    break;
nkeynes@1
   818
                case 13:/* DMULS.L Rm, Rn */
nkeynes@1
   819
                    sh4r.mac = SIGNEXT32(RM(ir)) * SIGNEXT32(RN(ir));
nkeynes@1
   820
                    break;
nkeynes@1
   821
                case 14:/* ADDC    Rm, Rn */
nkeynes@1
   822
                    tmp = RN(ir);
nkeynes@1
   823
                    RN(ir) += RM(ir) + sh4r.t;
nkeynes@1
   824
                    sh4r.t = ( RN(ir) < tmp || (RN(ir) == tmp && sh4r.t != 0) ? 1 : 0 );
nkeynes@1
   825
                    break;
nkeynes@1
   826
                case 15:/* ADDV    Rm, Rn */
nkeynes@227
   827
		    tmp = RN(ir) + RM(ir);
nkeynes@227
   828
		    sh4r.t = ( (RN(ir)>>31) == (RM(ir)>>31) && ((RN(ir)>>31) != (tmp>>31)) );
nkeynes@227
   829
		    RN(ir) = tmp;
nkeynes@1
   830
                    break;
nkeynes@1
   831
                default: UNDEF(ir);
nkeynes@1
   832
            }
nkeynes@1
   833
            break;
nkeynes@1
   834
        case 4: /* 0100nnnnxxxxxxxx */
nkeynes@1
   835
            switch( ir&0x00FF ) {
nkeynes@1
   836
                case 0x00: /* SHLL    Rn */
nkeynes@1
   837
                    sh4r.t = RN(ir) >> 31;
nkeynes@1
   838
                    RN(ir) <<= 1;
nkeynes@1
   839
                    break;
nkeynes@1
   840
                case 0x01: /* SHLR    Rn */
nkeynes@1
   841
                    sh4r.t = RN(ir) & 0x00000001;
nkeynes@1
   842
                    RN(ir) >>= 1;
nkeynes@1
   843
                    break;
nkeynes@1
   844
                case 0x02: /* STS.L   MACH, [--Rn] */
nkeynes@1
   845
                    RN(ir) -= 4;
nkeynes@208
   846
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
   847
                    MEM_WRITE_LONG( RN(ir), (sh4r.mac>>32) );
nkeynes@1
   848
                    break;
nkeynes@1
   849
                case 0x03: /* STC.L   SR, [--Rn] */
nkeynes@1
   850
                    CHECKPRIV();
nkeynes@1
   851
                    RN(ir) -= 4;
nkeynes@208
   852
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
   853
                    MEM_WRITE_LONG( RN(ir), sh4_read_sr() );
nkeynes@1
   854
                    break;
nkeynes@1
   855
                case 0x04: /* ROTL    Rn */
nkeynes@1
   856
                    sh4r.t = RN(ir) >> 31;
nkeynes@1
   857
                    RN(ir) <<= 1;
nkeynes@1
   858
                    RN(ir) |= sh4r.t;
nkeynes@1
   859
                    break;
nkeynes@1
   860
                case 0x05: /* ROTR    Rn */
nkeynes@1
   861
                    sh4r.t = RN(ir) & 0x00000001;
nkeynes@1
   862
                    RN(ir) >>= 1;
nkeynes@1
   863
                    RN(ir) |= (sh4r.t << 31);
nkeynes@1
   864
                    break;
nkeynes@1
   865
                case 0x06: /* LDS.L   [Rn++], MACH */
nkeynes@208
   866
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
   867
                    sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
nkeynes@1
   868
                        (((uint64_t)MEM_READ_LONG(RN(ir)))<<32);
nkeynes@1
   869
                    RN(ir) += 4;
nkeynes@1
   870
                    break;
nkeynes@1
   871
                case 0x07: /* LDC.L   [Rn++], SR */
nkeynes@232
   872
		    CHECKSLOTILLEGAL();
nkeynes@1
   873
                    CHECKPRIV();
nkeynes@208
   874
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
   875
                    sh4_load_sr( MEM_READ_LONG(RN(ir)) );
nkeynes@1
   876
                    RN(ir) +=4;
nkeynes@1
   877
                    break;
nkeynes@1
   878
                case 0x08: /* SHLL2   Rn */
nkeynes@1
   879
                    RN(ir) <<= 2;
nkeynes@1
   880
                    break;
nkeynes@1
   881
                case 0x09: /* SHLR2   Rn */
nkeynes@1
   882
                    RN(ir) >>= 2;
nkeynes@1
   883
                    break;
nkeynes@1
   884
                case 0x0A: /* LDS     Rn, MACH */
nkeynes@1
   885
                    sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
nkeynes@1
   886
                        (((uint64_t)RN(ir))<<32);
nkeynes@1
   887
                    break;
nkeynes@1
   888
                case 0x0B: /* JSR     [Rn] */
nkeynes@1
   889
                    CHECKDEST( RN(ir) );
nkeynes@2
   890
                    CHECKSLOTILLEGAL();
nkeynes@2
   891
                    sh4r.in_delay_slot = 1;
nkeynes@1
   892
                    sh4r.pc = sh4r.new_pc;
nkeynes@1
   893
                    sh4r.new_pc = RN(ir);
nkeynes@1
   894
                    sh4r.pr = pc + 4;
nkeynes@157
   895
		    TRACE_CALL( pc, sh4r.new_pc );
nkeynes@27
   896
                    return TRUE;
nkeynes@1
   897
                case 0x0E: /* LDC     Rn, SR */
nkeynes@232
   898
		    CHECKSLOTILLEGAL();
nkeynes@1
   899
                    CHECKPRIV();
nkeynes@1
   900
                    sh4_load_sr( RN(ir) );
nkeynes@1
   901
                    break;
nkeynes@1
   902
                case 0x10: /* DT      Rn */
nkeynes@1
   903
                    RN(ir) --;
nkeynes@1
   904
                    sh4r.t = ( RN(ir) == 0 ? 1 : 0 );
nkeynes@1
   905
                    break;
nkeynes@1
   906
                case 0x11: /* CMP/PZ  Rn */
nkeynes@1
   907
                    sh4r.t = ( ((int32_t)RN(ir)) >= 0 ? 1 : 0 );
nkeynes@1
   908
                    break;
nkeynes@1
   909
                case 0x12: /* STS.L   MACL, [--Rn] */
nkeynes@1
   910
                    RN(ir) -= 4;
nkeynes@208
   911
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
   912
                    MEM_WRITE_LONG( RN(ir), (uint32_t)sh4r.mac );
nkeynes@1
   913
                    break;
nkeynes@1
   914
                case 0x13: /* STC.L   GBR, [--Rn] */
nkeynes@1
   915
                    RN(ir) -= 4;
nkeynes@208
   916
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
   917
                    MEM_WRITE_LONG( RN(ir), sh4r.gbr );
nkeynes@1
   918
                    break;
nkeynes@1
   919
                case 0x15: /* CMP/PL  Rn */
nkeynes@1
   920
                    sh4r.t = ( ((int32_t)RN(ir)) > 0 ? 1 : 0 );
nkeynes@1
   921
                    break;
nkeynes@1
   922
                case 0x16: /* LDS.L   [Rn++], MACL */
nkeynes@208
   923
		    CHECKRALIGN32( RN(ir) );
nkeynes@2
   924
                    sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
nkeynes@1
   925
                        (uint64_t)((uint32_t)MEM_READ_LONG(RN(ir)));
nkeynes@1
   926
                    RN(ir) += 4;
nkeynes@1
   927
                    break;
nkeynes@1
   928
                case 0x17: /* LDC.L   [Rn++], GBR */
nkeynes@208
   929
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
   930
                    sh4r.gbr = MEM_READ_LONG(RN(ir));
nkeynes@1
   931
                    RN(ir) +=4;
nkeynes@1
   932
                    break;
nkeynes@1
   933
                case 0x18: /* SHLL8   Rn */
nkeynes@1
   934
                    RN(ir) <<= 8;
nkeynes@1
   935
                    break;
nkeynes@1
   936
                case 0x19: /* SHLR8   Rn */
nkeynes@1
   937
                    RN(ir) >>= 8;
nkeynes@1
   938
                    break;
nkeynes@1
   939
                case 0x1A: /* LDS     Rn, MACL */
nkeynes@2
   940
                    sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
nkeynes@1
   941
                        (uint64_t)((uint32_t)(RN(ir)));
nkeynes@1
   942
                    break;
nkeynes@1
   943
                case 0x1B: /* TAS.B   [Rn] */
nkeynes@1
   944
                    tmp = MEM_READ_BYTE( RN(ir) );
nkeynes@1
   945
                    sh4r.t = ( tmp == 0 ? 1 : 0 );
nkeynes@1
   946
                    MEM_WRITE_BYTE( RN(ir), tmp | 0x80 );
nkeynes@1
   947
                    break;
nkeynes@1
   948
                case 0x1E: /* LDC     Rn, GBR */
nkeynes@1
   949
                    sh4r.gbr = RN(ir);
nkeynes@1
   950
                    break;
nkeynes@1
   951
                case 0x20: /* SHAL    Rn */
nkeynes@1
   952
                    sh4r.t = RN(ir) >> 31;
nkeynes@1
   953
                    RN(ir) <<= 1;
nkeynes@1
   954
                    break;
nkeynes@1
   955
                case 0x21: /* SHAR    Rn */
nkeynes@1
   956
                    sh4r.t = RN(ir) & 0x00000001;
nkeynes@1
   957
                    RN(ir) = ((int32_t)RN(ir)) >> 1;
nkeynes@1
   958
                    break;
nkeynes@1
   959
                case 0x22: /* STS.L   PR, [--Rn] */
nkeynes@1
   960
                    RN(ir) -= 4;
nkeynes@208
   961
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
   962
                    MEM_WRITE_LONG( RN(ir), sh4r.pr );
nkeynes@1
   963
                    break;
nkeynes@1
   964
                case 0x23: /* STC.L   VBR, [--Rn] */
nkeynes@1
   965
                    CHECKPRIV();
nkeynes@1
   966
                    RN(ir) -= 4;
nkeynes@208
   967
		    CHECKWALIGN32( RN(ir) );
nkeynes@2
   968
                    MEM_WRITE_LONG( RN(ir), sh4r.vbr );
nkeynes@1
   969
                    break;
nkeynes@1
   970
                case 0x24: /* ROTCL   Rn */
nkeynes@1
   971
                    tmp = RN(ir) >> 31;
nkeynes@1
   972
                    RN(ir) <<= 1;
nkeynes@1
   973
                    RN(ir) |= sh4r.t;
nkeynes@1
   974
                    sh4r.t = tmp;
nkeynes@1
   975
                    break;
nkeynes@1
   976
                case 0x25: /* ROTCR   Rn */
nkeynes@1
   977
                    tmp = RN(ir) & 0x00000001;
nkeynes@1
   978
                    RN(ir) >>= 1;
nkeynes@1
   979
                    RN(ir) |= (sh4r.t << 31 );
nkeynes@1
   980
                    sh4r.t = tmp;
nkeynes@1
   981
                    break;
nkeynes@1
   982
                case 0x26: /* LDS.L   [Rn++], PR */
nkeynes@208
   983
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
   984
                    sh4r.pr = MEM_READ_LONG( RN(ir) );
nkeynes@1
   985
                    RN(ir) += 4;
nkeynes@1
   986
                    break;
nkeynes@1
   987
                case 0x27: /* LDC.L   [Rn++], VBR */
nkeynes@1
   988
                    CHECKPRIV();
nkeynes@208
   989
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
   990
                    sh4r.vbr = MEM_READ_LONG(RN(ir));
nkeynes@1
   991
                    RN(ir) +=4;
nkeynes@1
   992
                    break;
nkeynes@1
   993
                case 0x28: /* SHLL16  Rn */
nkeynes@1
   994
                    RN(ir) <<= 16;
nkeynes@1
   995
                    break;
nkeynes@1
   996
                case 0x29: /* SHLR16  Rn */
nkeynes@1
   997
                    RN(ir) >>= 16;
nkeynes@1
   998
                    break;
nkeynes@1
   999
                case 0x2A: /* LDS     Rn, PR */
nkeynes@1
  1000
                    sh4r.pr = RN(ir);
nkeynes@1
  1001
                    break;
nkeynes@1
  1002
                case 0x2B: /* JMP     [Rn] */
nkeynes@1
  1003
                    CHECKDEST( RN(ir) );
nkeynes@2
  1004
                    CHECKSLOTILLEGAL();
nkeynes@2
  1005
                    sh4r.in_delay_slot = 1;
nkeynes@1
  1006
                    sh4r.pc = sh4r.new_pc;
nkeynes@1
  1007
                    sh4r.new_pc = RN(ir);
nkeynes@27
  1008
                    return TRUE;
nkeynes@1
  1009
                case 0x2E: /* LDC     Rn, VBR */
nkeynes@1
  1010
                    CHECKPRIV();
nkeynes@1
  1011
                    sh4r.vbr = RN(ir);
nkeynes@1
  1012
                    break;
nkeynes@1
  1013
                case 0x32: /* STC.L   SGR, [--Rn] */
nkeynes@1
  1014
                    CHECKPRIV();
nkeynes@1
  1015
                    RN(ir) -= 4;
nkeynes@208
  1016
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
  1017
                    MEM_WRITE_LONG( RN(ir), sh4r.sgr );
nkeynes@1
  1018
                    break;
nkeynes@1
  1019
                case 0x33: /* STC.L   SSR, [--Rn] */
nkeynes@1
  1020
                    CHECKPRIV();
nkeynes@1
  1021
                    RN(ir) -= 4;
nkeynes@208
  1022
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
  1023
                    MEM_WRITE_LONG( RN(ir), sh4r.ssr );
nkeynes@1
  1024
                    break;
nkeynes@1
  1025
                case 0x37: /* LDC.L   [Rn++], SSR */
nkeynes@1
  1026
                    CHECKPRIV();
nkeynes@208
  1027
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
  1028
                    sh4r.ssr = MEM_READ_LONG(RN(ir));
nkeynes@1
  1029
                    RN(ir) +=4;
nkeynes@1
  1030
                    break;
nkeynes@1
  1031
                case 0x3E: /* LDC     Rn, SSR */
nkeynes@1
  1032
                    CHECKPRIV();
nkeynes@1
  1033
                    sh4r.ssr = RN(ir);
nkeynes@1
  1034
                    break;
nkeynes@1
  1035
                case 0x43: /* STC.L   SPC, [--Rn] */
nkeynes@1
  1036
                    CHECKPRIV();
nkeynes@1
  1037
                    RN(ir) -= 4;
nkeynes@208
  1038
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
  1039
                    MEM_WRITE_LONG( RN(ir), sh4r.spc );
nkeynes@1
  1040
                    break;
nkeynes@1
  1041
                case 0x47: /* LDC.L   [Rn++], SPC */
nkeynes@1
  1042
                    CHECKPRIV();
nkeynes@208
  1043
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
  1044
                    sh4r.spc = MEM_READ_LONG(RN(ir));
nkeynes@1
  1045
                    RN(ir) +=4;
nkeynes@1
  1046
                    break;
nkeynes@1
  1047
                case 0x4E: /* LDC     Rn, SPC */
nkeynes@1
  1048
                    CHECKPRIV();
nkeynes@1
  1049
                    sh4r.spc = RN(ir);
nkeynes@1
  1050
                    break;
nkeynes@1
  1051
                case 0x52: /* STS.L   FPUL, [--Rn] */
nkeynes@1
  1052
                    RN(ir) -= 4;
nkeynes@208
  1053
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
  1054
                    MEM_WRITE_LONG( RN(ir), sh4r.fpul );
nkeynes@1
  1055
                    break;
nkeynes@1
  1056
                case 0x56: /* LDS.L   [Rn++], FPUL */
nkeynes@208
  1057
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
  1058
                    sh4r.fpul = MEM_READ_LONG(RN(ir));
nkeynes@1
  1059
                    RN(ir) +=4;
nkeynes@1
  1060
                    break;
nkeynes@1
  1061
                case 0x5A: /* LDS     Rn, FPUL */
nkeynes@1
  1062
                    sh4r.fpul = RN(ir);
nkeynes@1
  1063
                    break;
nkeynes@1
  1064
                case 0x62: /* STS.L   FPSCR, [--Rn] */
nkeynes@1
  1065
                    RN(ir) -= 4;
nkeynes@208
  1066
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
  1067
                    MEM_WRITE_LONG( RN(ir), sh4r.fpscr );
nkeynes@1
  1068
                    break;
nkeynes@1
  1069
                case 0x66: /* LDS.L   [Rn++], FPSCR */
nkeynes@208
  1070
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
  1071
                    sh4r.fpscr = MEM_READ_LONG(RN(ir));
nkeynes@1
  1072
                    RN(ir) +=4;
nkeynes@1
  1073
                    break;
nkeynes@1
  1074
                case 0x6A: /* LDS     Rn, FPSCR */
nkeynes@1
  1075
                    sh4r.fpscr = RN(ir);
nkeynes@1
  1076
                    break;
nkeynes@1
  1077
                case 0xF2: /* STC.L   DBR, [--Rn] */
nkeynes@1
  1078
                    CHECKPRIV();
nkeynes@1
  1079
                    RN(ir) -= 4;
nkeynes@208
  1080
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
  1081
                    MEM_WRITE_LONG( RN(ir), sh4r.dbr );
nkeynes@1
  1082
                    break;
nkeynes@1
  1083
                case 0xF6: /* LDC.L   [Rn++], DBR */
nkeynes@1
  1084
                    CHECKPRIV();
nkeynes@208
  1085
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
  1086
                    sh4r.dbr = MEM_READ_LONG(RN(ir));
nkeynes@1
  1087
                    RN(ir) +=4;
nkeynes@1
  1088
                    break;
nkeynes@1
  1089
                case 0xFA: /* LDC     Rn, DBR */
nkeynes@1
  1090
                    CHECKPRIV();
nkeynes@1
  1091
                    sh4r.dbr = RN(ir);
nkeynes@1
  1092
                    break;
nkeynes@1
  1093
                case 0x83: case 0x93: case 0xA3: case 0xB3: case 0xC3:
nkeynes@1
  1094
                case 0xD3: case 0xE3: case 0xF3: /* STC.L   Rn_BANK, [--Rn] */
nkeynes@1
  1095
                    CHECKPRIV();
nkeynes@1
  1096
                    RN(ir) -= 4;
nkeynes@208
  1097
		    CHECKWALIGN32( RN(ir) );
nkeynes@1
  1098
                    MEM_WRITE_LONG( RN(ir), RN_BANK(ir) );
nkeynes@1
  1099
                    break;
nkeynes@1
  1100
                case 0x87: case 0x97: case 0xA7: case 0xB7: case 0xC7:
nkeynes@1
  1101
                case 0xD7: case 0xE7: case 0xF7: /* LDC.L   [Rn++], Rn_BANK */
nkeynes@1
  1102
                    CHECKPRIV();
nkeynes@208
  1103
		    CHECKRALIGN32( RN(ir) );
nkeynes@1
  1104
                    RN_BANK(ir) = MEM_READ_LONG( RN(ir) );
nkeynes@1
  1105
                    RN(ir) += 4;
nkeynes@1
  1106
                    break;
nkeynes@1
  1107
                case 0x8E: case 0x9E: case 0xAE: case 0xBE: case 0xCE:
nkeynes@1
  1108
                case 0xDE: case 0xEE: case 0xFE: /* LDC     Rm, Rn_BANK */
nkeynes@1
  1109
                    CHECKPRIV();
nkeynes@1
  1110
                    RN_BANK(ir) = RM(ir);
nkeynes@1
  1111
                    break;
nkeynes@1
  1112
                default:
nkeynes@1
  1113
                    if( (ir&0x000F) == 0x0F ) {
nkeynes@1
  1114
                        /* MAC.W   [Rm++], [Rn++] */
nkeynes@208
  1115
			CHECKRALIGN16( RN(ir) );
nkeynes@208
  1116
			CHECKRALIGN16( RM(ir) );
nkeynes@1
  1117
                        tmp = SIGNEXT16(MEM_READ_WORD(RM(ir))) *
nkeynes@1
  1118
                            SIGNEXT16(MEM_READ_WORD(RN(ir)));
nkeynes@1
  1119
                        if( sh4r.s ) {
nkeynes@1
  1120
                            /* FIXME */
nkeynes@1
  1121
                            UNIMP(ir);
nkeynes@1
  1122
                        } else sh4r.mac += SIGNEXT32(tmp);
nkeynes@1
  1123
                        RM(ir) += 2;
nkeynes@1
  1124
                        RN(ir) += 2;
nkeynes@1
  1125
                    } else if( (ir&0x000F) == 0x0C ) {
nkeynes@1
  1126
                        /* SHAD    Rm, Rn */
nkeynes@1
  1127
                        tmp = RM(ir);
nkeynes@1
  1128
                        if( (tmp & 0x80000000) == 0 ) RN(ir) <<= (tmp&0x1f);
nkeynes@9
  1129
                        else if( (tmp & 0x1F) == 0 )  
nkeynes@9
  1130
			  RN(ir) = ((int32_t)RN(ir)) >> 31;
nkeynes@9
  1131
                        else 
nkeynes@9
  1132
			  RN(ir) = ((int32_t)RN(ir)) >> (((~RM(ir)) & 0x1F)+1);
nkeynes@1
  1133
                    } else if( (ir&0x000F) == 0x0D ) {
nkeynes@1
  1134
                        /* SHLD    Rm, Rn */
nkeynes@1
  1135
                        tmp = RM(ir);
nkeynes@1
  1136
                        if( (tmp & 0x80000000) == 0 ) RN(ir) <<= (tmp&0x1f);
nkeynes@1
  1137
                        else if( (tmp & 0x1F) == 0 ) RN(ir) = 0;
nkeynes@1
  1138
                        else RN(ir) >>= (((~tmp) & 0x1F)+1);
nkeynes@1
  1139
                    } else UNDEF(ir);
nkeynes@1
  1140
            }
nkeynes@1
  1141
            break;
nkeynes@1
  1142
        case 5: /* 0101nnnnmmmmdddd */
nkeynes@1
  1143
            /* MOV.L   [Rm + disp4*4], Rn */
nkeynes@208
  1144
	    tmp = RM(ir) + (DISP4(ir)<<2);
nkeynes@208
  1145
	    CHECKRALIGN32( tmp );
nkeynes@208
  1146
            RN(ir) = MEM_READ_LONG( tmp );
nkeynes@1
  1147
            break;
nkeynes@1
  1148
        case 6: /* 0110xxxxxxxxxxxx */
nkeynes@1
  1149
            switch( ir&0x000f ) {
nkeynes@1
  1150
                case 0: /* MOV.B   [Rm], Rn */
nkeynes@1
  1151
                    RN(ir) = MEM_READ_BYTE( RM(ir) );
nkeynes@1
  1152
                    break;
nkeynes@1
  1153
                case 1: /* MOV.W   [Rm], Rn */
nkeynes@208
  1154
		    CHECKRALIGN16( RM(ir) );
nkeynes@1
  1155
                    RN(ir) = MEM_READ_WORD( RM(ir) );
nkeynes@1
  1156
                    break;
nkeynes@1
  1157
                case 2: /* MOV.L   [Rm], Rn */
nkeynes@208
  1158
		    CHECKRALIGN32( RM(ir) );
nkeynes@1
  1159
                    RN(ir) = MEM_READ_LONG( RM(ir) );
nkeynes@1
  1160
                    break;
nkeynes@1
  1161
                case 3: /* MOV     Rm, Rn */
nkeynes@1
  1162
                    RN(ir) = RM(ir);
nkeynes@1
  1163
                    break;
nkeynes@1
  1164
                case 4: /* MOV.B   [Rm++], Rn */
nkeynes@1
  1165
                    RN(ir) = MEM_READ_BYTE( RM(ir) );
nkeynes@1
  1166
                    RM(ir) ++;
nkeynes@1
  1167
                    break;
nkeynes@1
  1168
                case 5: /* MOV.W   [Rm++], Rn */
nkeynes@208
  1169
		    CHECKRALIGN16( RM(ir) );
nkeynes@1
  1170
                    RN(ir) = MEM_READ_WORD( RM(ir) );
nkeynes@1
  1171
                    RM(ir) += 2;
nkeynes@1
  1172
                    break;
nkeynes@1
  1173
                case 6: /* MOV.L   [Rm++], Rn */
nkeynes@208
  1174
		    CHECKRALIGN32( RM(ir) );
nkeynes@1
  1175
                    RN(ir) = MEM_READ_LONG( RM(ir) );
nkeynes@1
  1176
                    RM(ir) += 4;
nkeynes@1
  1177
                    break;
nkeynes@1
  1178
                case 7: /* NOT     Rm, Rn */
nkeynes@1
  1179
                    RN(ir) = ~RM(ir);
nkeynes@1
  1180
                    break;
nkeynes@1
  1181
                case 8: /* SWAP.B  Rm, Rn */
nkeynes@1
  1182
                    RN(ir) = (RM(ir)&0xFFFF0000) | ((RM(ir)&0x0000FF00)>>8) |
nkeynes@1
  1183
                        ((RM(ir)&0x000000FF)<<8);
nkeynes@1
  1184
                    break;
nkeynes@1
  1185
                case 9: /* SWAP.W  Rm, Rn */
nkeynes@1
  1186
                    RN(ir) = (RM(ir)>>16) | (RM(ir)<<16);
nkeynes@1
  1187
                    break;
nkeynes@1
  1188
                case 10:/* NEGC    Rm, Rn */
nkeynes@1
  1189
                    tmp = 0 - RM(ir);
nkeynes@1
  1190
                    RN(ir) = tmp - sh4r.t;
nkeynes@1
  1191
                    sh4r.t = ( 0<tmp || tmp<RN(ir) ? 1 : 0 );
nkeynes@1
  1192
                    break;
nkeynes@1
  1193
                case 11:/* NEG     Rm, Rn */
nkeynes@1
  1194
                    RN(ir) = 0 - RM(ir);
nkeynes@1
  1195
                    break;
nkeynes@1
  1196
                case 12:/* EXTU.B  Rm, Rn */
nkeynes@1
  1197
                    RN(ir) = RM(ir)&0x000000FF;
nkeynes@1
  1198
                    break;
nkeynes@1
  1199
                case 13:/* EXTU.W  Rm, Rn */
nkeynes@1
  1200
                    RN(ir) = RM(ir)&0x0000FFFF;
nkeynes@1
  1201
                    break;
nkeynes@1
  1202
                case 14:/* EXTS.B  Rm, Rn */
nkeynes@1
  1203
                    RN(ir) = SIGNEXT8( RM(ir)&0x000000FF );
nkeynes@1
  1204
                    break;
nkeynes@1
  1205
                case 15:/* EXTS.W  Rm, Rn */
nkeynes@1
  1206
                    RN(ir) = SIGNEXT16( RM(ir)&0x0000FFFF );
nkeynes@1
  1207
                    break;
nkeynes@1
  1208
            }
nkeynes@1
  1209
            break;
nkeynes@1
  1210
        case 7: /* 0111nnnniiiiiiii */
nkeynes@1
  1211
            /* ADD    imm8, Rn */
nkeynes@1
  1212
            RN(ir) += IMM8(ir);
nkeynes@1
  1213
            break;
nkeynes@1
  1214
        case 8: /* 1000xxxxxxxxxxxx */
nkeynes@1
  1215
            switch( (ir&0x0F00) >> 8 ) {
nkeynes@1
  1216
                case 0: /* MOV.B   R0, [Rm + disp4] */
nkeynes@1
  1217
                    MEM_WRITE_BYTE( RM(ir) + DISP4(ir), R0 );
nkeynes@1
  1218
                    break;
nkeynes@1
  1219
                case 1: /* MOV.W   R0, [Rm + disp4*2] */
nkeynes@208
  1220
		    tmp = RM(ir) + (DISP4(ir)<<1);
nkeynes@208
  1221
		    CHECKWALIGN16( tmp );
nkeynes@208
  1222
                    MEM_WRITE_WORD( tmp, R0 );
nkeynes@1
  1223
                    break;
nkeynes@1
  1224
                case 4: /* MOV.B   [Rm + disp4], R0 */
nkeynes@1
  1225
                    R0 = MEM_READ_BYTE( RM(ir) + DISP4(ir) );
nkeynes@1
  1226
                    break;
nkeynes@1
  1227
                case 5: /* MOV.W   [Rm + disp4*2], R0 */
nkeynes@208
  1228
		    tmp = RM(ir) + (DISP4(ir)<<1);
nkeynes@208
  1229
		    CHECKRALIGN16( tmp );
nkeynes@208
  1230
                    R0 = MEM_READ_WORD( tmp );
nkeynes@1
  1231
                    break;
nkeynes@1
  1232
                case 8: /* CMP/EQ  imm, R0 */
nkeynes@1
  1233
                    sh4r.t = ( R0 == IMM8(ir) ? 1 : 0 );
nkeynes@1
  1234
                    break;
nkeynes@1
  1235
                case 9: /* BT      disp8 */
nkeynes@246
  1236
                    CHECKSLOTILLEGAL();
nkeynes@1
  1237
                    if( sh4r.t ) {
nkeynes@1
  1238
                        CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
nkeynes@1
  1239
                        sh4r.pc += (PCDISP8(ir)<<1) + 4;
nkeynes@1
  1240
                        sh4r.new_pc = sh4r.pc + 2;
nkeynes@27
  1241
                        return TRUE;
nkeynes@1
  1242
                    }
nkeynes@1
  1243
                    break;
nkeynes@1
  1244
                case 11:/* BF      disp8 */
nkeynes@246
  1245
                    CHECKSLOTILLEGAL();
nkeynes@1
  1246
                    if( !sh4r.t ) {
nkeynes@1
  1247
                        CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
nkeynes@1
  1248
                        sh4r.pc += (PCDISP8(ir)<<1) + 4;
nkeynes@1
  1249
                        sh4r.new_pc = sh4r.pc + 2;
nkeynes@27
  1250
                        return TRUE;
nkeynes@1
  1251
                    }
nkeynes@1
  1252
                    break;
nkeynes@1
  1253
                case 13:/* BT/S    disp8 */
nkeynes@246
  1254
                    CHECKSLOTILLEGAL();
nkeynes@1
  1255
                    if( sh4r.t ) {
nkeynes@1
  1256
                        CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
nkeynes@2
  1257
                        sh4r.in_delay_slot = 1;
nkeynes@1
  1258
                        sh4r.pc = sh4r.new_pc;
nkeynes@1
  1259
                        sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
nkeynes@2
  1260
                        sh4r.in_delay_slot = 1;
nkeynes@27
  1261
                        return TRUE;
nkeynes@1
  1262
                    }
nkeynes@1
  1263
                    break;
nkeynes@1
  1264
                case 15:/* BF/S    disp8 */
nkeynes@246
  1265
                    CHECKSLOTILLEGAL();
nkeynes@1
  1266
                    if( !sh4r.t ) {
nkeynes@1
  1267
                        CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
nkeynes@2
  1268
                        sh4r.in_delay_slot = 1;
nkeynes@1
  1269
                        sh4r.pc = sh4r.new_pc;
nkeynes@1
  1270
                        sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
nkeynes@27
  1271
                        return TRUE;
nkeynes@1
  1272
                    }
nkeynes@1
  1273
                    break;
nkeynes@1
  1274
                default: UNDEF(ir);
nkeynes@1
  1275
            }
nkeynes@1
  1276
            break;
nkeynes@1
  1277
        case 9: /* 1001xxxxxxxxxxxx */
nkeynes@1
  1278
            /* MOV.W   [disp8*2 + pc + 4], Rn */
nkeynes@232
  1279
	    CHECKSLOTILLEGAL();
nkeynes@208
  1280
	    tmp = pc + 4 + (DISP8(ir)<<1);
nkeynes@208
  1281
            RN(ir) = MEM_READ_WORD( tmp );
nkeynes@1
  1282
            break;
nkeynes@1
  1283
        case 10:/* 1010dddddddddddd */
nkeynes@1
  1284
            /* BRA     disp12 */
nkeynes@246
  1285
            CHECKSLOTILLEGAL();
nkeynes@246
  1286
            CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 );
nkeynes@2
  1287
            sh4r.in_delay_slot = 1;
nkeynes@1
  1288
            sh4r.pc = sh4r.new_pc;
nkeynes@1
  1289
            sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
nkeynes@27
  1290
            return TRUE;
nkeynes@1
  1291
        case 11:/* 1011dddddddddddd */
nkeynes@1
  1292
            /* BSR     disp12 */
nkeynes@246
  1293
            CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 );
nkeynes@246
  1294
	    CHECKSLOTILLEGAL();
nkeynes@2
  1295
            sh4r.in_delay_slot = 1;
nkeynes@1
  1296
            sh4r.pr = pc + 4;
nkeynes@1
  1297
            sh4r.pc = sh4r.new_pc;
nkeynes@1
  1298
            sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
nkeynes@157
  1299
	    TRACE_CALL( pc, sh4r.new_pc );
nkeynes@27
  1300
            return TRUE;
nkeynes@1
  1301
        case 12:/* 1100xxxxdddddddd */
nkeynes@1
  1302
        switch( (ir&0x0F00)>>8 ) {
nkeynes@1
  1303
                case 0: /* MOV.B  R0, [GBR + disp8] */
nkeynes@1
  1304
                    MEM_WRITE_BYTE( sh4r.gbr + DISP8(ir), R0 );
nkeynes@1
  1305
                    break;
nkeynes@1
  1306
                case 1: /* MOV.W  R0, [GBR + disp8*2] */
nkeynes@208
  1307
		    tmp = sh4r.gbr + (DISP8(ir)<<1);
nkeynes@208
  1308
		    CHECKWALIGN16( tmp );
nkeynes@208
  1309
                    MEM_WRITE_WORD( tmp, R0 );
nkeynes@1
  1310
                    break;
nkeynes@1
  1311
                case  2: /*MOV.L   R0, [GBR + disp8*4] */
nkeynes@208
  1312
		    tmp = sh4r.gbr + (DISP8(ir)<<2);
nkeynes@208
  1313
		    CHECKWALIGN32( tmp );
nkeynes@208
  1314
                    MEM_WRITE_LONG( tmp, R0 );
nkeynes@1
  1315
                    break;
nkeynes@1
  1316
                case 3: /* TRAPA   imm8 */
nkeynes@246
  1317
                    CHECKSLOTILLEGAL();
nkeynes@116
  1318
                    MMIO_WRITE( MMU, TRA, UIMM8(ir)<<2 );
nkeynes@246
  1319
		    sh4r.pc += 2;
nkeynes@246
  1320
                    sh4_raise_exception( EXC_TRAP );
nkeynes@1
  1321
                    break;
nkeynes@1
  1322
                case 4: /* MOV.B   [GBR + disp8], R0 */
nkeynes@1
  1323
                    R0 = MEM_READ_BYTE( sh4r.gbr + DISP8(ir) );
nkeynes@1
  1324
                    break;
nkeynes@1
  1325
                case 5: /* MOV.W   [GBR + disp8*2], R0 */
nkeynes@208
  1326
		    tmp = sh4r.gbr + (DISP8(ir)<<1);
nkeynes@208
  1327
		    CHECKRALIGN16( tmp );
nkeynes@208
  1328
                    R0 = MEM_READ_WORD( tmp );
nkeynes@1
  1329
                    break;
nkeynes@1
  1330
                case 6: /* MOV.L   [GBR + disp8*4], R0 */
nkeynes@208
  1331
		    tmp = sh4r.gbr + (DISP8(ir)<<2);
nkeynes@208
  1332
		    CHECKRALIGN32( tmp );
nkeynes@208
  1333
                    R0 = MEM_READ_LONG( tmp );
nkeynes@1
  1334
                    break;
nkeynes@1
  1335
                case 7: /* MOVA    disp8 + pc&~3 + 4, R0 */
nkeynes@232
  1336
		    CHECKSLOTILLEGAL();
nkeynes@1
  1337
                    R0 = (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4;
nkeynes@1
  1338
                    break;
nkeynes@1
  1339
                case 8: /* TST     imm8, R0 */
nkeynes@1
  1340
                    sh4r.t = (R0 & UIMM8(ir) ? 0 : 1);
nkeynes@1
  1341
                    break;
nkeynes@1
  1342
                case 9: /* AND     imm8, R0 */
nkeynes@1
  1343
                    R0 &= UIMM8(ir);
nkeynes@1
  1344
                    break;
nkeynes@1
  1345
                case 10:/* XOR     imm8, R0 */
nkeynes@1
  1346
                    R0 ^= UIMM8(ir);
nkeynes@1
  1347
                    break;
nkeynes@1
  1348
                case 11:/* OR      imm8, R0 */
nkeynes@1
  1349
                    R0 |= UIMM8(ir);
nkeynes@1
  1350
                    break;
nkeynes@208
  1351
                case 12:/* TST.B   imm8, [R0+GBR] */		    
nkeynes@1
  1352
                    sh4r.t = ( MEM_READ_BYTE(R0 + sh4r.gbr) & UIMM8(ir) ? 0 : 1 );
nkeynes@1
  1353
                    break;
nkeynes@1
  1354
                case 13:/* AND.B   imm8, [R0+GBR] */
nkeynes@1
  1355
                    MEM_WRITE_BYTE( R0 + sh4r.gbr,
nkeynes@1
  1356
                                    UIMM8(ir) & MEM_READ_BYTE(R0 + sh4r.gbr) );
nkeynes@1
  1357
                    break;
nkeynes@1
  1358
                case 14:/* XOR.B   imm8, [R0+GBR] */
nkeynes@1
  1359
                    MEM_WRITE_BYTE( R0 + sh4r.gbr,
nkeynes@1
  1360
                                    UIMM8(ir) ^ MEM_READ_BYTE(R0 + sh4r.gbr) );
nkeynes@1
  1361
                    break;
nkeynes@1
  1362
                case 15:/* OR.B    imm8, [R0+GBR] */
nkeynes@1
  1363
                    MEM_WRITE_BYTE( R0 + sh4r.gbr,
nkeynes@1
  1364
                                    UIMM8(ir) | MEM_READ_BYTE(R0 + sh4r.gbr) );
nkeynes@1
  1365
                    break;
nkeynes@1
  1366
            }
nkeynes@1
  1367
            break;
nkeynes@1
  1368
        case 13:/* 1101nnnndddddddd */
nkeynes@1
  1369
            /* MOV.L   [disp8*4 + pc&~3 + 4], Rn */
nkeynes@232
  1370
	    CHECKSLOTILLEGAL();
nkeynes@208
  1371
	    tmp = (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4;
nkeynes@208
  1372
            RN(ir) = MEM_READ_LONG( tmp );
nkeynes@1
  1373
            break;
nkeynes@1
  1374
        case 14:/* 1110nnnniiiiiiii */
nkeynes@1
  1375
            /* MOV     imm8, Rn */
nkeynes@1
  1376
            RN(ir) = IMM8(ir);
nkeynes@1
  1377
            break;
nkeynes@1
  1378
        case 15:/* 1111xxxxxxxxxxxx */
nkeynes@1
  1379
            CHECKFPUEN();
nkeynes@84
  1380
	    if( IS_FPU_DOUBLEPREC() ) {
nkeynes@84
  1381
		switch( ir&0x000F ) {
nkeynes@84
  1382
                case 0: /* FADD    FRm, FRn */
nkeynes@84
  1383
                    DRN(ir) += DRM(ir);
nkeynes@84
  1384
                    break;
nkeynes@84
  1385
                case 1: /* FSUB    FRm, FRn */
nkeynes@84
  1386
                    DRN(ir) -= DRM(ir);
nkeynes@84
  1387
                    break;
nkeynes@84
  1388
                case 2: /* FMUL    FRm, FRn */
nkeynes@84
  1389
                    DRN(ir) = DRN(ir) * DRM(ir);
nkeynes@84
  1390
                    break;
nkeynes@84
  1391
                case 3: /* FDIV    FRm, FRn */
nkeynes@84
  1392
                    DRN(ir) = DRN(ir) / DRM(ir);
nkeynes@84
  1393
                    break;
nkeynes@84
  1394
                case 4: /* FCMP/EQ FRm, FRn */
nkeynes@84
  1395
                    sh4r.t = ( DRN(ir) == DRM(ir) ? 1 : 0 );
nkeynes@84
  1396
                    break;
nkeynes@84
  1397
                case 5: /* FCMP/GT FRm, FRn */
nkeynes@84
  1398
                    sh4r.t = ( DRN(ir) > DRM(ir) ? 1 : 0 );
nkeynes@84
  1399
                    break;
nkeynes@84
  1400
                case 6: /* FMOV.S  [Rm+R0], FRn */
nkeynes@84
  1401
                    MEM_FP_READ( RM(ir) + R0, FRNn(ir) );
nkeynes@84
  1402
                    break;
nkeynes@84
  1403
                case 7: /* FMOV.S  FRm, [Rn+R0] */
nkeynes@84
  1404
                    MEM_FP_WRITE( RN(ir) + R0, FRMn(ir) );
nkeynes@84
  1405
                    break;
nkeynes@84
  1406
                case 8: /* FMOV.S  [Rm], FRn */
nkeynes@84
  1407
                    MEM_FP_READ( RM(ir), FRNn(ir) );
nkeynes@84
  1408
                    break;
nkeynes@84
  1409
                case 9: /* FMOV.S  [Rm++], FRn */
nkeynes@84
  1410
                    MEM_FP_READ( RM(ir), FRNn(ir) );
nkeynes@84
  1411
                    RM(ir) += FP_WIDTH;
nkeynes@84
  1412
                    break;
nkeynes@84
  1413
                case 10:/* FMOV.S  FRm, [Rn] */
nkeynes@84
  1414
                    MEM_FP_WRITE( RN(ir), FRMn(ir) );
nkeynes@84
  1415
                    break;
nkeynes@84
  1416
                case 11:/* FMOV.S  FRm, [--Rn] */
nkeynes@84
  1417
                    RN(ir) -= FP_WIDTH;
nkeynes@84
  1418
                    MEM_FP_WRITE( RN(ir), FRMn(ir) );
nkeynes@84
  1419
                    break;
nkeynes@84
  1420
                case 12:/* FMOV    FRm, FRn */
nkeynes@84
  1421
		    if( IS_FPU_DOUBLESIZE() )
nkeynes@84
  1422
			DRN(ir) = DRM(ir);
nkeynes@84
  1423
		    else
nkeynes@84
  1424
			FRN(ir) = FRM(ir);
nkeynes@84
  1425
                    break;
nkeynes@84
  1426
                case 13:
nkeynes@84
  1427
                    switch( (ir&0x00F0) >> 4 ) {
nkeynes@84
  1428
		    case 0: /* FSTS    FPUL, FRn */
nkeynes@84
  1429
			FRN(ir) = FPULf;
nkeynes@84
  1430
			break;
nkeynes@84
  1431
		    case 1: /* FLDS    FRn,FPUL */
nkeynes@84
  1432
			FPULf = FRN(ir);
nkeynes@84
  1433
			break;
nkeynes@84
  1434
		    case 2: /* FLOAT   FPUL, FRn */
nkeynes@84
  1435
			DRN(ir) = (float)FPULi;
nkeynes@84
  1436
			break;
nkeynes@84
  1437
		    case 3: /* FTRC    FRn, FPUL */
nkeynes@123
  1438
			dtmp = DRN(ir);
nkeynes@123
  1439
			if( dtmp >= MAX_INTF )
nkeynes@123
  1440
			    FPULi = MAX_INT;
nkeynes@123
  1441
			else if( dtmp <= MIN_INTF )
nkeynes@123
  1442
			    FPULi = MIN_INT;
nkeynes@123
  1443
			else 
nkeynes@123
  1444
			    FPULi = (int32_t)dtmp;
nkeynes@84
  1445
			break;
nkeynes@84
  1446
		    case 4: /* FNEG    FRn */
nkeynes@84
  1447
			DRN(ir) = -DRN(ir);
nkeynes@84
  1448
			break;
nkeynes@84
  1449
		    case 5: /* FABS    FRn */
nkeynes@84
  1450
			DRN(ir) = fabs(DRN(ir));
nkeynes@84
  1451
			break;
nkeynes@84
  1452
		    case 6: /* FSQRT   FRn */
nkeynes@84
  1453
			DRN(ir) = sqrt(DRN(ir));
nkeynes@84
  1454
			break;
nkeynes@84
  1455
		    case 7: /* FSRRA FRn */
nkeynes@181
  1456
			/* NO-OP when PR=1 */
nkeynes@84
  1457
			break;
nkeynes@84
  1458
		    case 8: /* FLDI0   FRn */
nkeynes@84
  1459
			DRN(ir) = 0.0;
nkeynes@84
  1460
			break;
nkeynes@84
  1461
		    case 9: /* FLDI1   FRn */
nkeynes@84
  1462
			DRN(ir) = 1.0;
nkeynes@84
  1463
			break;
nkeynes@84
  1464
		    case 10: /* FCNVSD FPUL, DRn */
nkeynes@181
  1465
			if( ! IS_FPU_DOUBLESIZE() )
nkeynes@181
  1466
			    DRN(ir) = (double)FPULf;
nkeynes@84
  1467
			break;
nkeynes@84
  1468
		    case 11: /* FCNVDS DRn, FPUL */
nkeynes@181
  1469
			if( ! IS_FPU_DOUBLESIZE() )
nkeynes@181
  1470
			    FPULf = (float)DRN(ir);
nkeynes@84
  1471
			break;
nkeynes@84
  1472
		    case 14:/* FIPR    FVm, FVn */
nkeynes@181
  1473
			/* NO-OP when PR=1 */
nkeynes@84
  1474
			break;
nkeynes@84
  1475
		    case 15:
nkeynes@84
  1476
			if( (ir&0x0300) == 0x0100 ) { /* FTRV    XMTRX,FVn */
nkeynes@181
  1477
			    /* NO-OP when PR=1 */
nkeynes@84
  1478
			    break;
nkeynes@84
  1479
			}
nkeynes@181
  1480
			else if( (ir&0x0100) == 0 ) { /* FSCA    FPUL, DRn */	
nkeynes@181
  1481
			    /* NO-OP when PR=1 */
nkeynes@84
  1482
			    break;
nkeynes@84
  1483
			}
nkeynes@84
  1484
			else if( ir == 0xFBFD ) {
nkeynes@84
  1485
			    /* FRCHG   */
nkeynes@84
  1486
			    sh4r.fpscr ^= FPSCR_FR;
nkeynes@84
  1487
			    break;
nkeynes@84
  1488
			}
nkeynes@84
  1489
			else if( ir == 0xF3FD ) {
nkeynes@84
  1490
			    /* FSCHG   */
nkeynes@84
  1491
			    sh4r.fpscr ^= FPSCR_SZ;
nkeynes@84
  1492
			    break;
nkeynes@84
  1493
			}
nkeynes@84
  1494
		    default: UNDEF(ir);
nkeynes@84
  1495
                    }
nkeynes@84
  1496
                    break;
nkeynes@84
  1497
                case 14:/* FMAC    FR0, FRm, FRn */
nkeynes@84
  1498
                    DRN(ir) += DRM(ir)*DR0;
nkeynes@84
  1499
                    break;
nkeynes@84
  1500
                default: UNDEF(ir);
nkeynes@84
  1501
		}
nkeynes@122
  1502
	    } else { /* Single precision */
nkeynes@84
  1503
		switch( ir&0x000F ) {
nkeynes@1
  1504
                case 0: /* FADD    FRm, FRn */
nkeynes@1
  1505
                    FRN(ir) += FRM(ir);
nkeynes@1
  1506
                    break;
nkeynes@1
  1507
                case 1: /* FSUB    FRm, FRn */
nkeynes@1
  1508
                    FRN(ir) -= FRM(ir);
nkeynes@1
  1509
                    break;
nkeynes@1
  1510
                case 2: /* FMUL    FRm, FRn */
nkeynes@1
  1511
                    FRN(ir) = FRN(ir) * FRM(ir);
nkeynes@1
  1512
                    break;
nkeynes@1
  1513
                case 3: /* FDIV    FRm, FRn */
nkeynes@1
  1514
                    FRN(ir) = FRN(ir) / FRM(ir);
nkeynes@1
  1515
                    break;
nkeynes@1
  1516
                case 4: /* FCMP/EQ FRm, FRn */
nkeynes@1
  1517
                    sh4r.t = ( FRN(ir) == FRM(ir) ? 1 : 0 );
nkeynes@1
  1518
                    break;
nkeynes@1
  1519
                case 5: /* FCMP/GT FRm, FRn */
nkeynes@1
  1520
                    sh4r.t = ( FRN(ir) > FRM(ir) ? 1 : 0 );
nkeynes@1
  1521
                    break;
nkeynes@1
  1522
                case 6: /* FMOV.S  [Rm+R0], FRn */
nkeynes@1
  1523
                    MEM_FP_READ( RM(ir) + R0, FRNn(ir) );
nkeynes@1
  1524
                    break;
nkeynes@1
  1525
                case 7: /* FMOV.S  FRm, [Rn+R0] */
nkeynes@1
  1526
                    MEM_FP_WRITE( RN(ir) + R0, FRMn(ir) );
nkeynes@1
  1527
                    break;
nkeynes@1
  1528
                case 8: /* FMOV.S  [Rm], FRn */
nkeynes@1
  1529
                    MEM_FP_READ( RM(ir), FRNn(ir) );
nkeynes@1
  1530
                    break;
nkeynes@1
  1531
                case 9: /* FMOV.S  [Rm++], FRn */
nkeynes@1
  1532
                    MEM_FP_READ( RM(ir), FRNn(ir) );
nkeynes@1
  1533
                    RM(ir) += FP_WIDTH;
nkeynes@1
  1534
                    break;
nkeynes@1
  1535
                case 10:/* FMOV.S  FRm, [Rn] */
nkeynes@1
  1536
                    MEM_FP_WRITE( RN(ir), FRMn(ir) );
nkeynes@1
  1537
                    break;
nkeynes@1
  1538
                case 11:/* FMOV.S  FRm, [--Rn] */
nkeynes@1
  1539
                    RN(ir) -= FP_WIDTH;
nkeynes@1
  1540
                    MEM_FP_WRITE( RN(ir), FRMn(ir) );
nkeynes@1
  1541
                    break;
nkeynes@1
  1542
                case 12:/* FMOV    FRm, FRn */
nkeynes@84
  1543
		    if( IS_FPU_DOUBLESIZE() )
nkeynes@84
  1544
			DRN(ir) = DRM(ir);
nkeynes@84
  1545
		    else
nkeynes@84
  1546
			FRN(ir) = FRM(ir);
nkeynes@1
  1547
                    break;
nkeynes@1
  1548
                case 13:
nkeynes@1
  1549
                    switch( (ir&0x00F0) >> 4 ) {
nkeynes@84
  1550
		    case 0: /* FSTS    FPUL, FRn */
nkeynes@84
  1551
			FRN(ir) = FPULf;
nkeynes@84
  1552
			break;
nkeynes@84
  1553
		    case 1: /* FLDS    FRn,FPUL */
nkeynes@84
  1554
			FPULf = FRN(ir);
nkeynes@84
  1555
			break;
nkeynes@84
  1556
		    case 2: /* FLOAT   FPUL, FRn */
nkeynes@84
  1557
			FRN(ir) = (float)FPULi;
nkeynes@84
  1558
			break;
nkeynes@84
  1559
		    case 3: /* FTRC    FRn, FPUL */
nkeynes@123
  1560
			ftmp = FRN(ir);
nkeynes@123
  1561
			if( ftmp >= MAX_INTF )
nkeynes@123
  1562
			    FPULi = MAX_INT;
nkeynes@123
  1563
			else if( ftmp <= MIN_INTF )
nkeynes@123
  1564
			    FPULi = MIN_INT;
nkeynes@123
  1565
			else
nkeynes@123
  1566
			    FPULi = (int32_t)ftmp;
nkeynes@84
  1567
			break;
nkeynes@84
  1568
		    case 4: /* FNEG    FRn */
nkeynes@84
  1569
			FRN(ir) = -FRN(ir);
nkeynes@84
  1570
			break;
nkeynes@84
  1571
		    case 5: /* FABS    FRn */
nkeynes@84
  1572
			FRN(ir) = fabsf(FRN(ir));
nkeynes@84
  1573
			break;
nkeynes@84
  1574
		    case 6: /* FSQRT   FRn */
nkeynes@84
  1575
			FRN(ir) = sqrtf(FRN(ir));
nkeynes@84
  1576
			break;
nkeynes@84
  1577
		    case 7: /* FSRRA FRn */
nkeynes@84
  1578
			FRN(ir) = 1.0/sqrtf(FRN(ir));
nkeynes@84
  1579
			break;
nkeynes@84
  1580
		    case 8: /* FLDI0   FRn */
nkeynes@84
  1581
			FRN(ir) = 0.0;
nkeynes@84
  1582
			break;
nkeynes@84
  1583
		    case 9: /* FLDI1   FRn */
nkeynes@84
  1584
			FRN(ir) = 1.0;
nkeynes@84
  1585
			break;
nkeynes@84
  1586
		    case 10: /* FCNVSD FPUL, DRn */
nkeynes@84
  1587
			break;
nkeynes@84
  1588
		    case 11: /* FCNVDS DRn, FPUL */
nkeynes@84
  1589
			break;
nkeynes@84
  1590
		    case 14:/* FIPR    FVm, FVn */
nkeynes@2
  1591
                            /* FIXME: This is not going to be entirely accurate
nkeynes@2
  1592
                             * as the SH4 instruction is less precise. Also
nkeynes@2
  1593
                             * need to check for 0s and infinities.
nkeynes@2
  1594
                             */
nkeynes@2
  1595
                        {
nkeynes@2
  1596
                            int tmp2 = FVN(ir);
nkeynes@2
  1597
                            tmp = FVM(ir);
nkeynes@84
  1598
                            FR(tmp2+3) = FR(tmp)*FR(tmp2) +
nkeynes@84
  1599
                                FR(tmp+1)*FR(tmp2+1) +
nkeynes@84
  1600
                                FR(tmp+2)*FR(tmp2+2) +
nkeynes@84
  1601
                                FR(tmp+3)*FR(tmp2+3);
nkeynes@1
  1602
                            break;
nkeynes@2
  1603
                        }
nkeynes@84
  1604
		    case 15:
nkeynes@84
  1605
			if( (ir&0x0300) == 0x0100 ) { /* FTRV    XMTRX,FVn */
nkeynes@84
  1606
			    tmp = FVN(ir);
nkeynes@84
  1607
			    float fv[4] = { FR(tmp), FR(tmp+1), FR(tmp+2), FR(tmp+3) };
nkeynes@84
  1608
			    FR(tmp) = XF(0) * fv[0] + XF(4)*fv[1] +
nkeynes@84
  1609
				XF(8)*fv[2] + XF(12)*fv[3];
nkeynes@84
  1610
			    FR(tmp+1) = XF(1) * fv[0] + XF(5)*fv[1] +
nkeynes@84
  1611
				XF(9)*fv[2] + XF(13)*fv[3];
nkeynes@84
  1612
			    FR(tmp+2) = XF(2) * fv[0] + XF(6)*fv[1] +
nkeynes@84
  1613
				XF(10)*fv[2] + XF(14)*fv[3];
nkeynes@84
  1614
			    FR(tmp+3) = XF(3) * fv[0] + XF(7)*fv[1] +
nkeynes@84
  1615
				XF(11)*fv[2] + XF(15)*fv[3];
nkeynes@84
  1616
			    break;
nkeynes@84
  1617
			}
nkeynes@84
  1618
			else if( (ir&0x0100) == 0 ) { /* FSCA    FPUL, DRn */
nkeynes@84
  1619
			    float angle = (((float)(short)(FPULi>>16)) +
nkeynes@122
  1620
					   (((float)(FPULi&0xFFFF))/65536.0)) *
nkeynes@84
  1621
				2 * M_PI;
nkeynes@84
  1622
			    int reg = FRNn(ir);
nkeynes@84
  1623
			    FR(reg) = sinf(angle);
nkeynes@84
  1624
			    FR(reg+1) = cosf(angle);
nkeynes@84
  1625
			    break;
nkeynes@84
  1626
			}
nkeynes@84
  1627
			else if( ir == 0xFBFD ) {
nkeynes@84
  1628
			    /* FRCHG   */
nkeynes@84
  1629
			    sh4r.fpscr ^= FPSCR_FR;
nkeynes@84
  1630
			    break;
nkeynes@84
  1631
			}
nkeynes@84
  1632
			else if( ir == 0xF3FD ) {
nkeynes@84
  1633
			    /* FSCHG   */
nkeynes@84
  1634
			    sh4r.fpscr ^= FPSCR_SZ;
nkeynes@84
  1635
			    break;
nkeynes@84
  1636
			}
nkeynes@84
  1637
		    default: UNDEF(ir);
nkeynes@1
  1638
                    }
nkeynes@1
  1639
                    break;
nkeynes@1
  1640
                case 14:/* FMAC    FR0, FRm, FRn */
nkeynes@1
  1641
                    FRN(ir) += FRM(ir)*FR0;
nkeynes@1
  1642
                    break;
nkeynes@1
  1643
                default: UNDEF(ir);
nkeynes@84
  1644
		}
nkeynes@84
  1645
	    }
nkeynes@84
  1646
	    break;
nkeynes@1
  1647
    }
nkeynes@1
  1648
    sh4r.pc = sh4r.new_pc;
nkeynes@1
  1649
    sh4r.new_pc += 2;
nkeynes@2
  1650
    sh4r.in_delay_slot = 0;
nkeynes@1
  1651
}
.