Search
lxdream.org :: lxdream/src/sh4/sh4dasm.in
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4dasm.in
changeset 1300:d18488c8668b
prev1190:2e66e9053037
author nkeynes
date Wed May 27 08:46:29 2015 +1000 (6 years ago)
permissions -rw-r--r--
last change Add support for extracting the ELF symbol table and printing symbol names
alongside the SH4 disassembly
file annotate diff log raw
nkeynes@359
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@359
     3
 * 
nkeynes@359
     4
 * SH4 CPU definition and disassembly functions
nkeynes@359
     5
 *
nkeynes@359
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@359
     7
 *
nkeynes@359
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@359
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@359
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@359
    11
 * (at your option) any later version.
nkeynes@359
    12
 *
nkeynes@359
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@359
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@359
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@359
    16
 * GNU General Public License for more details.
nkeynes@359
    17
 */
nkeynes@359
    18
nkeynes@730
    19
#include "sh4/sh4core.h"
nkeynes@730
    20
#include "sh4/sh4dasm.h"
nkeynes@963
    21
#include "sh4/mmu.h"
nkeynes@359
    22
#include "mem.h"
nkeynes@359
    23
nkeynes@1300
    24
#include <string.h>
nkeynes@1300
    25
nkeynes@359
    26
#define UNIMP(ir) snprintf( buf, len, "???     " )
nkeynes@359
    27
nkeynes@597
    28
