Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
ns32k-dis.c File Reference
#include "bfd.h"
#include "sysdep.h"
#include "dis-asm.h"
#include "opcode/ns32k.h"
#include "opintl.h"
#include <setjmp.h>

Go to the source code of this file.

Classes

struct  private
struct  ns32k_option

Defines

#define const
#define INVALID_FLOAT(val, size)   invalid_float ((bfd_byte *) val, size)
#define MAXLEN   62
#define FETCH_DATA(info, addr)
#define NOPCODES   (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])
#define NEXT_IS_ADDR   '|'
#define Is_gen(c)
#define Adrmod_index_byte   0x1c
#define Adrmod_index_word   0x1d
#define Adrmod_index_doubleword   0x1e
#define Adrmod_index_quadword   0x1f
#define Adrmod_is_index(mode)

Functions

static long read_memory_integer (unsigned char *addr, int nr)
static int fetch_data (struct disassemble_info *info, bfd_byte *addr)
static void optlist (int options, const struct ns32k_option *optionP, char *result)
static void list_search (int reg_value, const struct ns32k_option *optionP, char *result)
static int bit_extract (bfd_byte *buffer, int offset, int count)
static int bit_extract_simple (bfd_byte *buffer, int offset, int count)
static void bit_copy (bfd_byte *buffer, int offset, int count, char *to)
static int sign_extend (int value, int bits)
static void flip_bytes (char *ptr, int count)
static int get_displacement (bfd_byte *buffer, int *aoffsetp)
static int invalid_float (bfd_byte *p, int len)
static int print_insn_arg (int d, int ioffset, int *aoffsetp, bfd_byte *buffer, bfd_vma addr, char *result, int index_offset)
int print_insn_ns32k (bfd_vma memaddr, disassemble_info *info)

Variables

static disassemble_infodis_info
static struct ns32k_option []

Class Documentation

struct private

Definition at line 35 of file h8500-dis.c.

Class Members
jmp_buf bailout
bfd_vma insn_start
bfd_byte * max_fetched
bfd_byte the_buffer
struct ns32k_option

Definition at line 103 of file tc-ns32k.c.

Class Members
unsigned long and
unsigned long match
unsigned long or
char * pattern
unsigned long value

Define Documentation

#define Adrmod_index_byte   0x1c

Definition at line 353 of file ns32k-dis.c.

#define Adrmod_index_doubleword   0x1e

Definition at line 355 of file ns32k-dis.c.

#define Adrmod_index_quadword   0x1f

Definition at line 356 of file ns32k-dis.c.

#define Adrmod_index_word   0x1d

Definition at line 354 of file ns32k-dis.c.

#define Adrmod_is_index (   mode)
Value:

Definition at line 359 of file ns32k-dis.c.

#define const

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

#define FETCH_DATA (   info,
  addr 
)
Value:
((addr) <= ((struct private *)(info->private_data))->max_fetched \
   ? 1 : fetch_data ((info), (addr)))

Definition at line 69 of file ns32k-dis.c.

#define INVALID_FLOAT (   val,
  size 
)    invalid_float ((bfd_byte *) val, size)

Definition at line 35 of file ns32k-dis.c.

