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 Sun Jan 01 08:08:40 2006 +0000 (18 years ago)
permissions -rw-r--r--
last change Add (partial) DMAC implementation
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
}
.