OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [opcodes/] [tic4x-dis.c] - Diff between revs 156 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/* Print instructions for the Texas TMS320C[34]X, for GDB and GNU Binutils.
/* Print instructions for the Texas TMS320C[34]X, for GDB and GNU Binutils.
 
 
   Copyright 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
   Copyright 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
 
 
   Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
   Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
 
 
   This file is part of the GNU opcodes library.
   This file is part of the GNU opcodes library.
 
 
   This library is free software; you can redistribute it and/or modify
   This library is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   the Free Software Foundation; either version 3, or (at your option)
   any later version.
   any later version.
 
 
   It is distributed in the hope that it will be useful, but WITHOUT
   It is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   License for more details.
   License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */
   MA 02110-1301, USA.  */
 
 
#include <math.h>
#include <math.h>
#include "libiberty.h"
#include "libiberty.h"
#include "dis-asm.h"
#include "dis-asm.h"
#include "opcode/tic4x.h"
#include "opcode/tic4x.h"
 
 
#define TIC4X_DEBUG 0
#define TIC4X_DEBUG 0
 
 
#define TIC4X_HASH_SIZE   11   /* 11 (bits) and above should give unique entries.  */
#define TIC4X_HASH_SIZE   11   /* 11 (bits) and above should give unique entries.  */
#define TIC4X_SPESOP_SIZE 8    /* Max 8. ops for special instructions.  */
#define TIC4X_SPESOP_SIZE 8    /* Max 8. ops for special instructions.  */
 
 
typedef enum
typedef enum
{
{
  IMMED_SINT,
  IMMED_SINT,
  IMMED_SUINT,
  IMMED_SUINT,
  IMMED_SFLOAT,
  IMMED_SFLOAT,
  IMMED_INT,
  IMMED_INT,
  IMMED_UINT,
  IMMED_UINT,
  IMMED_FLOAT
  IMMED_FLOAT
}
}
immed_t;
immed_t;
 
 
typedef enum
typedef enum
{
{
  INDIRECT_SHORT,
  INDIRECT_SHORT,
  INDIRECT_LONG,
  INDIRECT_LONG,
  INDIRECT_TIC4X
  INDIRECT_TIC4X
}
}
indirect_t;
indirect_t;
 
 
static int tic4x_version = 0;
static int tic4x_version = 0;
static int tic4x_dp = 0;
static int tic4x_dp = 0;
 
 
static int
static int
tic4x_pc_offset (unsigned int op)
tic4x_pc_offset (unsigned int op)
{
{
  /* Determine the PC offset for a C[34]x instruction.
  /* Determine the PC offset for a C[34]x instruction.
     This could be simplified using some boolean algebra
     This could be simplified using some boolean algebra
     but at the expense of readability.  */
     but at the expense of readability.  */
  switch (op >> 24)
  switch (op >> 24)
    {
    {
    case 0x60:  /* br */
    case 0x60:  /* br */
    case 0x62:  /* call  (C4x) */
    case 0x62:  /* call  (C4x) */
    case 0x64:  /* rptb  (C4x) */
    case 0x64:  /* rptb  (C4x) */
      return 1;
      return 1;
    case 0x61:  /* brd */
    case 0x61:  /* brd */
    case 0x63:  /* laj */
    case 0x63:  /* laj */
    case 0x65:  /* rptbd (C4x) */
    case 0x65:  /* rptbd (C4x) */
      return 3;
      return 3;
    case 0x66:  /* swi */
    case 0x66:  /* swi */
    case 0x67:
    case 0x67:
      return 0;
      return 0;
    default:
    default:
      break;
      break;
    }
    }
 
 
  switch ((op & 0xffe00000) >> 20)
  switch ((op & 0xffe00000) >> 20)
    {
    {
    case 0x6a0: /* bB */
    case 0x6a0: /* bB */
    case 0x720: /* callB */
    case 0x720: /* callB */
    case 0x740: /* trapB */
    case 0x740: /* trapB */
      return 1;
      return 1;
 
 
    case 0x6a2: /* bBd */
    case 0x6a2: /* bBd */
    case 0x6a6: /* bBat */
    case 0x6a6: /* bBat */
    case 0x6aa: /* bBaf */
    case 0x6aa: /* bBaf */
    case 0x722: /* lajB */
    case 0x722: /* lajB */
    case 0x748: /* latB */
    case 0x748: /* latB */
    case 0x798: /* rptbd */
    case 0x798: /* rptbd */
      return 3;
      return 3;
 
 
    default:
    default:
      break;
      break;
    }
    }
 
 
  switch ((op & 0xfe200000) >> 20)
  switch ((op & 0xfe200000) >> 20)
    {
    {
    case 0x6e0: /* dbB */
    case 0x6e0: /* dbB */
      return 1;
      return 1;
 
 
    case 0x6e2: /* dbBd */
    case 0x6e2: /* dbBd */
      return 3;
      return 3;
 
 
    default:
    default:
      break;
      break;
    }
    }
 
 
  return 0;
  return 0;
}
}
 
 
static int
static int
tic4x_print_char (struct disassemble_info * info, char ch)
tic4x_print_char (struct disassemble_info * info, char ch)
{
{
  if (info != NULL)
  if (info != NULL)
    (*info->fprintf_func) (info->stream, "%c", ch);
    (*info->fprintf_func) (info->stream, "%c", ch);
  return 1;
  return 1;
}
}
 
 
static int
static int
tic4x_print_str (struct disassemble_info *info, char *str)
tic4x_print_str (struct disassemble_info *info, char *str)
{
{
  if (info != NULL)
  if (info != NULL)
    (*info->fprintf_func) (info->stream, "%s", str);
    (*info->fprintf_func) (info->stream, "%s", str);
  return 1;
  return 1;
}
}
 
 
static int
static int
tic4x_print_register (struct disassemble_info *info, unsigned long regno)
tic4x_print_register (struct disassemble_info *info, unsigned long regno)
{
{
  static tic4x_register_t ** registertable = NULL;
  static tic4x_register_t ** registertable = NULL;
  unsigned int i;
  unsigned int i;
 
 
  if (registertable == NULL)
  if (registertable == NULL)
    {
    {
      registertable = xmalloc (sizeof (tic4x_register_t *) * REG_TABLE_SIZE);
      registertable = xmalloc (sizeof (tic4x_register_t *) * REG_TABLE_SIZE);
      for (i = 0; i < tic3x_num_registers; i++)
      for (i = 0; i < tic3x_num_registers; i++)
        registertable[tic3x_registers[i].regno] = (tic4x_register_t *) (tic3x_registers + i);
        registertable[tic3x_registers[i].regno] = (tic4x_register_t *) (tic3x_registers + i);
      if (IS_CPU_TIC4X (tic4x_version))
      if (IS_CPU_TIC4X (tic4x_version))
        {
        {
          /* Add C4x additional registers, overwriting
          /* Add C4x additional registers, overwriting
             any C3x registers if necessary.  */
             any C3x registers if necessary.  */
          for (i = 0; i < tic4x_num_registers; i++)
          for (i = 0; i < tic4x_num_registers; i++)
            registertable[tic4x_registers[i].regno] =
            registertable[tic4x_registers[i].regno] =
              (tic4x_register_t *)(tic4x_registers + i);
              (tic4x_register_t *)(tic4x_registers + i);
        }
        }
    }
    }
  if ((int) regno > (IS_CPU_TIC4X (tic4x_version) ? TIC4X_REG_MAX : TIC3X_REG_MAX))
  if ((int) regno > (IS_CPU_TIC4X (tic4x_version) ? TIC4X_REG_MAX : TIC3X_REG_MAX))
    return 0;
    return 0;
  if (info != NULL)
  if (info != NULL)
    (*info->fprintf_func) (info->stream, "%s", registertable[regno]->name);
    (*info->fprintf_func) (info->stream, "%s", registertable[regno]->name);
  return 1;
  return 1;
}
}
 
 
static int
static int
tic4x_print_addr (struct disassemble_info *info, unsigned long addr)
tic4x_print_addr (struct disassemble_info *info, unsigned long addr)
{
{
  if (info != NULL)
  if (info != NULL)
    (*info->print_address_func)(addr, info);
    (*info->print_address_func)(addr, info);
  return 1;
  return 1;
}
}
 
 
static int
static int
tic4x_print_relative (struct disassemble_info *info,
tic4x_print_relative (struct disassemble_info *info,
                      unsigned long pc,
                      unsigned long pc,
                      long offset,
                      long offset,
                      unsigned long opcode)
                      unsigned long opcode)
{
{
  return tic4x_print_addr (info, pc + offset + tic4x_pc_offset (opcode));
  return tic4x_print_addr (info, pc + offset + tic4x_pc_offset (opcode));
}
}
 
 
static int
static int
tic4x_print_direct (struct disassemble_info *info, unsigned long arg)
tic4x_print_direct (struct disassemble_info *info, unsigned long arg)
{
{
  if (info != NULL)
  if (info != NULL)
    {
    {
      (*info->fprintf_func) (info->stream, "@");
      (*info->fprintf_func) (info->stream, "@");
      tic4x_print_addr (info, arg + (tic4x_dp << 16));
      tic4x_print_addr (info, arg + (tic4x_dp << 16));
    }
    }
  return 1;
  return 1;
}
}
#if 0
#if 0
/* FIXME: make the floating point stuff not rely on host
/* FIXME: make the floating point stuff not rely on host
   floating point arithmetic.  */
   floating point arithmetic.  */
 
 
