Back to index

cell-binutils  2.17cvs20070401
Defines | Functions
m10300-dis.c File Reference
#include <stdio.h>
#include "sysdep.h"
#include "opcode/mn10300.h"
#include "dis-asm.h"
#include "opintl.h"

Go to the source code of this file.

Defines

#define HAVE_AM33_2   (info->mach == AM33_2)
#define HAVE_AM33   (info->mach == AM33 || HAVE_AM33_2)
#define HAVE_AM30   (info->mach == AM30)

Functions

static void disassemble (bfd_vma memaddr, struct disassemble_info *info, unsigned long insn, unsigned int size)
int print_insn_mn10300 (bfd_vma memaddr, struct disassemble_info *info)

Define Documentation

#define HAVE_AM30   (info->mach == AM30)

Definition at line 29 of file m10300-dis.c.

#define HAVE_AM33   (info->mach == AM33 || HAVE_AM33_2)

Definition at line 28 of file m10300-dis.c.

#define HAVE_AM33_2   (info->mach == AM33_2)

Definition at line 27 of file m10300-dis.c.


Function Documentation

static void disassemble ( bfd_vma  memaddr,
struct disassemble_info info,
unsigned long  insn,
unsigned int  size 
) [static]

Definition at line 32 of file m10300-dis.c.

