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 | }
|