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