{
  struct mn10300_opcode *op = (struct mn10300_opcode *) mn10300_opcodes;
  const struct mn10300_operand *operand;
  bfd_byte buffer[4];
  unsigned long extension = 0;
  int status, match = 0;

  /* Find the opcode.  */
  while (op->name)
    {
      int mysize, extra_shift;

      if (op->format == FMT_S0)
       mysize = 1;
      else if (op->format == FMT_S1
              || op->format == FMT_D0)
       mysize = 2;
      else if (op->format == FMT_S2
              || op->format == FMT_D1)
       mysize = 3;
      else if (op->format == FMT_S4)
       mysize = 5;
      else if (op->format == FMT_D2)
       mysize = 4;
      else if (op->format == FMT_D3)
       mysize = 5;
      else if (op->format == FMT_D4)
       mysize = 6;
      else if (op->format == FMT_D6)
       mysize = 3;
      else if (op->format == FMT_D7 || op->format == FMT_D10)
       mysize = 4;
      else if (op->format == FMT_D8)
       mysize = 6;
      else if (op->format == FMT_D9)
       mysize = 7;
      else
       mysize = 7;

      if ((op->mask & insn) == op->opcode
         && size == (unsigned int) mysize
         && (op->machine == 0
             || (op->machine == AM33_2 && HAVE_AM33_2)
             || (op->machine == AM33 && HAVE_AM33)
             || (op->machine == AM30 && HAVE_AM30)))
       {
         const unsigned char *opindex_ptr;
         unsigned int nocomma;
         int paren = 0;

         if (op->format == FMT_D1 || op->format == FMT_S1)
           extra_shift = 8;
         else if (op->format == FMT_D2 || op->format == FMT_D4
                 || op->format == FMT_S2 || op->format == FMT_S4
                 || op->format == FMT_S6 || op->format == FMT_D5)
           extra_shift = 16;
         else if (op->format == FMT_D7
                 || op->format == FMT_D8
                 || op->format == FMT_D9)
           extra_shift = 8;
         else
           extra_shift = 0;

         if (size == 1 || size == 2)
           extension = 0;

         else if (size == 3
                 && (op->format == FMT_D1
                     || op->opcode == 0xdf0000
                     || op->opcode == 0xde0000))
           extension = 0;

         else if (size == 3
                 && op->format == FMT_D6)
           extension = 0;

         else if (size == 3)
           {
             insn &= 0xff0000;
             status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }

             insn |= bfd_getl16 (buffer);
             extension = 0;
           }
         else if (size == 4
                 && (op->opcode == 0xfaf80000
                     || op->opcode == 0xfaf00000
                     || op->opcode == 0xfaf40000))
           extension = 0;

         else if (size == 4
                 && (op->format == FMT_D7
                     || op->format == FMT_D10))
           extension = 0;

         else if (size == 4)
           {
             insn &= 0xffff0000;
             status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }

             insn |= bfd_getl16 (buffer);
             extension = 0;
           }
         else if (size == 5 && op->opcode == 0xdc000000)
           {
             unsigned long temp = 0;

             status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             temp |= bfd_getl32 (buffer);

             insn &= 0xff000000;
             insn |= (temp & 0xffffff00) >> 8;
             extension = temp & 0xff;
           }
         else if (size == 5 && op->format == FMT_D3)
           {
             status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             insn &= 0xffff0000;
             insn |= bfd_getl16 (buffer);

             status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             extension = *(unsigned char *) buffer;
           }
         else if (size == 5)
           {
             unsigned long temp = 0;

             status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             temp |= bfd_getl16 (buffer);

             insn &= 0xff0000ff;
             insn |= temp << 8;

             status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             extension = *(unsigned char *) buffer;
           }
         else if (size == 6 && op->format == FMT_D8)
           {
             insn &= 0xffffff00;
             status = (*info->read_memory_func) (memaddr + 5, buffer, 1, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             insn |= *(unsigned char *) buffer;

             status = (*info->read_memory_func) (memaddr + 3, buffer, 2, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             extension = bfd_getl16 (buffer);
           }
         else if (size == 6)
           {
             unsigned long temp = 0;

             status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             temp |= bfd_getl32 (buffer);

             insn &= 0xffff0000;
             insn |= (temp >> 16) & 0xffff;
             extension = temp & 0xffff;
           }
         else if (size == 7 && op->format == FMT_D9)
           {
             insn &= 0xffffff00;
             status = (*info->read_memory_func) (memaddr + 3, buffer, 4, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             extension = bfd_getl32 (buffer);
             insn |= (extension & 0xff000000) >> 24;
             extension &= 0xffffff;
           }
         else if (size == 7 && op->opcode == 0xdd000000)
           {
             unsigned long temp = 0;

             status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             temp |= bfd_getl32 (buffer);

             insn &= 0xff000000;
             insn |= (temp >> 8) & 0xffffff;
             extension = (temp & 0xff) << 16;

             status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             extension |= bfd_getb16 (buffer);
           }
         else if (size == 7)
           {
             unsigned long temp = 0;

             status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             temp |= bfd_getl32 (buffer);

             insn &= 0xffff0000;
             insn |= (temp >> 16) & 0xffff;
             extension = (temp & 0xffff) << 8;

             status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
             if (status != 0)
              {
                (*info->memory_error_func) (status, memaddr, info);
                return;
              }
             extension |= *(unsigned char *) buffer;
           }

         match = 1;
         (*info->fprintf_func) (info->stream, "%s\t", op->name);

         /* Now print the operands.  */
         for (opindex_ptr = op->operands, nocomma = 1;
              *opindex_ptr != 0;
              opindex_ptr++)
           {
             unsigned long value;

             operand = &mn10300_operands[*opindex_ptr];

             /* If this operand is a PLUS (autoincrement), then do not emit
               a comma before emitting the plus.  */
             if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
              nocomma = 1;

             if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
              {
                unsigned long temp;

                value = insn & ((1 << operand->bits) - 1);
                value <<= (32 - operand->bits);
                temp = extension >> operand->shift;
                temp &= ((1 << (32 - operand->bits)) - 1);
                value |= temp;
                value = ((value ^ (((unsigned long) 1) << 31))
                        - (((unsigned long) 1) << 31));
              }
             else if ((operand->flags & MN10300_OPERAND_24BIT) != 0)
              {
                unsigned long temp;

                value = insn & ((1 << operand->bits) - 1);
                value <<= (24 - operand->bits);
                temp = extension >> operand->shift;
                temp &= ((1 << (24 - operand->bits)) - 1);
                value |= temp;
                if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
                  value = ((value & 0xffffff) ^ 0x800000) - 0x800000;
              }
             else if ((operand->flags & (MN10300_OPERAND_FSREG
                                     | MN10300_OPERAND_FDREG)))
              {
                /* See m10300-opc.c just before #define FSM0 for an
                   explanation of these variables.  Note that
                   FMT-implied shifts are not taken into account for
                   FP registers.  */
                unsigned long mask_low, mask_high;
                int shl_low, shr_high, shl_high;

                switch (operand->bits)
                  {
                  case 5:
                    /* Handle regular FP registers.  */
                    if (operand->shift >= 0)
                     {
                       /* This is an `m' register.  */
                       shl_low = operand->shift;
                       shl_high = 8 + (8 & shl_low) + (shl_low & 4) / 4;
                     }
                    else
                     {
                       /* This is an `n' register.  */
                       shl_low = -operand->shift;
                       shl_high = shl_low / 4;
                     }
                    mask_low = 0x0f;
                    mask_high = 0x10;
                    shr_high = 4;
                    break;

                  case 3:
                    /* Handle accumulators.  */
                    shl_low = -operand->shift;
                    shl_high = 0;
                    mask_low = 0x03;
                    mask_high = 0x04;
                    shr_high = 2;
                    break;

                  default:
                    abort ();
                  }
                value = ((((insn >> shl_high) << shr_high) & mask_high)
                        | ((insn >> shl_low) & mask_low));
              }
             else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
              value = ((extension >> (operand->shift))
                      & ((1 << operand->bits) - 1));

             else
              value = ((insn >> (operand->shift))
                      & ((1 << operand->bits) - 1));

             if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
                /* These are properly extended by the code above.  */
                && ((operand->flags & MN10300_OPERAND_24BIT) == 0))
              value = ((value ^ (((unsigned long) 1) << (operand->bits - 1)))
                      - (((unsigned long) 1) << (operand->bits - 1)));

             if (!nocomma
                && (!paren
                    || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
              (*info->fprintf_func) (info->stream, ",");

             nocomma = 0;

             if ((operand->flags & MN10300_OPERAND_DREG) != 0)
              {
                value = ((insn >> (operand->shift + extra_shift))
                        & ((1 << operand->bits) - 1));
                (*info->fprintf_func) (info->stream, "d%d", (int) value);
              }

             else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
              {
                value = ((insn >> (operand->shift + extra_shift))
                        & ((1 << operand->bits) - 1));
                (*info->fprintf_func) (info->stream, "a%d", (int) value);
              }

             else if ((operand->flags & MN10300_OPERAND_SP) != 0)
              (*info->fprintf_func) (info->stream, "sp");

             else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
              (*info->fprintf_func) (info->stream, "psw");

             else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
              (*info->fprintf_func) (info->stream, "mdr");

             else if ((operand->flags & MN10300_OPERAND_RREG) != 0)
              {
                value = ((insn >> (operand->shift + extra_shift))
                        & ((1 << operand->bits) - 1));
                if (value < 8)
                  (*info->fprintf_func) (info->stream, "r%d", (int) value);
                else if (value < 12)
                  (*info->fprintf_func) (info->stream, "a%d", (int) value - 8);
                else
                  (*info->fprintf_func) (info->stream, "d%d", (int) value - 12);
              }

             else if ((operand->flags & MN10300_OPERAND_XRREG) != 0)
              {
                value = ((insn >> (operand->shift + extra_shift))
                        & ((1 << operand->bits) - 1));
                if (value == 0)
                  (*info->fprintf_func) (info->stream, "sp");
                else
                  (*info->fprintf_func) (info->stream, "xr%d", (int) value);
              }

             else if ((operand->flags & MN10300_OPERAND_FSREG) != 0)
              (*info->fprintf_func) (info->stream, "fs%d", (int) value);

             else if ((operand->flags & MN10300_OPERAND_FDREG) != 0)
              (*info->fprintf_func) (info->stream, "fd%d", (int) value);

             else if ((operand->flags & MN10300_OPERAND_FPCR) != 0)
              (*info->fprintf_func) (info->stream, "fpcr");

             else if ((operand->flags & MN10300_OPERAND_USP) != 0)
              (*info->fprintf_func) (info->stream, "usp");

             else if ((operand->flags & MN10300_OPERAND_SSP) != 0)
              (*info->fprintf_func) (info->stream, "ssp");

             else if ((operand->flags & MN10300_OPERAND_MSP) != 0)
              (*info->fprintf_func) (info->stream, "msp");

             else if ((operand->flags & MN10300_OPERAND_PC) != 0)
              (*info->fprintf_func) (info->stream, "pc");

             else if ((operand->flags & MN10300_OPERAND_EPSW) != 0)
              (*info->fprintf_func) (info->stream, "epsw");

             else if ((operand->flags & MN10300_OPERAND_PLUS) != 0)
              (*info->fprintf_func) (info->stream, "+");

             else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
              {
                if (paren)
                  (*info->fprintf_func) (info->stream, ")");
                else
                  {
                    (*info->fprintf_func) (info->stream, "(");
                    nocomma = 1;
                  }
                paren = !paren;
              }

             else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
              (*info->print_address_func) ((long) value + memaddr, info);

             else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
              (*info->print_address_func) (value, info);

             else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
              {
                int comma = 0;

                (*info->fprintf_func) (info->stream, "[");
                if (value & 0x80)
                  {
                    (*info->fprintf_func) (info->stream, "d2");
                    comma = 1;
                  }

                if (value & 0x40)
                  {
                    if (comma)
                     (*info->fprintf_func) (info->stream, ",");
                    (*info->fprintf_func) (info->stream, "d3");
                    comma = 1;
                  }

                if (value & 0x20)
                  {
                    if (comma)
                     (*info->fprintf_func) (info->stream, ",");
                    (*info->fprintf_func) (info->stream, "a2");
                    comma = 1;
                  }

                if (value & 0x10)
                  {
                    if (comma)
                     (*info->fprintf_func) (info->stream, ",");
                    (*info->fprintf_func) (info->stream, "a3");
                    comma = 1;
                  }

                if (value & 0x08)
                  {
                    if (comma)
                     (*info->fprintf_func) (info->stream, ",");
                    (*info->fprintf_func) (info->stream, "other");
                    comma = 1;
                  }

                if (value & 0x04)
                  {
                    if (comma)
                     (*info->fprintf_func) (info->stream, ",");
                    (*info->fprintf_func) (info->stream, "exreg0");
                    comma = 1;
                  }
                if (value & 0x02)
                  {
                    if (comma)
                     (*info->fprintf_func) (info->stream, ",");
                    (*info->fprintf_func) (info->stream, "exreg1");
                    comma = 1;
                  }
                if (value & 0x01)
                  {
                    if (comma)
                     (*info->fprintf_func) (info->stream, ",");
                    (*info->fprintf_func) (info->stream, "exother");
                    comma = 1;
                  }
                (*info->fprintf_func) (info->stream, "]");
              }

             else
              (*info->fprintf_func) (info->stream, "%ld", (long) value);
           }
         /* All done. */
         break;
       }
      op++;
    }

  if (!match)
    /* xgettext:c-format */
    (*info->fprintf_func) (info->stream, _("unknown\t0x%04lx"), insn);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 584 of file m10300-dis.c.

{
  int status;
  bfd_byte buffer[4];
  unsigned long insn;
  unsigned int consume;

  /* First figure out how big the opcode is.  */
  status = (*info->read_memory_func) (memaddr, buffer, 1, info);
  if (status != 0)
    {
      (*info->memory_error_func) (status, memaddr, info);
      return -1;
    }
  insn = *(unsigned char *) buffer;

  /* These are one byte insns.  */
  if ((insn & 0xf3) == 0x00
      || (insn & 0xf0) == 0x10
      || (insn & 0xfc) == 0x3c
      || (insn & 0xf3) == 0x41
      || (insn & 0xf3) == 0x40
      || (insn & 0xfc) == 0x50
      || (insn & 0xfc) == 0x54
      || (insn & 0xf0) == 0x60
      || (insn & 0xf0) == 0x70
      || ((insn & 0xf0) == 0x80
         && (insn & 0x0c) >> 2 != (insn & 0x03))
      || ((insn & 0xf0) == 0x90
         && (insn & 0x0c) >> 2 != (insn & 0x03))
      || ((insn & 0xf0) == 0xa0
         && (insn & 0x0c) >> 2 != (insn & 0x03))
      || ((insn & 0xf0) == 0xb0
         && (insn & 0x0c) >> 2 != (insn & 0x03))
      || (insn & 0xff) == 0xcb
      || (insn & 0xfc) == 0xd0
      || (insn & 0xfc) == 0xd4
      || (insn & 0xfc) == 0xd8
      || (insn & 0xf0) == 0xe0
      || (insn & 0xff) == 0xff)
    {
      consume = 1;
    }

  /* These are two byte insns.  */
  else if ((insn & 0xf0) == 0x80
          || (insn & 0xf0) == 0x90
          || (insn & 0xf0) == 0xa0
          || (insn & 0xf0) == 0xb0
          || (insn & 0xfc) == 0x20
          || (insn & 0xfc) == 0x28
          || (insn & 0xf3) == 0x43
          || (insn & 0xf3) == 0x42
          || (insn & 0xfc) == 0x58
          || (insn & 0xfc) == 0x5c
          || ((insn & 0xf0) == 0xc0
              && (insn & 0xff) != 0xcb
              && (insn & 0xff) != 0xcc
              && (insn & 0xff) != 0xcd)
          || (insn & 0xff) == 0xf0
          || (insn & 0xff) == 0xf1
          || (insn & 0xff) == 0xf2
          || (insn & 0xff) == 0xf3
          || (insn & 0xff) == 0xf4
          || (insn & 0xff) == 0xf5
          || (insn & 0xff) == 0xf6)
    {
      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
      if (status != 0)
       {
         (*info->memory_error_func) (status, memaddr, info);
         return -1;
       }
      insn = bfd_getb16 (buffer);
      consume = 2;
    }

  /* These are three byte insns.  */
  else if ((insn & 0xff) == 0xf8
          || (insn & 0xff) == 0xcc
          || (insn & 0xff) == 0xf9
          || (insn & 0xf3) == 0x01
          || (insn & 0xf3) == 0x02
          || (insn & 0xf3) == 0x03
          || (insn & 0xfc) == 0x24
          || (insn & 0xfc) == 0x2c
          || (insn & 0xfc) == 0x30
          || (insn & 0xfc) == 0x34
          || (insn & 0xfc) == 0x38
          || (insn & 0xff) == 0xde
          || (insn & 0xff) == 0xdf
          || (insn & 0xff) == 0xf9
          || (insn & 0xff) == 0xcc)
    {
      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
      if (status != 0)
       {
         (*info->memory_error_func) (status, memaddr, info);
         return -1;
       }
      insn = bfd_getb16 (buffer);
      insn <<= 8;
      status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
      if (status != 0)
       {
         (*info->memory_error_func) (status, memaddr, info);
         return -1;
       }
      insn |= *(unsigned char *) buffer;
      consume = 3;
    }

  /* These are four byte insns.  */
  else if ((insn & 0xff) == 0xfa
          || (insn & 0xff) == 0xf7
          || (insn & 0xff) == 0xfb)
    {
      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
      if (status != 0)
       {
         (*info->memory_error_func) (status, memaddr, info);
         return -1;
       }
      insn = bfd_getb32 (buffer);
      consume = 4;
    }

  /* These are five byte insns.  */
  else if ((insn & 0xff) == 0xcd
          || (insn & 0xff) == 0xdc)
    {
      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
      if (status != 0)
       {
         (*info->memory_error_func) (status, memaddr, info);
         return -1;
       }
      insn = bfd_getb32 (buffer);
      consume = 5;
    }

  /* These are six byte insns.  */
  else if ((insn & 0xff) == 0xfd
          || (insn & 0xff) == 0xfc)
    {
      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
      if (status != 0)
       {
         (*info->memory_error_func) (status, memaddr, info);
         return -1;
       }

      insn = bfd_getb32 (buffer);
      consume = 6;
    }

  /* Else its a seven byte insns (in theory).  */
  else
    {
      status = (*info->read_memory_func) (memaddr, buffer, 4, info);
      if (status != 0)
       {
         (*info->memory_error_func) (status, memaddr, info);
         return -1;
       }

      insn = bfd_getb32 (buffer);
      consume = 7;
      /* Handle the 5-byte extended instruction codes.  */
      if ((insn & 0xfff80000) == 0xfe800000)
       consume = 5;
    }

  disassemble (memaddr, info, insn, consume);

  return consume;
}

Here is the call graph for this function:

Here is the caller graph for this function: