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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [opcodes/] [ia64-opc.c] - Diff between revs 834 and 842

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

Rev 834 Rev 842
/* ia64-opc.c -- Functions to access the compacted opcode table
/* ia64-opc.c -- Functions to access the compacted opcode table
   Copyright 1999, 2000, 2001, 2003, 2005, 2007, 2009 Free Software Foundation, Inc.
   Copyright 1999, 2000, 2001, 2003, 2005, 2007, 2009 Free Software Foundation, Inc.
   Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com>
   Written by Bob Manson of Cygnus Solutions, <manson@cygnus.com>
 
 
   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 file; see the file COPYING.  If not, write to the
   along with this file; see the file COPYING.  If not, write to the
   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
   Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
   MA 02110-1301, USA.  */
   MA 02110-1301, USA.  */
 
 
#include "ansidecl.h"
#include "ansidecl.h"
#include "sysdep.h"
#include "sysdep.h"
#include "libiberty.h"
#include "libiberty.h"
#include "ia64-asmtab.h"
#include "ia64-asmtab.h"
#include "ia64-asmtab.c"
#include "ia64-asmtab.c"
 
 
static void get_opc_prefix (const char **, char *);
static void get_opc_prefix (const char **, char *);
static short int find_string_ent (const char *);
static short int find_string_ent (const char *);
static short int find_main_ent (short int);
static short int find_main_ent (short int);
static short int find_completer (short int, short int, const char *);
static short int find_completer (short int, short int, const char *);
static ia64_insn apply_completer (ia64_insn, int);
static ia64_insn apply_completer (ia64_insn, int);
static int extract_op_bits (int, int, int);
static int extract_op_bits (int, int, int);
static int extract_op (int, int *, unsigned int *);
static int extract_op (int, int *, unsigned int *);
static int opcode_verify (ia64_insn, int, enum ia64_insn_type);
static int opcode_verify (ia64_insn, int, enum ia64_insn_type);
static int locate_opcode_ent (ia64_insn, enum ia64_insn_type);
static int locate_opcode_ent (ia64_insn, enum ia64_insn_type);
static struct ia64_opcode *make_ia64_opcode
static struct ia64_opcode *make_ia64_opcode
  (ia64_insn, const char *, int, int);
  (ia64_insn, const char *, int, int);
static struct ia64_opcode *ia64_find_matching_opcode
static struct ia64_opcode *ia64_find_matching_opcode
  (const char *, short int);
  (const char *, short int);
 
 