uint32_t sh4_disasm_instruction( sh4vma_t pc, char *buf, int len, char *opcode )
nkeynes@359
    29
{
nkeynes@597
    30
    sh4addr_t addr = mmu_vma_to_phys_disasm(pc);
nkeynes@939
    31
    uint32_t tmp;
nkeynes@1190
    32
    
nkeynes@1190
    33
    if( addr == MMU_VMA_ERROR ) {
nkeynes@1190
    34
        sprintf( opcode, "?? ??" );
nkeynes@1190
    35
        snprintf( buf, len, "???" );
nkeynes@1190
    36
        return pc+2;
nkeynes@1190
    37
    }
nkeynes@1190
    38
    
nkeynes@939
    39
    uint16_t ir = ext_address_space[addr>>12]->read_word(addr);
nkeynes@359
    40
nkeynes@359
    41
#define UNDEF(ir) snprintf( buf, len, "????    " );
nkeynes@359
    42
#define RN(ir) ((ir&0x0F00)>>8)
nkeynes@359
    43
#define RN_BANK(ir) ((ir&0x0070)>>4)
nkeynes@359
    44
#define RM(ir) ((ir&0x00F0)>>4)
nkeynes@359
    45
#define DISP4(ir) (ir&0x000F) /* 4-bit displacements are *not* sign extended */
nkeynes@359
    46
#define DISP8(ir) (ir&0x00FF)
nkeynes@359
    47
#define PCDISP8(ir) SIGNEXT8(ir&0x00FF)
nkeynes@359
    48
#define UIMM8(ir) (ir&0x00FF)
nkeynes@359
    49
#define IMM8(ir) SIGNEXT8(ir&0x00FF)
nkeynes@359
    50
#define DISP12(ir) SIGNEXT12(ir&0x0FFF)
nkeynes@359
    51
#define FVN(ir) ((ir&0x0C00)>>10)
nkeynes@359
    52
#define FVM(ir) ((ir&0x0300)>>8)
nkeynes@359
    53
nkeynes@359
    54
    sprintf( opcode, "%02X %02X", ir&0xFF, ir>>8 );
nkeynes@359
    55
nkeynes@359
    56
%%
nkeynes@359
    57
ADD Rm, Rn       {: snprintf( buf, len, "ADD     R%d, R%d", Rm, Rn ); :}
nkeynes@359
    58
ADD #imm, Rn     {: snprintf( buf, len, "ADD     #%d, R%d", imm, Rn ); :}
nkeynes@359
    59
ADDC Rm, Rn      {: snprintf( buf, len, "ADDC    R%d, R%d", Rm, Rn ); :}
nkeynes@359
    60
ADDV Rm, Rn      {: snprintf( buf, len, "ADDV    R%d, R%d", Rm, Rn ); :}
nkeynes@359
    61
AND Rm, Rn       {: snprintf( buf, len, "AND     R%d, R%d", Rm, Rn ); :}
nkeynes@595
    62
AND #imm, R0     {: snprintf( buf, len, "AND     #%d, R0", imm ); :}
nkeynes@359
    63
AND.B #imm, @(R0, GBR) {: snprintf( buf, len, "AND.B   #%d, @(R0, GBR)", imm ); :}
nkeynes@359
    64
BF disp          {: snprintf( buf, len, "BF      $%xh", disp+pc+4 ); :}
nkeynes@359
    65
BF/S disp        {: snprintf( buf, len, "BF/S    $%xh", disp+pc+4 ); :}
nkeynes@359
    66
BRA disp         {: snprintf( buf, len, "BRA     $%xh", disp+pc+4 ); :}
nkeynes@359
    67
BRAF Rn          {: snprintf( buf, len, "BRAF    R%d", Rn ); :}
nkeynes@359
    68
BSR disp         {: snprintf( buf, len, "BSR     $%xh", disp+pc+4 ); :}
nkeynes@359
    69
BSRF Rn          {: snprintf( buf, len, "BSRF    R%d", Rn ); :}
nkeynes@359
    70
BT disp          {: snprintf( buf, len, "BT      $%xh", disp+pc+4 ); :}
nkeynes@359
    71
BT/S disp        {: snprintf( buf, len, "BT/S    $%xh", disp+pc+4 ); :}
nkeynes@359
    72
CLRMAC           {: snprintf( buf, len, "CLRMAC  " ); :}
nkeynes@359
    73
CLRS             {: snprintf( buf, len, "CLRS    " ); :}
nkeynes@359
    74
CLRT             {: snprintf( buf, len, "CLRT    " ); :}
nkeynes@359
    75
CMP/EQ Rm, Rn    {: snprintf( buf, len, "CMP/EQ  R%d, R%d", Rm, Rn ); :}
nkeynes@359
    76
CMP/EQ #imm, R0  {: snprintf( buf, len, "CMP/EQ  #%d, R0", imm ); :}
nkeynes@359
    77
CMP/GE Rm, Rn    {: snprintf( buf, len, "CMP/GE  R%d, R%d", Rm, Rn ); :}
nkeynes@359
    78
CMP/GT Rm, Rn    {: snprintf( buf, len, "CMP/GT  R%d, R%d", Rm, Rn ); :}
nkeynes@359
    79
CMP/HI Rm, Rn    {: snprintf( buf, len, "CMP/HI  R%d, R%d", Rm, Rn ); :}
nkeynes@359
    80
CMP/HS Rm, Rn    {: snprintf( buf, len, "CMP/HS  R%d, R%d", Rm, Rn ); :}
nkeynes@359
    81
CMP/PL Rn        {: snprintf( buf, len, "CMP/PL  R%d", Rn ); :}
nkeynes@359
    82
CMP/PZ Rn        {: snprintf( buf, len, "CMP/PZ  R%d", Rn ); :}
nkeynes@359
    83
CMP/STR Rm, Rn   {: snprintf( buf, len, "CMP/STR R%d, R%d", Rm, Rn ); :}
nkeynes@359
    84
DIV0S Rm, Rn     {: snprintf( buf, len, "DIV0S   R%d, R%d", Rm, Rn ); :}
nkeynes@359
    85
DIV0U            {: snprintf( buf, len, "DIV0U   " ); :}
nkeynes@359
    86
DIV1 Rm, Rn      {: snprintf( buf, len, "DIV1    R%d, R%d", Rm, Rn ); :}
nkeynes@359
    87
DMULS.L Rm, Rn   {: snprintf( buf, len, "DMULS.L R%d, R%d", Rm, Rn ); :}
nkeynes@359
    88
DMULU.L RM, Rn   {: snprintf( buf, len, "DMULU.L R%d, R%d", Rm, Rn ); :}
nkeynes@359
    89
DT Rn            {: snprintf( buf, len, "DT      R%d", Rn ); :}
nkeynes@359
    90
EXTS.B Rm, Rn    {: snprintf( buf, len, "EXTS.B  R%d, R%d", Rm, Rn ); :}
nkeynes@359
    91
EXTS.W Rm, Rn    {: snprintf( buf, len, "EXTS.W  R%d, R%d", Rm, Rn ); :}
nkeynes@359
    92
EXTU.B Rm, Rn    {: snprintf( buf, len, "EXTU.B  R%d, R%d", Rm, Rn ); :}
nkeynes@359
    93
EXTU.W Rm, Rn    {: snprintf( buf, len, "EXTU.W  R%d, R%d", Rm, Rn ); :}
nkeynes@359
    94
FABS FRn         {: snprintf( buf, len, "FABS    FR%d", FRn ); :}
nkeynes@359
    95
FADD FRm, FRn    {: snprintf( buf, len, "FADD    FR%d, FR%d", FRm, FRn ); :}
nkeynes@359
    96
FCMP/EQ FRm, FRn {: snprintf( buf, len, "FCMP/EQ FR%d, FR%d", FRm, FRn ); :}
nkeynes@873
    97
FCMP/GT FRm, FRn {: snprintf( buf, len, "FCMP/GT FR%d, FR%d", FRm, FRn ); :}
nkeynes@359
    98
FCNVDS FRm, FPUL {: snprintf( buf, len, "FCNVDS  FR%d, FPUL", FRm ); :}
nkeynes@359
    99
FCNVSD FPUL, FRn {: snprintf( buf, len, "FCNVSD  FPUL, FR%d", FRn ); :}
nkeynes@359
   100
FDIV FRm, FRn    {: snprintf( buf, len, "FDIV    FR%d, FR%d", FRm, FRn ); :}
nkeynes@359
   101
FIPR FVm, FVn    {: snprintf( buf, len, "FIPR    FV%d, FV%d", FVm, FVn ); :}
nkeynes@359
   102
FLDS FRm, FPUL   {: snprintf( buf, len, "FLDS    FR%d, FPUL", FRm ); :}
nkeynes@359
   103
FLDI0 FRn        {: snprintf( buf, len, "FLDI0   FR%d", FRn ); :}
nkeynes@359
   104
FLDI1 FRn        {: snprintf( buf, len, "FLDI1   FR%d", FRn ); :}
nkeynes@359
   105
FLOAT FPUL, FRn  {: snprintf( buf, len, "FLOAT   FPUL, FR%d", FRn ); :}
nkeynes@359
   106
FMAC FR0, FRm, FRn {: snprintf( buf, len, "FMAC    FR0, FR%d, FR%d", FRm, FRn ); :}
nkeynes@359
   107
FMOV FRm, FRn    {: snprintf( buf, len, "FMOV    FR%d, FR%d", FRm, FRn ); :}
nkeynes@359
   108
FMOV FRm, @Rn    {: snprintf( buf, len, "FMOV    FR%d, @R%d", FRm, Rn ); :}
nkeynes@359
   109
FMOV FRm, @-Rn   {: snprintf( buf, len, "FMOV    FR%d, @-R%d", FRm, Rn ); :}
nkeynes@359
   110
FMOV FRm, @(R0, Rn) {: snprintf( buf, len, "FMOV    FR%d, @(R0, R%d)", FRm, Rn ); :}
nkeynes@359
   111
FMOV @Rm, FRn    {: snprintf( buf, len, "FMOV    @R%d, FR%d", Rm, FRn ); :}
nkeynes@359
   112
FMOV @Rm+, FRn   {: snprintf( buf, len, "FMOV    @R%d+, FR%d", Rm, FRn ); :}
nkeynes@359
   113
FMOV @(R0, Rm), FRn {: snprintf( buf, len, "FMOV    @(R0, R%d), FR%d", Rm, FRn ); :}
nkeynes@430
   114
FMUL FRm, FRn    {: snprintf( buf, len, "FMUL    FR%d, FR%d", FRm, FRn ); :}
nkeynes@359
   115
FNEG FRn         {: snprintf( buf, len, "FNEG    FR%d", FRn ); :}
nkeynes@359
   116
FRCHG            {: snprintf( buf, len, "FRCHG   " ); :}
nkeynes@359
   117
FSCA FPUL, FRn   {: snprintf( buf, len, "FSCA    FPUL, FR%d", FRn ); :}
nkeynes@359
   118
FSCHG            {: snprintf( buf, len, "FSCHG   " ); :}
nkeynes@359
   119
FSQRT FRn        {: snprintf( buf, len, "FSQRT   FR%d", FRn ); :}
nkeynes@359
   120
FSRRA FRn        {: snprintf( buf, len, "FSRRA   FR%d", FRn ); :}
nkeynes@359
   121
FSTS FPUL, FRn   {: snprintf( buf, len, "FSTS    FPUL, FR%d", FRn ); :}
nkeynes@430
   122
FSUB FRm, FRn    {: snprintf( buf, len, "FSUB    FR%d, FR%d", FRm, FRn ); :}
nkeynes@359
   123
FTRC FRm, FPUL   {: snprintf( buf, len, "FTRC    FR%d, FPUL", FRm ); :}
nkeynes@359
   124
FTRV XMTRX, FVn  {: snprintf( buf, len, "FTRV    XMTRX, FV%d", FVn ); :}
nkeynes@359
   125
JMP @Rn          {: snprintf( buf, len, "JMP     @R%d", Rn ); :}
nkeynes@359
   126
JSR @Rn          {: snprintf( buf, len, "JSR     @R%d", Rn ); :}
nkeynes@359
   127
LDC Rm, GBR      {: snprintf( buf, len, "LDC     R%d, GBR", Rm ); :}
nkeynes@359
   128
LDC Rm, SR       {: snprintf( buf, len, "LDC     R%d, SR", Rm ); :}
nkeynes@359
   129
LDC Rm, VBR      {: snprintf( buf, len, "LDC     R%d, VBR", Rm ); :}
nkeynes@359
   130
LDC Rm, SSR      {: snprintf( buf, len, "LDC     R%d, SSR", Rm ); :}
nkeynes@359
   131
LDC Rm, SGR      {: snprintf( buf, len, "LDC     R%d, SGR", Rm ); :}
nkeynes@359
   132
LDC Rm, SPC      {: snprintf( buf, len, "LDC     R%d, SPC", Rm ); :}
nkeynes@359
   133
LDC Rm, DBR      {: snprintf( buf, len, "LDC     R%d, DBR", Rm ); :}
nkeynes@359
   134
LDC Rm, Rn_BANK  {: snprintf( buf, len, "LDC     R%d, R%d_BANK", Rm, Rn_BANK ); :}
nkeynes@359
   135
LDS Rm, FPSCR    {: snprintf( buf, len, "LDS     R%d, FPSCR", Rm ); :}
nkeynes@359
   136
LDS Rm, FPUL     {: snprintf( buf, len, "LDS     R%d, FPUL", Rm ); :}
nkeynes@359
   137
LDS Rm, MACH     {: snprintf( buf, len, "LDS     R%d, MACH", Rm ); :}
nkeynes@359
   138
LDS Rm, MACL     {: snprintf( buf, len, "LDS     R%d, MACL", Rm ); :}
nkeynes@359
   139
LDS Rm, PR       {: snprintf( buf, len, "LDS     R%d, PR", Rm ); :}
nkeynes@359
   140
LDC.L @Rm+, GBR  {: snprintf( buf, len, "LDC.L   @R%d+, GBR", Rm ); :}
nkeynes@359
   141
LDC.L @Rm+, SR   {: snprintf( buf, len, "LDC.L   @R%d+, SR", Rm ); :}
nkeynes@359
   142
LDC.L @Rm+, VBR  {: snprintf( buf, len, "LDC.L   @R%d+, VBR", Rm ); :}
nkeynes@359
   143
LDC.L @Rm+, SSR  {: snprintf( buf, len, "LDC.L   @R%d+, SSR", Rm ); :}
nkeynes@359
   144
LDC.L @Rm+, SGR  {: snprintf( buf, len, "LDC.L   @R%d+, SGR", Rm ); :}
nkeynes@359
   145
LDC.L @Rm+, SPC  {: snprintf( buf, len, "LDC.L   @R%d+, SPC", Rm ); :}
nkeynes@359
   146
LDC.L @Rm+, DBR  {: snprintf( buf, len, "LDC.L   @R%d+, DBR", Rm ); :}
nkeynes@359
   147
LDC.L @Rm+, Rn_BANK{: snprintf( buf, len, "LDC.L   @R%d+, @R%d+_BANK", Rm, Rn_BANK ); :}
nkeynes@359
   148
LDS.L @Rm+, FPSCR{: snprintf( buf, len, "LDS.L   @R%d+, FPSCR", Rm ); :}
nkeynes@359
   149
LDS.L @Rm+, FPUL {: snprintf( buf, len, "LDS.L   @R%d+, FPUL", Rm ); :}
nkeynes@359
   150
LDS.L @Rm+, MACH {: snprintf( buf, len, "LDS.L   @R%d+, MACH", Rm ); :}
nkeynes@359
   151
LDS.L @Rm+, MACL {: snprintf( buf, len, "LDS.L   @R%d+, MACL", Rm ); :}
nkeynes@359
   152
LDS.L @Rm+, PR   {: snprintf( buf, len, "LDS.L   @R%d+, PR", Rm ); :}
nkeynes@359
   153
LDTLB            {: snprintf( buf, len, "LDTLB   " ); :}
nkeynes@359
   154
MAC.L @Rm+, @Rn+ {: snprintf( buf, len, "MAC.L   @R%d+, @R%d+", Rm, Rn ); :}
nkeynes@359
   155
MAC.W @Rm+, @Rn+ {: snprintf( buf, len, "MAC.W   @R%d+, @R%d+", Rm, Rn ); :}
nkeynes@359
   156
MOV Rm, Rn       {: snprintf( buf, len, "MOV     R%d, R%d", Rm, Rn ); :}
nkeynes@359
   157
MOV #imm, Rn     {: snprintf( buf, len, "MOV     #%d, R%d", imm, Rn ); :}
nkeynes@359
   158
MOV.B Rm, @Rn    {: snprintf( buf, len, "MOV.B   R%d, @R%d", Rm, Rn ); :}
nkeynes@359
   159
MOV.B Rm, @-Rn   {: snprintf( buf, len, "MOV.B   R%d, @-R%d", Rm, Rn ); :}
nkeynes@359
   160
MOV.B Rm, @(R0, Rn) {: snprintf( buf, len, "MOV.B   R%d, @(R0, R%d)", Rm, Rn ); :}
nkeynes@359
   161
MOV.B R0, @(disp, GBR) {: snprintf( buf, len, "MOV.B   R0, @(%d, GBR)", disp ); :}
nkeynes@359
   162
MOV.B R0, @(disp, Rn)  {: snprintf( buf, len, "MOV.B   R0, @(%d, R%d)", disp, Rn ); :}
nkeynes@359
   163
MOV.B @Rm, Rn    {: snprintf( buf, len, "MOV.B   @R%d, R%d", Rm, Rn ); :}
nkeynes@359
   164
MOV.B @Rm+, Rn   {: snprintf( buf, len, "MOV.B   @R%d+, R%d", Rm, Rn ); :}
nkeynes@359
   165
MOV.B @(R0, Rm), Rn {: snprintf( buf, len, "MOV.B   @(R0, R%d), R%d", Rm, Rn ); :}
nkeynes@359
   166
MOV.B @(disp, GBR), R0{: snprintf( buf, len, "MOV.B   @(%d, GBR), R0", disp ); :}
nkeynes@359
   167
MOV.B @(disp, Rm), R0 {: snprintf( buf, len, "MOV.B   @(%d, R%d), R0", disp, Rm ); :}
nkeynes@359
   168
MOV.L Rm, @Rn    {: snprintf( buf, len, "MOV.L   R%d, @R%d", Rm, Rn ); :}
nkeynes@359
   169
MOV.L Rm, @-Rn   {: snprintf( buf, len, "MOV.L   R%d, @-R%d", Rm, Rn ); :}
nkeynes@359
   170
MOV.L Rm, @(R0, Rn) {: snprintf( buf, len, "MOV.L   R%d, @(R0, R%d)", Rm, Rn ); :}
nkeynes@359
   171
MOV.L R0, @(disp, GBR) {: snprintf( buf, len, "MOV.L   R0, @(%d, GBR)", disp ); :}
nkeynes@359
   172
MOV.L Rm, @(disp, Rn) {: snprintf( buf, len, "MOV.L   R%d, @(%d, R%d)", Rm, disp, Rn ); :}
nkeynes@359
   173
MOV.L @Rm, Rn    {: snprintf( buf, len, "MOV.L   @R%d, R%d", Rm, Rn ); :}
nkeynes@359
   174
MOV.L @Rm+, Rn   {: snprintf( buf, len, "MOV.L   @R%d+, R%d", Rm, Rn ); :}
nkeynes@359
   175
MOV.L @(R0, Rm), Rn {: snprintf( buf, len, "MOV.L   @(R0, R%d), R%d", Rm, Rn ); :}
nkeynes@359
   176
MOV.L @(disp, GBR), R0 {: snprintf( buf, len, "MOV.L   @(%d, GBR), R0",disp ); :}
nkeynes@939
   177
MOV.L @(disp, PC), Rn  {:
nkeynes@939
   178
    tmp = mmu_vma_to_phys_disasm(disp + (pc&0xFFFFFFFC) + 4); 
nkeynes@939
   179
    snprintf( buf, len, "MOV.L   @($%xh), R%d ; <- #%08x", disp + (pc&0xFFFFFFFC)+4, Rn, ext_address_space[tmp>>12]->read_long(tmp) );
nkeynes@939
   180
:}
nkeynes@496
   181
MOV.L @(disp, Rm), Rn  {: snprintf( buf, len, "MOV.L   @(%d, R%d), R%d", disp, Rm, Rn ); :}
nkeynes@359
   182
MOV.W Rm, @Rn    {: snprintf( buf, len, "MOV.W   R%d, @R%d", Rm, Rn ); :}
nkeynes@359
   183
MOV.W Rm, @-Rn   {: snprintf( buf, len, "MOV.W   R%d, @-R%d", Rm, Rn ); :}
nkeynes@359
   184
MOV.W Rm, @(R0, Rn) {: snprintf( buf, len, "MOV.W   R%d, @(R0, R%d)", Rm, Rn ); :}
nkeynes@359
   185
MOV.W R0, @(disp, GBR) {: snprintf( buf, len, "MOV.W   R0, @(%d, GBR)", disp); :}
nkeynes@430
   186
MOV.W R0, @(disp, Rn)  {: snprintf( buf, len, "MOV.W   R0, @(%d, R%d)", disp, Rn ); :}
nkeynes@359
   187
MOV.W @Rm, Rn    {: snprintf( buf, len, "MOV.W   @R%d, R%d", Rm, Rn ); :}
nkeynes@359
   188
MOV.W @Rm+, Rn   {: snprintf( buf, len, "MOV.W   @R%d+, R%d", Rm, Rn ); :}
nkeynes@359
   189
MOV.W @(R0, Rm), Rn {: snprintf( buf, len, "MOV.W   @(R0, R%d), R%d", Rm, Rn ); :}
nkeynes@359
   190
MOV.W @(disp, GBR), R0 {: snprintf( buf, len, "MOV.W   @(%d, GBR), R0", disp ); :}
nkeynes@939
   191
MOV.W @(disp, PC), Rn  {:
nkeynes@939
   192
    tmp = mmu_vma_to_phys_disasm(disp+pc+4);
nkeynes@939
   193
    snprintf( buf, len, "MOV.W   @($%xh), R%d ; <- #%08x", disp+pc+4, Rn, ext_address_space[tmp>>12]->read_word(tmp) );
nkeynes@939
   194
:}
nkeynes@359
   195
MOV.W @(disp, Rm), R0  {: snprintf( buf, len, "MOV.W   @(%d, R%d), R0", disp, Rm ); :}
nkeynes@359
   196
MOVA @(disp, PC), R0   {: snprintf( buf, len, "MOVA    @($%xh), R0", disp + (pc&0xFFFFFFFC) + 4 ); :}
nkeynes@359
   197
MOVCA.L R0, @Rn  {: snprintf( buf, len, "MOVCA.L R0, @R%d", Rn ); :}
nkeynes@359
   198
MOVT Rn          {: snprintf( buf, len, "MOVT    R%d", Rn ); :}
nkeynes@359
   199
MUL.L Rm, Rn     {: snprintf( buf, len, "MUL.L   R%d, R%d", Rm, Rn ); :}
nkeynes@359
   200
MULS.W Rm, Rn    {: snprintf( buf, len, "MULS.W  R%d, R%d", Rm, Rn ); :}
nkeynes@359
   201
MULU.W Rm, Rn    {: snprintf( buf, len, "MULU.W  R%d, R%d", Rm, Rn ); :}
nkeynes@359
   202
NEG Rm, Rn       {: snprintf( buf, len, "NEG     R%d, R%d", Rm, Rn ); :}
nkeynes@359
   203
NEGC Rm, Rn      {: snprintf( buf, len, "NEGC    R%d, R%d", Rm, Rn ); :}
nkeynes@359
   204
NOP              {: snprintf( buf, len, "NOP     " ); :}
nkeynes@359
   205
NOT Rm, Rn       {: snprintf( buf, len, "NOT     R%d, R%d", Rm, Rn ); :}
nkeynes@359
   206
OCBI @Rn         {: snprintf( buf, len, "OCBI    @R%d", Rn ); :}
nkeynes@359
   207
OCBP @Rn         {: snprintf( buf, len, "OCBP    @R%d", Rn ); :}
nkeynes@359
   208
OCBWB @Rn        {: snprintf( buf, len, "OCBWB   @R%d", Rn ); :}
nkeynes@359
   209
OR Rm, Rn        {: snprintf( buf, len, "OR      R%d, R%d", Rm, Rn ); :}
nkeynes@359
   210
OR #imm, R0      {: snprintf( buf, len, "OR      #%d, R0", imm ); :}
nkeynes@359
   211
OR.B #imm, @(R0, GBR) {: snprintf( buf, len, "OR.B    #%d, @(R0, GBR)", imm ); :}
nkeynes@359
   212
PREF @Rn         {: snprintf( buf, len, "PREF    R%d", Rn ); :}
nkeynes@359
   213
ROTCL Rn         {: snprintf( buf, len, "ROTCL   R%d", Rn ); :}
nkeynes@359
   214
ROTCR Rn         {: snprintf( buf, len, "ROTCR   R%d", Rn ); :}
nkeynes@359
   215
ROTL Rn          {: snprintf( buf, len, "ROTL    R%d", Rn ); :}
nkeynes@359
   216
ROTR Rn          {: snprintf( buf, len, "ROTR    R%d", Rn ); :}
nkeynes@359
   217
RTE              {: snprintf( buf, len, "RTE     " ); :}
nkeynes@359
   218
RTS              {: snprintf( buf, len, "RTS     " ); :}
nkeynes@359
   219
SETS             {: snprintf( buf, len, "SETS    " ); :}
nkeynes@359
   220
SETT             {: snprintf( buf, len, "SETT    " ); :}
nkeynes@359
   221
SHAD Rm, Rn      {: snprintf( buf, len, "SHAD    R%d, R%d", Rm, Rn ); :}
nkeynes@359
   222
SHAL Rn          {: snprintf( buf, len, "SHAL    R%d", Rn ); :}
nkeynes@359
   223
SHAR Rn          {: snprintf( buf, len, "SHAR    R%d", Rn ); :}
nkeynes@359
   224
SHLD Rm, Rn      {: snprintf( buf, len, "SHLD    R%d, R%d", Rm, Rn ); :}
nkeynes@359
   225
SHLL Rn          {: snprintf( buf, len, "SHLL    R%d", Rn ); :}
nkeynes@359
   226
SHLL2 Rn         {: snprintf( buf, len, "SHLL2   R%d", Rn ); :}
nkeynes@359
   227
SHLL8 Rn         {: snprintf( buf, len, "SHLL8   R%d", Rn ); :}
nkeynes@359
   228
SHLL16 Rn        {: snprintf( buf, len, "SHLL16  R%d", Rn ); :}
nkeynes@359
   229
SHLR Rn          {: snprintf( buf, len, "SHLR    R%d", Rn ); :}
nkeynes@359
   230
SHLR2 Rn         {: snprintf( buf, len, "SHLR2   R%d", Rn ); :}
nkeynes@359
   231
SHLR8 Rn         {: snprintf( buf, len, "SHLR8   R%d", Rn ); :}
nkeynes@359
   232
SHLR16 Rn        {: snprintf( buf, len, "SHLR16  R%d", Rn ); :}
nkeynes@359
   233
SLEEP            {: snprintf( buf, len, "SLEEP   " ); :}
nkeynes@359
   234
STC SR, Rn       {: snprintf( buf, len, "STC     SR, R%d", Rn ); :}
nkeynes@359
   235
STC GBR, Rn      {: snprintf( buf, len, "STC     GBR, R%d", Rn ); :}
nkeynes@359
   236
STC VBR, Rn      {: snprintf( buf, len, "STC     VBR, R%d", Rn ); :}
nkeynes@359
   237
STC SSR, Rn      {: snprintf( buf, len, "STC     SSR, R%d", Rn ); :}
nkeynes@359
   238
STC SPC, Rn      {: snprintf( buf, len, "STC     SPC, R%d", Rn ); :}
nkeynes@359
   239
STC SGR, Rn      {: snprintf( buf, len, "STC     SGR, R%d", Rn ); :}
nkeynes@359
   240
STC DBR, Rn      {: snprintf( buf, len, "STC     DBR, R%d", Rn ); :}
nkeynes@359
   241
STC Rm_BANK, Rn  {: snprintf( buf, len, "STC     R%d_BANK, R%d", Rm_BANK, Rn ); :}
nkeynes@359
   242
STS FPSCR, Rn    {: snprintf( buf, len, "STS     FPSCR, R%d", Rn ); :}
nkeynes@359
   243
STS FPUL, Rn     {: snprintf( buf, len, "STS     FPUL, R%d", Rn ); :}
nkeynes@359
   244
STS MACH, Rn     {: snprintf( buf, len, "STS     MACH, R%d", Rn ); :}
nkeynes@359
   245
STS MACL, Rn     {: snprintf( buf, len, "STS     MACL, R%d", Rn ); :}
nkeynes@359
   246
STS PR, Rn       {: snprintf( buf, len, "STS     PR, R%d", Rn ); :}
nkeynes@359
   247
STC.L SR, @-Rn   {: snprintf( buf, len, "STC.L   SR, @-R%d", Rn ); :}
nkeynes@359
   248
STC.L GBR, @-Rn  {: snprintf( buf, len, "STC.L   GBR, @-R%d", Rn ); :}
nkeynes@359
   249
STC.L VBR, @-Rn  {: snprintf( buf, len, "STC.L   VBR, @-R%d", Rn ); :}
nkeynes@359
   250
STC.L SSR, @-Rn  {: snprintf( buf, len, "STC.L   SSR, @-R%d", Rn ); :}
nkeynes@359
   251
STC.L SPC, @-Rn  {: snprintf( buf, len, "STC.L   SPC, @-R%d", Rn ); :}
nkeynes@359
   252
STC.L SGR, @-Rn  {: snprintf( buf, len, "STC.L   SGR, @-R%d", Rn ); :}
nkeynes@359
   253
STC.L DBR, @-Rn  {: snprintf( buf, len, "STC.L    DBR, @-R%d", Rn ); :}
nkeynes@359
   254
STC.L Rm_BANK, @-Rn {: snprintf( buf, len, "STC.L   @-R%d_BANK, @-R%d", Rm_BANK, Rn ); :}
nkeynes@359
   255
STS.L FPSCR, @-Rn{: snprintf( buf, len, "STS.L   FPSCR, @-R%d", Rn ); :}
nkeynes@359
   256
STS.L FPUL, @-Rn {: snprintf( buf, len, "STS.L   FPUL, @-R%d", Rn ); :}
nkeynes@359
   257
STS.L MACH, @-Rn {: snprintf( buf, len, "STS.L   MACH, @-R%d", Rn ); :}
nkeynes@359
   258
STS.L MACL, @-Rn {: snprintf( buf, len, "STS.L   MACL, @-R%d", Rn ); :}
nkeynes@359
   259
STS.L PR, @-Rn   {: snprintf( buf, len, "STS.L   PR, @-R%d", Rn ); :}
nkeynes@359
   260
SUB Rm, Rn       {: snprintf( buf, len, "SUB     R%d, R%d", Rm, Rn ); :}
nkeynes@359
   261
SUBC Rm, Rn      {: snprintf( buf, len, "SUBC    R%d, R%d", Rm, Rn ); :}
nkeynes@359
   262
SUBV Rm, Rn      {: snprintf( buf, len, "SUBV    R%d, R%d", Rm, Rn ); :}
nkeynes@359
   263
SWAP.B Rm, Rn    {: snprintf( buf, len, "SWAP.B  R%d, R%d", Rm, Rn ); :}
nkeynes@359
   264
SWAP.W Rm, Rn    {: snprintf( buf, len, "SWAP.W  R%d, R%d", Rm, Rn ); :}
nkeynes@359
   265
TAS.B @Rn        {: snprintf( buf, len, "TAS.B   R%d", Rn ); :}
nkeynes@359
   266
TRAPA #imm       {: snprintf( buf, len, "TRAPA   #%d", imm ); :}
nkeynes@359
   267
TST Rm, Rn       {: snprintf( buf, len, "TST     R%d, R%d", Rm, Rn ); :}
nkeynes@359
   268
TST #imm, R0     {: snprintf( buf, len, "TST     #%d, R0", imm ); :}
nkeynes@359
   269
TST.B #imm, @(R0, GBR) {: snprintf( buf, len, "TST.B   #%d, @(R0, GBR)", imm ); :}
nkeynes@359
   270
XOR Rm, Rn       {: snprintf( buf, len, "XOR     R%d, R%d", Rm, Rn ); :}
nkeynes@359
   271
XOR #imm, R0     {: snprintf( buf, len, "XOR     #%d, R0", imm ); :}
nkeynes@359
   272
XOR.B #imm, @(R0, GBR) {: snprintf( buf, len, "XOR.B   #%d, @(R0, GBR)", imm ); :}
nkeynes@359
   273
XTRCT Rm, Rn     {: snprintf( buf, len, "XTRCT   R%d, R%d", Rm, Rn ); :}
nkeynes@359
   274
UNDEF            {: snprintf( buf, len, "UNDEF   " ); :}
nkeynes@359
   275
%%
nkeynes@359
   276
    return pc+2;
nkeynes@359
   277
}
nkeynes@359
   278
