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