Back to index

cell-binutils  2.17cvs20070401
Functions
ia64-opc.c File Reference
#include "ansidecl.h"
#include "sysdep.h"
#include "libiberty.h"
#include "ia64-asmtab.h"
#include "ia64-asmtab.c"

Go to the source code of this file.

Functions

static void get_opc_prefix (const char **, char *)
static short int find_string_ent (const char *)
static short int find_main_ent (short int)
static short int find_completer (short int, short int, const char *)
static ia64_insn apply_completer (ia64_insn, int)
static int extract_op_bits (int, int, int)
static int extract_op (int, int *, unsigned int *)
static int opcode_verify (ia64_insn, int, enum ia64_insn_type)
static int locate_opcode_ent (ia64_insn, enum ia64_insn_type)
static struct ia64_opcodemake_ia64_opcode (ia64_insn, const char *, int, int)
static struct ia64_opcodeia64_find_matching_opcode (const char *, short int)
struct ia64_opcodeia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type)
struct ia64_opcodeia64_find_next_opcode (struct ia64_opcode *prev_ent)
struct ia64_opcodeia64_find_opcode (const char *name)
void ia64_free_opcode (struct ia64_opcode *ent)
struct ia64_dependencyia64_find_dependency (int index)

Function Documentation

static ia64_insn apply_completer ( ia64_insn  opcode,
int  completer_index 
) [static]

Definition at line 196 of file ia64-opc.c.

{
  ia64_insn mask = completer_table[completer_index].mask;
  ia64_insn bits = completer_table[completer_index].bits;
  int shiftamt = (completer_table[completer_index].offset & 63);

  mask = mask << shiftamt;
  bits = bits << shiftamt;
  opcode = (opcode & ~mask) | bits;
  return opcode;
}

Here is the caller graph for this function:

static int extract_op ( int  op_pointer,
int opval,
unsigned int op 
) [static]

Definition at line 250 of file ia64-opc.c.

