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