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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [opcodes/] [arc-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
/* Instruction printing code for the ARC.
/* Instruction printing code for the ARC.
   Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005, 2007
   Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005, 2007
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Contributed by Doug Evans (dje@cygnus.com).
   Contributed by Doug Evans (dje@cygnus.com).
 
 
   This file is part of libopcodes.
   This file is part of libopcodes.
 
 
   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 "ansidecl.h"
#include "ansidecl.h"
#include "libiberty.h"
#include "libiberty.h"
#include "dis-asm.h"
#include "dis-asm.h"
#include "opcode/arc.h"
#include "opcode/arc.h"
#include "elf-bfd.h"
#include "elf-bfd.h"
#include "elf/arc.h"
#include "elf/arc.h"
#include <string.h>
#include <string.h>
#include "opintl.h"
#include "opintl.h"
 
 
#include <stdarg.h>
#include <stdarg.h>
#include "arc-dis.h"
#include "arc-dis.h"
#include "arc-ext.h"
#include "arc-ext.h"
 
 
#ifndef dbg
#ifndef dbg
#define dbg (0)
#define dbg (0)
#endif
#endif
 
 
/* Classification of the opcodes for the decoder to print
/* Classification of the opcodes for the decoder to print
   the instructions.  */
   the instructions.  */
 
 
typedef enum
typedef enum
{
{
  CLASS_A4_ARITH,
  CLASS_A4_ARITH,
  CLASS_A4_OP3_GENERAL,
  CLASS_A4_OP3_GENERAL,
  CLASS_A4_FLAG,
  CLASS_A4_FLAG,
  /* All branches other than JC.  */
  /* All branches other than JC.  */
  CLASS_A4_BRANCH,
  CLASS_A4_BRANCH,
  CLASS_A4_JC ,
  CLASS_A4_JC ,
  /* All loads other than immediate
  /* All loads other than immediate
     indexed loads.  */
     indexed loads.  */
  CLASS_A4_LD0,
  CLASS_A4_LD0,
  CLASS_A4_LD1,
  CLASS_A4_LD1,
  CLASS_A4_ST,
  CLASS_A4_ST,
  CLASS_A4_SR,
  CLASS_A4_SR,
  /* All single operand instructions.  */
  /* All single operand instructions.  */
  CLASS_A4_OP3_SUBOPC3F,
  CLASS_A4_OP3_SUBOPC3F,
  CLASS_A4_LR
  CLASS_A4_LR
} a4_decoding_class;
} a4_decoding_class;
 
 
#define BIT(word,n)     ((word) & (1 << n))
#define BIT(word,n)     ((word) & (1 << n))
#define BITS(word,s,e)  (((word) << (31 - e)) >> (s + (31 - e)))
#define BITS(word,s,e)  (((word) << (31 - e)) >> (s + (31 - e)))
#define OPCODE(word)    (BITS ((word), 27, 31))
#define OPCODE(word)    (BITS ((word), 27, 31))
#define FIELDA(word)    (BITS ((word), 21, 26))
#define FIELDA(word)    (BITS ((word), 21, 26))
#define FIELDB(word)    (BITS ((word), 15, 20))
#define FIELDB(word)    (BITS ((word), 15, 20))
#define FIELDC(word)    (BITS ((word),  9, 14))
#define FIELDC(word)    (BITS ((word),  9, 14))
 
 
/* FIELD D is signed in all of its uses, so we make sure argument is
/* FIELD D is signed in all of its uses, so we make sure argument is
   treated as signed for bit shifting purposes:  */
   treated as signed for bit shifting purposes:  */
#define FIELDD(word)    (BITS (((signed int)word), 0, 8))
#define FIELDD(word)    (BITS (((signed int)word), 0, 8))
 
 
#define PUT_NEXT_WORD_IN(a)                                             \
#define PUT_NEXT_WORD_IN(a)                                             \
  do                                                                    \
  do                                                                    \
    {                                                                   \
    {                                                                   \
      if (is_limm == 1 && !NEXT_WORD (1))                               \
      if (is_limm == 1 && !NEXT_WORD (1))                               \
        mwerror (state, _("Illegal limm reference in last instruction!\n")); \
        mwerror (state, _("Illegal limm reference in last instruction!\n")); \
      a = state->words[1];                                              \
      a = state->words[1];                                              \
    }                                                                   \
    }                                                                   \
  while (0)
  while (0)
 
 
#define CHECK_FLAG_COND_NULLIFY()                               \
#define CHECK_FLAG_COND_NULLIFY()                               \
  do                                                            \
  do                                                            \
    {                                                           \
    {                                                           \
      if (is_shimm == 0)                                 \
      if (is_shimm == 0)                                 \
        {                                                       \
        {                                                       \
          flag = BIT (state->words[0], 8);                       \
          flag = BIT (state->words[0], 8);                       \
          state->nullifyMode = BITS (state->words[0], 5, 6);     \
          state->nullifyMode = BITS (state->words[0], 5, 6);     \
          cond = BITS (state->words[0], 0, 4);                    \
          cond = BITS (state->words[0], 0, 4);                    \
        }                                                       \
        }                                                       \
    }                                                           \
    }                                                           \
  while (0)
  while (0)
 
 
#define CHECK_COND()                            \
#define CHECK_COND()                            \
  do                                            \
  do                                            \
    {                                           \
    {                                           \
      if (is_shimm == 0)                 \
      if (is_shimm == 0)                 \
        cond = BITS (state->words[0], 0, 4);      \
        cond = BITS (state->words[0], 0, 4);      \
    }                                           \
    }                                           \
  while (0)
  while (0)
 
 
#define CHECK_FIELD(field)                      \
#define CHECK_FIELD(field)                      \
  do                                            \
  do                                            \
    {                                           \
    {                                           \
      if (field == 62)                          \
      if (field == 62)                          \
        {                                       \
        {                                       \
          is_limm++;                            \
          is_limm++;                            \
          field##isReg = 0;                     \
          field##isReg = 0;                     \
          PUT_NEXT_WORD_IN (field);             \
          PUT_NEXT_WORD_IN (field);             \
          limm_value = field;                   \
          limm_value = field;                   \
        }                                       \
        }                                       \
      else if (field > 60)                      \
      else if (field > 60)                      \
        {                                       \
        {                                       \
          field##isReg = 0;                     \
          field##isReg = 0;                     \
          is_shimm++;                           \
          is_shimm++;                           \
          flag = (field == 61);                 \
          flag = (field == 61);                 \
          field = FIELDD (state->words[0]);      \
          field = FIELDD (state->words[0]);      \
        }                                       \
        }                                       \
    }                                           \
    }                                           \
  while (0)
  while (0)
 
 
#define CHECK_FIELD_A()                         \
#define CHECK_FIELD_A()                         \
  do                                            \
  do                                            \
    {                                           \
    {                                           \
      fieldA = FIELDA (state->words[0]); \
      fieldA = FIELDA (state->words[0]); \
      if (fieldA > 60)                          \
      if (fieldA > 60)                          \
        {                                       \
        {                                       \
          fieldAisReg = 0;                       \
          fieldAisReg = 0;                       \
          fieldA = 0;                            \
          fieldA = 0;                            \
        }                                       \
        }                                       \
    }                                           \
    }                                           \
  while (0)
  while (0)
 
 
#define CHECK_FIELD_B()                         \
#define CHECK_FIELD_B()                         \
  do                                            \
  do                                            \
    {                                           \
    {                                           \
      fieldB = FIELDB (state->words[0]); \
      fieldB = FIELDB (state->words[0]); \
      CHECK_FIELD (fieldB);                     \
      CHECK_FIELD (fieldB);                     \
    }                                           \
    }                                           \
  while (0)
  while (0)
 
 
#define CHECK_FIELD_C()                         \
#define CHECK_FIELD_C()                         \
  do                                            \
  do                                            \
    {                                           \
    {                                           \
      fieldC = FIELDC (state->words[0]); \
      fieldC = FIELDC (state->words[0]); \
      CHECK_FIELD (fieldC);                     \
      CHECK_FIELD (fieldC);                     \
    }                                           \
    }                                           \
  while (0)
  while (0)
 
 
#define IS_SMALL(x)                 (((field##x) < 256) && ((field##x) > -257))
#define IS_SMALL(x)                 (((field##x) < 256) && ((field##x) > -257))
#define IS_REG(x)                    (field##x##isReg)
#define IS_REG(x)                    (field##x##isReg)
#define WRITE_FORMAT_LB_Rx_RB(x)     WRITE_FORMAT (x, "[","]","","")
#define WRITE_FORMAT_LB_Rx_RB(x)     WRITE_FORMAT (x, "[","]","","")
#define WRITE_FORMAT_x_COMMA_LB(x)   WRITE_FORMAT (x, "",",[","",",[")
#define WRITE_FORMAT_x_COMMA_LB(x)   WRITE_FORMAT (x, "",",[","",",[")
#define WRITE_FORMAT_COMMA_x_RB(x)   WRITE_FORMAT (x, ",","]",",","]")
#define WRITE_FORMAT_COMMA_x_RB(x)   WRITE_FORMAT (x, ",","]",",","]")
#define WRITE_FORMAT_x_RB(x)         WRITE_FORMAT (x, "","]","","]")
#define WRITE_FORMAT_x_RB(x)         WRITE_FORMAT (x, "","]","","]")
#define WRITE_FORMAT_COMMA_x(x)      WRITE_FORMAT (x, ",","",",","")
#define WRITE_FORMAT_COMMA_x(x)      WRITE_FORMAT (x, ",","",",","")
#define WRITE_FORMAT_x_COMMA(x)      WRITE_FORMAT (x, "",",","",",")
#define WRITE_FORMAT_x_COMMA(x)      WRITE_FORMAT (x, "",",","",",")
#define WRITE_FORMAT_x(x)            WRITE_FORMAT (x, "","","","")
#define WRITE_FORMAT_x(x)            WRITE_FORMAT (x, "","","","")
#define WRITE_FORMAT(x,cb1,ca1,cb,ca) strcat (formatString,             \
#define WRITE_FORMAT(x,cb1,ca1,cb,ca) strcat (formatString,             \
                                     (IS_REG (x) ? cb1"%r"ca1 :         \
                                     (IS_REG (x) ? cb1"%r"ca1 :         \
                                      usesAuxReg ? cb"%a"ca :           \
                                      usesAuxReg ? cb"%a"ca :           \
                                      IS_SMALL (x) ? cb"%d"ca : cb"%h"ca))
                                      IS_SMALL (x) ? cb"%d"ca : cb"%h"ca))
