Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
or32-opc.c File Reference
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "safe-ctype.h"
#include "ansidecl.h"
#include "opcode/or32.h"

Go to the source code of this file.

Classes

struct  temp_insn_struct

Defines

#define EFN   &l_none
#define EF(func)   EFN
#define EFI   EFN
#define MAX_AUTOMATA_SIZE   1200
#define MAX_OP_TABLE_SIZE   1200
#define LEAF_FLAG   0x80000000
#define MAX_LEN   8
#define MIN(x, y)   ((x) < (y) ? (x) : (y))

Functions

static void ATTRIBUTE_PRINTF_2 debug (int level ATTRIBUTE_UNUSED, const char *format ATTRIBUTE_UNUSED,...)
int insn_len (int insn_index ATTRIBUTE_UNUSED)
int letter_signed (char l)
int letter_range (char l)
int insn_index (char *insn)
const char * insn_name (int index)
void l_none (void)
static unsigned long insn_extract (char param_ch, char *enc_initial)
static unsigned longcover_insn (unsigned long *cur, int pass, unsigned int mask)
static int num_ones (unsigned long value)
static struct insn_op_structparse_params (const struct or32_opcode *opcode, struct insn_op_struct *cur)
void build_automata (void)
void destruct_automata (void)
int insn_decode (unsigned int insn)
static unsigned long extend_imm (unsigned long imm, char l)
static unsigned long or32_extract (char param_ch, char *enc_initial, unsigned long insn)
static void or32_print_register (char param_ch, char *encoding, unsigned long insn)
static void or32_print_immediate (char param_ch, char *encoding, unsigned long insn)
int disassemble_insn (unsigned long insn)

Variables

const unsigned int or32_num_opcodes = ((sizeof(or32_opcodes)) / (sizeof(struct or32_opcode))) - 1
unsigned longautomata
int nuncovered
int curpass = 0
struct temp_insn_structti
struct insn_op_structop_data
struct insn_op_struct ** op_start
static char disassembled_str [50]
char * disassembled = &disassembled_str[0]

Class Documentation

struct temp_insn_struct

Definition at line 477 of file or32-opc.c.

Class Members
int in_pass
unsigned long insn
unsigned long insn_mask

Define Documentation

#define EF (   func)    EFN

Definition at line 66 of file or32-opc.c.

#define EFI   EFN

Definition at line 67 of file or32-opc.c.

#define EFN   &l_none

Definition at line 60 of file or32-opc.c.

#define LEAF_FLAG   0x80000000

Definition at line 465 of file or32-opc.c.

#define MAX_AUTOMATA_SIZE   1200

Definition at line 463 of file or32-opc.c.

#define MAX_LEN   8

Definition at line 466 of file or32-opc.c.

#define MAX_OP_TABLE_SIZE   1200

Definition at line 464 of file or32-opc.c.

#define MIN (   x,
  y 
)    ((x) < (y) ? (x) : (y))

Definition at line 469 of file or32-opc.c.


Function Documentation

void build_automata ( void  )

Definition at line 738 of file or32-opc.c.

{
  unsigned int i;
  unsigned long *end;
  struct insn_op_struct *cur;
  
  automata = malloc (MAX_AUTOMATA_SIZE * sizeof (unsigned long));
  ti = malloc (sizeof (struct temp_insn_struct) * or32_num_opcodes);

  nuncovered = or32_num_opcodes;
  printf ("Building automata... ");
  /* Build temporary information about instructions.  */
  for (i = 0; i < or32_num_opcodes; i++)
    {
      unsigned long ones, zeros;
      char *encoding = or32_opcodes[i].encoding;

      ones  = insn_extract('1', encoding);
      zeros = insn_extract('0', encoding);

      ti[i].insn_mask = ones | zeros;
      ti[i].insn = ones;
      ti[i].in_pass = curpass = 0;

      /*debug(9, "%s: %s %08X %08X\n", or32_opcodes[i].name,
       or32_opcodes[i].encoding, ti[i].insn_mask, ti[i].insn);*/
    }
  
  /* Until all are covered search for best criteria to separate them.  */
  end = cover_insn (automata, curpass, 0xFFFFFFFF);

  if (end - automata > MAX_AUTOMATA_SIZE)
    {
      fprintf (stderr, "Automata too large. Increase MAX_AUTOMATA_SIZE.");
      exit (1);
    }

  printf ("done, num uncovered: %i/%i.\n", nuncovered, or32_num_opcodes);
  printf ("Parsing operands data... ");

  op_data = malloc (MAX_OP_TABLE_SIZE * sizeof (struct insn_op_struct));
  op_start = malloc (or32_num_opcodes * sizeof (struct insn_op_struct *));
  cur = op_data;

  for (i = 0; i < or32_num_opcodes; i++)
    {
      op_start[i] = cur;
      cur = parse_params (&or32_opcodes[i], cur);

      if (cur - op_data > MAX_OP_TABLE_SIZE)
       {
         fprintf (stderr, "Operands table too small, increase MAX_OP_TABLE_SIZE.\n");
         exit (1);
       }
    }
  printf ("done.\n");
}

