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