#define WRITE_FORMAT_RB()       strcat (formatString, "]")
#define WRITE_FORMAT_RB()       strcat (formatString, "]")
#define WRITE_COMMENT(str)      (state->comm[state->commNum++] = (str))
#define WRITE_COMMENT(str)      (state->comm[state->commNum++] = (str))
#define WRITE_NOP_COMMENT()     if (!fieldAisReg && !flag) WRITE_COMMENT ("nop");
#define WRITE_NOP_COMMENT()     if (!fieldAisReg && !flag) WRITE_COMMENT ("nop");
 
 
#define NEXT_WORD(x)    (offset += 4, state->words[x])
#define NEXT_WORD(x)    (offset += 4, state->words[x])
 
 
#define add_target(x)   (state->targets[state->tcnt++] = (x))
#define add_target(x)   (state->targets[state->tcnt++] = (x))
 
 
static char comment_prefix[] = "\t; ";
static char comment_prefix[] = "\t; ";
 
 
static const char *
static const char *
core_reg_name (struct arcDisState * state, int val)
core_reg_name (struct arcDisState * state, int val)
{
{
  if (state->coreRegName)
  if (state->coreRegName)
    return (*state->coreRegName)(state->_this, val);
    return (*state->coreRegName)(state->_this, val);
  return 0;
  return 0;
}
}
 
 
static const char *
static const char *
aux_reg_name (struct arcDisState * state, int val)
aux_reg_name (struct arcDisState * state, int val)
{
{
  if (state->auxRegName)
  if (state->auxRegName)
    return (*state->auxRegName)(state->_this, val);
    return (*state->auxRegName)(state->_this, val);
  return 0;
  return 0;
}
}
 
 
static const char *
static const char *
cond_code_name (struct arcDisState * state, int val)
cond_code_name (struct arcDisState * state, int val)
{
{
  if (state->condCodeName)
  if (state->condCodeName)
    return (*state->condCodeName)(state->_this, val);
    return (*state->condCodeName)(state->_this, val);
  return 0;
  return 0;
}
}
 
 
static const char *
static const char *
instruction_name (struct arcDisState * state,
instruction_name (struct arcDisState * state,
                  int    op1,
                  int    op1,
                  int    op2,
                  int    op2,
                  int *  flags)
                  int *  flags)
{
{
  if (state->instName)
  if (state->instName)
    return (*state->instName)(state->_this, op1, op2, flags);
    return (*state->instName)(state->_this, op1, op2, flags);
  return 0;
  return 0;
}
}
 
 
static void
static void
mwerror (struct arcDisState * state, const char * msg)
mwerror (struct arcDisState * state, const char * msg)
{
{
  if (state->err != 0)
  if (state->err != 0)
    (*state->err)(state->_this, (msg));
    (*state->err)(state->_this, (msg));
}
}
 
 
static const char *
static const char *
post_address (struct arcDisState * state, int addr)
post_address (struct arcDisState * state, int addr)
{
{
  static char id[3 * ARRAY_SIZE (state->addresses)];
  static char id[3 * ARRAY_SIZE (state->addresses)];
  int j, i = state->acnt;
  int j, i = state->acnt;
 
 
  if (i < ((int) ARRAY_SIZE (state->addresses)))
  if (i < ((int) ARRAY_SIZE (state->addresses)))
    {
    {
      state->addresses[i] = addr;
      state->addresses[i] = addr;
      ++state->acnt;
      ++state->acnt;
      j = i*3;
      j = i*3;
      id[j+0] = '@';
      id[j+0] = '@';
      id[j+1] = '0'+i;
      id[j+1] = '0'+i;
      id[j+2] = 0;
      id[j+2] = 0;
 
 
      return id + j;
      return id + j;
    }
    }
  return "";
  return "";
}
}
 
 
static void
static void
arc_sprintf (struct arcDisState *state, char *buf, const char *format, ...)
arc_sprintf (struct arcDisState *state, char *buf, const char *format, ...)
{
{
  char *bp;
  char *bp;
  const char *p;
  const char *p;
  int size, leading_zero, regMap[2];
  int size, leading_zero, regMap[2];
  long auxNum;
  long auxNum;
  va_list ap;
  va_list ap;
 
 
  va_start (ap, format);
  va_start (ap, format);
 
 
  bp = buf;
  bp = buf;
  *bp = 0;
  *bp = 0;
  p = format;
  p = format;
  auxNum = -1;
  auxNum = -1;
  regMap[0] = 0;
  regMap[0] = 0;
  regMap[1] = 0;
  regMap[1] = 0;
 
 
  while (1)
  while (1)
    switch (*p++)
    switch (*p++)
      {
      {
      case 0:
      case 0:
        goto DOCOMM; /* (return)  */
        goto DOCOMM; /* (return)  */
      default:
      default:
        *bp++ = p[-1];
        *bp++ = p[-1];
        break;
        break;
      case '%':
      case '%':
        size = 0;
        size = 0;
        leading_zero = 0;
        leading_zero = 0;
      RETRY: ;
      RETRY: ;
        switch (*p++)
        switch (*p++)
          {
          {
          case '0':
          case '0':
          case '1':
          case '1':
          case '2':
          case '2':
          case '3':
          case '3':
          case '4':
          case '4':
          case '5':
          case '5':
          case '6':
          case '6':
          case '7':
          case '7':
          case '8':
          case '8':
          case '9':
          case '9':
            {
            {
              /* size.  */
              /* size.  */
              size = p[-1] - '0';
              size = p[-1] - '0';
              if (size == 0)
              if (size == 0)
                leading_zero = 1; /* e.g. %08x  */
                leading_zero = 1; /* e.g. %08x  */
              while (*p >= '0' && *p <= '9')
              while (*p >= '0' && *p <= '9')
                {
                {
                  size = size * 10 + *p - '0';
                  size = size * 10 + *p - '0';
                  p++;
                  p++;
                }
                }
              goto RETRY;
              goto RETRY;
            }
            }
#define inc_bp() bp = bp + strlen (bp)
#define inc_bp() bp = bp + strlen (bp)
 
 
          case 'h':
          case 'h':
            {
            {
              unsigned u = va_arg (ap, int);
              unsigned u = va_arg (ap, int);
 
 
              /* Hex.  We can change the format to 0x%08x in
              /* Hex.  We can change the format to 0x%08x in
                 one place, here, if we wish.
                 one place, here, if we wish.
                 We add underscores for easy reading.  */
                 We add underscores for easy reading.  */
              if (u > 65536)
              if (u > 65536)
                sprintf (bp, "0x%x_%04x", u >> 16, u & 0xffff);
                sprintf (bp, "0x%x_%04x", u >> 16, u & 0xffff);
              else
              else
                sprintf (bp, "0x%x", u);
                sprintf (bp, "0x%x", u);
              inc_bp ();
              inc_bp ();
            }
            }
            break;
            break;
          case 'X': case 'x':
          case 'X': case 'x':
            {
            {
              int val = va_arg (ap, int);
              int val = va_arg (ap, int);
 
 
              if (size != 0)
              if (size != 0)
                if (leading_zero)
                if (leading_zero)
                  sprintf (bp, "%0*x", size, val);
                  sprintf (bp, "%0*x", size, val);
                else
                else
                  sprintf (bp, "%*x", size, val);
                  sprintf (bp, "%*x", size, val);
              else
              else
                sprintf (bp, "%x", val);
                sprintf (bp, "%x", val);
              inc_bp ();
              inc_bp ();
            }
            }
            break;
            break;
          case 'd':
          case 'd':
            {
            {
              int val = va_arg (ap, int);
              int val = va_arg (ap, int);
 
 
              if (size != 0)
              if (size != 0)
                sprintf (bp, "%*d", size, val);
                sprintf (bp, "%*d", size, val);
              else
              else
                sprintf (bp, "%d", val);
                sprintf (bp, "%d", val);
              inc_bp ();
              inc_bp ();
            }
            }
            break;
            break;
          case 'r':
          case 'r':
            {
            {
              /* Register.  */
              /* Register.  */
              int val = va_arg (ap, int);
              int val = va_arg (ap, int);
 
 
#define REG2NAME(num, name) case num: sprintf (bp, ""name); \
#define REG2NAME(num, name) case num: sprintf (bp, ""name); \
  regMap[(num < 32) ? 0 : 1] |= 1 << (num - ((num < 32) ? 0 : 32)); break;
  regMap[(num < 32) ? 0 : 1] |= 1 << (num - ((num < 32) ? 0 : 32)); break;
 
 
              switch (val)
              switch (val)
                {
                {
                  REG2NAME (26, "gp");
                  REG2NAME (26, "gp");
                  REG2NAME (27, "fp");
                  REG2NAME (27, "fp");
                  REG2NAME (28, "sp");
                  REG2NAME (28, "sp");
                  REG2NAME (29, "ilink1");
                  REG2NAME (29, "ilink1");
                  REG2NAME (30, "ilink2");
                  REG2NAME (30, "ilink2");
                  REG2NAME (31, "blink");
                  REG2NAME (31, "blink");
                  REG2NAME (60, "lp_count");
                  REG2NAME (60, "lp_count");
                default:
                default:
                  {
                  {
                    const char * ext;
                    const char * ext;
 
 
                    ext = core_reg_name (state, val);
                    ext = core_reg_name (state, val);
                    if (ext)
                    if (ext)
                      sprintf (bp, "%s", ext);
                      sprintf (bp, "%s", ext);
                    else
                    else
                      sprintf (bp,"r%d",val);
                      sprintf (bp,"r%d",val);
                  }
                  }
                  break;
                  break;
                }
                }
              inc_bp ();
              inc_bp ();
            } break;
            } break;
 
 
          case 'a':
          case 'a':
            {
            {
              /* Aux Register.  */
              /* Aux Register.  */
              int val = va_arg (ap, int);
              int val = va_arg (ap, int);
 
 
#define AUXREG2NAME(num, name) case num: sprintf (bp,name); break;
#define AUXREG2NAME(num, name) case num: sprintf (bp,name); break;
 
 
              switch (val)
              switch (val)
                {
                {
                  AUXREG2NAME (0x0, "status");
                  AUXREG2NAME (0x0, "status");
                  AUXREG2NAME (0x1, "semaphore");
                  AUXREG2NAME (0x1, "semaphore");
                  AUXREG2NAME (0x2, "lp_start");
                  AUXREG2NAME (0x2, "lp_start");
                  AUXREG2NAME (0x3, "lp_end");
                  AUXREG2NAME (0x3, "lp_end");
                  AUXREG2NAME (0x4, "identity");
                  AUXREG2NAME (0x4, "identity");
                  AUXREG2NAME (0x5, "debug");
                  AUXREG2NAME (0x5, "debug");
                default:
                default:
                  {
                  {
                    const char *ext;
                    const char *ext;
 
 
                    ext = aux_reg_name (state, val);
                    ext = aux_reg_name (state, val);
                    if (ext)
                    if (ext)
                      sprintf (bp, "%s", ext);
                      sprintf (bp, "%s", ext);
                    else
                    else
                      arc_sprintf (state, bp, "%h", val);
                      arc_sprintf (state, bp, "%h", val);
                  }
                  }
                  break;
                  break;
                }
                }
              inc_bp ();
              inc_bp ();
            }
            }
            break;
            break;
 
 
          case 's':
          case 's':
            {
            {
              sprintf (bp, "%s", va_arg (ap, char *));
              sprintf (bp, "%s", va_arg (ap, char *));
              inc_bp ();
              inc_bp ();
            }
            }
            break;
            break;
 
 
          default:
          default:
            fprintf (stderr, "?? format %c\n", p[-1]);
            fprintf (stderr, "?? format %c\n", p[-1]);
            break;
            break;
          }
          }
      }
      }
 
 
 DOCOMM: *bp = 0;
 DOCOMM: *bp = 0;
  va_end (ap);
  va_end (ap);
}
}
 
 
static void
static void
write_comments_(struct arcDisState * state,
write_comments_(struct arcDisState * state,
                int shimm,
                int shimm,
                int is_limm,
                int is_limm,
                long limm_value)
                long limm_value)
{
{
  if (state->commentBuffer != 0)
  if (state->commentBuffer != 0)
    {
    {
      int i;
      int i;
 
 
      if (is_limm)
      if (is_limm)
        {
        {
          const char *name = post_address (state, limm_value + shimm);
          const char *name = post_address (state, limm_value + shimm);
 
 
          if (*name != 0)
          if (*name != 0)
            WRITE_COMMENT (name);
            WRITE_COMMENT (name);
        }
        }
      for (i = 0; i < state->commNum; i++)
      for (i = 0; i < state->commNum; i++)
        {
        {
          if (i == 0)
          if (i == 0)
            strcpy (state->commentBuffer, comment_prefix);
            strcpy (state->commentBuffer, comment_prefix);
          else
          else
            strcat (state->commentBuffer, ", ");
            strcat (state->commentBuffer, ", ");
          strncat (state->commentBuffer, state->comm[i],
          strncat (state->commentBuffer, state->comm[i],
                   sizeof (state->commentBuffer));
                   sizeof (state->commentBuffer));
        }
        }
    }
    }
}
}
 
 
#define write_comments2(x) write_comments_ (state, x, is_limm, limm_value)
#define write_comments2(x) write_comments_ (state, x, is_limm, limm_value)
#define write_comments()   write_comments2 (0)
#define write_comments()   write_comments2 (0)
 
 
static const char *condName[] =
static const char *condName[] =
{
{
  /* 0..15.  */
  /* 0..15.  */
  ""   , "z"  , "nz" , "p"  , "n"  , "c"  , "nc" , "v"  ,
  ""   , "z"  , "nz" , "p"  , "n"  , "c"  , "nc" , "v"  ,
  "nv" , "gt" , "ge" , "lt" , "le" , "hi" , "ls" , "pnz"
  "nv" , "gt" , "ge" , "lt" , "le" , "hi" , "ls" , "pnz"
};
};
 
 
static void
static void
write_instr_name_(struct arcDisState * state,
write_instr_name_(struct arcDisState * state,
                  const char * instrName,
                  const char * instrName,
                  int cond,
                  int cond,
                  int condCodeIsPartOfName,
                  int condCodeIsPartOfName,
                  int flag,
                  int flag,
                  int signExtend,
                  int signExtend,
                  int addrWriteBack,
                  int addrWriteBack,
                  int directMem)
                  int directMem)
{
{
  strcpy (state->instrBuffer, instrName);
  strcpy (state->instrBuffer, instrName);
 
 
  if (cond > 0)
  if (cond > 0)
    {
    {
      const char *cc = 0;
      const char *cc = 0;
 
 
      if (!condCodeIsPartOfName)
      if (!condCodeIsPartOfName)
        strcat (state->instrBuffer, ".");
        strcat (state->instrBuffer, ".");
 
 
      if (cond < 16)
      if (cond < 16)
        cc = condName[cond];
        cc = condName[cond];
      else
      else
        cc = cond_code_name (state, cond);
        cc = cond_code_name (state, cond);
 
 
      if (!cc)
      if (!cc)
        cc = "???";
        cc = "???";
 
 
      strcat (state->instrBuffer, cc);
      strcat (state->instrBuffer, cc);
    }
    }
 
 
  if (flag)
  if (flag)
    strcat (state->instrBuffer, ".f");
    strcat (state->instrBuffer, ".f");
 
 
  switch (state->nullifyMode)
  switch (state->nullifyMode)
    {
    {
    case BR_exec_always:
    case BR_exec_always:
      strcat (state->instrBuffer, ".d");
      strcat (state->instrBuffer, ".d");
      break;
      break;
    case BR_exec_when_jump:
    case BR_exec_when_jump:
      strcat (state->instrBuffer, ".jd");
      strcat (state->instrBuffer, ".jd");
      break;
      break;
    }
    }
 
 
  if (signExtend)
  if (signExtend)
    strcat (state->instrBuffer, ".x");
    strcat (state->instrBuffer, ".x");
 
 
  if (addrWriteBack)
  if (addrWriteBack)
    strcat (state->instrBuffer, ".a");
    strcat (state->instrBuffer, ".a");
 
 
  if (directMem)
  if (directMem)
    strcat (state->instrBuffer, ".di");
    strcat (state->instrBuffer, ".di");
}
}
 
 
#define write_instr_name()                                              \
#define write_instr_name()                                              \
  do                                                                    \
  do                                                                    \
    {                                                                   \
    {                                                                   \
      write_instr_name_(state, instrName,cond, condCodeIsPartOfName,    \
      write_instr_name_(state, instrName,cond, condCodeIsPartOfName,    \
                        flag, signExtend, addrWriteBack, directMem);    \
                        flag, signExtend, addrWriteBack, directMem);    \
      formatString[0] = '\0';                                            \
      formatString[0] = '\0';                                            \
    }                                                                   \
    }                                                                   \
  while (0)
  while (0)
 
 