static void
static void
tic4x_print_ftoa (unsigned int val, FILE *stream, fprintf_ftype pfunc)
tic4x_print_ftoa (unsigned int val, FILE *stream, fprintf_ftype pfunc)
{
{
  int e;
  int e;
  int s;
  int s;
  int f;
  int f;
  double num = 0.0;
  double num = 0.0;
 
 
  e = EXTRS (val, 31, 24);      /* Exponent.  */
  e = EXTRS (val, 31, 24);      /* Exponent.  */
  if (e != -128)
  if (e != -128)
    {
    {
      s = EXTRU (val, 23, 23);  /* Sign bit.  */
      s = EXTRU (val, 23, 23);  /* Sign bit.  */
      f = EXTRU (val, 22, 0);    /* Mantissa.  */
      f = EXTRU (val, 22, 0);    /* Mantissa.  */
      if (s)
      if (s)
        f += -2 * (1 << 23);
        f += -2 * (1 << 23);
      else
      else
        f += (1 << 23);
        f += (1 << 23);
      num = f / (double)(1 << 23);
      num = f / (double)(1 << 23);
      num = ldexp (num, e);
      num = ldexp (num, e);
    }
    }
  (*pfunc)(stream, "%.9g", num);
  (*pfunc)(stream, "%.9g", num);
}
}
#endif
#endif
 
 
static int
static int
tic4x_print_immed (struct disassemble_info *info,
tic4x_print_immed (struct disassemble_info *info,
                   immed_t type,
                   immed_t type,
                   unsigned long arg)
                   unsigned long arg)
{
{
  int s;
  int s;
  int f;
  int f;
  int e;
  int e;
  double num = 0.0;
  double num = 0.0;
 
 
  if (info == NULL)
  if (info == NULL)
    return 1;
    return 1;
  switch (type)
  switch (type)
    {
    {
    case IMMED_SINT:
    case IMMED_SINT:
    case IMMED_INT:
    case IMMED_INT:
      (*info->fprintf_func) (info->stream, "%ld", (long) arg);
      (*info->fprintf_func) (info->stream, "%ld", (long) arg);
      break;
      break;
 
 
    case IMMED_SUINT:
    case IMMED_SUINT:
    case IMMED_UINT:
    case IMMED_UINT:
      (*info->fprintf_func) (info->stream, "%lu", arg);
      (*info->fprintf_func) (info->stream, "%lu", arg);
      break;
      break;
 
 
    case IMMED_SFLOAT:
    case IMMED_SFLOAT:
      e = EXTRS (arg, 15, 12);
      e = EXTRS (arg, 15, 12);
      if (e != -8)
      if (e != -8)
        {
        {
          s = EXTRU (arg, 11, 11);
          s = EXTRU (arg, 11, 11);
          f = EXTRU (arg, 10, 0);
          f = EXTRU (arg, 10, 0);
          if (s)
          if (s)
            f += -2 * (1 << 11);
            f += -2 * (1 << 11);
          else
          else
            f += (1 << 11);
            f += (1 << 11);
          num = f / (double)(1 << 11);
          num = f / (double)(1 << 11);
          num = ldexp (num, e);
          num = ldexp (num, e);
        }
        }
      (*info->fprintf_func) (info->stream, "%f", num);
      (*info->fprintf_func) (info->stream, "%f", num);
      break;
      break;
    case IMMED_FLOAT:
    case IMMED_FLOAT:
      e = EXTRS (arg, 31, 24);
      e = EXTRS (arg, 31, 24);
      if (e != -128)
      if (e != -128)
        {
        {
          s = EXTRU (arg, 23, 23);
          s = EXTRU (arg, 23, 23);
          f = EXTRU (arg, 22, 0);
          f = EXTRU (arg, 22, 0);
          if (s)
          if (s)
            f += -2 * (1 << 23);
            f += -2 * (1 << 23);
          else
          else
            f += (1 << 23);
            f += (1 << 23);
          num = f / (double)(1 << 23);
          num = f / (double)(1 << 23);
          num = ldexp (num, e);
          num = ldexp (num, e);
        }
        }
      (*info->fprintf_func) (info->stream, "%f", num);
      (*info->fprintf_func) (info->stream, "%f", num);
      break;
      break;
    }
    }
  return 1;
  return 1;
}
}
 
 
static int
static int
tic4x_print_cond (struct disassemble_info *info, unsigned int cond)
tic4x_print_cond (struct disassemble_info *info, unsigned int cond)
{
{
  static tic4x_cond_t **condtable = NULL;
  static tic4x_cond_t **condtable = NULL;
  unsigned int i;
  unsigned int i;
 
 
  if (condtable == NULL)
  if (condtable == NULL)
    {
    {
      condtable = xmalloc (sizeof (tic4x_cond_t *) * 32);
      condtable = xmalloc (sizeof (tic4x_cond_t *) * 32);
      for (i = 0; i < tic4x_num_conds; i++)
      for (i = 0; i < tic4x_num_conds; i++)
        condtable[tic4x_conds[i].cond] = (tic4x_cond_t *)(tic4x_conds + i);
        condtable[tic4x_conds[i].cond] = (tic4x_cond_t *)(tic4x_conds + i);
    }
    }
  if (cond > 31 || condtable[cond] == NULL)
  if (cond > 31 || condtable[cond] == NULL)
    return 0;
    return 0;
  if (info != NULL)
  if (info != NULL)
    (*info->fprintf_func) (info->stream, "%s", condtable[cond]->name);
    (*info->fprintf_func) (info->stream, "%s", condtable[cond]->name);
  return 1;
  return 1;
}
}
 
 
static int
static int
tic4x_print_indirect (struct disassemble_info *info,
tic4x_print_indirect (struct disassemble_info *info,
                      indirect_t type,
                      indirect_t type,
                      unsigned long arg)
                      unsigned long arg)
{
{
  unsigned int aregno;
  unsigned int aregno;
  unsigned int modn;
  unsigned int modn;
  unsigned int disp;
  unsigned int disp;
  char *a;
  char *a;
 
 
  aregno = 0;
  aregno = 0;
  modn = 0;
  modn = 0;
  disp = 1;
  disp = 1;
  switch(type)
  switch(type)
    {
    {
    case INDIRECT_TIC4X:                /* *+ARn(disp) */
    case INDIRECT_TIC4X:                /* *+ARn(disp) */
      disp = EXTRU (arg, 7, 3);
      disp = EXTRU (arg, 7, 3);
      aregno = EXTRU (arg, 2, 0) + REG_AR0;
      aregno = EXTRU (arg, 2, 0) + REG_AR0;
      modn = 0;
      modn = 0;
      break;
      break;
    case INDIRECT_SHORT:
    case INDIRECT_SHORT:
      disp = 1;
      disp = 1;
      aregno = EXTRU (arg, 2, 0) + REG_AR0;
      aregno = EXTRU (arg, 2, 0) + REG_AR0;
      modn = EXTRU (arg, 7, 3);
      modn = EXTRU (arg, 7, 3);
      break;
      break;
    case INDIRECT_LONG:
    case INDIRECT_LONG:
      disp = EXTRU (arg, 7, 0);
      disp = EXTRU (arg, 7, 0);
      aregno = EXTRU (arg, 10, 8) + REG_AR0;
      aregno = EXTRU (arg, 10, 8) + REG_AR0;
      modn = EXTRU (arg, 15, 11);
      modn = EXTRU (arg, 15, 11);
      if (modn > 7 && disp != 0)
      if (modn > 7 && disp != 0)
        return 0;
        return 0;
      break;
      break;
    default:
    default:
        (*info->fprintf_func)(info->stream, "# internal error: Unknown indirect type %d", type);
        (*info->fprintf_func)(info->stream, "# internal error: Unknown indirect type %d", type);
        return 0;
        return 0;
    }
    }
  if (modn > TIC3X_MODN_MAX)
  if (modn > TIC3X_MODN_MAX)
    return 0;
    return 0;
  a = tic4x_indirects[modn].name;
  a = tic4x_indirects[modn].name;
  while (*a)
  while (*a)
    {
    {
      switch (*a)
      switch (*a)
        {
        {
        case 'a':
        case 'a':
          tic4x_print_register (info, aregno);
          tic4x_print_register (info, aregno);
          break;
          break;
        case 'd':
        case 'd':
          tic4x_print_immed (info, IMMED_UINT, disp);
          tic4x_print_immed (info, IMMED_UINT, disp);
          break;
          break;
        case 'y':
        case 'y':
          tic4x_print_str (info, "ir0");
          tic4x_print_str (info, "ir0");
          break;
          break;
        case 'z':
        case 'z':
          tic4x_print_str (info, "ir1");
          tic4x_print_str (info, "ir1");
          break;
          break;
        default:
        default:
          tic4x_print_char (info, *a);
          tic4x_print_char (info, *a);
          break;
          break;
        }
        }
      a++;
      a++;
    }
    }
  return 1;
  return 1;
}
}
 
 
static int
static int
tic4x_print_op (struct disassemble_info *info,
tic4x_print_op (struct disassemble_info *info,
                unsigned long instruction,
                unsigned long instruction,
                tic4x_inst_t *p,
                tic4x_inst_t *p,
                unsigned long pc)
                unsigned long pc)
{
{
  int val;
  int val;
  char *s;
  char *s;
  char *parallel = NULL;
  char *parallel = NULL;
 
 
  /* Print instruction name.  */
  /* Print instruction name.  */
  s = p->name;
  s = p->name;
  while (*s && parallel == NULL)
  while (*s && parallel == NULL)
    {
    {
      switch (*s)
      switch (*s)
        {
        {
        case 'B':
        case 'B':
          if (! tic4x_print_cond (info, EXTRU (instruction, 20, 16)))
          if (! tic4x_print_cond (info, EXTRU (instruction, 20, 16)))
            return 0;
            return 0;
          break;
          break;
        case 'C':
        case 'C':
          if (! tic4x_print_cond (info, EXTRU (instruction, 27, 23)))
          if (! tic4x_print_cond (info, EXTRU (instruction, 27, 23)))
            return 0;
            return 0;
          break;
          break;
        case '_':
        case '_':
          parallel = s + 1;     /* Skip past `_' in name.  */
          parallel = s + 1;     /* Skip past `_' in name.  */
          break;
          break;
        default:
        default:
          tic4x_print_char (info, *s);
          tic4x_print_char (info, *s);
          break;
          break;
        }
        }
      s++;
      s++;
    }
    }
 
 
  /* Print arguments.  */
  /* Print arguments.  */
  s = p->args;
  s = p->args;
  if (*s)
  if (*s)
    tic4x_print_char (info, ' ');
    tic4x_print_char (info, ' ');
 
 
  while (*s)
  while (*s)
    {
    {
      switch (*s)
      switch (*s)
        {
        {
        case '*': /* Indirect 0--15.  */
        case '*': /* Indirect 0--15.  */
          if (! tic4x_print_indirect (info, INDIRECT_LONG,
          if (! tic4x_print_indirect (info, INDIRECT_LONG,
                                      EXTRU (instruction, 15, 0)))
                                      EXTRU (instruction, 15, 0)))
            return 0;
            return 0;
          break;
          break;
 
 
        case '#': /* Only used for ldp, ldpk.  */
        case '#': /* Only used for ldp, ldpk.  */
          tic4x_print_immed (info, IMMED_UINT, EXTRU (instruction, 15, 0));
          tic4x_print_immed (info, IMMED_UINT, EXTRU (instruction, 15, 0));
          break;
          break;
 
 
        case '@': /* Direct 0--15.  */
        case '@': /* Direct 0--15.  */
          tic4x_print_direct (info, EXTRU (instruction, 15, 0));
          tic4x_print_direct (info, EXTRU (instruction, 15, 0));
          break;
          break;
 
 
        case 'A': /* Address register 24--22.  */
        case 'A': /* Address register 24--22.  */
          if (! tic4x_print_register (info, EXTRU (instruction, 24, 22) +
          if (! tic4x_print_register (info, EXTRU (instruction, 24, 22) +
                                      REG_AR0))
                                      REG_AR0))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'B': /* 24-bit unsigned int immediate br(d)/call/rptb
        case 'B': /* 24-bit unsigned int immediate br(d)/call/rptb
                     address 0--23.  */
                     address 0--23.  */
          if (IS_CPU_TIC4X (tic4x_version))
          if (IS_CPU_TIC4X (tic4x_version))
            tic4x_print_relative (info, pc, EXTRS (instruction, 23, 0),
            tic4x_print_relative (info, pc, EXTRS (instruction, 23, 0),
                                  p->opcode);
                                  p->opcode);
          else
          else
            tic4x_print_addr (info, EXTRU (instruction, 23, 0));
            tic4x_print_addr (info, EXTRU (instruction, 23, 0));
          break;
          break;
 
 
        case 'C': /* Indirect (short C4x) 0--7.  */
        case 'C': /* Indirect (short C4x) 0--7.  */
          if (! IS_CPU_TIC4X (tic4x_version))
          if (! IS_CPU_TIC4X (tic4x_version))
            return 0;
            return 0;
          if (! tic4x_print_indirect (info, INDIRECT_TIC4X,
          if (! tic4x_print_indirect (info, INDIRECT_TIC4X,
                                      EXTRU (instruction, 7, 0)))
                                      EXTRU (instruction, 7, 0)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'D':
        case 'D':
          /* Cockup if get here...  */
          /* Cockup if get here...  */
          break;
          break;
 
 
        case 'E': /* Register 0--7.  */
        case 'E': /* Register 0--7.  */
        case 'e':
        case 'e':
          if (! tic4x_print_register (info, EXTRU (instruction, 7, 0)))
          if (! tic4x_print_register (info, EXTRU (instruction, 7, 0)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'F': /* 16-bit float immediate 0--15.  */
        case 'F': /* 16-bit float immediate 0--15.  */
          tic4x_print_immed (info, IMMED_SFLOAT,
          tic4x_print_immed (info, IMMED_SFLOAT,
                             EXTRU (instruction, 15, 0));
                             EXTRU (instruction, 15, 0));
          break;
          break;
 
 
        case 'i': /* Extended indirect 0--7.  */
        case 'i': /* Extended indirect 0--7.  */
          if (EXTRU (instruction, 7, 5) == 7)
          if (EXTRU (instruction, 7, 5) == 7)
            {
            {
              if (!tic4x_print_register (info, EXTRU (instruction, 4, 0)))
              if (!tic4x_print_register (info, EXTRU (instruction, 4, 0)))
                return 0;
                return 0;
              break;
              break;
            }
            }
          /* Fallthrough */
          /* Fallthrough */
 
 
        case 'I': /* Indirect (short) 0--7.  */
        case 'I': /* Indirect (short) 0--7.  */
          if (! tic4x_print_indirect (info, INDIRECT_SHORT,
          if (! tic4x_print_indirect (info, INDIRECT_SHORT,
                                      EXTRU (instruction, 7, 0)))
                                      EXTRU (instruction, 7, 0)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'j': /* Extended indirect 8--15 */
        case 'j': /* Extended indirect 8--15 */
          if (EXTRU (instruction, 15, 13) == 7)
          if (EXTRU (instruction, 15, 13) == 7)
            {
            {
              if (! tic4x_print_register (info, EXTRU (instruction, 12, 8)))
              if (! tic4x_print_register (info, EXTRU (instruction, 12, 8)))
                return 0;
                return 0;
              break;
              break;
            }
            }
 
 
        case 'J': /* Indirect (short) 8--15.  */
        case 'J': /* Indirect (short) 8--15.  */
          if (! tic4x_print_indirect (info, INDIRECT_SHORT,
          if (! tic4x_print_indirect (info, INDIRECT_SHORT,
                                      EXTRU (instruction, 15, 8)))
                                      EXTRU (instruction, 15, 8)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'G': /* Register 8--15.  */
        case 'G': /* Register 8--15.  */
        case 'g':
        case 'g':
          if (! tic4x_print_register (info, EXTRU (instruction, 15, 8)))
          if (! tic4x_print_register (info, EXTRU (instruction, 15, 8)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'H': /* Register 16--18.  */
        case 'H': /* Register 16--18.  */
          if (! tic4x_print_register (info, EXTRU (instruction, 18, 16)))
          if (! tic4x_print_register (info, EXTRU (instruction, 18, 16)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'K': /* Register 19--21.  */
        case 'K': /* Register 19--21.  */
          if (! tic4x_print_register (info, EXTRU (instruction, 21, 19)))
          if (! tic4x_print_register (info, EXTRU (instruction, 21, 19)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'L': /* Register 22--24.  */
        case 'L': /* Register 22--24.  */
          if (! tic4x_print_register (info, EXTRU (instruction, 24, 22)))
          if (! tic4x_print_register (info, EXTRU (instruction, 24, 22)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'M': /* Register 22--22.  */
        case 'M': /* Register 22--22.  */
          tic4x_print_register (info, EXTRU (instruction, 22, 22) + REG_R2);
          tic4x_print_register (info, EXTRU (instruction, 22, 22) + REG_R2);
          break;
          break;
 
 
        case 'N': /* Register 23--23.  */
        case 'N': /* Register 23--23.  */
          tic4x_print_register (info, EXTRU (instruction, 23, 23) + REG_R0);
          tic4x_print_register (info, EXTRU (instruction, 23, 23) + REG_R0);
          break;
          break;
 
 
        case 'O': /* Indirect (short C4x) 8--15.  */
        case 'O': /* Indirect (short C4x) 8--15.  */
          if (! IS_CPU_TIC4X (tic4x_version))
          if (! IS_CPU_TIC4X (tic4x_version))
            return 0;
            return 0;
          if (! tic4x_print_indirect (info, INDIRECT_TIC4X,
          if (! tic4x_print_indirect (info, INDIRECT_TIC4X,
                                      EXTRU (instruction, 15, 8)))
                                      EXTRU (instruction, 15, 8)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'P': /* Displacement 0--15 (used by Bcond and BcondD).  */
        case 'P': /* Displacement 0--15 (used by Bcond and BcondD).  */
          tic4x_print_relative (info, pc, EXTRS (instruction, 15, 0),
          tic4x_print_relative (info, pc, EXTRS (instruction, 15, 0),
                                p->opcode);
                                p->opcode);
          break;
          break;
 
 
        case 'Q': /* Register 0--15.  */
        case 'Q': /* Register 0--15.  */
        case 'q':
        case 'q':
          if (! tic4x_print_register (info, EXTRU (instruction, 15, 0)))
          if (! tic4x_print_register (info, EXTRU (instruction, 15, 0)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'R': /* Register 16--20.  */
        case 'R': /* Register 16--20.  */
        case 'r':
        case 'r':
          if (! tic4x_print_register (info, EXTRU (instruction, 20, 16)))
          if (! tic4x_print_register (info, EXTRU (instruction, 20, 16)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'S': /* 16-bit signed immediate 0--15.  */
        case 'S': /* 16-bit signed immediate 0--15.  */
          tic4x_print_immed (info, IMMED_SINT,
          tic4x_print_immed (info, IMMED_SINT,
                             EXTRS (instruction, 15, 0));
                             EXTRS (instruction, 15, 0));
          break;
          break;
 
 
        case 'T': /* 5-bit signed immediate 16--20  (C4x stik).  */
        case 'T': /* 5-bit signed immediate 16--20  (C4x stik).  */
          if (! IS_CPU_TIC4X (tic4x_version))
          if (! IS_CPU_TIC4X (tic4x_version))
            return 0;
            return 0;
          if (! tic4x_print_immed (info, IMMED_SUINT,
          if (! tic4x_print_immed (info, IMMED_SUINT,
                                   EXTRU (instruction, 20, 16)))
                                   EXTRU (instruction, 20, 16)))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'U': /* 16-bit unsigned int immediate 0--15.  */
        case 'U': /* 16-bit unsigned int immediate 0--15.  */
          tic4x_print_immed (info, IMMED_SUINT, EXTRU (instruction, 15, 0));
          tic4x_print_immed (info, IMMED_SUINT, EXTRU (instruction, 15, 0));
          break;
          break;
 
 
        case 'V': /* 5/9-bit unsigned vector 0--4/8.  */
        case 'V': /* 5/9-bit unsigned vector 0--4/8.  */
          tic4x_print_immed (info, IMMED_SUINT,
          tic4x_print_immed (info, IMMED_SUINT,
                             IS_CPU_TIC4X (tic4x_version) ?
                             IS_CPU_TIC4X (tic4x_version) ?
                             EXTRU (instruction, 8, 0) :
                             EXTRU (instruction, 8, 0) :
                             EXTRU (instruction, 4, 0) & ~0x20);
                             EXTRU (instruction, 4, 0) & ~0x20);
          break;
          break;
 
 
        case 'W': /* 8-bit signed immediate 0--7.  */
        case 'W': /* 8-bit signed immediate 0--7.  */
          if (! IS_CPU_TIC4X (tic4x_version))
          if (! IS_CPU_TIC4X (tic4x_version))
            return 0;
            return 0;
          tic4x_print_immed (info, IMMED_SINT, EXTRS (instruction, 7, 0));
          tic4x_print_immed (info, IMMED_SINT, EXTRS (instruction, 7, 0));
          break;
          break;
 
 
        case 'X': /* Expansion register 4--0.  */
        case 'X': /* Expansion register 4--0.  */
          val = EXTRU (instruction, 4, 0) + REG_IVTP;
          val = EXTRU (instruction, 4, 0) + REG_IVTP;
          if (val < REG_IVTP || val > REG_TVTP)
          if (val < REG_IVTP || val > REG_TVTP)
            return 0;
            return 0;
          if (! tic4x_print_register (info, val))
          if (! tic4x_print_register (info, val))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'Y': /* Address register 16--20.  */
        case 'Y': /* Address register 16--20.  */
          val = EXTRU (instruction, 20, 16);
          val = EXTRU (instruction, 20, 16);
          if (val < REG_AR0 || val > REG_SP)
          if (val < REG_AR0 || val > REG_SP)
            return 0;
            return 0;
          if (! tic4x_print_register (info, val))
          if (! tic4x_print_register (info, val))
            return 0;
            return 0;
          break;
          break;
 
 
        case 'Z': /* Expansion register 16--20.  */
        case 'Z': /* Expansion register 16--20.  */
          val = EXTRU (instruction, 20, 16) + REG_IVTP;
          val = EXTRU (instruction, 20, 16) + REG_IVTP;
          if (val < REG_IVTP || val > REG_TVTP)
          if (val < REG_IVTP || val > REG_TVTP)
            return 0;
            return 0;
          if (! tic4x_print_register (info, val))
          if (! tic4x_print_register (info, val))
            return 0;
            return 0;
          break;
          break;
 
 
        case '|':       /* Parallel instruction.  */
        case '|':       /* Parallel instruction.  */
          tic4x_print_str (info, " || ");
          tic4x_print_str (info, " || ");
          tic4x_print_str (info, parallel);
          tic4x_print_str (info, parallel);
          tic4x_print_char (info, ' ');
          tic4x_print_char (info, ' ');
          break;
          break;
 
 
        case ';':
        case ';':
          tic4x_print_char (info, ',');
          tic4x_print_char (info, ',');
          break;
          break;
 
 
        default:
        default:
          tic4x_print_char (info, *s);
          tic4x_print_char (info, *s);
          break;
          break;
        }
        }
      s++;
      s++;
    }
    }
  return 1;
  return 1;
}
}
 
 
static void
static void
tic4x_hash_opcode_special (tic4x_inst_t **optable_special,
tic4x_hash_opcode_special (tic4x_inst_t **optable_special,
                           const tic4x_inst_t *inst)
                           const tic4x_inst_t *inst)
{
{
  int i;
  int i;
 
 
  for (i = 0;i < TIC4X_SPESOP_SIZE; i++)
  for (i = 0;i < TIC4X_SPESOP_SIZE; i++)
    if (optable_special[i] != NULL
    if (optable_special[i] != NULL
        && optable_special[i]->opcode == inst->opcode)
        && optable_special[i]->opcode == inst->opcode)
      {
      {
        /* Collision (we have it already) - overwrite.  */
        /* Collision (we have it already) - overwrite.  */
        optable_special[i] = (tic4x_inst_t *) inst;
        optable_special[i] = (tic4x_inst_t *) inst;
        return;
        return;
      }
      }
 
 
  for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
  for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
    if (optable_special[i] == NULL)
    if (optable_special[i] == NULL)
      {
      {
        /* Add the new opcode.  */
        /* Add the new opcode.  */
        optable_special[i] = (tic4x_inst_t *) inst;
        optable_special[i] = (tic4x_inst_t *) inst;
        return;
        return;
      }
      }
 
 
  /* This should never occur. This happens if the number of special
  /* This should never occur. This happens if the number of special
     instructions exceeds TIC4X_SPESOP_SIZE. Please increase the variable
     instructions exceeds TIC4X_SPESOP_SIZE. Please increase the variable
     of this variable */
     of this variable */
#if TIC4X_DEBUG
#if TIC4X_DEBUG
  printf ("optable_special[] is full, please increase TIC4X_SPESOP_SIZE!\n");
  printf ("optable_special[] is full, please increase TIC4X_SPESOP_SIZE!\n");
#endif
#endif
}
}
 
 
static void
static void
tic4x_hash_opcode (tic4x_inst_t **optable,
tic4x_hash_opcode (tic4x_inst_t **optable,
                   tic4x_inst_t **optable_special,
                   tic4x_inst_t **optable_special,
                   const tic4x_inst_t *inst,
                   const tic4x_inst_t *inst,
                   const unsigned long tic4x_oplevel)
                   const unsigned long tic4x_oplevel)
{
{
  int j;
  int j;
  int opcode = inst->opcode >> (32 - TIC4X_HASH_SIZE);
  int opcode = inst->opcode >> (32 - TIC4X_HASH_SIZE);
  int opmask = inst->opmask >> (32 - TIC4X_HASH_SIZE);
  int opmask = inst->opmask >> (32 - TIC4X_HASH_SIZE);
 
 
  /* Use a TIC4X_HASH_SIZE bit index as a hash index.  We should
  /* Use a TIC4X_HASH_SIZE bit index as a hash index.  We should
     have unique entries so there's no point having a linked list
     have unique entries so there's no point having a linked list
     for each entry?  */
     for each entry?  */
  for (j = opcode; j < opmask; j++)
  for (j = opcode; j < opmask; j++)
    if ((j & opmask) == opcode
    if ((j & opmask) == opcode
         && inst->oplevel & tic4x_oplevel)
         && inst->oplevel & tic4x_oplevel)
      {
      {
#if TIC4X_DEBUG
#if TIC4X_DEBUG
        /* We should only have collisions for synonyms like
        /* We should only have collisions for synonyms like
           ldp for ldi.  */
           ldp for ldi.  */
        if (optable[j] != NULL)
        if (optable[j] != NULL)
          printf ("Collision at index %d, %s and %s\n",
          printf ("Collision at index %d, %s and %s\n",
                  j, optable[j]->name, inst->name);
                  j, optable[j]->name, inst->name);
#endif
#endif
        /* Catch those ops that collide with others already inside the
        /* Catch those ops that collide with others already inside the
           hash, and have a opmask greater than the one we use in the
           hash, and have a opmask greater than the one we use in the
           hash. Store them in a special-list, that will handle full
           hash. Store them in a special-list, that will handle full
           32-bit INSN, not only the first 11-bit (or so). */
           32-bit INSN, not only the first 11-bit (or so). */
        if (optable[j] != NULL
        if (optable[j] != NULL
            && inst->opmask & ~(opmask << (32 - TIC4X_HASH_SIZE)))
            && inst->opmask & ~(opmask << (32 - TIC4X_HASH_SIZE)))
          {
          {
            /* Add the instruction already on the list.  */
            /* Add the instruction already on the list.  */
            tic4x_hash_opcode_special (optable_special, optable[j]);
            tic4x_hash_opcode_special (optable_special, optable[j]);
 
 
            /* Add the new instruction.  */
            /* Add the new instruction.  */
            tic4x_hash_opcode_special (optable_special, inst);
            tic4x_hash_opcode_special (optable_special, inst);
          }
          }
 
 
        optable[j] = (tic4x_inst_t *) inst;
        optable[j] = (tic4x_inst_t *) inst;
      }
      }
}
}
 
 
/* Disassemble the instruction in 'instruction'.
/* Disassemble the instruction in 'instruction'.
   'pc' should be the address of this instruction, it will
   'pc' should be the address of this instruction, it will
   be used to print the target address if this is a relative jump or call
   be used to print the target address if this is a relative jump or call
   the disassembled instruction is written to 'info'.
   the disassembled instruction is written to 'info'.
   The function returns the length of this instruction in words.  */
   The function returns the length of this instruction in words.  */
 
 
static int
static int
tic4x_disassemble (unsigned long pc,
tic4x_disassemble (unsigned long pc,
                   unsigned long instruction,
                   unsigned long instruction,
                   struct disassemble_info *info)
                   struct disassemble_info *info)
{
{
  static tic4x_inst_t **optable = NULL;
  static tic4x_inst_t **optable = NULL;
  static tic4x_inst_t **optable_special = NULL;
  static tic4x_inst_t **optable_special = NULL;
  tic4x_inst_t *p;
  tic4x_inst_t *p;
  int i;
  int i;
  unsigned long tic4x_oplevel;
  unsigned long tic4x_oplevel;
 
 
  tic4x_version = info->mach;
  tic4x_version = info->mach;
 
 
  tic4x_oplevel  = (IS_CPU_TIC4X (tic4x_version)) ? OP_C4X : 0;
  tic4x_oplevel  = (IS_CPU_TIC4X (tic4x_version)) ? OP_C4X : 0;
  tic4x_oplevel |= OP_C3X | OP_LPWR | OP_IDLE2 | OP_ENH;
  tic4x_oplevel |= OP_C3X | OP_LPWR | OP_IDLE2 | OP_ENH;
 
 
  if (optable == NULL)
  if (optable == NULL)
    {
    {
      optable = xcalloc (sizeof (tic4x_inst_t *), (1 << TIC4X_HASH_SIZE));
      optable = xcalloc (sizeof (tic4x_inst_t *), (1 << TIC4X_HASH_SIZE));
 
 
      optable_special = xcalloc (sizeof (tic4x_inst_t *), TIC4X_SPESOP_SIZE);
      optable_special = xcalloc (sizeof (tic4x_inst_t *), TIC4X_SPESOP_SIZE);
 
 
      /* Install opcodes in reverse order so that preferred
      /* Install opcodes in reverse order so that preferred
         forms overwrite synonyms.  */
         forms overwrite synonyms.  */
      for (i = tic4x_num_insts - 1; i >= 0; i--)
      for (i = tic4x_num_insts - 1; i >= 0; i--)
        tic4x_hash_opcode (optable, optable_special, &tic4x_insts[i],
        tic4x_hash_opcode (optable, optable_special, &tic4x_insts[i],
                           tic4x_oplevel);
                           tic4x_oplevel);
 
 
      /* We now need to remove the insn that are special from the
      /* We now need to remove the insn that are special from the
         "normal" optable, to make the disasm search this extra list
         "normal" optable, to make the disasm search this extra list
         for them.  */
         for them.  */
      for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
      for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
        if (optable_special[i] != NULL)
        if (optable_special[i] != NULL)
          optable[optable_special[i]->opcode >> (32 - TIC4X_HASH_SIZE)] = NULL;
          optable[optable_special[i]->opcode >> (32 - TIC4X_HASH_SIZE)] = NULL;
    }
    }
 
 
  /* See if we can pick up any loading of the DP register...  */
  /* See if we can pick up any loading of the DP register...  */
  if ((instruction >> 16) == 0x5070 || (instruction >> 16) == 0x1f70)
  if ((instruction >> 16) == 0x5070 || (instruction >> 16) == 0x1f70)
    tic4x_dp = EXTRU (instruction, 15, 0);
    tic4x_dp = EXTRU (instruction, 15, 0);
 
 
  p = optable[instruction >> (32 - TIC4X_HASH_SIZE)];
  p = optable[instruction >> (32 - TIC4X_HASH_SIZE)];
  if (p != NULL)
  if (p != NULL)
    {
    {
      if (((instruction & p->opmask) == p->opcode)
      if (((instruction & p->opmask) == p->opcode)
           && tic4x_print_op (NULL, instruction, p, pc))
           && tic4x_print_op (NULL, instruction, p, pc))
        tic4x_print_op (info, instruction, p, pc);
        tic4x_print_op (info, instruction, p, pc);
      else
      else
        (*info->fprintf_func) (info->stream, "%08lx", instruction);
        (*info->fprintf_func) (info->stream, "%08lx", instruction);
    }
    }
  else
  else
    {
    {
      for (i = 0; i<TIC4X_SPESOP_SIZE; i++)
      for (i = 0; i<TIC4X_SPESOP_SIZE; i++)
        if (optable_special[i] != NULL
        if (optable_special[i] != NULL
            && optable_special[i]->opcode == instruction)
            && optable_special[i]->opcode == instruction)
          {
          {
            (*info->fprintf_func)(info->stream, "%s", optable_special[i]->name);
            (*info->fprintf_func)(info->stream, "%s", optable_special[i]->name);
            break;
            break;
          }
          }
      if (i == TIC4X_SPESOP_SIZE)
      if (i == TIC4X_SPESOP_SIZE)
        (*info->fprintf_func) (info->stream, "%08lx", instruction);
        (*info->fprintf_func) (info->stream, "%08lx", instruction);
    }
    }
 
 
  /* Return size of insn in words.  */
  /* Return size of insn in words.  */
  return 1;
  return 1;
}
}
 
 
/* The entry point from objdump and gdb.  */
/* The entry point from objdump and gdb.  */
int
int
print_insn_tic4x (bfd_vma memaddr, struct disassemble_info *info)
print_insn_tic4x (bfd_vma memaddr, struct disassemble_info *info)
{
{
  int status;
  int status;
  unsigned long pc;
  unsigned long pc;
  unsigned long op;
  unsigned long op;
  bfd_byte buffer[4];
  bfd_byte buffer[4];
 
 
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  if (status != 0)
  if (status != 0)
    {
    {
      (*info->memory_error_func) (status, memaddr, info);
      (*info->memory_error_func) (status, memaddr, info);
      return -1;
      return -1;
    }
    }
 
 
  pc = memaddr;
  pc = memaddr;
  op = bfd_getl32 (buffer);
  op = bfd_getl32 (buffer);
  info->bytes_per_line = 4;
  info->bytes_per_line = 4;
  info->bytes_per_chunk = 4;
  info->bytes_per_chunk = 4;
  info->octets_per_byte = 4;
  info->octets_per_byte = 4;
  info->display_endian = BFD_ENDIAN_LITTLE;
  info->display_endian = BFD_ENDIAN_LITTLE;
  return tic4x_disassemble (pc, op, info) * 4;
  return tic4x_disassemble (pc, op, info) * 4;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.