sh-dis.c revision 38889
133965Sjdp/* Disassemble SH instructions. 238889Sjdp Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. 333965Sjdp 433965SjdpThis program is free software; you can redistribute it and/or modify 533965Sjdpit under the terms of the GNU General Public License as published by 633965Sjdpthe Free Software Foundation; either version 2 of the License, or 733965Sjdp(at your option) any later version. 833965Sjdp 933965SjdpThis program is distributed in the hope that it will be useful, 1033965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1133965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1233965SjdpGNU General Public License for more details. 1333965Sjdp 1433965SjdpYou should have received a copy of the GNU General Public License 1533965Sjdpalong with this program; if not, write to the Free Software 1633965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 1733965Sjdp 1833965Sjdp#include <stdio.h> 1933965Sjdp#define STATIC_TABLE 2033965Sjdp#define DEFINE_TABLE 2133965Sjdp 2233965Sjdp#include "sh-opc.h" 2333965Sjdp#include "dis-asm.h" 2433965Sjdp 2533965Sjdp#define LITTLE_BIT 2 2633965Sjdp 2733965Sjdpstatic int 2838889Sjdpprint_insn_shx (memaddr, info) 2933965Sjdp bfd_vma memaddr; 3033965Sjdp struct disassemble_info *info; 3133965Sjdp{ 3238889Sjdp fprintf_ftype fprintf_fn = info->fprintf_func; 3333965Sjdp void *stream = info->stream; 3438889Sjdp unsigned char insn[2]; 3538889Sjdp unsigned char nibs[4]; 3633965Sjdp int status; 3738889Sjdp bfd_vma relmask = ~ (bfd_vma) 0; 3833965Sjdp sh_opcode_info *op; 3933965Sjdp 4038889Sjdp status = info->read_memory_func (memaddr, insn, 2, info); 4138889Sjdp 4233965Sjdp if (status != 0) 4333965Sjdp { 4438889Sjdp info->memory_error_func (status, memaddr, info); 4533965Sjdp return -1; 4633965Sjdp } 4733965Sjdp 4833965Sjdp if (info->flags & LITTLE_BIT) 4933965Sjdp { 5033965Sjdp nibs[0] = (insn[1] >> 4) & 0xf; 5133965Sjdp nibs[1] = insn[1] & 0xf; 5233965Sjdp 5333965Sjdp nibs[2] = (insn[0] >> 4) & 0xf; 5433965Sjdp nibs[3] = insn[0] & 0xf; 5533965Sjdp } 5633965Sjdp else 5733965Sjdp { 5833965Sjdp nibs[0] = (insn[0] >> 4) & 0xf; 5933965Sjdp nibs[1] = insn[0] & 0xf; 6033965Sjdp 6133965Sjdp nibs[2] = (insn[1] >> 4) & 0xf; 6233965Sjdp nibs[3] = insn[1] & 0xf; 6333965Sjdp } 6433965Sjdp 6533965Sjdp for (op = sh_table; op->name; op++) 6633965Sjdp { 6733965Sjdp int n; 6838889Sjdp int imm = 0; 6938889Sjdp int rn = 0; 7038889Sjdp int rm = 0; 7138889Sjdp int rb = 0; 7238889Sjdp int disp_pc; 7338889Sjdp bfd_vma disp_pc_addr = 0; 7433965Sjdp 7538889Sjdp for (n = 0; n < 4; n++) 7638889Sjdp { 7738889Sjdp int i = op->nibbles[n]; 7833965Sjdp 7938889Sjdp if (i < 16) 8038889Sjdp { 8138889Sjdp if (nibs[n] == i) 8238889Sjdp continue; 8338889Sjdp goto fail; 8438889Sjdp } 8538889Sjdp switch (i) 8638889Sjdp { 8738889Sjdp case BRANCH_8: 8838889Sjdp imm = (nibs[2] << 4) | (nibs[3]); 8938889Sjdp if (imm & 0x80) 9038889Sjdp imm |= ~0xff; 9138889Sjdp imm = ((char)imm) * 2 + 4 ; 9238889Sjdp goto ok; 9338889Sjdp case BRANCH_12: 9438889Sjdp imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]); 9538889Sjdp if (imm & 0x800) 9638889Sjdp imm |= ~0xfff; 9738889Sjdp imm = imm * 2 + 4; 9838889Sjdp goto ok; 9938889Sjdp case IMM_4: 10038889Sjdp imm = nibs[3]; 10138889Sjdp goto ok; 10238889Sjdp case IMM_4BY2: 10338889Sjdp imm = nibs[3] <<1; 10438889Sjdp goto ok; 10538889Sjdp case IMM_4BY4: 10638889Sjdp imm = nibs[3] <<2; 10738889Sjdp goto ok; 10838889Sjdp case IMM_8: 10938889Sjdp imm = (nibs[2] << 4) | nibs[3]; 11038889Sjdp goto ok; 11138889Sjdp case PCRELIMM_8BY2: 11238889Sjdp imm = ((nibs[2] << 4) | nibs[3]) <<1; 11338889Sjdp relmask = ~ (bfd_vma) 1; 11438889Sjdp goto ok; 11538889Sjdp case PCRELIMM_8BY4: 11638889Sjdp imm = ((nibs[2] << 4) | nibs[3]) <<2; 11738889Sjdp relmask = ~ (bfd_vma) 3; 11838889Sjdp goto ok; 11938889Sjdp case IMM_8BY2: 12038889Sjdp imm = ((nibs[2] << 4) | nibs[3]) <<1; 12138889Sjdp goto ok; 12238889Sjdp case IMM_8BY4: 12338889Sjdp imm = ((nibs[2] << 4) | nibs[3]) <<2; 12438889Sjdp goto ok; 12538889Sjdp case DISP_8: 12638889Sjdp imm = (nibs[2] << 4) | (nibs[3]); 12738889Sjdp goto ok; 12838889Sjdp case DISP_4: 12938889Sjdp imm = nibs[3]; 13038889Sjdp goto ok; 13138889Sjdp case REG_N: 13238889Sjdp rn = nibs[n]; 13338889Sjdp break; 13438889Sjdp case REG_M: 13538889Sjdp rm = nibs[n]; 13638889Sjdp break; 13738889Sjdp case REG_NM: 13838889Sjdp rn = (nibs[n] & 0xc) >> 2; 13938889Sjdp rm = (nibs[n] & 0x3); 14038889Sjdp break; 14138889Sjdp case REG_B: 14238889Sjdp rb = nibs[n] & 0x07; 14338889Sjdp break; 14438889Sjdp default: 14538889Sjdp abort(); 14638889Sjdp } 14738889Sjdp } 14833965Sjdp 14933965Sjdp ok: 15038889Sjdp fprintf_fn (stream,"%s\t", op->name); 15138889Sjdp disp_pc = 0; 15233965Sjdp for (n = 0; n < 3 && op->arg[n] != A_END; n++) 15333965Sjdp { 15433965Sjdp if (n && op->arg[1] != A_END) 15538889Sjdp fprintf_fn (stream, ","); 15633965Sjdp switch (op->arg[n]) 15733965Sjdp { 15833965Sjdp case A_IMM: 15938889Sjdp fprintf_fn (stream, "#%d", (char)(imm)); 16033965Sjdp break; 16133965Sjdp case A_R0: 16238889Sjdp fprintf_fn (stream, "r0"); 16333965Sjdp break; 16433965Sjdp case A_REG_N: 16538889Sjdp fprintf_fn (stream, "r%d", rn); 16633965Sjdp break; 16733965Sjdp case A_INC_N: 16838889Sjdp fprintf_fn (stream, "@r%d+", rn); 16933965Sjdp break; 17033965Sjdp case A_DEC_N: 17138889Sjdp fprintf_fn (stream, "@-r%d", rn); 17233965Sjdp break; 17333965Sjdp case A_IND_N: 17438889Sjdp fprintf_fn (stream, "@r%d", rn); 17533965Sjdp break; 17633965Sjdp case A_DISP_REG_N: 17738889Sjdp fprintf_fn (stream, "@(%d,r%d)", imm, rn); 17833965Sjdp break; 17933965Sjdp case A_REG_M: 18038889Sjdp fprintf_fn (stream, "r%d", rm); 18133965Sjdp break; 18233965Sjdp case A_INC_M: 18338889Sjdp fprintf_fn (stream, "@r%d+", rm); 18433965Sjdp break; 18533965Sjdp case A_DEC_M: 18638889Sjdp fprintf_fn (stream, "@-r%d", rm); 18733965Sjdp break; 18833965Sjdp case A_IND_M: 18938889Sjdp fprintf_fn (stream, "@r%d", rm); 19033965Sjdp break; 19133965Sjdp case A_DISP_REG_M: 19238889Sjdp fprintf_fn (stream, "@(%d,r%d)", imm, rm); 19333965Sjdp break; 19438889Sjdp case A_REG_B: 19538889Sjdp fprintf_fn (stream, "r%d_bank", rb); 19633965Sjdp break; 19733965Sjdp case A_DISP_PC: 19838889Sjdp disp_pc = 1; 19938889Sjdp disp_pc_addr = imm + 4 + (memaddr & relmask); 20038889Sjdp (*info->print_address_func) (disp_pc_addr, info); 20133965Sjdp break; 20233965Sjdp case A_IND_R0_REG_N: 20338889Sjdp fprintf_fn (stream, "@(r0,r%d)", rn); 20433965Sjdp break; 20533965Sjdp case A_IND_R0_REG_M: 20638889Sjdp fprintf_fn (stream, "@(r0,r%d)", rm); 20733965Sjdp break; 20833965Sjdp case A_DISP_GBR: 20938889Sjdp fprintf_fn (stream, "@(%d,gbr)",imm); 21033965Sjdp break; 21133965Sjdp case A_R0_GBR: 21238889Sjdp fprintf_fn (stream, "@(r0,gbr)"); 21333965Sjdp break; 21433965Sjdp case A_BDISP12: 21533965Sjdp case A_BDISP8: 21633965Sjdp (*info->print_address_func) (imm + memaddr, info); 21733965Sjdp break; 21833965Sjdp case A_SR: 21938889Sjdp fprintf_fn (stream, "sr"); 22033965Sjdp break; 22133965Sjdp case A_GBR: 22238889Sjdp fprintf_fn (stream, "gbr"); 22333965Sjdp break; 22433965Sjdp case A_VBR: 22538889Sjdp fprintf_fn (stream, "vbr"); 22633965Sjdp break; 22733965Sjdp case A_SSR: 22838889Sjdp fprintf_fn (stream, "ssr"); 22933965Sjdp break; 23033965Sjdp case A_SPC: 23138889Sjdp fprintf_fn (stream, "spc"); 23233965Sjdp break; 23333965Sjdp case A_MACH: 23438889Sjdp fprintf_fn (stream, "mach"); 23533965Sjdp break; 23633965Sjdp case A_MACL: 23738889Sjdp fprintf_fn (stream ,"macl"); 23833965Sjdp break; 23933965Sjdp case A_PR: 24038889Sjdp fprintf_fn (stream, "pr"); 24133965Sjdp break; 24238889Sjdp case A_SGR: 24338889Sjdp fprintf_fn (stream, "sgr"); 24438889Sjdp break; 24538889Sjdp case A_DBR: 24638889Sjdp fprintf_fn (stream, "dbr"); 24738889Sjdp break; 24838889Sjdp case FD_REG_N: 24938889Sjdp if (0) 25038889Sjdp goto d_reg_n; 25133965Sjdp case F_REG_N: 25238889Sjdp fprintf_fn (stream, "fr%d", rn); 25333965Sjdp break; 25433965Sjdp case F_REG_M: 25538889Sjdp fprintf_fn (stream, "fr%d", rm); 25633965Sjdp break; 25738889Sjdp case DX_REG_N: 25838889Sjdp if (rn & 1) 25938889Sjdp { 26038889Sjdp fprintf_fn (stream, "xd%d", rn & ~1); 26138889Sjdp break; 26238889Sjdp } 26338889Sjdp d_reg_n: 26438889Sjdp case D_REG_N: 26538889Sjdp fprintf_fn (stream, "dr%d", rn); 26638889Sjdp break; 26738889Sjdp case DX_REG_M: 26838889Sjdp if (rm & 1) 26938889Sjdp { 27038889Sjdp fprintf_fn (stream, "xd%d", rm & ~1); 27138889Sjdp break; 27238889Sjdp } 27338889Sjdp case D_REG_M: 27438889Sjdp fprintf_fn (stream, "dr%d", rm); 27538889Sjdp break; 27633965Sjdp case FPSCR_M: 27733965Sjdp case FPSCR_N: 27838889Sjdp fprintf_fn (stream, "fpscr"); 27933965Sjdp break; 28033965Sjdp case FPUL_M: 28133965Sjdp case FPUL_N: 28238889Sjdp fprintf_fn (stream, "fpul"); 28333965Sjdp break; 28433965Sjdp case F_FR0: 28538889Sjdp fprintf_fn (stream, "fr0"); 28633965Sjdp break; 28738889Sjdp case V_REG_N: 28838889Sjdp fprintf_fn (stream, "fv%d", rn*4); 28938889Sjdp break; 29038889Sjdp case V_REG_M: 29138889Sjdp fprintf_fn (stream, "fv%d", rm*4); 29238889Sjdp break; 29338889Sjdp case XMTRX_M4: 29438889Sjdp fprintf_fn (stream, "xmtrx"); 29538889Sjdp break; 29633965Sjdp default: 29733965Sjdp abort(); 29833965Sjdp } 29933965Sjdp } 30038889Sjdp 30138889Sjdp#if 0 30238889Sjdp /* This code prints instructions in delay slots on the same line 30338889Sjdp as the instruction which needs the delay slots. This can be 30438889Sjdp confusing, since other disassembler don't work this way, and 30538889Sjdp it means that the instructions are not all in a line. So I 30638889Sjdp disabled it. Ian. */ 30733965Sjdp if (!(info->flags & 1) 30833965Sjdp && (op->name[0] == 'j' 30933965Sjdp || (op->name[0] == 'b' 31033965Sjdp && (op->name[1] == 'r' 31133965Sjdp || op->name[1] == 's')) 31233965Sjdp || (op->name[0] == 'r' && op->name[1] == 't') 31333965Sjdp || (op->name[0] == 'b' && op->name[2] == '.'))) 31433965Sjdp { 31533965Sjdp info->flags |= 1; 31638889Sjdp fprintf_fn (stream, "\t(slot "); 31738889Sjdp print_insn_shx (memaddr + 2, info); 31833965Sjdp info->flags &= ~1; 31938889Sjdp fprintf_fn (stream, ")"); 32033965Sjdp return 4; 32133965Sjdp } 32238889Sjdp#endif 32338889Sjdp 32438889Sjdp if (disp_pc && strcmp (op->name, "mova") != 0) 32538889Sjdp { 32638889Sjdp int size; 32738889Sjdp bfd_byte bytes[4]; 32838889Sjdp 32938889Sjdp if (relmask == ~ (bfd_vma) 1) 33038889Sjdp size = 2; 33138889Sjdp else 33238889Sjdp size = 4; 33338889Sjdp status = info->read_memory_func (disp_pc_addr, bytes, size, info); 33438889Sjdp if (status == 0) 33538889Sjdp { 33638889Sjdp unsigned int val; 33738889Sjdp 33838889Sjdp if (size == 2) 33938889Sjdp { 34038889Sjdp if ((info->flags & LITTLE_BIT) != 0) 34138889Sjdp val = bfd_getl16 (bytes); 34238889Sjdp else 34338889Sjdp val = bfd_getb16 (bytes); 34438889Sjdp } 34538889Sjdp else 34638889Sjdp { 34738889Sjdp if ((info->flags & LITTLE_BIT) != 0) 34838889Sjdp val = bfd_getl32 (bytes); 34938889Sjdp else 35038889Sjdp val = bfd_getb32 (bytes); 35138889Sjdp } 35238889Sjdp fprintf_fn (stream, "\t! 0x%x", val); 35338889Sjdp } 35438889Sjdp } 35538889Sjdp 35633965Sjdp return 2; 35733965Sjdp fail: 35833965Sjdp ; 35933965Sjdp 36033965Sjdp } 36138889Sjdp fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]); 36233965Sjdp return 2; 36333965Sjdp} 36433965Sjdp 36533965Sjdpint 36638889Sjdpprint_insn_shl (memaddr, info) 36733965Sjdp bfd_vma memaddr; 36833965Sjdp struct disassemble_info *info; 36933965Sjdp{ 37033965Sjdp int r; 37138889Sjdp 37233965Sjdp info->flags = LITTLE_BIT; 37338889Sjdp r = print_insn_shx (memaddr, info); 37433965Sjdp return r; 37533965Sjdp} 37633965Sjdp 37733965Sjdpint 37838889Sjdpprint_insn_sh (memaddr, info) 37933965Sjdp bfd_vma memaddr; 38033965Sjdp struct disassemble_info *info; 38133965Sjdp{ 38233965Sjdp int r; 38338889Sjdp 38433965Sjdp info->flags = 0; 38538889Sjdp r = print_insn_shx (memaddr, info); 38633965Sjdp return r; 38733965Sjdp} 388