sh-dis.c revision 104834
133965Sjdp/* Disassemble SH instructions. 289857Sobrien Copyright 1993, 1994, 1995, 1997, 1998, 2000, 2001 385815Sobrien Free Software Foundation, Inc. 433965Sjdp 533965SjdpThis program is free software; you can redistribute it and/or modify 633965Sjdpit under the terms of the GNU General Public License as published by 733965Sjdpthe Free Software Foundation; either version 2 of the License, or 833965Sjdp(at your option) any later version. 933965Sjdp 1033965SjdpThis program is distributed in the hope that it will be useful, 1133965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1233965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1333965SjdpGNU General Public License for more details. 1433965Sjdp 1533965SjdpYou should have received a copy of the GNU General Public License 1633965Sjdpalong with this program; if not, write to the Free Software 1733965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 1833965Sjdp 1985815Sobrien#include <stdio.h> 2060484Sobrien#include "sysdep.h" 2133965Sjdp#define STATIC_TABLE 2233965Sjdp#define DEFINE_TABLE 2333965Sjdp 2433965Sjdp#include "sh-opc.h" 2533965Sjdp#include "dis-asm.h" 2633965Sjdp 2789857Sobrienstatic void print_movxy 2889857Sobrien PARAMS ((sh_opcode_info *, int, int, fprintf_ftype, void *)); 2989857Sobrienstatic void print_insn_ddt PARAMS ((int, struct disassemble_info *)); 3089857Sobrienstatic void print_dsp_reg PARAMS ((int, fprintf_ftype, void *)); 3189857Sobrienstatic void print_insn_ppi PARAMS ((int, struct disassemble_info *)); 3289857Sobrien 3360484Sobrienstatic void 3460484Sobrienprint_movxy (op, rn, rm, fprintf_fn, stream) 3560484Sobrien sh_opcode_info *op; 3660484Sobrien int rn, rm; 3760484Sobrien fprintf_ftype fprintf_fn; 3860484Sobrien void *stream; 3960484Sobrien{ 4060484Sobrien int n; 4160484Sobrien 4285815Sobrien fprintf_fn (stream, "%s\t", op->name); 4360484Sobrien for (n = 0; n < 2; n++) 4460484Sobrien { 4560484Sobrien switch (op->arg[n]) 4660484Sobrien { 4760484Sobrien case A_IND_N: 4885815Sobrien fprintf_fn (stream, "@r%d", rn); 4960484Sobrien break; 5060484Sobrien case A_INC_N: 5185815Sobrien fprintf_fn (stream, "@r%d+", rn); 5260484Sobrien break; 5360484Sobrien case A_PMOD_N: 5485815Sobrien fprintf_fn (stream, "@r%d+r8", rn); 5560484Sobrien break; 5660484Sobrien case A_PMODY_N: 5785815Sobrien fprintf_fn (stream, "@r%d+r9", rn); 5860484Sobrien break; 5960484Sobrien case DSP_REG_M: 6060484Sobrien fprintf_fn (stream, "a%c", '0' + rm); 6160484Sobrien break; 6260484Sobrien case DSP_REG_X: 6360484Sobrien fprintf_fn (stream, "x%c", '0' + rm); 6460484Sobrien break; 6560484Sobrien case DSP_REG_Y: 6660484Sobrien fprintf_fn (stream, "y%c", '0' + rm); 6760484Sobrien break; 6860484Sobrien default: 6960484Sobrien abort (); 7060484Sobrien } 7160484Sobrien if (n == 0) 7285815Sobrien fprintf_fn (stream, ","); 7360484Sobrien } 7460484Sobrien} 7560484Sobrien 7660484Sobrien/* Print a double data transfer insn. INSN is just the lower three 7760484Sobrien nibbles of the insn, i.e. field a and the bit that indicates if 7860484Sobrien a parallel processing insn follows. 7960484Sobrien Return nonzero if a field b of a parallel processing insns follows. */ 8085815Sobrien 8160484Sobrienstatic void 8260484Sobrienprint_insn_ddt (insn, info) 8360484Sobrien int insn; 8460484Sobrien struct disassemble_info *info; 8560484Sobrien{ 8660484Sobrien fprintf_ftype fprintf_fn = info->fprintf_func; 8760484Sobrien void *stream = info->stream; 8860484Sobrien 8960484Sobrien /* If this is just a nop, make sure to emit something. */ 9060484Sobrien if (insn == 0x000) 9160484Sobrien fprintf_fn (stream, "nopx\tnopy"); 9260484Sobrien 9360484Sobrien /* If a parallel processing insn was printed before, 9460484Sobrien and we got a non-nop, emit a tab. */ 9560484Sobrien if ((insn & 0x800) && (insn & 0x3ff)) 9660484Sobrien fprintf_fn (stream, "\t"); 9760484Sobrien 9860484Sobrien /* Check if either the x or y part is invalid. */ 9960484Sobrien if (((insn & 0xc) == 0 && (insn & 0x2a0)) 10060484Sobrien || ((insn & 3) == 0 && (insn & 0x150))) 10160484Sobrien fprintf_fn (stream, ".word 0x%x", insn); 10260484Sobrien else 10360484Sobrien { 10460484Sobrien static sh_opcode_info *first_movx, *first_movy; 10560484Sobrien sh_opcode_info *opx, *opy; 10685815Sobrien unsigned int insn_x, insn_y; 10760484Sobrien 10860484Sobrien if (! first_movx) 10960484Sobrien { 11085815Sobrien for (first_movx = sh_table; first_movx->nibbles[1] != MOVX;) 11160484Sobrien first_movx++; 11285815Sobrien for (first_movy = first_movx; first_movy->nibbles[1] != MOVY;) 11360484Sobrien first_movy++; 11460484Sobrien } 11560484Sobrien insn_x = (insn >> 2) & 0xb; 11660484Sobrien if (insn_x) 11760484Sobrien { 11885815Sobrien for (opx = first_movx; opx->nibbles[2] != insn_x;) 11985815Sobrien opx++; 12060484Sobrien print_movxy (opx, ((insn >> 9) & 1) + 4, (insn >> 7) & 1, 12160484Sobrien fprintf_fn, stream); 12260484Sobrien } 12360484Sobrien insn_y = (insn & 3) | ((insn >> 1) & 8); 12460484Sobrien if (insn_y) 12560484Sobrien { 12660484Sobrien if (insn_x) 12760484Sobrien fprintf_fn (stream, "\t"); 12885815Sobrien for (opy = first_movy; opy->nibbles[2] != insn_y;) 12985815Sobrien opy++; 13060484Sobrien print_movxy (opy, ((insn >> 8) & 1) + 6, (insn >> 6) & 1, 13160484Sobrien fprintf_fn, stream); 13260484Sobrien } 13360484Sobrien } 13460484Sobrien} 13560484Sobrien 13660484Sobrienstatic void 13760484Sobrienprint_dsp_reg (rm, fprintf_fn, stream) 13860484Sobrien int rm; 13960484Sobrien fprintf_ftype fprintf_fn; 14060484Sobrien void *stream; 14160484Sobrien{ 14260484Sobrien switch (rm) 14360484Sobrien { 14460484Sobrien case A_A1_NUM: 14560484Sobrien fprintf_fn (stream, "a1"); 14660484Sobrien break; 14760484Sobrien case A_A0_NUM: 14860484Sobrien fprintf_fn (stream, "a0"); 14960484Sobrien break; 15060484Sobrien case A_X0_NUM: 15160484Sobrien fprintf_fn (stream, "x0"); 15260484Sobrien break; 15360484Sobrien case A_X1_NUM: 15460484Sobrien fprintf_fn (stream, "x1"); 15560484Sobrien break; 15660484Sobrien case A_Y0_NUM: 15760484Sobrien fprintf_fn (stream, "y0"); 15860484Sobrien break; 15960484Sobrien case A_Y1_NUM: 16060484Sobrien fprintf_fn (stream, "y1"); 16160484Sobrien break; 16260484Sobrien case A_M0_NUM: 16360484Sobrien fprintf_fn (stream, "m0"); 16460484Sobrien break; 16560484Sobrien case A_A1G_NUM: 16660484Sobrien fprintf_fn (stream, "a1g"); 16760484Sobrien break; 16860484Sobrien case A_M1_NUM: 16960484Sobrien fprintf_fn (stream, "m1"); 17060484Sobrien break; 17160484Sobrien case A_A0G_NUM: 17260484Sobrien fprintf_fn (stream, "a0g"); 17360484Sobrien break; 17460484Sobrien default: 17560484Sobrien fprintf_fn (stream, "0x%x", rm); 17660484Sobrien break; 17760484Sobrien } 17860484Sobrien} 17960484Sobrien 18060484Sobrienstatic void 18160484Sobrienprint_insn_ppi (field_b, info) 18260484Sobrien int field_b; 18360484Sobrien struct disassemble_info *info; 18460484Sobrien{ 18585815Sobrien static char *sx_tab[] = { "x0", "x1", "a0", "a1" }; 18685815Sobrien static char *sy_tab[] = { "y0", "y1", "m0", "m1" }; 18760484Sobrien fprintf_ftype fprintf_fn = info->fprintf_func; 18860484Sobrien void *stream = info->stream; 18985815Sobrien unsigned int nib1, nib2, nib3; 19085815Sobrien char *dc = NULL; 19160484Sobrien sh_opcode_info *op; 19260484Sobrien 19360484Sobrien if ((field_b & 0xe800) == 0) 19460484Sobrien { 19560484Sobrien fprintf_fn (stream, "psh%c\t#%d,", 19660484Sobrien field_b & 0x1000 ? 'a' : 'l', 19760484Sobrien (field_b >> 4) & 127); 19860484Sobrien print_dsp_reg (field_b & 0xf, fprintf_fn, stream); 19960484Sobrien return; 20060484Sobrien } 20160484Sobrien if ((field_b & 0xc000) == 0x4000 && (field_b & 0x3000) != 0x1000) 20260484Sobrien { 20385815Sobrien static char *du_tab[] = { "x0", "y0", "a0", "a1" }; 20485815Sobrien static char *se_tab[] = { "x0", "x1", "y0", "a1" }; 20585815Sobrien static char *sf_tab[] = { "y0", "y1", "x0", "a1" }; 20685815Sobrien static char *sg_tab[] = { "m0", "m1", "a0", "a1" }; 20760484Sobrien 20860484Sobrien if (field_b & 0x2000) 20960484Sobrien { 21060484Sobrien fprintf_fn (stream, "p%s %s,%s,%s\t", 21160484Sobrien (field_b & 0x1000) ? "add" : "sub", 21260484Sobrien sx_tab[(field_b >> 6) & 3], 21360484Sobrien sy_tab[(field_b >> 4) & 3], 21460484Sobrien du_tab[(field_b >> 0) & 3]); 21560484Sobrien } 21660484Sobrien fprintf_fn (stream, "pmuls%c%s,%s,%s", 21760484Sobrien field_b & 0x2000 ? ' ' : '\t', 21860484Sobrien se_tab[(field_b >> 10) & 3], 21960484Sobrien sf_tab[(field_b >> 8) & 3], 22060484Sobrien sg_tab[(field_b >> 2) & 3]); 22160484Sobrien return; 22260484Sobrien } 22360484Sobrien 22460484Sobrien nib1 = PPIC; 22560484Sobrien nib2 = field_b >> 12 & 0xf; 22660484Sobrien nib3 = field_b >> 8 & 0xf; 22760484Sobrien switch (nib3 & 0x3) 22860484Sobrien { 22960484Sobrien case 0: 23060484Sobrien dc = ""; 23160484Sobrien nib1 = PPI3; 23260484Sobrien break; 23360484Sobrien case 1: 23460484Sobrien dc = ""; 23560484Sobrien break; 23660484Sobrien case 2: 23760484Sobrien dc = "dct "; 23860484Sobrien nib3 -= 1; 23960484Sobrien break; 24060484Sobrien case 3: 24160484Sobrien dc = "dcf "; 24260484Sobrien nib3 -= 2; 24360484Sobrien break; 24460484Sobrien } 24560484Sobrien for (op = sh_table; op->name; op++) 24660484Sobrien { 24760484Sobrien if (op->nibbles[1] == nib1 24860484Sobrien && op->nibbles[2] == nib2 24960484Sobrien && op->nibbles[3] == nib3) 25060484Sobrien { 25160484Sobrien int n; 25260484Sobrien 25360484Sobrien fprintf_fn (stream, "%s%s\t", dc, op->name); 25485815Sobrien for (n = 0; n < 3 && op->arg[n] != A_END; n++) 25560484Sobrien { 25660484Sobrien if (n && op->arg[1] != A_END) 25760484Sobrien fprintf_fn (stream, ","); 25885815Sobrien switch (op->arg[n]) 25960484Sobrien { 26060484Sobrien case DSP_REG_N: 26160484Sobrien print_dsp_reg (field_b & 0xf, fprintf_fn, stream); 26260484Sobrien break; 26360484Sobrien case DSP_REG_X: 26460484Sobrien fprintf_fn (stream, sx_tab[(field_b >> 6) & 3]); 26560484Sobrien break; 26660484Sobrien case DSP_REG_Y: 26760484Sobrien fprintf_fn (stream, sy_tab[(field_b >> 4) & 3]); 26860484Sobrien break; 26960484Sobrien case A_MACH: 27060484Sobrien fprintf_fn (stream, "mach"); 27160484Sobrien break; 27260484Sobrien case A_MACL: 27385815Sobrien fprintf_fn (stream, "macl"); 27460484Sobrien break; 27560484Sobrien default: 27660484Sobrien abort (); 27760484Sobrien } 27860484Sobrien } 27960484Sobrien return; 28060484Sobrien } 28160484Sobrien } 28260484Sobrien /* Not found. */ 28360484Sobrien fprintf_fn (stream, ".word 0x%x", field_b); 28460484Sobrien} 28560484Sobrien 286104834Sobrienint 287104834Sobrienprint_insn_sh (memaddr, info) 28833965Sjdp bfd_vma memaddr; 28933965Sjdp struct disassemble_info *info; 29033965Sjdp{ 29138889Sjdp fprintf_ftype fprintf_fn = info->fprintf_func; 29233965Sjdp void *stream = info->stream; 29338889Sjdp unsigned char insn[2]; 29438889Sjdp unsigned char nibs[4]; 29533965Sjdp int status; 29685815Sobrien bfd_vma relmask = ~(bfd_vma) 0; 29733965Sjdp sh_opcode_info *op; 29860484Sobrien int target_arch; 29933965Sjdp 30060484Sobrien switch (info->mach) 30160484Sobrien { 30260484Sobrien case bfd_mach_sh: 30360484Sobrien target_arch = arch_sh1; 304104834Sobrien /* SH coff object files lack information about the machine type, so 305104834Sobrien we end up with bfd_mach_sh unless it was set explicitly (which 306104834Sobrien could have happended if this is a call from gdb or the simulator.) */ 307104834Sobrien if (info->symbols 308104834Sobrien && bfd_asymbol_flavour(*info->symbols) == bfd_target_coff_flavour) 309104834Sobrien target_arch = arch_sh4; 31060484Sobrien break; 31160484Sobrien case bfd_mach_sh2: 31260484Sobrien target_arch = arch_sh2; 31360484Sobrien break; 31460484Sobrien case bfd_mach_sh_dsp: 31560484Sobrien target_arch = arch_sh_dsp; 31660484Sobrien break; 31760484Sobrien case bfd_mach_sh3: 31860484Sobrien target_arch = arch_sh3; 31960484Sobrien break; 32060484Sobrien case bfd_mach_sh3_dsp: 32160484Sobrien target_arch = arch_sh3_dsp; 32260484Sobrien break; 32360484Sobrien case bfd_mach_sh3e: 32460484Sobrien target_arch = arch_sh3e; 32560484Sobrien break; 32660484Sobrien case bfd_mach_sh4: 32760484Sobrien target_arch = arch_sh4; 32860484Sobrien break; 32991041Sobrien case bfd_mach_sh5: 330104834Sobrien#ifdef INCLUDE_SHMEDIA 331104834Sobrien status = print_insn_sh64 (memaddr, info); 332104834Sobrien if (status != -2) 333104834Sobrien return status; 334104834Sobrien#endif 33591041Sobrien /* When we get here for sh64, it's because we want to disassemble 33691041Sobrien SHcompact, i.e. arch_sh4. */ 33791041Sobrien target_arch = arch_sh4; 33891041Sobrien break; 33960484Sobrien default: 34060484Sobrien abort (); 34160484Sobrien } 34260484Sobrien 34338889Sjdp status = info->read_memory_func (memaddr, insn, 2, info); 34438889Sjdp 34585815Sobrien if (status != 0) 34633965Sjdp { 34738889Sjdp info->memory_error_func (status, memaddr, info); 34833965Sjdp return -1; 34933965Sjdp } 35033965Sjdp 351104834Sobrien if (info->endian == BFD_ENDIAN_LITTLE) 35233965Sjdp { 35333965Sjdp nibs[0] = (insn[1] >> 4) & 0xf; 35433965Sjdp nibs[1] = insn[1] & 0xf; 35533965Sjdp 35633965Sjdp nibs[2] = (insn[0] >> 4) & 0xf; 35733965Sjdp nibs[3] = insn[0] & 0xf; 35833965Sjdp } 35985815Sobrien else 36033965Sjdp { 36133965Sjdp nibs[0] = (insn[0] >> 4) & 0xf; 36233965Sjdp nibs[1] = insn[0] & 0xf; 36333965Sjdp 36433965Sjdp nibs[2] = (insn[1] >> 4) & 0xf; 36533965Sjdp nibs[3] = insn[1] & 0xf; 36633965Sjdp } 36733965Sjdp 36860484Sobrien if (nibs[0] == 0xf && (nibs[1] & 4) == 0 && target_arch & arch_sh_dsp_up) 36960484Sobrien { 37060484Sobrien if (nibs[1] & 8) 37160484Sobrien { 37260484Sobrien int field_b; 37360484Sobrien 37460484Sobrien status = info->read_memory_func (memaddr + 2, insn, 2, info); 37560484Sobrien 37685815Sobrien if (status != 0) 37760484Sobrien { 37860484Sobrien info->memory_error_func (status, memaddr + 2, info); 37960484Sobrien return -1; 38060484Sobrien } 38160484Sobrien 382104834Sobrien if (info->endian == BFD_ENDIAN_LITTLE) 38360484Sobrien field_b = insn[1] << 8 | insn[0]; 38460484Sobrien else 38560484Sobrien field_b = insn[0] << 8 | insn[1]; 38660484Sobrien 38760484Sobrien print_insn_ppi (field_b, info); 38860484Sobrien print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info); 38960484Sobrien return 4; 39060484Sobrien } 39160484Sobrien print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info); 39260484Sobrien return 2; 39360484Sobrien } 39485815Sobrien for (op = sh_table; op->name; op++) 39533965Sjdp { 39633965Sjdp int n; 39738889Sjdp int imm = 0; 39838889Sjdp int rn = 0; 39938889Sjdp int rm = 0; 40038889Sjdp int rb = 0; 40138889Sjdp int disp_pc; 40238889Sjdp bfd_vma disp_pc_addr = 0; 40333965Sjdp 40460484Sobrien if ((op->arch & target_arch) == 0) 40560484Sobrien goto fail; 40638889Sjdp for (n = 0; n < 4; n++) 40738889Sjdp { 40838889Sjdp int i = op->nibbles[n]; 40933965Sjdp 41085815Sobrien if (i < 16) 41138889Sjdp { 41238889Sjdp if (nibs[n] == i) 41338889Sjdp continue; 41438889Sjdp goto fail; 41538889Sjdp } 41638889Sjdp switch (i) 41738889Sjdp { 41838889Sjdp case BRANCH_8: 41985815Sobrien imm = (nibs[2] << 4) | (nibs[3]); 42038889Sjdp if (imm & 0x80) 42138889Sjdp imm |= ~0xff; 42285815Sobrien imm = ((char) imm) * 2 + 4; 42338889Sjdp goto ok; 42438889Sjdp case BRANCH_12: 42538889Sjdp imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]); 42638889Sjdp if (imm & 0x800) 42738889Sjdp imm |= ~0xfff; 42838889Sjdp imm = imm * 2 + 4; 42938889Sjdp goto ok; 43085815Sobrien case IMM0_4: 43185815Sobrien case IMM1_4: 43238889Sjdp imm = nibs[3]; 43338889Sjdp goto ok; 43485815Sobrien case IMM0_4BY2: 43585815Sobrien case IMM1_4BY2: 43685815Sobrien imm = nibs[3] << 1; 43738889Sjdp goto ok; 43885815Sobrien case IMM0_4BY4: 43985815Sobrien case IMM1_4BY4: 44085815Sobrien imm = nibs[3] << 2; 44138889Sjdp goto ok; 44285815Sobrien case IMM0_8: 44385815Sobrien case IMM1_8: 44438889Sjdp imm = (nibs[2] << 4) | nibs[3]; 44538889Sjdp goto ok; 44638889Sjdp case PCRELIMM_8BY2: 44785815Sobrien imm = ((nibs[2] << 4) | nibs[3]) << 1; 44885815Sobrien relmask = ~(bfd_vma) 1; 44938889Sjdp goto ok; 45038889Sjdp case PCRELIMM_8BY4: 45185815Sobrien imm = ((nibs[2] << 4) | nibs[3]) << 2; 45285815Sobrien relmask = ~(bfd_vma) 3; 45338889Sjdp goto ok; 45485815Sobrien case IMM0_8BY2: 45585815Sobrien case IMM1_8BY2: 45685815Sobrien imm = ((nibs[2] << 4) | nibs[3]) << 1; 45738889Sjdp goto ok; 45885815Sobrien case IMM0_8BY4: 45985815Sobrien case IMM1_8BY4: 46085815Sobrien imm = ((nibs[2] << 4) | nibs[3]) << 2; 46138889Sjdp goto ok; 46238889Sjdp case REG_N: 46338889Sjdp rn = nibs[n]; 46438889Sjdp break; 46538889Sjdp case REG_M: 46638889Sjdp rm = nibs[n]; 46738889Sjdp break; 46838889Sjdp case REG_NM: 46938889Sjdp rn = (nibs[n] & 0xc) >> 2; 47038889Sjdp rm = (nibs[n] & 0x3); 47138889Sjdp break; 47238889Sjdp case REG_B: 47338889Sjdp rb = nibs[n] & 0x07; 47485815Sobrien break; 47560484Sobrien case SDT_REG_N: 47660484Sobrien /* sh-dsp: single data transfer. */ 47760484Sobrien rn = nibs[n]; 47860484Sobrien if ((rn & 0xc) != 4) 47960484Sobrien goto fail; 48060484Sobrien rn = rn & 0x3; 48185815Sobrien rn |= (!(rn & 2)) << 2; 48260484Sobrien break; 48360484Sobrien case PPI: 48485815Sobrien case REPEAT: 48560484Sobrien goto fail; 48638889Sjdp default: 48785815Sobrien abort (); 48838889Sjdp } 48938889Sjdp } 49033965Sjdp 49133965Sjdp ok: 49285815Sobrien fprintf_fn (stream, "%s\t", op->name); 49338889Sjdp disp_pc = 0; 49485815Sobrien for (n = 0; n < 3 && op->arg[n] != A_END; n++) 49533965Sjdp { 49633965Sjdp if (n && op->arg[1] != A_END) 49738889Sjdp fprintf_fn (stream, ","); 49885815Sobrien switch (op->arg[n]) 49933965Sjdp { 50033965Sjdp case A_IMM: 50185815Sobrien fprintf_fn (stream, "#%d", (char) (imm)); 50233965Sjdp break; 50333965Sjdp case A_R0: 50438889Sjdp fprintf_fn (stream, "r0"); 50533965Sjdp break; 50633965Sjdp case A_REG_N: 50738889Sjdp fprintf_fn (stream, "r%d", rn); 50833965Sjdp break; 50933965Sjdp case A_INC_N: 51085815Sobrien fprintf_fn (stream, "@r%d+", rn); 51133965Sjdp break; 51233965Sjdp case A_DEC_N: 51385815Sobrien fprintf_fn (stream, "@-r%d", rn); 51433965Sjdp break; 51533965Sjdp case A_IND_N: 51685815Sobrien fprintf_fn (stream, "@r%d", rn); 51733965Sjdp break; 51833965Sjdp case A_DISP_REG_N: 51985815Sobrien fprintf_fn (stream, "@(%d,r%d)", imm, rn); 52033965Sjdp break; 52160484Sobrien case A_PMOD_N: 52285815Sobrien fprintf_fn (stream, "@r%d+r8", rn); 52360484Sobrien break; 52433965Sjdp case A_REG_M: 52538889Sjdp fprintf_fn (stream, "r%d", rm); 52633965Sjdp break; 52733965Sjdp case A_INC_M: 52885815Sobrien fprintf_fn (stream, "@r%d+", rm); 52933965Sjdp break; 53033965Sjdp case A_DEC_M: 53185815Sobrien fprintf_fn (stream, "@-r%d", rm); 53233965Sjdp break; 53333965Sjdp case A_IND_M: 53485815Sobrien fprintf_fn (stream, "@r%d", rm); 53533965Sjdp break; 53633965Sjdp case A_DISP_REG_M: 53785815Sobrien fprintf_fn (stream, "@(%d,r%d)", imm, rm); 53833965Sjdp break; 53938889Sjdp case A_REG_B: 54038889Sjdp fprintf_fn (stream, "r%d_bank", rb); 54133965Sjdp break; 54233965Sjdp case A_DISP_PC: 54338889Sjdp disp_pc = 1; 54438889Sjdp disp_pc_addr = imm + 4 + (memaddr & relmask); 54538889Sjdp (*info->print_address_func) (disp_pc_addr, info); 54633965Sjdp break; 54733965Sjdp case A_IND_R0_REG_N: 54838889Sjdp fprintf_fn (stream, "@(r0,r%d)", rn); 54985815Sobrien break; 55033965Sjdp case A_IND_R0_REG_M: 55138889Sjdp fprintf_fn (stream, "@(r0,r%d)", rm); 55285815Sobrien break; 55333965Sjdp case A_DISP_GBR: 55485815Sobrien fprintf_fn (stream, "@(%d,gbr)", imm); 55533965Sjdp break; 55633965Sjdp case A_R0_GBR: 55738889Sjdp fprintf_fn (stream, "@(r0,gbr)"); 55833965Sjdp break; 55933965Sjdp case A_BDISP12: 56033965Sjdp case A_BDISP8: 56133965Sjdp (*info->print_address_func) (imm + memaddr, info); 56233965Sjdp break; 56333965Sjdp case A_SR: 56438889Sjdp fprintf_fn (stream, "sr"); 56533965Sjdp break; 56633965Sjdp case A_GBR: 56738889Sjdp fprintf_fn (stream, "gbr"); 56833965Sjdp break; 56933965Sjdp case A_VBR: 57038889Sjdp fprintf_fn (stream, "vbr"); 57133965Sjdp break; 57260484Sobrien case A_DSR: 57360484Sobrien fprintf_fn (stream, "dsr"); 57460484Sobrien break; 57560484Sobrien case A_MOD: 57660484Sobrien fprintf_fn (stream, "mod"); 57760484Sobrien break; 57860484Sobrien case A_RE: 57960484Sobrien fprintf_fn (stream, "re"); 58060484Sobrien break; 58160484Sobrien case A_RS: 58260484Sobrien fprintf_fn (stream, "rs"); 58360484Sobrien break; 58460484Sobrien case A_A0: 58560484Sobrien fprintf_fn (stream, "a0"); 58660484Sobrien break; 58760484Sobrien case A_X0: 58860484Sobrien fprintf_fn (stream, "x0"); 58960484Sobrien break; 59060484Sobrien case A_X1: 59160484Sobrien fprintf_fn (stream, "x1"); 59260484Sobrien break; 59360484Sobrien case A_Y0: 59460484Sobrien fprintf_fn (stream, "y0"); 59560484Sobrien break; 59660484Sobrien case A_Y1: 59760484Sobrien fprintf_fn (stream, "y1"); 59860484Sobrien break; 59960484Sobrien case DSP_REG_M: 60060484Sobrien print_dsp_reg (rm, fprintf_fn, stream); 60160484Sobrien break; 60233965Sjdp case A_SSR: 60338889Sjdp fprintf_fn (stream, "ssr"); 60433965Sjdp break; 60533965Sjdp case A_SPC: 60638889Sjdp fprintf_fn (stream, "spc"); 60733965Sjdp break; 60833965Sjdp case A_MACH: 60938889Sjdp fprintf_fn (stream, "mach"); 61033965Sjdp break; 61133965Sjdp case A_MACL: 61285815Sobrien fprintf_fn (stream, "macl"); 61333965Sjdp break; 61433965Sjdp case A_PR: 61538889Sjdp fprintf_fn (stream, "pr"); 61633965Sjdp break; 61738889Sjdp case A_SGR: 61838889Sjdp fprintf_fn (stream, "sgr"); 61938889Sjdp break; 62038889Sjdp case A_DBR: 62138889Sjdp fprintf_fn (stream, "dbr"); 62238889Sjdp break; 62333965Sjdp case F_REG_N: 62438889Sjdp fprintf_fn (stream, "fr%d", rn); 62533965Sjdp break; 62633965Sjdp case F_REG_M: 62738889Sjdp fprintf_fn (stream, "fr%d", rm); 62833965Sjdp break; 62938889Sjdp case DX_REG_N: 63038889Sjdp if (rn & 1) 63138889Sjdp { 63238889Sjdp fprintf_fn (stream, "xd%d", rn & ~1); 63338889Sjdp break; 63438889Sjdp } 63538889Sjdp case D_REG_N: 63638889Sjdp fprintf_fn (stream, "dr%d", rn); 63738889Sjdp break; 63838889Sjdp case DX_REG_M: 63938889Sjdp if (rm & 1) 64038889Sjdp { 64138889Sjdp fprintf_fn (stream, "xd%d", rm & ~1); 64238889Sjdp break; 64338889Sjdp } 64438889Sjdp case D_REG_M: 64538889Sjdp fprintf_fn (stream, "dr%d", rm); 64638889Sjdp break; 64733965Sjdp case FPSCR_M: 64833965Sjdp case FPSCR_N: 64938889Sjdp fprintf_fn (stream, "fpscr"); 65033965Sjdp break; 65133965Sjdp case FPUL_M: 65233965Sjdp case FPUL_N: 65338889Sjdp fprintf_fn (stream, "fpul"); 65433965Sjdp break; 65533965Sjdp case F_FR0: 65638889Sjdp fprintf_fn (stream, "fr0"); 65733965Sjdp break; 65838889Sjdp case V_REG_N: 65985815Sobrien fprintf_fn (stream, "fv%d", rn * 4); 66038889Sjdp break; 66138889Sjdp case V_REG_M: 66285815Sobrien fprintf_fn (stream, "fv%d", rm * 4); 66338889Sjdp break; 66438889Sjdp case XMTRX_M4: 66538889Sjdp fprintf_fn (stream, "xmtrx"); 66638889Sjdp break; 66733965Sjdp default: 66885815Sobrien abort (); 66933965Sjdp } 67033965Sjdp } 67138889Sjdp 67238889Sjdp#if 0 67338889Sjdp /* This code prints instructions in delay slots on the same line 67438889Sjdp as the instruction which needs the delay slots. This can be 67538889Sjdp confusing, since other disassembler don't work this way, and 67638889Sjdp it means that the instructions are not all in a line. So I 67738889Sjdp disabled it. Ian. */ 67833965Sjdp if (!(info->flags & 1) 67933965Sjdp && (op->name[0] == 'j' 68033965Sjdp || (op->name[0] == 'b' 68185815Sobrien && (op->name[1] == 'r' 68233965Sjdp || op->name[1] == 's')) 68333965Sjdp || (op->name[0] == 'r' && op->name[1] == 't') 68433965Sjdp || (op->name[0] == 'b' && op->name[2] == '.'))) 68533965Sjdp { 68633965Sjdp info->flags |= 1; 68738889Sjdp fprintf_fn (stream, "\t(slot "); 688104834Sobrien print_insn_sh (memaddr + 2, info); 68933965Sjdp info->flags &= ~1; 69038889Sjdp fprintf_fn (stream, ")"); 69133965Sjdp return 4; 69233965Sjdp } 69338889Sjdp#endif 69438889Sjdp 69538889Sjdp if (disp_pc && strcmp (op->name, "mova") != 0) 69638889Sjdp { 69738889Sjdp int size; 69838889Sjdp bfd_byte bytes[4]; 69938889Sjdp 70085815Sobrien if (relmask == ~(bfd_vma) 1) 70138889Sjdp size = 2; 70238889Sjdp else 70338889Sjdp size = 4; 70438889Sjdp status = info->read_memory_func (disp_pc_addr, bytes, size, info); 70538889Sjdp if (status == 0) 70638889Sjdp { 70738889Sjdp unsigned int val; 70838889Sjdp 70938889Sjdp if (size == 2) 71038889Sjdp { 711104834Sobrien if (info->endian == BFD_ENDIAN_LITTLE) 71238889Sjdp val = bfd_getl16 (bytes); 71338889Sjdp else 71438889Sjdp val = bfd_getb16 (bytes); 71538889Sjdp } 71638889Sjdp else 71738889Sjdp { 718104834Sobrien if (info->endian == BFD_ENDIAN_LITTLE) 71938889Sjdp val = bfd_getl32 (bytes); 72038889Sjdp else 72138889Sjdp val = bfd_getb32 (bytes); 72238889Sjdp } 72338889Sjdp fprintf_fn (stream, "\t! 0x%x", val); 72438889Sjdp } 72538889Sjdp } 72638889Sjdp 72733965Sjdp return 2; 72833965Sjdp fail: 72933965Sjdp ; 73033965Sjdp 73133965Sjdp } 73238889Sjdp fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]); 73333965Sjdp return 2; 73433965Sjdp} 735