nkeynes@359
   279
nkeynes@1300
   280
static struct sh4_symbol *sh4_symbol_table = NULL;
nkeynes@1300
   281
static unsigned sh4_symbol_table_size = 0;
nkeynes@1300
   282
static sh4_symtab_destroy_cb sh4_symbol_table_cb = NULL;
nkeynes@1300
   283
nkeynes@1300
   284
nkeynes@1300
   285
static void swap_symbol( struct sh4_symbol *a, struct sh4_symbol *b ) {
nkeynes@1300
   286
    struct sh4_symbol tmp;
nkeynes@1300
   287
    if( a == b )
nkeynes@1300
   288
        return;
nkeynes@1300
   289
    memcpy( &tmp, a, sizeof( struct sh4_symbol ) );
nkeynes@1300
   290
    memcpy( a, b, sizeof( struct sh4_symbol ) );
nkeynes@1300
   291
    memcpy( b, &tmp, sizeof( struct sh4_symbol ) );
nkeynes@1300
   292
}
nkeynes@1300
   293
nkeynes@1300
   294
static unsigned sort_symtab( struct sh4_symbol *table, unsigned numSymtabEntries ) {
nkeynes@1300
   295
    /* Implement via simple selection sort for now; usually we don't have very
nkeynes@1300
   296
     * large symbol tables.
nkeynes@1300
   297
     */
nkeynes@1300
   298
    for( unsigned i = 0; i < numSymtabEntries; i++ ) {
nkeynes@1300
   299
        struct sh4_symbol *next_entry = &table[i];
nkeynes@1300
   300
        for( unsigned j = i + 1; j < numSymtabEntries; ) {
nkeynes@1300
   301
            if( table[j].address < next_entry->address ) {
nkeynes@1300
   302
                next_entry = &table[j];
nkeynes@1300
   303
                j++;
nkeynes@1300
   304
            } else if( table[j].address == next_entry->address ) {
nkeynes@1300
   305
                /* Duplicate - kill it */
nkeynes@1300
   306
                swap_symbol( &table[j], &table[--numSymtabEntries] );
nkeynes@1300
   307
            } else {
nkeynes@1300
   308
                j++;
nkeynes@1300
   309
            }
nkeynes@1300
   310
        }
nkeynes@1300
   311
        swap_symbol( &table[i], next_entry );
nkeynes@1300
   312
    }
nkeynes@1300
   313
    return numSymtabEntries;
nkeynes@1300
   314
}
nkeynes@1300
   315
