2002-03-07 Daniel Jacobowitz <drow@mvista.com>
[deliverable/binutils-gdb.git] / gas / itbl-ops.c
index f008dcafebc4aa060769c2166cb5ec6ff97cc4a0..d67a9869e5b20564ff24262a141027cdb17db8bf 100644 (file)
@@ -1,5 +1,5 @@
 /* itbl-ops.c
-   Copyright (C) 1997, 1998  Free Software Foundation, Inc.
+   Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -114,45 +114,39 @@ int itbl_have_entries = 0;
 /*======================================================================*/
 /* structures for keeping itbl format entries */
 
-struct itbl_range
-  {
-    int sbit;                  /* mask starting bit position */
-    int ebit;                  /* mask ending bit position */
-  };
-
-struct itbl_field
-  {
-    e_type type;               /* dreg/creg/greg/immed/symb */
-    struct itbl_range range;   /* field's bitfield range within instruction */
-    unsigned long flags;       /* field flags */
-    struct itbl_field *next;   /* next field in list */
-  };
+struct itbl_range {
+  int sbit;                    /* mask starting bit position */
+  int ebit;                    /* mask ending bit position */
+};
 
+struct itbl_field {
+  e_type type;                 /* dreg/creg/greg/immed/symb */
+  struct itbl_range range;     /* field's bitfield range within instruction */
+  unsigned long flags;         /* field flags */
+  struct itbl_field *next;     /* next field in list */
+};
 
 /* These structures define the instructions and registers for a processor.
  * If the type is an instruction, the structure defines the format of an
  * instruction where the fields are the list of operands.
  * The flags field below uses the same values as those defined in the
- * gnu assembler and are machine specific. */
-struct itbl_entry
-  {
-    e_processor processor;     /* processor number */
-    e_type type;               /* dreg/creg/greg/insn */
-    char *name;                        /* mnemionic name for insn/register */
-    unsigned long value;       /* opcode/instruction mask/register number */
-    unsigned long flags;       /* effects of the instruction */
-    struct itbl_range range;   /* bit range within instruction for value */
-    struct itbl_field *fields; /* list of operand definitions (if any) */
-    struct itbl_entry *next;   /* next entry */
-  };
-
+ * gnu assembler and are machine specific.  */
+struct itbl_entry {
+  e_processor processor;       /* processor number */
+  e_type type;                 /* dreg/creg/greg/insn */
+  char *name;                  /* mnemionic name for insn/register */
+  unsigned long value;         /* opcode/instruction mask/register number */
+  unsigned long flags;         /* effects of the instruction */
+  struct itbl_range range;     /* bit range within instruction for value */
+  struct itbl_field *fields;   /* list of operand definitions (if any) */
+  struct itbl_entry *next;     /* next entry */
+};
 
 /* local data and structures */
 
 static int itbl_num_opcodes = 0;
 /* Array of entries for each processor and entry type */
