Back to index

cell-binutils  2.17cvs20070401
sh-dis.c
Go to the documentation of this file.
00001 /* Disassemble SH instructions.
00002    Copyright 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005
00003    Free Software Foundation, Inc.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
00018    MA 02110-1301, USA.  */
00019 
00020 #include <stdio.h>
00021 #include "sysdep.h"
00022 #define STATIC_TABLE
00023 #define DEFINE_TABLE
00024 
00025 #include "sh-opc.h"
00026 #include "dis-asm.h"
00027 
00028 #ifdef ARCH_all
00029 #define INCLUDE_SHMEDIA
00030 #endif
00031 
00032 static void
00033 print_movxy (const sh_opcode_info *op,
00034             int rn,
00035             int rm,
00036             fprintf_ftype fprintf_fn,
00037             void *stream)
00038 {
00039   int n;
00040 
00041   fprintf_fn (stream, "%s\t", op->name);
00042   for (n = 0; n < 2; n++)
00043     {
00044       switch (op->arg[n])
00045        {
00046        case A_IND_N:
00047        case AX_IND_N:
00048        case AXY_IND_N:
00049        case AY_IND_N:
00050        case AYX_IND_N:
00051          fprintf_fn (stream, "@r%d", rn);
00052          break;
00053        case A_INC_N:
00054        case AX_INC_N:
00055        case AXY_INC_N:
00056        case AY_INC_N:
00057        case AYX_INC_N:
00058          fprintf_fn (stream, "@r%d+", rn);
00059          break;
00060        case AX_PMOD_N:
00061        case AXY_PMOD_N:
00062          fprintf_fn (stream, "@r%d+r8", rn);
00063          break;
00064        case AY_PMOD_N:
00065        case AYX_PMOD_N:
00066          fprintf_fn (stream, "@r%d+r9", rn);
00067          break;
00068        case DSP_REG_A_M:
00069          fprintf_fn (stream, "a%c", '0' + rm);
00070          break;
00071        case DSP_REG_X:
00072          fprintf_fn (stream, "x%c", '0' + rm);
00073          break;
00074        case DSP_REG_Y:
00075          fprintf_fn (stream, "y%c", '0' + rm);
00076          break;
00077        case DSP_REG_AX:
00078          fprintf_fn (stream, "%c%c",
00079                     (rm & 1) ? 'x' : 'a',
00080                     (rm & 2) ? '1' : '0');
00081          break;
00082        case DSP_REG_XY:
00083          fprintf_fn (stream, "%c%c",
00084                     (rm & 1) ? 'y' : 'x',
00085                     (rm & 2) ? '1' : '0');
00086          break;
00087        case DSP_REG_AY:
00088          fprintf_fn (stream, "%c%c",
00089                     (rm & 2) ? 'y' : 'a',
00090                     (rm & 1) ? '1' : '0');
00091          break;
00092        case DSP_REG_YX:
00093          fprintf_fn (stream, "%c%c",
00094                     (rm & 2) ? 'x' : 'y',
00095                     (rm & 1) ? '1' : '0');
00096          break;
00097        default:
00098          abort ();
00099        }
00100       if (n == 0)
00101        fprintf_fn (stream, ",");
00102     }
00103 }
00104 
00105 /* Print a double data transfer insn.  INSN is just the lower three
00106    nibbles of the insn, i.e. field a and the bit that indicates if
00107    a parallel processing insn follows.
00108    Return nonzero if a field b of a parallel processing insns follows.  */
00109 
00110 static void
00111 print_insn_ddt (int insn, struct disassemble_info *info)
00112 {
00113   fprintf_ftype fprintf_fn = info->fprintf_func;
00114   void *stream = info->stream;
00115 
00116   /* If this is just a nop, make sure to emit something.  */
00117   if (insn == 0x000)
00118     fprintf_fn (stream, "nopx\tnopy");
00119 
00120   /* If a parallel processing insn was printed before,
00121      and we got a non-nop, emit a tab.  */
00122   if ((insn & 0x800) && (insn & 0x3ff))
00123     fprintf_fn (stream, "\t");
00124 
00125   /* Check if either the x or y part is invalid.  */
00126   if (((insn & 0xc) == 0 && (insn & 0x2a0))
00127       || ((insn & 3) == 0 && (insn & 0x150)))
00128     if (info->mach != bfd_mach_sh_dsp
00129         && info->mach != bfd_mach_sh3_dsp)
00130       {
00131        static const sh_opcode_info *first_movx, *first_movy;
00132        const sh_opcode_info *op;
00133        int is_movy;
00134 
00135        if (! first_movx)
00136          {
00137            for (first_movx = sh_table; first_movx->nibbles[1] != MOVX_NOPY;)
00138              first_movx++;
00139            for (first_movy = first_movx; first_movy->nibbles[1] != MOVY_NOPX;)
00140              first_movy++;
00141          }
00142 
00143        is_movy = ((insn & 3) != 0);
00144 
00145        if (is_movy)
00146          op = first_movy;
00147        else
00148          op = first_movx;
00149 
00150        while (op->nibbles[2] != (unsigned) ((insn >> 4) & 3)
00151               || op->nibbles[3] != (unsigned) (insn & 0xf))
00152          op++;
00153        
00154        print_movxy (op,
00155                    (4 * ((insn & (is_movy ? 0x200 : 0x100)) == 0)
00156                     + 2 * is_movy
00157                     + 1 * ((insn & (is_movy ? 0x100 : 0x200)) != 0)),
00158                    (insn >> 6) & 3,
00159                    fprintf_fn, stream);
00160       }
00161     else
00162       fprintf_fn (stream, ".word 0x%x", insn);
00163   else
00164     {
00165       static const sh_opcode_info *first_movx, *first_movy;
00166       const sh_opcode_info *opx, *opy;
00167       unsigned int insn_x, insn_y;
00168 
00169       if (! first_movx)
00170        {
00171          for (first_movx = sh_table; first_movx->nibbles[1] != MOVX;)
00172            first_movx++;
00173          for (first_movy = first_movx; first_movy->nibbles[1] != MOVY;)
00174            first_movy++;
00175        }
00176       insn_x = (insn >> 2) & 0xb;
00177       if (insn_x)
00178        {
00179          for (opx = first_movx; opx->nibbles[2] != insn_x;)
00180            opx++;
00181          print_movxy (opx, ((insn >> 9) & 1) + 4, (insn >> 7) & 1,
00182                      fprintf_fn, stream);
00183        }
00184       insn_y = (insn & 3) | ((insn >> 1) & 8);
00185       if (insn_y)
00186        {
00187          if (insn_x)
00188            fprintf_fn (stream, "\t");
00189          for (opy = first_movy; opy->nibbles[2] != insn_y;)
00190            opy++;
00191          print_movxy (opy, ((insn >> 8) & 1) + 6, (insn >> 6) & 1,
00192                      fprintf_fn, stream);
00193        }
00194     }
00195 }
00196 
00197 static void
00198 print_dsp_reg (int rm, fprintf_ftype fprintf_fn, void *stream)
00199 {
00200   switch (rm)
00201     {
00202     case A_A1_NUM:
00203       fprintf_fn (stream, "a1");
00204       break;
00205     case A_A0_NUM:
00206       fprintf_fn (stream, "a0");
00207       break;
00208     case A_X0_NUM:
00209       fprintf_fn (stream, "x0");
00210       break;
00211     case A_X1_NUM:
00212       fprintf_fn (stream, "x1");
00213       break;
00214     case A_Y0_NUM:
00215       fprintf_fn (stream, "y0");
00216       break;
00217     case A_Y1_NUM:
00218       fprintf_fn (stream, "y1");
00219       break;
00220     case A_M0_NUM:
00221       fprintf_fn (stream, "m0");
00222       break;
00223     case A_A1G_NUM:
00224       fprintf_fn (stream, "a1g");
00225       break;
00226     case A_M1_NUM:
00227       fprintf_fn (stream, "m1");
00228       break;
00229     case A_A0G_NUM:
00230       fprintf_fn (stream, "a0g");
00231       break;
00232     default:
00233       fprintf_fn (stream, "0x%x", rm);
00234       break;
00235     }
00236 }
00237 
00238 static void
00239 print_insn_ppi (int field_b, struct disassemble_info *info)
00240 {
00241   static char *sx_tab[] = { "x0", "x1", "a0", "a1" };
00242   static char *sy_tab[] = { "y0", "y1", "m0", "m1" };
00243   fprintf_ftype fprintf_fn = info->fprintf_func;
00244   void *stream = info->stream;
00245   unsigned int nib1, nib2, nib3;
00246   unsigned int altnib1, nib4;
00247   char *dc = NULL;
00248   const sh_opcode_info *op;
00249 
00250   if ((field_b & 0xe800) == 0)
00251     {
00252       fprintf_fn (stream, "psh%c\t#%d,",
00253                 field_b & 0x1000 ? 'a' : 'l',
00254                 (field_b >> 4) & 127);
00255       print_dsp_reg (field_b & 0xf, fprintf_fn, stream);
00256       return;
00257     }
00258   if ((field_b & 0xc000) == 0x4000 && (field_b & 0x3000) != 0x1000)
00259     {
00260       static char *du_tab[] = { "x0", "y0", "a0", "a1" };
00261       static char *se_tab[] = { "x0", "x1", "y0", "a1" };
00262       static char *sf_tab[] = { "y0", "y1", "x0", "a1" };
00263       static char *sg_tab[] = { "m0", "m1", "a0", "a1" };
00264 
00265       if (field_b & 0x2000)
00266        fprintf_fn (stream, "p%s %s,%s,%s\t",
00267                   (field_b & 0x1000) ? "add" : "sub",
00268                   sx_tab[(field_b >> 6) & 3],
00269                   sy_tab[(field_b >> 4) & 3],
00270                   du_tab[(field_b >> 0) & 3]);
00271 
00272       else if ((field_b & 0xf0) == 0x10
00273               && info->mach != bfd_mach_sh_dsp
00274               && info->mach != bfd_mach_sh3_dsp)
00275        fprintf_fn (stream, "pclr %s \t", du_tab[(field_b >> 0) & 3]);
00276 
00277       else if ((field_b & 0xf3) != 0)
00278        fprintf_fn (stream, ".word 0x%x\t", field_b);
00279 
00280       fprintf_fn (stream, "pmuls%c%s,%s,%s",
00281                 field_b & 0x2000 ? ' ' : '\t',
00282                 se_tab[(field_b >> 10) & 3],
00283                 sf_tab[(field_b >>  8) & 3],
00284                 sg_tab[(field_b >>  2) & 3]);
00285       return;
00286     }
00287 
00288   nib1 = PPIC;
00289   nib2 = field_b >> 12 & 0xf;
00290   nib3 = field_b >> 8 & 0xf;
00291   nib4 = field_b >> 4 & 0xf;
00292   switch (nib3 & 0x3)
00293     {
00294     case 0:
00295       dc = "";
00296       nib1 = PPI3;
00297       break;
00298     case 1:
00299       dc = "";
00300       break;
00301     case 2:
00302       dc = "dct ";
00303       nib3 -= 1;
00304       break;
00305     case 3:
00306       dc = "dcf ";
00307       nib3 -= 2;
00308       break;
00309     }
00310   if (nib1 == PPI3)
00311     altnib1 = PPI3NC;
00312   else
00313     altnib1 = nib1;
00314   for (op = sh_table; op->name; op++)
00315     {
00316       if ((op->nibbles[1] == nib1 || op->nibbles[1] == altnib1)
00317          && op->nibbles[2] == nib2
00318          && op->nibbles[3] == nib3)
00319        {
00320          int n;
00321 
00322          switch (op->nibbles[4])
00323            {
00324            case HEX_0:
00325              break;
00326            case HEX_XX00:
00327              if ((nib4 & 3) != 0)
00328               continue;
00329              break;
00330            case HEX_1:
00331              if ((nib4 & 3) != 1)
00332               continue;
00333              break;
00334            case HEX_00YY:
00335              if ((nib4 & 0xc) != 0)
00336               continue;
00337              break;
00338            case HEX_4:
00339              if ((nib4 & 0xc) != 4)
00340               continue;
00341              break;
00342            default:
00343              abort ();
00344            }
00345          fprintf_fn (stream, "%s%s\t", dc, op->name);
00346          for (n = 0; n < 3 && op->arg[n] != A_END; n++)
00347            {
00348              if (n && op->arg[1] != A_END)
00349               fprintf_fn (stream, ",");
00350              switch (op->arg[n])
00351               {
00352               case DSP_REG_N:
00353                 print_dsp_reg (field_b & 0xf, fprintf_fn, stream);
00354                 break;
00355               case DSP_REG_X:
00356                 fprintf_fn (stream, sx_tab[(field_b >> 6) & 3]);
00357                 break;
00358               case DSP_REG_Y:
00359                 fprintf_fn (stream, sy_tab[(field_b >> 4) & 3]);
00360                 break;
00361               case A_MACH:
00362                 fprintf_fn (stream, "mach");
00363                 break;
00364               case A_MACL:
00365                 fprintf_fn (stream, "macl");
00366                 break;
00367               default:
00368                 abort ();
00369               }
00370            }
00371          return;
00372        }
00373     }
00374   /* Not found.  */
00375   fprintf_fn (stream, ".word 0x%x", field_b);
00376 }
00377 
00378 /* FIXME mvs: movx insns print as ".word 0x%03x", insn & 0xfff
00379    (ie. the upper nibble is missing).  */
00380 
00381 int
00382 print_insn_sh (bfd_vma memaddr, struct disassemble_info *info)
00383 {
00384   fprintf_ftype fprintf_fn = info->fprintf_func;
00385   void *stream = info->stream;
00386   unsigned char insn[4];
00387   unsigned char nibs[8];
00388   int status;
00389   bfd_vma relmask = ~(bfd_vma) 0;
00390   const sh_opcode_info *op;
00391   unsigned int target_arch;
00392   int allow_op32;
00393 
00394   switch (info->mach)
00395     {
00396     case bfd_mach_sh:
00397       target_arch = arch_sh1;
00398       /* SH coff object files lack information about the machine type, so
00399          we end up with bfd_mach_sh unless it was set explicitly (which
00400         could have happended if this is a call from gdb or the simulator.)  */
00401       if (info->symbols
00402          && bfd_asymbol_flavour(*info->symbols) == bfd_target_coff_flavour)
00403        target_arch = arch_sh4;
00404       break;
00405     case bfd_mach_sh5:
00406 #ifdef INCLUDE_SHMEDIA
00407       status = print_insn_sh64 (memaddr, info);
00408       if (status != -2)
00409        return status;
00410 #endif
00411       /* When we get here for sh64, it's because we want to disassemble
00412         SHcompact, i.e. arch_sh4.  */
00413       target_arch = arch_sh4;
00414       break;
00415     default:
00416       target_arch = sh_get_arch_from_bfd_mach (info->mach);
00417     }
00418 
00419   status = info->read_memory_func (memaddr, insn, 2, info);
00420 
00421   if (status != 0)
00422     {
00423       info->memory_error_func (status, memaddr, info);
00424       return -1;
00425     }
00426 
00427   if (info->endian == BFD_ENDIAN_LITTLE)
00428     {
00429       nibs[0] = (insn[1] >> 4) & 0xf;
00430       nibs[1] = insn[1] & 0xf;
00431 
00432       nibs[2] = (insn[0] >> 4) & 0xf;
00433       nibs[3] = insn[0] & 0xf;
00434     }
00435   else
00436     {
00437       nibs[0] = (insn[0] >> 4) & 0xf;
00438       nibs[1] = insn[0] & 0xf;
00439 
00440       nibs[2] = (insn[1] >> 4) & 0xf;
00441       nibs[3] = insn[1] & 0xf;
00442     }
00443   status = info->read_memory_func (memaddr + 2, insn + 2, 2, info);
00444   if (status != 0)
00445     allow_op32 = 0;
00446   else
00447     {
00448       allow_op32 = 1;
00449 
00450       if (info->endian == BFD_ENDIAN_LITTLE)
00451        {
00452          nibs[4] = (insn[3] >> 4) & 0xf;
00453          nibs[5] = insn[3] & 0xf;
00454 
00455          nibs[6] = (insn[2] >> 4) & 0xf;
00456          nibs[7] = insn[2] & 0xf;
00457        }
00458       else
00459        {
00460          nibs[4] = (insn[2] >> 4) & 0xf;
00461          nibs[5] = insn[2] & 0xf;
00462 
00463          nibs[6] = (insn[3] >> 4) & 0xf;
00464          nibs[7] = insn[3] & 0xf;
00465        }
00466     }
00467 
00468   if (nibs[0] == 0xf && (nibs[1] & 4) == 0
00469       && SH_MERGE_ARCH_SET_VALID (target_arch, arch_sh_dsp_up))
00470     {
00471       if (nibs[1] & 8)
00472        {
00473          int field_b;
00474 
00475          status = info->read_memory_func (memaddr + 2, insn, 2, info);
00476 
00477          if (status != 0)
00478            {
00479              info->memory_error_func (status, memaddr + 2, info);
00480              return -1;
00481            }
00482 
00483          if (info->endian == BFD_ENDIAN_LITTLE)
00484            field_b = insn[1] << 8 | insn[0];
00485          else
00486            field_b = insn[0] << 8 | insn[1];
00487 
00488          print_insn_ppi (field_b, info);
00489          print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
00490          return 4;
00491        }
00492       print_insn_ddt ((nibs[1] << 8) | (nibs[2] << 4) | nibs[3], info);
00493       return 2;
00494     }
00495   for (op = sh_table; op->name; op++)
00496     {
00497       int n;
00498       int imm = 0;
00499       int rn = 0;
00500       int rm = 0;
00501       int rb = 0;
00502       int disp_pc;
00503       bfd_vma disp_pc_addr = 0;
00504       int disp = 0;
00505       int has_disp = 0;
00506       int max_n = SH_MERGE_ARCH_SET (op->arch, arch_op32) ? 8 : 4;
00507 
00508       if (!allow_op32
00509          && SH_MERGE_ARCH_SET (op->arch, arch_op32))
00510        goto fail;
00511 
00512       if (!SH_MERGE_ARCH_SET_VALID (op->arch, target_arch))
00513        goto fail;
00514       for (n = 0; n < max_n; n++)
00515        {
00516          int i = op->nibbles[n];
00517 
00518          if (i < 16)
00519            {
00520              if (nibs[n] == i)
00521               continue;
00522              goto fail;
00523            }
00524          switch (i)
00525            {
00526            case BRANCH_8:
00527              imm = (nibs[2] << 4) | (nibs[3]);
00528              if (imm & 0x80)
00529               imm |= ~0xff;
00530              imm = ((char) imm) * 2 + 4;
00531              goto ok;
00532            case BRANCH_12:
00533              imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]);
00534              if (imm & 0x800)
00535               imm |= ~0xfff;
00536              imm = imm * 2 + 4;
00537              goto ok;
00538            case IMM0_3c:
00539              if (nibs[3] & 0x8)
00540               goto fail;
00541              imm = nibs[3] & 0x7;
00542              break;
00543            case IMM0_3s:
00544              if (!(nibs[3] & 0x8))
00545               goto fail;
00546              imm = nibs[3] & 0x7;
00547              break;
00548            case IMM0_3Uc:
00549              if (nibs[2] & 0x8)
00550               goto fail;
00551              imm = nibs[2] & 0x7;
00552              break;
00553            case IMM0_3Us:
00554              if (!(nibs[2] & 0x8))
00555               goto fail;
00556              imm = nibs[2] & 0x7;
00557              break;
00558            case DISP0_12:
00559            case DISP1_12:
00560              disp = (nibs[5] << 8) | (nibs[6] << 4) | nibs[7];
00561              has_disp = 1;
00562              goto ok;
00563            case DISP0_12BY2:
00564            case DISP1_12BY2:
00565              disp = ((nibs[5] << 8) | (nibs[6] << 4) | nibs[7]) << 1;
00566              relmask = ~(bfd_vma) 1;
00567              has_disp = 1;
00568              goto ok;
00569            case DISP0_12BY4:
00570            case DISP1_12BY4:
00571              disp = ((nibs[5] << 8) | (nibs[6] << 4) | nibs[7]) << 2;
00572              relmask = ~(bfd_vma) 3;
00573              has_disp = 1;
00574              goto ok;
00575            case DISP0_12BY8:
00576            case DISP1_12BY8:
00577              disp = ((nibs[5] << 8) | (nibs[6] << 4) | nibs[7]) << 3;
00578              relmask = ~(bfd_vma) 7;
00579              has_disp = 1;
00580              goto ok;
00581            case IMM0_20_4:
00582              break;
00583            case IMM0_20:
00584              imm = ((nibs[2] << 16) | (nibs[4] << 12) | (nibs[5] << 8)
00585                    | (nibs[6] << 4) | nibs[7]);
00586              if (imm & 0x80000)
00587               imm -= 0x100000;
00588              goto ok;
00589            case IMM0_20BY8:
00590              imm = ((nibs[2] << 16) | (nibs[4] << 12) | (nibs[5] << 8)
00591                    | (nibs[6] << 4) | nibs[7]);
00592              imm <<= 8;
00593              if (imm & 0x8000000)
00594               imm -= 0x10000000;
00595              goto ok;
00596            case IMM0_4:
00597            case IMM1_4:
00598              imm = nibs[3];
00599              goto ok;
00600            case IMM0_4BY2:
00601            case IMM1_4BY2:
00602              imm = nibs[3] << 1;
00603              goto ok;
00604            case IMM0_4BY4:
00605            case IMM1_4BY4:
00606              imm = nibs[3] << 2;
00607              goto ok;
00608            case IMM0_8:
00609            case IMM1_8:
00610              imm = (nibs[2] << 4) | nibs[3];
00611              disp = imm;
00612              has_disp = 1;
00613              if (imm & 0x80)
00614               imm -= 0x100;
00615              goto ok;
00616            case PCRELIMM_8BY2:
00617              imm = ((nibs[2] << 4) | nibs[3]) << 1;
00618              relmask = ~(bfd_vma) 1;
00619              goto ok;
00620            case PCRELIMM_8BY4:
00621              imm = ((nibs[2] << 4) | nibs[3]) << 2;
00622              relmask = ~(bfd_vma) 3;
00623              goto ok;
00624            case IMM0_8BY2:
00625            case IMM1_8BY2:
00626              imm = ((nibs[2] << 4) | nibs[3]) << 1;
00627              goto ok;
00628            case IMM0_8BY4:
00629            case IMM1_8BY4:
00630              imm = ((nibs[2] << 4) | nibs[3]) << 2;
00631              goto ok;
00632            case REG_N_D:
00633              if ((nibs[n] & 1) != 0)
00634               goto fail;
00635              /* Fall through.  */
00636            case REG_N:
00637              rn = nibs[n];
00638              break;
00639            case REG_M:
00640              rm = nibs[n];
00641              break;
00642            case REG_N_B01:
00643              if ((nibs[n] & 0x3) != 1 /* binary 01 */)
00644               goto fail;
00645              rn = (nibs[n] & 0xc) >> 2;
00646              break;
00647            case REG_NM:
00648              rn = (nibs[n] & 0xc) >> 2;
00649              rm = (nibs[n] & 0x3);
00650              break;
00651            case REG_B:
00652              rb = nibs[n] & 0x07;
00653              break;
00654            case SDT_REG_N:
00655              /* sh-dsp: single data transfer.  */
00656              rn = nibs[n];
00657              if ((rn & 0xc) != 4)
00658               goto fail;
00659              rn = rn & 0x3;
00660              rn |= (!(rn & 2)) << 2;
00661              break;
00662            case PPI:
00663            case REPEAT:
00664              goto fail;
00665            default:
00666              abort ();
00667            }
00668        }
00669 
00670     ok:
00671       /* sh2a has D_REG but not X_REG.  We don't know the pattern
00672         doesn't match unless we check the output args to see if they
00673         make sense.  */
00674       if (target_arch == arch_sh2a
00675          && ((op->arg[0] == DX_REG_M && (rm & 1) != 0)
00676              || (op->arg[1] == DX_REG_N && (rn & 1) != 0)))
00677        goto fail;
00678 
00679       fprintf_fn (stream, "%s\t", op->name);
00680       disp_pc = 0;
00681       for (n = 0; n < 3 && op->arg[n] != A_END; n++)
00682        {
00683          if (n && op->arg[1] != A_END)
00684            fprintf_fn (stream, ",");
00685          switch (op->arg[n])
00686            {
00687            case A_IMM:
00688              fprintf_fn (stream, "#%d", imm);
00689              break;
00690            case A_R0:
00691              fprintf_fn (stream, "r0");
00692              break;
00693            case A_REG_N:
00694              fprintf_fn (stream, "r%d", rn);
00695              break;
00696            case A_INC_N:
00697            case AS_INC_N:
00698              fprintf_fn (stream, "@r%d+", rn);
00699              break;
00700            case A_DEC_N:
00701            case AS_DEC_N:
00702              fprintf_fn (stream, "@-r%d", rn);
00703              break;
00704            case A_IND_N:
00705            case AS_IND_N:
00706              fprintf_fn (stream, "@r%d", rn);
00707              break;
00708            case A_DISP_REG_N:
00709              fprintf_fn (stream, "@(%d,r%d)", has_disp?disp:imm, rn);
00710              break;
00711            case AS_PMOD_N:
00712              fprintf_fn (stream, "@r%d+r8", rn);
00713              break;
00714            case A_REG_M:
00715              fprintf_fn (stream, "r%d", rm);
00716              break;
00717            case A_INC_M:
00718              fprintf_fn (stream, "@r%d+", rm);
00719              break;
00720            case A_DEC_M:
00721              fprintf_fn (stream, "@-r%d", rm);
00722              break;
00723            case A_IND_M:
00724              fprintf_fn (stream, "@r%d", rm);
00725              break;
00726            case A_DISP_REG_M:
00727              fprintf_fn (stream, "@(%d,r%d)", has_disp?disp:imm, rm);
00728              break;
00729            case A_REG_B:
00730              fprintf_fn (stream, "r%d_bank", rb);
00731              break;
00732            case A_DISP_PC:
00733              disp_pc = 1;
00734              disp_pc_addr = imm + 4 + (memaddr & relmask);
00735              (*info->print_address_func) (disp_pc_addr, info);
00736              break;
00737            case A_IND_R0_REG_N:
00738              fprintf_fn (stream, "@(r0,r%d)", rn);
00739              break;
00740            case A_IND_R0_REG_M:
00741              fprintf_fn (stream, "@(r0,r%d)", rm);
00742              break;
00743            case A_DISP_GBR:
00744              fprintf_fn (stream, "@(%d,gbr)", has_disp?disp:imm);
00745              break;
00746            case A_TBR:
00747              fprintf_fn (stream, "tbr");
00748              break;
00749            case A_DISP2_TBR:
00750              fprintf_fn (stream, "@@(%d,tbr)", has_disp?disp:imm);
00751              break;
00752            case A_INC_R15:
00753              fprintf_fn (stream, "@r15+");
00754              break;
00755            case A_DEC_R15:
00756              fprintf_fn (stream, "@-r15");
00757              break;
00758            case A_R0_GBR:
00759              fprintf_fn (stream, "@(r0,gbr)");
00760              break;
00761            case A_BDISP12:
00762            case A_BDISP8:
00763              (*info->print_address_func) (imm + memaddr, info);
00764              break;
00765            case A_SR:
00766              fprintf_fn (stream, "sr");
00767              break;
00768            case A_GBR:
00769              fprintf_fn (stream, "gbr");
00770              break;
00771            case A_VBR:
00772              fprintf_fn (stream, "vbr");
00773              break;
00774            case A_DSR:
00775              fprintf_fn (stream, "dsr");
00776              break;
00777            case A_MOD:
00778              fprintf_fn (stream, "mod");
00779              break;
00780            case A_RE:
00781              fprintf_fn (stream, "re");
00782              break;
00783            case A_RS:
00784              fprintf_fn (stream, "rs");
00785              break;
00786            case A_A0:
00787              fprintf_fn (stream, "a0");
00788              break;
00789            case A_X0:
00790              fprintf_fn (stream, "x0");
00791              break;
00792            case A_X1:
00793              fprintf_fn (stream, "x1");
00794              break;
00795            case A_Y0:
00796              fprintf_fn (stream, "y0");
00797              break;
00798            case A_Y1:
00799              fprintf_fn (stream, "y1");
00800              break;
00801            case DSP_REG_M:
00802              print_dsp_reg (rm, fprintf_fn, stream);
00803              break;
00804            case A_SSR:
00805              fprintf_fn (stream, "ssr");
00806              break;
00807            case A_SPC:
00808              fprintf_fn (stream, "spc");
00809              break;
00810            case A_MACH:
00811              fprintf_fn (stream, "mach");
00812              break;
00813            case A_MACL:
00814              fprintf_fn (stream, "macl");
00815              break;
00816            case A_PR:
00817              fprintf_fn (stream, "pr");
00818              break;
00819            case A_SGR:
00820              fprintf_fn (stream, "sgr");
00821              break;
00822            case A_DBR:
00823              fprintf_fn (stream, "dbr");
00824              break;
00825            case F_REG_N:
00826              fprintf_fn (stream, "fr%d", rn);
00827              break;
00828            case F_REG_M:
00829              fprintf_fn (stream, "fr%d", rm);
00830              break;
00831            case DX_REG_N:
00832              if (rn & 1)
00833               {
00834                 fprintf_fn (stream, "xd%d", rn & ~1);
00835                 break;
00836               }
00837            case D_REG_N:
00838              fprintf_fn (stream, "dr%d", rn);
00839              break;
00840            case DX_REG_M:
00841              if (rm & 1)
00842               {
00843                 fprintf_fn (stream, "xd%d", rm & ~1);
00844                 break;
00845               }
00846            case D_REG_M:
00847              fprintf_fn (stream, "dr%d", rm);
00848              break;
00849            case FPSCR_M:
00850            case FPSCR_N:
00851              fprintf_fn (stream, "fpscr");
00852              break;
00853            case FPUL_M:
00854            case FPUL_N:
00855              fprintf_fn (stream, "fpul");
00856              break;
00857            case F_FR0:
00858              fprintf_fn (stream, "fr0");
00859              break;
00860            case V_REG_N:
00861              fprintf_fn (stream, "fv%d", rn * 4);
00862              break;
00863            case V_REG_M:
00864              fprintf_fn (stream, "fv%d", rm * 4);
00865              break;
00866            case XMTRX_M4:
00867              fprintf_fn (stream, "xmtrx");
00868              break;
00869            default:
00870              abort ();
00871            }
00872        }
00873 
00874 #if 0
00875       /* This code prints instructions in delay slots on the same line
00876          as the instruction which needs the delay slots.  This can be
00877          confusing, since other disassembler don't work this way, and
00878          it means that the instructions are not all in a line.  So I
00879          disabled it.  Ian.  */
00880       if (!(info->flags & 1)
00881          && (op->name[0] == 'j'
00882              || (op->name[0] == 'b'
00883                 && (op->name[1] == 'r'
00884                     || op->name[1] == 's'))
00885              || (op->name[0] == 'r' && op->name[1] == 't')
00886              || (op->name[0] == 'b' && op->name[2] == '.')))
00887        {
00888          info->flags |= 1;
00889          fprintf_fn (stream, "\t(slot ");
00890          print_insn_sh (memaddr + 2, info);
00891          info->flags &= ~1;
00892          fprintf_fn (stream, ")");
00893          return 4;
00894        }
00895 #endif
00896 
00897       if (disp_pc && strcmp (op->name, "mova") != 0)
00898        {
00899          int size;
00900          bfd_byte bytes[4];
00901 
00902          if (relmask == ~(bfd_vma) 1)
00903            size = 2;
00904          else
00905            size = 4;
00906          status = info->read_memory_func (disp_pc_addr, bytes, size, info);
00907          if (status == 0)
00908            {
00909              unsigned int val;
00910 
00911              if (size == 2)
00912               {
00913                 if (info->endian == BFD_ENDIAN_LITTLE)
00914                   val = bfd_getl16 (bytes);
00915                 else
00916                   val = bfd_getb16 (bytes);
00917               }
00918              else
00919               {
00920                 if (info->endian == BFD_ENDIAN_LITTLE)
00921                   val = bfd_getl32 (bytes);
00922                 else
00923                   val = bfd_getb32 (bytes);
00924               }
00925              if ((*info->symbol_at_address_func) (val, info))
00926               {
00927                 fprintf_fn (stream, "\t! ");
00928                 (*info->print_address_func) (val, info);
00929               }
00930              else
00931               fprintf_fn (stream, "\t! %x", val);
00932            }
00933        }
00934 
00935       return SH_MERGE_ARCH_SET (op->arch, arch_op32) ? 4 : 2;
00936     fail:
00937       ;
00938 
00939     }
00940   fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]);
00941   return 2;
00942 }