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