nkeynes@1300
   316
const char *sh4_disasm_get_symbol( sh4addr_t addr )
nkeynes@1300
   317
{
nkeynes@1300
   318
	int l = 0, h = sh4_symbol_table_size;
nkeynes@1300
   319
	while( l != h ) {
nkeynes@1300
   320
	    int i = l + (h-l)/2;
nkeynes@1300
   321
	    int iaddr = sh4_symbol_table[i].address;
nkeynes@1300
   322
	    if( iaddr == addr ) {
nkeynes@1300
   323
	        return sh4_symbol_table[i].name;
nkeynes@1300
   324
	    } else if( iaddr > addr ) {
nkeynes@1300
   325
	        h = i;
nkeynes@1300
   326
	    } else { /* iaddr < addr */
nkeynes@1300
   327
	        l = i+1;
nkeynes@1300
   328
	    }
nkeynes@1300
   329
	}
nkeynes@1300
   330
	return NULL;
nkeynes@1300
   331
}
nkeynes@1300
   332
nkeynes@1300
   333
void sh4_set_symbol_table( struct sh4_symbol *table, unsigned size, sh4_symtab_destroy_cb callback )
nkeynes@1300
   334
{
nkeynes@1300
   335
    if( sh4_symbol_table_cb != NULL ) {
nkeynes@1300
   336
        sh4_symbol_table_cb(sh4_symbol_table, sh4_symbol_table_size);
nkeynes@1300
   337
    }
nkeynes@1300
   338
    sh4_symbol_table = table;
nkeynes@1300
   339
    sh4_symbol_table_cb = callback;
nkeynes@1300
   340
    if( table == NULL ) {
nkeynes@1300
   341
        sh4_symbol_table_size = 0;
nkeynes@1300
   342
    } else {
nkeynes@1300
   343
        sh4_symbol_table_size = sort_symtab(table, size);
nkeynes@1300
   344
    }
nkeynes@1300
   345
}
nkeynes@1300
   346
    
