Search
lxdream.org :: lxdream/src/sh4/sh4core.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4core.c
changeset 15:5194dd0fdb60
prev10:c898b37506e0
next16:f383e7640da4
author nkeynes
date Mon Dec 12 13:11:11 2005 +0000 (17 years ago)
permissions -rw-r--r--
last change Add dreamcast_module module structure
file annotate diff log raw
nkeynes@1
     1
#include <math.h>
nkeynes@1
     2
#include "dream.h"
nkeynes@15
     3
#include "modules.h"
nkeynes@1
     4
#include "sh4core.h"
nkeynes@1
     5
#include "sh4mmio.h"
nkeynes@1
     6
#include "mem.h"
nkeynes@1
     7
#include "intc.h"
nkeynes@1
     8
nkeynes@15
     9
struct dreamcast_module sh4_module = { "SH4", sh4_init, sh4_reset, 
nkeynes@15
    10
				       NULL, sh4_stop,
nkeynes@15
    11
				       NULL, NULL };
nkeynes@15
    12
nkeynes@1
    13
struct sh4_registers sh4r;
nkeynes@1
    14
static int running = 0;
nkeynes@1
    15
nkeynes@1
    16
void sh4_init(void)
nkeynes@1
    17
{
nkeynes@15
    18
    mem_create_ram_region( 0x0C000000, 16 MB, MEM_REGION_MAIN );
nkeynes@1
    19
    register_io_regions( mmio_list_sh4mmio );
nkeynes@10
    20
    mmu_init();
nkeynes@1
    21
}
nkeynes@1
    22
nkeynes@1
    23
void sh4_reset(void)
nkeynes@1
    24
{
nkeynes@1
    25
    sh4r.pc    = 0xA0000000;
nkeynes@1
    26
    sh4r.new_pc= 0xA0000002;
nkeynes@1
    27
    sh4r.vbr   = 0x00000000;
nkeynes@1
    28
    sh4r.fpscr = 0x00040001;
nkeynes@1
    29
    sh4r.sr    = 0x700000F0;
nkeynes@1
    30
    sh4r.icount= 0;
nkeynes@1
    31
    /* Everything else is undefined anyway, so don't bother setting it */
nkeynes@1
    32
    intc_reset();
nkeynes@1
    33
}
nkeynes@1
    34
nkeynes@1
    35
void sh4_set_pc( int pc )
nkeynes@1
    36
{
nkeynes@1
    37
    sh4r.pc = pc;
nkeynes@1
    38
    sh4r.new_pc = pc+2;
nkeynes@1
    39
}
nkeynes@1
    40
nkeynes@1
    41
void sh4_stop(void)
nkeynes@1
    42
{
nkeynes@1
    43
    running = 0;
nkeynes@1
    44
}
nkeynes@1
    45
nkeynes@1
    46
void sh4_run(void)
nkeynes@1
    47
{
nkeynes@1
    48
    running = 1;
nkeynes@1
    49
    while( running ) {
nkeynes@1
    50
        sh4_execute_instruction();
nkeynes@1
    51
    }
nkeynes@1
    52
}
nkeynes@1
    53
nkeynes@1
    54
void sh4_runfor(uint32_t count)
nkeynes@1
    55
{
nkeynes@1
    56
    running = 1;
nkeynes@1
    57
    while( running && count--) {
nkeynes@2
    58
        int pc = sh4r.pc;
nkeynes@1
    59
        sh4_execute_instruction();
nkeynes@2
    60
        /*
nkeynes@2
    61
        if( sh4r.pc == 0x8C0C1636 ||
nkeynes@2
    62
            sh4r.pc == 0x8C0C1634 ) {
nkeynes@2
    63
            WARN( "Branching to %08X from %08X", sh4r.pc, pc );
nkeynes@2
    64
            sh4_stop();
nkeynes@2
    65
            }*/
nkeynes@1
    66
    }
nkeynes@1
    67
}
nkeynes@1
    68
nkeynes@1
    69
int sh4_isrunning(void)
nkeynes@1
    70
{
nkeynes@1
    71
    return running;
nkeynes@1
    72
}
nkeynes@1
    73
nkeynes@1
    74
void sh4_runto( uint32_t target_pc, uint32_t count )
nkeynes@1
    75
{
nkeynes@1
    76
    running = 1;
nkeynes@2
    77
    while( running && count--) {
nkeynes@1
    78
        sh4_execute_instruction();
nkeynes@2
    79
        if( sh4r.pc == target_pc ) {
nkeynes@2
    80
            running = 0;
nkeynes@2
    81
            break;
nkeynes@2
    82
        }
nkeynes@2
    83
    }
nkeynes@1
    84
}
nkeynes@1
    85
nkeynes@1
    86
#define UNDEF(ir) do{ ERROR( "Raising exception on undefined instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_stop(); RAISE( EXC_ILLEGAL, EXV_ILLEGAL ); }while(0)
nkeynes@1
    87
#define UNIMP(ir) do{ ERROR( "Halted on unimplemented instruction at %08x, opcode = %04x", sh4r.pc, ir ); sh4_stop(); return; }while(0)
nkeynes@1
    88
nkeynes@1
    89
#define RAISE( x, v ) do{ \
nkeynes@1
    90
    if( sh4r.vbr == 0 ) { \
nkeynes@1
    91
        ERROR( "%08X: VBR not initialized while raising exception %03X, halting", sh4r.pc, x ); \
nkeynes@1
    92
        sh4_stop(); \
nkeynes@1
    93
    } else { \
nkeynes@1
    94
        sh4r.spc = sh4r.pc + 2; \
nkeynes@1
    95
        sh4r.ssr = sh4_read_sr(); \
nkeynes@1
    96
        sh4r.sgr = sh4r.r[15]; \
nkeynes@1
    97
        MMIO_WRITE(MMU,EXPEVT,x); \
nkeynes@1
    98
        sh4r.pc = sh4r.vbr + v; \
nkeynes@1
    99
        sh4r.new_pc = sh4r.pc + 2; \
nkeynes@1
   100
        sh4_load_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB ); \
nkeynes@1
   101
    } \
nkeynes@1
   102
    return; } while(0)
nkeynes@1
   103
nkeynes@10
   104
#define MEM_READ_BYTE( addr ) sh4_read_byte(addr)
nkeynes@10
   105
#define MEM_READ_WORD( addr ) sh4_read_word(addr)
nkeynes@10
   106
#define MEM_READ_LONG( addr ) sh4_read_long(addr)
nkeynes@10
   107
#define MEM_WRITE_BYTE( addr, val ) sh4_write_byte(addr, val)
nkeynes@10
   108
#define MEM_WRITE_WORD( addr, val ) sh4_write_word(addr, val)
nkeynes@10
   109
#define MEM_WRITE_LONG( addr, val ) sh4_write_long(addr, val)
nkeynes@1
   110
nkeynes@1
   111
#define MEM_FP_READ( addr, reg ) if( IS_FPU_DOUBLESIZE() ) { \
nkeynes@10
   112
    ((uint32_t *)FR)[(reg)&0xE0] = sh4_read_long(addr); \
nkeynes@10
   113
    ((uint32_t *)FR)[(reg)|1] = sh4_read_long(addr+4); \
nkeynes@10
   114
} else ((uint32_t *)FR)[reg] = sh4_read_long(addr)
nkeynes@1
   115
nkeynes@1
   116
#define MEM_FP_WRITE( addr, reg ) if( IS_FPU_DOUBLESIZE() ) { \
nkeynes@10
   117
    sh4_write_long( addr, ((uint32_t *)FR)[(reg)&0xE0] ); \
nkeynes@10
   118
    sh4_write_long( addr+4, ((uint32_t *)FR)[(reg)|1] ); \
nkeynes@10
   119
} else sh4_write_long( addr, ((uint32_t *)FR)[reg] )
nkeynes@1
   120
nkeynes@1
   121
#define FP_WIDTH (IS_FPU_DOUBLESIZE() ? 8 : 4)
nkeynes@1
   122
nkeynes@1
   123
#define EXC_POWER_RESET  0x000 /* vector special */
nkeynes@1
   124
#define EXC_MANUAL_RESET 0x020
nkeynes@2
   125
#define EXC_SLOT_ILLEGAL 0x1A0
nkeynes@1
   126
#define EXC_ILLEGAL      0x180
nkeynes@1
   127
#define EXV_ILLEGAL      0x100
nkeynes@1
   128
#define EXC_TRAP         0x160
nkeynes@1
   129
#define EXV_TRAP         0x100
nkeynes@1
   130
#define EXC_FPDISABLE    0x800
nkeynes@1
   131
#define EXV_FPDISABLE    0x100
nkeynes@1
   132
nkeynes@1
   133
#define CHECK( x, c, v ) if( !x ) RAISE( c, v )
nkeynes@1
   134
#define CHECKPRIV() CHECK( IS_SH4_PRIVMODE(), EXC_ILLEGAL, EXV_ILLEGAL )
nkeynes@1
   135
#define CHECKFPUEN() CHECK( IS_FPU_ENABLED(), EXC_FPDISABLE, EXV_FPDISABLE )
nkeynes@1
   136
#define CHECKDEST(p) if( (p) == 0 ) { ERROR( "%08X: Branch/jump to NULL, CPU halted", sh4r.pc ); sh4_stop(); return; }
nkeynes@2
   137
#define CHECKSLOTILLEGAL() if(sh4r.in_delay_slot) { RAISE(EXC_SLOT_ILLEGAL,EXV_ILLEGAL); }
nkeynes@1
   138
nkeynes@1
   139
static void sh4_switch_banks( )
nkeynes@1
   140
{
nkeynes@1
   141
    uint32_t tmp[8];
nkeynes@1
   142
nkeynes@1
   143
    memcpy( tmp, sh4r.r, sizeof(uint32_t)*8 );
nkeynes@1
   144
    memcpy( sh4r.r, sh4r.r_bank, sizeof(uint32_t)*8 );
nkeynes@1
   145
    memcpy( sh4r.r_bank, tmp, sizeof(uint32_t)*8 );
nkeynes@1
   146
}
nkeynes@1
   147
nkeynes@1
   148
static void sh4_load_sr( uint32_t newval )
nkeynes@1
   149
{
nkeynes@1
   150
    if( (newval ^ sh4r.sr) & SR_RB )
nkeynes@1
   151
        sh4_switch_banks();
nkeynes@1
   152
    sh4r.sr = newval;
nkeynes@1
   153
    sh4r.t = (newval&SR_T) ? 1 : 0;
nkeynes@1
   154
    sh4r.s = (newval&SR_S) ? 1 : 0;
nkeynes@1
   155
    sh4r.m = (newval&SR_M) ? 1 : 0;
nkeynes@1
   156
    sh4r.q = (newval&SR_Q) ? 1 : 0;
nkeynes@1
   157
    intc_mask_changed();
nkeynes@1
   158
}
nkeynes@1
   159