enum
enum
{
{
  op_LD0 = 0, op_LD1 = 1, op_ST  = 2, op_3   = 3,
  op_LD0 = 0, op_LD1 = 1, op_ST  = 2, op_3   = 3,
  op_BC  = 4, op_BLC = 5, op_LPC = 6, op_JC  = 7,
  op_BC  = 4, op_BLC = 5, op_LPC = 6, op_JC  = 7,
  op_ADD = 8, op_ADC = 9, op_SUB = 10, op_SBC = 11,
  op_ADD = 8, op_ADC = 9, op_SUB = 10, op_SBC = 11,
  op_AND = 12, op_OR  = 13, op_BIC = 14, op_XOR = 15
  op_AND = 12, op_OR  = 13, op_BIC = 14, op_XOR = 15
};
};
 
 
extern disassemble_info tm_print_insn_info;
extern disassemble_info tm_print_insn_info;
 
 
static int
static int
dsmOneArcInst (bfd_vma addr, struct arcDisState * state)
dsmOneArcInst (bfd_vma addr, struct arcDisState * state)
{
{
  int condCodeIsPartOfName = 0;
  int condCodeIsPartOfName = 0;
  a4_decoding_class decodingClass;
  a4_decoding_class decodingClass;
  const char * instrName;
  const char * instrName;
  int repeatsOp = 0;
  int repeatsOp = 0;
  int fieldAisReg = 1;
  int fieldAisReg = 1;
  int fieldBisReg = 1;
  int fieldBisReg = 1;
  int fieldCisReg = 1;
  int fieldCisReg = 1;
  int fieldA;
  int fieldA;
  int fieldB;
  int fieldB;
  int fieldC = 0;
  int fieldC = 0;
  int flag = 0;
  int flag = 0;
  int cond = 0;
  int cond = 0;
  int is_shimm = 0;
  int is_shimm = 0;
  int is_limm = 0;
  int is_limm = 0;
  long limm_value = 0;
  long limm_value = 0;
  int signExtend = 0;
  int signExtend = 0;
  int addrWriteBack = 0;
  int addrWriteBack = 0;
  int directMem = 0;
  int directMem = 0;
  int is_linked = 0;
  int is_linked = 0;
  int offset = 0;
  int offset = 0;
  int usesAuxReg = 0;
  int usesAuxReg = 0;
  int flags;
  int flags;
  int ignoreFirstOpd;
  int ignoreFirstOpd;
  char formatString[60];
  char formatString[60];
 
 
  state->instructionLen = 4;
  state->instructionLen = 4;
  state->nullifyMode = BR_exec_when_no_jump;
  state->nullifyMode = BR_exec_when_no_jump;
  state->opWidth = 12;
  state->opWidth = 12;
  state->isBranch = 0;
  state->isBranch = 0;
 
 
  state->_mem_load = 0;
  state->_mem_load = 0;
  state->_ea_present = 0;
  state->_ea_present = 0;
  state->_load_len = 0;
  state->_load_len = 0;
  state->ea_reg1 = no_reg;
  state->ea_reg1 = no_reg;
  state->ea_reg2 = no_reg;
  state->ea_reg2 = no_reg;
  state->_offset = 0;
  state->_offset = 0;
 
 
  if (! NEXT_WORD (0))
  if (! NEXT_WORD (0))
    return 0;
    return 0;
 
 
  state->_opcode = OPCODE (state->words[0]);
  state->_opcode = OPCODE (state->words[0]);
  instrName = 0;
  instrName = 0;
  decodingClass = CLASS_A4_ARITH; /* default!  */
  decodingClass = CLASS_A4_ARITH; /* default!  */
  repeatsOp = 0;
  repeatsOp = 0;
  condCodeIsPartOfName=0;
  condCodeIsPartOfName=0;
  state->commNum = 0;
  state->commNum = 0;
  state->tcnt = 0;
  state->tcnt = 0;
  state->acnt = 0;
  state->acnt = 0;
  state->flow = noflow;
  state->flow = noflow;
  ignoreFirstOpd = 0;
  ignoreFirstOpd = 0;
 
 
  if (state->commentBuffer)
  if (state->commentBuffer)
    state->commentBuffer[0] = '\0';
    state->commentBuffer[0] = '\0';
 
 
  switch (state->_opcode)
  switch (state->_opcode)
    {
    {
    case op_LD0:
    case op_LD0:
      switch (BITS (state->words[0],1,2))
      switch (BITS (state->words[0],1,2))
        {
        {
        case 0:
        case 0:
          instrName = "ld";
          instrName = "ld";
          state->_load_len = 4;
          state->_load_len = 4;
          break;
          break;
        case 1:
        case 1:
          instrName = "ldb";
          instrName = "ldb";
          state->_load_len = 1;
          state->_load_len = 1;
          break;
          break;
        case 2:
        case 2:
          instrName = "ldw";
          instrName = "ldw";
          state->_load_len = 2;
          state->_load_len = 2;
          break;
          break;
        default:
        default:
          instrName = "??? (0[3])";
          instrName = "??? (0[3])";
          state->flow = invalid_instr;
          state->flow = invalid_instr;
          break;
          break;
        }
        }
      decodingClass = CLASS_A4_LD0;
      decodingClass = CLASS_A4_LD0;
      break;
      break;
 
 
    case op_LD1:
    case op_LD1:
      if (BIT (state->words[0],13))
      if (BIT (state->words[0],13))
        {
        {
          instrName = "lr";
          instrName = "lr";
          decodingClass = CLASS_A4_LR;
          decodingClass = CLASS_A4_LR;
        }
        }
      else
      else
        {
        {
          switch (BITS (state->words[0], 10, 11))
          switch (BITS (state->words[0], 10, 11))
            {
            {
            case 0:
            case 0:
              instrName = "ld";
              instrName = "ld";
              state->_load_len = 4;
              state->_load_len = 4;
              break;
              break;
            case 1:
            case 1:
              instrName = "ldb";
              instrName = "ldb";
              state->_load_len = 1;
              state->_load_len = 1;
              break;
              break;
            case 2:
            case 2:
              instrName = "ldw";
              instrName = "ldw";
              state->_load_len = 2;
              state->_load_len = 2;
              break;
              break;
            default:
            default:
              instrName = "??? (1[3])";
              instrName = "??? (1[3])";
              state->flow = invalid_instr;
              state->flow = invalid_instr;
              break;
              break;
            }
            }
          decodingClass = CLASS_A4_LD1;
          decodingClass = CLASS_A4_LD1;
        }
        }
      break;
      break;
 
 
    case op_ST:
    case op_ST:
      if (BIT (state->words[0], 25))
      if (BIT (state->words[0], 25))
        {
        {
          instrName = "sr";
          instrName = "sr";
          decodingClass = CLASS_A4_SR;
          decodingClass = CLASS_A4_SR;
        }
        }
      else
      else
        {
        {
          switch (BITS (state->words[0], 22, 23))
          switch (BITS (state->words[0], 22, 23))
            {
            {
            case 0:
            case 0:
              instrName = "st";
              instrName = "st";
              break;
              break;
            case 1:
            case 1:
              instrName = "stb";
              instrName = "stb";
              break;
              break;
            case 2:
            case 2:
              instrName = "stw";
              instrName = "stw";
              break;
              break;
            default:
            default:
              instrName = "??? (2[3])";
              instrName = "??? (2[3])";
              state->flow = invalid_instr;
              state->flow = invalid_instr;
              break;
              break;
            }
            }
          decodingClass = CLASS_A4_ST;
          decodingClass = CLASS_A4_ST;
        }
        }
      break;
      break;
 
 
    case op_3:
    case op_3:
      decodingClass = CLASS_A4_OP3_GENERAL;  /* default for opcode 3...  */
      decodingClass = CLASS_A4_OP3_GENERAL;  /* default for opcode 3...  */
      switch (FIELDC (state->words[0]))
      switch (FIELDC (state->words[0]))
        {
        {
        case  0:
        case  0:
          instrName = "flag";
          instrName = "flag";
          decodingClass = CLASS_A4_FLAG;
          decodingClass = CLASS_A4_FLAG;
          break;
          break;
        case  1:
        case  1:
          instrName = "asr";
          instrName = "asr";
          break;
          break;
        case  2:
        case  2:
          instrName = "lsr";
          instrName = "lsr";
          break;
          break;
        case  3:
        case  3:
          instrName = "ror";
          instrName = "ror";
          break;
          break;
        case  4:
        case  4:
          instrName = "rrc";
          instrName = "rrc";
          break;
          break;
        case  5:
        case  5:
          instrName = "sexb";
          instrName = "sexb";
          break;
          break;
        case  6:
        case  6:
          instrName = "sexw";
          instrName = "sexw";
          break;
          break;
        case  7:
        case  7:
          instrName = "extb";
          instrName = "extb";
          break;
          break;
        case  8:
        case  8:
          instrName = "extw";
          instrName = "extw";
          break;
          break;
        case  0x3f:
        case  0x3f:
          {
          {
            decodingClass = CLASS_A4_OP3_SUBOPC3F;
            decodingClass = CLASS_A4_OP3_SUBOPC3F;
            switch (FIELDD (state->words[0]))
            switch (FIELDD (state->words[0]))
              {
              {
              case 0:
              case 0:
                instrName = "brk";
                instrName = "brk";
                break;
                break;
              case 1:
              case 1:
                instrName = "sleep";
                instrName = "sleep";
                break;
                break;
              case 2:
              case 2:
                instrName = "swi";
                instrName = "swi";
                break;
                break;
              default:
              default:
                instrName = "???";
                instrName = "???";
                state->flow=invalid_instr;
                state->flow=invalid_instr;
                break;
                break;
              }
              }
          }
          }
          break;
          break;
 
 
          /* ARC Extension Library Instructions
          /* ARC Extension Library Instructions
             NOTE: We assume that extension codes are these instrs.  */
             NOTE: We assume that extension codes are these instrs.  */
        default:
        default:
          instrName = instruction_name (state,
          instrName = instruction_name (state,
                                        state->_opcode,
                                        state->_opcode,
                                        FIELDC (state->words[0]),
                                        FIELDC (state->words[0]),
                                        &flags);
                                        &flags);
          if (!instrName)
          if (!instrName)
            {
            {
              instrName = "???";
              instrName = "???";
              state->flow = invalid_instr;
              state->flow = invalid_instr;
            }
            }
          if (flags & IGNORE_FIRST_OPD)
          if (flags & IGNORE_FIRST_OPD)
            ignoreFirstOpd = 1;
            ignoreFirstOpd = 1;
          break;
          break;
        }
        }
      break;
      break;
 
 
    case op_BC:
    case op_BC:
      instrName = "b";
      instrName = "b";
    case op_BLC:
    case op_BLC:
      if (!instrName)
      if (!instrName)
        instrName = "bl";
        instrName = "bl";
    case op_LPC:
    case op_LPC:
      if (!instrName)
      if (!instrName)
        instrName = "lp";
        instrName = "lp";
    case op_JC:
    case op_JC:
      if (!instrName)
      if (!instrName)
        {
        {
          if (BITS (state->words[0],9,9))
          if (BITS (state->words[0],9,9))
            {
            {
              instrName = "jl";
              instrName = "jl";
              is_linked = 1;
              is_linked = 1;
            }
            }
          else
          else
            {
            {
              instrName = "j";
              instrName = "j";
              is_linked = 0;
              is_linked = 0;
            }
            }
        }
        }
      condCodeIsPartOfName = 1;
      condCodeIsPartOfName = 1;
      decodingClass = ((state->_opcode == op_JC) ? CLASS_A4_JC : CLASS_A4_BRANCH );
      decodingClass = ((state->_opcode == op_JC) ? CLASS_A4_JC : CLASS_A4_BRANCH );
      state->isBranch = 1;
      state->isBranch = 1;
      break;
      break;
 
 
    case op_ADD:
    case op_ADD:
    case op_ADC:
    case op_ADC:
    case op_AND:
    case op_AND:
      repeatsOp = (FIELDC (state->words[0]) == FIELDB (state->words[0]));
      repeatsOp = (FIELDC (state->words[0]) == FIELDB (state->words[0]));
 
 
      switch (state->_opcode)
      switch (state->_opcode)
        {
        {
        case op_ADD:
        case op_ADD:
          instrName = (repeatsOp ? "asl" : "add");
          instrName = (repeatsOp ? "asl" : "add");
          break;
          break;
        case op_ADC:
        case op_ADC:
          instrName = (repeatsOp ? "rlc" : "adc");
          instrName = (repeatsOp ? "rlc" : "adc");
          break;
          break;
        case op_AND:
        case op_AND:
          instrName = (repeatsOp ? "mov" : "and");
          instrName = (repeatsOp ? "mov" : "and");
          break;
          break;
        }
        }
      break;
      break;
 
 
    case op_SUB: instrName = "sub";
    case op_SUB: instrName = "sub";
      break;
      break;
    case op_SBC: instrName = "sbc";
    case op_SBC: instrName = "sbc";
      break;
      break;
    case op_OR:  instrName = "or";
    case op_OR:  instrName = "or";
      break;
      break;
    case op_BIC: instrName = "bic";
    case op_BIC: instrName = "bic";
      break;
      break;
 
 
    case op_XOR:
    case op_XOR:
      if (state->words[0] == 0x7fffffff)
      if (state->words[0] == 0x7fffffff)
        {
        {
          /* NOP encoded as xor -1, -1, -1.   */
          /* NOP encoded as xor -1, -1, -1.   */
          instrName = "nop";
          instrName = "nop";
          decodingClass = CLASS_A4_OP3_SUBOPC3F;
          decodingClass = CLASS_A4_OP3_SUBOPC3F;
        }
        }
      else
      else
        instrName = "xor";
        instrName = "xor";
      break;
      break;
 
 
    default:
    default:
      instrName = instruction_name (state,state->_opcode,0,&flags);
      instrName = instruction_name (state,state->_opcode,0,&flags);
      /* if (instrName) printf("FLAGS=0x%x\n", flags);  */
      /* if (instrName) printf("FLAGS=0x%x\n", flags);  */
      if (!instrName)
      if (!instrName)
        {
        {
          instrName = "???";
          instrName = "???";
          state->flow=invalid_instr;
          state->flow=invalid_instr;
        }
        }
      if (flags & IGNORE_FIRST_OPD)
      if (flags & IGNORE_FIRST_OPD)
        ignoreFirstOpd = 1;
        ignoreFirstOpd = 1;
      break;
      break;
    }
    }
 
 
  fieldAisReg = fieldBisReg = fieldCisReg = 1; /* Assume regs for now.  */
  fieldAisReg = fieldBisReg = fieldCisReg = 1; /* Assume regs for now.  */
  flag = cond = is_shimm = is_limm = 0;
  flag = cond = is_shimm = is_limm = 0;
  state->nullifyMode = BR_exec_when_no_jump;    /* 0  */
  state->nullifyMode = BR_exec_when_no_jump;    /* 0  */
  signExtend = addrWriteBack = directMem = 0;
  signExtend = addrWriteBack = directMem = 0;
  usesAuxReg = 0;
  usesAuxReg = 0;
 
 
  switch (decodingClass)
  switch (decodingClass)
    {
    {
    case CLASS_A4_ARITH:
    case CLASS_A4_ARITH:
      CHECK_FIELD_A ();
      CHECK_FIELD_A ();
      CHECK_FIELD_B ();
      CHECK_FIELD_B ();
      if (!repeatsOp)
      if (!repeatsOp)
        CHECK_FIELD_C ();
        CHECK_FIELD_C ();
      CHECK_FLAG_COND_NULLIFY ();
      CHECK_FLAG_COND_NULLIFY ();
 
 
      write_instr_name ();
      write_instr_name ();
      if (!ignoreFirstOpd)
      if (!ignoreFirstOpd)
        {
        {
          WRITE_FORMAT_x (A);
          WRITE_FORMAT_x (A);
          WRITE_FORMAT_COMMA_x (B);
          WRITE_FORMAT_COMMA_x (B);
          if (!repeatsOp)
          if (!repeatsOp)
            WRITE_FORMAT_COMMA_x (C);
            WRITE_FORMAT_COMMA_x (C);
          WRITE_NOP_COMMENT ();
          WRITE_NOP_COMMENT ();
          arc_sprintf (state, state->operandBuffer, formatString,
          arc_sprintf (state, state->operandBuffer, formatString,
                      fieldA, fieldB, fieldC);
                      fieldA, fieldB, fieldC);
        }
        }
      else
      else
        {
        {
          WRITE_FORMAT_x (B);
          WRITE_FORMAT_x (B);
          if (!repeatsOp)
          if (!repeatsOp)
            WRITE_FORMAT_COMMA_x (C);
            WRITE_FORMAT_COMMA_x (C);
          arc_sprintf (state, state->operandBuffer, formatString,
          arc_sprintf (state, state->operandBuffer, formatString,
                      fieldB, fieldC);
                      fieldB, fieldC);
        }
        }
      write_comments ();
      write_comments ();
      break;
      break;
 
 
    case CLASS_A4_OP3_GENERAL:
    case CLASS_A4_OP3_GENERAL:
      CHECK_FIELD_A ();
      CHECK_FIELD_A ();
      CHECK_FIELD_B ();
      CHECK_FIELD_B ();
      CHECK_FLAG_COND_NULLIFY ();
      CHECK_FLAG_COND_NULLIFY ();
 
 
      write_instr_name ();
      write_instr_name ();
      if (!ignoreFirstOpd)
      if (!ignoreFirstOpd)
        {
        {
          WRITE_FORMAT_x (A);
          WRITE_FORMAT_x (A);
          WRITE_FORMAT_COMMA_x (B);
          WRITE_FORMAT_COMMA_x (B);
          WRITE_NOP_COMMENT ();
          WRITE_NOP_COMMENT ();
          arc_sprintf (state, state->operandBuffer, formatString,
          arc_sprintf (state, state->operandBuffer, formatString,
                      fieldA, fieldB);
                      fieldA, fieldB);
        }
        }
      else
      else
        {
        {
          WRITE_FORMAT_x (B);
          WRITE_FORMAT_x (B);
          arc_sprintf (state, state->operandBuffer, formatString, fieldB);
          arc_sprintf (state, state->operandBuffer, formatString, fieldB);
        }
        }
      write_comments ();
      write_comments ();
      break;
      break;
 
 
    case CLASS_A4_FLAG:
    case CLASS_A4_FLAG:
      CHECK_FIELD_B ();
      CHECK_FIELD_B ();
      CHECK_FLAG_COND_NULLIFY ();
      CHECK_FLAG_COND_NULLIFY ();
      flag = 0; /* This is the FLAG instruction -- it's redundant.  */
      flag = 0; /* This is the FLAG instruction -- it's redundant.  */
 
 
      write_instr_name ();
      write_instr_name ();
      WRITE_FORMAT_x (B);
      WRITE_FORMAT_x (B);
      arc_sprintf (state, state->operandBuffer, formatString, fieldB);
      arc_sprintf (state, state->operandBuffer, formatString, fieldB);
      write_comments ();
      write_comments ();
      break;
      break;
 
 
    case CLASS_A4_BRANCH:
    case CLASS_A4_BRANCH:
      fieldA = BITS (state->words[0],7,26) << 2;
      fieldA = BITS (state->words[0],7,26) << 2;
      fieldA = (fieldA << 10) >> 10; /* Make it signed.  */
      fieldA = (fieldA << 10) >> 10; /* Make it signed.  */
      fieldA += addr + 4;
      fieldA += addr + 4;
      CHECK_FLAG_COND_NULLIFY ();
      CHECK_FLAG_COND_NULLIFY ();
      flag = 0;
      flag = 0;
 
 
      write_instr_name ();
      write_instr_name ();
      /* This address could be a label we know. Convert it.  */
      /* This address could be a label we know. Convert it.  */
      if (state->_opcode != op_LPC /* LP  */)
      if (state->_opcode != op_LPC /* LP  */)
        {
        {
          add_target (fieldA); /* For debugger.  */
          add_target (fieldA); /* For debugger.  */
          state->flow = state->_opcode == op_BLC /* BL  */
          state->flow = state->_opcode == op_BLC /* BL  */
            ? direct_call
            ? direct_call
            : direct_jump;
            : direct_jump;
          /* indirect calls are achieved by "lr blink,[status];
          /* indirect calls are achieved by "lr blink,[status];
             lr dest<- func addr; j [dest]"  */
             lr dest<- func addr; j [dest]"  */
        }
        }
 
 
      strcat (formatString, "%s"); /* Address/label name.  */
      strcat (formatString, "%s"); /* Address/label name.  */
      arc_sprintf (state, state->operandBuffer, formatString,
      arc_sprintf (state, state->operandBuffer, formatString,
                  post_address (state, fieldA));
                  post_address (state, fieldA));
      write_comments ();
      write_comments ();
      break;
      break;
 
 
    case CLASS_A4_JC:
    case CLASS_A4_JC:
      /* For op_JC -- jump to address specified.
      /* For op_JC -- jump to address specified.
         Also covers jump and link--bit 9 of the instr. word
         Also covers jump and link--bit 9 of the instr. word
         selects whether linked, thus "is_linked" is set above.  */
         selects whether linked, thus "is_linked" is set above.  */
      fieldA = 0;
      fieldA = 0;
      CHECK_FIELD_B ();
      CHECK_FIELD_B ();
      CHECK_FLAG_COND_NULLIFY ();
      CHECK_FLAG_COND_NULLIFY ();
 
 
      if (!fieldBisReg)
      if (!fieldBisReg)
        {
        {
          fieldAisReg = 0;
          fieldAisReg = 0;
          fieldA = (fieldB >> 25) & 0x7F; /* Flags.  */
          fieldA = (fieldB >> 25) & 0x7F; /* Flags.  */
          fieldB = (fieldB & 0xFFFFFF) << 2;
          fieldB = (fieldB & 0xFFFFFF) << 2;
          state->flow = is_linked ? direct_call : direct_jump;
          state->flow = is_linked ? direct_call : direct_jump;
          add_target (fieldB);
          add_target (fieldB);
          /* Screwy JLcc requires .jd mode to execute correctly
          /* Screwy JLcc requires .jd mode to execute correctly
             but we pretend it is .nd (no delay slot).  */
             but we pretend it is .nd (no delay slot).  */
          if (is_linked && state->nullifyMode == BR_exec_when_jump)
          if (is_linked && state->nullifyMode == BR_exec_when_jump)
            state->nullifyMode = BR_exec_when_no_jump;
            state->nullifyMode = BR_exec_when_no_jump;
        }
        }
      else
      else
        {
        {
          state->flow = is_linked ? indirect_call : indirect_jump;
          state->flow = is_linked ? indirect_call : indirect_jump;
          /* We should also treat this as indirect call if NOT linked
          /* We should also treat this as indirect call if NOT linked
             but the preceding instruction was a "lr blink,[status]"
             but the preceding instruction was a "lr blink,[status]"
             and we have a delay slot with "add blink,blink,2".
             and we have a delay slot with "add blink,blink,2".
             For now we can't detect such.  */
             For now we can't detect such.  */
          state->register_for_indirect_jump = fieldB;
          state->register_for_indirect_jump = fieldB;
        }
        }
 
 
      write_instr_name ();
      write_instr_name ();
      strcat (formatString,
      strcat (formatString,
              IS_REG (B) ? "[%r]" : "%s"); /* Address/label name.  */
              IS_REG (B) ? "[%r]" : "%s"); /* Address/label name.  */
      if (fieldA != 0)
      if (fieldA != 0)
        {
        {
          fieldAisReg = 0;
          fieldAisReg = 0;
          WRITE_FORMAT_COMMA_x (A);
          WRITE_FORMAT_COMMA_x (A);
        }
        }
      if (IS_REG (B))
      if (IS_REG (B))
        arc_sprintf (state, state->operandBuffer, formatString, fieldB, fieldA);
        arc_sprintf (state, state->operandBuffer, formatString, fieldB, fieldA);
      else
      else
        arc_sprintf (state, state->operandBuffer, formatString,
        arc_sprintf (state, state->operandBuffer, formatString,
                    post_address (state, fieldB), fieldA);
                    post_address (state, fieldB), fieldA);
      write_comments ();
      write_comments ();
      break;
      break;
 
 
    case CLASS_A4_LD0:
    case CLASS_A4_LD0:
      /* LD instruction.
      /* LD instruction.
         B and C can be regs, or one (both?) can be limm.  */
         B and C can be regs, or one (both?) can be limm.  */
      CHECK_FIELD_A ();
      CHECK_FIELD_A ();
      CHECK_FIELD_B ();
      CHECK_FIELD_B ();
      CHECK_FIELD_C ();
      CHECK_FIELD_C ();
      if (dbg)
      if (dbg)
        printf ("5:b reg %d %d c reg %d %d  \n",
        printf ("5:b reg %d %d c reg %d %d  \n",
                fieldBisReg,fieldB,fieldCisReg,fieldC);
                fieldBisReg,fieldB,fieldCisReg,fieldC);
      state->_offset = 0;
      state->_offset = 0;
      state->_ea_present = 1;
      state->_ea_present = 1;
      if (fieldBisReg)
      if (fieldBisReg)
        state->ea_reg1 = fieldB;
        state->ea_reg1 = fieldB;
      else
      else
        state->_offset += fieldB;
        state->_offset += fieldB;
      if (fieldCisReg)
      if (fieldCisReg)
        state->ea_reg2 = fieldC;
        state->ea_reg2 = fieldC;
      else
      else
        state->_offset += fieldC;
        state->_offset += fieldC;
      state->_mem_load = 1;
      state->_mem_load = 1;
 
 
      directMem     = BIT (state->words[0], 5);
      directMem     = BIT (state->words[0], 5);
      addrWriteBack = BIT (state->words[0], 3);
      addrWriteBack = BIT (state->words[0], 3);
      signExtend    = BIT (state->words[0], 0);
      signExtend    = BIT (state->words[0], 0);
 
 
      write_instr_name ();
      write_instr_name ();
      WRITE_FORMAT_x_COMMA_LB(A);
      WRITE_FORMAT_x_COMMA_LB(A);
      if (fieldBisReg || fieldB != 0)
      if (fieldBisReg || fieldB != 0)
        WRITE_FORMAT_x_COMMA (B);
        WRITE_FORMAT_x_COMMA (B);
      else
      else
        fieldB = fieldC;
        fieldB = fieldC;
 
 
      WRITE_FORMAT_x_RB (C);
      WRITE_FORMAT_x_RB (C);
      arc_sprintf (state, state->operandBuffer, formatString,
      arc_sprintf (state, state->operandBuffer, formatString,
                  fieldA, fieldB, fieldC);
                  fieldA, fieldB, fieldC);
      write_comments ();
      write_comments ();
      break;
      break;
 
 
    case CLASS_A4_LD1:
    case CLASS_A4_LD1:
      /* LD instruction.  */
      /* LD instruction.  */
      CHECK_FIELD_B ();
      CHECK_FIELD_B ();
      CHECK_FIELD_A ();
      CHECK_FIELD_A ();
      fieldC = FIELDD (state->words[0]);
      fieldC = FIELDD (state->words[0]);
 
 
      if (dbg)
      if (dbg)
        printf ("6:b reg %d %d c 0x%x  \n",
        printf ("6:b reg %d %d c 0x%x  \n",
                fieldBisReg, fieldB, fieldC);
                fieldBisReg, fieldB, fieldC);
      state->_ea_present = 1;
      state->_ea_present = 1;
      state->_offset = fieldC;
      state->_offset = fieldC;
      state->_mem_load = 1;
      state->_mem_load = 1;
      if (fieldBisReg)
      if (fieldBisReg)
        state->ea_reg1 = fieldB;
        state->ea_reg1 = fieldB;
      /* Field B is either a shimm (same as fieldC) or limm (different!)
      /* Field B is either a shimm (same as fieldC) or limm (different!)
         Say ea is not present, so only one of us will do the name lookup.  */
         Say ea is not present, so only one of us will do the name lookup.  */
      else
      else
        state->_offset += fieldB, state->_ea_present = 0;
        state->_offset += fieldB, state->_ea_present = 0;
 
 
      directMem     = BIT (state->words[0],14);
      directMem     = BIT (state->words[0],14);
      addrWriteBack = BIT (state->words[0],12);
      addrWriteBack = BIT (state->words[0],12);
      signExtend    = BIT (state->words[0],9);
      signExtend    = BIT (state->words[0],9);
 
 
      write_instr_name ();
      write_instr_name ();
      WRITE_FORMAT_x_COMMA_LB (A);
      WRITE_FORMAT_x_COMMA_LB (A);
      if (!fieldBisReg)
      if (!fieldBisReg)
        {
        {
          fieldB = state->_offset;
          fieldB = state->_offset;
          WRITE_FORMAT_x_RB (B);
          WRITE_FORMAT_x_RB (B);
        }
        }
      else
      else
        {
        {
          WRITE_FORMAT_x (B);
          WRITE_FORMAT_x (B);
          if (fieldC != 0 && !BIT (state->words[0],13))
          if (fieldC != 0 && !BIT (state->words[0],13))
            {
            {
              fieldCisReg = 0;
              fieldCisReg = 0;
              WRITE_FORMAT_COMMA_x_RB (C);
              WRITE_FORMAT_COMMA_x_RB (C);
            }
            }
          else
          else
            WRITE_FORMAT_RB ();
            WRITE_FORMAT_RB ();
        }
        }
      arc_sprintf (state, state->operandBuffer, formatString,
      arc_sprintf (state, state->operandBuffer, formatString,
                  fieldA, fieldB, fieldC);
                  fieldA, fieldB, fieldC);
      write_comments ();
      write_comments ();
      break;
      break;
 
 
    case CLASS_A4_ST:
    case CLASS_A4_ST:
      /* ST instruction.  */
      /* ST instruction.  */
      CHECK_FIELD_B();
      CHECK_FIELD_B();
      CHECK_FIELD_C();
      CHECK_FIELD_C();
      fieldA = FIELDD(state->words[0]); /* shimm  */
      fieldA = FIELDD(state->words[0]); /* shimm  */
 
 
      /* [B,A offset]  */
      /* [B,A offset]  */
      if (dbg) printf("7:b reg %d %x off %x\n",
      if (dbg) printf("7:b reg %d %x off %x\n",
                      fieldBisReg,fieldB,fieldA);
                      fieldBisReg,fieldB,fieldA);
      state->_ea_present = 1;
      state->_ea_present = 1;
      state->_offset = fieldA;
      state->_offset = fieldA;
      if (fieldBisReg)
      if (fieldBisReg)
        state->ea_reg1 = fieldB;
        state->ea_reg1 = fieldB;
      /* Field B is either a shimm (same as fieldA) or limm (different!)
      /* Field B is either a shimm (same as fieldA) or limm (different!)
         Say ea is not present, so only one of us will do the name lookup.
         Say ea is not present, so only one of us will do the name lookup.
         (for is_limm we do the name translation here).  */
         (for is_limm we do the name translation here).  */
      else
      else
        state->_offset += fieldB, state->_ea_present = 0;
        state->_offset += fieldB, state->_ea_present = 0;
 
 
      directMem     = BIT (state->words[0], 26);
      directMem     = BIT (state->words[0], 26);
      addrWriteBack = BIT (state->words[0], 24);
      addrWriteBack = BIT (state->words[0], 24);
 
 
      write_instr_name ();
      write_instr_name ();
      WRITE_FORMAT_x_COMMA_LB(C);
      WRITE_FORMAT_x_COMMA_LB(C);
 
 
      if (!fieldBisReg)
      if (!fieldBisReg)
        {
        {
          fieldB = state->_offset;
          fieldB = state->_offset;
          WRITE_FORMAT_x_RB (B);
          WRITE_FORMAT_x_RB (B);
        }
        }
      else
      else
        {
        {
          WRITE_FORMAT_x (B);
          WRITE_FORMAT_x (B);
          if (fieldBisReg && fieldA != 0)
          if (fieldBisReg && fieldA != 0)
            {
            {
              fieldAisReg = 0;
              fieldAisReg = 0;
              WRITE_FORMAT_COMMA_x_RB(A);
              WRITE_FORMAT_COMMA_x_RB(A);
            }
            }
          else
          else
            WRITE_FORMAT_RB();
            WRITE_FORMAT_RB();
        }
        }
      arc_sprintf (state, state->operandBuffer, formatString,
      arc_sprintf (state, state->operandBuffer, formatString,
                  fieldC, fieldB, fieldA);
                  fieldC, fieldB, fieldA);
      write_comments2 (fieldA);
      write_comments2 (fieldA);
      break;
      break;
 
 
    case CLASS_A4_SR:
    case CLASS_A4_SR:
      /* SR instruction  */
      /* SR instruction  */
      CHECK_FIELD_B();
      CHECK_FIELD_B();
      CHECK_FIELD_C();
      CHECK_FIELD_C();
 
 
      write_instr_name ();
      write_instr_name ();
      WRITE_FORMAT_x_COMMA_LB(C);
      WRITE_FORMAT_x_COMMA_LB(C);
      /* Try to print B as an aux reg if it is not a core reg.  */
      /* Try to print B as an aux reg if it is not a core reg.  */
      usesAuxReg = 1;
      usesAuxReg = 1;
      WRITE_FORMAT_x (B);
      WRITE_FORMAT_x (B);
      WRITE_FORMAT_RB ();
      WRITE_FORMAT_RB ();
      arc_sprintf (state, state->operandBuffer, formatString, fieldC, fieldB);
      arc_sprintf (state, state->operandBuffer, formatString, fieldC, fieldB);
      write_comments ();
      write_comments ();
      break;
      break;
 
 
    case CLASS_A4_OP3_SUBOPC3F:
    case CLASS_A4_OP3_SUBOPC3F:
      write_instr_name ();
      write_instr_name ();
      state->operandBuffer[0] = '\0';
      state->operandBuffer[0] = '\0';
      break;
      break;
 
 
    case CLASS_A4_LR:
    case CLASS_A4_LR:
      /* LR instruction */
      /* LR instruction */
      CHECK_FIELD_A ();
      CHECK_FIELD_A ();
      CHECK_FIELD_B ();
      CHECK_FIELD_B ();
 
 
      write_instr_name ();
      write_instr_name ();
      WRITE_FORMAT_x_COMMA_LB (A);
      WRITE_FORMAT_x_COMMA_LB (A);
      /* Try to print B as an aux reg if it is not a core reg. */
      /* Try to print B as an aux reg if it is not a core reg. */
      usesAuxReg = 1;
      usesAuxReg = 1;
      WRITE_FORMAT_x (B);
      WRITE_FORMAT_x (B);
      WRITE_FORMAT_RB ();
      WRITE_FORMAT_RB ();
      arc_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB);
      arc_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB);
      write_comments ();
      write_comments ();
      break;
      break;
 
 
    default:
    default:
      mwerror (state, "Bad decoding class in ARC disassembler");
      mwerror (state, "Bad decoding class in ARC disassembler");
      break;
      break;
    }
    }
 
 
  state->_cond = cond;
  state->_cond = cond;
  return state->instructionLen = offset;
  return state->instructionLen = offset;
}
}
 
 
 
 
/* Returns the name the user specified core extension register.  */
/* Returns the name the user specified core extension register.  */
 
 
static const char *
static const char *
_coreRegName(void * arg ATTRIBUTE_UNUSED, int regval)
_coreRegName(void * arg ATTRIBUTE_UNUSED, int regval)
{
{
  return arcExtMap_coreRegName (regval);
  return arcExtMap_coreRegName (regval);
}
}
 
 
/* Returns the name the user specified AUX extension register.  */
/* Returns the name the user specified AUX extension register.  */
 
 
static const char *
static const char *
_auxRegName(void *_this ATTRIBUTE_UNUSED, int regval)
_auxRegName(void *_this ATTRIBUTE_UNUSED, int regval)
{
{
  return arcExtMap_auxRegName(regval);
  return arcExtMap_auxRegName(regval);
}
}
 
 
/* Returns the name the user specified condition code name.  */
/* Returns the name the user specified condition code name.  */
 
 
static const char *
static const char *
_condCodeName(void *_this ATTRIBUTE_UNUSED, int regval)
_condCodeName(void *_this ATTRIBUTE_UNUSED, int regval)
{
{
  return arcExtMap_condCodeName(regval);
  return arcExtMap_condCodeName(regval);
}
}
 
 
/* Returns the name the user specified extension instruction.  */
/* Returns the name the user specified extension instruction.  */
 
 
static const char *
static const char *
_instName (void *_this ATTRIBUTE_UNUSED, int majop, int minop, int *flags)
_instName (void *_this ATTRIBUTE_UNUSED, int majop, int minop, int *flags)
{
{
  return arcExtMap_instName(majop, minop, flags);
  return arcExtMap_instName(majop, minop, flags);
}
}
 
 
/* Decode an instruction returning the size of the instruction
/* Decode an instruction returning the size of the instruction
   in bytes or zero if unrecognized.  */
   in bytes or zero if unrecognized.  */
 
 