const struct ia64_templ_desc ia64_templ_desc[16] =
const struct ia64_templ_desc ia64_templ_desc[16] =
  {
  {
    { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },     /* 0 */
    { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },     /* 0 */
    { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },
    { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },
    { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" },
    { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" },
    { 0, { 0, },                              "-3-" },
    { 0, { 0, },                              "-3-" },
    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },     /* 4 */
    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },     /* 4 */
    { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },
    { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },
    { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" },
    { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" },
    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" },
    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" },
    { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" },     /* 8 */
    { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" },     /* 8 */
    { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" },
    { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" },
    { 0, { 0, },                              "-a-" },
    { 0, { 0, },                              "-a-" },
    { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" },
    { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" },
    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" },     /* c */
    { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" },     /* c */
    { 0, { 0, },                              "-d-" },
    { 0, { 0, },                              "-d-" },
    { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" },
    { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" },
    { 0, { 0, },                              "-f-" },
    { 0, { 0, },                              "-f-" },
  };
  };
 
 
 
 
/* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST.
/* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST.
   PTR will be adjusted to point to the start of the next portion
   PTR will be adjusted to point to the start of the next portion
   of the opcode, or at the NUL character. */
   of the opcode, or at the NUL character. */
 
 
static void
static void
get_opc_prefix (const char **ptr, char *dest)
get_opc_prefix (const char **ptr, char *dest)
{
{
  char *c = strchr (*ptr, '.');
  char *c = strchr (*ptr, '.');
  if (c != NULL)
  if (c != NULL)
    {
    {
      memcpy (dest, *ptr, c - *ptr);
      memcpy (dest, *ptr, c - *ptr);
      dest[c - *ptr] = '\0';
      dest[c - *ptr] = '\0';
      *ptr = c + 1;
      *ptr = c + 1;
    }
    }
  else
  else
    {
    {
      int l = strlen (*ptr);
      int l = strlen (*ptr);
      memcpy (dest, *ptr, l);
      memcpy (dest, *ptr, l);
      dest[l] = '\0';
      dest[l] = '\0';
      *ptr += l;
      *ptr += l;
    }
    }
}
}


/* Find the index of the entry in the string table corresponding to
/* Find the index of the entry in the string table corresponding to
   STR; return -1 if one does not exist. */
   STR; return -1 if one does not exist. */
 
 
static short
static short
find_string_ent (const char *str)
find_string_ent (const char *str)
{
{
  short start = 0;
  short start = 0;
  short end = sizeof (ia64_strings) / sizeof (const char *);
  short end = sizeof (ia64_strings) / sizeof (const char *);
  short i = (start + end) / 2;
  short i = (start + end) / 2;
 
 
  if (strcmp (str, ia64_strings[end - 1]) > 0)
  if (strcmp (str, ia64_strings[end - 1]) > 0)
    {
    {
      return -1;
      return -1;
    }
    }
  while (start <= end)
  while (start <= end)
    {
    {
      int c = strcmp (str, ia64_strings[i]);
      int c = strcmp (str, ia64_strings[i]);
      if (c < 0)
      if (c < 0)
        {
        {
          end = i - 1;
          end = i - 1;
        }
        }
      else if (c == 0)
      else if (c == 0)
        {
        {
          return i;
          return i;
        }
        }
      else
      else
        {
        {
          start = i + 1;
          start = i + 1;
        }
        }
      i = (start + end) / 2;
      i = (start + end) / 2;
    }
    }
  return -1;
  return -1;
}
}


/* Find the opcode in the main opcode table whose name is STRINGINDEX, or
/* Find the opcode in the main opcode table whose name is STRINGINDEX, or
   return -1 if one does not exist. */
   return -1 if one does not exist. */
 
 
static short
static short
find_main_ent (short nameindex)
find_main_ent (short nameindex)
{
{
  short start = 0;
  short start = 0;
  short end = sizeof (main_table) / sizeof (struct ia64_main_table);
  short end = sizeof (main_table) / sizeof (struct ia64_main_table);
  short i = (start + end) / 2;
  short i = (start + end) / 2;
 
 
  if (nameindex < main_table[0].name_index
  if (nameindex < main_table[0].name_index
      || nameindex > main_table[end - 1].name_index)
      || nameindex > main_table[end - 1].name_index)
    {
    {
      return -1;
      return -1;
    }
    }
  while (start <= end)
  while (start <= end)
    {
    {
      if (nameindex < main_table[i].name_index)
      if (nameindex < main_table[i].name_index)
        {
        {
          end = i - 1;
          end = i - 1;
        }
        }
      else if (nameindex == main_table[i].name_index)
      else if (nameindex == main_table[i].name_index)
        {
        {
          while (i > 0 && main_table[i - 1].name_index == nameindex)
          while (i > 0 && main_table[i - 1].name_index == nameindex)
            {
            {
              i--;
              i--;
            }
            }
          return i;
          return i;
        }
        }
      else
      else
        {
        {
          start = i + 1;
          start = i + 1;
        }
        }
      i = (start + end) / 2;
      i = (start + end) / 2;
    }
    }
  return -1;
  return -1;
}
}


/* Find the index of the entry in the completer table that is part of
/* Find the index of the entry in the completer table that is part of
   MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or
   MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or
   return -1 if one does not exist. */
   return -1 if one does not exist. */
 
 
static short
static short
find_completer (short main_ent, short prev_completer, const char *name)
find_completer (short main_ent, short prev_completer, const char *name)
{
{
  short name_index = find_string_ent (name);
  short name_index = find_string_ent (name);
 
 
  if (name_index < 0)
  if (name_index < 0)
    {
    {
      return -1;
      return -1;
    }
    }
 
 
  if (prev_completer == -1)
  if (prev_completer == -1)
    {
    {
      prev_completer = main_table[main_ent].completers;
      prev_completer = main_table[main_ent].completers;
    }
    }
  else
  else
    {
    {
      prev_completer = completer_table[prev_completer].subentries;
      prev_completer = completer_table[prev_completer].subentries;
    }
    }
 
 
  while (prev_completer != -1)
  while (prev_completer != -1)
    {
    {
      if (completer_table[prev_completer].name_index == name_index)
      if (completer_table[prev_completer].name_index == name_index)
        {
        {
          return prev_completer;
          return prev_completer;
        }
        }
      prev_completer = completer_table[prev_completer].alternative;
      prev_completer = completer_table[prev_completer].alternative;
    }
    }
  return -1;
  return -1;
}
}


/* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
/* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
   return the result. */
   return the result. */
 
 
static ia64_insn
static ia64_insn
apply_completer (ia64_insn opcode, int completer_index)
apply_completer (ia64_insn opcode, int completer_index)
{
{
  ia64_insn mask = completer_table[completer_index].mask;
  ia64_insn mask = completer_table[completer_index].mask;
  ia64_insn bits = completer_table[completer_index].bits;
  ia64_insn bits = completer_table[completer_index].bits;
  int shiftamt = (completer_table[completer_index].offset & 63);
  int shiftamt = (completer_table[completer_index].offset & 63);
 
 
  mask = mask << shiftamt;
  mask = mask << shiftamt;
  bits = bits << shiftamt;
  bits = bits << shiftamt;
  opcode = (opcode & ~mask) | bits;
  opcode = (opcode & ~mask) | bits;
  return opcode;
  return opcode;
}
}


/* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in
/* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in
   the dis_table array, and return its value.  (BITOFFSET is numbered
   the dis_table array, and return its value.  (BITOFFSET is numbered
   starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the
   starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the
   first byte in OP_POINTER.) */
   first byte in OP_POINTER.) */
 
 
static int
static int
extract_op_bits (int op_pointer, int bitoffset, int bits)
extract_op_bits (int op_pointer, int bitoffset, int bits)
{
{
  int res = 0;
  int res = 0;
 
 
  op_pointer += (bitoffset / 8);
  op_pointer += (bitoffset / 8);
 
 
  if (bitoffset % 8)
  if (bitoffset % 8)
    {
    {
      unsigned int op = dis_table[op_pointer++];
      unsigned int op = dis_table[op_pointer++];
      int numb = 8 - (bitoffset % 8);
      int numb = 8 - (bitoffset % 8);
      int mask = (1 << numb) - 1;
      int mask = (1 << numb) - 1;
      int bata = (bits < numb) ? bits : numb;
      int bata = (bits < numb) ? bits : numb;
      int delta = numb - bata;
      int delta = numb - bata;
 
 
      res = (res << bata) | ((op & mask) >> delta);
      res = (res << bata) | ((op & mask) >> delta);
      bitoffset += bata;
      bitoffset += bata;
      bits -= bata;
      bits -= bata;
    }
    }
  while (bits >= 8)
  while (bits >= 8)
    {
    {
      res = (res << 8) | (dis_table[op_pointer++] & 255);
      res = (res << 8) | (dis_table[op_pointer++] & 255);
      bits -= 8;
      bits -= 8;
    }
    }
  if (bits > 0)
  if (bits > 0)
    {
    {
      unsigned int op = (dis_table[op_pointer++] & 255);
      unsigned int op = (dis_table[op_pointer++] & 255);
      res = (res << bits) | (op >> (8 - bits));
      res = (res << bits) | (op >> (8 - bits));
    }
    }
  return res;
  return res;
}
}


/* Examine the state machine entry at OP_POINTER in the dis_table
/* Examine the state machine entry at OP_POINTER in the dis_table
   array, and extract its values into OPVAL and OP.  The length of the
   array, and extract its values into OPVAL and OP.  The length of the
   state entry in bits is returned. */
   state entry in bits is returned. */
 
 
static int
static int
extract_op (int op_pointer, int *opval, unsigned int *op)
extract_op (int op_pointer, int *opval, unsigned int *op)
{
{
  int oplen = 5;
  int oplen = 5;
 
 
  *op = dis_table[op_pointer];
  *op = dis_table[op_pointer];
 
 
  if ((*op) & 0x40)
  if ((*op) & 0x40)
    {
    {
      opval[0] = extract_op_bits (op_pointer, oplen, 5);
      opval[0] = extract_op_bits (op_pointer, oplen, 5);
      oplen += 5;
      oplen += 5;
    }
    }
  switch ((*op) & 0x30)
  switch ((*op) & 0x30)
    {
    {
    case 0x10:
    case 0x10:
      {
      {
        opval[1] = extract_op_bits (op_pointer, oplen, 8);
        opval[1] = extract_op_bits (op_pointer, oplen, 8);
        oplen += 8;
        oplen += 8;
        opval[1] += op_pointer;
        opval[1] += op_pointer;
        break;
        break;
      }
      }
    case 0x20:
    case 0x20:
      {
      {
        opval[1] = extract_op_bits (op_pointer, oplen, 16);
        opval[1] = extract_op_bits (op_pointer, oplen, 16);
        if (! (opval[1] & 32768))
        if (! (opval[1] & 32768))
          {
          {
            opval[1] += op_pointer;
            opval[1] += op_pointer;
          }
          }
        oplen += 16;
        oplen += 16;
        break;
        break;
      }
      }
    case 0x30:
    case 0x30:
      {
      {
        oplen--;
        oplen--;
        opval[2] = extract_op_bits (op_pointer, oplen, 12);
        opval[2] = extract_op_bits (op_pointer, oplen, 12);
        oplen += 12;
        oplen += 12;
        opval[2] |= 32768;
        opval[2] |= 32768;
        break;
        break;
      }
      }
    }
    }
  if (((*op) & 0x08) && (((*op) & 0x30) != 0x30))
  if (((*op) & 0x08) && (((*op) & 0x30) != 0x30))
    {
    {
      opval[2] = extract_op_bits (op_pointer, oplen, 16);
      opval[2] = extract_op_bits (op_pointer, oplen, 16);
      oplen += 16;
      oplen += 16;
      if (! (opval[2] & 32768))
      if (! (opval[2] & 32768))
        {
        {
          opval[2] += op_pointer;
          opval[2] += op_pointer;
        }
        }
    }
    }
  return oplen;
  return oplen;
}
}


/* Returns a non-zero value if the opcode in the main_table list at
/* Returns a non-zero value if the opcode in the main_table list at
   PLACE matches OPCODE and is of type TYPE. */
   PLACE matches OPCODE and is of type TYPE. */
 
 
static int
static int
opcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type)
opcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type)
{
{
  if (main_table[place].opcode_type != type)
  if (main_table[place].opcode_type != type)
    {
    {
      return 0;
      return 0;
    }
    }
  if (main_table[place].flags
  if (main_table[place].flags
      & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT))
      & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT))
    {
    {
      const struct ia64_operand *o1, *o2;
      const struct ia64_operand *o1, *o2;
      ia64_insn f2, f3;
      ia64_insn f2, f3;
 
 
      if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3)
      if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3)
        {
        {
          o1 = elf64_ia64_operands + IA64_OPND_F2;
          o1 = elf64_ia64_operands + IA64_OPND_F2;
          o2 = elf64_ia64_operands + IA64_OPND_F3;
          o2 = elf64_ia64_operands + IA64_OPND_F3;
          (*o1->extract) (o1, opcode, &f2);
          (*o1->extract) (o1, opcode, &f2);
          (*o2->extract) (o2, opcode, &f3);
          (*o2->extract) (o2, opcode, &f3);
          if (f2 != f3)
          if (f2 != f3)
            return 0;
            return 0;
        }
        }
      else
      else
        {
        {
          ia64_insn len, count;
          ia64_insn len, count;
 
 
          /* length must equal 64-count: */
          /* length must equal 64-count: */
          o1 = elf64_ia64_operands + IA64_OPND_LEN6;
          o1 = elf64_ia64_operands + IA64_OPND_LEN6;
          o2 = elf64_ia64_operands + main_table[place].operands[2];
          o2 = elf64_ia64_operands + main_table[place].operands[2];
          (*o1->extract) (o1, opcode, &len);
          (*o1->extract) (o1, opcode, &len);
          (*o2->extract) (o2, opcode, &count);
          (*o2->extract) (o2, opcode, &count);
          if (len != 64 - count)
          if (len != 64 - count)
            return 0;
            return 0;
        }
        }
    }
    }
  return 1;
  return 1;
}
}


/* Find an instruction entry in the ia64_dis_names array that matches
/* Find an instruction entry in the ia64_dis_names array that matches
   opcode OPCODE and is of type TYPE.  Returns either a positive index
   opcode OPCODE and is of type TYPE.  Returns either a positive index
   into the array, or a negative value if an entry for OPCODE could
   into the array, or a negative value if an entry for OPCODE could
   not be found.  Checks all matches and returns the one with the highest
   not be found.  Checks all matches and returns the one with the highest
   priority. */
   priority. */
 
 
static int
static int
locate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type)
locate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type)
{
{
  int currtest[41];
  int currtest[41];
  int bitpos[41];
  int bitpos[41];
  int op_ptr[41];
  int op_ptr[41];
  int currstatenum = 0;
  int currstatenum = 0;
  short found_disent = -1;
  short found_disent = -1;
  short found_priority = -1;
  short found_priority = -1;
 
 
  currtest[currstatenum] = 0;
  currtest[currstatenum] = 0;
  op_ptr[currstatenum] = 0;
  op_ptr[currstatenum] = 0;
  bitpos[currstatenum] = 40;
  bitpos[currstatenum] = 40;
 
 
  while (1)
  while (1)
    {
    {
      int op_pointer = op_ptr[currstatenum];
      int op_pointer = op_ptr[currstatenum];
      unsigned int op;
      unsigned int op;
      int currbitnum = bitpos[currstatenum];
      int currbitnum = bitpos[currstatenum];
      int oplen;
      int oplen;
      int opval[3] = {0};
      int opval[3] = {0};
      int next_op;
      int next_op;
      int currbit;
      int currbit;
 
 
      oplen = extract_op (op_pointer, opval, &op);
      oplen = extract_op (op_pointer, opval, &op);
 
 
      bitpos[currstatenum] = currbitnum;
      bitpos[currstatenum] = currbitnum;
 
 
      /* Skip opval[0] bits in the instruction. */
      /* Skip opval[0] bits in the instruction. */
      if (op & 0x40)
      if (op & 0x40)
        {
        {
          currbitnum -= opval[0];
          currbitnum -= opval[0];
        }
        }
 
 
      /* The value of the current bit being tested. */
      /* The value of the current bit being tested. */
      currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0;
      currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0;
      next_op = -1;
      next_op = -1;
 
 
      /* We always perform the tests specified in the current state in
      /* We always perform the tests specified in the current state in
         a particular order, falling through to the next test if the
         a particular order, falling through to the next test if the
         previous one failed. */
         previous one failed. */
      switch (currtest[currstatenum])
      switch (currtest[currstatenum])
        {
        {
        case 0:
        case 0:
          currtest[currstatenum]++;
          currtest[currstatenum]++;
          if (currbit == 0 && (op & 0x80))
          if (currbit == 0 && (op & 0x80))
            {
            {
              /* Check for a zero bit.  If this test solely checks for
              /* Check for a zero bit.  If this test solely checks for
                 a zero bit, we can check for up to 8 consecutive zero
                 a zero bit, we can check for up to 8 consecutive zero
                 bits (the number to check is specified by the lower 3
                 bits (the number to check is specified by the lower 3
                 bits in the state code.)
                 bits in the state code.)
 
 
                 If the state instruction matches, we go to the very
                 If the state instruction matches, we go to the very
                 next state instruction; otherwise, try the next test. */
                 next state instruction; otherwise, try the next test. */
 
 
              if ((op & 0xf8) == 0x80)
              if ((op & 0xf8) == 0x80)
                {
                {
                  int count = op & 0x7;
                  int count = op & 0x7;
                  int x;
                  int x;
 
 
                  for (x = 0; x <= count; x++)
                  for (x = 0; x <= count; x++)
                    {
                    {
                      int i =
                      int i =
                        opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0;
                        opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0;
                      if (i)
                      if (i)
                        {
                        {
                          break;
                          break;
                        }
                        }
                    }
                    }
                  if (x > count)
                  if (x > count)
                    {
                    {
                      next_op = op_pointer + ((oplen + 7) / 8);
                      next_op = op_pointer + ((oplen + 7) / 8);
                      currbitnum -= count;
                      currbitnum -= count;
                      break;
                      break;
                    }
                    }
                }
                }
              else if (! currbit)
              else if (! currbit)
                {
                {
                  next_op = op_pointer + ((oplen + 7) / 8);
                  next_op = op_pointer + ((oplen + 7) / 8);
                  break;
                  break;
                }
                }
            }
            }
          /* FALLTHROUGH */
          /* FALLTHROUGH */
        case 1:
        case 1:
          /* If the bit in the instruction is one, go to the state
          /* If the bit in the instruction is one, go to the state
             instruction specified by opval[1]. */
             instruction specified by opval[1]. */
          currtest[currstatenum]++;
          currtest[currstatenum]++;
          if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30))
          if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30))
            {
            {
              next_op = opval[1];
              next_op = opval[1];
              break;
              break;
            }
            }
          /* FALLTHROUGH */
          /* FALLTHROUGH */
        case 2:
        case 2:
          /* Don't care.  Skip the current bit and go to the state
          /* Don't care.  Skip the current bit and go to the state
             instruction specified by opval[2].
             instruction specified by opval[2].
 
 
             An encoding of 0x30 is special; this means that a 12-bit
             An encoding of 0x30 is special; this means that a 12-bit
             offset into the ia64_dis_names[] array is specified.  */
             offset into the ia64_dis_names[] array is specified.  */
          currtest[currstatenum]++;
          currtest[currstatenum]++;
          if ((op & 0x08) || ((op & 0x30) == 0x30))
          if ((op & 0x08) || ((op & 0x30) == 0x30))
            {
            {
              next_op = opval[2];
              next_op = opval[2];
              break;
              break;
            }
            }
        }
        }
 
 
      /* If bit 15 is set in the address of the next state, an offset
      /* If bit 15 is set in the address of the next state, an offset
         in the ia64_dis_names array was specified instead.  We then
         in the ia64_dis_names array was specified instead.  We then
         check to see if an entry in the list of opcodes matches the
         check to see if an entry in the list of opcodes matches the
         opcode we were given; if so, we have succeeded.  */
         opcode we were given; if so, we have succeeded.  */
 
 
      if ((next_op >= 0) && (next_op & 32768))
      if ((next_op >= 0) && (next_op & 32768))
        {
        {
          short disent = next_op & 32767;
          short disent = next_op & 32767;
          short priority = -1;
          short priority = -1;
 
 
          if (next_op > 65535)
          if (next_op > 65535)
            {
            {
              abort ();
              abort ();
            }
            }
 
 
          /* Run through the list of opcodes to check, trying to find
          /* Run through the list of opcodes to check, trying to find
             one that matches.  */
             one that matches.  */
          while (disent >= 0)
          while (disent >= 0)
            {
            {
              int place = ia64_dis_names[disent].insn_index;
              int place = ia64_dis_names[disent].insn_index;
 
 
              priority = ia64_dis_names[disent].priority;
              priority = ia64_dis_names[disent].priority;
 
 
              if (opcode_verify (opcode, place, type)
              if (opcode_verify (opcode, place, type)
                  && priority > found_priority)
                  && priority > found_priority)
                {
                {
                  break;
                  break;
                }
                }
              if (ia64_dis_names[disent].next_flag)
              if (ia64_dis_names[disent].next_flag)
                {
                {
                  disent++;
                  disent++;
                }
                }
              else
              else
                {
                {
                  disent = -1;
                  disent = -1;
                }
                }
            }
            }
 
 
          if (disent >= 0)
          if (disent >= 0)
            {
            {
              found_disent = disent;
              found_disent = disent;
              found_priority = priority;
              found_priority = priority;
            }
            }
          /* Try the next test in this state, regardless of whether a match
          /* Try the next test in this state, regardless of whether a match
             was found. */
             was found. */
          next_op = -2;
          next_op = -2;
        }
        }
 
 
      /* next_op == -1 is "back up to the previous state".
      /* next_op == -1 is "back up to the previous state".
         next_op == -2 is "stay in this state and try the next test".
         next_op == -2 is "stay in this state and try the next test".
         Otherwise, transition to the state indicated by next_op. */
         Otherwise, transition to the state indicated by next_op. */
 
 
      if (next_op == -1)
      if (next_op == -1)
        {
        {
          currstatenum--;
          currstatenum--;
          if (currstatenum < 0)
          if (currstatenum < 0)
            {
            {
              return found_disent;
              return found_disent;
            }
            }
        }
        }
      else if (next_op >= 0)
      else if (next_op >= 0)
        {
        {
          currstatenum++;
          currstatenum++;
          bitpos[currstatenum] = currbitnum - 1;
          bitpos[currstatenum] = currbitnum - 1;
          op_ptr[currstatenum] = next_op;
          op_ptr[currstatenum] = next_op;
          currtest[currstatenum] = 0;
          currtest[currstatenum] = 0;
        }
        }
    }
    }
}
}


/* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
/* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
 
 
static struct ia64_opcode *
static struct ia64_opcode *
make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind)
make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind)
{
{
  struct ia64_opcode *res =
  struct ia64_opcode *res =
    (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode));
    (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode));
  res->name = xstrdup (name);
  res->name = xstrdup (name);
  res->type = main_table[place].opcode_type;
  res->type = main_table[place].opcode_type;
  res->num_outputs = main_table[place].num_outputs;
  res->num_outputs = main_table[place].num_outputs;
  res->opcode = opcode;
  res->opcode = opcode;
  res->mask = main_table[place].mask;
  res->mask = main_table[place].mask;
  res->operands[0] = main_table[place].operands[0];
  res->operands[0] = main_table[place].operands[0];
  res->operands[1] = main_table[place].operands[1];
  res->operands[1] = main_table[place].operands[1];
  res->operands[2] = main_table[place].operands[2];
  res->operands[2] = main_table[place].operands[2];
  res->operands[3] = main_table[place].operands[3];
  res->operands[3] = main_table[place].operands[3];
  res->operands[4] = main_table[place].operands[4];
  res->operands[4] = main_table[place].operands[4];
  res->flags = main_table[place].flags;
  res->flags = main_table[place].flags;
  res->ent_index = place;
  res->ent_index = place;
  res->dependencies = &op_dependencies[depind];
  res->dependencies = &op_dependencies[depind];
  return res;
  return res;
}
}


/* Determine the ia64_opcode entry for the opcode specified by INSN
/* Determine the ia64_opcode entry for the opcode specified by INSN
   and TYPE.  If a valid entry is not found, return NULL. */
   and TYPE.  If a valid entry is not found, return NULL. */