nkeynes@1
   160
static uint32_t sh4_read_sr( void )
nkeynes@1
   161
{
nkeynes@1
   162
    /* synchronize sh4r.sr with the various bitflags */
nkeynes@1
   163
    sh4r.sr &= SR_MQSTMASK;
nkeynes@1
   164
    if( sh4r.t ) sh4r.sr |= SR_T;
nkeynes@1
   165
    if( sh4r.s ) sh4r.sr |= SR_S;
nkeynes@1
   166
    if( sh4r.m ) sh4r.sr |= SR_M;
nkeynes@1
   167
    if( sh4r.q ) sh4r.sr |= SR_Q;
nkeynes@1
   168
    return sh4r.sr;
nkeynes@1
   169
}
nkeynes@1
   170
/* function for external use */
nkeynes@1
   171
void sh4_raise_exception( int code, int vector )
nkeynes@1
   172
{
nkeynes@1
   173
    RAISE(code, vector);
nkeynes@1
   174
}
nkeynes@1
   175
nkeynes@1
   176
static void sh4_accept_interrupt( void )
nkeynes@1
   177
{
nkeynes@1
   178
    uint32_t code = intc_accept_interrupt();
nkeynes@1
   179
    sh4r.ssr = sh4_read_sr();
nkeynes@1
   180
    sh4r.spc = sh4r.pc;
nkeynes@1
   181
    sh4r.sgr = sh4r.r[15];
nkeynes@1
   182
    sh4_load_sr( sh4r.ssr|SR_BL|SR_MD|SR_RB );
nkeynes@1
   183
    MMIO_WRITE( MMU, INTEVT, code );
nkeynes@1
   184
    sh4r.pc = sh4r.vbr + 0x600;
nkeynes@1
   185
    sh4r.new_pc = sh4r.pc + 2;
nkeynes@2
   186
    WARN( "Accepting interrupt %03X, from %08X => %08X", code, sh4r.spc, sh4r.pc );
nkeynes@1
   187
}
nkeynes@1
   188
nkeynes@1
   189
