nkeynes@359: /** nkeynes@561: * $Id$ nkeynes@359: * nkeynes@359: * SH4 CPU definition and disassembly functions nkeynes@359: * nkeynes@359: * Copyright (c) 2005 Nathan Keynes. nkeynes@359: * nkeynes@359: * This program is free software; you can redistribute it and/or modify nkeynes@359: * it under the terms of the GNU General Public License as published by nkeynes@359: * the Free Software Foundation; either version 2 of the License, or nkeynes@359: * (at your option) any later version. nkeynes@359: * nkeynes@359: * This program is distributed in the hope that it will be useful, nkeynes@359: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@359: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@359: * GNU General Public License for more details. nkeynes@359: */ nkeynes@359: nkeynes@730: #include "sh4/sh4core.h" nkeynes@730: #include "sh4/sh4dasm.h" nkeynes@963: #include "sh4/mmu.h" nkeynes@359: #include "mem.h" nkeynes@359: nkeynes@1300: #include nkeynes@1300: nkeynes@359: #define UNIMP(ir) snprintf( buf, len, "??? " ) nkeynes@359: nkeynes@597: uint32_t sh4_disasm_instruction( sh4vma_t pc, char *buf, int len, char *opcode ) nkeynes@359: { nkeynes@597: sh4addr_t addr = mmu_vma_to_phys_disasm(pc); nkeynes@939: uint32_t tmp; nkeynes@1190: nkeynes@1190: if( addr == MMU_VMA_ERROR ) { nkeynes@1190: sprintf( opcode, "?? ??" ); nkeynes@1190: snprintf( buf, len, "???" ); nkeynes@1190: return pc+2; nkeynes@1190: } nkeynes@1190: nkeynes@939: uint16_t ir = ext_address_space[addr>>12]->read_word(addr); nkeynes@359: nkeynes@359: #define UNDEF(ir) snprintf( buf, len, "???? " ); nkeynes@359: #define RN(ir) ((ir&0x0F00)>>8) nkeynes@359: #define RN_BANK(ir) ((ir&0x0070)>>4) nkeynes@359: #define RM(ir) ((ir&0x00F0)>>4) nkeynes@359: #define DISP4(ir) (ir&0x000F) /* 4-bit displacements are *not* sign extended */ nkeynes@359: #define DISP8(ir) (ir&0x00FF) nkeynes@359: #define PCDISP8(ir) SIGNEXT8(ir&0x00FF) nkeynes@359: #define UIMM8(ir) (ir&0x00FF) nkeynes@359: #define IMM8(ir) SIGNEXT8(ir&0x00FF) nkeynes@359: #define DISP12(ir) SIGNEXT12(ir&0x0FFF) nkeynes@359: #define FVN(ir) ((ir&0x0C00)>>10) nkeynes@359: #define FVM(ir) ((ir&0x0300)>>8) nkeynes@359: nkeynes@359: sprintf( opcode, "%02X %02X", ir&0xFF, ir>>8 ); nkeynes@359: nkeynes@359: %% nkeynes@359: ADD Rm, Rn {: snprintf( buf, len, "ADD R%d, R%d", Rm, Rn ); :} nkeynes@359: ADD #imm, Rn {: snprintf( buf, len, "ADD #%d, R%d", imm, Rn ); :} nkeynes@359: ADDC Rm, Rn {: snprintf( buf, len, "ADDC R%d, R%d", Rm, Rn ); :} nkeynes@359: ADDV Rm, Rn {: snprintf( buf, len, "ADDV R%d, R%d", Rm, Rn ); :} nkeynes@359: AND Rm, Rn {: snprintf( buf, len, "AND R%d, R%d", Rm, Rn ); :} nkeynes@595: AND #imm, R0 {: snprintf( buf, len, "AND #%d, R0", imm ); :} nkeynes@359: AND.B #imm, @(R0, GBR) {: snprintf( buf, len, "AND.B #%d, @(R0, GBR)", imm ); :} nkeynes@359: BF disp {: snprintf( buf, len, "BF $%xh", disp+pc+4 ); :} nkeynes@359: BF/S disp {: snprintf( buf, len, "BF/S $%xh", disp+pc+4 ); :} nkeynes@359: BRA disp {: snprintf( buf, len, "BRA $%xh", disp+pc+4 ); :} nkeynes@359: BRAF Rn {: snprintf( buf, len, "BRAF R%d", Rn ); :} nkeynes@359: BSR disp {: snprintf( buf, len, "BSR $%xh", disp+pc+4 ); :} nkeynes@359: BSRF Rn {: snprintf( buf, len, "BSRF R%d", Rn ); :} nkeynes@359: BT disp {: snprintf( buf, len, "BT $%xh", disp+pc+4 ); :} nkeynes@359: BT/S disp {: snprintf( buf, len, "BT/S $%xh", disp+pc+4 ); :} nkeynes@359: CLRMAC {: snprintf( buf, len, "CLRMAC " ); :} nkeynes@359: CLRS {: snprintf( buf, len, "CLRS " ); :} nkeynes@359: CLRT {: snprintf( buf, len, "CLRT " ); :} nkeynes@359: CMP/EQ Rm, Rn {: snprintf( buf, len, "CMP/EQ R%d, R%d", Rm, Rn ); :} nkeynes@359: CMP/EQ #imm, R0 {: snprintf( buf, len, "CMP/EQ #%d, R0", imm ); :} nkeynes@359: CMP/GE Rm, Rn {: snprintf( buf, len, "CMP/GE R%d, R%d", Rm, Rn ); :} nkeynes@359: CMP/GT Rm, Rn {: snprintf( buf, len, "CMP/GT R%d, R%d", Rm, Rn ); :} nkeynes@359: CMP/HI Rm, Rn {: snprintf( buf, len, "CMP/HI R%d, R%d", Rm, Rn ); :} nkeynes@359: CMP/HS Rm, Rn {: snprintf( buf, len, "CMP/HS R%d, R%d", Rm, Rn ); :} nkeynes@359: CMP/PL Rn {: snprintf( buf, len, "CMP/PL R%d", Rn ); :} nkeynes@359: CMP/PZ Rn {: snprintf( buf, len, "CMP/PZ R%d", Rn ); :} nkeynes@359: CMP/STR Rm, Rn {: snprintf( buf, len, "CMP/STR R%d, R%d", Rm, Rn ); :} nkeynes@359: DIV0S Rm, Rn {: snprintf( buf, len, "DIV0S R%d, R%d", Rm, Rn ); :} nkeynes@359: DIV0U {: snprintf( buf, len, "DIV0U " ); :} nkeynes@359: DIV1 Rm, Rn {: snprintf( buf, len, "DIV1 R%d, R%d", Rm, Rn ); :} nkeynes@359: DMULS.L Rm, Rn {: snprintf( buf, len, "DMULS.L R%d, R%d", Rm, Rn ); :} nkeynes@359: DMULU.L RM, Rn {: snprintf( buf, len, "DMULU.L R%d, R%d", Rm, Rn ); :} nkeynes@359: DT Rn {: snprintf( buf, len, "DT R%d", Rn ); :} nkeynes@359: EXTS.B Rm, Rn {: snprintf( buf, len, "EXTS.B R%d, R%d", Rm, Rn ); :} nkeynes@359: EXTS.W Rm, Rn {: snprintf( buf, len, "EXTS.W R%d, R%d", Rm, Rn ); :} nkeynes@359: EXTU.B Rm, Rn {: snprintf( buf, len, "EXTU.B R%d, R%d", Rm, Rn ); :} nkeynes@359: EXTU.W Rm, Rn {: snprintf( buf, len, "EXTU.W R%d, R%d", Rm, Rn ); :} nkeynes@359: FABS FRn {: snprintf( buf, len, "FABS FR%d", FRn ); :} nkeynes@359: FADD FRm, FRn {: snprintf( buf, len, "FADD FR%d, FR%d", FRm, FRn ); :} nkeynes@359: FCMP/EQ FRm, FRn {: snprintf( buf, len, "FCMP/EQ FR%d, FR%d", FRm, FRn ); :} nkeynes@873: FCMP/GT FRm, FRn {: snprintf( buf, len, "FCMP/GT FR%d, FR%d", FRm, FRn ); :} nkeynes@359: FCNVDS FRm, FPUL {: snprintf( buf, len, "FCNVDS FR%d, FPUL", FRm ); :} nkeynes@359: FCNVSD FPUL, FRn {: snprintf( buf, len, "FCNVSD FPUL, FR%d", FRn ); :} nkeynes@359: FDIV FRm, FRn {: snprintf( buf, len, "FDIV FR%d, FR%d", FRm, FRn ); :} nkeynes@359: FIPR FVm, FVn {: snprintf( buf, len, "FIPR FV%d, FV%d", FVm, FVn ); :} nkeynes@359: FLDS FRm, FPUL {: snprintf( buf, len, "FLDS FR%d, FPUL", FRm ); :} nkeynes@359: FLDI0 FRn {: snprintf( buf, len, "FLDI0 FR%d", FRn ); :} nkeynes@359: FLDI1 FRn {: snprintf( buf, len, "FLDI1 FR%d", FRn ); :} nkeynes@359: FLOAT FPUL, FRn {: snprintf( buf, len, "FLOAT FPUL, FR%d", FRn ); :} nkeynes@359: FMAC FR0, FRm, FRn {: snprintf( buf, len, "FMAC FR0, FR%d, FR%d", FRm, FRn ); :} nkeynes@359: FMOV FRm, FRn {: snprintf( buf, len, "FMOV FR%d, FR%d", FRm, FRn ); :} nkeynes@359: FMOV FRm, @Rn {: snprintf( buf, len, "FMOV FR%d, @R%d", FRm, Rn ); :} nkeynes@359: FMOV FRm, @-Rn {: snprintf( buf, len, "FMOV FR%d, @-R%d", FRm, Rn ); :} nkeynes@359: FMOV FRm, @(R0, Rn) {: snprintf( buf, len, "FMOV FR%d, @(R0, R%d)", FRm, Rn ); :} nkeynes@359: FMOV @Rm, FRn {: snprintf( buf, len, "FMOV @R%d, FR%d", Rm, FRn ); :} nkeynes@359: FMOV @Rm+, FRn {: snprintf( buf, len, "FMOV @R%d+, FR%d", Rm, FRn ); :} nkeynes@359: FMOV @(R0, Rm), FRn {: snprintf( buf, len, "FMOV @(R0, R%d), FR%d", Rm, FRn ); :} nkeynes@430: FMUL FRm, FRn {: snprintf( buf, len, "FMUL FR%d, FR%d", FRm, FRn ); :} nkeynes@359: FNEG FRn {: snprintf( buf, len, "FNEG FR%d", FRn ); :} nkeynes@359: FRCHG {: snprintf( buf, len, "FRCHG " ); :} nkeynes@359: FSCA FPUL, FRn {: snprintf( buf, len, "FSCA FPUL, FR%d", FRn ); :} nkeynes@359: FSCHG {: snprintf( buf, len, "FSCHG " ); :} nkeynes@359: FSQRT FRn {: snprintf( buf, len, "FSQRT FR%d", FRn ); :} nkeynes@359: FSRRA FRn {: snprintf( buf, len, "FSRRA FR%d", FRn ); :} nkeynes@359: FSTS FPUL, FRn {: snprintf( buf, len, "FSTS FPUL, FR%d", FRn ); :} nkeynes@430: FSUB FRm, FRn {: snprintf( buf, len, "FSUB FR%d, FR%d", FRm, FRn ); :} nkeynes@359: FTRC FRm, FPUL {: snprintf( buf, len, "FTRC FR%d, FPUL", FRm ); :} nkeynes@359: FTRV XMTRX, FVn {: snprintf( buf, len, "FTRV XMTRX, FV%d", FVn ); :} nkeynes@359: JMP @Rn {: snprintf( buf, len, "JMP @R%d", Rn ); :} nkeynes@359: JSR @Rn {: snprintf( buf, len, "JSR @R%d", Rn ); :} nkeynes@359: LDC Rm, GBR {: snprintf( buf, len, "LDC R%d, GBR", Rm ); :} nkeynes@359: LDC Rm, SR {: snprintf( buf, len, "LDC R%d, SR", Rm ); :} nkeynes@359: LDC Rm, VBR {: snprintf( buf, len, "LDC R%d, VBR", Rm ); :} nkeynes@359: LDC Rm, SSR {: snprintf( buf, len, "LDC R%d, SSR", Rm ); :} nkeynes@359: LDC Rm, SGR {: snprintf( buf, len, "LDC R%d, SGR", Rm ); :} nkeynes@359: LDC Rm, SPC {: snprintf( buf, len, "LDC R%d, SPC", Rm ); :} nkeynes@359: LDC Rm, DBR {: snprintf( buf, len, "LDC R%d, DBR", Rm ); :} nkeynes@359: LDC Rm, Rn_BANK {: snprintf( buf, len, "LDC R%d, R%d_BANK", Rm, Rn_BANK ); :} nkeynes@359: LDS Rm, FPSCR {: snprintf( buf, len, "LDS R%d, FPSCR", Rm ); :} nkeynes@359: LDS Rm, FPUL {: snprintf( buf, len, "LDS R%d, FPUL", Rm ); :} nkeynes@359: LDS Rm, MACH {: snprintf( buf, len, "LDS R%d, MACH", Rm ); :} nkeynes@359: LDS Rm, MACL {: snprintf( buf, len, "LDS R%d, MACL", Rm ); :} nkeynes@359: LDS Rm, PR {: snprintf( buf, len, "LDS R%d, PR", Rm ); :} nkeynes@359: LDC.L @Rm+, GBR {: snprintf( buf, len, "LDC.L @R%d+, GBR", Rm ); :} nkeynes@359: LDC.L @Rm+, SR {: snprintf( buf, len, "LDC.L @R%d+, SR", Rm ); :} nkeynes@359: LDC.L @Rm+, VBR {: snprintf( buf, len, "LDC.L @R%d+, VBR", Rm ); :} nkeynes@359: LDC.L @Rm+, SSR {: snprintf( buf, len, "LDC.L @R%d+, SSR", Rm ); :} nkeynes@359: LDC.L @Rm+, SGR {: snprintf( buf, len, "LDC.L @R%d+, SGR", Rm ); :} nkeynes@359: LDC.L @Rm+, SPC {: snprintf( buf, len, "LDC.L @R%d+, SPC", Rm ); :} nkeynes@359: LDC.L @Rm+, DBR {: snprintf( buf, len, "LDC.L @R%d+, DBR", Rm ); :} nkeynes@359: LDC.L @Rm+, Rn_BANK{: snprintf( buf, len, "LDC.L @R%d+, @R%d+_BANK", Rm, Rn_BANK ); :} nkeynes@359: LDS.L @Rm+, FPSCR{: snprintf( buf, len, "LDS.L @R%d+, FPSCR", Rm ); :} nkeynes@359: LDS.L @Rm+, FPUL {: snprintf( buf, len, "LDS.L @R%d+, FPUL", Rm ); :} nkeynes@359: LDS.L @Rm+, MACH {: snprintf( buf, len, "LDS.L @R%d+, MACH", Rm ); :} nkeynes@359: LDS.L @Rm+, MACL {: snprintf( buf, len, "LDS.L @R%d+, MACL", Rm ); :} nkeynes@359: LDS.L @Rm+, PR {: snprintf( buf, len, "LDS.L @R%d+, PR", Rm ); :} nkeynes@359: LDTLB {: snprintf( buf, len, "LDTLB " ); :} nkeynes@359: MAC.L @Rm+, @Rn+ {: snprintf( buf, len, "MAC.L @R%d+, @R%d+", Rm, Rn ); :} nkeynes@359: MAC.W @Rm+, @Rn+ {: snprintf( buf, len, "MAC.W @R%d+, @R%d+", Rm, Rn ); :} nkeynes@359: MOV Rm, Rn {: snprintf( buf, len, "MOV R%d, R%d", Rm, Rn ); :} nkeynes@359: MOV #imm, Rn {: snprintf( buf, len, "MOV #%d, R%d", imm, Rn ); :} nkeynes@359: MOV.B Rm, @Rn {: snprintf( buf, len, "MOV.B R%d, @R%d", Rm, Rn ); :} nkeynes@359: MOV.B Rm, @-Rn {: snprintf( buf, len, "MOV.B R%d, @-R%d", Rm, Rn ); :} nkeynes@359: MOV.B Rm, @(R0, Rn) {: snprintf( buf, len, "MOV.B R%d, @(R0, R%d)", Rm, Rn ); :} nkeynes@359: MOV.B R0, @(disp, GBR) {: snprintf( buf, len, "MOV.B R0, @(%d, GBR)", disp ); :} nkeynes@359: MOV.B R0, @(disp, Rn) {: snprintf( buf, len, "MOV.B R0, @(%d, R%d)", disp, Rn ); :} nkeynes@359: MOV.B @Rm, Rn {: snprintf( buf, len, "MOV.B @R%d, R%d", Rm, Rn ); :} nkeynes@359: MOV.B @Rm+, Rn {: snprintf( buf, len, "MOV.B @R%d+, R%d", Rm, Rn ); :} nkeynes@359: MOV.B @(R0, Rm), Rn {: snprintf( buf, len, "MOV.B @(R0, R%d), R%d", Rm, Rn ); :} nkeynes@359: MOV.B @(disp, GBR), R0{: snprintf( buf, len, "MOV.B @(%d, GBR), R0", disp ); :} nkeynes@359: MOV.B @(disp, Rm), R0 {: snprintf( buf, len, "MOV.B @(%d, R%d), R0", disp, Rm ); :} nkeynes@359: MOV.L Rm, @Rn {: snprintf( buf, len, "MOV.L R%d, @R%d", Rm, Rn ); :} nkeynes@359: MOV.L Rm, @-Rn {: snprintf( buf, len, "MOV.L R%d, @-R%d", Rm, Rn ); :} nkeynes@359: MOV.L Rm, @(R0, Rn) {: snprintf( buf, len, "MOV.L R%d, @(R0, R%d)", Rm, Rn ); :} nkeynes@359: MOV.L R0, @(disp, GBR) {: snprintf( buf, len, "MOV.L R0, @(%d, GBR)", disp ); :} nkeynes@359: MOV.L Rm, @(disp, Rn) {: snprintf( buf, len, "MOV.L R%d, @(%d, R%d)", Rm, disp, Rn ); :} nkeynes@359: MOV.L @Rm, Rn {: snprintf( buf, len, "MOV.L @R%d, R%d", Rm, Rn ); :} nkeynes@359: MOV.L @Rm+, Rn {: snprintf( buf, len, "MOV.L @R%d+, R%d", Rm, Rn ); :} nkeynes@359: MOV.L @(R0, Rm), Rn {: snprintf( buf, len, "MOV.L @(R0, R%d), R%d", Rm, Rn ); :} nkeynes@359: MOV.L @(disp, GBR), R0 {: snprintf( buf, len, "MOV.L @(%d, GBR), R0",disp ); :} nkeynes@939: MOV.L @(disp, PC), Rn {: nkeynes@939: tmp = mmu_vma_to_phys_disasm(disp + (pc&0xFFFFFFFC) + 4); nkeynes@939: snprintf( buf, len, "MOV.L @($%xh), R%d ; <- #%08x", disp + (pc&0xFFFFFFFC)+4, Rn, ext_address_space[tmp>>12]->read_long(tmp) ); nkeynes@939: :} nkeynes@496: MOV.L @(disp, Rm), Rn {: snprintf( buf, len, "MOV.L @(%d, R%d), R%d", disp, Rm, Rn ); :} nkeynes@359: MOV.W Rm, @Rn {: snprintf( buf, len, "MOV.W R%d, @R%d", Rm, Rn ); :} nkeynes@359: MOV.W Rm, @-Rn {: snprintf( buf, len, "MOV.W R%d, @-R%d", Rm, Rn ); :} nkeynes@359: MOV.W Rm, @(R0, Rn) {: snprintf( buf, len, "MOV.W R%d, @(R0, R%d)", Rm, Rn ); :} nkeynes@359: MOV.W R0, @(disp, GBR) {: snprintf( buf, len, "MOV.W R0, @(%d, GBR)", disp); :} nkeynes@430: MOV.W R0, @(disp, Rn) {: snprintf( buf, len, "MOV.W R0, @(%d, R%d)", disp, Rn ); :} nkeynes@359: MOV.W @Rm, Rn {: snprintf( buf, len, "MOV.W @R%d, R%d", Rm, Rn ); :} nkeynes@359: MOV.W @Rm+, Rn {: snprintf( buf, len, "MOV.W @R%d+, R%d", Rm, Rn ); :} nkeynes@359: MOV.W @(R0, Rm), Rn {: snprintf( buf, len, "MOV.W @(R0, R%d), R%d", Rm, Rn ); :} nkeynes@359: MOV.W @(disp, GBR), R0 {: snprintf( buf, len, "MOV.W @(%d, GBR), R0", disp ); :} nkeynes@939: MOV.W @(disp, PC), Rn {: nkeynes@939: tmp = mmu_vma_to_phys_disasm(disp+pc+4); nkeynes@939: snprintf( buf, len, "MOV.W @($%xh), R%d ; <- #%08x", disp+pc+4, Rn, ext_address_space[tmp>>12]->read_word(tmp) ); nkeynes@939: :} nkeynes@359: MOV.W @(disp, Rm), R0 {: snprintf( buf, len, "MOV.W @(%d, R%d), R0", disp, Rm ); :} nkeynes@359: MOVA @(disp, PC), R0 {: snprintf( buf, len, "MOVA @($%xh), R0", disp + (pc&0xFFFFFFFC) + 4 ); :} nkeynes@359: MOVCA.L R0, @Rn {: snprintf( buf, len, "MOVCA.L R0, @R%d", Rn ); :} nkeynes@359: MOVT Rn {: snprintf( buf, len, "MOVT R%d", Rn ); :} nkeynes@359: MUL.L Rm, Rn {: snprintf( buf, len, "MUL.L R%d, R%d", Rm, Rn ); :} nkeynes@359: MULS.W Rm, Rn {: snprintf( buf, len, "MULS.W R%d, R%d", Rm, Rn ); :} nkeynes@359: MULU.W Rm, Rn {: snprintf( buf, len, "MULU.W R%d, R%d", Rm, Rn ); :} nkeynes@359: NEG Rm, Rn {: snprintf( buf, len, "NEG R%d, R%d", Rm, Rn ); :} nkeynes@359: NEGC Rm, Rn {: snprintf( buf, len, "NEGC R%d, R%d", Rm, Rn ); :} nkeynes@359: NOP {: snprintf( buf, len, "NOP " ); :} nkeynes@359: NOT Rm, Rn {: snprintf( buf, len, "NOT R%d, R%d", Rm, Rn ); :} nkeynes@359: OCBI @Rn {: snprintf( buf, len, "OCBI @R%d", Rn ); :} nkeynes@359: OCBP @Rn {: snprintf( buf, len, "OCBP @R%d", Rn ); :} nkeynes@359: OCBWB @Rn {: snprintf( buf, len, "OCBWB @R%d", Rn ); :} nkeynes@359: OR Rm, Rn {: snprintf( buf, len, "OR R%d, R%d", Rm, Rn ); :} nkeynes@359: OR #imm, R0 {: snprintf( buf, len, "OR #%d, R0", imm ); :} nkeynes@359: OR.B #imm, @(R0, GBR) {: snprintf( buf, len, "OR.B #%d, @(R0, GBR)", imm ); :} nkeynes@359: PREF @Rn {: snprintf( buf, len, "PREF R%d", Rn ); :} nkeynes@359: ROTCL Rn {: snprintf( buf, len, "ROTCL R%d", Rn ); :} nkeynes@359: ROTCR Rn {: snprintf( buf, len, "ROTCR R%d", Rn ); :} nkeynes@359: ROTL Rn {: snprintf( buf, len, "ROTL R%d", Rn ); :} nkeynes@359: ROTR Rn {: snprintf( buf, len, "ROTR R%d", Rn ); :} nkeynes@359: RTE {: snprintf( buf, len, "RTE " ); :} nkeynes@359: RTS {: snprintf( buf, len, "RTS " ); :} nkeynes@359: SETS {: snprintf( buf, len, "SETS " ); :} nkeynes@359: SETT {: snprintf( buf, len, "SETT " ); :} nkeynes@359: SHAD Rm, Rn {: snprintf( buf, len, "SHAD R%d, R%d", Rm, Rn ); :} nkeynes@359: SHAL Rn {: snprintf( buf, len, "SHAL R%d", Rn ); :} nkeynes@359: SHAR Rn {: snprintf( buf, len, "SHAR R%d", Rn ); :} nkeynes@359: SHLD Rm, Rn {: snprintf( buf, len, "SHLD R%d, R%d", Rm, Rn ); :} nkeynes@359: SHLL Rn {: snprintf( buf, len, "SHLL R%d", Rn ); :} nkeynes@359: SHLL2 Rn {: snprintf( buf, len, "SHLL2 R%d", Rn ); :} nkeynes@359: SHLL8 Rn {: snprintf( buf, len, "SHLL8 R%d", Rn ); :} nkeynes@359: SHLL16 Rn {: snprintf( buf, len, "SHLL16 R%d", Rn ); :} nkeynes@359: SHLR Rn {: snprintf( buf, len, "SHLR R%d", Rn ); :} nkeynes@359: SHLR2 Rn {: snprintf( buf, len, "SHLR2 R%d", Rn ); :} nkeynes@359: SHLR8 Rn {: snprintf( buf, len, "SHLR8 R%d", Rn ); :} nkeynes@359: SHLR16 Rn {: snprintf( buf, len, "SHLR16 R%d", Rn ); :} nkeynes@359: SLEEP {: snprintf( buf, len, "SLEEP " ); :} nkeynes@359: STC SR, Rn {: snprintf( buf, len, "STC SR, R%d", Rn ); :} nkeynes@359: STC GBR, Rn {: snprintf( buf, len, "STC GBR, R%d", Rn ); :} nkeynes@359: STC VBR, Rn {: snprintf( buf, len, "STC VBR, R%d", Rn ); :} nkeynes@359: STC SSR, Rn {: snprintf( buf, len, "STC SSR, R%d", Rn ); :} nkeynes@359: STC SPC, Rn {: snprintf( buf, len, "STC SPC, R%d", Rn ); :} nkeynes@359: STC SGR, Rn {: snprintf( buf, len, "STC SGR, R%d", Rn ); :} nkeynes@359: STC DBR, Rn {: snprintf( buf, len, "STC DBR, R%d", Rn ); :} nkeynes@359: STC Rm_BANK, Rn {: snprintf( buf, len, "STC R%d_BANK, R%d", Rm_BANK, Rn ); :} nkeynes@359: STS FPSCR, Rn {: snprintf( buf, len, "STS FPSCR, R%d", Rn ); :} nkeynes@359: STS FPUL, Rn {: snprintf( buf, len, "STS FPUL, R%d", Rn ); :} nkeynes@359: STS MACH, Rn {: snprintf( buf, len, "STS MACH, R%d", Rn ); :} nkeynes@359: STS MACL, Rn {: snprintf( buf, len, "STS MACL, R%d", Rn ); :} nkeynes@359: STS PR, Rn {: snprintf( buf, len, "STS PR, R%d", Rn ); :} nkeynes@359: STC.L SR, @-Rn {: snprintf( buf, len, "STC.L SR, @-R%d", Rn ); :} nkeynes@359: STC.L GBR, @-Rn {: snprintf( buf, len, "STC.L GBR, @-R%d", Rn ); :} nkeynes@359: STC.L VBR, @-Rn {: snprintf( buf, len, "STC.L VBR, @-R%d", Rn ); :} nkeynes@359: STC.L SSR, @-Rn {: snprintf( buf, len, "STC.L SSR, @-R%d", Rn ); :} nkeynes@359: STC.L SPC, @-Rn {: snprintf( buf, len, "STC.L SPC, @-R%d", Rn ); :} nkeynes@359: STC.L SGR, @-Rn {: snprintf( buf, len, "STC.L SGR, @-R%d", Rn ); :} nkeynes@359: STC.L DBR, @-Rn {: snprintf( buf, len, "STC.L DBR, @-R%d", Rn ); :} nkeynes@359: STC.L Rm_BANK, @-Rn {: snprintf( buf, len, "STC.L @-R%d_BANK, @-R%d", Rm_BANK, Rn ); :} nkeynes@359: STS.L FPSCR, @-Rn{: snprintf( buf, len, "STS.L FPSCR, @-R%d", Rn ); :} nkeynes@359: STS.L FPUL, @-Rn {: snprintf( buf, len, "STS.L FPUL, @-R%d", Rn ); :} nkeynes@359: STS.L MACH, @-Rn {: snprintf( buf, len, "STS.L MACH, @-R%d", Rn ); :} nkeynes@359: STS.L MACL, @-Rn {: snprintf( buf, len, "STS.L MACL, @-R%d", Rn ); :} nkeynes@359: STS.L PR, @-Rn {: snprintf( buf, len, "STS.L PR, @-R%d", Rn ); :} nkeynes@359: SUB Rm, Rn {: snprintf( buf, len, "SUB R%d, R%d", Rm, Rn ); :} nkeynes@359: SUBC Rm, Rn {: snprintf( buf, len, "SUBC R%d, R%d", Rm, Rn ); :} nkeynes@359: SUBV Rm, Rn {: snprintf( buf, len, "SUBV R%d, R%d", Rm, Rn ); :} nkeynes@359: SWAP.B Rm, Rn {: snprintf( buf, len, "SWAP.B R%d, R%d", Rm, Rn ); :} nkeynes@359: SWAP.W Rm, Rn {: snprintf( buf, len, "SWAP.W R%d, R%d", Rm, Rn ); :} nkeynes@359: TAS.B @Rn {: snprintf( buf, len, "TAS.B R%d", Rn ); :} nkeynes@359: TRAPA #imm {: snprintf( buf, len, "TRAPA #%d", imm ); :} nkeynes@359: TST Rm, Rn {: snprintf( buf, len, "TST R%d, R%d", Rm, Rn ); :} nkeynes@359: TST #imm, R0 {: snprintf( buf, len, "TST #%d, R0", imm ); :} nkeynes@359: TST.B #imm, @(R0, GBR) {: snprintf( buf, len, "TST.B #%d, @(R0, GBR)", imm ); :} nkeynes@359: XOR Rm, Rn {: snprintf( buf, len, "XOR R%d, R%d", Rm, Rn ); :} nkeynes@359: XOR #imm, R0 {: snprintf( buf, len, "XOR #%d, R0", imm ); :} nkeynes@359: XOR.B #imm, @(R0, GBR) {: snprintf( buf, len, "XOR.B #%d, @(R0, GBR)", imm ); :} nkeynes@359: XTRCT Rm, Rn {: snprintf( buf, len, "XTRCT R%d, R%d", Rm, Rn ); :} nkeynes@359: UNDEF {: snprintf( buf, len, "UNDEF " ); :} nkeynes@359: %% nkeynes@359: return pc+2; nkeynes@359: } nkeynes@359: nkeynes@359: nkeynes@1300: static struct sh4_symbol *sh4_symbol_table = NULL; nkeynes@1300: static unsigned sh4_symbol_table_size = 0; nkeynes@1300: static sh4_symtab_destroy_cb sh4_symbol_table_cb = NULL; nkeynes@1300: nkeynes@1300: nkeynes@1300: static void swap_symbol( struct sh4_symbol *a, struct sh4_symbol *b ) { nkeynes@1300: struct sh4_symbol tmp; nkeynes@1300: if( a == b ) nkeynes@1300: return; nkeynes@1300: memcpy( &tmp, a, sizeof( struct sh4_symbol ) ); nkeynes@1300: memcpy( a, b, sizeof( struct sh4_symbol ) ); nkeynes@1300: memcpy( b, &tmp, sizeof( struct sh4_symbol ) ); nkeynes@1300: } nkeynes@1300: nkeynes@1300: static unsigned sort_symtab( struct sh4_symbol *table, unsigned numSymtabEntries ) { nkeynes@1300: /* Implement via simple selection sort for now; usually we don't have very nkeynes@1300: * large symbol tables. nkeynes@1300: */ nkeynes@1300: for( unsigned i = 0; i < numSymtabEntries; i++ ) { nkeynes@1300: struct sh4_symbol *next_entry = &table[i]; nkeynes@1300: for( unsigned j = i + 1; j < numSymtabEntries; ) { nkeynes@1300: if( table[j].address < next_entry->address ) { nkeynes@1300: next_entry = &table[j]; nkeynes@1300: j++; nkeynes@1300: } else if( table[j].address == next_entry->address ) { nkeynes@1300: /* Duplicate - kill it */ nkeynes@1300: swap_symbol( &table[j], &table[--numSymtabEntries] ); nkeynes@1300: } else { nkeynes@1300: j++; nkeynes@1300: } nkeynes@1300: } nkeynes@1300: swap_symbol( &table[i], next_entry ); nkeynes@1300: } nkeynes@1300: return numSymtabEntries; nkeynes@1300: } nkeynes@1300: nkeynes@1300: const char *sh4_disasm_get_symbol( sh4addr_t addr ) nkeynes@1300: { nkeynes@1300: int l = 0, h = sh4_symbol_table_size; nkeynes@1300: while( l != h ) { nkeynes@1300: int i = l + (h-l)/2; nkeynes@1300: int iaddr = sh4_symbol_table[i].address; nkeynes@1300: if( iaddr == addr ) { nkeynes@1300: return sh4_symbol_table[i].name; nkeynes@1300: } else if( iaddr > addr ) { nkeynes@1300: h = i; nkeynes@1300: } else { /* iaddr < addr */ nkeynes@1300: l = i+1; nkeynes@1300: } nkeynes@1300: } nkeynes@1300: return NULL; nkeynes@1300: } nkeynes@1300: nkeynes@1300: void sh4_set_symbol_table( struct sh4_symbol *table, unsigned size, sh4_symtab_destroy_cb callback ) nkeynes@1300: { nkeynes@1300: if( sh4_symbol_table_cb != NULL ) { nkeynes@1300: sh4_symbol_table_cb(sh4_symbol_table, sh4_symbol_table_size); nkeynes@1300: } nkeynes@1300: sh4_symbol_table = table; nkeynes@1300: sh4_symbol_table_cb = callback; nkeynes@1300: if( table == NULL ) { nkeynes@1300: sh4_symbol_table_size = 0; nkeynes@1300: } else { nkeynes@1300: sh4_symbol_table_size = sort_symtab(table, size); nkeynes@1300: } nkeynes@1300: } nkeynes@1300: nkeynes@1300: nkeynes@569: void sh4_disasm_region( FILE *f, int from, int to ) nkeynes@359: { nkeynes@359: int pc; nkeynes@359: char buf[80]; nkeynes@359: char opcode[16]; nkeynes@359: nkeynes@359: for( pc = from; pc < to; pc+=2 ) { nkeynes@359: buf[0] = '\0'; nkeynes@359: sh4_disasm_instruction( pc, nkeynes@359: buf, sizeof(buf), opcode ); nkeynes@1300: const char *sym = sh4_disasm_get_symbol( pc ); nkeynes@1300: if( sym != 0 ) { nkeynes@1300: fprintf( f, "%s:\n", sym ); nkeynes@1300: } nkeynes@359: fprintf( f, " %08x: %s %s\n", pc, opcode, buf ); nkeynes@359: } nkeynes@359: } nkeynes@706: nkeynes@706: void sh4_dump_region( int from, int to ) nkeynes@706: { nkeynes@706: sh4_disasm_region( stdout, from, to ); nkeynes@706: }