struct ia64_opcode *
struct ia64_opcode *
ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type)
ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type)
{
{
  int disent = locate_opcode_ent (insn, type);
  int disent = locate_opcode_ent (insn, type);
 
 
  if (disent < 0)
  if (disent < 0)
    {
    {
      return NULL;
      return NULL;
    }
    }
  else
  else
    {
    {
      unsigned int cb = ia64_dis_names[disent].completer_index;
      unsigned int cb = ia64_dis_names[disent].completer_index;
      static char name[128];
      static char name[128];
      int place = ia64_dis_names[disent].insn_index;
      int place = ia64_dis_names[disent].insn_index;
      int ci = main_table[place].completers;
      int ci = main_table[place].completers;
      ia64_insn tinsn = main_table[place].opcode;
      ia64_insn tinsn = main_table[place].opcode;
 
 
      strcpy (name, ia64_strings [main_table[place].name_index]);
      strcpy (name, ia64_strings [main_table[place].name_index]);
 
 
      while (cb)
      while (cb)
        {
        {
          if (cb & 1)
          if (cb & 1)
            {
            {
              int cname = completer_table[ci].name_index;
              int cname = completer_table[ci].name_index;
 
 
              tinsn = apply_completer (tinsn, ci);
              tinsn = apply_completer (tinsn, ci);
 
 
              if (ia64_strings[cname][0] != '\0')
              if (ia64_strings[cname][0] != '\0')
                {
                {
                  strcat (name, ".");
                  strcat (name, ".");
                  strcat (name, ia64_strings[cname]);
                  strcat (name, ia64_strings[cname]);
                }
                }
              if (cb != 1)
              if (cb != 1)
                {
                {
                  ci = completer_table[ci].subentries;
                  ci = completer_table[ci].subentries;
                }
                }
            }
            }
          else
          else
            {
            {
              ci = completer_table[ci].alternative;
              ci = completer_table[ci].alternative;
            }
            }
          if (ci < 0)
          if (ci < 0)
            {
            {
              abort ();
              abort ();
            }
            }
          cb = cb >> 1;
          cb = cb >> 1;
        }
        }
      if (tinsn != (insn & main_table[place].mask))
      if (tinsn != (insn & main_table[place].mask))
        {
        {
          abort ();
          abort ();
        }
        }
      return make_ia64_opcode (insn, name, place,
      return make_ia64_opcode (insn, name, place,
                               completer_table[ci].dependencies);
                               completer_table[ci].dependencies);
    }
    }
}
}