-static struct itbl_entry *entries[e_nprocs][e_ntypes] =
-{
+static struct itbl_entry *entries[e_nprocs][e_ntypes] = {
   {0, 0, 0, 0, 0, 0},
   {0, 0, 0, 0, 0, 0},
   {0, 0, 0, 0, 0, 0},
@@ -163,45 +157,44 @@ static struct itbl_entry *entries[e_nprocs][e_ntypes] =
 static unsigned long build_opcode PARAMS ((struct itbl_entry *e));
 static e_type get_type PARAMS ((int yytype));
 static e_processor get_processor PARAMS ((int yyproc));
-static struct itbl_entry **get_entries PARAMS ((e_processor processor, 
+static struct itbl_entry **get_entries PARAMS ((e_processor processor,
                                                e_type type));
-static struct itbl_entry *find_entry_byname PARAMS ((e_processor processor, 
+static struct itbl_entry *find_entry_byname PARAMS ((e_processor processor,
                                        e_type type, char *name));
-static struct itbl_entry *find_entry_byval PARAMS ((e_processor processor, 
+static struct itbl_entry *find_entry_byval PARAMS ((e_processor processor,
                        e_type type, unsigned long val, struct itbl_range *r));
-static struct itbl_entry *alloc_entry PARAMS ((e_processor processor, 
+static struct itbl_entry *alloc_entry PARAMS ((e_processor processor,
                e_type type, char *name, unsigned long value));
-static unsigned long apply_range PARAMS ((unsigned long value, 
+static unsigned long apply_range PARAMS ((unsigned long value,
                                                struct itbl_range r));
-static unsigned long extract_range PARAMS ((unsigned long value, 
+static unsigned long extract_range PARAMS ((unsigned long value,
                                                struct itbl_range r));
-static struct itbl_field *alloc_field PARAMS ((e_type type, int sbit, 
+static struct itbl_field *alloc_field PARAMS ((e_type type, int sbit,
                                        int ebit, unsigned long flags));
 
-
 /*======================================================================*/
 /* Interfaces to the parser */
 
-
 /* Open the table and use lex and yacc to parse the entries.
  * Return 1 for failure; 0 for success.  */
 
-int 
+int
 itbl_parse (char *insntbl)
 {
   extern FILE *yyin;
   extern int yyparse (void);
-  yyin = fopen (insntbl, "r");
+
+  yyin = fopen (insntbl, FOPEN_RT);
   if (yyin == 0)
     {
       printf ("Can't open processor instruction specification file \"%s\"\n",
              insntbl);
       return 1;
     }
-  else
-    {
-      while (yyparse ());
-    }
+
+  while (yyparse ())
+    ;
+
   fclose (yyin);
   itbl_have_entries = 1;
   return 0;
@@ -213,7 +206,7 @@ struct itbl_entry *
 itbl_add_reg (int yyprocessor, int yytype, char *regname,
              int regnum)
 {
-#if 0                          
+#if 0
 #include "as.h"
 #include "symbols.h"
   /* Since register names don't have a prefix, we put them in the symbol table so
@@ -256,7 +249,7 @@ itbl_add_operand (struct itbl_entry *e, int yytype, int sbit,
   struct itbl_field *f, **last_f;
   if (!e)
     return 0;
-  /* Add to end of fields' list. */
+  /* Add to end of fields' list.  */
   f = alloc_field (get_type (yytype), sbit, ebit, flags);
   if (f)
     {
@@ -269,7 +262,6 @@ itbl_add_operand (struct itbl_entry *e, int yytype, int sbit,
   return f;
 }
 
-
 /*======================================================================*/
 /* Interfaces for assembler and disassembler */
 
@@ -278,8 +270,9 @@ itbl_add_operand (struct itbl_entry *e, int yytype, int sbit,
 #include "symbols.h"
 static void append_insns_as_macros (void);
 
-/* initialize for gas */
-void 
+/* Initialize for gas.  */
+
+void
 itbl_init (void)
 {
   struct itbl_entry *e, **es;
@@ -287,11 +280,11 @@ itbl_init (void)
   e_type type;
 
   if (!itbl_have_entries)
-       return;
+    return;
 
   /* Since register names don't have a prefix, put them in the symbol table so
      they can't be used as symbols.  This simplifies argument parsing as
-     we can let gas parse registers for us. */
+     we can let gas parse registers for us.  */
   /* Use symbol_create instead of symbol_new so we don't try to
      output registers into the object file's symbol table.  */
 
@@ -302,22 +295,21 @@ itbl_init (void)
        for (e = *es; e; e = e->next)
          {
            symbol_table_insert (symbol_create (e->name, reg_section,
-                                            e->value, &zero_address_frag));
+                                               e->value, &zero_address_frag));
          }
       }
   append_insns_as_macros ();
 }
 
-
-/* Append insns to opcodes table and increase number of opcodes 
- * Structure of opcodes table: 
+/* Append insns to opcodes table and increase number of opcodes
+ * Structure of opcodes table:
  * struct itbl_opcode
  * {
  *   const char *name;
- *   const char *args;                 - string describing the arguments.  
- *   unsigned long match;      - opcode, or ISA level if pinfo=INSN_MACRO 
- *   unsigned long mask;       - opcode mask, or macro id if pinfo=INSN_MACRO 
- *   unsigned long pinfo;      - insn flags, or INSN_MACRO 
+ *   const char *args;                 - string describing the arguments.
+ *   unsigned long match;      - opcode, or ISA level if pinfo=INSN_MACRO
+ *   unsigned long mask;       - opcode mask, or macro id if pinfo=INSN_MACRO
+ *   unsigned long pinfo;      - insn flags, or INSN_MACRO
  * };
  * examples:
  *     {"li",      "t,i",  0x34000000, 0xffe00000, WR_t    },
@@ -325,7 +317,7 @@ itbl_init (void)
  */
 
 static char *form_args (struct itbl_entry *e);
-static void 
+static void
 append_insns_as_macros (void)
 {
   struct ITBL_OPCODE_STRUCT *new_opcodes, *o;
@@ -333,7 +325,7 @@ append_insns_as_macros (void)
   int n, id, size, new_size, new_num_opcodes;
 
   if (!itbl_have_entries)
-       return;
+    return;
 
   if (!itbl_num_opcodes)       /* no new instructions to add! */
     {
@@ -352,7 +344,7 @@ append_insns_as_macros (void)
   ASSERT (new_size > size);
 
   /* FIXME since ITBL_OPCODES culd be a static table,
-               we can't realloc or delete the old memory. */
+               we can't realloc or delete the old memory.  */
   new_opcodes = (struct ITBL_OPCODE_STRUCT *) malloc (new_size);
   if (!new_opcodes)
     {
@@ -363,7 +355,7 @@ append_insns_as_macros (void)
     memcpy (new_opcodes, ITBL_OPCODES, size);
 
   /* FIXME! some NUMOPCODES are calculated expressions.
-               These need to be changed before itbls can be supported. */
+               These need to be changed before itbls can be supported.  */
 
   id = ITBL_NUM_MACROS;                /* begin the next macro id after the last */
   o = &new_opcodes[ITBL_NUM_OPCODES];  /* append macro to opcodes list */
@@ -407,7 +399,7 @@ append_insns_as_macros (void)
                Don't free name though, since name is being used by the new
                opcodes table.
 
-               Eventually, we should also free the new opcodes table itself 
+               Eventually, we should also free the new opcodes table itself
                on exit.
        */
 }
@@ -454,21 +446,22 @@ form_args (struct itbl_entry *e)
 }
 #endif /* !STAND_ALONE */
 
-
 /* Get processor's register name from val */
 
-unsigned long 
-itbl_get_reg_val (char *name)
+int
+itbl_get_reg_val (char *name, unsigned long *pval)
 {
   e_type t;
   e_processor p;
-  int r = 0;
+
   for (p = e_p0; p < e_nprocs; p++)
-    for (t = e_regtype0; t < e_nregtypes; t++)
-      {
-       if (r = itbl_get_val (p, t, name), r)
-         return r;
-      }
+    {
+      for (t = e_regtype0; t < e_nregtypes; t++)
+       {
+         if (itbl_get_val (p, t, name, pval))
+           return 1;
+       }
+    }
   return 0;
 }
 
@@ -486,35 +479,35 @@ itbl_get_name (e_processor processor, e_type type, unsigned long val)
 
 /* Get processor's register value from name */
 
-unsigned long 
-itbl_get_val (e_processor processor, e_type type, char *name)
+int
+itbl_get_val (e_processor processor, e_type type, char *name,
+             unsigned long *pval)
 {
   struct itbl_entry *r;
   /* type depends on instruction passed */
   r = find_entry_byname (processor, type, name);
-  if (r)
-    return r->value;
-  else
-    return 0;                  /* error; invalid operand */
+  if (r == NULL)
+    return 0;
+  *pval = r->value;
+  return 1;
 }
 
-
 /* Assemble instruction "name" with operands "s".
  * name - name of instruction
  * s - operands
  * returns - long word for assembled instruction */
 
-unsigned long 
+unsigned long
 itbl_assemble (char *name, char *s)
 {
   unsigned long opcode;
-  struct itbl_entry *e;
+  struct itbl_entry *e = NULL;
   struct itbl_field *f;
   char *n;
   int processor;
 
   if (!name || !*name)
-    return 0;                  /* error!  must have a opcode name/expr */
+    return 0;                  /* error!  must have an opcode name/expr */
 
   /* find entry in list of instructions for all processors */
   for (processor = 0; processor < e_nprocs; processor++)
@@ -524,11 +517,11 @@ itbl_assemble (char *name, char *s)
        break;
     }
   if (!e)
-    return 0;                  /* opcode not in table; invalid instrustion */
+    return 0;                  /* opcode not in table; invalid instruction */
   opcode = build_opcode (e);
 
   /* parse opcode's args (if any) */
-  for (f = e->fields; f; f = f->next)  /* for each arg, ... */
+  for (f = e->fields; f; f = f->next)  /* for each arg, ...  */
     {
       struct itbl_entry *r;
       unsigned long value;
@@ -570,7 +563,7 @@ itbl_assemble (char *name, char *s)
                        */
          /* If not a symbol, fall thru to IMMED */
        case e_immed:
-         if (*n == '0' && *(n + 1) == 'x')     /* hex begins 0x... */
+         if (*n == '0' && *(n + 1) == 'x')     /* hex begins 0x...  */
            {
              n += 2;
              value = strtol (n, 0, 16);
@@ -600,7 +593,7 @@ itbl_assemble (char *name, char *s)
  * returns - 1 if succeeded; 0 if failed
  */
 
-int 
+int
 itbl_disassemble (char *s, unsigned long insn)
 {
   e_processor processor;
@@ -608,24 +601,24 @@ itbl_disassemble (char *s, unsigned long insn)
   struct itbl_field *f;
 
   if (!ITBL_IS_INSN (insn))
-    return 0;                  /* error*/
+    return 0;                  /* error */
   processor = get_processor (ITBL_DECODE_PNUM (insn));
 
   /* find entry in list */
   e = find_entry_byval (processor, e_insn, insn, 0);
   if (!e)
-    return 0;                  /* opcode not in table; invalid instrustion */
+    return 0;                  /* opcode not in table; invalid instruction */
   strcpy (s, e->name);
 
-  /* parse insn's args (if any) */
-  for (f = e->fields; f; f = f->next)  /* for each arg, ... */
+  /* Parse insn's args (if any).  */
+  for (f = e->fields; f; f = f->next)  /* for each arg, ...  */
     {
       struct itbl_entry *r;
       unsigned long value;
 
-      if (f == e->fields)      /* first operand is preceeded by tab */
+      if (f == e->fields)      /* First operand is preceeded by tab.  */
        strcat (s, "\t");
-      else                     /* ','s separate following operands */
+      else                     /* ','s separate following operands */
        strcat (s, ",");
       value = extract_range (insn, f->range);
       /* n should be in form $n or 0xhhh (are symbol names valid?? */
@@ -635,27 +628,25 @@ itbl_disassemble (char *s, unsigned long insn)
        case e_creg:
        case e_greg:
          /* Accept either a string name
-                        * or '$' followed by the register number */
+            or '$' followed by the register number.  */
          r = find_entry_byval (e->processor, f->type, value, &f->range);
          if (r)
            strcat (s, r->name);
          else
-           sprintf (s, "%s$%d", s, value);
+           sprintf (s, "%s$%lu", s, value);
          break;
        case e_addr:
-         /* use assembler's symbol table to find symbol */
-         /* FIXME!! Do we need this?
-                        *   if so, what about relocs??
-                       */
-         /* If not a symbol, fall thru to IMMED */
+         /* Use assembler's symbol table to find symbol.  */
+         /* FIXME!! Do we need this?  If so, what about relocs??  */
+         /* If not a symbol, fall through to IMMED.  */
        case e_immed:
-         sprintf (s, "%s0x%x", s, value);
+         sprintf (s, "%s0x%lx", s, value);
          break;
        default:
          return 0;             /* error; invalid field spec */
        }
     }
-  return 1;                    /* done! */
+  return 1;                    /* Done!  */
 }
 
 /*======================================================================*/
@@ -667,7 +658,7 @@ itbl_disassemble (char *s, unsigned long insn)
 
 /* Calculate instruction's opcode and function values from entry */
 
-static unsigned long 
+static unsigned long
 build_opcode (struct itbl_entry *e)
 {
   unsigned long opcode;
@@ -688,7 +679,7 @@ build_opcode (struct itbl_entry *e)
  * mask: 0x01f00000.
  */
 
-static unsigned long 
+static unsigned long
 apply_range (unsigned long rval, struct itbl_range r)
 {
   unsigned long mask;
@@ -712,7 +703,7 @@ apply_range (unsigned long rval, struct itbl_range r)
 /* Calculate relative value given the absolute value and bit position range
  * within the instruction.  */
 
-static unsigned long 
+static unsigned long
 extract_range (unsigned long aval, struct itbl_range r)
 {
   unsigned long mask;
@@ -732,28 +723,20 @@ extract_range (unsigned long aval, struct itbl_range r)
 /* Extract processor's assembly instruction field name from s;
  * forms are "n args" "n,args" or "n" */
 /* Return next argument from string pointer "s" and advance s.
- * delimiters are " ,\0" */
+ * delimiters are " ,()" */
 
 char *
 itbl_get_field (char **S)
 {
   static char n[128];
-  char *p, *ps, *s;
+  char *s;
   int len;
 
   s = *S;
   if (!s || !*s)
     return 0;
-  p = s + strlen (s);
-  if (ps = strchr (s, ','), ps)
-    p = ps;
-  if (ps = strchr (s, ' '), ps)
-    p = min (p, ps);
-  if (ps = strchr (s, '\0'), ps)
-    p = min (p, ps);
-  if (p == 0)
-    return 0;                  /* error! */
-  len = p - s;
+  /* FIXME: This is a weird set of delimiters.  */
+  len = strcspn (s, " \t,()");
   ASSERT (128 > len + 1);
   strncpy (n, s, len);
   n[len] = 0;
@@ -777,7 +760,7 @@ find_entry_byname (e_processor processor,
   struct itbl_entry *e, **es;
 
   es = get_entries (processor, type);
-  for (e = *es; e; e = e->next)        /* for each entry, ... */
+  for (e = *es; e; e = e->next)        /* for each entry, ...  */
     {
       if (!strcmp (e->name, n))
        return e;
@@ -799,7 +782,7 @@ find_entry_byval (e_processor processor, e_type type,
   unsigned long eval;
 
   es = get_entries (processor, type);
-  for (e = *es; e; e = e->next)        /* for each entry, ... */
+  for (e = *es; e; e = e->next)        /* for each entry, ...  */
     {
       if (processor != e->processor)
        continue;
@@ -809,15 +792,15 @@ find_entry_byval (e_processor processor, e_type type,
         * This could cause ambiguities.
         * For operands, we get an extracted value and a range.
         */
-      /* if range is 0, mask val against the range of the compared entry. */
+      /* if range is 0, mask val against the range of the compared entry.  */
       if (r == 0)              /* if no range passed, must be whole 32-bits
                         * so create 32-bit value from entry's range */
        {
          eval = apply_range (e->value, e->range);
          val &= apply_range (0xffffffff, e->range);
        }
-      else if (r->sbit == e->range.sbit && r->ebit == e->range.ebit
-              || e->range.sbit == 0 && e->range.ebit == 0)
+      else if ((r->sbit == e->range.sbit && r->ebit == e->range.ebit)
+              || (e->range.sbit == 0 && e->range.ebit == 0))
        {
          eval = apply_range (e->value, *r);
          val = apply_range (val, *r);
@@ -830,7 +813,7 @@ find_entry_byval (e_processor processor, e_type type,
   return 0;
 }
 
-/* Return a pointer to the list of entries for a given processor and type. */
+/* Return a pointer to the list of entries for a given processor and type.  */
 
 static struct itbl_entry **
 get_entries (e_processor processor, e_type type)
@@ -838,9 +821,9 @@ get_entries (e_processor processor, e_type type)
   return &entries[processor][type];
 }
 
-/* Return an integral value for the processor passed from yyparse. */
+/* Return an integral value for the processor passed from yyparse.  */
 
-static e_processor 
+static e_processor
 get_processor (int yyproc)
 {
   /* translate from yacc's processor to enum */
@@ -849,9 +832,9 @@ get_processor (int yyproc)
   return e_invproc;            /* error; invalid processor */
 }
 
-/* Return an integral value for the entry type passed from yyparse. */
+/* Return an integral value for the entry type passed from yyparse.  */
 
-static e_type 
+static e_type
 get_type (int yytype)
 {
   switch (yytype)
@@ -874,7 +857,6 @@ get_type (int yytype)
     }
 }
 
-
 /* Allocate and initialize an entry */
 
 static struct itbl_entry *
This page took 0.043451 seconds and 4 git commands to generate.