Home | History | Annotate | Line # | Download | only in gas
itbl-ops.c revision 1.1.1.8
      1      1.1  christos /* itbl-ops.c
      2  1.1.1.8  christos    Copyright (C) 1997-2025 Free Software Foundation, Inc.
      3      1.1  christos 
      4      1.1  christos    This file is part of GAS, the GNU Assembler.
      5      1.1  christos 
      6      1.1  christos    GAS is free software; you can redistribute it and/or modify
      7      1.1  christos    it under the terms of the GNU General Public License as published by
      8      1.1  christos    the Free Software Foundation; either version 3, or (at your option)
      9      1.1  christos    any later version.
     10      1.1  christos 
     11      1.1  christos    GAS is distributed in the hope that it will be useful,
     12      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14      1.1  christos    GNU General Public License for more details.
     15      1.1  christos 
     16      1.1  christos    You should have received a copy of the GNU General Public License
     17      1.1  christos    along with GAS; see the file COPYING.  If not, write to the Free
     18      1.1  christos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     19      1.1  christos    02110-1301, USA.  */
     20      1.1  christos 
     21      1.1  christos /*======================================================================*/
     22      1.1  christos /*
     23      1.1  christos  * Herein lies the support for dynamic specification of processor
     24      1.1  christos  * instructions and registers.  Mnemonics, values, and formats for each
     25      1.1  christos  * instruction and register are specified in an ascii file consisting of
     26      1.1  christos  * table entries.  The grammar for the table is defined in the document
     27      1.1  christos  * "Processor instruction table specification".
     28      1.1  christos  *
     29      1.1  christos  * Instructions use the gnu assembler syntax, with the addition of
     30      1.1  christos  * allowing mnemonics for register.
     31      1.1  christos  * Eg. "func $2,reg3,0x100,symbol ; comment"
     32      1.1  christos  * 	func - opcode name
     33      1.1  christos  * 	$n - register n
     34      1.1  christos  * 	reg3 - mnemonic for processor's register defined in table
     35      1.1  christos  * 	0xddd..d - immediate value
     36      1.1  christos  * 	symbol - address of label or external symbol
     37      1.1  christos  *
     38      1.1  christos  * First, itbl_parse reads in the table of register and instruction
     39      1.1  christos  * names and formats, and builds a list of entries for each
     40      1.1  christos  * processor/type combination.  lex and yacc are used to parse
     41      1.1  christos  * the entries in the table and call functions defined here to
     42      1.1  christos  * add each entry to our list.
     43      1.1  christos  *
     44      1.1  christos  * Then, when assembling or disassembling, these functions are called to
     45      1.1  christos  * 1) get information on a processor's registers and
     46      1.1  christos  * 2) assemble/disassemble an instruction.
     47      1.1  christos  * To assemble(disassemble) an instruction, the function
     48      1.1  christos  * itbl_assemble(itbl_disassemble) is called to search the list of
     49      1.1  christos  * instruction entries, and if a match is found, uses the format
     50      1.1  christos  * described in the instruction entry structure to complete the action.
     51      1.1  christos  *
     52      1.1  christos  * Eg. Suppose we have a Mips coprocessor "cop3" with data register "d2"
     53      1.1  christos  * and we want to define function "pig" which takes two operands.
     54      1.1  christos  *
     55      1.1  christos  * Given the table entries:
     56      1.1  christos  * 	"p3 insn pig 0x1:24-21 dreg:20-16 immed:15-0"
     57      1.1  christos  * 	"p3 dreg d2 0x2"
     58      1.1  christos  * and that the instruction encoding for coprocessor pz has encoding:
     59      1.1  christos  * 	#define MIPS_ENCODE_COP_NUM(z) ((0x21|(z<<1))<<25)
     60      1.1  christos  * 	#define ITBL_ENCODE_PNUM(pnum) MIPS_ENCODE_COP_NUM(pnum)
     61      1.1  christos  *
     62      1.1  christos  * a structure to describe the instruction might look something like:
     63      1.1  christos  *      struct itbl_entry = {
     64      1.1  christos  *      e_processor processor = e_p3
     65      1.1  christos  *      e_type type = e_insn
     66      1.1  christos  *      char *name = "pig"
     67      1.1  christos  *      uint value = 0x1
     68      1.1  christos  *      uint flags = 0
     69      1.1  christos  *      struct itbl_range range = 24-21
     70      1.1  christos  *      struct itbl_field *field = {
     71      1.1  christos  *              e_type type = e_dreg
     72      1.1  christos  *              struct itbl_range range = 20-16
     73      1.1  christos  *              struct itbl_field *next = {
     74      1.1  christos  *                      e_type type = e_immed
     75      1.1  christos  *                      struct itbl_range range = 15-0
     76      1.1  christos  *                      struct itbl_field *next = 0
     77      1.1  christos  *                      };
     78      1.1  christos  *              };
     79      1.1  christos  *      struct itbl_entry *next = 0
     80      1.1  christos  *      };
     81      1.1  christos  *
     82      1.1  christos  * And the assembler instructions:
     83      1.1  christos  * 	"pig d2,0x100"
     84      1.1  christos  * 	"pig $2,0x100"
     85      1.1  christos  *
     86      1.1  christos  * would both assemble to the hex value:
     87      1.1  christos  * 	"0x4e220100"
     88      1.1  christos  *
     89      1.1  christos  */
     90      1.1  christos 
     91      1.1  christos #include "as.h"
     92      1.1  christos #include "itbl-ops.h"
     93      1.1  christos #include <itbl-parse.h>
     94      1.1  christos 
     95      1.1  christos /* #define DEBUG */
     96      1.1  christos 
     97      1.1  christos #ifdef DEBUG
     98      1.1  christos #include <assert.h>
     99      1.1  christos #define ASSERT(x) gas_assert (x)
    100      1.1  christos #define DBG(x) printf x
    101      1.1  christos #else
    102      1.1  christos #define ASSERT(x)
    103      1.1  christos #define DBG(x)
    104      1.1  christos #endif
    105      1.1  christos 
    106      1.1  christos #ifndef min
    107      1.1  christos #define min(a,b) (a<b?a:b)
    108      1.1  christos #endif
    109      1.1  christos 
    110      1.1  christos int itbl_have_entries = 0;
    111      1.1  christos 
    112      1.1  christos /*======================================================================*/
    113      1.1  christos /* structures for keeping itbl format entries */
    114      1.1  christos 
    115      1.1  christos struct itbl_range {
    116      1.1  christos   int sbit;			/* mask starting bit position */
    117      1.1  christos   int ebit;			/* mask ending bit position */
    118      1.1  christos };
    119      1.1  christos 
    120      1.1  christos struct itbl_field {
    121      1.1  christos   e_type type;			/* dreg/creg/greg/immed/symb */
    122      1.1  christos   struct itbl_range range;	/* field's bitfield range within instruction */
    123      1.1  christos   unsigned long flags;		/* field flags */
    124      1.1  christos   struct itbl_field *next;	/* next field in list */
    125      1.1  christos };
    126      1.1  christos 
    127      1.1  christos /* These structures define the instructions and registers for a processor.
    128      1.1  christos  * If the type is an instruction, the structure defines the format of an
    129      1.1  christos  * instruction where the fields are the list of operands.
    130      1.1  christos  * The flags field below uses the same values as those defined in the
    131      1.1  christos  * gnu assembler and are machine specific.  */
    132      1.1  christos struct itbl_entry {
    133      1.1  christos   e_processor processor;	/* processor number */
    134      1.1  christos   e_type type;			/* dreg/creg/greg/insn */
    135  1.1.1.4  christos   char *name;			/* mnemonic name for insn/register */
    136      1.1  christos   unsigned long value;		/* opcode/instruction mask/register number */
    137      1.1  christos   unsigned long flags;		/* effects of the instruction */
    138      1.1  christos   struct itbl_range range;	/* bit range within instruction for value */
    139      1.1  christos   struct itbl_field *fields;	/* list of operand definitions (if any) */
    140      1.1  christos   struct itbl_entry *next;	/* next entry */
    141      1.1  christos };
    142      1.1  christos 
    143      1.1  christos /* local data and structures */
    144      1.1  christos 
    145      1.1  christos static int itbl_num_opcodes = 0;
    146      1.1  christos /* Array of entries for each processor and entry type */
    147      1.1  christos static struct itbl_entry *entries[e_nprocs][e_ntypes];
    148      1.1  christos 
    149      1.1  christos /* local prototypes */
    150      1.1  christos static unsigned long build_opcode (struct itbl_entry *e);
    151      1.1  christos static e_type get_type (int yytype);
    152      1.1  christos static e_processor get_processor (int yyproc);
    153      1.1  christos static struct itbl_entry **get_entries (e_processor processor,
    154      1.1  christos 					e_type type);
    155      1.1  christos static struct itbl_entry *find_entry_byname (e_processor processor,
    156      1.1  christos 					e_type type, char *name);
    157      1.1  christos static struct itbl_entry *find_entry_byval (e_processor processor,
    158      1.1  christos 			e_type type, unsigned long val, struct itbl_range *r);
    159      1.1  christos static struct itbl_entry *alloc_entry (e_processor processor,
    160      1.1  christos 		e_type type, char *name, unsigned long value);
    161      1.1  christos static unsigned long apply_range (unsigned long value, struct itbl_range r);
    162      1.1  christos static unsigned long extract_range (unsigned long value, struct itbl_range r);
    163      1.1  christos static struct itbl_field *alloc_field (e_type type, int sbit,
    164      1.1  christos 					int ebit, unsigned long flags);
    165      1.1  christos 
    166      1.1  christos /*======================================================================*/
    167      1.1  christos /* Interfaces to the parser */
    168      1.1  christos 
    169      1.1  christos /* Open the table and use lex and yacc to parse the entries.
    170      1.1  christos  * Return 1 for failure; 0 for success.  */
    171      1.1  christos 
    172      1.1  christos int
    173      1.1  christos itbl_parse (char *insntbl)
    174      1.1  christos {
    175      1.1  christos   extern FILE *yyin;
    176      1.1  christos   extern int yyparse (void);
    177      1.1  christos 
    178      1.1  christos   yyin = fopen (insntbl, FOPEN_RT);
    179      1.1  christos   if (yyin == 0)
    180      1.1  christos     {
    181      1.1  christos       printf ("Can't open processor instruction specification file \"%s\"\n",
    182      1.1  christos 	      insntbl);
    183      1.1  christos       return 1;
    184      1.1  christos     }
    185      1.1  christos 
    186      1.1  christos   while (yyparse ())
    187      1.1  christos     ;
    188      1.1  christos 
    189      1.1  christos   fclose (yyin);
    190      1.1  christos   itbl_have_entries = 1;
    191      1.1  christos   return 0;
    192      1.1  christos }
    193      1.1  christos 
    194      1.1  christos /* Add a register entry */
    195      1.1  christos 
    196      1.1  christos struct itbl_entry *
    197      1.1  christos itbl_add_reg (int yyprocessor, int yytype, char *regname,
    198      1.1  christos 	      int regnum)
    199      1.1  christos {
    200      1.1  christos   return alloc_entry (get_processor (yyprocessor), get_type (yytype), regname,
    201      1.1  christos 		      (unsigned long) regnum);
    202      1.1  christos }
    203      1.1  christos 
    204      1.1  christos /* Add an instruction entry */
    205      1.1  christos 
    206      1.1  christos struct itbl_entry *
    207      1.1  christos itbl_add_insn (int yyprocessor, char *name, unsigned long value,
    208      1.1  christos 	       int sbit, int ebit, unsigned long flags)
    209      1.1  christos {
    210      1.1  christos   struct itbl_entry *e;
    211      1.1  christos   e = alloc_entry (get_processor (yyprocessor), e_insn, name, value);
    212      1.1  christos   if (e)
    213      1.1  christos     {
    214      1.1  christos       e->range.sbit = sbit;
    215      1.1  christos       e->range.ebit = ebit;
    216      1.1  christos       e->flags = flags;
    217      1.1  christos       itbl_num_opcodes++;
    218      1.1  christos     }
    219      1.1  christos   return e;
    220      1.1  christos }
    221      1.1  christos 
    222      1.1  christos /* Add an operand to an instruction entry */
    223      1.1  christos 
    224      1.1  christos struct itbl_field *
    225      1.1  christos itbl_add_operand (struct itbl_entry *e, int yytype, int sbit,
    226      1.1  christos 		  int ebit, unsigned long flags)
    227      1.1  christos {
    228      1.1  christos   struct itbl_field *f, **last_f;
    229      1.1  christos   if (!e)
    230      1.1  christos     return 0;
    231      1.1  christos   /* Add to end of fields' list.  */
    232      1.1  christos   f = alloc_field (get_type (yytype), sbit, ebit, flags);
    233      1.1  christos   if (f)
    234      1.1  christos     {
    235      1.1  christos       last_f = &e->fields;
    236      1.1  christos       while (*last_f)
    237      1.1  christos 	last_f = &(*last_f)->next;
    238      1.1  christos       *last_f = f;
    239      1.1  christos       f->next = 0;
    240      1.1  christos     }
    241      1.1  christos   return f;
    242      1.1  christos }
    243      1.1  christos 
    244      1.1  christos /*======================================================================*/
    245      1.1  christos /* Interfaces for assembler and disassembler */
    246      1.1  christos 
    247      1.1  christos #ifndef STAND_ALONE
    248      1.1  christos static void append_insns_as_macros (void);
    249      1.1  christos 
    250      1.1  christos /* Initialize for gas.  */
    251      1.1  christos 
    252      1.1  christos void
    253      1.1  christos itbl_init (void)
    254      1.1  christos {
    255      1.1  christos   struct itbl_entry *e, **es;
    256      1.1  christos   e_processor procn;
    257      1.1  christos   e_type type;
    258      1.1  christos 
    259      1.1  christos   if (!itbl_have_entries)
    260      1.1  christos     return;
    261      1.1  christos 
    262      1.1  christos   /* Since register names don't have a prefix, put them in the symbol table so
    263      1.1  christos      they can't be used as symbols.  This simplifies argument parsing as
    264      1.1  christos      we can let gas parse registers for us.  */
    265      1.1  christos   /* Use symbol_create instead of symbol_new so we don't try to
    266      1.1  christos      output registers into the object file's symbol table.  */
    267      1.1  christos 
    268      1.1  christos   for (type = e_regtype0; type < e_nregtypes; type++)
    269      1.1  christos     for (procn = e_p0; procn < e_nprocs; procn++)
    270      1.1  christos       {
    271      1.1  christos 	es = get_entries (procn, type);
    272      1.1  christos 	for (e = *es; e; e = e->next)
    273      1.1  christos 	  {
    274      1.1  christos 	    symbol_table_insert (symbol_create (e->name, reg_section,
    275  1.1.1.6  christos 						&zero_address_frag, e->value));
    276      1.1  christos 	  }
    277      1.1  christos       }
    278      1.1  christos   append_insns_as_macros ();
    279      1.1  christos }
    280      1.1  christos 
    281      1.1  christos /* Append insns to opcodes table and increase number of opcodes
    282      1.1  christos  * Structure of opcodes table:
    283      1.1  christos  * struct itbl_opcode
    284      1.1  christos  * {
    285      1.1  christos  *   const char *name;
    286      1.1  christos  *   const char *args; 		- string describing the arguments.
    287      1.1  christos  *   unsigned long match; 	- opcode, or ISA level if pinfo=INSN_MACRO
    288      1.1  christos  *   unsigned long mask; 	- opcode mask, or macro id if pinfo=INSN_MACRO
    289      1.1  christos  *   unsigned long pinfo; 	- insn flags, or INSN_MACRO
    290      1.1  christos  * };
    291      1.1  christos  * examples:
    292      1.1  christos  *	{"li",      "t,i",  0x34000000, 0xffe00000, WR_t    },
    293      1.1  christos  *	{"li",      "t,I",  0,    (int) M_LI,   INSN_MACRO  },
    294      1.1  christos  */
    295      1.1  christos 
    296      1.1  christos static char *form_args (struct itbl_entry *e);
    297      1.1  christos static void
    298      1.1  christos append_insns_as_macros (void)
    299      1.1  christos {
    300      1.1  christos   struct ITBL_OPCODE_STRUCT *new_opcodes, *o;
    301      1.1  christos   struct itbl_entry *e, **es;
    302  1.1.1.3  christos   int n, size, new_num_opcodes;
    303      1.1  christos #ifdef USE_MACROS
    304      1.1  christos   int id;
    305      1.1  christos #endif
    306      1.1  christos 
    307      1.1  christos   if (!itbl_have_entries)
    308      1.1  christos     return;
    309      1.1  christos 
    310      1.1  christos   if (!itbl_num_opcodes)	/* no new instructions to add! */
    311      1.1  christos     {
    312      1.1  christos       return;
    313      1.1  christos     }
    314      1.1  christos   DBG (("previous num_opcodes=%d\n", ITBL_NUM_OPCODES));
    315      1.1  christos 
    316      1.1  christos   new_num_opcodes = ITBL_NUM_OPCODES + itbl_num_opcodes;
    317      1.1  christos   ASSERT (new_num_opcodes >= itbl_num_opcodes);
    318      1.1  christos 
    319      1.1  christos   size = sizeof (struct ITBL_OPCODE_STRUCT) * ITBL_NUM_OPCODES;
    320      1.1  christos   ASSERT (size >= 0);
    321      1.1  christos   DBG (("I get=%d\n", size / sizeof (ITBL_OPCODES[0])));
    322      1.1  christos 
    323  1.1.1.4  christos   /* FIXME since ITBL_OPCODES could be a static table,
    324      1.1  christos 		we can't realloc or delete the old memory.  */
    325  1.1.1.3  christos   new_opcodes = XNEWVEC (struct ITBL_OPCODE_STRUCT, new_num_opcodes);
    326      1.1  christos   if (!new_opcodes)
    327      1.1  christos     {
    328      1.1  christos       printf (_("Unable to allocate memory for new instructions\n"));
    329      1.1  christos       return;
    330      1.1  christos     }
    331      1.1  christos   if (size)			/* copy preexisting opcodes table */
    332      1.1  christos     memcpy (new_opcodes, ITBL_OPCODES, size);
    333      1.1  christos 
    334      1.1  christos   /* FIXME! some NUMOPCODES are calculated expressions.
    335      1.1  christos 		These need to be changed before itbls can be supported.  */
    336      1.1  christos 
    337      1.1  christos #ifdef USE_MACROS
    338      1.1  christos   id = ITBL_NUM_MACROS;		/* begin the next macro id after the last */
    339      1.1  christos #endif
    340      1.1  christos   o = &new_opcodes[ITBL_NUM_OPCODES];	/* append macro to opcodes list */
    341      1.1  christos   for (n = e_p0; n < e_nprocs; n++)
    342      1.1  christos     {
    343      1.1  christos       es = get_entries (n, e_insn);
    344      1.1  christos       for (e = *es; e; e = e->next)
    345      1.1  christos 	{
    346      1.1  christos 	  /* name,    args,   mask,       match,  pinfo
    347      1.1  christos 		 * {"li",      "t,i",  0x34000000, 0xffe00000, WR_t    },
    348      1.1  christos 		 * {"li",      "t,I",  0,    (int) M_LI,   INSN_MACRO  },
    349      1.1  christos 		 * Construct args from itbl_fields.
    350      1.1  christos 		*/
    351      1.1  christos 	  o->name = e->name;
    352      1.1  christos 	  o->args = strdup (form_args (e));
    353      1.1  christos 	  o->mask = apply_range (e->value, e->range);
    354      1.1  christos 	  /* FIXME how to catch during assembly? */
    355      1.1  christos 	  /* mask to identify this insn */
    356      1.1  christos 	  o->match = apply_range (e->value, e->range);
    357      1.1  christos 	  o->pinfo = 0;
    358      1.1  christos 
    359      1.1  christos #ifdef USE_MACROS
    360      1.1  christos 	  o->mask = id++;	/* FIXME how to catch during assembly? */
    361      1.1  christos 	  o->match = 0;		/* for macros, the insn_isa number */
    362      1.1  christos 	  o->pinfo = INSN_MACRO;
    363      1.1  christos #endif
    364      1.1  christos 
    365      1.1  christos 	  /* Don't add instructions which caused an error */
    366      1.1  christos 	  if (o->args)
    367      1.1  christos 	    o++;
    368      1.1  christos 	  else
    369      1.1  christos 	    new_num_opcodes--;
    370      1.1  christos 	}
    371      1.1  christos     }
    372      1.1  christos   ITBL_OPCODES = new_opcodes;
    373      1.1  christos   ITBL_NUM_OPCODES = new_num_opcodes;
    374      1.1  christos 
    375      1.1  christos   /* FIXME
    376      1.1  christos 		At this point, we can free the entries, as they should have
    377      1.1  christos 		been added to the assembler's tables.
    378      1.1  christos 		Don't free name though, since name is being used by the new
    379      1.1  christos 		opcodes table.
    380      1.1  christos 
    381      1.1  christos 		Eventually, we should also free the new opcodes table itself
    382      1.1  christos 		on exit.
    383      1.1  christos 	*/
    384      1.1  christos }
    385      1.1  christos 
    386      1.1  christos static char *
    387      1.1  christos form_args (struct itbl_entry *e)
    388      1.1  christos {
    389      1.1  christos   static char s[31];
    390      1.1  christos   char c = 0, *p = s;
    391      1.1  christos   struct itbl_field *f;
    392      1.1  christos 
    393      1.1  christos   ASSERT (e);
    394      1.1  christos   for (f = e->fields; f; f = f->next)
    395      1.1  christos     {
    396      1.1  christos       switch (f->type)
    397      1.1  christos 	{
    398      1.1  christos 	case e_dreg:
    399      1.1  christos 	  c = 'd';
    400      1.1  christos 	  break;
    401      1.1  christos 	case e_creg:
    402      1.1  christos 	  c = 't';
    403      1.1  christos 	  break;
    404      1.1  christos 	case e_greg:
    405      1.1  christos 	  c = 's';
    406      1.1  christos 	  break;
    407      1.1  christos 	case e_immed:
    408      1.1  christos 	  c = 'i';
    409      1.1  christos 	  break;
    410      1.1  christos 	case e_addr:
    411      1.1  christos 	  c = 'a';
    412      1.1  christos 	  break;
    413      1.1  christos 	default:
    414      1.1  christos 	  c = 0;		/* ignore; unknown field type */
    415      1.1  christos 	}
    416      1.1  christos       if (c)
    417      1.1  christos 	{
    418      1.1  christos 	  if (p != s)
    419      1.1  christos 	    *p++ = ',';
    420      1.1  christos 	  *p++ = c;
    421      1.1  christos 	}
    422      1.1  christos     }
    423      1.1  christos   *p = 0;
    424      1.1  christos   return s;
    425      1.1  christos }
    426      1.1  christos #endif /* !STAND_ALONE */
    427      1.1  christos 
    428      1.1  christos /* Get processor's register name from val */
    429      1.1  christos 
    430      1.1  christos int
    431      1.1  christos itbl_get_reg_val (char *name, unsigned long *pval)
    432      1.1  christos {
    433      1.1  christos   e_type t;
    434      1.1  christos   e_processor p;
    435      1.1  christos 
    436      1.1  christos   for (p = e_p0; p < e_nprocs; p++)
    437      1.1  christos     {
    438      1.1  christos       for (t = e_regtype0; t < e_nregtypes; t++)
    439      1.1  christos 	{
    440      1.1  christos 	  if (itbl_get_val (p, t, name, pval))
    441      1.1  christos 	    return 1;
    442      1.1  christos 	}
    443      1.1  christos     }
    444      1.1  christos   return 0;
    445      1.1  christos }
    446      1.1  christos 
    447      1.1  christos char *
    448      1.1  christos itbl_get_name (e_processor processor, e_type type, unsigned long val)
    449      1.1  christos {
    450      1.1  christos   struct itbl_entry *r;
    451      1.1  christos   /* type depends on instruction passed */
    452      1.1  christos   r = find_entry_byval (processor, type, val, 0);
    453      1.1  christos   if (r)
    454      1.1  christos     return r->name;
    455      1.1  christos   else
    456      1.1  christos     return 0;			/* error; invalid operand */
    457      1.1  christos }
    458      1.1  christos 
    459      1.1  christos /* Get processor's register value from name */
    460      1.1  christos 
    461      1.1  christos int
    462      1.1  christos itbl_get_val (e_processor processor, e_type type, char *name,
    463      1.1  christos 	      unsigned long *pval)
    464      1.1  christos {
    465      1.1  christos   struct itbl_entry *r;
    466      1.1  christos   /* type depends on instruction passed */
    467      1.1  christos   r = find_entry_byname (processor, type, name);
    468      1.1  christos   if (r == NULL)
    469      1.1  christos     return 0;
    470      1.1  christos   *pval = r->value;
    471      1.1  christos   return 1;
    472      1.1  christos }
    473      1.1  christos 
    474      1.1  christos /* Assemble instruction "name" with operands "s".
    475      1.1  christos  * name - name of instruction
    476      1.1  christos  * s - operands
    477      1.1  christos  * returns - long word for assembled instruction */
    478      1.1  christos 
    479      1.1  christos unsigned long
    480      1.1  christos itbl_assemble (char *name, char *s)
    481      1.1  christos {
    482      1.1  christos   unsigned long opcode;
    483      1.1  christos   struct itbl_entry *e = NULL;
    484      1.1  christos   struct itbl_field *f;
    485      1.1  christos   char *n;
    486      1.1  christos   int processor;
    487      1.1  christos 
    488      1.1  christos   if (!name || !*name)
    489      1.1  christos     return 0;			/* error!  must have an opcode name/expr */
    490      1.1  christos 
    491      1.1  christos   /* find entry in list of instructions for all processors */
    492      1.1  christos   for (processor = 0; processor < e_nprocs; processor++)
    493      1.1  christos     {
    494      1.1  christos       e = find_entry_byname (processor, e_insn, name);
    495      1.1  christos       if (e)
    496      1.1  christos 	break;
    497      1.1  christos     }
    498      1.1  christos   if (!e)
    499      1.1  christos     return 0;			/* opcode not in table; invalid instruction */
    500      1.1  christos   opcode = build_opcode (e);
    501      1.1  christos 
    502      1.1  christos   /* parse opcode's args (if any) */
    503      1.1  christos   for (f = e->fields; f; f = f->next)	/* for each arg, ...  */
    504      1.1  christos     {
    505      1.1  christos       struct itbl_entry *r;
    506      1.1  christos       unsigned long value;
    507      1.1  christos       if (!s || !*s)
    508      1.1  christos 	return 0;		/* error - not enough operands */
    509      1.1  christos       n = itbl_get_field (&s);
    510      1.1  christos       /* n should be in form $n or 0xhhh (are symbol names valid?? */
    511      1.1  christos       switch (f->type)
    512      1.1  christos 	{
    513      1.1  christos 	case e_dreg:
    514      1.1  christos 	case e_creg:
    515      1.1  christos 	case e_greg:
    516      1.1  christos 	  /* Accept either a string name
    517      1.1  christos 			 * or '$' followed by the register number */
    518      1.1  christos 	  if (*n == '$')
    519      1.1  christos 	    {
    520      1.1  christos 	      n++;
    521      1.1  christos 	      value = strtol (n, 0, 10);
    522      1.1  christos 	      /* FIXME! could have "0l"... then what?? */
    523      1.1  christos 	      if (value == 0 && *n != '0')
    524      1.1  christos 		return 0;	/* error; invalid operand */
    525      1.1  christos 	    }
    526      1.1  christos 	  else
    527      1.1  christos 	    {
    528      1.1  christos 	      r = find_entry_byname (e->processor, f->type, n);
    529      1.1  christos 	      if (r)
    530      1.1  christos 		value = r->value;
    531      1.1  christos 	      else
    532      1.1  christos 		return 0;	/* error; invalid operand */
    533      1.1  christos 	    }
    534      1.1  christos 	  break;
    535      1.1  christos 	case e_addr:
    536      1.1  christos 	  /* use assembler's symbol table to find symbol */
    537      1.1  christos 	  /* FIXME!! Do we need this?
    538      1.1  christos 				if so, what about relocs??
    539      1.1  christos 				my_getExpression (&imm_expr, s);
    540      1.1  christos 				return 0;	/-* error; invalid operand *-/
    541      1.1  christos 				break;
    542      1.1  christos 			*/
    543  1.1.1.4  christos 	  /* If not a symbol, fallthru to IMMED */
    544      1.1  christos 	case e_immed:
    545      1.1  christos 	  if (*n == '0' && *(n + 1) == 'x')	/* hex begins 0x...  */
    546      1.1  christos 	    {
    547      1.1  christos 	      n += 2;
    548      1.1  christos 	      value = strtol (n, 0, 16);
    549      1.1  christos 	      /* FIXME! could have "0xl"... then what?? */
    550      1.1  christos 	    }
    551      1.1  christos 	  else
    552      1.1  christos 	    {
    553      1.1  christos 	      value = strtol (n, 0, 10);
    554      1.1  christos 	      /* FIXME! could have "0l"... then what?? */
    555      1.1  christos 	      if (value == 0 && *n != '0')
    556      1.1  christos 		return 0;	/* error; invalid operand */
    557      1.1  christos 	    }
    558      1.1  christos 	  break;
    559      1.1  christos 	default:
    560      1.1  christos 	  return 0;		/* error; invalid field spec */
    561      1.1  christos 	}
    562      1.1  christos       opcode |= apply_range (value, f->range);
    563      1.1  christos     }
    564      1.1  christos   if (s && *s)
    565      1.1  christos     return 0;			/* error - too many operands */
    566      1.1  christos   return opcode;		/* done! */
    567      1.1  christos }
    568      1.1  christos 
    569      1.1  christos /* Disassemble instruction "insn".
    570      1.1  christos  * insn - instruction
    571      1.1  christos  * s - buffer to hold disassembled instruction
    572      1.1  christos  * returns - 1 if succeeded; 0 if failed
    573      1.1  christos  */
    574      1.1  christos 
    575      1.1  christos int
    576      1.1  christos itbl_disassemble (char *s, unsigned long insn)
    577      1.1  christos {
    578      1.1  christos   e_processor processor;
    579      1.1  christos   struct itbl_entry *e;
    580      1.1  christos   struct itbl_field *f;
    581      1.1  christos 
    582      1.1  christos   if (!ITBL_IS_INSN (insn))
    583      1.1  christos     return 0;			/* error */
    584      1.1  christos   processor = get_processor (ITBL_DECODE_PNUM (insn));
    585      1.1  christos 
    586      1.1  christos   /* find entry in list */
    587      1.1  christos   e = find_entry_byval (processor, e_insn, insn, 0);
    588      1.1  christos   if (!e)
    589      1.1  christos     return 0;			/* opcode not in table; invalid instruction */
    590      1.1  christos   strcpy (s, e->name);
    591      1.1  christos 
    592      1.1  christos   /* Parse insn's args (if any).  */
    593      1.1  christos   for (f = e->fields; f; f = f->next)	/* for each arg, ...  */
    594      1.1  christos     {
    595      1.1  christos       struct itbl_entry *r;
    596      1.1  christos       unsigned long value;
    597      1.1  christos       char s_value[20];
    598      1.1  christos 
    599      1.1  christos       if (f == e->fields)	/* First operand is preceded by tab.  */
    600      1.1  christos 	strcat (s, "\t");
    601      1.1  christos       else			/* ','s separate following operands.  */
    602      1.1  christos 	strcat (s, ",");
    603      1.1  christos       value = extract_range (insn, f->range);
    604      1.1  christos       /* n should be in form $n or 0xhhh (are symbol names valid?? */
    605      1.1  christos       switch (f->type)
    606      1.1  christos 	{
    607      1.1  christos 	case e_dreg:
    608      1.1  christos 	case e_creg:
    609      1.1  christos 	case e_greg:
    610      1.1  christos 	  /* Accept either a string name
    611      1.1  christos 	     or '$' followed by the register number.  */
    612      1.1  christos 	  r = find_entry_byval (e->processor, f->type, value, &f->range);
    613      1.1  christos 	  if (r)
    614      1.1  christos 	    strcat (s, r->name);
    615      1.1  christos 	  else
    616      1.1  christos 	    {
    617      1.1  christos 	      sprintf (s_value, "$%lu", value);
    618      1.1  christos 	      strcat (s, s_value);
    619      1.1  christos 	    }
    620      1.1  christos 	  break;
    621      1.1  christos 	case e_addr:
    622      1.1  christos 	  /* Use assembler's symbol table to find symbol.  */
    623      1.1  christos 	  /* FIXME!! Do we need this?  If so, what about relocs??  */
    624      1.1  christos 	  /* If not a symbol, fall through to IMMED.  */
    625      1.1  christos 	case e_immed:
    626      1.1  christos 	  sprintf (s_value, "0x%lx", value);
    627      1.1  christos 	  strcat (s, s_value);
    628      1.1  christos 	  break;
    629      1.1  christos 	default:
    630      1.1  christos 	  return 0;		/* error; invalid field spec */
    631      1.1  christos 	}
    632      1.1  christos     }
    633      1.1  christos   return 1;			/* Done!  */
    634      1.1  christos }
    635      1.1  christos 
    636      1.1  christos /*======================================================================*/
    637      1.1  christos /*
    638      1.1  christos  * Local functions for manipulating private structures containing
    639      1.1  christos  * the names and format for the new instructions and registers
    640      1.1  christos  * for each processor.
    641      1.1  christos  */
    642      1.1  christos 
    643      1.1  christos /* Calculate instruction's opcode and function values from entry */
    644      1.1  christos 
    645      1.1  christos static unsigned long
    646      1.1  christos build_opcode (struct itbl_entry *e)
    647      1.1  christos {
    648      1.1  christos   unsigned long opcode;
    649      1.1  christos 
    650      1.1  christos   opcode = apply_range (e->value, e->range);
    651      1.1  christos   opcode |= ITBL_ENCODE_PNUM (e->processor);
    652      1.1  christos   return opcode;
    653      1.1  christos }
    654      1.1  christos 
    655      1.1  christos /* Calculate absolute value given the relative value and bit position range
    656      1.1  christos  * within the instruction.
    657      1.1  christos  * The range is inclusive where 0 is least significant bit.
    658      1.1  christos  * A range of { 24, 20 } will have a mask of
    659      1.1  christos  * bit   3           2            1
    660      1.1  christos  * pos: 1098 7654 3210 9876 5432 1098 7654 3210
    661      1.1  christos  * bin: 0000 0001 1111 0000 0000 0000 0000 0000
    662      1.1  christos  * hex:    0    1    f    0    0    0    0    0
    663      1.1  christos  * mask: 0x01f00000.
    664      1.1  christos  */
    665      1.1  christos 
    666      1.1  christos static unsigned long
    667      1.1  christos apply_range (unsigned long rval, struct itbl_range r)
    668      1.1  christos {
    669      1.1  christos   unsigned long mask;
    670      1.1  christos   unsigned long aval;
    671      1.1  christos   int len = MAX_BITPOS - r.sbit;
    672      1.1  christos 
    673      1.1  christos   ASSERT (r.sbit >= r.ebit);
    674      1.1  christos   ASSERT (MAX_BITPOS >= r.sbit);
    675      1.1  christos   ASSERT (r.ebit >= 0);
    676      1.1  christos 
    677      1.1  christos   /* create mask by truncating 1s by shifting */
    678      1.1  christos   mask = 0xffffffff << len;
    679      1.1  christos   mask = mask >> len;
    680      1.1  christos   mask = mask >> r.ebit;
    681      1.1  christos   mask = mask << r.ebit;
    682      1.1  christos 
    683      1.1  christos   aval = (rval << r.ebit) & mask;
    684      1.1  christos   return aval;
    685      1.1  christos }
    686      1.1  christos 
    687      1.1  christos /* Calculate relative value given the absolute value and bit position range
    688      1.1  christos  * within the instruction.  */
    689      1.1  christos 
    690      1.1  christos static unsigned long
    691      1.1  christos extract_range (unsigned long aval, struct itbl_range r)
    692      1.1  christos {
    693      1.1  christos   unsigned long mask;
    694      1.1  christos   unsigned long rval;
    695      1.1  christos   int len = MAX_BITPOS - r.sbit;
    696      1.1  christos 
    697      1.1  christos   /* create mask by truncating 1s by shifting */
    698      1.1  christos   mask = 0xffffffff << len;
    699      1.1  christos   mask = mask >> len;
    700      1.1  christos   mask = mask >> r.ebit;
    701      1.1  christos   mask = mask << r.ebit;
    702      1.1  christos 
    703      1.1  christos   rval = (aval & mask) >> r.ebit;
    704      1.1  christos   return rval;
    705      1.1  christos }
    706      1.1  christos 
    707      1.1  christos /* Extract processor's assembly instruction field name from s;
    708      1.1  christos  * forms are "n args" "n,args" or "n" */
    709      1.1  christos /* Return next argument from string pointer "s" and advance s.
    710      1.1  christos  * delimiters are " ,()" */
    711      1.1  christos 
    712      1.1  christos char *
    713      1.1  christos itbl_get_field (char **S)
    714      1.1  christos {
    715      1.1  christos   static char n[128];
    716      1.1  christos   char *s;
    717      1.1  christos   int len;
    718      1.1  christos 
    719      1.1  christos   s = *S;
    720      1.1  christos   if (!s || !*s)
    721      1.1  christos     return 0;
    722      1.1  christos   /* FIXME: This is a weird set of delimiters.  */
    723      1.1  christos   len = strcspn (s, " \t,()");
    724      1.1  christos   ASSERT (128 > len + 1);
    725      1.1  christos   strncpy (n, s, len);
    726      1.1  christos   n[len] = 0;
    727      1.1  christos   if (s[len] == '\0')
    728      1.1  christos     s = 0;			/* no more args */
    729      1.1  christos   else
    730      1.1  christos     s += len + 1;		/* advance to next arg */
    731      1.1  christos 
    732      1.1  christos   *S = s;
    733      1.1  christos   return n;
    734      1.1  christos }
    735      1.1  christos 
    736      1.1  christos /* Search entries for a given processor and type
    737      1.1  christos  * to find one matching the name "n".
    738      1.1  christos  * Return a pointer to the entry */
    739      1.1  christos 
    740      1.1  christos static struct itbl_entry *
    741      1.1  christos find_entry_byname (e_processor processor,
    742      1.1  christos 		   e_type type, char *n)
    743      1.1  christos {
    744      1.1  christos   struct itbl_entry *e, **es;
    745      1.1  christos 
    746      1.1  christos   es = get_entries (processor, type);
    747      1.1  christos   for (e = *es; e; e = e->next)	/* for each entry, ...  */
    748      1.1  christos     {
    749      1.1  christos       if (!strcmp (e->name, n))
    750      1.1  christos 	return e;
    751      1.1  christos     }
    752      1.1  christos   return 0;
    753      1.1  christos }
    754      1.1  christos 
    755      1.1  christos /* Search entries for a given processor and type
    756      1.1  christos  * to find one matching the value "val" for the range "r".
    757      1.1  christos  * Return a pointer to the entry.
    758      1.1  christos  * This function is used for disassembling fields of an instruction.
    759      1.1  christos  */
    760      1.1  christos 
    761      1.1  christos static struct itbl_entry *
    762      1.1  christos find_entry_byval (e_processor processor, e_type type,
    763      1.1  christos 		  unsigned long val, struct itbl_range *r)
    764      1.1  christos {
    765      1.1  christos   struct itbl_entry *e, **es;
    766      1.1  christos   unsigned long eval;
    767      1.1  christos 
    768      1.1  christos   es = get_entries (processor, type);
    769      1.1  christos   for (e = *es; e; e = e->next)	/* for each entry, ...  */
    770      1.1  christos     {
    771      1.1  christos       if (processor != e->processor)
    772      1.1  christos 	continue;
    773      1.1  christos       /* For insns, we might not know the range of the opcode,
    774      1.1  christos 	 * so a range of 0 will allow this routine to match against
    775      1.1  christos 	 * the range of the entry to be compared with.
    776      1.1  christos 	 * This could cause ambiguities.
    777      1.1  christos 	 * For operands, we get an extracted value and a range.
    778      1.1  christos 	 */
    779      1.1  christos       /* if range is 0, mask val against the range of the compared entry.  */
    780      1.1  christos       if (r == 0)		/* if no range passed, must be whole 32-bits
    781      1.1  christos 			 * so create 32-bit value from entry's range */
    782      1.1  christos 	{
    783      1.1  christos 	  eval = apply_range (e->value, e->range);
    784      1.1  christos 	  val &= apply_range (0xffffffff, e->range);
    785      1.1  christos 	}
    786      1.1  christos       else if ((r->sbit == e->range.sbit && r->ebit == e->range.ebit)
    787      1.1  christos 	       || (e->range.sbit == 0 && e->range.ebit == 0))
    788      1.1  christos 	{
    789      1.1  christos 	  eval = apply_range (e->value, *r);
    790      1.1  christos 	  val = apply_range (val, *r);
    791      1.1  christos 	}
    792      1.1  christos       else
    793      1.1  christos 	continue;
    794      1.1  christos       if (val == eval)
    795      1.1  christos 	return e;
    796      1.1  christos     }
    797      1.1  christos   return 0;
    798      1.1  christos }
    799      1.1  christos 
    800      1.1  christos /* Return a pointer to the list of entries for a given processor and type.  */
    801      1.1  christos 
    802      1.1  christos static struct itbl_entry **
    803      1.1  christos get_entries (e_processor processor, e_type type)
    804      1.1  christos {
    805      1.1  christos   return &entries[processor][type];
    806      1.1  christos }
    807      1.1  christos 
    808      1.1  christos /* Return an integral value for the processor passed from yyparse.  */
    809      1.1  christos 
    810      1.1  christos static e_processor
    811      1.1  christos get_processor (int yyproc)
    812      1.1  christos {
    813      1.1  christos   /* translate from yacc's processor to enum */
    814      1.1  christos   if (yyproc >= e_p0 && yyproc < e_nprocs)
    815      1.1  christos     return (e_processor) yyproc;
    816      1.1  christos   return e_invproc;		/* error; invalid processor */
    817      1.1  christos }
    818      1.1  christos 
    819      1.1  christos /* Return an integral value for the entry type passed from yyparse.  */
    820      1.1  christos 
    821      1.1  christos static e_type
    822      1.1  christos get_type (int yytype)
    823      1.1  christos {
    824      1.1  christos   switch (yytype)
    825      1.1  christos     {
    826      1.1  christos       /* translate from yacc's type to enum */
    827      1.1  christos     case INSN:
    828      1.1  christos       return e_insn;
    829      1.1  christos     case DREG:
    830      1.1  christos       return e_dreg;
    831      1.1  christos     case CREG:
    832      1.1  christos       return e_creg;
    833      1.1  christos     case GREG:
    834      1.1  christos       return e_greg;
    835      1.1  christos     case ADDR:
    836      1.1  christos       return e_addr;
    837      1.1  christos     case IMMED:
    838      1.1  christos       return e_immed;
    839      1.1  christos     default:
    840      1.1  christos       return e_invtype;		/* error; invalid type */
    841      1.1  christos     }
    842      1.1  christos }
    843      1.1  christos 
    844      1.1  christos /* Allocate and initialize an entry */
    845      1.1  christos 
    846      1.1  christos static struct itbl_entry *
    847      1.1  christos alloc_entry (e_processor processor, e_type type,
    848      1.1  christos 	     char *name, unsigned long value)
    849      1.1  christos {
    850      1.1  christos   struct itbl_entry *e, **es;
    851      1.1  christos   if (!name)
    852      1.1  christos     return 0;
    853  1.1.1.3  christos   e = XNEW (struct itbl_entry);
    854      1.1  christos   if (e)
    855      1.1  christos     {
    856      1.1  christos       memset (e, 0, sizeof (struct itbl_entry));
    857  1.1.1.3  christos       e->name = xstrdup (name);
    858      1.1  christos       e->processor = processor;
    859      1.1  christos       e->type = type;
    860      1.1  christos       e->value = value;
    861      1.1  christos       es = get_entries (e->processor, e->type);
    862      1.1  christos       e->next = *es;
    863      1.1  christos       *es = e;
    864      1.1  christos     }
    865      1.1  christos   return e;
    866      1.1  christos }
    867      1.1  christos 
    868      1.1  christos /* Allocate and initialize an entry's field */
    869      1.1  christos 
    870      1.1  christos static struct itbl_field *
    871      1.1  christos alloc_field (e_type type, int sbit, int ebit,
    872      1.1  christos 	     unsigned long flags)
    873      1.1  christos {
    874      1.1  christos   struct itbl_field *f;
    875  1.1.1.3  christos   f = XNEW (struct itbl_field);
    876      1.1  christos   if (f)
    877      1.1  christos     {
    878      1.1  christos       memset (f, 0, sizeof (struct itbl_field));
    879      1.1  christos       f->type = type;
    880      1.1  christos       f->range.sbit = sbit;
    881      1.1  christos       f->range.ebit = ebit;
    882      1.1  christos       f->flags = flags;
    883      1.1  christos     }
    884      1.1  christos   return f;
    885      1.1  christos }
    886