#define Is_gen (   c)
Value:
((c) == 'F' || (c) == 'L' || (c) == 'B' \
   || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z')

Definition at line 348 of file ns32k-dis.c.

#define MAXLEN   62

Definition at line 52 of file ns32k-dis.c.

#define NEXT_IS_ADDR   '|'

Definition at line 97 of file ns32k-dis.c.

#define NOPCODES   (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0])

Definition at line 95 of file ns32k-dis.c.


Function Documentation

static void bit_copy ( bfd_byte buffer,
int  offset,
int  count,
char *  to 
) [static]

Definition at line 316 of file ns32k-dis.c.

{
  for (; count > 8; count -= 8, to++, offset += 8)
    *to = bit_extract (buffer, offset, 8);
  *to = bit_extract (buffer, offset, count);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int bit_extract ( bfd_byte buffer,
int  offset,
int  count 
) [static]

Definition at line 265 of file ns32k-dis.c.

{
  int result;
  int bit;

  buffer += offset >> 3;
  offset &= 7;
  bit = 1;
  result = 0;
  while (count--)
    {
      FETCH_DATA (dis_info, buffer + 1);
      if ((*buffer & (1 << offset)))
       result |= bit;
      if (++offset == 8)
       {
         offset = 0;
         buffer++;
       }
      bit <<= 1;
    }
  return result;
}

Here is the caller graph for this function:

static int bit_extract_simple ( bfd_byte buffer,
int  offset,
int  count 
) [static]

Definition at line 292 of file ns32k-dis.c.

{
  int result;
  int bit;

  buffer += offset >> 3;
  offset &= 7;
  bit = 1;
  result = 0;
  while (count--)
    {
      if ((*buffer & (1 << offset)))
       result |= bit;
      if (++offset == 8)
       {
         offset = 0;
         buffer++;
       }
      bit <<= 1;
    }
  return result;
}

Here is the caller graph for this function:

static int fetch_data ( struct disassemble_info info,
bfd_byte addr 
) [static]

Definition at line 74 of file ns32k-dis.c.

{
  int status;
  struct private *priv = (struct private *) info->private_data;
  bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);

  status = (*info->read_memory_func) (start,
                                  priv->max_fetched,
                                  addr - priv->max_fetched,
                                  info);
  if (status != 0)
    {
      (*info->memory_error_func) (status, start, info);
      longjmp (priv->bailout, 1);
    }
  else
    priv->max_fetched = addr;
  return 1;
}
static void flip_bytes ( char *  ptr,
int  count 
) [static]

Definition at line 333 of file ns32k-dis.c.

{
  char tmp;

  while (count > 0)
    {
      tmp = ptr[0];
      ptr[0] = ptr[count - 1];
      ptr[count - 1] = tmp;
      ptr++;
      count -= 2;
    }
}

Here is the caller graph for this function:

static int get_displacement ( bfd_byte buffer,
int aoffsetp 
) [static]

Definition at line 367 of file ns32k-dis.c.

{
  int Ivalue;
  short Ivalue2;

  Ivalue = bit_extract (buffer, *aoffsetp, 8);
  switch (Ivalue & 0xc0)
    {
    case 0x00:
    case 0x40:
      Ivalue = sign_extend (Ivalue, 7);
      *aoffsetp += 8;
      break;
    case 0x80:
      Ivalue2 = bit_extract (buffer, *aoffsetp, 16);
      flip_bytes ((char *) & Ivalue2, 2);
      Ivalue = sign_extend (Ivalue2, 14);
      *aoffsetp += 16;
      break;
    case 0xc0:
      Ivalue = bit_extract (buffer, *aoffsetp, 32);
      flip_bytes ((char *) & Ivalue, 4);
      Ivalue = sign_extend (Ivalue, 30);
      *aoffsetp += 32;
      break;
    }
  return Ivalue;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int invalid_float ( bfd_byte p,
int  len 
) [static]

Definition at line 398 of file ns32k-dis.c.

{
  int val;

  if (len == 4)
    val = (bit_extract_simple (p, 23, 8)/*exponent*/ == 0xff
          || (bit_extract_simple (p, 23, 8)/*exponent*/ == 0
              && bit_extract_simple (p, 0, 23)/*mantisa*/ != 0));
  else if (len == 8)
    val = (bit_extract_simple (p, 52, 11)/*exponent*/ == 0x7ff
          || (bit_extract_simple (p, 52, 11)/*exponent*/ == 0
              && (bit_extract_simple (p, 0, 32)/*low mantisa*/ != 0
                 || bit_extract_simple (p, 32, 20)/*high mantisa*/ != 0)));
  else
    val = 1;
  return (val);
}

Here is the call graph for this function:

static void list_search ( int  reg_value,
const struct ns32k_option optionP,
char *  result 
) [static]

Definition at line 249 of file ns32k-dis.c.

{
  for (; optionP->pattern; optionP++)
    {
      if ((reg_value & optionP->match) == optionP->value)
       {
         sprintf (result, "%s", optionP->pattern);
         return;
       }
    }
  sprintf (result, "undefined");
}

Here is the caller graph for this function:

static void optlist ( int  options,
const struct ns32k_option optionP,
char *  result 
) [static]

Definition at line 220 of file ns32k-dis.c.

{
  if (options == 0)
    {
      sprintf (result, "[]");
      return;
    }

  sprintf (result, "[");

  for (; (options != 0) && optionP->pattern; optionP++)
    {
      if ((options & optionP->match) == optionP->value)
       {
         /* We found a match, update result and options.  */
         strcat (result, optionP->pattern);
         options &= ~optionP->value;
         if (options != 0)  /* More options to come.  */
           strcat (result, ",");
       }
    }

  if (options != 0)
    strcat (result, "undefined");

  strcat (result, "]");
}

Here is the caller graph for this function:

static int print_insn_arg ( int  d,
int  ioffset,
int aoffsetp,
bfd_byte buffer,
bfd_vma  addr,
char *  result,
int  index_offset 
) [static]

Definition at line 453 of file ns32k-dis.c.

{
  union
  {
    float f;
    double d;
    int i[2];
  } value;
  int Ivalue;
  int addr_mode;
  int disp1, disp2;
  int index;
  int size;

  switch (d)
    {
    case 'f':
      /* A "gen" operand but 5 bits from the end of instruction.  */
      ioffset -= 5;
    case 'Z':
    case 'F':
    case 'L':
    case 'I':
    case 'B':
    case 'W':
    case 'D':
    case 'A':
      addr_mode = bit_extract (buffer, ioffset - 5, 5);
      ioffset -= 5;
      switch (addr_mode)
       {
       case 0x0: case 0x1: case 0x2: case 0x3:
       case 0x4: case 0x5: case 0x6: case 0x7:
         /* Register mode R0 -- R7.  */
         switch (d)
           {
           case 'F':
           case 'L':
           case 'Z':
             sprintf (result, "f%d", addr_mode);
             break;
           default:
             sprintf (result, "r%d", addr_mode);
           }
         break;
       case 0x8: case 0x9: case 0xa: case 0xb:
       case 0xc: case 0xd: case 0xe: case 0xf:
         /* Register relative disp(R0 -- R7).  */
         disp1 = get_displacement (buffer, aoffsetp);
         sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
         break;
       case 0x10:
       case 0x11:
       case 0x12:
         /* Memory relative disp2(disp1(FP, SP, SB)).  */
         disp1 = get_displacement (buffer, aoffsetp);
         disp2 = get_displacement (buffer, aoffsetp);
         sprintf (result, "%d(%d(%s))", disp2, disp1,
                 addr_mode == 0x10 ? "fp" : addr_mode == 0x11 ? "sp" : "sb");
         break;
       case 0x13:
         /* Reserved.  */
         sprintf (result, "reserved");
         break;
       case 0x14:
         /* Immediate.  */
         switch (d)
           {
           case 'I':
           case 'Z':
           case 'A':
             /* I and Z are output operands and can`t be immediate
                A is an address and we can`t have the address of
                an immediate either. We don't know how much to increase
                aoffsetp by since whatever generated this is broken
                anyway!  */
             sprintf (result, _("$<undefined>"));
             break;
           case 'B':
             Ivalue = bit_extract (buffer, *aoffsetp, 8);
             Ivalue = sign_extend (Ivalue, 8);
             *aoffsetp += 8;
             sprintf (result, "$%d", Ivalue);
             break;
           case 'W':
             Ivalue = bit_extract (buffer, *aoffsetp, 16);
             flip_bytes ((char *) & Ivalue, 2);
             *aoffsetp += 16;
             Ivalue = sign_extend (Ivalue, 16);
             sprintf (result, "$%d", Ivalue);
             break;
           case 'D':
             Ivalue = bit_extract (buffer, *aoffsetp, 32);
             flip_bytes ((char *) & Ivalue, 4);
             *aoffsetp += 32;
             sprintf (result, "$%d", Ivalue);
             break;
           case 'F':
             bit_copy (buffer, *aoffsetp, 32, (char *) &value.f);
             flip_bytes ((char *) &value.f, 4);
             *aoffsetp += 32;
             if (INVALID_FLOAT (&value.f, 4))
              sprintf (result, "<<invalid float 0x%.8x>>", value.i[0]);
             else /* Assume host has ieee float.  */
              sprintf (result, "$%g", value.f);
             break;
           case 'L':
             bit_copy (buffer, *aoffsetp, 64, (char *) &value.d);
             flip_bytes ((char *) &value.d, 8);
             *aoffsetp += 64;
             if (INVALID_FLOAT (&value.d, 8))
              sprintf (result, "<<invalid double 0x%.8x%.8x>>",
                      value.i[1], value.i[0]);
             else /* Assume host has ieee float.  */
              sprintf (result, "$%g", value.d);
             break;
           }
         break;
       case 0x15:
         /* Absolute @disp.  */
         disp1 = get_displacement (buffer, aoffsetp);
         sprintf (result, "@|%d|", disp1);
         break;
       case 0x16:
         /* External EXT(disp1) + disp2 (Mod table stuff).  */
         disp1 = get_displacement (buffer, aoffsetp);
         disp2 = get_displacement (buffer, aoffsetp);
         sprintf (result, "EXT(%d) + %d", disp1, disp2);
         break;
       case 0x17:
         /* Top of stack tos.  */
         sprintf (result, "tos");
         break;
       case 0x18:
         /* Memory space disp(FP).  */
         disp1 = get_displacement (buffer, aoffsetp);
         sprintf (result, "%d(fp)", disp1);
         break;
       case 0x19:
         /* Memory space disp(SP).  */
         disp1 = get_displacement (buffer, aoffsetp);
         sprintf (result, "%d(sp)", disp1);
         break;
       case 0x1a:
         /* Memory space disp(SB).  */
         disp1 = get_displacement (buffer, aoffsetp);
         sprintf (result, "%d(sb)", disp1);
         break;
       case 0x1b:
         /* Memory space disp(PC).  */
         disp1 = get_displacement (buffer, aoffsetp);
         *result++ = NEXT_IS_ADDR;
         sprintf_vma (result, addr + disp1);
         result += strlen (result);
         *result++ = NEXT_IS_ADDR;
         *result = '\0';
         break;
       case 0x1c:
       case 0x1d:
       case 0x1e:
       case 0x1f:
         /* Scaled index basemode[R0 -- R7:B,W,D,Q].  */
         index = bit_extract (buffer, index_offset - 8, 3);
         print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
                       result, 0);
         {
           static const char *ind = "bwdq";
           char *off;

           off = result + strlen (result);
           sprintf (off, "[r%d:%c]", index,
                   ind[addr_mode & 3]);
         }
         break;
       }
      break;
    case 'H':
    case 'q':
      Ivalue = bit_extract (buffer, ioffset-4, 4);
      Ivalue = sign_extend (Ivalue, 4);
      sprintf (result, "%d", Ivalue);
      ioffset -= 4;
      break;
    case 'r':
      Ivalue = bit_extract (buffer, ioffset-3, 3);
      sprintf (result, "r%d", Ivalue&7);
      ioffset -= 3;
      break;
    case 'd':
      sprintf (result, "%d", get_displacement (buffer, aoffsetp));
      break;
    case 'b':
      Ivalue = get_displacement (buffer, aoffsetp);
      /* Warning!!  HACK ALERT!
         Operand type 'b' is only used by the cmp{b,w,d} and
         movm{b,w,d} instructions; we need to know whether
         it's a `b' or `w' or `d' instruction; and for both
         cmpm and movm it's stored at the same place so we
         just grab two bits of the opcode and look at it...  */
      size = bit_extract(buffer, ioffset-6, 2);
      if (size == 0)        /* 00 => b.  */
       size = 1;
      else if (size == 1)   /* 01 => w.  */
       size = 2;
      else
       size = 4;            /* 11 => d.  */

      sprintf (result, "%d", (Ivalue / size) + 1);
      break;
    case 'p':
      *result++ = NEXT_IS_ADDR;
      sprintf_vma (result, addr + get_displacement (buffer, aoffsetp));
      result += strlen (result);
      *result++ = NEXT_IS_ADDR;
      *result = '\0';
      break;
    case 'i':
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
      *aoffsetp += 8;
      sprintf (result, "0x%x", Ivalue);
      break;
    case 'u':
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
      optlist (Ivalue, opt_u, result);
      *aoffsetp += 8;
      break;
    case 'U':
      Ivalue = bit_extract (buffer, *aoffsetp, 8);
      optlist (Ivalue, opt_U, result);
      *aoffsetp += 8;
      break;
    case 'O':
      Ivalue = bit_extract (buffer, ioffset - 9, 9);
      optlist (Ivalue, opt_O, result);
      ioffset -= 9;
      break;
    case 'C':
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
      optlist (Ivalue, opt_C, result);
      ioffset -= 4;
      break;
    case 'S':
      Ivalue = bit_extract (buffer, ioffset - 8, 8);
      optlist (Ivalue, opt_S, result);
      ioffset -= 8;
      break;
    case 'M':
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
      list_search (Ivalue, 0 ? list_M032 : list_M532, result);
      ioffset -= 4;
      break;
    case 'P':
      Ivalue = bit_extract (buffer, ioffset - 4, 4);
      list_search (Ivalue, 0 ? list_P032 : list_P532, result);
      ioffset -= 4;
      break;
    case 'g':
      Ivalue = bit_extract (buffer, *aoffsetp, 3);
      sprintf (result, "%d", Ivalue);
      *aoffsetp += 3;
      break;
    case 'G':
      Ivalue = bit_extract(buffer, *aoffsetp, 5);
      sprintf (result, "%d", Ivalue + 1);
      *aoffsetp += 5;
      break;
    }
  return ioffset;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int print_insn_ns32k ( bfd_vma  memaddr,
disassemble_info info 
)

Definition at line 734 of file ns32k-dis.c.

{
  unsigned int i;
  const char *d;
  unsigned short first_word;
  int ioffset;              /* Bits into instruction.  */
  int aoffset;              /* Bits into arguments.  */
  char arg_bufs[MAX_ARGS+1][ARG_LEN];
  int argnum;
  int maxarg;
  struct private priv;
  bfd_byte *buffer = priv.the_buffer;
  dis_info = info;

  info->private_data = & priv;
  priv.max_fetched = priv.the_buffer;
  priv.insn_start = memaddr;
  if (setjmp (priv.bailout) != 0)
    /* Error return.  */
    return -1;

  /* Look for 8bit opcodes first. Other wise, fetching two bytes could take
     us over the end of accessible data unnecessarilly.  */
  FETCH_DATA (info, buffer + 1);
  for (i = 0; i < NOPCODES; i++)
    if (ns32k_opcodes[i].opcode_id_size <= 8
       && ((buffer[0]
            & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
           == ns32k_opcodes[i].opcode_seed))
      break;
  if (i == NOPCODES)
    {
      /* Maybe it is 9 to 16 bits big.  */
      FETCH_DATA (info, buffer + 2);
      first_word = read_memory_integer(buffer, 2);

      for (i = 0; i < NOPCODES; i++)
       if ((first_word
            & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1))
           == ns32k_opcodes[i].opcode_seed)
         break;

      /* Handle undefined instructions.  */
      if (i == NOPCODES)
       {
         (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]);
         return 1;
       }
    }

  (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name);

  ioffset = ns32k_opcodes[i].opcode_size;
  aoffset = ns32k_opcodes[i].opcode_size;
  d = ns32k_opcodes[i].operands;

  if (*d)
    {
      /* Offset in bits of the first thing beyond each index byte.
        Element 0 is for operand A and element 1 is for operand B.
        The rest are irrelevant, but we put them here so we don't
        index outside the array.  */
      int index_offset[MAX_ARGS];

      /* 0 for operand A, 1 for operand B, greater for other args.  */
      int whicharg = 0;
      
      (*dis_info->fprintf_func)(dis_info->stream, "\t");

      maxarg = 0;

      /* First we have to find and keep track of the index bytes,
        if we are using scaled indexed addressing mode, since the index
        bytes occur right after the basic instruction, not as part
        of the addressing extension.  */
      if (Is_gen(d[1]))
       {
         int addr_mode = bit_extract (buffer, ioffset - 5, 5);

         if (Adrmod_is_index (addr_mode))
           {
             aoffset += 8;
             index_offset[0] = aoffset;
           }
       }

      if (d[2] && Is_gen(d[3]))
       {
         int addr_mode = bit_extract (buffer, ioffset - 10, 5);

         if (Adrmod_is_index (addr_mode))
           {
             aoffset += 8;
             index_offset[1] = aoffset;
           }
       }

      while (*d)
       {
         argnum = *d - '1';
         d++;
         if (argnum > maxarg && argnum < MAX_ARGS)
           maxarg = argnum;
         ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
                                memaddr, arg_bufs[argnum],
                                index_offset[whicharg]);
         d++;
         whicharg++;
       }
      for (argnum = 0; argnum <= maxarg; argnum++)
       {
         bfd_vma addr;
         char *ch;

         for (ch = arg_bufs[argnum]; *ch;)
           {
             if (*ch == NEXT_IS_ADDR)
              {
                ++ch;
                addr = bfd_scan_vma (ch, NULL, 16);
                (*dis_info->print_address_func) (addr, dis_info);
                while (*ch && *ch != NEXT_IS_ADDR)
                  ++ch;
                if (*ch)
                  ++ch;
              }
             else
              (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++);
           }
         if (argnum < maxarg)
           (*dis_info->fprintf_func)(dis_info->stream, ", ");
       }
    }
  return aoffset / 8;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static long read_memory_integer ( unsigned char *  addr,
int  nr 
) [static]

Definition at line 38 of file ns32k-dis.c.

{
  long val;
  int i;

  for (val = 0, i = nr - 1; i >= 0; i--)
    {
      val =  (val << 8);
      val |= (0xff & *(addr + i));
    }
  return val;
}

Here is the caller graph for this function:

static int sign_extend ( int  value,
int  bits 
) [static]

Definition at line 324 of file ns32k-dis.c.

{
  value = value & ((1 << bits) - 1);
  return (value & (1 << (bits - 1))
         ? value | (~((1 << bits) - 1))
         : value);
}

Here is the caller graph for this function:


Variable Documentation

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

static struct ns32k_option [static]
Initial value:
 
{
  { "r0",     0x80,  0x80   },
  { "r1",     0x40,  0x40   },
  { "r2",     0x20,  0x20   },
  { "r3",     0x10,  0x10   },
  { "r4",     0x08,  0x08   },
  { "r5",     0x04,  0x04   },
  { "r6",     0x02,  0x02   },
  { "r7",     0x01,  0x01   },
  {  0 ,      0x00,  0x00   }
}

Definition at line 108 of file ns32k-dis.c.