Back to index

cell-binutils  2.17cvs20070401
m10200-dis.c
Go to the documentation of this file.
00001 /* Disassemble MN10200 instructions.
00002    Copyright 1996, 1997, 1998, 2000, 2005 Free Software Foundation, Inc.
00003 
00004    This program is free software; you can redistribute it and/or modify
00005    it under the terms of the GNU General Public License as published by
00006    the Free Software Foundation; either version 2 of the License, or
00007    (at your option) any later version.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program; if not, write to the Free Software
00016    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
00017    MA 02110-1301, USA.  */
00018 
00019 #include <stdio.h>
00020 
00021 #include "sysdep.h"
00022 #include "opcode/mn10200.h" 
00023 #include "dis-asm.h"
00024 #include "opintl.h"
00025 
00026 static void
00027 disassemble (bfd_vma memaddr,
00028             struct disassemble_info *info,
00029             unsigned long insn,
00030             unsigned long extension,
00031             unsigned int size)
00032 {
00033   struct mn10200_opcode *op = (struct mn10200_opcode *)mn10200_opcodes;
00034   const struct mn10200_operand *operand;
00035   int match = 0;
00036 
00037   /* Find the opcode.  */
00038   while (op->name)
00039     {
00040       int mysize, extra_shift;
00041 
00042       if (op->format == FMT_1)
00043        mysize = 1;
00044       else if (op->format == FMT_2
00045               || op->format == FMT_4)
00046        mysize = 2;
00047       else if (op->format == FMT_3
00048               || op->format == FMT_5)
00049        mysize = 3;
00050       else if (op->format == FMT_6)
00051        mysize = 4;
00052       else if (op->format == FMT_7)
00053        mysize = 5;
00054       else
00055        abort ();
00056        
00057       if (op->format == FMT_2 || op->format == FMT_5)
00058        extra_shift = 8;
00059       else if (op->format == FMT_3
00060               || op->format == FMT_6
00061               || op->format == FMT_7)
00062        extra_shift = 16;
00063       else
00064        extra_shift = 0;
00065 
00066       if ((op->mask & insn) == op->opcode
00067          && size == (unsigned int) mysize)
00068        {
00069          const unsigned char *opindex_ptr;
00070          unsigned int nocomma;
00071          int paren = 0;
00072          
00073          match = 1;
00074          (*info->fprintf_func) (info->stream, "%s\t", op->name);
00075 
00076          /* Now print the operands.  */
00077          for (opindex_ptr = op->operands, nocomma = 1;
00078               *opindex_ptr != 0;
00079               opindex_ptr++)
00080            {
00081              unsigned long value;
00082 
00083              operand = &mn10200_operands[*opindex_ptr];
00084 
00085              if ((operand->flags & MN10200_OPERAND_EXTENDED) != 0)
00086               {
00087                 value = (insn & 0xffff) << 8;
00088                 value |= extension;
00089               }
00090              else
00091               {
00092                 value = ((insn >> (operand->shift))
00093                         & ((1L << operand->bits) - 1L));
00094               }
00095 
00096              if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
00097               value = ((long)(value << (32 - operand->bits))
00098                        >> (32 - operand->bits));
00099 
00100              if (!nocomma
00101                 && (!paren
00102                     || ((operand->flags & MN10200_OPERAND_PAREN) == 0)))
00103               (*info->fprintf_func) (info->stream, ",");
00104 
00105              nocomma = 0;
00106               
00107              if ((operand->flags & MN10200_OPERAND_DREG) != 0)
00108               {
00109                 value = ((insn >> (operand->shift + extra_shift))
00110                         & ((1 << operand->bits) - 1));
00111                 (*info->fprintf_func) (info->stream, "d%ld", value);
00112               }
00113 
00114              else if ((operand->flags & MN10200_OPERAND_AREG) != 0)
00115               {
00116                 value = ((insn >> (operand->shift + extra_shift))
00117                         & ((1 << operand->bits) - 1));
00118                 (*info->fprintf_func) (info->stream, "a%ld", value);
00119               }
00120 
00121              else if ((operand->flags & MN10200_OPERAND_PSW) != 0)
00122               (*info->fprintf_func) (info->stream, "psw");
00123 
00124              else if ((operand->flags & MN10200_OPERAND_MDR) != 0)
00125               (*info->fprintf_func) (info->stream, "mdr");
00126 
00127              else if ((operand->flags & MN10200_OPERAND_PAREN) != 0)
00128               {
00129                 if (paren)
00130                   (*info->fprintf_func) (info->stream, ")");
00131                 else
00132                   {
00133                     (*info->fprintf_func) (info->stream, "(");
00134                     nocomma = 1;
00135                   }
00136                 paren = !paren;
00137               }
00138 
00139              else if ((operand->flags & MN10200_OPERAND_PCREL) != 0)
00140               (*info->print_address_func)
00141                 ((value + memaddr + mysize) & 0xffffff, info);
00142 
00143              else if ((operand->flags & MN10200_OPERAND_MEMADDR) != 0)
00144               (*info->print_address_func) (value, info);
00145 
00146              else 
00147               (*info->fprintf_func) (info->stream, "%ld", value);
00148            }
00149          /* All done. */
00150          break;
00151        }
00152       op++;
00153     }
00154 
00155   if (!match)
00156     (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
00157 }
00158 
00159 int 
00160 print_insn_mn10200 (bfd_vma memaddr, struct disassemble_info *info)
00161 {
00162   int status;
00163   bfd_byte buffer[4];
00164   unsigned long insn;
00165   unsigned long extension = 0;
00166   unsigned int consume;
00167 
00168   /* First figure out how big the opcode is.  */
00169   status = (*info->read_memory_func) (memaddr, buffer, 1, info);
00170   if (status != 0)
00171     {
00172       (*info->memory_error_func) (status, memaddr, info);
00173       return -1;
00174     }
00175 
00176   insn = *(unsigned char *) buffer;
00177 
00178   /* These are one byte insns.  */
00179   if ((insn & 0xf0) == 0x00
00180       || (insn & 0xf0) == 0x10
00181       || (insn & 0xf0) == 0x20
00182       || (insn & 0xf0) == 0x30
00183       || ((insn & 0xf0) == 0x80
00184          && (insn & 0x0c) >> 2 != (insn & 0x03))
00185       || (insn & 0xf0) == 0x90
00186       || (insn & 0xf0) == 0xa0
00187       || (insn & 0xf0) == 0xb0
00188       || (insn & 0xff) == 0xeb
00189       || (insn & 0xff) == 0xf6
00190       || (insn & 0xff) == 0xfe
00191       || (insn & 0xff) == 0xff)
00192     {
00193       extension = 0;
00194       consume = 1;
00195     }
00196 
00197   /* These are two byte insns.  */
00198   else if ((insn & 0xf0) == 0x40
00199           || (insn & 0xf0) == 0x50
00200           || (insn & 0xf0) == 0x60
00201           || (insn & 0xf0) == 0x70
00202           || (insn & 0xf0) == 0x80
00203           || (insn & 0xfc) == 0xd0
00204           || (insn & 0xfc) == 0xd4
00205           || (insn & 0xfc) == 0xd8
00206           || (insn & 0xfc) == 0xe0
00207           || (insn & 0xfc) == 0xe4
00208           || (insn & 0xff) == 0xe8
00209           || (insn & 0xff) == 0xe9
00210           || (insn & 0xff) == 0xea
00211           || (insn & 0xff) == 0xf0
00212           || (insn & 0xff) == 0xf1
00213           || (insn & 0xff) == 0xf2
00214           || (insn & 0xff) == 0xf3)
00215     {
00216       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
00217       if (status != 0)
00218        {
00219          (*info->memory_error_func) (status, memaddr, info);
00220           return -1;
00221        }
00222       insn = bfd_getb16 (buffer);
00223       consume = 2;
00224     }
00225 
00226   /* These are three byte insns with a 16bit operand in little
00227      endian form.  */
00228   else if ((insn & 0xf0) == 0xc0
00229           || (insn & 0xfc) == 0xdc
00230           || (insn & 0xfc) == 0xec
00231           || (insn & 0xff) == 0xf8
00232           || (insn & 0xff) == 0xf9
00233           || (insn & 0xff) == 0xfa
00234           || (insn & 0xff) == 0xfb
00235           || (insn & 0xff) == 0xfc
00236           || (insn & 0xff) == 0xfd)
00237     {
00238       status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
00239       if (status != 0)
00240        {
00241          (*info->memory_error_func) (status, memaddr, info);
00242          return -1;
00243        }
00244       insn <<= 16;
00245       insn |= bfd_getl16 (buffer);
00246       extension = 0;
00247       consume = 3;
00248     }
00249   /* These are three byte insns too, but we don't have to mess with
00250      endianness stuff.  */
00251   else if ((insn & 0xff) == 0xf5)
00252     {
00253       status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
00254       if (status != 0)
00255        {
00256          (*info->memory_error_func) (status, memaddr, info);
00257          return -1;
00258        }
00259       insn <<= 16;
00260       insn |= bfd_getb16 (buffer);
00261       extension = 0;
00262       consume = 3;
00263     }
00264 
00265   /* These are four byte insns.  */
00266   else if ((insn & 0xff) == 0xf7)
00267     {
00268       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
00269       if (status != 0)
00270        {
00271          (*info->memory_error_func) (status, memaddr, info);
00272          return -1;
00273        }
00274       insn = bfd_getb16 (buffer);
00275       insn <<= 16;
00276       status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
00277       if (status != 0)
00278        {
00279          (*info->memory_error_func) (status, memaddr, info);
00280          return -1;
00281        }
00282       insn |= bfd_getl16 (buffer);
00283       extension = 0;
00284       consume = 4;
00285     }
00286 
00287   /* These are five byte insns.  */
00288   else if ((insn & 0xff) == 0xf4)
00289     {
00290       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
00291       if (status != 0)
00292        {
00293          (*info->memory_error_func) (status, memaddr, info);
00294          return -1;
00295        }
00296       insn = bfd_getb16 (buffer);
00297       insn <<= 16;
00298 
00299       status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
00300       if (status != 0)
00301        {
00302          (*info->memory_error_func) (status, memaddr, info);
00303          return -1;
00304        }
00305       insn |= (*(unsigned char *)buffer << 8) & 0xff00;
00306 
00307       status = (*info->read_memory_func) (memaddr + 3, buffer, 1, info);
00308       if (status != 0)
00309        {
00310          (*info->memory_error_func) (status, memaddr, info);
00311          return -1;
00312        }
00313       insn |= (*(unsigned char *)buffer) & 0xff;
00314 
00315       status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
00316       if (status != 0)
00317        {
00318          (*info->memory_error_func) (status, memaddr, info);
00319          return -1;
00320        }
00321       extension = (*(unsigned char *)buffer) & 0xff;
00322       consume = 5;
00323     }
00324   else
00325     {
00326       (*info->fprintf_func) (info->stream, _("unknown\t0x%02lx"), insn);
00327       return 1;
00328     }
00329 
00330   disassemble (memaddr, info, insn, extension, consume);
00331 
00332   return consume;
00333 }