Here is the call graph for this function:

static unsigned long* cover_insn ( unsigned long cur,
int  pass,
unsigned int  mask 
) [static]

Definition at line 489 of file or32-opc.c.

{
  int best_first = 0, last_match = -1, ninstr = 0;
  unsigned int best_len = 0;
  unsigned int i;
  unsigned long cur_mask = mask;
  unsigned long *next;

  for (i = 0; i < or32_num_opcodes; i++)
    if (ti[i].in_pass == pass)
      {
       cur_mask &= ti[i].insn_mask;
       ninstr++;
       last_match = i;
      }
  
  debug (8, "%08X %08lX\n", mask, cur_mask);

  if (ninstr == 0)
    return 0;

  if (ninstr == 1)
    {
      /* Leaf holds instruction index.  */
      debug (8, "%li>I%i %s\n",
            (long)(cur - automata), last_match, or32_opcodes[last_match].name);

      *cur = LEAF_FLAG | last_match;
      cur++;
      nuncovered--;
    }
  else
    {
      /* Find longest match.  */
      for (i = 0; i < 32; i++)
       {
         unsigned int len;

         for (len = best_len + 1; len < MIN (MAX_LEN, 33 - i); len++)
           {
             unsigned long m = (1UL << ((unsigned long) len)) - 1;

             debug (9, " (%i(%08lX & %08lX>>%i = %08lX, %08lX)",
                   len,m, cur_mask, i, (cur_mask >> (unsigned)i),
                   (cur_mask >> (unsigned) i) & m);

             if ((m & (cur_mask >> (unsigned) i)) == m)
              {
                best_len = len;
                best_first = i;
                debug (9, "!");
              }
             else
              break;
           }
       }

      debug (9, "\n");

      if (!best_len)
       {
         fprintf (stderr, "%i instructions match mask 0x%08X:\n", ninstr, mask);

         for (i = 0; i < or32_num_opcodes; i++)
           if (ti[i].in_pass == pass)
             fprintf (stderr, "%s ", or32_opcodes[i].name);
         
         fprintf (stderr, "\n");
         exit (1);
       }

      debug (8, "%li> #### %i << %i (%i) ####\n",
            (long)(cur - automata), best_len, best_first, ninstr);

      *cur = best_first;
      cur++;
      *cur = (1 << best_len) - 1;
      cur++;
      next = cur;    

      /* Allocate space for pointers.  */
      cur += 1 << best_len;
      cur_mask = (1 << (unsigned long) best_len) - 1;
      
      for (i = 0; i < ((unsigned) 1 << best_len); i++)
       {
         unsigned int j;
         unsigned long *c;

         curpass++;
         for (j = 0; j < or32_num_opcodes; j++)
           if (ti[j].in_pass == pass
              && ((ti[j].insn >> best_first) & cur_mask) == (unsigned long) i
              && ((ti[j].insn_mask >> best_first) & cur_mask) == cur_mask)
             ti[j].in_pass = curpass;

         debug (9, "%08X %08lX %i\n", mask, cur_mask, best_first);
         c = cover_insn (cur, curpass, mask & (~(cur_mask << best_first)));
         if (c)
           {
             debug (8, "%li> #%X -> %lu\n", (long)(next - automata), i, (long)(cur - automata));
             *next = cur - automata;
             cur = c;        
           }
         else 
           {
             debug (8, "%li> N/A\n", (long)(next - automata));
             *next = 0;
           }
         next++;
       }
    }
  return cur;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ATTRIBUTE_PRINTF_2 debug ( int level  ATTRIBUTE_UNUSED,
const char *format  ATTRIBUTE_UNUSED,
  ... 
) [static]

Definition at line 338 of file or32-opc.c.

{
}
void destruct_automata ( void  )

Definition at line 797 of file or32-opc.c.

Here is the call graph for this function:

Definition at line 981 of file or32-opc.c.

{
  int index;
  index = insn_decode (insn);

  if (index >= 0)
    {
      struct or32_opcode const *opcode = &or32_opcodes[index];
      char *s;

      sprintf (disassembled, "%s ", opcode->name);
      for (s = opcode->args; *s != '\0'; ++s)
        {
          switch (*s)
            {
            case '\0':
              return 4;
  
            case 'r':
              or32_print_register (*++s, opcode->encoding, insn);
              break;
  
            default:
              if (strchr (opcode->encoding, *s))
                or32_print_immediate (*s, opcode->encoding, insn);
              else
                sprintf (disassembled, "%s%c", disassembled, *s);
            }
        }
    }
  else
    {
      /* This used to be %8x for binutils.  */
      sprintf (disassembled, "%s.word 0x%08lx", disassembled, insn);
    }

  return insn_len (insn);
}

Here is the call graph for this function:

static unsigned long extend_imm ( unsigned long  imm,
char  l 
) [static]

Definition at line 852 of file or32-opc.c.

{
  unsigned long mask;
  int letter_bits;
  
  /* First truncate all bits above valid range for this letter
     in case it is zero extend.  */
  letter_bits = letter_range (l);
  mask = (1 << letter_bits) - 1;
  imm &= mask;
  
  /* Do sign extend if this is the right one.  */
  if (letter_signed(l) && (imm >> (letter_bits - 1)))
    imm |= (~mask);

  return imm;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 808 of file or32-opc.c.

{
  unsigned long *a = automata;
  int i;

  while (!(*a & LEAF_FLAG))
    {
      unsigned int first = *a;

      debug (9, "%li ", (long)(a - automata));

      a++;
      i = (insn >> first) & *a;
      a++;
      if (!*(a + i))
       {
         /* Invalid instruction found?  */
         debug (9, "XXX\n");
         return -1;
       }
      a = automata + *(a + i);
    }

  i = *a & ~LEAF_FLAG;

  debug (9, "%i\n", i);

  /* Final check - do we have direct match?
     (based on or32_opcodes this should be the only possibility,
     but in case of invalid/missing instruction we must perform a check)  */
  if ((ti[i].insn_mask & insn) == ti[i].insn) 
    return i;
  else
    return -1;
}

Here is the caller graph for this function:

static unsigned long insn_extract ( char  param_ch,
char *  enc_initial 
) [static]

Definition at line 430 of file or32-opc.c.

{
  char *enc;
  unsigned long ret = 0;
  unsigned opc_pos = 32;

  for (enc = enc_initial; *enc != '\0'; )
    if ((*enc == '0') && (*(enc + 1) == 'x')) 
      {
       unsigned long tmp = strtol (enc+2, NULL, 16);

        opc_pos -= 4;
       if (param_ch == '0' || param_ch == '1')
         {
           if (param_ch == '0')
             tmp = 15 - tmp;
           ret |= tmp << opc_pos;
         }
        enc += 3;
      }
    else
      {
       if (*enc == '0' || *enc == '1' || *enc == '-' || ISALPHA (*enc))
         {
           opc_pos--;
           if (param_ch == *enc)
             ret |= 1 << opc_pos;
         }
       enc++;
      }
  return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int insn_index ( char *  insn)

Definition at line 397 of file or32-opc.c.

{
  unsigned int i;
  int found = -1;

  for (i = 0; i < or32_num_opcodes; i++)
    if (!strcmp (or32_opcodes[i].name, insn))
      {
       found = i;
       break;
      }
  return found;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int insn_len ( int insn_index  ATTRIBUTE_UNUSED)

Definition at line 348 of file or32-opc.c.

{
  return 4;
}
const char* insn_name ( int  index)

Definition at line 412 of file or32-opc.c.

{
  if (index >= 0 && index < (int) or32_num_opcodes)
    return or32_opcodes[index].name;
  else
    return "???";
}

Here is the caller graph for this function:

void l_none ( void  )

Definition at line 421 of file or32-opc.c.

{
}
int letter_range ( char  l)

Definition at line 371 of file or32-opc.c.

{
  const struct or32_opcode *pinsn;
  char *enc;
  int range = 0;
  
  for (pinsn = or32_opcodes; strlen (pinsn->name); pinsn ++)
    {
      if (strchr (pinsn->encoding,l))
       {
         for (enc = pinsn->encoding; *enc != '\0'; enc ++)
           if ((*enc == '0') && (*(enc + 1) == 'x'))
             enc += 2;
           else if (*enc == l)
             range++;
         return range;
       }
    }

  printf ("\nABORT: letter_range(%c): Never used letter.\n", l);
  exit (1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int letter_signed ( char  l)

Definition at line 356 of file or32-opc.c.

{
  const struct or32_letter *pletter;
  
  for (pletter = or32_letters; pletter->letter != '\0'; pletter++)
    if (pletter->letter == l)
      return pletter->sign;
  
  printf ("letter_signed(%c): Unknown letter.\n", l);
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int num_ones ( unsigned long  value) [static]

Definition at line 607 of file or32-opc.c.

{
  int c = 0;

  while (value)
    {
      if (value & 1)
       c++;
      value >>= 1;
    }
  return c;
}

Here is the caller graph for this function:

static unsigned long or32_extract ( char  param_ch,
char *  enc_initial,
unsigned long  insn 
) [static]

Definition at line 871 of file or32-opc.c.

{
  char *enc;
  unsigned long ret = 0;
  int opc_pos = 0;
  int param_pos = 0;

  for (enc = enc_initial; *enc != '\0'; enc++)
    if (*enc == param_ch)
      {
        if (enc - 2 >= enc_initial && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
         continue;
        else
          param_pos++;
      }

#if DEBUG
  printf ("or32_extract: %x ", param_pos);
#endif
  opc_pos = 32;

  for (enc = enc_initial; *enc != '\0'; )
    if ((*enc == '0') && (*(enc + 1) == 'x')) 
      {
        opc_pos -= 4;
        if ((param_ch == '0') || (param_ch == '1')) 
          {
            unsigned long tmp = strtol (enc, NULL, 16);
#if DEBUG
            printf (" enc=%s, tmp=%x ", enc, tmp);
#endif
            if (param_ch == '0')
              tmp = 15 - tmp;
            ret |= tmp << opc_pos;
          }
        enc += 3;
      }
    else if ((*enc == '0') || (*enc == '1')) 
      {
        opc_pos--;
        if (param_ch == *enc)
          ret |= 1 << opc_pos;
        enc++;
      }
    else if (*enc == param_ch) 
      {
        opc_pos--;
        param_pos--;
#if DEBUG
        printf ("\n  ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos, param_pos);
#endif  
        if (ISLOWER (param_ch))
          ret -= ((insn >> opc_pos) & 0x1) << param_pos;
        else
          ret += ((insn >> opc_pos) & 0x1) << param_pos;
        enc++;
      }
    else if (ISALPHA (*enc)) 
      {
        opc_pos--;
        enc++;
      }
    else if (*enc == '-') 
      {
        opc_pos--;
        enc++;
      }
    else
      enc++;

#if DEBUG
  printf ("ret=%x\n", ret);
#endif
  return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void or32_print_immediate ( char  param_ch,
char *  encoding,
unsigned long  insn 
) [static]

Definition at line 960 of file or32-opc.c.

{
  int imm = or32_extract (param_ch, encoding, insn);

  imm = extend_imm (imm, param_ch);
  
  if (letter_signed (param_ch))
    {
      if (imm < 0)
        sprintf (disassembled, "%s%d", disassembled, imm);
      else
        sprintf (disassembled, "%s0x%x", disassembled, imm);
    }
  else
    sprintf (disassembled, "%s%#x", disassembled, imm);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void or32_print_register ( char  param_ch,
char *  encoding,
unsigned long  insn 
) [static]

Definition at line 950 of file or32-opc.c.

{
  int regnum = or32_extract(param_ch, encoding, insn);
  
  sprintf (disassembled, "%sr%d", disassembled, regnum);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct insn_op_struct* parse_params ( const struct or32_opcode opcode,
struct insn_op_struct cur 
) [static, read]

Definition at line 624 of file or32-opc.c.

{
  char *args = opcode->args;
  int i, type;
  
  i = 0;
  type = 0;
  /* In case we don't have any parameters, we add dummy read from r0.  */

  if (!(*args))
    {
      cur->type = OPTYPE_REG | OPTYPE_OP | OPTYPE_LAST;
      cur->data = 0;
      debug (9, "#%08lX %08lX\n", cur->type, cur->data);
      cur++;
      return cur;
  }
  
  while (*args != '\0')
    {     
      if (*args == 'r')
       {
         args++;
         type |= OPTYPE_REG;
       }
      else if (ISALPHA (*args))
       {
         unsigned long arg;

         arg = insn_extract (*args, opcode->encoding);
         debug (9, "%s : %08lX ------\n", opcode->name, arg);
         if (letter_signed (*args))
           {
             type |= OPTYPE_SIG;
             type |= ((num_ones (arg) - 1) << OPTYPE_SBIT_SHR) & OPTYPE_SBIT;
           }

         /* Split argument to sequences of consecutive ones.  */
         while (arg)
           {
             int shr = 0;
             unsigned long tmp = arg, mask = 0;

             while ((tmp & 1) == 0)
              {
                shr++;
                tmp >>= 1;
              }
             while (tmp & 1)
              {
                mask++;
                tmp >>= 1;
              }
             cur->type = type | shr;
             cur->data = mask;
             arg &= ~(((1 << mask) - 1) << shr);
             debug (6, "|%08lX %08lX\n", cur->type, cur->data);
             cur++;
           }
         args++;
       }
      else if (*args == '(')
       {
         /* Next param is displacement.
            Later we will treat them as one operand.  */
         cur--;
         cur->type = type | cur->type | OPTYPE_DIS | OPTYPE_OP;
         debug (9, ">%08lX %08lX\n", cur->type, cur->data);
         cur++;
         type = 0;
         i++;
         args++;
       }
      else if (*args == OPERAND_DELIM)
       {
         cur--;
         cur->type = type | cur->type | OPTYPE_OP;
         debug (9, ">%08lX %08lX\n", cur->type, cur->data);
         cur++;
         type = 0;
         i++;
         args++;
       }
      else if (*args == '0')
       {
         cur->type = type;
         cur->data = 0;
         debug (9, ">%08lX %08lX\n", cur->type, cur->data);
         cur++;
         type = 0;
         i++;
         args++;
       }
      else if (*args == ')')
       args++;
      else
       {
         fprintf (stderr, "%s : parse error in args.\n", opcode->name);
         exit (1);
       }
    }

  cur--;
  cur->type = type | cur->type | OPTYPE_OP | OPTYPE_LAST;
  debug (9, "#%08lX %08lX\n", cur->type, cur->data);
  cur++;

  return cur;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Definition at line 472 of file or32-opc.c.

int curpass = 0

Definition at line 474 of file or32-opc.c.

Definition at line 845 of file or32-opc.c.

char disassembled_str[50] [static]

Definition at line 844 of file or32-opc.c.

Definition at line 473 of file or32-opc.c.

Definition at line 484 of file or32-opc.c.

Definition at line 484 of file or32-opc.c.

const unsigned int or32_num_opcodes = ((sizeof(or32_opcodes)) / (sizeof(struct or32_opcode))) - 1

Definition at line 343 of file or32-opc.c.