Search
lxdream.org :: lxdream/src/sh4/sh4dasm.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4dasm.c
changeset 54:d8b73031289c
prev43:0cf3e339cc59
next302:96b5cc24309c
author nkeynes
date Wed Jan 03 09:00:17 2007 +0000 (17 years ago)
permissions -rw-r--r--
last change Adjust timers when they're read rather than waiting until the next time
slice. Also temporarily cut the CPU time by 4.
Initialize the FRQCR register to 0x0E0A for convenience
file annotate diff log raw
nkeynes@30
     1
/**
nkeynes@54
     2
 * $Id: sh4dasm.c,v 1.9 2006-01-01 08:08:40 nkeynes Exp $
nkeynes@30
     3
 * 
nkeynes@30
     4
 * SH4 CPU definition and disassembly functions
nkeynes@30
     5
 *
nkeynes@30
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@30
     7
 *
nkeynes@30
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@30
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@30
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@30
    11
 * (at your option) any later version.
nkeynes@30
    12
 *
nkeynes@30
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@30
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@30
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@30
    16
 * GNU General Public License for more details.
nkeynes@30
    17
 */
nkeynes@30
    18
nkeynes@1
    19
#include "sh4core.h"
nkeynes@1
    20
#include "sh4dasm.h"
nkeynes@1
    21
#include "mem.h"
nkeynes@1
    22
nkeynes@1
    23
#define UNIMP(ir) snprintf( buf, len, "???     " )
nkeynes@1
    24
nkeynes@9
    25
nkeynes@11
    26
const struct reg_desc_struct sh4_reg_map[] = 
nkeynes@9
    27
  { {"R0", REG_INT, &sh4r.r[0]}, {"R1", REG_INT, &sh4r.r[1]},
nkeynes@9
    28
    {"R2", REG_INT, &sh4r.r[2]}, {"R3", REG_INT, &sh4r.r[3]},
nkeynes@9
    29
    {"R4", REG_INT, &sh4r.r[4]}, {"R5", REG_INT, &sh4r.r[5]},
nkeynes@9
    30
    {"R6", REG_INT, &sh4r.r[6]}, {"R7", REG_INT, &sh4r.r[7]},
nkeynes@9
    31
    {"R8", REG_INT, &sh4r.r[8]}, {"R9", REG_INT, &sh4r.r[9]},
nkeynes@9
    32
    {"R10",REG_INT, &sh4r.r[10]}, {"R11",REG_INT, &sh4r.r[11]},
nkeynes@9
    33
    {"R12",REG_INT, &sh4r.r[12]}, {"R13",REG_INT, &sh4r.r[13]},
nkeynes@9
    34
    {"R14",REG_INT, &sh4r.r[14]}, {"R15",REG_INT, &sh4r.r[15]},
nkeynes@9
    35
    {"SR", REG_INT, &sh4r.sr}, {"GBR", REG_INT, &sh4r.gbr},
nkeynes@9
    36
    {"SSR",REG_INT, &sh4r.ssr}, {"SPC", REG_INT, &sh4r.spc},
nkeynes@9
    37
    {"SGR",REG_INT, &sh4r.sgr}, {"DBR", REG_INT, &sh4r.dbr},
nkeynes@9
    38
    {"VBR",REG_INT, &sh4r.vbr},
nkeynes@9
    39
    {"PC", REG_INT, &sh4r.pc}, {"PR", REG_INT, &sh4r.pr},
nkeynes@9
    40
    {"MACL",REG_INT, &sh4r.mac},{"MACH",REG_INT, ((uint32_t *)&sh4r.mac)+1},
nkeynes@9
    41
    {"FPUL", REG_INT, &sh4r.fpul}, {"FPSCR", REG_INT, &sh4r.fpscr},
nkeynes@9
    42
    {NULL, 0, NULL} };
nkeynes@9
    43
nkeynes@10
    44
nkeynes@14
    45
const struct cpu_desc_struct sh4_cpu_desc = 
nkeynes@43
    46
    { "SH4", sh4_disasm_instruction, sh4_execute_instruction, mem_has_page, 
nkeynes@43
    47
      sh4_set_breakpoint, sh4_clear_breakpoint, sh4_get_breakpoint, 2,
nkeynes@14
    48
      (char *)&sh4r, sizeof(sh4r), sh4_reg_map,
nkeynes@30
    49
      &sh4r.pc, &sh4r.icount };
nkeynes@9
    50
nkeynes@11
    51
uint32_t sh4_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
nkeynes@1
    52
{
nkeynes@10
    53
    uint16_t ir = sh4_read_word(pc);
nkeynes@1
    54
    
nkeynes@1
    55
#define RN(ir) ((ir&0x0F00)>>8)
nkeynes@1
    56
#define RN_BANK(ir) ((ir&0x0070)>>4)
nkeynes@1
    57
#define RM(ir) ((ir&0x00F0)>>4)
nkeynes@1
    58
#define DISP4(ir) (ir&0x000F) /* 4-bit displacements are *not* sign extended */
nkeynes@1
    59
#define DISP8(ir) (ir&0x00FF)
nkeynes@1
    60
#define PCDISP8(ir) SIGNEXT8(ir&0x00FF)
nkeynes@1
    61
#define UIMM8(ir) (ir&0x00FF)
nkeynes@1
    62
#define IMM8(ir) SIGNEXT8(ir&0x00FF)
nkeynes@1
    63
#define DISP12(ir) SIGNEXT12(ir&0x0FFF)
nkeynes@1
    64
#define FVN(ir) ((ir&0x0C00)>>10)
nkeynes@1
    65
#define FVM(ir) ((ir&0x0300)>>8)
nkeynes@1
    66
nkeynes@11
    67
    sprintf( opcode, "%02X %02X", ir&0xFF, ir>>8 );
nkeynes@11
    68
nkeynes@1
    69
    switch( (ir&0xF000)>>12 ) {
nkeynes@1
    70
        case 0: /* 0000nnnnmmmmxxxx */
nkeynes@1
    71
            switch( ir&0x000F ) {
nkeynes@1
    72
                case 2:
nkeynes@1
    73
                    switch( (ir&0x00F0)>>4 ) {
nkeynes@1
    74
                        case 0: snprintf( buf, len, "STC     SR, R%d", RN(ir) ); break;
nkeynes@1
    75
                        case 1: snprintf( buf, len, "STC     GBR, R%d", RN(ir) ); break;
nkeynes@1
    76
                        case 2: snprintf( buf, len, "STC     VBR, R%d", RN(ir) ); break;
nkeynes@1
    77
                        case 3: snprintf( buf, len, "STC     SSR, R%d", RN(ir) ); break;
nkeynes@1
    78
                        case 4: snprintf( buf, len, "STC     SPC, R%d", RN(ir) ); break;
nkeynes@1
    79
                        case 8: case 9: case 10: case 11: case 12: case 13: case 14:
nkeynes@1
    80
                        case 15:snprintf( buf, len, "STC     R%d_bank, R%d", RN_BANK(ir), RN(ir) ); break;
nkeynes@1
    81
                        default: UNIMP(ir);
nkeynes@1
    82
                    }
nkeynes@1
    83
                    break;
nkeynes@1
    84
                case 3:
nkeynes@1
    85
                    switch( (ir&0x00F0)>>4 ) {
nkeynes@1
    86
                        case 0: snprintf( buf, len, "BSRF    R%d", RN(ir) ); break;
nkeynes@1
    87
                        case 2: snprintf( buf, len, "BRAF    R%d", RN(ir) ); break;
nkeynes@1
    88
                        case 8: snprintf( buf, len, "PREF    [R%d]", RN(ir) ); break;
nkeynes@1
    89
                        case 9: snprintf( buf, len, "OCBI    [R%d]", RN(ir) ); break;
nkeynes@1
    90
                        case 10:snprintf( buf, len, "OCBP    [R%d]", RN(ir) ); break;
nkeynes@1
    91
                        case 11:snprintf( buf, len, "OCBWB   [R%d]", RN(ir) ); break;
nkeynes@1
    92
                        case 12:snprintf( buf, len, "MOVCA.L R0, [R%d]", RN(ir) ); break;
nkeynes@1
    93
                        default: UNIMP(ir);
nkeynes@1
    94
                    }
nkeynes@1
    95
                    break;
nkeynes@1
    96
                case 4: snprintf( buf, len, "MOV.B   R%d, [R0+R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
    97
                case 5: snprintf( buf, len, "MOV.W   R%d, [R0+R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
    98
                case 6: snprintf( buf, len, "MOV.L   R%d, [R0+R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
    99
                case 7: snprintf( buf, len, "MUL.L   R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   100
                case 8:
nkeynes@1
   101
                    switch( (ir&0x0FF0)>>4 ) {
nkeynes@1
   102
                        case 0: snprintf( buf, len, "CLRT    " ); break;
nkeynes@1
   103
                        case 1: snprintf( buf, len, "SETT    " ); break;
nkeynes@1
   104
                        case 2: snprintf( buf, len, "CLRMAC  " ); break;
nkeynes@1
   105
                        case 3: snprintf( buf, len, "LDTLB   " ); break;
nkeynes@1
   106
                        case 4: snprintf( buf, len, "CLRS    " ); break;
nkeynes@1
   107
                        case 5: snprintf( buf, len, "SETS    " ); break;
nkeynes@1
   108
                        default: UNIMP(ir);
nkeynes@1
   109
                    }
nkeynes@1
   110
                    break;
nkeynes@1
   111
                case 9:
nkeynes@1
   112
                    if( (ir&0x00F0) == 0x20 )
nkeynes@1
   113
                        snprintf( buf, len, "MOVT    R%d", RN(ir) );
nkeynes@1
   114
                    else if( ir == 0x0019 )
nkeynes@1
   115
                        snprintf( buf, len, "DIV0U   " );
nkeynes@1
   116
                    else if( ir == 0x0009 )
nkeynes@1
   117
                        snprintf( buf, len, "NOP     " );
nkeynes@1
   118
                    else UNIMP(ir);
nkeynes@1
   119
                    break;
nkeynes@1
   120
                case 10:
nkeynes@1
   121
                    switch( (ir&0x00F0) >> 4 ) {
nkeynes@1
   122
                        case 0: snprintf( buf, len, "STS     MACH, R%d", RN(ir) ); break;
nkeynes@1
   123
                        case 1: snprintf( buf, len, "STS     MACL, R%d", RN(ir) ); break;
nkeynes@1
   124
                        case 2: snprintf( buf, len, "STS     PR, R%d", RN(ir) ); break;
nkeynes@1
   125
                        case 3: snprintf( buf, len, "STC     SGR, R%d", RN(ir) ); break;
nkeynes@1
   126
                        case 5: snprintf( buf, len, "STS     FPUL, R%d", RN(ir) ); break;
nkeynes@1
   127
                        case 6: snprintf( buf, len, "STS     FPSCR, R%d", RN(ir) ); break;
nkeynes@1
   128
                        case 15:snprintf( buf, len, "STC     DBR, R%d", RN(ir) ); break;
nkeynes@1
   129
                        default: UNIMP(ir);
nkeynes@1
   130
                    }
nkeynes@1
   131
                    break;
nkeynes@1
   132
                case 11:
nkeynes@1
   133
                    switch( (ir&0x0FF0)>>4 ) {
nkeynes@1
   134
                        case 0: snprintf( buf, len, "RTS     " ); break;
nkeynes@1
   135
                        case 1: snprintf( buf, len, "SLEEP   " ); break;
nkeynes@1
   136
                        case 2: snprintf( buf, len, "RTE     " ); break;
nkeynes@1
   137
                        default:UNIMP(ir);
nkeynes@1
   138
                    }
nkeynes@1
   139
                    break;
nkeynes@1
   140
                case 12:snprintf( buf, len, "MOV.B   [R0+R%d], R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   141
                case 13:snprintf( buf, len, "MOV.W   [R0+R%d], R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   142
                case 14:snprintf( buf, len, "MOV.L   [R0+R%d], R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   143
                case 15:snprintf( buf, len, "MAC.L   [R%d++], [R%d++]", RM(ir), RN(ir) ); break;
nkeynes@1
   144
                default: UNIMP(ir);
nkeynes@1
   145
            }
nkeynes@1
   146
            break;
nkeynes@1
   147
        case 1: /* 0001nnnnmmmmdddd */
nkeynes@1
   148
            snprintf( buf, len, "MOV.L   R%d, [R%d%+d]", RM(ir), RN(ir), DISP4(ir)<<2 ); break;
nkeynes@1
   149
        case 2: /* 0010nnnnmmmmxxxx */
nkeynes@1
   150
            switch( ir&0x000F ) {
nkeynes@1
   151
                case 0: snprintf( buf, len, "MOV.B   R%d, [R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
   152
                case 1: snprintf( buf, len, "MOV.W   R%d, [R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
   153
                case 2: snprintf( buf, len, "MOV.L   R%d, [R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
   154
                case 3: UNIMP(ir); break;
nkeynes@1
   155
                case 4: snprintf( buf, len, "MOV.B   R%d, [--R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
   156
                case 5: snprintf( buf, len, "MOV.W   R%d, [--R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
   157
                case 6: snprintf( buf, len, "MOV.L   R%d, [--R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
   158
                case 7: snprintf( buf, len, "DIV0S   R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   159
                case 8: snprintf( buf, len, "TST     R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   160
                case 9: snprintf( buf, len, "AND     R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   161
                case 10:snprintf( buf, len, "XOR     R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   162
                case 11:snprintf( buf, len, "OR      R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   163
                case 12:snprintf( buf, len, "CMP/STR R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   164
                case 13:snprintf( buf, len, "XTRCT   R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   165
                case 14:snprintf( buf, len, "MULU.W  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   166
                case 15:snprintf( buf, len, "MULS.W  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   167
            }
nkeynes@1
   168
            break;
nkeynes@1
   169
        case 3: /* 0011nnnnmmmmxxxx */
nkeynes@1
   170
            switch( ir&0x000F ) {
nkeynes@1
   171
                case 0: snprintf( buf, len, "CMP/EQ  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   172
                case 2: snprintf( buf, len, "CMP/HS  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   173
                case 3: snprintf( buf, len, "CMP/GE  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   174
                case 4: snprintf( buf, len, "DIV1    R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   175
                case 5: snprintf( buf, len, "DMULU.L R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   176
                case 6: snprintf( buf, len, "CMP/HI  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   177
                case 7: snprintf( buf, len, "CMP/GT  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   178
                case 8: snprintf( buf, len, "SUB     R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   179
                case 10:snprintf( buf, len, "SUBC    R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   180
                case 11:snprintf( buf, len, "SUBV    R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   181
                case 12:snprintf( buf, len, "ADD     R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   182
                case 13:snprintf( buf, len, "DMULS.L R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   183
                case 14:snprintf( buf, len, "ADDC    R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   184
                case 15:snprintf( buf, len, "ADDV    R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   185
                default: UNIMP(ir);
nkeynes@1
   186
            }
nkeynes@1
   187
            break;
nkeynes@1
   188
        case 4: /* 0100nnnnxxxxxxxx */
nkeynes@1
   189
            switch( ir&0x00FF ) {
nkeynes@1
   190
                case 0x00: snprintf( buf, len, "SHLL    R%d", RN(ir) ); break;
nkeynes@1
   191
                case 0x01: snprintf( buf, len, "SHLR    R%d", RN(ir) ); break;
nkeynes@1
   192
                case 0x02: snprintf( buf, len, "STS.L   MACH, [--R%d]", RN(ir) ); break;
nkeynes@1
   193
                case 0x03: snprintf( buf, len, "STC.L   SR, [--R%d]", RN(ir) ); break;
nkeynes@1
   194
                case 0x04: snprintf( buf, len, "ROTL    R%d", RN(ir) ); break;
nkeynes@1
   195
                case 0x05: snprintf( buf, len, "ROTR    R%d", RN(ir) ); break;
nkeynes@1
   196
                case 0x06: snprintf( buf, len, "LDS.L   [R%d++], MACH", RN(ir) ); break;
nkeynes@1
   197
                case 0x07: snprintf( buf, len, "LDC.L   [R%d++], SR", RN(ir) ); break;
nkeynes@1
   198
                case 0x08: snprintf( buf, len, "SHLL2   R%d", RN(ir) ); break;
nkeynes@1
   199
                case 0x09: snprintf( buf, len, "SHLR2   R%d", RN(ir) ); break;
nkeynes@1
   200
                case 0x0A: snprintf( buf, len, "LDS     R%d, MACH", RN(ir) ); break;
nkeynes@1
   201
                case 0x0B: snprintf( buf, len, "JSR     [R%d]", RN(ir) ); break;
nkeynes@1
   202
                case 0x0E: snprintf( buf, len, "LDC     R%d, SR", RN(ir) ); break;
nkeynes@1
   203
                case 0x10: snprintf( buf, len, "DT      R%d", RN(ir) ); break;
nkeynes@1
   204
                case 0x11: snprintf( buf, len, "CMP/PZ  R%d", RN(ir) ); break;
nkeynes@1
   205
                case 0x12: snprintf( buf, len, "STS.L   MACL, [--R%d]", RN(ir) ); break;
nkeynes@1
   206
                case 0x13: snprintf( buf, len, "STC.L   GBR, [--R%d]", RN(ir) ); break;
nkeynes@1
   207
                case 0x15: snprintf( buf, len, "CMP/PL  R%d", RN(ir) ); break;
nkeynes@1
   208
                case 0x16: snprintf( buf, len, "LDS.L   [R%d++], MACL", RN(ir) ); break;
nkeynes@1
   209
                case 0x17: snprintf( buf, len, "LDC.L   [R%d++], GBR", RN(ir) ); break;
nkeynes@1
   210
                case 0x18: snprintf( buf, len, "SHLL8   R%d", RN(ir) ); break;
nkeynes@1
   211
                case 0x19: snprintf( buf, len, "SHLR8   R%d", RN(ir) ); break;
nkeynes@1
   212
                case 0x1A: snprintf( buf, len, "LDS     R%d, MACL", RN(ir) ); break;
nkeynes@1
   213
                case 0x1B: snprintf( buf, len, "TAS.B   [R%d]", RN(ir) ); break;
nkeynes@1
   214
                case 0x1E: snprintf( buf, len, "LDC     R%d, GBR", RN(ir) ); break;
nkeynes@1
   215
                case 0x20: snprintf( buf, len, "SHAL    R%d", RN(ir) ); break;
nkeynes@1
   216
                case 0x21: snprintf( buf, len, "SHAR    R%d", RN(ir) ); break;
nkeynes@1
   217
                case 0x22: snprintf( buf, len, "STS.L   PR, [--R%d]", RN(ir) ); break;
nkeynes@1
   218
                case 0x23: snprintf( buf, len, "STC.L   VBR, [--R%d]", RN(ir) ); break;
nkeynes@1
   219
                case 0x24: snprintf( buf, len, "ROTCL   R%d", RN(ir) ); break;
nkeynes@1
   220
                case 0x25: snprintf( buf, len, "ROTCR   R%d", RN(ir) ); break;
nkeynes@1
   221
                case 0x26: snprintf( buf, len, "LDS.L   [R%d++], PR", RN(ir) ); break;
nkeynes@1
   222
                case 0x27: snprintf( buf, len, "LDC.L   [R%d++], VBR", RN(ir) ); break;
nkeynes@1
   223
                case 0x28: snprintf( buf, len, "SHLL16  R%d", RN(ir) ); break;
nkeynes@1
   224
                case 0x29: snprintf( buf, len, "SHLR16  R%d", RN(ir) ); break;
nkeynes@1
   225
                case 0x2A: snprintf( buf, len, "LDS     R%d, PR", RN(ir) ); break;
nkeynes@1
   226
                case 0x2B: snprintf( buf, len, "JMP     [R%d]", RN(ir) ); break;
nkeynes@1
   227
                case 0x2E: snprintf( buf, len, "LDC     R%d, VBR", RN(ir) ); break;
nkeynes@1
   228
                case 0x32: snprintf( buf, len, "STC.L   SGR, [--R%d]", RN(ir) ); break;
nkeynes@1
   229
                case 0x33: snprintf( buf, len, "STC.L   SSR, [--R%d]", RN(ir) ); break;
nkeynes@1
   230
                case 0x37: snprintf( buf, len, "LDC.L   [R%d++], SSR", RN(ir) ); break;
nkeynes@1
   231
                case 0x3E: snprintf( buf, len, "LDC     R%d, SSR", RN(ir) ); break;
nkeynes@1
   232
                case 0x43: snprintf( buf, len, "STC.L   SPC, [--R%d]", RN(ir) ); break;
nkeynes@1
   233
                case 0x47: snprintf( buf, len, "LDC.L   [R%d++], SPC", RN(ir) ); break;
nkeynes@1
   234
                case 0x4E: snprintf( buf, len, "LDC     R%d, SPC", RN(ir) ); break;
nkeynes@1
   235
                case 0x52: snprintf( buf, len, "STS.L   FPUL, [--R%d]", RN(ir) ); break;
nkeynes@1
   236
                case 0x56: snprintf( buf, len, "LDS.L   [R%d++], FPUL", RN(ir) ); break;
nkeynes@1
   237
                case 0x5A: snprintf( buf, len, "LDS     R%d, FPUL", RN(ir) ); break;
nkeynes@1
   238
                case 0x62: snprintf( buf, len, "STS.L   FPSCR, [--R%d]", RN(ir) ); break;
nkeynes@1
   239
                case 0x66: snprintf( buf, len, "LDS.L   [R%d++], FPSCR", RN(ir) ); break;
nkeynes@1
   240
                case 0x6A: snprintf( buf, len, "LDS     R%d, FPSCR", RN(ir) ); break;
nkeynes@1
   241
                case 0xF2: snprintf( buf, len, "STC.L   DBR, [--R%d]", RN(ir) ); break;
nkeynes@1
   242
                case 0xF6: snprintf( buf, len, "LDC.L   [R%d++], DBR", RN(ir) ); break;
nkeynes@1
   243
                case 0xFA: snprintf( buf, len, "LDC     R%d, DBR", RN(ir) ); break;
nkeynes@1
   244
                case 0x83: case 0x93: case 0xA3: case 0xB3: case 0xC3: case 0xD3: case 0xE3:
nkeynes@1
   245
                case 0xF3: snprintf( buf, len, "STC.L   R%d_BANK, [--R%d]", RN_BANK(ir), RN(ir) ); break;
nkeynes@1
   246
                case 0x87: case 0x97: case 0xA7: case 0xB7: case 0xC7: case 0xD7: case 0xE7:
nkeynes@1
   247
                case 0xF7: snprintf( buf, len, "LDC.L   [R%d++], R%d_BANK", RN(ir), RN_BANK(ir) ); break; 
nkeynes@1
   248
                case 0x8E: case 0x9E: case 0xAE: case 0xBE: case 0xCE: case 0xDE: case 0xEE:
nkeynes@1
   249
                case 0xFE: snprintf( buf, len, "LDC     R%d, R%d_BANK", RN(ir), RN_BANK(ir) ); break;
nkeynes@1
   250
                default:
nkeynes@1
   251
                    if( (ir&0x000F) == 0x0F ) {
nkeynes@1
   252
                        snprintf( buf, len, "MAC.W   [R%d++], [R%d++]", RM(ir), RN(ir) );
nkeynes@1
   253
                    } else if( (ir&0x000F) == 0x0C ) {
nkeynes@1
   254
                        snprintf( buf, len, "SHAD    R%d, R%d", RM(ir), RN(ir) );
nkeynes@1
   255
                    } else if( (ir&0x000F) == 0x0D ) {
nkeynes@1
   256
                        snprintf( buf, len, "SHLD    R%d, R%d", RM(ir), RN(ir) );
nkeynes@1
   257
                    } else UNIMP(ir);
nkeynes@1
   258
            }
nkeynes@1
   259
            break;
nkeynes@1
   260
        case 5: /* 0101nnnnmmmmdddd */
nkeynes@1
   261
            snprintf( buf, len, "MOV.L   [R%d%+d], R%d", RM(ir), DISP4(ir)<<2, RN(ir) ); break;
nkeynes@1
   262
        case 6: /* 0110xxxxxxxxxxxx */
nkeynes@1
   263
            switch( ir&0x000f ) {
nkeynes@1
   264
                case 0: snprintf( buf, len, "MOV.B   [R%d], R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   265
                case 1: snprintf( buf, len, "MOV.W   [R%d], R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   266
                case 2: snprintf( buf, len, "MOV.L   [R%d], R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   267
                case 3: snprintf( buf, len, "MOV     R%d, R%d", RM(ir), RN(ir) );   break;
nkeynes@1
   268
                case 4: snprintf( buf, len, "MOV.B   [R%d++], R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   269
                case 5: snprintf( buf, len, "MOV.W   [R%d++], R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   270
                case 6: snprintf( buf, len, "MOV.L   [R%d++], R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   271
                case 7: snprintf( buf, len, "NOT     R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   272
                case 8: snprintf( buf, len, "SWAP.B  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   273
                case 9: snprintf( buf, len, "SWAP.W  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   274
                case 10:snprintf( buf, len, "NEGC    R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   275
                case 11:snprintf( buf, len, "NEG     R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   276
                case 12:snprintf( buf, len, "EXTU.B  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   277
                case 13:snprintf( buf, len, "EXTU.W  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   278
                case 14:snprintf( buf, len, "EXTS.B  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   279
                case 15:snprintf( buf, len, "EXTS.W  R%d, R%d", RM(ir), RN(ir) ); break;
nkeynes@1
   280
            }
nkeynes@1
   281
            break;
nkeynes@1
   282
        case 7: /* 0111nnnniiiiiiii */
nkeynes@1
   283
            snprintf( buf, len, "ADD    #%d, R%d", SIGNEXT8(ir&0x00FF), RN(ir) ); break;
nkeynes@1
   284
        case 8: /* 1000xxxxxxxxxxxx */
nkeynes@1
   285
            switch( (ir&0x0F00) >> 8 ) {
nkeynes@1
   286
                case 0: snprintf( buf, len, "MOV.B   R0, [R%d%+d]", RM(ir), DISP4(ir) ); break;
nkeynes@1
   287
                case 1: snprintf( buf, len, "MOV.W   R0, [R%d%+d]", RM(ir), DISP4(ir)<<1 ); break;
nkeynes@1
   288
                case 4: snprintf( buf, len, "MOV.B   [R%d%+d], R0", RM(ir), DISP4(ir) ); break;
nkeynes@1
   289
                case 5: snprintf( buf, len, "MOV.W   [R%d%+d], R0", RM(ir), DISP4(ir)<<1 ); break;
nkeynes@1
   290
                case 8: snprintf( buf, len, "CMP/EQ  #%d, R0", IMM8(ir) ); break;
nkeynes@1
   291
                case 9: snprintf( buf, len, "BT      $%xh", (PCDISP8(ir)<<1)+pc+4 ); break;
nkeynes@1
   292
                case 11:snprintf( buf, len, "BF      $%xh", (PCDISP8(ir)<<1)+pc+4 ); break;
nkeynes@1
   293
                case 13:snprintf( buf, len, "BT/S    $%xh", (PCDISP8(ir)<<1)+pc+4 ); break;
nkeynes@1
   294
                case 15:snprintf( buf, len, "BF/S    $%xh", (PCDISP8(ir)<<1)+pc+4 ); break;
nkeynes@1
   295
                default: UNIMP(ir);
nkeynes@1
   296
            }
nkeynes@1
   297
            break;
nkeynes@1
   298
        case 9: /* 1001xxxxxxxxxxxx */
nkeynes@1
   299
            snprintf( buf, len, "MOV.W   [$%xh], R%-2d ; <- #%08x", (DISP8(ir)<<1)+pc+4, RN(ir),
nkeynes@10
   300
                      sh4_read_word( (DISP8(ir)<<1)+pc+4 ) ); break;
nkeynes@1
   301
        case 10:/* 1010xxxxxxxxxxxx */
nkeynes@1
   302
            snprintf( buf, len, "BRA     $%xh", (DISP12(ir)<<1)+pc+4 ); break;
nkeynes@1
   303
        case 11:/* 1011xxxxxxxxxxxx */
nkeynes@1
   304
            snprintf( buf, len, "BSR     $%xh", (DISP12(ir)<<1)+pc+4 ); break;            
nkeynes@1
   305
        case 12:/* 1100xxxxdddddddd */
nkeynes@1
   306
            switch( (ir&0x0F00)>>8 ) {
nkeynes@1
   307
                case 0: snprintf( buf, len, "MOV.B   R0, [GBR%+d]", DISP8(ir) ); break;
nkeynes@1
   308
                case 1: snprintf( buf, len, "MOV.W   R0, [GBR%+d]", DISP8(ir)<<1 ); break;
nkeynes@1
   309
                case 2: snprintf( buf, len, "MOV.L   R0, [GBR%+d]", DISP8(ir)<<2 ); break;
nkeynes@1
   310
                case 3: snprintf( buf, len, "TRAPA   #%d", UIMM8(ir) ); break;
nkeynes@1
   311
                case 4: snprintf( buf, len, "MOV.B   [GBR%+d], R0", DISP8(ir) ); break;
nkeynes@1
   312
                case 5: snprintf( buf, len, "MOV.W   [GBR%+d], R0", DISP8(ir)<<1 ); break;
nkeynes@1
   313
                case 6: snprintf( buf, len, "MOV.L   [GBR%+d], R0", DISP8(ir)<<2 ); break;
nkeynes@1
   314
                case 7: snprintf( buf, len, "MOVA    $%xh, R0", (DISP8(ir)<<2)+(pc&~3)+4 ); break;
nkeynes@1
   315
                case 8: snprintf( buf, len, "TST     #%02Xh, R0", UIMM8(ir) ); break;
nkeynes@1
   316
                case 9: snprintf( buf, len, "AND     #%02Xh, R0", UIMM8(ir) ); break;
nkeynes@1
   317
                case 10:snprintf( buf, len, "XOR     #%02Xh, R0", UIMM8(ir) ); break;
nkeynes@1
   318
                case 11:snprintf( buf, len, "OR      #%02Xh, R0", UIMM8(ir) ); break;
nkeynes@1
   319
                case 12:snprintf( buf, len, "TST.B   #%02Xh, [R0+GBR]", UIMM8(ir) ); break;
nkeynes@1
   320
                case 13:snprintf( buf, len, "AND.B   #%02Xh, [R0+GBR]", UIMM8(ir) ); break;
nkeynes@1
   321
                case 14:snprintf( buf, len, "XOR.B   #%02Xh, [R0+GBR]", UIMM8(ir) ); break;
nkeynes@1
   322
                case 15:snprintf( buf, len, "OR.B    #%02Xh, [R0+GBR]", UIMM8(ir) ); break;
nkeynes@1
   323
            }
nkeynes@1
   324
            break;
nkeynes@1
   325
        case 13:/* 1101xxxxxxxxxxxx */
nkeynes@1
   326
            snprintf( buf, len, "MOV.L   [$%xh], R%-2d ; <- #%08x", (DISP8(ir)<<2)+(pc&~3)+4, RN(ir),
nkeynes@10
   327
                      sh4_read_long( (DISP8(ir)<<2)+(pc&~3)+4 ) ); break;
nkeynes@1
   328
        case 14:/* 1110xxxxxxxxxxxx */
nkeynes@1
   329
            snprintf( buf, len, "MOV     #%d, R%d", DISP8(ir), RN(ir)); break;
nkeynes@1
   330
        case 15:/* 1111xxxxxxxxxxxx */
nkeynes@1
   331
            switch( ir&0x000F ) {
nkeynes@1
   332
                case 0: snprintf( buf, len, "FADD    FR%d, FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   333
                case 1: snprintf( buf, len, "FSUB    FR%d, FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   334
                case 2: snprintf( buf, len, "FMUL    FR%d, FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   335
                case 3: snprintf( buf, len, "FDIV    FR%d, FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   336
                case 4: snprintf( buf, len, "FCMP/EQ FR%d, FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   337
                case 5: snprintf( buf, len, "FCMP/GT FR%d, FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   338
                case 6: snprintf( buf, len, "FMOV.S  [R%d+R0], FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   339
                case 7: snprintf( buf, len, "FMOV.S  FR%d, [R%d+R0]", RM(ir), RN(ir) ); break;
nkeynes@1
   340
                case 8: snprintf( buf, len, "FMOV.S  [R%d], FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   341
                case 9: snprintf( buf, len, "FMOV.S  [R%d++], FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   342
                case 10:snprintf( buf, len, "FMOV.S  FR%d, [R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
   343
                case 11:snprintf( buf, len, "FMOV.S  FR%d, [--R%d]", RM(ir), RN(ir) ); break;
nkeynes@1
   344
                case 12:snprintf( buf, len, "FMOV    FR%d, FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   345
                case 13:
nkeynes@1
   346
                    switch( (ir&0x00F0) >> 4 ) {
nkeynes@1
   347
                        case 0: snprintf( buf, len, "FSTS    FPUL, FR%d", RN(ir) ); break;
nkeynes@1
   348
                        case 1: snprintf( buf, len, "FLDS    FR%d, FPUL", RN(ir) ); break;
nkeynes@1
   349
                        case 2: snprintf( buf, len, "FLOAT   FPUL, FR%d", RN(ir) ); break;
nkeynes@1
   350
                        case 3: snprintf( buf, len, "FTRC    FR%d, FPUL", RN(ir) ); break;
nkeynes@1
   351
                        case 4: snprintf( buf, len, "FNEG    FR%d", RN(ir) ); break;
nkeynes@1
   352
                        case 5: snprintf( buf, len, "FABS    FR%d", RN(ir) ); break;
nkeynes@1
   353
                        case 6: snprintf( buf, len, "FSQRT   FR%d", RN(ir) ); break;
nkeynes@2
   354
                        case 7: snprintf( buf, len, "FSRRA   FR%d", RN(ir) ); break;
nkeynes@1
   355
                        case 8: snprintf( buf, len, "FLDI0   FR%d", RN(ir) ); break;
nkeynes@1
   356
                        case 9: snprintf( buf, len, "FLDI1   FR%d", RN(ir) ); break;
nkeynes@1
   357
                        case 10:snprintf( buf, len, "FCNVSD  FPUL, DR%d", RN(ir)>>1 ); break;
nkeynes@1
   358
                        case 11:snprintf( buf, len, "FCNVDS  DR%d, FPUL", RN(ir)>>1 ); break;
nkeynes@1
   359
                        case 14:snprintf( buf, len, "FIPR    FV%d, FV%d", FVM(ir), FVN(ir) ); break;
nkeynes@1
   360
                        case 15:
nkeynes@2
   361
                            if( (ir & 0x0300) == 0x0100 )
nkeynes@1
   362
                                snprintf( buf, len, "FTRV    XMTRX,FV%d", FVN(ir) );
nkeynes@2
   363
                            else if( (ir & 0x0100) == 0 )
nkeynes@2
   364
                                snprintf( buf, len, "FSCA    FPUL, DR%d", RN(ir) );
nkeynes@1
   365
                            else if( ir == 0xFBFD )
nkeynes@1
   366
                                snprintf( buf, len, "FRCHG   " );
nkeynes@1
   367
                            else if( ir == 0xF3FD )
nkeynes@1
   368
                                snprintf( buf, len, "FSCHG   " );
nkeynes@2
   369
                            else UNIMP(ir);
nkeynes@1
   370
                            break;
nkeynes@1
   371
                        default: UNIMP(ir);
nkeynes@1
   372
                    }
nkeynes@1
   373
                    break;
nkeynes@1
   374
                case 14:snprintf( buf, len, "FMAC    FR0, FR%d, FR%d", RM(ir), RN(ir) ); break;
nkeynes@1
   375
                default: UNIMP(ir);
nkeynes@1
   376
            }
nkeynes@1
   377
            break;
nkeynes@1
   378
    }
nkeynes@1
   379
    return pc+2;
nkeynes@1
   380
}
nkeynes@1
   381
nkeynes@1
   382
nkeynes@54
   383
void sh4_disasm_region( const gchar *filename, int from, int to )
nkeynes@1
   384
{
nkeynes@1
   385
    int pc;
nkeynes@1
   386
    char buf[80];
nkeynes@11
   387
    char opcode[16];
nkeynes@54
   388
    FILE *f;
nkeynes@1
   389
    
nkeynes@54
   390
    f = fopen( filename, "w" );
nkeynes@1
   391
    for( pc = from; pc < to; pc+=2 ) {
nkeynes@1
   392
        buf[0] = '\0';
nkeynes@1
   393
        sh4_disasm_instruction( pc,
nkeynes@11
   394
                                buf, sizeof(buf), opcode );
nkeynes@54
   395
        fprintf( f, "  %08x:  %s  %s\n", pc, opcode, buf );
nkeynes@1
   396
    }
nkeynes@54
   397
    fclose(f);
nkeynes@1
   398
}
.