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