Back to index

cell-binutils  2.17cvs20070401
h8500-dis.c
Go to the documentation of this file.
00001 /* Disassemble h8500 instructions.
00002    Copyright 1993, 1998, 2000, 2001, 2002, 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 
00022 #define DISASSEMBLER_TABLE
00023 #define DEFINE_TABLE
00024 
00025 #include "sysdep.h"
00026 #include "h8500-opc.h"
00027 #include "dis-asm.h"
00028 #include "opintl.h"
00029 
00030 /* Maximum length of an instruction.  */
00031 #define MAXLEN 8
00032 
00033 #include <setjmp.h>
00034 
00035 struct private
00036 {
00037   /* Points to first byte not fetched.  */
00038   bfd_byte *max_fetched;
00039   bfd_byte the_buffer[MAXLEN];
00040   bfd_vma insn_start;
00041   jmp_buf bailout;
00042 };
00043 
00044 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
00045    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
00046    on error.  */
00047 #define FETCH_DATA(info, addr) \
00048   ((addr) <= ((struct private *)(info->private_data))->max_fetched \
00049    ? 1 : fetch_data ((info), (addr)))
00050 
00051 static int
00052 fetch_data (struct disassemble_info *info, bfd_byte *addr)
00053 {
00054   int status;
00055   struct private *priv = (struct private *) info->private_data;
00056   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
00057 
00058   status = (*info->read_memory_func) (start,
00059                                   priv->max_fetched,
00060                                   addr - priv->max_fetched,
00061                                   info);
00062   if (status != 0)
00063     {
00064       (*info->memory_error_func) (status, start, info);
00065       longjmp (priv->bailout, 1);
00066     }
00067   else
00068     priv->max_fetched = addr;
00069   return 1;
00070 }
00071 
00072 static char *crname[] = { "sr", "ccr", "*", "br", "ep", "dp", "*", "tp" };
00073 
00074 int
00075 print_insn_h8500 (bfd_vma addr, disassemble_info *info)
00076 {
00077   const h8500_opcode_info *opcode;
00078   void *stream = info->stream;
00079   fprintf_ftype func = info->fprintf_func;
00080   struct private priv;
00081   bfd_byte *buffer = priv.the_buffer;
00082 
00083   info->private_data = (PTR) & priv;
00084   priv.max_fetched = priv.the_buffer;
00085   priv.insn_start = addr;
00086   if (setjmp (priv.bailout) != 0)
00087     /* Error return.  */
00088     return -1;
00089 
00090   /* Run down the table to find the one which matches.  */
00091   for (opcode = h8500_table; opcode->name; opcode++)
00092     {
00093       int byte;
00094       int rn = 0;
00095       int rd = 0;
00096       int rs = 0;
00097       int disp = 0;
00098       int abs = 0;
00099       int imm = 0;
00100       int pcrel = 0;
00101       int qim = 0;
00102       int i;
00103       int cr = 0;
00104 
00105       for (byte = 0; byte < opcode->length; byte++)
00106        {
00107          FETCH_DATA (info, buffer + byte + 1);
00108          if ((buffer[byte] & opcode->bytes[byte].mask)
00109              != (opcode->bytes[byte].contents))
00110            goto next;
00111 
00112          else
00113            {
00114              /* Extract any info parts.  */
00115              switch (opcode->bytes[byte].insert)
00116               {
00117               case 0:
00118               case FP:
00119                 break;
00120               default:
00121                 /* xgettext:c-format */
00122                 func (stream, _("can't cope with insert %d\n"),
00123                      opcode->bytes[byte].insert);
00124                 break;
00125               case RN:
00126                 rn = buffer[byte] & 0x7;
00127                 break;
00128               case RS:
00129                 rs = buffer[byte] & 0x7;
00130                 break;
00131               case CRB:
00132                 cr = buffer[byte] & 0x7;
00133                 if (cr == 0)
00134                   goto next;
00135                 break;
00136               case CRW:
00137                 cr = buffer[byte] & 0x7;
00138                 if (cr != 0)
00139                   goto next;
00140                 break;
00141               case DISP16:
00142                 FETCH_DATA (info, buffer + byte + 2);
00143                 disp = (buffer[byte] << 8) | (buffer[byte + 1]);
00144                 break;
00145               case FPIND_D8:
00146               case DISP8:
00147                 disp = ((char) (buffer[byte]));
00148                 break;
00149               case RD:
00150               case RDIND:
00151                 rd = buffer[byte] & 0x7;
00152                 break;
00153               case ABS24:
00154                 FETCH_DATA (info, buffer + byte + 3);
00155                 abs =
00156                   (buffer[byte] << 16)
00157                   | (buffer[byte + 1] << 8)
00158                   | (buffer[byte + 2]);
00159                 break;
00160               case ABS16:
00161                 FETCH_DATA (info, buffer + byte + 2);
00162                 abs = (buffer[byte] << 8) | (buffer[byte + 1]);
00163                 break;
00164               case ABS8:
00165                 abs = (buffer[byte]);
00166                 break;
00167               case IMM16:
00168                 FETCH_DATA (info, buffer + byte + 2);
00169                 imm = (buffer[byte] << 8) | (buffer[byte + 1]);
00170                 break;
00171               case IMM4:
00172                 imm = (buffer[byte]) & 0xf;
00173                 break;
00174               case IMM8:
00175               case RLIST:
00176                 imm = (buffer[byte]);
00177                 break;
00178               case PCREL16:
00179                 FETCH_DATA (info, buffer + byte + 2);
00180                 pcrel = (buffer[byte] << 8) | (buffer[byte + 1]);
00181                 break;
00182               case PCREL8:
00183                 pcrel = (buffer[byte]);
00184                 break;
00185               case QIM:
00186                 switch (buffer[byte] & 0x7)
00187                   {
00188                   case 0:
00189                     qim = 1;
00190                     break;
00191                   case 1:
00192                     qim = 2;
00193                     break;
00194                   case 4:
00195                     qim = -1;
00196                     break;
00197                   case 5:
00198                     qim = -2;
00199                     break;
00200                   }
00201                 break;
00202 
00203               }
00204            }
00205        }
00206       /* We get here when all the masks have passed so we can output
00207         the operands.  */
00208       FETCH_DATA (info, buffer + opcode->length);
00209       (func) (stream, "%s\t", opcode->name);
00210       for (i = 0; i < opcode->nargs; i++)
00211        {
00212          if (i)
00213            (func) (stream, ",");
00214          switch (opcode->arg_type[i])
00215            {
00216            case FP:
00217              func (stream, "fp");
00218              break;
00219            case RNIND_D16:
00220              func (stream, "@(0x%x:16,r%d)", disp, rn);
00221              break;
00222            case RNIND_D8:
00223              func (stream, "@(0x%x:8 (%d),r%d)", disp & 0xff, disp, rn);
00224              break;
00225            case RDIND_D16:
00226              func (stream, "@(0x%x:16,r%d)", disp, rd);
00227              break;
00228            case RDIND_D8:
00229              func (stream, "@(0x%x:8 (%d), r%d)", disp & 0xff, disp, rd);
00230              break;
00231            case FPIND_D8:
00232              func (stream, "@(0x%x:8 (%d), fp)", disp & 0xff, disp);
00233              break;
00234            case CRB:
00235            case CRW:
00236              func (stream, "%s", crname[cr]);
00237              break;
00238            case RN:
00239              func (stream, "r%d", rn);
00240              break;
00241            case RD:
00242              func (stream, "r%d", rd);
00243              break;
00244            case RS:
00245              func (stream, "r%d", rs);
00246              break;
00247            case RNDEC:
00248              func (stream, "@-r%d", rn);
00249              break;
00250            case RNINC:
00251              func (stream, "@r%d+", rn);
00252              break;
00253            case RNIND:
00254              func (stream, "@r%d", rn);
00255              break;
00256            case RDIND:
00257              func (stream, "@r%d", rd);
00258              break;
00259            case SPINC:
00260              func (stream, "@sp+");
00261              break;
00262            case SPDEC:
00263              func (stream, "@-sp");
00264              break;
00265            case ABS24:
00266              func (stream, "@0x%0x:24", abs);
00267              break;
00268            case ABS16:
00269              func (stream, "@0x%0x:16", abs & 0xffff);
00270              break;
00271            case ABS8:
00272              func (stream, "@0x%0x:8", abs & 0xff);
00273              break;
00274            case IMM16:
00275              func (stream, "#0x%0x:16", imm & 0xffff);
00276              break;
00277            case RLIST:
00278              {
00279               int i;
00280               int nc = 0;
00281 
00282               func (stream, "(");
00283               for (i = 0; i < 8; i++)
00284                 {
00285                   if (imm & (1 << i))
00286                     {
00287                      func (stream, "r%d", i);
00288                      if (nc)
00289                        func (stream, ",");
00290                      nc = 1;
00291                     }
00292                 }
00293               func (stream, ")");
00294              }
00295              break;
00296            case IMM8:
00297              func (stream, "#0x%0x:8", imm & 0xff);
00298              break;
00299            case PCREL16:
00300              func (stream, "0x%0x:16",
00301                   (int)(pcrel + addr + opcode->length) & 0xffff);
00302              break;
00303            case PCREL8:
00304              func (stream, "#0x%0x:8",
00305                   (int)((char) pcrel + addr + opcode->length) & 0xffff);
00306              break;
00307            case QIM:
00308              func (stream, "#%d:q", qim);
00309              break;
00310            case IMM4:
00311              func (stream, "#%d:4", imm);
00312              break;
00313            }
00314        }
00315       return opcode->length;
00316     next:
00317       ;
00318     }
00319 
00320   /* Couldn't understand anything.  */
00321   /* xgettext:c-format */
00322   func (stream, _("%02x\t\t*unknown*"), buffer[0]);
00323   return 1;
00324 }