void sh4_execute_instruction( void )
nkeynes@1
   190
{
nkeynes@2
   191
    int pc;
nkeynes@2
   192
    unsigned short ir;
nkeynes@1
   193
    uint32_t tmp;
nkeynes@1
   194
    uint64_t tmpl;
nkeynes@1
   195
    
nkeynes@1
   196
#define R0 sh4r.r[0]
nkeynes@1
   197
#define FR0 (FR[0])
nkeynes@1
   198
#define RN(ir) sh4r.r[(ir&0x0F00)>>8]
nkeynes@1
   199
#define RN_BANK(ir) sh4r.r_bank[(ir&0x0070)>>4]
nkeynes@1
   200
#define RM(ir) sh4r.r[(ir&0x00F0)>>4]
nkeynes@1
   201
#define DISP4(ir) (ir&0x000F) /* 4-bit displacements are *NOT* sign-extended */
nkeynes@1
   202
#define DISP8(ir) (ir&0x00FF)
nkeynes@1
   203
#define PCDISP8(ir) SIGNEXT8(ir&0x00FF)
nkeynes@1
   204
#define IMM8(ir) SIGNEXT8(ir&0x00FF)
nkeynes@1
   205
#define UIMM8(ir) (ir&0x00FF) /* Unsigned immmediate */
nkeynes@1
   206
#define DISP12(ir) SIGNEXT12(ir&0x0FFF)
nkeynes@2
   207
#define FVN(ir) ((ir&0x0C00)>>8)
nkeynes@2
   208
#define FVM(ir) ((ir&0x0300)>>6)
nkeynes@1
   209
#define FRN(ir) (FR[(ir&0x0F00)>>8])
nkeynes@1
   210
#define FRM(ir) (FR[(ir&0x00F0)>>4])
nkeynes@1
   211
#define FRNi(ir) (((uint32_t *)FR)[(ir&0x0F00)>>8])
nkeynes@1
   212
#define FRMi(ir) (((uint32_t *)FR)[(ir&0x00F0)>>4])
nkeynes@1
   213
#define DRN(ir) (((double *)FR)[(ir&0x0E00)>>9])
nkeynes@1
   214
#define DRM(ir) (((double *)FR)[(ir&0x00E0)>>5])
nkeynes@1
   215
#define DRNi(ir) (((uint64_t *)FR)[(ir&0x0E00)>>9])
nkeynes@1
   216
#define DRMi(ir) (((uint64_t *)FR)[(ir&0x00E0)>>5])
nkeynes@1
   217
#define FRNn(ir) ((ir&0x0F00)>>8)
nkeynes@1
   218
#define FRMn(ir) ((ir&0x00F0)>>4)
nkeynes@1
   219
#define FPULf   *((float *)&sh4r.fpul)
nkeynes@1
   220
#define FPULi    (sh4r.fpul)
nkeynes@1
   221
nkeynes@2
   222
    if( SH4_INT_PENDING() ) 
nkeynes@2
   223
        sh4_accept_interrupt();
nkeynes@1
   224
                 
nkeynes@2
   225
    pc = sh4r.pc;
nkeynes@2
   226
    ir = MEM_READ_WORD(pc);
nkeynes@1
   227
    sh4r.icount++;
nkeynes@1
   228
    
nkeynes@1
   229
    switch( (ir&0xF000)>>12 ) {
nkeynes@1
   230
        case 0: /* 0000nnnnmmmmxxxx */
nkeynes@1
   231
            switch( ir&0x000F ) {
nkeynes@1
   232
                case 2:
nkeynes@1
   233
                    switch( (ir&0x00F0)>>4 ) {
nkeynes@1
   234
                        case 0: /* STC     SR, Rn */
nkeynes@1
   235
                            CHECKPRIV();
nkeynes@1
   236
                            RN(ir) = sh4_read_sr();
nkeynes@1
   237
                            break;
nkeynes@1
   238
                        case 1: /* STC     GBR, Rn */
nkeynes@1
   239
                            RN(ir) = sh4r.gbr;
nkeynes@1
   240
                            break;
nkeynes@1
   241
                        case 2: /* STC     VBR, Rn */
nkeynes@1
   242
                            CHECKPRIV();
nkeynes@1
   243
                            RN(ir) = sh4r.vbr;
nkeynes@1
   244
                            break;
nkeynes@1
   245
                        case 3: /* STC     SSR, Rn */
nkeynes@1
   246
                            CHECKPRIV();
nkeynes@1
   247
                            RN(ir) = sh4r.ssr;
nkeynes@1
   248
                            break;
nkeynes@1
   249
                        case 4: /* STC     SPC, Rn */
nkeynes@1
   250
                            CHECKPRIV();
nkeynes@1
   251
                            RN(ir) = sh4r.spc;
nkeynes@1
   252
                            break;
nkeynes@1
   253
                        case 8: case 9: case 10: case 11: case 12: case 13:
nkeynes@1
   254
                        case 14: case 15:/* STC     Rm_bank, Rn */
nkeynes@1
   255
                            CHECKPRIV();
nkeynes@1
   256
                            RN(ir) = RN_BANK(ir);
nkeynes@1
   257
                            break;
nkeynes@1
   258
                        default: UNDEF(ir);
nkeynes@1
   259
                    }
nkeynes@1
   260
                    break;
nkeynes@1
   261
                case 3:
nkeynes@1
   262
                    switch( (ir&0x00F0)>>4 ) {
nkeynes@1
   263
                        case 0: /* BSRF    Rn */
nkeynes@1
   264
                            CHECKDEST( pc + 4 + RN(ir) );
nkeynes@2
   265
                            CHECKSLOTILLEGAL();
nkeynes@2
   266
                            sh4r.in_delay_slot = 1;
nkeynes@1
   267
                            sh4r.pr = sh4r.pc + 4;
nkeynes@1
   268
                            sh4r.pc = sh4r.new_pc;
nkeynes@1
   269
                            sh4r.new_pc = pc + 4 + RN(ir);
nkeynes@1
   270
                            return;
nkeynes@1
   271
                        case 2: /* BRAF    Rn */
nkeynes@1
   272
                            CHECKDEST( pc + 4 + RN(ir) );
nkeynes@2
   273
                            CHECKSLOTILLEGAL();
nkeynes@2
   274
                            sh4r.in_delay_slot = 1;
nkeynes@1
   275
                            sh4r.pc = sh4r.new_pc;
nkeynes@1
   276
                            sh4r.new_pc = pc + 4 + RN(ir);
nkeynes@1
   277
                            return;
nkeynes@1
   278
                        case 8: /* PREF    [Rn] */
nkeynes@2
   279
                            tmp = RN(ir);
nkeynes@2
   280
                            if( (tmp & 0xFC000000) == 0xE0000000 ) {
nkeynes@2
   281
                                /* Store queue operation */
nkeynes@2
   282
                                int queue = (tmp&0x20)>>2;
nkeynes@2
   283
                                int32_t *src = &sh4r.store_queue[queue];
nkeynes@2
   284
                                uint32_t hi = (MMIO_READ( MMU, (queue == 0 ? QACR0 : QACR1) ) & 0x1C) << 24;
nkeynes@2
   285
                                uint32_t target = tmp&0x03FFFFE0 | hi;
nkeynes@2
   286
                                mem_copy_to_sh4( target, src, 32 );
nkeynes@2
   287
                                WARN( "Executed SQ%c => %08X",
nkeynes@2
   288
                                      (queue == 0 ? '0' : '1'), target );
nkeynes@2
   289
                            }
nkeynes@2
   290
                            break;
nkeynes@1
   291
                        case 9: /* OCBI    [Rn] */
nkeynes@1
   292
                        case 10:/* OCBP    [Rn] */
nkeynes@1
   293
                        case 11:/* OCBWB   [Rn] */
nkeynes@1
   294
                            /* anything? */
nkeynes@1
   295
                            break;
nkeynes@1
   296
                        case 12:/* MOVCA.L R0, [Rn] */
nkeynes@1
   297
                            UNIMP(ir);
nkeynes@1
   298
                        default: UNDEF(ir);
nkeynes@1
   299
                    }
nkeynes@1
   300
                    break;
nkeynes@1
   301
                case 4: /* MOV.B   Rm, [R0 + Rn] */
nkeynes@1
   302
                    MEM_WRITE_BYTE( R0 + RN(ir), RM(ir) );
nkeynes@1
   303
                    break;
nkeynes@1
   304
                case 5: /* MOV.W   Rm, [R0 + Rn] */
nkeynes@1
   305
                    MEM_WRITE_WORD( R0 + RN(ir), RM(ir) );
nkeynes@1
   306
                    break;
nkeynes@1
   307
                case 6: /* MOV.L   Rm, [R0 + Rn] */
nkeynes@1
   308
                    MEM_WRITE_LONG( R0 + RN(ir), RM(ir) );
nkeynes@1
   309
                    break;
nkeynes@1
   310
                case 7: /* MUL.L   Rm, Rn */
nkeynes@2
   311
                    sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
nkeynes@1
   312
                        (RM(ir) * RN(ir));
nkeynes@1
   313
                    break;
nkeynes@1
   314
                case 8: 
nkeynes@1
   315
                    switch( (ir&0x0FF0)>>4 ) {
nkeynes@1
   316
                        case 0: /* CLRT    */
nkeynes@1
   317
                            sh4r.t = 0;
nkeynes@1
   318
                            break;
nkeynes@1
   319
                        case 1: /* SETT    */
nkeynes@1
   320
                            sh4r.t = 1;
nkeynes@1
   321
                            break;
nkeynes@1
   322
                        case 2: /* CLRMAC  */
nkeynes@1
   323
                            sh4r.mac = 0;
nkeynes@1
   324
                            break;
nkeynes@1
   325
                        case 3: /* LDTLB   */
nkeynes@1
   326
                            break;
nkeynes@1
   327
                        case 4: /* CLRS    */
nkeynes@1
   328
                            sh4r.s = 0;
nkeynes@1
   329
                            break;
nkeynes@1
   330
                        case 5: /* SETS    */
nkeynes@1
   331
                            sh4r.s = 1;
nkeynes@1
   332
                            break;
nkeynes@1
   333
                        default: UNDEF(ir);
nkeynes@1
   334
                    }
nkeynes@1
   335
                    break;
nkeynes@1
   336
                case 9: 
nkeynes@1
   337
                    if( (ir&0x00F0) == 0x20 ) /* MOVT    Rn */
nkeynes@1
   338
                        RN(ir) = sh4r.t;
nkeynes@1
   339
                    else if( ir == 0x0019 ) /* DIV0U   */
nkeynes@1
   340
                        sh4r.m = sh4r.q = sh4r.t = 0;
nkeynes@1
   341
                    else if( ir == 0x0009 )
nkeynes@1
   342
                        /* NOP     */;
nkeynes@1
   343
                    else UNDEF(ir);
nkeynes@1
   344
                    break;
nkeynes@1
   345
                case 10:
nkeynes@1
   346
                    switch( (ir&0x00F0) >> 4 ) {
nkeynes@1
   347
                        case 0: /* STS     MACH, Rn */
nkeynes@1
   348
                            RN(ir) = sh4r.mac >> 32;
nkeynes@1
   349
                            break;
nkeynes@1
   350
                        case 1: /* STS     MACL, Rn */
nkeynes@1
   351
                            RN(ir) = (uint32_t)sh4r.mac;
nkeynes@1
   352
                            break;
nkeynes@1
   353
                        case 2: /* STS     PR, Rn */
nkeynes@1
   354
                            RN(ir) = sh4r.pr;
nkeynes@1
   355
                            break;
nkeynes@1
   356
                        case 3: /* STC     SGR, Rn */
nkeynes@1
   357
                            CHECKPRIV();
nkeynes@1
   358
                            RN(ir) = sh4r.sgr;
nkeynes@1
   359
                            break;
nkeynes@1
   360
                        case 5:/* STS      FPUL, Rn */
nkeynes@1
   361
                            RN(ir) = sh4r.fpul;
nkeynes@1
   362
                            break;
nkeynes@1
   363
                        case 6: /* STS     FPSCR, Rn */
nkeynes@1
   364
                            RN(ir) = sh4r.fpscr;
nkeynes@1
   365
                            break;
nkeynes@1
   366
                        case 15:/* STC     DBR, Rn */
nkeynes@1
   367
                            CHECKPRIV();
nkeynes@1
   368
                            RN(ir) = sh4r.dbr;
nkeynes@1
   369
                            break;
nkeynes@1
   370
                        default: UNDEF(ir);
nkeynes@1
   371
                    }
nkeynes@1
   372
                    break;
nkeynes@1
   373
                case 11:
nkeynes@1
   374
                    switch( (ir&0x0FF0)>>4 ) {
nkeynes@1
   375
                        case 0: /* RTS     */
nkeynes@1
   376
                            CHECKDEST( sh4r.pr );
nkeynes@2
   377
                            CHECKSLOTILLEGAL();
nkeynes@2
   378
                            sh4r.in_delay_slot = 1;
nkeynes@1
   379
                            sh4r.pc = sh4r.new_pc;
nkeynes@1
   380
                            sh4r.new_pc = sh4r.pr;
nkeynes@1
   381
                            return;
nkeynes@1
   382
                        case 1: /* SLEEP   */
nkeynes@1
   383
                            running = 0;
nkeynes@1
   384
                            break;
nkeynes@1
   385
                        case 2: /* RTE     */
nkeynes@1
   386
                            CHECKPRIV();
nkeynes@1
   387
                            CHECKDEST( sh4r.spc );
nkeynes@2
   388
                            CHECKSLOTILLEGAL();
nkeynes@2
   389
                            sh4r.in_delay_slot = 1;
nkeynes@1
   390
                            sh4r.pc = sh4r.new_pc;
nkeynes@1
   391
                            sh4r.new_pc = sh4r.spc;
nkeynes@1
   392
                            sh4_load_sr( sh4r.ssr );
nkeynes@2
   393
                            WARN( "RTE => %08X", sh4r.new_pc );
nkeynes@1
   394
                            return;
nkeynes@1
   395
                        default:UNDEF(ir);
nkeynes@1
   396
                    }
nkeynes@1
   397
                    break;
nkeynes@1
   398
                case 12:/* MOV.B   [R0+R%d], R%d */
nkeynes@1
   399
                    RN(ir) = MEM_READ_BYTE( R0 + RM(ir) );
nkeynes@1
   400
                    break;
nkeynes@1
   401
                case 13:/* MOV.W   [R0+R%d], R%d */
nkeynes@1
   402
                    RN(ir) = MEM_READ_WORD( R0 + RM(ir) );
nkeynes@1
   403
                    break;
nkeynes@1
   404
                case 14:/* MOV.L   [R0+R%d], R%d */
nkeynes@1
   405
                    RN(ir) = MEM_READ_LONG( R0 + RM(ir) );
nkeynes@1
   406
                    break;
nkeynes@1
   407
                case 15:/* MAC.L   [Rm++], [Rn++] */
nkeynes@1
   408
                    tmpl = ( SIGNEXT32(MEM_READ_LONG(RM(ir))) *
nkeynes@1
   409
                                  SIGNEXT32(MEM_READ_LONG(RN(ir))) );
nkeynes@1
   410
                    if( sh4r.s ) {
nkeynes@1
   411
                        /* 48-bit Saturation. Yuch */
nkeynes@1
   412
                        tmpl += SIGNEXT48(sh4r.mac);
nkeynes@2
   413
                        if( tmpl < 0xFFFF800000000000LL )
nkeynes@2
   414
                            tmpl = 0xFFFF800000000000LL;
nkeynes@2
   415
                        else if( tmpl > 0x00007FFFFFFFFFFFLL )
nkeynes@2
   416
                            tmpl = 0x00007FFFFFFFFFFFLL;
nkeynes@2
   417
                        sh4r.mac = (sh4r.mac&0xFFFF000000000000LL) |
nkeynes@2
   418
                            (tmpl&0x0000FFFFFFFFFFFFLL);
nkeynes@1
   419
                    } else sh4r.mac = tmpl;
nkeynes@1
   420
                    
nkeynes@1
   421
                    RM(ir) += 4;
nkeynes@1
   422
                    RN(ir) += 4;
nkeynes@1
   423
                    
nkeynes@1
   424
                    break;
nkeynes@1
   425
                default: UNDEF(ir);
nkeynes@1
   426
            }
nkeynes@1
   427
            break;
nkeynes@1
   428
        case 1: /* 0001nnnnmmmmdddd */
nkeynes@1
   429
            /* MOV.L   Rm, [Rn + disp4*4] */
nkeynes@1
   430
            MEM_WRITE_LONG( RN(ir) + (DISP4(ir)<<2), RM(ir) );
nkeynes@1
   431
            break;
nkeynes@1
   432
        case 2: /* 0010nnnnmmmmxxxx */
nkeynes@1
   433
            switch( ir&0x000F ) {
nkeynes@1
   434
                case 0: /* MOV.B   Rm, [Rn] */
nkeynes@1
   435
                    MEM_WRITE_BYTE( RN(ir), RM(ir) );
nkeynes@1
   436
                    break;
nkeynes@1
   437
                case 1: /* MOV.W   Rm, [Rn] */
nkeynes@1
   438
                    MEM_WRITE_WORD( RN(ir), RM(ir) );
nkeynes@1
   439
                    break;
nkeynes@1
   440
                case 2: /* MOV.L   Rm, [Rn] */
nkeynes@1
   441
                    MEM_WRITE_LONG( RN(ir), RM(ir) );
nkeynes@1
   442
                    break;
nkeynes@1
   443
                case 3: UNDEF(ir);
nkeynes@1
   444
                    break;
nkeynes@1
   445
                case 4: /* MOV.B   Rm, [--Rn] */
nkeynes@1
   446
                    RN(ir) --;
nkeynes@1
   447
                    MEM_WRITE_BYTE( RN(ir), RM(ir) );
nkeynes@1
   448
                    break;
nkeynes@1
   449
                case 5: /* MOV.W   Rm, [--Rn] */
nkeynes@1
   450
                    RN(ir) -= 2;
nkeynes@1
   451
                    MEM_WRITE_WORD( RN(ir), RM(ir) );
nkeynes@1
   452
                    break;
nkeynes@1
   453
                case 6: /* MOV.L   Rm, [--Rn] */
nkeynes@1
   454
                    RN(ir) -= 4;
nkeynes@1
   455
                    MEM_WRITE_LONG( RN(ir), RM(ir) );
nkeynes@1
   456
                    break;
nkeynes@1
   457
                case 7: /* DIV0S   Rm, Rn */
nkeynes@1
   458
                    sh4r.q = RN(ir)>>31;
nkeynes@1
   459
                    sh4r.m = RM(ir)>>31;
nkeynes@1
   460
                    sh4r.t = sh4r.q ^ sh4r.m;
nkeynes@1
   461
                    break;
nkeynes@1
   462
                case 8: /* TST     Rm, Rn */
nkeynes@1
   463
                    sh4r.t = (RN(ir)&RM(ir) ? 0 : 1);
nkeynes@1
   464
                    break;
nkeynes@1
   465
                case 9: /* AND     Rm, Rn */
nkeynes@1
   466
                    RN(ir) &= RM(ir);
nkeynes@1
   467
                    break;
nkeynes@1
   468
                case 10:/* XOR     Rm, Rn */
nkeynes@1
   469
                    RN(ir) ^= RM(ir);
nkeynes@1
   470
                    break;
nkeynes@1
   471
                case 11:/* OR      Rm, Rn */
nkeynes@1
   472
                    RN(ir) |= RM(ir);
nkeynes@1
   473
                    break;
nkeynes@1
   474
                case 12:/* CMP/STR Rm, Rn */
nkeynes@1
   475
                    /* set T = 1 if any byte in RM & RN is the same */
nkeynes@1
   476
                    tmp = RM(ir) ^ RN(ir);
nkeynes@1
   477
                    sh4r.t = ((tmp&0x000000FF)==0 || (tmp&0x0000FF00)==0 ||
nkeynes@1
   478
                              (tmp&0x00FF0000)==0 || (tmp&0xFF000000)==0)?1:0;
nkeynes@1
   479
                    break;
nkeynes@1
   480
                case 13:/* XTRCT   Rm, Rn */
nkeynes@1
   481
                    RN(ir) = (RN(ir)>>16) | (RM(ir)<<16);
nkeynes@1
   482
                    break;
nkeynes@1
   483
                case 14:/* MULU.W  Rm, Rn */
nkeynes@2
   484
                    sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
nkeynes@1
   485
                        (uint32_t)((RM(ir)&0xFFFF) * (RN(ir)&0xFFFF));
nkeynes@1
   486
                    break;
nkeynes@1
   487
                case 15:/* MULS.W  Rm, Rn */
nkeynes@2
   488
                    sh4r.mac = (sh4r.mac&0xFFFFFFFF00000000LL) |
nkeynes@1
   489
                        (uint32_t)(SIGNEXT32(RM(ir)&0xFFFF) * SIGNEXT32(RN(ir)&0xFFFF));
nkeynes@1
   490
                    break;
nkeynes@1
   491
            }
nkeynes@1
   492
            break;
nkeynes@1
   493
        case 3: /* 0011nnnnmmmmxxxx */
nkeynes@1
   494
            switch( ir&0x000F ) {
nkeynes@1
   495
                case 0: /* CMP/EQ  Rm, Rn */
nkeynes@1
   496
                    sh4r.t = ( RM(ir) == RN(ir) ? 1 : 0 );
nkeynes@1
   497
                    break;
nkeynes@1
   498
                case 2: /* CMP/HS  Rm, Rn */
nkeynes@1
   499
                    sh4r.t = ( RN(ir) >= RM(ir) ? 1 : 0 );
nkeynes@1
   500
                    break;
nkeynes@1
   501
                case 3: /* CMP/GE  Rm, Rn */
nkeynes@1
   502
                    sh4r.t = ( ((int32_t)RN(ir)) >= ((int32_t)RM(ir)) ? 1 : 0 );
nkeynes@1
   503
                    break;
nkeynes@1
   504
                case 4: { /* DIV1    Rm, Rn */
nkeynes@1
   505
                    /* This is just from the sh4p manual with some
nkeynes@1
   506
                     * simplifications (someone want to check it's correct? :)
nkeynes@1
   507
                     * Why they couldn't just provide a real DIV instruction...
nkeynes@1
   508
                     * Please oh please let the translator batch these things
nkeynes@1
   509
                     * up into a single DIV... */
nkeynes@1
   510
                    uint32_t tmp0, tmp1, tmp2, dir;
nkeynes@1
   511
nkeynes@1
   512
                    dir = sh4r.q ^ sh4r.m;
nkeynes@1
   513
                    sh4r.q = (RN(ir) >> 31);
nkeynes@1
   514
                    tmp2 = RM(ir);
nkeynes@1
   515
                    RN(ir) = (RN(ir) << 1) | sh4r.t;
nkeynes@1
   516
                    tmp0 = RN(ir);
nkeynes@1
   517
                    if( dir ) {
nkeynes@1
   518
                        RN(ir) += tmp2;
nkeynes@1
   519
                        tmp1 = (RN(ir)<tmp0 ? 1 : 0 );
nkeynes@1
   520
                    } else {
nkeynes@1
   521
                        RN(ir) -= tmp2;
nkeynes@1
   522
                        tmp1 = (RN(ir)>tmp0 ? 1 : 0 );
nkeynes@1
   523
                    }
nkeynes@1
   524
                    sh4r.q ^= sh4r.m ^ tmp1;
nkeynes@1
   525
                    sh4r.t = ( sh4r.q == sh4r.m ? 1 : 0 );
nkeynes@1
   526
                    break; }
nkeynes@1
   527
                case 5: /* DMULU.L Rm, Rn */
nkeynes@1
   528
                    sh4r.mac = ((uint64_t)RM(ir)) * ((uint64_t)RN(ir));
nkeynes@1
   529
                    break;
nkeynes@1
   530
                case 6: /* CMP/HI  Rm, Rn */
nkeynes@1
   531
                    sh4r.t = ( RN(ir) > RM(ir) ? 1 : 0 );
nkeynes@1
   532
                    break;
nkeynes@1
   533
                case 7: /* CMP/GT  Rm, Rn */
nkeynes@1
   534
                    sh4r.t = ( ((int32_t)RN(ir)) > ((int32_t)RM(ir)) ? 1 : 0 );
nkeynes@1
   535
                    break;
nkeynes@1
   536
                case 8: /* SUB     Rm, Rn */
nkeynes@1
   537
                    RN(ir) -= RM(ir);
nkeynes@1
   538
                    break;
nkeynes@1
   539
                case 10:/* SUBC    Rm, Rn */
nkeynes@1
   540
                    tmp = RN(ir);
nkeynes@1
   541
                    RN(ir) = RN(ir) - RM(ir) - sh4r.t;
nkeynes@1
   542
                    sh4r.t = (RN(ir) > tmp || (RN(ir) == tmp && sh4r.t == 1));
nkeynes@1
   543
                    break;
nkeynes@1
   544
                case 11:/* SUBV    Rm, Rn */
nkeynes@1
   545
                    UNIMP(ir);
nkeynes@1
   546
                    break;
nkeynes@1
   547
                case 12:/* ADD     Rm, Rn */
nkeynes@1
   548
                    RN(ir) += RM(ir);
nkeynes@1
   549
                    break;
nkeynes@1
   550
                case 13:/* DMULS.L Rm, Rn */
nkeynes@1
   551
                    sh4r.mac = SIGNEXT32(RM(ir)) * SIGNEXT32(RN(ir));
nkeynes@1
   552
                    break;
nkeynes@1
   553
                case 14:/* ADDC    Rm, Rn */
nkeynes@1
   554
                    tmp = RN(ir);
nkeynes@1
   555
                    RN(ir) += RM(ir) + sh4r.t;
nkeynes@1
   556
                    sh4r.t = ( RN(ir) < tmp || (RN(ir) == tmp && sh4r.t != 0) ? 1 : 0 );
nkeynes@1
   557
                    break;
nkeynes@1
   558
                case 15:/* ADDV    Rm, Rn */
nkeynes@1
   559
                    UNIMP(ir);
nkeynes@1
   560
                    break;
nkeynes@1
   561
                default: UNDEF(ir);
nkeynes@1
   562
            }
nkeynes@1
   563
            break;
nkeynes@1
   564
        case 4: /* 0100nnnnxxxxxxxx */
nkeynes@1
   565
            switch( ir&0x00FF ) {
nkeynes@1
   566
                case 0x00: /* SHLL    Rn */
nkeynes@1
   567
                    sh4r.t = RN(ir) >> 31;
nkeynes@1
   568
                    RN(ir) <<= 1;
nkeynes@1
   569
                    break;
nkeynes@1
   570
                case 0x01: /* SHLR    Rn */
nkeynes@1
   571
                    sh4r.t = RN(ir) & 0x00000001;
nkeynes@1
   572
                    RN(ir) >>= 1;
nkeynes@1
   573
                    break;
nkeynes@1
   574
                case 0x02: /* STS.L   MACH, [--Rn] */
nkeynes@1
   575
                    RN(ir) -= 4;
nkeynes@1
   576
                    MEM_WRITE_LONG( RN(ir), (sh4r.mac>>32) );
nkeynes@1
   577
                    break;
nkeynes@1
   578
                case 0x03: /* STC.L   SR, [--Rn] */
nkeynes@1
   579
                    CHECKPRIV();
nkeynes@1
   580
                    RN(ir) -= 4;
nkeynes@1
   581
                    MEM_WRITE_LONG( RN(ir), sh4_read_sr() );
nkeynes@1
   582
                    break;
nkeynes@1
   583
                case 0x04: /* ROTL    Rn */
nkeynes@1
   584
                    sh4r.t = RN(ir) >> 31;
nkeynes@1
   585
                    RN(ir) <<= 1;
nkeynes@1
   586
                    RN(ir) |= sh4r.t;
nkeynes@1
   587
                    break;
nkeynes@1
   588
                case 0x05: /* ROTR    Rn */
nkeynes@1
   589
                    sh4r.t = RN(ir) & 0x00000001;
nkeynes@1
   590
                    RN(ir) >>= 1;
nkeynes@1
   591
                    RN(ir) |= (sh4r.t << 31);
nkeynes@1
   592
                    break;
nkeynes@1
   593
                case 0x06: /* LDS.L   [Rn++], MACH */
nkeynes@1
   594
                    sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
nkeynes@1
   595
                        (((uint64_t)MEM_READ_LONG(RN(ir)))<<32);
nkeynes@1
   596
                    RN(ir) += 4;
nkeynes@1
   597
                    break;
nkeynes@1
   598
                case 0x07: /* LDC.L   [Rn++], SR */
nkeynes@1
   599
                    CHECKPRIV();
nkeynes@1
   600
                    sh4_load_sr( MEM_READ_LONG(RN(ir)) );
nkeynes@1
   601
                    RN(ir) +=4;
nkeynes@1
   602
                    break;
nkeynes@1
   603
                case 0x08: /* SHLL2   Rn */
nkeynes@1
   604
                    RN(ir) <<= 2;
nkeynes@1
   605
                    break;
nkeynes@1
   606
                case 0x09: /* SHLR2   Rn */
nkeynes@1
   607
                    RN(ir) >>= 2;
nkeynes@1
   608
                    break;
nkeynes@1
   609
                case 0x0A: /* LDS     Rn, MACH */
nkeynes@1
   610
                    sh4r.mac = (sh4r.mac & 0x00000000FFFFFFFF) |
nkeynes@1
   611
                        (((uint64_t)RN(ir))<<32);
nkeynes@1
   612
                    break;
nkeynes@1
   613
                case 0x0B: /* JSR     [Rn] */
nkeynes@1
   614
                    CHECKDEST( RN(ir) );
nkeynes@2
   615
                    CHECKSLOTILLEGAL();
nkeynes@2
   616
                    sh4r.in_delay_slot = 1;
nkeynes@1
   617
                    sh4r.pc = sh4r.new_pc;
nkeynes@1
   618
                    sh4r.new_pc = RN(ir);
nkeynes@1
   619
                    sh4r.pr = pc + 4;
nkeynes@1
   620
                    return;
nkeynes@1
   621
                case 0x0E: /* LDC     Rn, SR */
nkeynes@1
   622
                    CHECKPRIV();
nkeynes@1
   623
                    sh4_load_sr( RN(ir) );
nkeynes@1
   624
                    break;
nkeynes@1
   625
                case 0x10: /* DT      Rn */
nkeynes@1
   626
                    RN(ir) --;
nkeynes@1
   627
                    sh4r.t = ( RN(ir) == 0 ? 1 : 0 );
nkeynes@1
   628
                    break;
nkeynes@1
   629
                case 0x11: /* CMP/PZ  Rn */
nkeynes@1
   630
                    sh4r.t = ( ((int32_t)RN(ir)) >= 0 ? 1 : 0 );
nkeynes@1
   631
                    break;
nkeynes@1
   632
                case 0x12: /* STS.L   MACL, [--Rn] */
nkeynes@1
   633
                    RN(ir) -= 4;
nkeynes@1
   634
                    MEM_WRITE_LONG( RN(ir), (uint32_t)sh4r.mac );
nkeynes@1
   635
                    break;
nkeynes@1
   636
                case 0x13: /* STC.L   GBR, [--Rn] */
nkeynes@1
   637
                    RN(ir) -= 4;
nkeynes@1
   638
                    MEM_WRITE_LONG( RN(ir), sh4r.gbr );
nkeynes@1
   639
                    break;
nkeynes@1
   640
                case 0x15: /* CMP/PL  Rn */
nkeynes@1
   641
                    sh4r.t = ( ((int32_t)RN(ir)) > 0 ? 1 : 0 );
nkeynes@1
   642
                    break;
nkeynes@1
   643
                case 0x16: /* LDS.L   [Rn++], MACL */
nkeynes@2
   644
                    sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
nkeynes@1
   645
                        (uint64_t)((uint32_t)MEM_READ_LONG(RN(ir)));
nkeynes@1
   646
                    RN(ir) += 4;
nkeynes@1
   647
                    break;
nkeynes@1
   648
                case 0x17: /* LDC.L   [Rn++], GBR */
nkeynes@1
   649
                    sh4r.gbr = MEM_READ_LONG(RN(ir));
nkeynes@1
   650
                    RN(ir) +=4;
nkeynes@1
   651
                    break;
nkeynes@1
   652
                case 0x18: /* SHLL8   Rn */
nkeynes@1
   653
                    RN(ir) <<= 8;
nkeynes@1
   654
                    break;
nkeynes@1
   655
                case 0x19: /* SHLR8   Rn */
nkeynes@1
   656
                    RN(ir) >>= 8;
nkeynes@1
   657
                    break;
nkeynes@1
   658
                case 0x1A: /* LDS     Rn, MACL */
nkeynes@2
   659
                    sh4r.mac = (sh4r.mac & 0xFFFFFFFF00000000LL) |
nkeynes@1
   660
                        (uint64_t)((uint32_t)(RN(ir)));
nkeynes@1
   661
                    break;
nkeynes@1
   662
                case 0x1B: /* TAS.B   [Rn] */
nkeynes@1
   663
                    tmp = MEM_READ_BYTE( RN(ir) );
nkeynes@1
   664
                    sh4r.t = ( tmp == 0 ? 1 : 0 );
nkeynes@1
   665
                    MEM_WRITE_BYTE( RN(ir), tmp | 0x80 );
nkeynes@1
   666
                    break;
nkeynes@1
   667
                case 0x1E: /* LDC     Rn, GBR */
nkeynes@1
   668
                    sh4r.gbr = RN(ir);
nkeynes@1
   669
                    break;
nkeynes@1
   670
                case 0x20: /* SHAL    Rn */
nkeynes@1
   671
                    sh4r.t = RN(ir) >> 31;
nkeynes@1
   672
                    RN(ir) <<= 1;
nkeynes@1
   673
                    break;
nkeynes@1
   674
                case 0x21: /* SHAR    Rn */
nkeynes@1
   675
                    sh4r.t = RN(ir) & 0x00000001;
nkeynes@1
   676
                    RN(ir) = ((int32_t)RN(ir)) >> 1;
nkeynes@1
   677
                    break;
nkeynes@1
   678
                case 0x22: /* STS.L   PR, [--Rn] */
nkeynes@1
   679
                    RN(ir) -= 4;
nkeynes@1
   680
                    MEM_WRITE_LONG( RN(ir), sh4r.pr );
nkeynes@1
   681
                    break;
nkeynes@1
   682
                case 0x23: /* STC.L   VBR, [--Rn] */
nkeynes@1
   683
                    CHECKPRIV();
nkeynes@1
   684
                    RN(ir) -= 4;
nkeynes@2
   685
                    MEM_WRITE_LONG( RN(ir), sh4r.vbr );
nkeynes@1
   686
                    break;
nkeynes@1
   687
                case 0x24: /* ROTCL   Rn */
nkeynes@1
   688
                    tmp = RN(ir) >> 31;
nkeynes@1
   689
                    RN(ir) <<= 1;
nkeynes@1
   690
                    RN(ir) |= sh4r.t;
nkeynes@1
   691
                    sh4r.t = tmp;
nkeynes@1
   692
                    break;
nkeynes@1
   693
                case 0x25: /* ROTCR   Rn */
nkeynes@1
   694
                    tmp = RN(ir) & 0x00000001;
nkeynes@1
   695
                    RN(ir) >>= 1;
nkeynes@1
   696
                    RN(ir) |= (sh4r.t << 31 );
nkeynes@1
   697
                    sh4r.t = tmp;
nkeynes@1
   698
                    break;
nkeynes@1
   699
                case 0x26: /* LDS.L   [Rn++], PR */
nkeynes@1
   700
                    sh4r.pr = MEM_READ_LONG( RN(ir) );
nkeynes@1
   701
                    RN(ir) += 4;
nkeynes@1
   702
                    break;
nkeynes@1
   703
                case 0x27: /* LDC.L   [Rn++], VBR */
nkeynes@1
   704
                    CHECKPRIV();
nkeynes@1
   705
                    sh4r.vbr = MEM_READ_LONG(RN(ir));
nkeynes@1
   706
                    RN(ir) +=4;
nkeynes@1
   707
                    break;
nkeynes@1
   708
                case 0x28: /* SHLL16  Rn */
nkeynes@1
   709
                    RN(ir) <<= 16;
nkeynes@1
   710
                    break;
nkeynes@1
   711
                case 0x29: /* SHLR16  Rn */
nkeynes@1
   712
                    RN(ir) >>= 16;
nkeynes@1
   713
                    break;
nkeynes@1
   714
                case 0x2A: /* LDS     Rn, PR */
nkeynes@1
   715
                    sh4r.pr = RN(ir);
nkeynes@1
   716
                    break;
nkeynes@1
   717
                case 0x2B: /* JMP     [Rn] */
nkeynes@1
   718
                    CHECKDEST( RN(ir) );
nkeynes@2
   719
                    CHECKSLOTILLEGAL();
nkeynes@2
   720
                    sh4r.in_delay_slot = 1;
nkeynes@1
   721
                    sh4r.pc = sh4r.new_pc;
nkeynes@1
   722
                    sh4r.new_pc = RN(ir);
nkeynes@1
   723
                    return;
nkeynes@1
   724
                case 0x2E: /* LDC     Rn, VBR */
nkeynes@1
   725
                    CHECKPRIV();
nkeynes@1
   726
                    sh4r.vbr = RN(ir);
nkeynes@1
   727
                    break;
nkeynes@1
   728
                case 0x32: /* STC.L   SGR, [--Rn] */
nkeynes@1
   729
                    CHECKPRIV();
nkeynes@1
   730
                    RN(ir) -= 4;
nkeynes@1
   731
                    MEM_WRITE_LONG( RN(ir), sh4r.sgr );
nkeynes@1
   732
                    break;
nkeynes@1
   733
                case 0x33: /* STC.L   SSR, [--Rn] */
nkeynes@1
   734
                    CHECKPRIV();
nkeynes@1
   735
                    RN(ir) -= 4;
nkeynes@1
   736
                    MEM_WRITE_LONG( RN(ir), sh4r.ssr );
nkeynes@1
   737
                    break;
nkeynes@1
   738
                case 0x37: /* LDC.L   [Rn++], SSR */
nkeynes@1
   739
                    CHECKPRIV();
nkeynes@1
   740
                    sh4r.ssr = MEM_READ_LONG(RN(ir));
nkeynes@1
   741
                    RN(ir) +=4;
nkeynes@1
   742
                    break;
nkeynes@1
   743
                case 0x3E: /* LDC     Rn, SSR */
nkeynes@1
   744
                    CHECKPRIV();
nkeynes@1
   745
                    sh4r.ssr = RN(ir);
nkeynes@1
   746
                    break;
nkeynes@1
   747
                case 0x43: /* STC.L   SPC, [--Rn] */
nkeynes@1
   748
                    CHECKPRIV();
nkeynes@1
   749
                    RN(ir) -= 4;
nkeynes@1
   750
                    MEM_WRITE_LONG( RN(ir), sh4r.spc );
nkeynes@1
   751
                    break;
nkeynes@1
   752
                case 0x47: /* LDC.L   [Rn++], SPC */
nkeynes@1
   753
                    CHECKPRIV();
nkeynes@1
   754
                    sh4r.spc = MEM_READ_LONG(RN(ir));
nkeynes@1
   755
                    RN(ir) +=4;
nkeynes@1
   756
                    break;
nkeynes@1
   757
                case 0x4E: /* LDC     Rn, SPC */
nkeynes@1
   758
                    CHECKPRIV();
nkeynes@1
   759
                    sh4r.spc = RN(ir);
nkeynes@1
   760
                    break;
nkeynes@1
   761
                case 0x52: /* STS.L   FPUL, [--Rn] */
nkeynes@1
   762
                    RN(ir) -= 4;
nkeynes@1
   763
                    MEM_WRITE_LONG( RN(ir), sh4r.fpul );
nkeynes@1
   764
                    break;
nkeynes@1
   765
                case 0x56: /* LDS.L   [Rn++], FPUL */
nkeynes@1
   766
                    sh4r.fpul = MEM_READ_LONG(RN(ir));
nkeynes@1
   767
                    RN(ir) +=4;
nkeynes@1
   768
                    break;
nkeynes@1
   769
                case 0x5A: /* LDS     Rn, FPUL */
nkeynes@1
   770
                    sh4r.fpul = RN(ir);
nkeynes@1
   771
                    break;
nkeynes@1
   772
                case 0x62: /* STS.L   FPSCR, [--Rn] */
nkeynes@1
   773
                    RN(ir) -= 4;
nkeynes@1
   774
                    MEM_WRITE_LONG( RN(ir), sh4r.fpscr );
nkeynes@1
   775
                    break;
nkeynes@1
   776
                case 0x66: /* LDS.L   [Rn++], FPSCR */
nkeynes@1
   777
                    sh4r.fpscr = MEM_READ_LONG(RN(ir));
nkeynes@1
   778
                    RN(ir) +=4;
nkeynes@1
   779
                    break;
nkeynes@1
   780
                case 0x6A: /* LDS     Rn, FPSCR */
nkeynes@1
   781
                    sh4r.fpscr = RN(ir);
nkeynes@1
   782
                    break;
nkeynes@1
   783
                case 0xF2: /* STC.L   DBR, [--Rn] */
nkeynes@1
   784
                    CHECKPRIV();
nkeynes@1
   785
                    RN(ir) -= 4;
nkeynes@1
   786
                    MEM_WRITE_LONG( RN(ir), sh4r.dbr );
nkeynes@1
   787
                    break;
nkeynes@1
   788
                case 0xF6: /* LDC.L   [Rn++], DBR */
nkeynes@1
   789
                    CHECKPRIV();
nkeynes@1
   790
                    sh4r.dbr = MEM_READ_LONG(RN(ir));
nkeynes@1
   791
                    RN(ir) +=4;
nkeynes@1
   792
                    break;
nkeynes@1
   793
                case 0xFA: /* LDC     Rn, DBR */
nkeynes@1
   794
                    CHECKPRIV();
nkeynes@1
   795
                    sh4r.dbr = RN(ir);
nkeynes@1
   796
                    break;
nkeynes@1
   797
                case 0x83: case 0x93: case 0xA3: case 0xB3: case 0xC3:
nkeynes@1
   798
                case 0xD3: case 0xE3: case 0xF3: /* STC.L   Rn_BANK, [--Rn] */
nkeynes@1
   799
                    CHECKPRIV();
nkeynes@1
   800
                    RN(ir) -= 4;
nkeynes@1
   801
                    MEM_WRITE_LONG( RN(ir), RN_BANK(ir) );
nkeynes@1
   802
                    break;
nkeynes@1
   803
                case 0x87: case 0x97: case 0xA7: case 0xB7: case 0xC7:
nkeynes@1
   804
                case 0xD7: case 0xE7: case 0xF7: /* LDC.L   [Rn++], Rn_BANK */
nkeynes@1
   805
                    CHECKPRIV();
nkeynes@1
   806
                    RN_BANK(ir) = MEM_READ_LONG( RN(ir) );
nkeynes@1
   807
                    RN(ir) += 4;
nkeynes@1
   808
                    break;
nkeynes@1
   809
                case 0x8E: case 0x9E: case 0xAE: case 0xBE: case 0xCE:
nkeynes@1
   810
                case 0xDE: case 0xEE: case 0xFE: /* LDC     Rm, Rn_BANK */
nkeynes@1
   811
                    CHECKPRIV();
nkeynes@1
   812
                    RN_BANK(ir) = RM(ir);
nkeynes@1
   813
                    break;
nkeynes@1
   814
                default:
nkeynes@1
   815
                    if( (ir&0x000F) == 0x0F ) {
nkeynes@1
   816
                        /* MAC.W   [Rm++], [Rn++] */
nkeynes@1
   817
                        tmp = SIGNEXT16(MEM_READ_WORD(RM(ir))) *
nkeynes@1
   818
                            SIGNEXT16(MEM_READ_WORD(RN(ir)));
nkeynes@1
   819
                        if( sh4r.s ) {
nkeynes@1
   820
                            /* FIXME */
nkeynes@1
   821
                            UNIMP(ir);
nkeynes@1
   822
                        } else sh4r.mac += SIGNEXT32(tmp);
nkeynes@1
   823
                        RM(ir) += 2;
nkeynes@1
   824
                        RN(ir) += 2;
nkeynes@1
   825
                    } else if( (ir&0x000F) == 0x0C ) {
nkeynes@1
   826
                        /* SHAD    Rm, Rn */
nkeynes@1
   827
                        tmp = RM(ir);
nkeynes@1
   828
                        if( (tmp & 0x80000000) == 0 ) RN(ir) <<= (tmp&0x1f);
nkeynes@9
   829
                        else if( (tmp & 0x1F) == 0 )  
nkeynes@9
   830
			  RN(ir) = ((int32_t)RN(ir)) >> 31;
nkeynes@9
   831
                        else 
nkeynes@9
   832
			  RN(ir) = ((int32_t)RN(ir)) >> (((~RM(ir)) & 0x1F)+1);
nkeynes@1
   833
                    } else if( (ir&0x000F) == 0x0D ) {
nkeynes@1
   834
                        /* SHLD    Rm, Rn */
nkeynes@1
   835
                        tmp = RM(ir);
nkeynes@1
   836
                        if( (tmp & 0x80000000) == 0 ) RN(ir) <<= (tmp&0x1f);
nkeynes@1
   837
                        else if( (tmp & 0x1F) == 0 ) RN(ir) = 0;
nkeynes@1
   838
                        else RN(ir) >>= (((~tmp) & 0x1F)+1);
nkeynes@1
   839
                    } else UNDEF(ir);
nkeynes@1
   840
            }
nkeynes@1
   841
            break;
nkeynes@1
   842
        case 5: /* 0101nnnnmmmmdddd */
nkeynes@1
   843
            /* MOV.L   [Rm + disp4*4], Rn */
nkeynes@1
   844
            RN(ir) = MEM_READ_LONG( RM(ir) + (DISP4(ir)<<2) );
nkeynes@1
   845
            break;
nkeynes@1
   846
        case 6: /* 0110xxxxxxxxxxxx */
nkeynes@1
   847
            switch( ir&0x000f ) {
nkeynes@1
   848
                case 0: /* MOV.B   [Rm], Rn */
nkeynes@1
   849
                    RN(ir) = MEM_READ_BYTE( RM(ir) );
nkeynes@1
   850
                    break;
nkeynes@1
   851
                case 1: /* MOV.W   [Rm], Rn */
nkeynes@1
   852
                    RN(ir) = MEM_READ_WORD( RM(ir) );
nkeynes@1
   853
                    break;
nkeynes@1
   854
                case 2: /* MOV.L   [Rm], Rn */
nkeynes@1
   855
                    RN(ir) = MEM_READ_LONG( RM(ir) );
nkeynes@1
   856
                    break;
nkeynes@1
   857
                case 3: /* MOV     Rm, Rn */
nkeynes@1
   858
                    RN(ir) = RM(ir);
nkeynes@1
   859
                    break;
nkeynes@1
   860
                case 4: /* MOV.B   [Rm++], Rn */
nkeynes@1
   861
                    RN(ir) = MEM_READ_BYTE( RM(ir) );
nkeynes@1
   862
                    RM(ir) ++;
nkeynes@1
   863
                    break;
nkeynes@1
   864
                case 5: /* MOV.W   [Rm++], Rn */
nkeynes@1
   865
                    RN(ir) = MEM_READ_WORD( RM(ir) );
nkeynes@1
   866
                    RM(ir) += 2;
nkeynes@1
   867
                    break;
nkeynes@1
   868
                case 6: /* MOV.L   [Rm++], Rn */
nkeynes@1
   869
                    RN(ir) = MEM_READ_LONG( RM(ir) );
nkeynes@1
   870
                    RM(ir) += 4;
nkeynes@1
   871
                    break;
nkeynes@1
   872
                case 7: /* NOT     Rm, Rn */
nkeynes@1
   873
                    RN(ir) = ~RM(ir);
nkeynes@1
   874
                    break;
nkeynes@1
   875
                case 8: /* SWAP.B  Rm, Rn */
nkeynes@1
   876
                    RN(ir) = (RM(ir)&0xFFFF0000) | ((RM(ir)&0x0000FF00)>>8) |
nkeynes@1
   877
                        ((RM(ir)&0x000000FF)<<8);
nkeynes@1
   878
                    break;
nkeynes@1
   879
                case 9: /* SWAP.W  Rm, Rn */
nkeynes@1
   880
                    RN(ir) = (RM(ir)>>16) | (RM(ir)<<16);
nkeynes@1
   881
                    break;
nkeynes@1
   882
                case 10:/* NEGC    Rm, Rn */
nkeynes@1
   883
                    tmp = 0 - RM(ir);
nkeynes@1
   884
                    RN(ir) = tmp - sh4r.t;
nkeynes@1
   885
                    sh4r.t = ( 0<tmp || tmp<RN(ir) ? 1 : 0 );
nkeynes@1
   886
                    break;
nkeynes@1
   887
                case 11:/* NEG     Rm, Rn */
nkeynes@1
   888
                    RN(ir) = 0 - RM(ir);
nkeynes@1
   889
                    break;
nkeynes@1
   890
                case 12:/* EXTU.B  Rm, Rn */
nkeynes@1
   891
                    RN(ir) = RM(ir)&0x000000FF;
nkeynes@1
   892
                    break;
nkeynes@1
   893
                case 13:/* EXTU.W  Rm, Rn */
nkeynes@1
   894
                    RN(ir) = RM(ir)&0x0000FFFF;
nkeynes@1
   895
                    break;
nkeynes@1
   896
                case 14:/* EXTS.B  Rm, Rn */
nkeynes@1
   897
                    RN(ir) = SIGNEXT8( RM(ir)&0x000000FF );
nkeynes@1
   898
                    break;
nkeynes@1
   899
                case 15:/* EXTS.W  Rm, Rn */
nkeynes@1
   900
                    RN(ir) = SIGNEXT16( RM(ir)&0x0000FFFF );
nkeynes@1
   901
                    break;
nkeynes@1
   902
            }
nkeynes@1
   903
            break;
nkeynes@1
   904
        case 7: /* 0111nnnniiiiiiii */
nkeynes@1
   905
            /* ADD    imm8, Rn */
nkeynes@1
   906
            RN(ir) += IMM8(ir);
nkeynes@1
   907
            break;
nkeynes@1
   908
        case 8: /* 1000xxxxxxxxxxxx */
nkeynes@1
   909
            switch( (ir&0x0F00) >> 8 ) {
nkeynes@1
   910
                case 0: /* MOV.B   R0, [Rm + disp4] */
nkeynes@1
   911
                    MEM_WRITE_BYTE( RM(ir) + DISP4(ir), R0 );
nkeynes@1
   912
                    break;
nkeynes@1
   913
                case 1: /* MOV.W   R0, [Rm + disp4*2] */
nkeynes@1
   914
                    MEM_WRITE_WORD( RM(ir) + (DISP4(ir)<<1), R0 );
nkeynes@1
   915
                    break;
nkeynes@1
   916
                case 4: /* MOV.B   [Rm + disp4], R0 */
nkeynes@1
   917
                    R0 = MEM_READ_BYTE( RM(ir) + DISP4(ir) );
nkeynes@1
   918
                    break;
nkeynes@1
   919
                case 5: /* MOV.W   [Rm + disp4*2], R0 */
nkeynes@1
   920
                    R0 = MEM_READ_WORD( RM(ir) + (DISP4(ir)<<1) );
nkeynes@1
   921
                    break;
nkeynes@1
   922
                case 8: /* CMP/EQ  imm, R0 */
nkeynes@1
   923
                    sh4r.t = ( R0 == IMM8(ir) ? 1 : 0 );
nkeynes@1
   924
                    break;
nkeynes@1
   925
                case 9: /* BT      disp8 */
nkeynes@2
   926
                    CHECKSLOTILLEGAL()
nkeynes@1
   927
                    if( sh4r.t ) {
nkeynes@1
   928
                        CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
nkeynes@1
   929
                        sh4r.pc += (PCDISP8(ir)<<1) + 4;
nkeynes@1
   930
                        sh4r.new_pc = sh4r.pc + 2;
nkeynes@1
   931
                        return;
nkeynes@1
   932
                    }
nkeynes@1
   933
                    break;
nkeynes@1
   934
                case 11:/* BF      disp8 */
nkeynes@2
   935
                    CHECKSLOTILLEGAL()
nkeynes@1
   936
                    if( !sh4r.t ) {
nkeynes@1
   937
                        CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
nkeynes@1
   938
                        sh4r.pc += (PCDISP8(ir)<<1) + 4;
nkeynes@1
   939
                        sh4r.new_pc = sh4r.pc + 2;
nkeynes@1
   940
                        return;
nkeynes@1
   941
                    }
nkeynes@1
   942
                    break;
nkeynes@1
   943
                case 13:/* BT/S    disp8 */
nkeynes@2
   944
                    CHECKSLOTILLEGAL()
nkeynes@1
   945
                    if( sh4r.t ) {
nkeynes@1
   946
                        CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
nkeynes@2
   947
                        sh4r.in_delay_slot = 1;
nkeynes@1
   948
                        sh4r.pc = sh4r.new_pc;
nkeynes@1
   949
                        sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
nkeynes@2
   950
                        sh4r.in_delay_slot = 1;
nkeynes@1
   951
                        return;
nkeynes@1
   952
                    }
nkeynes@1
   953
                    break;
nkeynes@1
   954
                case 15:/* BF/S    disp8 */
nkeynes@2
   955
                    CHECKSLOTILLEGAL()
nkeynes@1
   956
                    if( !sh4r.t ) {
nkeynes@1
   957
                        CHECKDEST( sh4r.pc + (PCDISP8(ir)<<1) + 4 )
nkeynes@2
   958
                        sh4r.in_delay_slot = 1;
nkeynes@1
   959
                        sh4r.pc = sh4r.new_pc;
nkeynes@1
   960
                        sh4r.new_pc = pc + (PCDISP8(ir)<<1) + 4;
nkeynes@1
   961
                        return;
nkeynes@1
   962
                    }
nkeynes@1
   963
                    break;
nkeynes@1
   964
                default: UNDEF(ir);
nkeynes@1
   965
            }
nkeynes@1
   966
            break;
nkeynes@1
   967
        case 9: /* 1001xxxxxxxxxxxx */
nkeynes@1
   968
            /* MOV.W   [disp8*2 + pc + 4], Rn */
nkeynes@1
   969
            RN(ir) = MEM_READ_WORD( pc + 4 + (DISP8(ir)<<1) );
nkeynes@1
   970
            break;
nkeynes@1
   971
        case 10:/* 1010dddddddddddd */
nkeynes@1
   972
            /* BRA     disp12 */
nkeynes@2
   973
            CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 )
nkeynes@2
   974
            CHECKSLOTILLEGAL()
nkeynes@2
   975
            sh4r.in_delay_slot = 1;
nkeynes@1
   976
            sh4r.pc = sh4r.new_pc;
nkeynes@1
   977
            sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
nkeynes@1
   978
            return;
nkeynes@1
   979
        case 11:/* 1011dddddddddddd */
nkeynes@1
   980
            /* BSR     disp12 */
nkeynes@1
   981
            CHECKDEST( sh4r.pc + (DISP12(ir)<<1) + 4 )
nkeynes@2
   982
            CHECKSLOTILLEGAL()
nkeynes@2
   983
            sh4r.in_delay_slot = 1;
nkeynes@1
   984
            sh4r.pr = pc + 4;
nkeynes@1
   985
            sh4r.pc = sh4r.new_pc;
nkeynes@1
   986
            sh4r.new_pc = pc + 4 + (DISP12(ir)<<1);
nkeynes@1
   987
            return;
nkeynes@1
   988
        case 12:/* 1100xxxxdddddddd */
nkeynes@1
   989
        switch( (ir&0x0F00)>>8 ) {
nkeynes@1
   990
                case 0: /* MOV.B  R0, [GBR + disp8] */
nkeynes@1
   991
                    MEM_WRITE_BYTE( sh4r.gbr + DISP8(ir), R0 );
nkeynes@1
   992
                    break;
nkeynes@1
   993
                case 1: /* MOV.W  R0, [GBR + disp8*2] */
nkeynes@1
   994
                    MEM_WRITE_WORD( sh4r.gbr + (DISP8(ir)<<1), R0 );
nkeynes@1
   995
                    break;
nkeynes@1
   996
                case  2: /*MOV.L   R0, [GBR + disp8*4] */
nkeynes@1
   997
                    MEM_WRITE_LONG( sh4r.gbr + (DISP8(ir)<<2), R0 );
nkeynes@1
   998
                    break;
nkeynes@1
   999
                case 3: /* TRAPA   imm8 */
nkeynes@2
  1000
                    CHECKSLOTILLEGAL()
nkeynes@2
  1001
                    sh4r.in_delay_slot = 1;
nkeynes@1
  1002
                    MMIO_WRITE( MMU, TRA, UIMM8(ir) );
nkeynes@1
  1003
                    sh4r.pc = sh4r.new_pc;  /* RAISE ends the instruction */
nkeynes@1
  1004
                    sh4r.new_pc += 2;
nkeynes@1
  1005
                    RAISE( EXC_TRAP, EXV_TRAP );
nkeynes@1
  1006
                    break;
nkeynes@1
  1007
                case 4: /* MOV.B   [GBR + disp8], R0 */
nkeynes@1
  1008
                    R0 = MEM_READ_BYTE( sh4r.gbr + DISP8(ir) );
nkeynes@1
  1009
                    break;
nkeynes@1
  1010
                case 5: /* MOV.W   [GBR + disp8*2], R0 */
nkeynes@1
  1011
                    R0 = MEM_READ_WORD( sh4r.gbr + (DISP8(ir)<<1) );
nkeynes@1
  1012
                    break;
nkeynes@1
  1013
                case 6: /* MOV.L   [GBR + disp8*4], R0 */
nkeynes@1
  1014
                    R0 = MEM_READ_LONG( sh4r.gbr + (DISP8(ir)<<2) );
nkeynes@1
  1015
                    break;
nkeynes@1
  1016
                case 7: /* MOVA    disp8 + pc&~3 + 4, R0 */
nkeynes@1
  1017
                    R0 = (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4;
nkeynes@1
  1018
                    break;
nkeynes@1
  1019
                case 8: /* TST     imm8, R0 */
nkeynes@1
  1020
                    sh4r.t = (R0 & UIMM8(ir) ? 0 : 1);
nkeynes@1
  1021
                    break;
nkeynes@1
  1022
                case 9: /* AND     imm8, R0 */
nkeynes@1
  1023
                    R0 &= UIMM8(ir);
nkeynes@1
  1024
                    break;
nkeynes@1
  1025
                case 10:/* XOR     imm8, R0 */
nkeynes@1
  1026
                    R0 ^= UIMM8(ir);
nkeynes@1
  1027
                    break;
nkeynes@1
  1028
                case 11:/* OR      imm8, R0 */
nkeynes@1
  1029
                    R0 |= UIMM8(ir);
nkeynes@1
  1030
                    break;
nkeynes@1
  1031
                case 12:/* TST.B   imm8, [R0+GBR] */
nkeynes@1
  1032
                    sh4r.t = ( MEM_READ_BYTE(R0 + sh4r.gbr) & UIMM8(ir) ? 0 : 1 );
nkeynes@1
  1033
                    break;
nkeynes@1
  1034
                case 13:/* AND.B   imm8, [R0+GBR] */
nkeynes@1
  1035
                    MEM_WRITE_BYTE( R0 + sh4r.gbr,
nkeynes@1
  1036
                                    UIMM8(ir) & MEM_READ_BYTE(R0 + sh4r.gbr) );
nkeynes@1
  1037
                    break;
nkeynes@1
  1038
                case 14:/* XOR.B   imm8, [R0+GBR] */
nkeynes@1
  1039
                    MEM_WRITE_BYTE( R0 + sh4r.gbr,
nkeynes@1
  1040
                                    UIMM8(ir) ^ MEM_READ_BYTE(R0 + sh4r.gbr) );
nkeynes@1
  1041
                    break;
nkeynes@1
  1042
                case 15:/* OR.B    imm8, [R0+GBR] */
nkeynes@1
  1043
                    MEM_WRITE_BYTE( R0 + sh4r.gbr,
nkeynes@1
  1044
                                    UIMM8(ir) | MEM_READ_BYTE(R0 + sh4r.gbr) );
nkeynes@1
  1045
                    break;
nkeynes@1
  1046
            }
nkeynes@1
  1047
            break;
nkeynes@1
  1048
        case 13:/* 1101nnnndddddddd */
nkeynes@1
  1049
            /* MOV.L   [disp8*4 + pc&~3 + 4], Rn */
nkeynes@1
  1050
            RN(ir) = MEM_READ_LONG( (pc&0xFFFFFFFC) + (DISP8(ir)<<2) + 4 );
nkeynes@1
  1051
            break;
nkeynes@1
  1052
        case 14:/* 1110nnnniiiiiiii */
nkeynes@1
  1053
            /* MOV     imm8, Rn */
nkeynes@1
  1054
            RN(ir) = IMM8(ir);
nkeynes@1
  1055
            break;
nkeynes@1
  1056
        case 15:/* 1111xxxxxxxxxxxx */
nkeynes@1
  1057
            CHECKFPUEN();
nkeynes@1
  1058
            switch( ir&0x000F ) {
nkeynes@1
  1059
                case 0: /* FADD    FRm, FRn */
nkeynes@1
  1060
                    FRN(ir) += FRM(ir);
nkeynes@1
  1061
                    break;
nkeynes@1
  1062
                case 1: /* FSUB    FRm, FRn */
nkeynes@1
  1063
                    FRN(ir) -= FRM(ir);
nkeynes@1
  1064
                    break;
nkeynes@1
  1065
                case 2: /* FMUL    FRm, FRn */
nkeynes@1
  1066
                    FRN(ir) = FRN(ir) * FRM(ir);
nkeynes@1
  1067
                    break;
nkeynes@1
  1068
                case 3: /* FDIV    FRm, FRn */
nkeynes@1
  1069
                    FRN(ir) = FRN(ir) / FRM(ir);
nkeynes@1
  1070
                    break;
nkeynes@1
  1071
                case 4: /* FCMP/EQ FRm, FRn */
nkeynes@1
  1072
                    sh4r.t = ( FRN(ir) == FRM(ir) ? 1 : 0 );
nkeynes@1
  1073
                    break;
nkeynes@1
  1074
                case 5: /* FCMP/GT FRm, FRn */
nkeynes@1
  1075
                    sh4r.t = ( FRN(ir) > FRM(ir) ? 1 : 0 );
nkeynes@1
  1076
                    break;
nkeynes@1
  1077
                case 6: /* FMOV.S  [Rm+R0], FRn */
nkeynes@1
  1078
                    MEM_FP_READ( RM(ir) + R0, FRNn(ir) );
nkeynes@1
  1079
                    break;
nkeynes@1
  1080
                case 7: /* FMOV.S  FRm, [Rn+R0] */
nkeynes@1
  1081
                    MEM_FP_WRITE( RN(ir) + R0, FRMn(ir) );
nkeynes@1
  1082
                    break;
nkeynes@1
  1083
                case 8: /* FMOV.S  [Rm], FRn */
nkeynes@1
  1084
                    MEM_FP_READ( RM(ir), FRNn(ir) );
nkeynes@1
  1085
                    break;
nkeynes@1
  1086
                case 9: /* FMOV.S  [Rm++], FRn */
nkeynes@1
  1087
                    MEM_FP_READ( RM(ir), FRNn(ir) );
nkeynes@1
  1088
                    RM(ir) += FP_WIDTH;
nkeynes@1
  1089
                    break;
nkeynes@1
  1090
                case 10:/* FMOV.S  FRm, [Rn] */
nkeynes@1
  1091
                    MEM_FP_WRITE( RN(ir), FRMn(ir) );
nkeynes@1
  1092
                    break;
nkeynes@1
  1093
                case 11:/* FMOV.S  FRm, [--Rn] */
nkeynes@1
  1094
                    RN(ir) -= FP_WIDTH;
nkeynes@1
  1095
                    MEM_FP_WRITE( RN(ir), FRMn(ir) );
nkeynes@1
  1096
                    break;
nkeynes@1
  1097
                case 12:/* FMOV    FRm, FRn */
nkeynes@1
  1098
                    if( IS_FPU_DOUBLESIZE() ) {
nkeynes@1
  1099
                        DRN(ir) = DRM(ir);
nkeynes@1
  1100
                    } else {
nkeynes@1
  1101
                        FRN(ir) = FRM(ir);
nkeynes@1
  1102
                    }
nkeynes@1
  1103
                    break;
nkeynes@1
  1104
                case 13:
nkeynes@1
  1105
                    switch( (ir&0x00F0) >> 4 ) {
nkeynes@1
  1106
                        case 0: /* FSTS    FPUL, FRn */
nkeynes@1
  1107
                            FRN(ir) = FPULf;
nkeynes@1
  1108
                            break;
nkeynes@1
  1109
                        case 1: /* FLDS    FRn, FPUL */
nkeynes@1
  1110
                            FPULf = FRN(ir);
nkeynes@1
  1111
                            break;
nkeynes@1
  1112
                        case 2: /* FLOAT   FPUL, FRn */
nkeynes@1
  1113
                            FRN(ir) = (float)FPULi;
nkeynes@1
  1114
                            break;
nkeynes@1
  1115
                        case 3: /* FTRC    FRn, FPUL */
nkeynes@1
  1116
                            FPULi = (uint32_t)FRN(ir);
nkeynes@1
  1117
                            /* FIXME: is this sufficient? */
nkeynes@1
  1118
                            break;
nkeynes@1
  1119
                        case 4: /* FNEG    FRn */
nkeynes@1
  1120
                            FRN(ir) = -FRN(ir);
nkeynes@1
  1121
                            break;
nkeynes@1
  1122
                        case 5: /* FABS    FRn */
nkeynes@1
  1123
                            FRN(ir) = fabsf(FRN(ir));
nkeynes@1
  1124
                            break;
nkeynes@1
  1125
                        case 6: /* FSQRT   FRn */
nkeynes@1
  1126
                            FRN(ir) = sqrtf(FRN(ir));
nkeynes@1
  1127
                            break;
nkeynes@2
  1128
                        case 7: /* FSRRA FRn */
nkeynes@2
  1129
                            FRN(ir) = 1.0/sqrtf(FRN(ir));
nkeynes@2
  1130
                            break;
nkeynes@1
  1131
                        case 8: /* FLDI0   FRn */
nkeynes@1
  1132
                            FRN(ir) = 0.0;
nkeynes@1
  1133
                            break;
nkeynes@1
  1134
                        case 9: /* FLDI1   FRn */
nkeynes@1
  1135
                            FRN(ir) = 1.0;
nkeynes@1
  1136
                            break;
nkeynes@1
  1137
                        case 10: /* FCNVSD FPUL, DRn */
nkeynes@1
  1138
                            if( IS_FPU_DOUBLEPREC() )
nkeynes@1
  1139
                                DRN(ir) = (double)FPULf;
nkeynes@1
  1140
                            else UNDEF(ir);
nkeynes@1
  1141
                            break;
nkeynes@1
  1142
                        case 11: /* FCNVDS DRn, FPUL */
nkeynes@1
  1143
                            if( IS_FPU_DOUBLEPREC() ) 
nkeynes@1
  1144
                                FPULf = (float)DRN(ir);
nkeynes@1
  1145
                            else UNDEF(ir);
nkeynes@1
  1146
                            break;
nkeynes@2
  1147
                        case 14:/* FIPR    FVm, FVn */
nkeynes@2
  1148
                            /* FIXME: This is not going to be entirely accurate
nkeynes@2
  1149
                             * as the SH4 instruction is less precise. Also
nkeynes@2
  1150
                             * need to check for 0s and infinities.
nkeynes@2
  1151
                             */
nkeynes@2
  1152
                        {
nkeynes@2
  1153
                            float *fr_bank = FR;
nkeynes@2
  1154
                            int tmp2 = FVN(ir);
nkeynes@2
  1155
                            tmp = FVM(ir);
nkeynes@2
  1156
                            fr_bank[tmp2+3] = fr_bank[tmp]*fr_bank[tmp2] +
nkeynes@2
  1157
                                fr_bank[tmp+1]*fr_bank[tmp2+1] +
nkeynes@2
  1158
                                fr_bank[tmp+2]*fr_bank[tmp2+2] +
nkeynes@2
  1159
                                fr_bank[tmp+3]*fr_bank[tmp2+3];
nkeynes@1
  1160
                            break;
nkeynes@2
  1161
                        }
nkeynes@1
  1162
                        case 15:
nkeynes@2
  1163
                            if( (ir&0x0300) == 0x0100 ) { /* FTRV    XMTRX,FVn */
nkeynes@2
  1164
                                float *fvout = FR+FVN(ir);
nkeynes@2
  1165
                                float *xm = XF;
nkeynes@2
  1166
                                float fv[4] = { fvout[0], fvout[1], fvout[2], fvout[3] };
nkeynes@2
  1167
                                fvout[0] = xm[0] * fv[0] + xm[4]*fv[1] +
nkeynes@2
  1168
                                    xm[8]*fv[2] + xm[12]*fv[3];
nkeynes@2
  1169
                                fvout[1] = xm[1] * fv[0] + xm[5]*fv[1] +
nkeynes@2
  1170
                                    xm[9]*fv[2] + xm[13]*fv[3];
nkeynes@2
  1171
                                fvout[2] = xm[2] * fv[0] + xm[6]*fv[1] +
nkeynes@2
  1172
                                    xm[10]*fv[2] + xm[14]*fv[3];
nkeynes@2
  1173
                                fvout[3] = xm[3] * fv[0] + xm[7]*fv[1] +
nkeynes@2
  1174
                                    xm[11]*fv[2] + xm[15]*fv[3];
nkeynes@2
  1175
                                break;
nkeynes@2
  1176
                            }
nkeynes@2
  1177
                            else if( (ir&0x0100) == 0 ) { /* FSCA    FPUL, DRn */
nkeynes@2
  1178
                                float angle = (((float)(short)(FPULi>>16)) +
nkeynes@2
  1179
                                               ((float)(FPULi&16)/65536.0)) *
nkeynes@2
  1180
                                    2 * M_PI;
nkeynes@2
  1181
                                int reg = FRNn(ir);
nkeynes@2
  1182
                                FR[reg] = sinf(angle);
nkeynes@2
  1183
                                FR[reg+1] = cosf(angle);
nkeynes@2
  1184
                                break;
nkeynes@2
  1185
                            }
nkeynes@2
  1186
                            else if( ir == 0xFBFD ) {
nkeynes@2
  1187
                                /* FRCHG   */
nkeynes@1
  1188
                                sh4r.fpscr ^= FPSCR_FR;
nkeynes@2
  1189
                                break;
nkeynes@2
  1190
                            }
nkeynes@2
  1191
                            else if( ir == 0xF3FD ) {
nkeynes@2
  1192
                                /* FSCHG   */
nkeynes@1
  1193
                                sh4r.fpscr ^= FPSCR_SZ;
nkeynes@2
  1194
                                break;
nkeynes@2
  1195
                            }
nkeynes@1
  1196
                        default: UNDEF(ir);
nkeynes@1
  1197
                    }
nkeynes@1
  1198
                    break;
nkeynes@1
  1199
                case 14:/* FMAC    FR0, FRm, FRn */
nkeynes@1
  1200
                    FRN(ir) += FRM(ir)*FR0;
nkeynes@1
  1201
                    break;
nkeynes@1
  1202
                default: UNDEF(ir);
nkeynes@1
  1203
            }
nkeynes@1
  1204
            break;
nkeynes@1
  1205
    }
nkeynes@1
  1206
    sh4r.pc = sh4r.new_pc;
nkeynes@1
  1207
    sh4r.new_pc += 2;
nkeynes@2
  1208
    sh4r.in_delay_slot = 0;
nkeynes@1
  1209
}
.