{
  int oplen = 5;

  *op = dis_table[op_pointer];

  if ((*op) & 0x40)
    {
      opval[0] = extract_op_bits (op_pointer, oplen, 5);
      oplen += 5;
    }
  switch ((*op) & 0x30)
    {
    case 0x10:
      {
       opval[1] = extract_op_bits (op_pointer, oplen, 8);
       oplen += 8;
       opval[1] += op_pointer;
       break;
      }
    case 0x20:
      {
       opval[1] = extract_op_bits (op_pointer, oplen, 16);
       if (! (opval[1] & 32768))
         {
           opval[1] += op_pointer;
         }
       oplen += 16;
       break;
      }
    case 0x30:
      {
       oplen--;
       opval[2] = extract_op_bits (op_pointer, oplen, 12);
       oplen += 12;
       opval[2] |= 32768;
       break;
      }
    }
  if (((*op) & 0x08) && (((*op) & 0x30) != 0x30))
    {
      opval[2] = extract_op_bits (op_pointer, oplen, 16);
      oplen += 16;
      if (! (opval[2] & 32768))
       {
         opval[2] += op_pointer;
       }
    }
  return oplen;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int extract_op_bits ( int  op_pointer,
int  bitoffset,
int  bits 
) [static]

Definition at line 214 of file ia64-opc.c.

{
  int res = 0;

  op_pointer += (bitoffset / 8);

  if (bitoffset % 8)
    {
      unsigned int op = dis_table[op_pointer++];
      int numb = 8 - (bitoffset % 8);
      int mask = (1 << numb) - 1;
      int bata = (bits < numb) ? bits : numb;
      int delta = numb - bata;

      res = (res << bata) | ((op & mask) >> delta);
      bitoffset += bata;
      bits -= bata;
    }
  while (bits >= 8)
    {
      res = (res << 8) | (dis_table[op_pointer++] & 255);
      bits -= 8;
    }
  if (bits > 0)
    {
      unsigned int op = (dis_table[op_pointer++] & 255);
      res = (res << bits) | (op >> (8 - bits));
    }
  return res;
}

Here is the caller graph for this function:

static short find_completer ( short  int,
short  int,
const char *  name 
) [static]

Definition at line 163 of file ia64-opc.c.

{
  short name_index = find_string_ent (name);

  if (name_index < 0)
    {
      return -1;
    }

  if (prev_completer == -1)
    {
      prev_completer = main_table[main_ent].completers;
    }
  else
    {
      prev_completer = completer_table[prev_completer].subentries;
    }

  while (prev_completer != -1)
    {
      if (completer_table[prev_completer].name_index == name_index)
       {
         return prev_completer;
       }
      prev_completer = completer_table[prev_completer].alternative;
    }
  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static short find_main_ent ( short  int) [static]

Definition at line 124 of file ia64-opc.c.

{
  short start = 0;
  short end = sizeof (main_table) / sizeof (struct ia64_main_table);
  short i = (start + end) / 2;

  if (nameindex < main_table[0].name_index
      || nameindex > main_table[end - 1].name_index)
    {
      return -1;
    }
  while (start <= end)
    {
      if (nameindex < main_table[i].name_index)
       {
         end = i - 1;
       }
      else if (nameindex == main_table[i].name_index)
       {
         while (i > 0 && main_table[i - 1].name_index == nameindex)
           {
             i--;
           }
         return i;
       }
      else
       {
         start = i + 1;
       }
      i = (start + end) / 2;
    }
  return -1;
}

Here is the caller graph for this function:

static short find_string_ent ( const char *  str) [static]

Definition at line 90 of file ia64-opc.c.

{
  short start = 0;
  short end = sizeof (ia64_strings) / sizeof (const char *);
  short i = (start + end) / 2;

  if (strcmp (str, ia64_strings[end - 1]) > 0)
    {
      return -1;
    }
  while (start <= end)
    {
      int c = strcmp (str, ia64_strings[i]);
      if (c < 0)
       {
         end = i - 1;
       }
      else if (c == 0)
       {
         return i;
       }
      else
       {
         start = i + 1;
       }
      i = (start + end) / 2;
    }
  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void get_opc_prefix ( const char **  ptr,
char *  dest 
) [static]

Definition at line 68 of file ia64-opc.c.

{
  char *c = strchr (*ptr, '.');
  if (c != NULL)
    {
      memcpy (dest, *ptr, c - *ptr);
      dest[c - *ptr] = '\0';
      *ptr = c + 1;
    }
  else
    {
      int l = strlen (*ptr);
      memcpy (dest, *ptr, l);
      dest[l] = '\0';
      *ptr += l;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct ia64_opcode* ia64_dis_opcode ( ia64_insn  insn,
enum ia64_insn_type  type 
) [read]

Definition at line 551 of file ia64-opc.c.

{
  int disent = locate_opcode_ent (insn, type);

  if (disent < 0)
    {
      return NULL;
    }
  else
    {
      unsigned int cb = ia64_dis_names[disent].completer_index;
      static char name[128];
      int place = ia64_dis_names[disent].insn_index;
      int ci = main_table[place].completers;
      ia64_insn tinsn = main_table[place].opcode;

      strcpy (name, ia64_strings [main_table[place].name_index]);

      while (cb)
       {
         if (cb & 1)
           {
             int cname = completer_table[ci].name_index;

             tinsn = apply_completer (tinsn, ci);

             if (ia64_strings[cname][0] != '\0')
              {
                strcat (name, ".");
                strcat (name, ia64_strings[cname]);
              }
             if (cb != 1)
              {
                ci = completer_table[ci].subentries;
              }
           }
         else
           {
             ci = completer_table[ci].alternative;
           }
         if (ci < 0)
           {
             abort ();
           }
         cb = cb >> 1;
       }
      if (tinsn != (insn & main_table[place].mask))
       {
         abort ();
       }
      return make_ia64_opcode (insn, name, place,
                               completer_table[ci].dependencies);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 721 of file ia64-opc.c.

{
  index = DEP(index);

  if (index < 0
      || index >= (int)(sizeof(dependencies) / sizeof(dependencies[0])))
    return NULL;

  return &dependencies[index];
}

Here is the caller graph for this function:

static struct ia64_opcode * ia64_find_matching_opcode ( const char *  name,
short  int 
) [static, read]

Definition at line 610 of file ia64-opc.c.

{
  char op[129];
  const char *suffix;
  short name_index;

  if (strlen (name) > 128)
    {
      return NULL;
    }
  suffix = name;
  get_opc_prefix (&suffix, op);
  name_index = find_string_ent (op);
  if (name_index < 0)
    {
      return NULL;
    }

  while (main_table[place].name_index == name_index)
    {
      const char *curr_suffix = suffix;
      ia64_insn curr_insn = main_table[place].opcode;
      short completer = -1;

      do {
       if (suffix[0] == '\0')
         {
           completer = find_completer (place, completer, suffix);
         }
       else
         {
           get_opc_prefix (&curr_suffix, op);
           completer = find_completer (place, completer, op);
         }
       if (completer != -1)
         {
           curr_insn = apply_completer (curr_insn, completer);
         }
      } while (completer != -1 && curr_suffix[0] != '\0');

      if (completer != -1 && curr_suffix[0] == '\0'
         && completer_table[completer].terminal_completer)
       {
          int depind = completer_table[completer].dependencies;
         return make_ia64_opcode (curr_insn, name, place, depind);
       }
      else
       {
         place++;
       }
    }
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 671 of file ia64-opc.c.

{
  return ia64_find_matching_opcode (prev_ent->name,
                                prev_ent->ent_index + 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

struct ia64_opcode* ia64_find_opcode ( const char *  name) [read]

Definition at line 684 of file ia64-opc.c.

{
  char op[129];
  const char *suffix;
  short place;
  short name_index;

  if (strlen (name) > 128)
    {
      return NULL;
    }
  suffix = name;
  get_opc_prefix (&suffix, op);
  name_index = find_string_ent (op);
  if (name_index < 0)
    {
      return NULL;
    }

  place = find_main_ent (name_index);

  if (place < 0)
    {
      return NULL;
    }
  return ia64_find_matching_opcode (name, place);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 714 of file ia64-opc.c.

{
  free ((void *)ent->name);
  free (ent);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int locate_opcode_ent ( ia64_insn  opcode,
enum ia64_insn_type  type 
) [static]

Definition at line 349 of file ia64-opc.c.

{
  int currtest[41];
  int bitpos[41];
  int op_ptr[41];
  int currstatenum = 0;
  short found_disent = -1;
  short found_priority = -1;

  currtest[currstatenum] = 0;
  op_ptr[currstatenum] = 0;
  bitpos[currstatenum] = 40;

  while (1)
    {
      int op_pointer = op_ptr[currstatenum];
      unsigned int op;
      int currbitnum = bitpos[currstatenum];
      int oplen;
      int opval[3] = {0};
      int next_op;
      int currbit;

      oplen = extract_op (op_pointer, opval, &op);

      bitpos[currstatenum] = currbitnum;

      /* Skip opval[0] bits in the instruction. */
      if (op & 0x40)
       {
         currbitnum -= opval[0];
       }

      /* The value of the current bit being tested. */
      currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0;
      next_op = -1;

      /* We always perform the tests specified in the current state in
        a particular order, falling through to the next test if the
        previous one failed. */
      switch (currtest[currstatenum])
       {
       case 0:
         currtest[currstatenum]++;
         if (currbit == 0 && (op & 0x80))
           {
             /* Check for a zero bit.  If this test solely checks for
               a zero bit, we can check for up to 8 consecutive zero
               bits (the number to check is specified by the lower 3
               bits in the state code.)

               If the state instruction matches, we go to the very
               next state instruction; otherwise, try the next test. */

             if ((op & 0xf8) == 0x80)
              {
                int count = op & 0x7;
                int x;

                for (x = 0; x <= count; x++)
                  {
                    int i =
                     opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0;
                    if (i)
                     {
                       break;
                     }
                  }
                if (x > count)
                  {
                    next_op = op_pointer + ((oplen + 7) / 8);
                    currbitnum -= count;
                    break;
                  }
              }
             else if (! currbit)
              {
                next_op = op_pointer + ((oplen + 7) / 8);
                break;
              }
           }
         /* FALLTHROUGH */
       case 1:
         /* If the bit in the instruction is one, go to the state
            instruction specified by opval[1]. */
         currtest[currstatenum]++;
         if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30))
           {
             next_op = opval[1];
             break;
           }
         /* FALLTHROUGH */
       case 2:
         /* Don't care.  Skip the current bit and go to the state
            instruction specified by opval[2].

            An encoding of 0x30 is special; this means that a 12-bit
            offset into the ia64_dis_names[] array is specified.  */
         currtest[currstatenum]++;
         if ((op & 0x08) || ((op & 0x30) == 0x30))
           {
             next_op = opval[2];
             break;
           }
       }

      /* 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
        check to see if an entry in the list of opcodes matches the
        opcode we were given; if so, we have succeeded.  */

      if ((next_op >= 0) && (next_op & 32768))
       {
         short disent = next_op & 32767;
          short priority = -1;

         if (next_op > 65535)
           {
             abort ();
           }

         /* Run through the list of opcodes to check, trying to find
            one that matches.  */
         while (disent >= 0)
           {
             int place = ia64_dis_names[disent].insn_index;

              priority = ia64_dis_names[disent].priority;

             if (opcode_verify (opcode, place, type)
                  && priority > found_priority)
              {
                break;
              }
             if (ia64_dis_names[disent].next_flag)
              {
                disent++;
              }
             else
              {
                disent = -1;
              }
           }

         if (disent >= 0)
           {
              found_disent = disent;
              found_priority = priority;
           }
          /* Try the next test in this state, regardless of whether a match
             was found. */
          next_op = -2;
       }

      /* next_op == -1 is "back up to the previous state".
        next_op == -2 is "stay in this state and try the next test".
        Otherwise, transition to the state indicated by next_op. */

      if (next_op == -1)
       {
         currstatenum--;
         if (currstatenum < 0)
           {
              return found_disent;
           }
       }
      else if (next_op >= 0)
       {
         currstatenum++;
         bitpos[currstatenum] = currbitnum - 1;
         op_ptr[currstatenum] = next_op;
         currtest[currstatenum] = 0;
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct ia64_opcode * make_ia64_opcode ( ia64_insn  opcode,
const char *  name,
int  place,
int  depind 
) [static, read]

Definition at line 528 of file ia64-opc.c.

{
  struct ia64_opcode *res =
    (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode));
  res->name = xstrdup (name);
  res->type = main_table[place].opcode_type;
  res->num_outputs = main_table[place].num_outputs;
  res->opcode = opcode;
  res->mask = main_table[place].mask;
  res->operands[0] = main_table[place].operands[0];
  res->operands[1] = main_table[place].operands[1];
  res->operands[2] = main_table[place].operands[2];
  res->operands[3] = main_table[place].operands[3];
  res->operands[4] = main_table[place].operands[4];
  res->flags = main_table[place].flags;
  res->ent_index = place;
  res->dependencies = &op_dependencies[depind];
  return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int opcode_verify ( ia64_insn  opcode,
int  place,
enum ia64_insn_type  type 
) [static]

Definition at line 305 of file ia64-opc.c.

{
  if (main_table[place].opcode_type != type)
    {
      return 0;
    }
  if (main_table[place].flags
      & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT))
    {
      const struct ia64_operand *o1, *o2;
      ia64_insn f2, f3;

      if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3)
       {
         o1 = elf64_ia64_operands + IA64_OPND_F2;
         o2 = elf64_ia64_operands + IA64_OPND_F3;
         (*o1->extract) (o1, opcode, &f2);
         (*o2->extract) (o2, opcode, &f3);
         if (f2 != f3)
           return 0;
       }
      else
       {
         ia64_insn len, count;

         /* length must equal 64-count: */
         o1 = elf64_ia64_operands + IA64_OPND_LEN6;
         o2 = elf64_ia64_operands + main_table[place].operands[2];
         (*o1->extract) (o1, opcode, &len);
         (*o2->extract) (o2, opcode, &count);
         if (len != 64 - count)
           return 0;
       }
    }
  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function: