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