static int
static int
decodeInstr (bfd_vma            address, /* Address of this instruction.  */
decodeInstr (bfd_vma            address, /* Address of this instruction.  */
             disassemble_info * info)
             disassemble_info * info)
{
{
  int status;
  int status;
  bfd_byte buffer[4];
  bfd_byte buffer[4];
  struct arcDisState s;         /* ARC Disassembler state.  */
  struct arcDisState s;         /* ARC Disassembler state.  */
  void *stream = info->stream;  /* Output stream.  */
  void *stream = info->stream;  /* Output stream.  */
  fprintf_ftype func = info->fprintf_func;
  fprintf_ftype func = info->fprintf_func;
  int bytes;
  int bytes;
 
 
  memset (&s, 0, sizeof(struct arcDisState));
  memset (&s, 0, sizeof(struct arcDisState));
 
 
  /* read first instruction  */
  /* read first instruction  */
  status = (*info->read_memory_func) (address, buffer, 4, info);
  status = (*info->read_memory_func) (address, buffer, 4, info);
  if (status != 0)
  if (status != 0)
    {
    {
      (*info->memory_error_func) (status, address, info);
      (*info->memory_error_func) (status, address, info);
      return 0;
      return 0;
    }
    }
  if (info->endian == BFD_ENDIAN_LITTLE)
  if (info->endian == BFD_ENDIAN_LITTLE)
    s.words[0] = bfd_getl32(buffer);
    s.words[0] = bfd_getl32(buffer);
  else
  else
    s.words[0] = bfd_getb32(buffer);
    s.words[0] = bfd_getb32(buffer);
  /* Always read second word in case of limm.  */
  /* Always read second word in case of limm.  */
 
 
  /* We ignore the result since last insn may not have a limm.  */
  /* We ignore the result since last insn may not have a limm.  */
  status = (*info->read_memory_func) (address + 4, buffer, 4, info);
  status = (*info->read_memory_func) (address + 4, buffer, 4, info);
  if (info->endian == BFD_ENDIAN_LITTLE)
  if (info->endian == BFD_ENDIAN_LITTLE)
    s.words[1] = bfd_getl32(buffer);
    s.words[1] = bfd_getl32(buffer);
  else
  else
    s.words[1] = bfd_getb32(buffer);
    s.words[1] = bfd_getb32(buffer);
 
 
  s._this = &s;
  s._this = &s;
  s.coreRegName = _coreRegName;
  s.coreRegName = _coreRegName;
  s.auxRegName = _auxRegName;
  s.auxRegName = _auxRegName;
  s.condCodeName = _condCodeName;
  s.condCodeName = _condCodeName;
  s.instName = _instName;
  s.instName = _instName;
 
 
  /* Disassemble.  */
  /* Disassemble.  */
  bytes = dsmOneArcInst (address, (void *)& s);
  bytes = dsmOneArcInst (address, (void *)& s);
 
 
  /* Display the disassembly instruction.  */
  /* Display the disassembly instruction.  */
  (*func) (stream, "%08lx ", s.words[0]);
  (*func) (stream, "%08lx ", s.words[0]);
  (*func) (stream, "    ");
  (*func) (stream, "    ");
  (*func) (stream, "%-10s ", s.instrBuffer);
  (*func) (stream, "%-10s ", s.instrBuffer);
 
 
  if (__TRANSLATION_REQUIRED (s))
  if (__TRANSLATION_REQUIRED (s))
    {
    {
      bfd_vma addr = s.addresses[s.operandBuffer[1] - '0'];
      bfd_vma addr = s.addresses[s.operandBuffer[1] - '0'];
 
 
      (*info->print_address_func) ((bfd_vma) addr, info);
      (*info->print_address_func) ((bfd_vma) addr, info);
      (*func) (stream, "\n");
      (*func) (stream, "\n");
    }
    }
  else
  else
    (*func) (stream, "%s",s.operandBuffer);
    (*func) (stream, "%s",s.operandBuffer);
 
 
  return s.instructionLen;
  return s.instructionLen;
}
}
 
 
/* Return the print_insn function to use.
/* Return the print_insn function to use.
   Side effect: load (possibly empty) extension section  */
   Side effect: load (possibly empty) extension section  */
 
 
disassembler_ftype
disassembler_ftype
arc_get_disassembler (void *ptr)
arc_get_disassembler (void *ptr)
{
{
  if (ptr)
  if (ptr)
    build_ARC_extmap (ptr);
    build_ARC_extmap (ptr);
  return decodeInstr;
  return decodeInstr;
}
}
 
 

powered by: WebSVN 2.1.0

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