X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fitbl-ops.c;h=b7be04fc9ce0496abced089b3870901493106e56;hb=e379e5f385f874adb0b414f917adb1fc50e20de9;hp=f008dcafebc4aa060769c2166cb5ec6ff97cc4a0;hpb=5b64ad42d36e6d487e1f7287d37fbc243a178e72;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/itbl-ops.c b/gas/itbl-ops.c index f008dcafeb..b7be04fc9c 100644 --- a/gas/itbl-ops.c +++ b/gas/itbl-ops.c @@ -1,11 +1,11 @@ /* itbl-ops.c - Copyright (C) 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1997-2019 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -15,8 +15,8 @@ You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ /*======================================================================*/ /* @@ -88,17 +88,15 @@ * */ -#include -#include -#include +#include "as.h" #include "itbl-ops.h" -#include "itbl-parse.h" +#include /* #define DEBUG */ #ifdef DEBUG #include -#define ASSERT(x) assert(x) +#define ASSERT(x) gas_assert (x) #define DBG(x) printf x #else #define ASSERT(x) @@ -114,94 +112,80 @@ int itbl_have_entries = 0; /*======================================================================*/ /* structures for keeping itbl format entries */ -struct itbl_range - { - int sbit; /* mask starting bit position */ - int ebit; /* mask ending bit position */ - }; - -struct itbl_field - { - e_type type; /* dreg/creg/greg/immed/symb */ - struct itbl_range range; /* field's bitfield range within instruction */ - unsigned long flags; /* field flags */ - struct itbl_field *next; /* next field in list */ - }; +struct itbl_range { + int sbit; /* mask starting bit position */ + int ebit; /* mask ending bit position */ +}; +struct itbl_field { + e_type type; /* dreg/creg/greg/immed/symb */ + struct itbl_range range; /* field's bitfield range within instruction */ + unsigned long flags; /* field flags */ + struct itbl_field *next; /* next field in list */ +}; /* These structures define the instructions and registers for a processor. * If the type is an instruction, the structure defines the format of an * instruction where the fields are the list of operands. * The flags field below uses the same values as those defined in the - * gnu assembler and are machine specific. */ -struct itbl_entry - { - e_processor processor; /* processor number */ - e_type type; /* dreg/creg/greg/insn */ - char *name; /* mnemionic name for insn/register */ - unsigned long value; /* opcode/instruction mask/register number */ - unsigned long flags; /* effects of the instruction */ - struct itbl_range range; /* bit range within instruction for value */ - struct itbl_field *fields; /* list of operand definitions (if any) */ - struct itbl_entry *next; /* next entry */ - }; - + * gnu assembler and are machine specific. */ +struct itbl_entry { + e_processor processor; /* processor number */ + e_type type; /* dreg/creg/greg/insn */ + char *name; /* mnemonic name for insn/register */ + unsigned long value; /* opcode/instruction mask/register number */ + unsigned long flags; /* effects of the instruction */ + struct itbl_range range; /* bit range within instruction for value */ + struct itbl_field *fields; /* list of operand definitions (if any) */ + struct itbl_entry *next; /* next entry */ +}; /* local data and structures */ static int itbl_num_opcodes = 0; /* Array of entries for each processor and entry type */ -static struct itbl_entry *entries[e_nprocs][e_ntypes] = -{ - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0} -}; +static struct itbl_entry *entries[e_nprocs][e_ntypes]; /* local prototypes */ -static unsigned long build_opcode PARAMS ((struct itbl_entry *e)); -static e_type get_type PARAMS ((int yytype)); -static e_processor get_processor PARAMS ((int yyproc)); -static struct itbl_entry **get_entries PARAMS ((e_processor processor, - e_type type)); -static struct itbl_entry *find_entry_byname PARAMS ((e_processor processor, - e_type type, char *name)); -static struct itbl_entry *find_entry_byval PARAMS ((e_processor processor, - e_type type, unsigned long val, struct itbl_range *r)); -static struct itbl_entry *alloc_entry PARAMS ((e_processor processor, - e_type type, char *name, unsigned long value)); -static unsigned long apply_range PARAMS ((unsigned long value, - struct itbl_range r)); -static unsigned long extract_range PARAMS ((unsigned long value, - struct itbl_range r)); -static struct itbl_field *alloc_field PARAMS ((e_type type, int sbit, - int ebit, unsigned long flags)); - +static unsigned long build_opcode (struct itbl_entry *e); +static e_type get_type (int yytype); +static e_processor get_processor (int yyproc); +static struct itbl_entry **get_entries (e_processor processor, + e_type type); +static struct itbl_entry *find_entry_byname (e_processor processor, + e_type type, char *name); +static struct itbl_entry *find_entry_byval (e_processor processor, + e_type type, unsigned long val, struct itbl_range *r); +static struct itbl_entry *alloc_entry (e_processor processor, + e_type type, char *name, unsigned long value); +static unsigned long apply_range (unsigned long value, struct itbl_range r); +static unsigned long extract_range (unsigned long value, struct itbl_range r); +static struct itbl_field *alloc_field (e_type type, int sbit, + int ebit, unsigned long flags); /*======================================================================*/ /* Interfaces to the parser */ - /* Open the table and use lex and yacc to parse the entries. * Return 1 for failure; 0 for success. */ -int +int itbl_parse (char *insntbl) { extern FILE *yyin; extern int yyparse (void); - yyin = fopen (insntbl, "r"); + + yyin = fopen (insntbl, FOPEN_RT); if (yyin == 0) { printf ("Can't open processor instruction specification file \"%s\"\n", insntbl); return 1; } - else - { - while (yyparse ()); - } + + while (yyparse ()) + ; + fclose (yyin); itbl_have_entries = 1; return 0; @@ -213,18 +197,6 @@ struct itbl_entry * itbl_add_reg (int yyprocessor, int yytype, char *regname, int regnum) { -#if 0 -#include "as.h" -#include "symbols.h" - /* Since register names don't have a prefix, we put them in the symbol table so - they can't be used as symbols. This also simplifies argument parsing as - we can let gas parse registers for us. The recorded register number is - regnum. */ - /* Use symbol_create here instead of symbol_new so we don't try to - output registers into the object file's symbol table. */ - symbol_table_insert (symbol_create (regname, reg_section, - regnum, &zero_address_frag)); -#endif return alloc_entry (get_processor (yyprocessor), get_type (yytype), regname, (unsigned long) regnum); } @@ -256,7 +228,7 @@ itbl_add_operand (struct itbl_entry *e, int yytype, int sbit, struct itbl_field *f, **last_f; if (!e) return 0; - /* Add to end of fields' list. */ + /* Add to end of fields' list. */ f = alloc_field (get_type (yytype), sbit, ebit, flags); if (f) { @@ -269,17 +241,15 @@ itbl_add_operand (struct itbl_entry *e, int yytype, int sbit, return f; } - /*======================================================================*/ /* Interfaces for assembler and disassembler */ #ifndef STAND_ALONE -#include "as.h" -#include "symbols.h" static void append_insns_as_macros (void); -/* initialize for gas */ -void +/* Initialize for gas. */ + +void itbl_init (void) { struct itbl_entry *e, **es; @@ -287,11 +257,11 @@ itbl_init (void) e_type type; if (!itbl_have_entries) - return; + return; /* Since register names don't have a prefix, put them in the symbol table so they can't be used as symbols. This simplifies argument parsing as - we can let gas parse registers for us. */ + we can let gas parse registers for us. */ /* Use symbol_create instead of symbol_new so we don't try to output registers into the object file's symbol table. */ @@ -302,22 +272,21 @@ itbl_init (void) for (e = *es; e; e = e->next) { symbol_table_insert (symbol_create (e->name, reg_section, - e->value, &zero_address_frag)); + e->value, &zero_address_frag)); } } append_insns_as_macros (); } - -/* Append insns to opcodes table and increase number of opcodes - * Structure of opcodes table: +/* Append insns to opcodes table and increase number of opcodes + * Structure of opcodes table: * struct itbl_opcode * { * const char *name; - * const char *args; - string describing the arguments. - * unsigned long match; - opcode, or ISA level if pinfo=INSN_MACRO - * unsigned long mask; - opcode mask, or macro id if pinfo=INSN_MACRO - * unsigned long pinfo; - insn flags, or INSN_MACRO + * const char *args; - string describing the arguments. + * unsigned long match; - opcode, or ISA level if pinfo=INSN_MACRO + * unsigned long mask; - opcode mask, or macro id if pinfo=INSN_MACRO + * unsigned long pinfo; - insn flags, or INSN_MACRO * }; * examples: * {"li", "t,i", 0x34000000, 0xffe00000, WR_t }, @@ -325,15 +294,18 @@ itbl_init (void) */ static char *form_args (struct itbl_entry *e); -static void +static void append_insns_as_macros (void) { struct ITBL_OPCODE_STRUCT *new_opcodes, *o; struct itbl_entry *e, **es; - int n, id, size, new_size, new_num_opcodes; + int n, size, new_num_opcodes; +#ifdef USE_MACROS + int id; +#endif if (!itbl_have_entries) - return; + return; if (!itbl_num_opcodes) /* no new instructions to add! */ { @@ -348,24 +320,23 @@ append_insns_as_macros (void) ASSERT (size >= 0); DBG (("I get=%d\n", size / sizeof (ITBL_OPCODES[0]))); - new_size = sizeof (struct ITBL_OPCODE_STRUCT) * new_num_opcodes; - ASSERT (new_size > size); - - /* FIXME since ITBL_OPCODES culd be a static table, - we can't realloc or delete the old memory. */ - new_opcodes = (struct ITBL_OPCODE_STRUCT *) malloc (new_size); + /* FIXME since ITBL_OPCODES could be a static table, + we can't realloc or delete the old memory. */ + new_opcodes = XNEWVEC (struct ITBL_OPCODE_STRUCT, new_num_opcodes); if (!new_opcodes) { printf (_("Unable to allocate memory for new instructions\n")); return; } - if (size) /* copy prexisting opcodes table */ + if (size) /* copy preexisting opcodes table */ memcpy (new_opcodes, ITBL_OPCODES, size); /* FIXME! some NUMOPCODES are calculated expressions. - These need to be changed before itbls can be supported. */ + These need to be changed before itbls can be supported. */ +#ifdef USE_MACROS id = ITBL_NUM_MACROS; /* begin the next macro id after the last */ +#endif o = &new_opcodes[ITBL_NUM_OPCODES]; /* append macro to opcodes list */ for (n = e_p0; n < e_nprocs; n++) { @@ -380,13 +351,13 @@ append_insns_as_macros (void) o->name = e->name; o->args = strdup (form_args (e)); o->mask = apply_range (e->value, e->range); - /* FIXME how to catch durring assembly? */ + /* FIXME how to catch during assembly? */ /* mask to identify this insn */ o->match = apply_range (e->value, e->range); o->pinfo = 0; #ifdef USE_MACROS - o->mask = id++; /* FIXME how to catch durring assembly? */ + o->mask = id++; /* FIXME how to catch during assembly? */ o->match = 0; /* for macros, the insn_isa number */ o->pinfo = INSN_MACRO; #endif @@ -407,7 +378,7 @@ append_insns_as_macros (void) Don't free name though, since name is being used by the new opcodes table. - Eventually, we should also free the new opcodes table itself + Eventually, we should also free the new opcodes table itself on exit. */ } @@ -454,21 +425,22 @@ form_args (struct itbl_entry *e) } #endif /* !STAND_ALONE */ - /* Get processor's register name from val */ -unsigned long -itbl_get_reg_val (char *name) +int +itbl_get_reg_val (char *name, unsigned long *pval) { e_type t; e_processor p; - int r = 0; + for (p = e_p0; p < e_nprocs; p++) - for (t = e_regtype0; t < e_nregtypes; t++) - { - if (r = itbl_get_val (p, t, name), r) - return r; - } + { + for (t = e_regtype0; t < e_nregtypes; t++) + { + if (itbl_get_val (p, t, name, pval)) + return 1; + } + } return 0; } @@ -486,35 +458,35 @@ itbl_get_name (e_processor processor, e_type type, unsigned long val) /* Get processor's register value from name */ -unsigned long -itbl_get_val (e_processor processor, e_type type, char *name) +int +itbl_get_val (e_processor processor, e_type type, char *name, + unsigned long *pval) { struct itbl_entry *r; /* type depends on instruction passed */ r = find_entry_byname (processor, type, name); - if (r) - return r->value; - else - return 0; /* error; invalid operand */ + if (r == NULL) + return 0; + *pval = r->value; + return 1; } - /* Assemble instruction "name" with operands "s". * name - name of instruction * s - operands * returns - long word for assembled instruction */ -unsigned long +unsigned long itbl_assemble (char *name, char *s) { unsigned long opcode; - struct itbl_entry *e; + struct itbl_entry *e = NULL; struct itbl_field *f; char *n; int processor; if (!name || !*name) - return 0; /* error! must have a opcode name/expr */ + return 0; /* error! must have an opcode name/expr */ /* find entry in list of instructions for all processors */ for (processor = 0; processor < e_nprocs; processor++) @@ -524,11 +496,11 @@ itbl_assemble (char *name, char *s) break; } if (!e) - return 0; /* opcode not in table; invalid instrustion */ + return 0; /* opcode not in table; invalid instruction */ opcode = build_opcode (e); /* parse opcode's args (if any) */ - for (f = e->fields; f; f = f->next) /* for each arg, ... */ + for (f = e->fields; f; f = f->next) /* for each arg, ... */ { struct itbl_entry *r; unsigned long value; @@ -568,9 +540,9 @@ itbl_assemble (char *name, char *s) return 0; /-* error; invalid operand *-/ break; */ - /* If not a symbol, fall thru to IMMED */ + /* If not a symbol, fallthru to IMMED */ case e_immed: - if (*n == '0' && *(n + 1) == 'x') /* hex begins 0x... */ + if (*n == '0' && *(n + 1) == 'x') /* hex begins 0x... */ { n += 2; value = strtol (n, 0, 16); @@ -600,7 +572,7 @@ itbl_assemble (char *name, char *s) * returns - 1 if succeeded; 0 if failed */ -int +int itbl_disassemble (char *s, unsigned long insn) { e_processor processor; @@ -608,24 +580,25 @@ itbl_disassemble (char *s, unsigned long insn) struct itbl_field *f; if (!ITBL_IS_INSN (insn)) - return 0; /* error*/ + return 0; /* error */ processor = get_processor (ITBL_DECODE_PNUM (insn)); /* find entry in list */ e = find_entry_byval (processor, e_insn, insn, 0); if (!e) - return 0; /* opcode not in table; invalid instrustion */ + return 0; /* opcode not in table; invalid instruction */ strcpy (s, e->name); - /* parse insn's args (if any) */ - for (f = e->fields; f; f = f->next) /* for each arg, ... */ + /* Parse insn's args (if any). */ + for (f = e->fields; f; f = f->next) /* for each arg, ... */ { struct itbl_entry *r; unsigned long value; + char s_value[20]; - if (f == e->fields) /* first operand is preceeded by tab */ + if (f == e->fields) /* First operand is preceded by tab. */ strcat (s, "\t"); - else /* ','s separate following operands */ + else /* ','s separate following operands. */ strcat (s, ","); value = extract_range (insn, f->range); /* n should be in form $n or 0xhhh (are symbol names valid?? */ @@ -635,27 +608,29 @@ itbl_disassemble (char *s, unsigned long insn) case e_creg: case e_greg: /* Accept either a string name - * or '$' followed by the register number */ + or '$' followed by the register number. */ r = find_entry_byval (e->processor, f->type, value, &f->range); if (r) strcat (s, r->name); else - sprintf (s, "%s$%d", s, value); + { + sprintf (s_value, "$%lu", value); + strcat (s, s_value); + } break; case e_addr: - /* use assembler's symbol table to find symbol */ - /* FIXME!! Do we need this? - * if so, what about relocs?? - */ - /* If not a symbol, fall thru to IMMED */ + /* Use assembler's symbol table to find symbol. */ + /* FIXME!! Do we need this? If so, what about relocs?? */ + /* If not a symbol, fall through to IMMED. */ case e_immed: - sprintf (s, "%s0x%x", s, value); + sprintf (s_value, "0x%lx", value); + strcat (s, s_value); break; default: return 0; /* error; invalid field spec */ } } - return 1; /* done! */ + return 1; /* Done! */ } /*======================================================================*/ @@ -667,7 +642,7 @@ itbl_disassemble (char *s, unsigned long insn) /* Calculate instruction's opcode and function values from entry */ -static unsigned long +static unsigned long build_opcode (struct itbl_entry *e) { unsigned long opcode; @@ -688,7 +663,7 @@ build_opcode (struct itbl_entry *e) * mask: 0x01f00000. */ -static unsigned long +static unsigned long apply_range (unsigned long rval, struct itbl_range r) { unsigned long mask; @@ -712,7 +687,7 @@ apply_range (unsigned long rval, struct itbl_range r) /* Calculate relative value given the absolute value and bit position range * within the instruction. */ -static unsigned long +static unsigned long extract_range (unsigned long aval, struct itbl_range r) { unsigned long mask; @@ -732,28 +707,20 @@ extract_range (unsigned long aval, struct itbl_range r) /* Extract processor's assembly instruction field name from s; * forms are "n args" "n,args" or "n" */ /* Return next argument from string pointer "s" and advance s. - * delimiters are " ,\0" */ + * delimiters are " ,()" */ char * itbl_get_field (char **S) { static char n[128]; - char *p, *ps, *s; + char *s; int len; s = *S; if (!s || !*s) return 0; - p = s + strlen (s); - if (ps = strchr (s, ','), ps) - p = ps; - if (ps = strchr (s, ' '), ps) - p = min (p, ps); - if (ps = strchr (s, '\0'), ps) - p = min (p, ps); - if (p == 0) - return 0; /* error! */ - len = p - s; + /* FIXME: This is a weird set of delimiters. */ + len = strcspn (s, " \t,()"); ASSERT (128 > len + 1); strncpy (n, s, len); n[len] = 0; @@ -777,7 +744,7 @@ find_entry_byname (e_processor processor, struct itbl_entry *e, **es; es = get_entries (processor, type); - for (e = *es; e; e = e->next) /* for each entry, ... */ + for (e = *es; e; e = e->next) /* for each entry, ... */ { if (!strcmp (e->name, n)) return e; @@ -799,7 +766,7 @@ find_entry_byval (e_processor processor, e_type type, unsigned long eval; es = get_entries (processor, type); - for (e = *es; e; e = e->next) /* for each entry, ... */ + for (e = *es; e; e = e->next) /* for each entry, ... */ { if (processor != e->processor) continue; @@ -809,15 +776,15 @@ find_entry_byval (e_processor processor, e_type type, * This could cause ambiguities. * For operands, we get an extracted value and a range. */ - /* if range is 0, mask val against the range of the compared entry. */ + /* if range is 0, mask val against the range of the compared entry. */ if (r == 0) /* if no range passed, must be whole 32-bits * so create 32-bit value from entry's range */ { eval = apply_range (e->value, e->range); val &= apply_range (0xffffffff, e->range); } - else if (r->sbit == e->range.sbit && r->ebit == e->range.ebit - || e->range.sbit == 0 && e->range.ebit == 0) + else if ((r->sbit == e->range.sbit && r->ebit == e->range.ebit) + || (e->range.sbit == 0 && e->range.ebit == 0)) { eval = apply_range (e->value, *r); val = apply_range (val, *r); @@ -830,7 +797,7 @@ find_entry_byval (e_processor processor, e_type type, return 0; } -/* Return a pointer to the list of entries for a given processor and type. */ +/* Return a pointer to the list of entries for a given processor and type. */ static struct itbl_entry ** get_entries (e_processor processor, e_type type) @@ -838,9 +805,9 @@ get_entries (e_processor processor, e_type type) return &entries[processor][type]; } -/* Return an integral value for the processor passed from yyparse. */ +/* Return an integral value for the processor passed from yyparse. */ -static e_processor +static e_processor get_processor (int yyproc) { /* translate from yacc's processor to enum */ @@ -849,9 +816,9 @@ get_processor (int yyproc) return e_invproc; /* error; invalid processor */ } -/* Return an integral value for the entry type passed from yyparse. */ +/* Return an integral value for the entry type passed from yyparse. */ -static e_type +static e_type get_type (int yytype) { switch (yytype) @@ -874,7 +841,6 @@ get_type (int yytype) } } - /* Allocate and initialize an entry */ static struct itbl_entry * @@ -884,13 +850,11 @@ alloc_entry (e_processor processor, e_type type, struct itbl_entry *e, **es; if (!name) return 0; - e = (struct itbl_entry *) malloc (sizeof (struct itbl_entry)); + e = XNEW (struct itbl_entry); if (e) { memset (e, 0, sizeof (struct itbl_entry)); - e->name = (char *) malloc (sizeof (strlen (name)) + 1); - if (e->name) - strcpy (e->name, name); + e->name = xstrdup (name); e->processor = processor; e->type = type; e->value = value; @@ -908,7 +872,7 @@ alloc_field (e_type type, int sbit, int ebit, unsigned long flags) { struct itbl_field *f; - f = (struct itbl_field *) malloc (sizeof (struct itbl_field)); + f = XNEW (struct itbl_field); if (f) { memset (f, 0, sizeof (struct itbl_field));