nkeynes@1300
   347
nkeynes@569
   348
void sh4_disasm_region( FILE *f, int from, int to )
nkeynes@359
   349
{
nkeynes@359
   350
    int pc;
nkeynes@359
   351
    char buf[80];
nkeynes@359
   352
    char opcode[16];
nkeynes@359
   353
    
nkeynes@359
   354
    for( pc = from; pc < to; pc+=2 ) {
nkeynes@359
   355
        buf[0] = '\0';
nkeynes@359
   356
        sh4_disasm_instruction( pc,
nkeynes@359
   357
                                buf, sizeof(buf), opcode );
nkeynes@1300
   358
        const char *sym = sh4_disasm_get_symbol( pc );
nkeynes@1300
   359
        if( sym != 0 ) {
nkeynes@1300
   360
            fprintf( f, "%s:\n", sym );
nkeynes@1300
   361
        }
nkeynes@359
   362
        fprintf( f, "  %08x:  %s  %s\n", pc, opcode, buf );
nkeynes@359
   363
    }
nkeynes@359
   364
}
nkeynes@706
   365
nkeynes@706
   366
void sh4_dump_region( int from, int to )
nkeynes@706
   367
{
nkeynes@706
   368
    sh4_disasm_region( stdout, from, to );
nkeynes@706
   369
}
.