Back to index

cell-binutils  2.17cvs20070401
itbl-ops.c
Go to the documentation of this file.
00001 /* itbl-ops.c
00002    Copyright 1997, 1999, 2000, 2001, 2002, 2003, 2005, 2006
00003    Free Software Foundation, Inc.
00004 
00005    This file is part of GAS, the GNU Assembler.
00006 
00007    GAS is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    GAS is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with GAS; see the file COPYING.  If not, write to the Free
00019    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 /*======================================================================*/
00023 /*
00024  * Herein lies the support for dynamic specification of processor
00025  * instructions and registers.  Mnemonics, values, and formats for each
00026  * instruction and register are specified in an ascii file consisting of
00027  * table entries.  The grammar for the table is defined in the document
00028  * "Processor instruction table specification".
00029  *
00030  * Instructions use the gnu assembler syntax, with the addition of
00031  * allowing mnemonics for register.
00032  * Eg. "func $2,reg3,0x100,symbol ; comment"
00033  *     func - opcode name
00034  *     $n - register n
00035  *     reg3 - mnemonic for processor's register defined in table
00036  *     0xddd..d - immediate value
00037  *     symbol - address of label or external symbol
00038  *
00039  * First, itbl_parse reads in the table of register and instruction
00040  * names and formats, and builds a list of entries for each
00041  * processor/type combination.  lex and yacc are used to parse
00042  * the entries in the table and call functions defined here to
00043  * add each entry to our list.
00044  *
00045  * Then, when assembling or disassembling, these functions are called to
00046  * 1) get information on a processor's registers and
00047  * 2) assemble/disassemble an instruction.
00048  * To assemble(disassemble) an instruction, the function
00049  * itbl_assemble(itbl_disassemble) is called to search the list of
00050  * instruction entries, and if a match is found, uses the format
00051  * described in the instruction entry structure to complete the action.
00052  *
00053  * Eg. Suppose we have a Mips coprocessor "cop3" with data register "d2"
00054  * and we want to define function "pig" which takes two operands.
00055  *
00056  * Given the table entries:
00057  *     "p3 insn pig 0x1:24-21 dreg:20-16 immed:15-0"
00058  *     "p3 dreg d2 0x2"
00059  * and that the instruction encoding for coprocessor pz has encoding:
00060  *     #define MIPS_ENCODE_COP_NUM(z) ((0x21|(z<<1))<<25)
00061  *     #define ITBL_ENCODE_PNUM(pnum) MIPS_ENCODE_COP_NUM(pnum)
00062  *
00063  * a structure to describe the instruction might look something like:
00064  *      struct itbl_entry = {
00065  *      e_processor processor = e_p3
00066  *      e_type type = e_insn
00067  *      char *name = "pig"
00068  *      uint value = 0x1
00069  *      uint flags = 0
00070  *      struct itbl_range range = 24-21
00071  *      struct itbl_field *field = {
00072  *              e_type type = e_dreg
00073  *              struct itbl_range range = 20-16
00074  *              struct itbl_field *next = {
00075  *                      e_type type = e_immed
00076  *                      struct itbl_range range = 15-0
00077  *                      struct itbl_field *next = 0
00078  *                      };
00079  *              };
00080  *      struct itbl_entry *next = 0
00081  *      };
00082  *
00083  * And the assembler instructions:
00084  *     "pig d2,0x100"
00085  *     "pig $2,0x100"
00086  *
00087  * would both assemble to the hex value:
00088  *     "0x4e220100"
00089  *
00090  */
00091 
00092 #include "as.h"
00093 #include "itbl-ops.h"
00094 #include <itbl-parse.h>
00095 
00096 /* #define DEBUG */
00097 
00098 #ifdef DEBUG
00099 #include <assert.h>
00100 #define ASSERT(x) assert(x)
00101 #define DBG(x) printf x
00102 #else
00103 #define ASSERT(x)
00104 #define DBG(x)
00105 #endif
00106 
00107 #ifndef min
00108 #define min(a,b) (a<b?a:b)
00109 #endif
00110 
00111 int itbl_have_entries = 0;
00112 
00113 /*======================================================================*/
00114 /* structures for keeping itbl format entries */
00115 
00116 struct itbl_range {
00117   int sbit;                 /* mask starting bit position */
00118   int ebit;                 /* mask ending bit position */
00119 };
00120 
00121 struct itbl_field {
00122   e_type type;                     /* dreg/creg/greg/immed/symb */
00123   struct itbl_range range;  /* field's bitfield range within instruction */
00124   unsigned long flags;             /* field flags */
00125   struct itbl_field *next;  /* next field in list */
00126 };
00127 
00128 /* These structures define the instructions and registers for a processor.
00129  * If the type is an instruction, the structure defines the format of an
00130  * instruction where the fields are the list of operands.
00131  * The flags field below uses the same values as those defined in the
00132  * gnu assembler and are machine specific.  */
00133 struct itbl_entry {
00134   e_processor processor;    /* processor number */
00135   e_type type;                     /* dreg/creg/greg/insn */
00136   char *name;               /* mnemionic name for insn/register */
00137   unsigned long value;             /* opcode/instruction mask/register number */
00138   unsigned long flags;             /* effects of the instruction */
00139   struct itbl_range range;  /* bit range within instruction for value */
00140   struct itbl_field *fields;       /* list of operand definitions (if any) */
00141   struct itbl_entry *next;  /* next entry */
00142 };
00143 
00144 /* local data and structures */
00145 
00146 static int itbl_num_opcodes = 0;
00147 /* Array of entries for each processor and entry type */
00148 static struct itbl_entry *entries[e_nprocs][e_ntypes];
00149 
00150 /* local prototypes */
00151 static unsigned long build_opcode (struct itbl_entry *e);
00152 static e_type get_type (int yytype);
00153 static e_processor get_processor (int yyproc);
00154 static struct itbl_entry **get_entries (e_processor processor,
00155                                    e_type type);
00156 static struct itbl_entry *find_entry_byname (e_processor processor,
00157                                    e_type type, char *name);
00158 static struct itbl_entry *find_entry_byval (e_processor processor,
00159                      e_type type, unsigned long val, struct itbl_range *r);
00160 static struct itbl_entry *alloc_entry (e_processor processor,
00161               e_type type, char *name, unsigned long value);
00162 static unsigned long apply_range (unsigned long value, struct itbl_range r);
00163 static unsigned long extract_range (unsigned long value, struct itbl_range r);
00164 static struct itbl_field *alloc_field (e_type type, int sbit,
00165                                    int ebit, unsigned long flags);
00166 
00167 /*======================================================================*/
00168 /* Interfaces to the parser */
00169 
00170 /* Open the table and use lex and yacc to parse the entries.
00171  * Return 1 for failure; 0 for success.  */
00172 
00173 int
00174 itbl_parse (char *insntbl)
00175 {
00176   extern FILE *yyin;
00177   extern int yyparse (void);
00178 
00179   yyin = fopen (insntbl, FOPEN_RT);
00180   if (yyin == 0)
00181     {
00182       printf ("Can't open processor instruction specification file \"%s\"\n",
00183              insntbl);
00184       return 1;
00185     }
00186 
00187   while (yyparse ())
00188     ;
00189 
00190   fclose (yyin);
00191   itbl_have_entries = 1;
00192   return 0;
00193 }
00194 
00195 /* Add a register entry */
00196 
00197 struct itbl_entry *
00198 itbl_add_reg (int yyprocessor, int yytype, char *regname,
00199              int regnum)
00200 {
00201   return alloc_entry (get_processor (yyprocessor), get_type (yytype), regname,
00202                     (unsigned long) regnum);
00203 }
00204 
00205 /* Add an instruction entry */
00206 
00207 struct itbl_entry *
00208 itbl_add_insn (int yyprocessor, char *name, unsigned long value,
00209               int sbit, int ebit, unsigned long flags)
00210 {
00211   struct itbl_entry *e;
00212   e = alloc_entry (get_processor (yyprocessor), e_insn, name, value);
00213   if (e)
00214     {
00215       e->range.sbit = sbit;
00216       e->range.ebit = ebit;
00217       e->flags = flags;
00218       itbl_num_opcodes++;
00219     }
00220   return e;
00221 }
00222 
00223 /* Add an operand to an instruction entry */
00224 
00225 struct itbl_field *
00226 itbl_add_operand (struct itbl_entry *e, int yytype, int sbit,
00227                 int ebit, unsigned long flags)
00228 {
00229   struct itbl_field *f, **last_f;
00230   if (!e)
00231     return 0;
00232   /* Add to end of fields' list.  */
00233   f = alloc_field (get_type (yytype), sbit, ebit, flags);
00234   if (f)
00235     {
00236       last_f = &e->fields;
00237       while (*last_f)
00238        last_f = &(*last_f)->next;
00239       *last_f = f;
00240       f->next = 0;
00241     }
00242   return f;
00243 }
00244 
00245 /*======================================================================*/
00246 /* Interfaces for assembler and disassembler */
00247 
00248 #ifndef STAND_ALONE
00249 static void append_insns_as_macros (void);
00250 
00251 /* Initialize for gas.  */
00252 
00253 void
00254 itbl_init (void)
00255 {
00256   struct itbl_entry *e, **es;
00257   e_processor procn;
00258   e_type type;
00259 
00260   if (!itbl_have_entries)
00261     return;
00262 
00263   /* Since register names don't have a prefix, put them in the symbol table so
00264      they can't be used as symbols.  This simplifies argument parsing as
00265      we can let gas parse registers for us.  */
00266   /* Use symbol_create instead of symbol_new so we don't try to
00267      output registers into the object file's symbol table.  */
00268 
00269   for (type = e_regtype0; type < e_nregtypes; type++)
00270     for (procn = e_p0; procn < e_nprocs; procn++)
00271       {
00272        es = get_entries (procn, type);
00273        for (e = *es; e; e = e->next)
00274          {
00275            symbol_table_insert (symbol_create (e->name, reg_section,
00276                                           e->value, &zero_address_frag));
00277          }
00278       }
00279   append_insns_as_macros ();
00280 }
00281 
00282 /* Append insns to opcodes table and increase number of opcodes
00283  * Structure of opcodes table:
00284  * struct itbl_opcode
00285  * {
00286  *   const char *name;
00287  *   const char *args;             - string describing the arguments.
00288  *   unsigned long match;   - opcode, or ISA level if pinfo=INSN_MACRO
00289  *   unsigned long mask;    - opcode mask, or macro id if pinfo=INSN_MACRO
00290  *   unsigned long pinfo;   - insn flags, or INSN_MACRO
00291  * };
00292  * examples:
00293  *     {"li",      "t,i",  0x34000000, 0xffe00000, WR_t    },
00294  *     {"li",      "t,I",  0,    (int) M_LI,   INSN_MACRO  },
00295  */
00296 
00297 static char *form_args (struct itbl_entry *e);
00298 static void
00299 append_insns_as_macros (void)
00300 {
00301   struct ITBL_OPCODE_STRUCT *new_opcodes, *o;
00302   struct itbl_entry *e, **es;
00303   int n, id, size, new_size, new_num_opcodes;
00304 
00305   if (!itbl_have_entries)
00306     return;
00307 
00308   if (!itbl_num_opcodes)    /* no new instructions to add! */
00309     {
00310       return;
00311     }
00312   DBG (("previous num_opcodes=%d\n", ITBL_NUM_OPCODES));
00313 
00314   new_num_opcodes = ITBL_NUM_OPCODES + itbl_num_opcodes;
00315   ASSERT (new_num_opcodes >= itbl_num_opcodes);
00316 
00317   size = sizeof (struct ITBL_OPCODE_STRUCT) * ITBL_NUM_OPCODES;
00318   ASSERT (size >= 0);
00319   DBG (("I get=%d\n", size / sizeof (ITBL_OPCODES[0])));
00320 
00321   new_size = sizeof (struct ITBL_OPCODE_STRUCT) * new_num_opcodes;
00322   ASSERT (new_size > size);
00323 
00324   /* FIXME since ITBL_OPCODES culd be a static table,
00325               we can't realloc or delete the old memory.  */
00326   new_opcodes = (struct ITBL_OPCODE_STRUCT *) malloc (new_size);
00327   if (!new_opcodes)
00328     {
00329       printf (_("Unable to allocate memory for new instructions\n"));
00330       return;
00331     }
00332   if (size)                 /* copy preexisting opcodes table */
00333     memcpy (new_opcodes, ITBL_OPCODES, size);
00334 
00335   /* FIXME! some NUMOPCODES are calculated expressions.
00336               These need to be changed before itbls can be supported.  */
00337 
00338   id = ITBL_NUM_MACROS;            /* begin the next macro id after the last */
00339   o = &new_opcodes[ITBL_NUM_OPCODES];     /* append macro to opcodes list */
00340   for (n = e_p0; n < e_nprocs; n++)
00341     {
00342       es = get_entries (n, e_insn);
00343       for (e = *es; e; e = e->next)
00344        {
00345          /* name,    args,   mask,       match,  pinfo
00346                * {"li",      "t,i",  0x34000000, 0xffe00000, WR_t    },
00347                * {"li",      "t,I",  0,    (int) M_LI,   INSN_MACRO  },
00348                * Construct args from itbl_fields.
00349               */
00350          o->name = e->name;
00351          o->args = strdup (form_args (e));
00352          o->mask = apply_range (e->value, e->range);
00353          /* FIXME how to catch during assembly? */
00354          /* mask to identify this insn */
00355          o->match = apply_range (e->value, e->range);
00356          o->pinfo = 0;
00357 
00358 #ifdef USE_MACROS
00359          o->mask = id++;    /* FIXME how to catch during assembly? */
00360          o->match = 0;             /* for macros, the insn_isa number */
00361          o->pinfo = INSN_MACRO;
00362 #endif
00363 
00364          /* Don't add instructions which caused an error */
00365          if (o->args)
00366            o++;
00367          else
00368            new_num_opcodes--;
00369        }
00370     }
00371   ITBL_OPCODES = new_opcodes;
00372   ITBL_NUM_OPCODES = new_num_opcodes;
00373 
00374   /* FIXME
00375               At this point, we can free the entries, as they should have
00376               been added to the assembler's tables.
00377               Don't free name though, since name is being used by the new
00378               opcodes table.
00379 
00380               Eventually, we should also free the new opcodes table itself
00381               on exit.
00382        */
00383 }
00384 
00385 static char *
00386 form_args (struct itbl_entry *e)
00387 {
00388   static char s[31];
00389   char c = 0, *p = s;
00390   struct itbl_field *f;
00391 
00392   ASSERT (e);
00393   for (f = e->fields; f; f = f->next)
00394     {
00395       switch (f->type)
00396        {
00397        case e_dreg:
00398          c = 'd';
00399          break;
00400        case e_creg:
00401          c = 't';
00402          break;
00403        case e_greg:
00404          c = 's';
00405          break;
00406        case e_immed:
00407          c = 'i';
00408          break;
00409        case e_addr:
00410          c = 'a';
00411          break;
00412        default:
00413          c = 0;             /* ignore; unknown field type */
00414        }
00415       if (c)
00416        {
00417          if (p != s)
00418            *p++ = ',';
00419          *p++ = c;
00420        }
00421     }
00422   *p = 0;
00423   return s;
00424 }
00425 #endif /* !STAND_ALONE */
00426 
00427 /* Get processor's register name from val */
00428 
00429 int
00430 itbl_get_reg_val (char *name, unsigned long *pval)
00431 {
00432   e_type t;
00433   e_processor p;
00434 
00435   for (p = e_p0; p < e_nprocs; p++)
00436     {
00437       for (t = e_regtype0; t < e_nregtypes; t++)
00438        {
00439          if (itbl_get_val (p, t, name, pval))
00440            return 1;
00441        }
00442     }
00443   return 0;
00444 }
00445 
00446 char *
00447 itbl_get_name (e_processor processor, e_type type, unsigned long val)
00448 {
00449   struct itbl_entry *r;
00450   /* type depends on instruction passed */
00451   r = find_entry_byval (processor, type, val, 0);
00452   if (r)
00453     return r->name;
00454   else
00455     return 0;               /* error; invalid operand */
00456 }
00457 
00458 /* Get processor's register value from name */
00459 
00460 int
00461 itbl_get_val (e_processor processor, e_type type, char *name,
00462              unsigned long *pval)
00463 {
00464   struct itbl_entry *r;
00465   /* type depends on instruction passed */
00466   r = find_entry_byname (processor, type, name);
00467   if (r == NULL)
00468     return 0;
00469   *pval = r->value;
00470   return 1;
00471 }
00472 
00473 /* Assemble instruction "name" with operands "s".
00474  * name - name of instruction
00475  * s - operands
00476  * returns - long word for assembled instruction */
00477 
00478 unsigned long
00479 itbl_assemble (char *name, char *s)
00480 {
00481   unsigned long opcode;
00482   struct itbl_entry *e = NULL;
00483   struct itbl_field *f;
00484   char *n;
00485   int processor;
00486 
00487   if (!name || !*name)
00488     return 0;               /* error!  must have an opcode name/expr */
00489 
00490   /* find entry in list of instructions for all processors */
00491   for (processor = 0; processor < e_nprocs; processor++)
00492     {
00493       e = find_entry_byname (processor, e_insn, name);
00494       if (e)
00495        break;
00496     }
00497   if (!e)
00498     return 0;               /* opcode not in table; invalid instruction */
00499   opcode = build_opcode (e);
00500 
00501   /* parse opcode's args (if any) */
00502   for (f = e->fields; f; f = f->next)     /* for each arg, ...  */
00503     {
00504       struct itbl_entry *r;
00505       unsigned long value;
00506       if (!s || !*s)
00507        return 0;            /* error - not enough operands */
00508       n = itbl_get_field (&s);
00509       /* n should be in form $n or 0xhhh (are symbol names valid?? */
00510       switch (f->type)
00511        {
00512        case e_dreg:
00513        case e_creg:
00514        case e_greg:
00515          /* Accept either a string name
00516                       * or '$' followed by the register number */
00517          if (*n == '$')
00518            {
00519              n++;
00520              value = strtol (n, 0, 10);
00521              /* FIXME! could have "0l"... then what?? */
00522              if (value == 0 && *n != '0')
00523               return 0;     /* error; invalid operand */
00524            }
00525          else
00526            {
00527              r = find_entry_byname (e->processor, f->type, n);
00528              if (r)
00529               value = r->value;
00530              else
00531               return 0;     /* error; invalid operand */
00532            }
00533          break;
00534        case e_addr:
00535          /* use assembler's symbol table to find symbol */
00536          /* FIXME!! Do we need this?
00537                             if so, what about relocs??
00538                             my_getExpression (&imm_expr, s);
00539                             return 0;     /-* error; invalid operand *-/
00540                             break;
00541                      */
00542          /* If not a symbol, fall thru to IMMED */
00543        case e_immed:
00544          if (*n == '0' && *(n + 1) == 'x')       /* hex begins 0x...  */
00545            {
00546              n += 2;
00547              value = strtol (n, 0, 16);
00548              /* FIXME! could have "0xl"... then what?? */
00549            }
00550          else
00551            {
00552              value = strtol (n, 0, 10);
00553              /* FIXME! could have "0l"... then what?? */
00554              if (value == 0 && *n != '0')
00555               return 0;     /* error; invalid operand */
00556            }
00557          break;
00558        default:
00559          return 0;          /* error; invalid field spec */
00560        }
00561       opcode |= apply_range (value, f->range);
00562     }
00563   if (s && *s)
00564     return 0;               /* error - too many operands */
00565   return opcode;            /* done! */
00566 }
00567 
00568 /* Disassemble instruction "insn".
00569  * insn - instruction
00570  * s - buffer to hold disassembled instruction
00571  * returns - 1 if succeeded; 0 if failed
00572  */
00573 
00574 int
00575 itbl_disassemble (char *s, unsigned long insn)
00576 {
00577   e_processor processor;
00578   struct itbl_entry *e;
00579   struct itbl_field *f;
00580 
00581   if (!ITBL_IS_INSN (insn))
00582     return 0;               /* error */
00583   processor = get_processor (ITBL_DECODE_PNUM (insn));
00584 
00585   /* find entry in list */
00586   e = find_entry_byval (processor, e_insn, insn, 0);
00587   if (!e)
00588     return 0;               /* opcode not in table; invalid instruction */
00589   strcpy (s, e->name);
00590 
00591   /* Parse insn's args (if any).  */
00592   for (f = e->fields; f; f = f->next)     /* for each arg, ...  */
00593     {
00594       struct itbl_entry *r;
00595       unsigned long value;
00596 
00597       if (f == e->fields)   /* First operand is preceded by tab.  */
00598        strcat (s, "\t");
00599       else                  /* ','s separate following operands.  */
00600        strcat (s, ",");
00601       value = extract_range (insn, f->range);
00602       /* n should be in form $n or 0xhhh (are symbol names valid?? */
00603       switch (f->type)
00604        {
00605        case e_dreg:
00606        case e_creg:
00607        case e_greg:
00608          /* Accept either a string name
00609             or '$' followed by the register number.  */
00610          r = find_entry_byval (e->processor, f->type, value, &f->range);
00611          if (r)
00612            strcat (s, r->name);
00613          else
00614            sprintf (s, "%s$%lu", s, value);
00615          break;
00616        case e_addr:
00617          /* Use assembler's symbol table to find symbol.  */
00618          /* FIXME!! Do we need this?  If so, what about relocs??  */
00619          /* If not a symbol, fall through to IMMED.  */
00620        case e_immed:
00621          sprintf (s, "%s0x%lx", s, value);
00622          break;
00623        default:
00624          return 0;          /* error; invalid field spec */
00625        }
00626     }
00627   return 1;                 /* Done!  */
00628 }
00629 
00630 /*======================================================================*/
00631 /*
00632  * Local functions for manipulating private structures containing
00633  * the names and format for the new instructions and registers
00634  * for each processor.
00635  */
00636 
00637 /* Calculate instruction's opcode and function values from entry */
00638 
00639 static unsigned long
00640 build_opcode (struct itbl_entry *e)
00641 {
00642   unsigned long opcode;
00643 
00644   opcode = apply_range (e->value, e->range);
00645   opcode |= ITBL_ENCODE_PNUM (e->processor);
00646   return opcode;
00647 }
00648 
00649 /* Calculate absolute value given the relative value and bit position range
00650  * within the instruction.
00651  * The range is inclusive where 0 is least significant bit.
00652  * A range of { 24, 20 } will have a mask of
00653  * bit   3           2            1
00654  * pos: 1098 7654 3210 9876 5432 1098 7654 3210
00655  * bin: 0000 0001 1111 0000 0000 0000 0000 0000
00656  * hex:    0    1    f    0    0    0    0    0
00657  * mask: 0x01f00000.
00658  */
00659 
00660 static unsigned long
00661 apply_range (unsigned long rval, struct itbl_range r)
00662 {
00663   unsigned long mask;
00664   unsigned long aval;
00665   int len = MAX_BITPOS - r.sbit;
00666 
00667   ASSERT (r.sbit >= r.ebit);
00668   ASSERT (MAX_BITPOS >= r.sbit);
00669   ASSERT (r.ebit >= 0);
00670 
00671   /* create mask by truncating 1s by shifting */
00672   mask = 0xffffffff << len;
00673   mask = mask >> len;
00674   mask = mask >> r.ebit;
00675   mask = mask << r.ebit;
00676 
00677   aval = (rval << r.ebit) & mask;
00678   return aval;
00679 }
00680 
00681 /* Calculate relative value given the absolute value and bit position range
00682  * within the instruction.  */
00683 
00684 static unsigned long
00685 extract_range (unsigned long aval, struct itbl_range r)
00686 {
00687   unsigned long mask;
00688   unsigned long rval;
00689   int len = MAX_BITPOS - r.sbit;
00690 
00691   /* create mask by truncating 1s by shifting */
00692   mask = 0xffffffff << len;
00693   mask = mask >> len;
00694   mask = mask >> r.ebit;
00695   mask = mask << r.ebit;
00696 
00697   rval = (aval & mask) >> r.ebit;
00698   return rval;
00699 }
00700 
00701 /* Extract processor's assembly instruction field name from s;
00702  * forms are "n args" "n,args" or "n" */
00703 /* Return next argument from string pointer "s" and advance s.
00704  * delimiters are " ,()" */
00705 
00706 char *
00707 itbl_get_field (char **S)
00708 {
00709   static char n[128];
00710   char *s;
00711   int len;
00712 
00713   s = *S;
00714   if (!s || !*s)
00715     return 0;
00716   /* FIXME: This is a weird set of delimiters.  */
00717   len = strcspn (s, " \t,()");
00718   ASSERT (128 > len + 1);
00719   strncpy (n, s, len);
00720   n[len] = 0;
00721   if (s[len] == '\0')
00722     s = 0;                  /* no more args */
00723   else
00724     s += len + 1;           /* advance to next arg */
00725 
00726   *S = s;
00727   return n;
00728 }
00729 
00730 /* Search entries for a given processor and type
00731  * to find one matching the name "n".
00732  * Return a pointer to the entry */
00733 
00734 static struct itbl_entry *
00735 find_entry_byname (e_processor processor,
00736                  e_type type, char *n)
00737 {
00738   struct itbl_entry *e, **es;
00739 
00740   es = get_entries (processor, type);
00741   for (e = *es; e; e = e->next)    /* for each entry, ...  */
00742     {
00743       if (!strcmp (e->name, n))
00744        return e;
00745     }
00746   return 0;
00747 }
00748 
00749 /* Search entries for a given processor and type
00750  * to find one matching the value "val" for the range "r".
00751  * Return a pointer to the entry.
00752  * This function is used for disassembling fields of an instruction.
00753  */
00754 
00755 static struct itbl_entry *
00756 find_entry_byval (e_processor processor, e_type type,
00757                 unsigned long val, struct itbl_range *r)
00758 {
00759   struct itbl_entry *e, **es;
00760   unsigned long eval;
00761 
00762   es = get_entries (processor, type);
00763   for (e = *es; e; e = e->next)    /* for each entry, ...  */
00764     {
00765       if (processor != e->processor)
00766        continue;
00767       /* For insns, we might not know the range of the opcode,
00768         * so a range of 0 will allow this routine to match against
00769         * the range of the entry to be compared with.
00770         * This could cause ambiguities.
00771         * For operands, we get an extracted value and a range.
00772         */
00773       /* if range is 0, mask val against the range of the compared entry.  */
00774       if (r == 0)           /* if no range passed, must be whole 32-bits
00775                       * so create 32-bit value from entry's range */
00776        {
00777          eval = apply_range (e->value, e->range);
00778          val &= apply_range (0xffffffff, e->range);
00779        }
00780       else if ((r->sbit == e->range.sbit && r->ebit == e->range.ebit)
00781               || (e->range.sbit == 0 && e->range.ebit == 0))
00782        {
00783          eval = apply_range (e->value, *r);
00784          val = apply_range (val, *r);
00785        }
00786       else
00787        continue;
00788       if (val == eval)
00789        return e;
00790     }
00791   return 0;
00792 }
00793 
00794 /* Return a pointer to the list of entries for a given processor and type.  */
00795 
00796 static struct itbl_entry **
00797 get_entries (e_processor processor, e_type type)
00798 {
00799   return &entries[processor][type];
00800 }
00801 
00802 /* Return an integral value for the processor passed from yyparse.  */
00803 
00804 static e_processor
00805 get_processor (int yyproc)
00806 {
00807   /* translate from yacc's processor to enum */
00808   if (yyproc >= e_p0 && yyproc < e_nprocs)
00809     return (e_processor) yyproc;
00810   return e_invproc;         /* error; invalid processor */
00811 }
00812 
00813 /* Return an integral value for the entry type passed from yyparse.  */
00814 
00815 static e_type
00816 get_type (int yytype)
00817 {
00818   switch (yytype)
00819     {
00820       /* translate from yacc's type to enum */
00821     case INSN:
00822       return e_insn;
00823     case DREG:
00824       return e_dreg;
00825     case CREG:
00826       return e_creg;
00827     case GREG:
00828       return e_greg;
00829     case ADDR:
00830       return e_addr;
00831     case IMMED:
00832       return e_immed;
00833     default:
00834       return e_invtype;            /* error; invalid type */
00835     }
00836 }
00837 
00838 /* Allocate and initialize an entry */
00839 
00840 static struct itbl_entry *
00841 alloc_entry (e_processor processor, e_type type,
00842             char *name, unsigned long value)
00843 {
00844   struct itbl_entry *e, **es;
00845   if (!name)
00846     return 0;
00847   e = (struct itbl_entry *) malloc (sizeof (struct itbl_entry));
00848   if (e)
00849     {
00850       memset (e, 0, sizeof (struct itbl_entry));
00851       e->name = (char *) malloc (sizeof (strlen (name)) + 1);
00852       if (e->name)
00853        strcpy (e->name, name);
00854       e->processor = processor;
00855       e->type = type;
00856       e->value = value;
00857       es = get_entries (e->processor, e->type);
00858       e->next = *es;
00859       *es = e;
00860     }
00861   return e;
00862 }
00863 
00864 /* Allocate and initialize an entry's field */
00865 
00866 static struct itbl_field *
00867 alloc_field (e_type type, int sbit, int ebit,
00868             unsigned long flags)
00869 {
00870   struct itbl_field *f;
00871   f = (struct itbl_field *) malloc (sizeof (struct itbl_field));
00872   if (f)
00873     {
00874       memset (f, 0, sizeof (struct itbl_field));
00875       f->type = type;
00876       f->range.sbit = sbit;
00877       f->range.ebit = ebit;
00878       f->flags = flags;
00879     }
00880   return f;
00881 }