/* Search the main_opcode table starting from PLACE for an opcode that
/* Search the main_opcode table starting from PLACE for an opcode that
   matches NAME.  Return NULL if one is not found. */
   matches NAME.  Return NULL if one is not found. */
 
 
static struct ia64_opcode *
static struct ia64_opcode *
ia64_find_matching_opcode (const char *name, short place)
ia64_find_matching_opcode (const char *name, short place)
{
{
  char op[129];
  char op[129];
  const char *suffix;
  const char *suffix;
  short name_index;
  short name_index;
 
 
  if (strlen (name) > 128)
  if (strlen (name) > 128)
    {
    {
      return NULL;
      return NULL;
    }
    }
  suffix = name;
  suffix = name;
  get_opc_prefix (&suffix, op);
  get_opc_prefix (&suffix, op);
  name_index = find_string_ent (op);
  name_index = find_string_ent (op);
  if (name_index < 0)
  if (name_index < 0)
    {
    {
      return NULL;
      return NULL;
    }
    }
 
 
  while (main_table[place].name_index == name_index)
  while (main_table[place].name_index == name_index)
    {
    {
      const char *curr_suffix = suffix;
      const char *curr_suffix = suffix;
      ia64_insn curr_insn = main_table[place].opcode;
      ia64_insn curr_insn = main_table[place].opcode;
      short completer = -1;
      short completer = -1;
 
 
      do {
      do {
        if (suffix[0] == '\0')
        if (suffix[0] == '\0')
          {
          {
            completer = find_completer (place, completer, suffix);
            completer = find_completer (place, completer, suffix);
          }
          }
        else
        else
          {
          {
            get_opc_prefix (&curr_suffix, op);
            get_opc_prefix (&curr_suffix, op);
            completer = find_completer (place, completer, op);
            completer = find_completer (place, completer, op);
          }
          }
        if (completer != -1)
        if (completer != -1)
          {
          {
            curr_insn = apply_completer (curr_insn, completer);
            curr_insn = apply_completer (curr_insn, completer);
          }
          }
      } while (completer != -1 && curr_suffix[0] != '\0');
      } while (completer != -1 && curr_suffix[0] != '\0');
 
 
      if (completer != -1 && curr_suffix[0] == '\0'
      if (completer != -1 && curr_suffix[0] == '\0'
          && completer_table[completer].terminal_completer)
          && completer_table[completer].terminal_completer)
        {
        {
          int depind = completer_table[completer].dependencies;
          int depind = completer_table[completer].dependencies;
          return make_ia64_opcode (curr_insn, name, place, depind);
          return make_ia64_opcode (curr_insn, name, place, depind);
        }
        }
      else
      else
        {
        {
          place++;
          place++;
        }
        }
    }
    }
  return NULL;
  return NULL;
}
}


/* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
/* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
   if one does not exist.
   if one does not exist.
 
 
   It is the caller's responsibility to invoke ia64_free_opcode () to
   It is the caller's responsibility to invoke ia64_free_opcode () to
   release any resources used by the returned entry. */
   release any resources used by the returned entry. */
 
 
struct ia64_opcode *
struct ia64_opcode *
ia64_find_next_opcode (struct ia64_opcode *prev_ent)
ia64_find_next_opcode (struct ia64_opcode *prev_ent)
{
{
  return ia64_find_matching_opcode (prev_ent->name,
  return ia64_find_matching_opcode (prev_ent->name,
                                    prev_ent->ent_index + 1);
                                    prev_ent->ent_index + 1);
}
}
 
 
/* Find the first opcode that matches NAME, or return NULL if it does
/* Find the first opcode that matches NAME, or return NULL if it does
   not exist.
   not exist.
 
 
   It is the caller's responsibility to invoke ia64_free_opcode () to
   It is the caller's responsibility to invoke ia64_free_opcode () to
   release any resources used by the returned entry. */
   release any resources used by the returned entry. */
 
 
struct ia64_opcode *
struct ia64_opcode *
ia64_find_opcode (const char *name)
ia64_find_opcode (const char *name)
{
{
  char op[129];
  char op[129];
  const char *suffix;
  const char *suffix;
  short place;
  short place;
  short name_index;
  short name_index;
 
 
  if (strlen (name) > 128)
  if (strlen (name) > 128)
    {
    {
      return NULL;
      return NULL;
    }
    }
  suffix = name;
  suffix = name;
  get_opc_prefix (&suffix, op);
  get_opc_prefix (&suffix, op);
  name_index = find_string_ent (op);
  name_index = find_string_ent (op);
  if (name_index < 0)
  if (name_index < 0)
    {
    {
      return NULL;
      return NULL;
    }
    }
 
 
  place = find_main_ent (name_index);
  place = find_main_ent (name_index);
 
 
  if (place < 0)
  if (place < 0)
    {
    {
      return NULL;
      return NULL;
    }
    }
  return ia64_find_matching_opcode (name, place);
  return ia64_find_matching_opcode (name, place);
}
}
 
 
/* Free any resources used by ENT. */
/* Free any resources used by ENT. */
void
void
ia64_free_opcode (struct ia64_opcode *ent)
ia64_free_opcode (struct ia64_opcode *ent)
{
{
  free ((void *)ent->name);
  free ((void *)ent->name);
  free (ent);
  free (ent);
}
}
 
 
const struct ia64_dependency *
const struct ia64_dependency *
ia64_find_dependency (int dep_index)
ia64_find_dependency (int dep_index)
{
{
  dep_index = DEP(dep_index);
  dep_index = DEP(dep_index);
 
 
  if (dep_index < 0
  if (dep_index < 0
      || dep_index >= (int) ARRAY_SIZE (dependencies))
      || dep_index >= (int) ARRAY_SIZE (dependencies))
    return NULL;
    return NULL;
 
 
  return &dependencies[dep_index];
  return &dependencies[dep_index];
}
}
 
 

powered by: WebSVN 2.1.0

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