X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=include%2Fopcode%2Fcgen.h;h=328a6bf9efc2ed0350091e59f907ffe9fb3caa02;hb=a3b3345ae62503982698171bcfce0afe23bd8a31;hp=a4f7601d4acb99efd34661f743f09a525f740935;hpb=39f7f4b83cd858b98aeb9bb44b78fd708aebda03;p=deliverable%2Fbinutils-gdb.git diff --git a/include/opcode/cgen.h b/include/opcode/cgen.h index a4f7601d4a..328a6bf9ef 100644 --- a/include/opcode/cgen.h +++ b/include/opcode/cgen.h @@ -1,32 +1,42 @@ /* Header file for targets using CGEN: Cpu tools GENerator. -Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + Copyright (C) 1996-2017 Free Software Foundation, Inc. -This file is part of GDB, the GNU debugger, and the GNU Binutils. + This file is part of GDB, the GNU debugger, and the GNU Binutils. -This program 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 of the License, or -(at your option) any later version. + This program 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 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef CGEN_H -#define CGEN_H +#ifndef OPCODE_CGEN_H +#define OPCODE_CGEN_H + +#include "symcat.h" +#include "cgen/bitset.h" + +/* ??? IWBN to replace bfd in the name. */ +#include "bfd_stdint.h" + +#ifdef __cplusplus +extern "C" { +#endif /* ??? This file requires bfd.h but only to get bfd_vma. Seems like an awful lot to require just to get such a fundamental type. Perhaps the definition of bfd_vma can be moved outside of bfd.h. Or perhaps one could duplicate its definition in another file. Until such time, this file conditionally compiles definitions that require - bfd_vma using BFD_VERSION. */ + bfd_vma using __BFD_H_SEEN__. */ /* Enums must be defined before they can be used. Allow them to be used in struct definitions, even though the enum must @@ -62,6 +72,9 @@ with this program; if not, write to the Free Software Foundation, Inc., when an array of characters the value is in target byte order. */ typedef unsigned int CGEN_INSN_INT; +typedef int64_t CGEN_INSN_LGSINT; /* large/long SINT */ +typedef uint64_t CGEN_INSN_LGUINT; /* large/long UINT */ + #if CGEN_INT_INSN_P typedef CGEN_INSN_INT CGEN_INSN_BYTES; typedef CGEN_INSN_INT *CGEN_INSN_BYTES_PTR; @@ -106,55 +119,61 @@ typedef struct cgen_cpu_desc *CGEN_CPU_DESC; /* Type of attribute values. */ -typedef int CGEN_ATTR_VALUE_TYPE; +typedef CGEN_BITSET CGEN_ATTR_VALUE_BITSET_TYPE; +typedef int CGEN_ATTR_VALUE_ENUM_TYPE; +typedef union +{ + CGEN_ATTR_VALUE_BITSET_TYPE bitset; + CGEN_ATTR_VALUE_ENUM_TYPE nonbitset; +} CGEN_ATTR_VALUE_TYPE; /* Struct to record attribute information. */ typedef struct { - /* Number of non-boolean attributes. */ - unsigned int num_nonbools; /* Boolean attributes. */ - unsigned int bool; + unsigned int bool_; /* Non-boolean integer attributes. */ CGEN_ATTR_VALUE_TYPE nonbool[1]; } CGEN_ATTR; /* Define a structure member for attributes with N non-boolean entries. - The attributes are sorted so that the non-boolean ones come first. There is no maximum number of non-boolean attributes. There is a maximum of 32 boolean attributes (since they are all recorded in one host int). */ #define CGEN_ATTR_TYPE(n) \ -struct { unsigned int num_nonbools; \ - unsigned int bool; \ +struct { unsigned int bool_; \ CGEN_ATTR_VALUE_TYPE nonbool[(n) ? (n) : 1]; } /* Return the boolean attributes. */ -#define CGEN_ATTR_BOOLS(a) ((a)->bool) +#define CGEN_ATTR_BOOLS(a) ((a)->bool_) -/* Boolean attribute numbers are offset by this much. */ +/* Non-boolean attribute numbers are offset by this much. */ -#define CGEN_ATTR_BOOL_OFFSET 32 +#define CGEN_ATTR_NBOOL_OFFSET 32 /* Given a boolean attribute number, return its mask. */ -#define CGEN_ATTR_MASK(attr) (1 << ((attr) - CGEN_ATTR_BOOL_OFFSET)) +#define CGEN_ATTR_MASK(attr) (1 << (attr)) /* Return the value of boolean attribute ATTR in ATTRS. */ #define CGEN_BOOL_ATTR(attrs, attr) ((CGEN_ATTR_MASK (attr) & (attrs)) != 0) /* Return value of attribute ATTR in ATTR_TABLE for OBJ. - OBJ is a pointer to the entity that has the attributes (not used at present - but is reserved for future purposes). */ + OBJ is a pointer to the entity that has the attributes + (??? not used at present but is reserved for future purposes - eventually + the goal is to allow recording attributes in source form and computing + them lazily at runtime, not sure of the details yet). */ #define CGEN_ATTR_VALUE(obj, attr_table, attr) \ -((unsigned int) (attr) < CGEN_ATTR_BOOL_OFFSET \ - ? ((attr_table)->nonbool[attr]) \ - : ((CGEN_ATTR_BOOLS (attr_table) & CGEN_ATTR_MASK (attr)) != 0)) +((unsigned int) (attr) < CGEN_ATTR_NBOOL_OFFSET \ + ? ((CGEN_ATTR_BOOLS (attr_table) & CGEN_ATTR_MASK (attr)) != 0) \ + : ((attr_table)->nonbool[(attr) - CGEN_ATTR_NBOOL_OFFSET].nonbitset)) +#define CGEN_BITSET_ATTR_VALUE(obj, attr_table, attr) \ + ((attr_table)->nonbool[(attr) - CGEN_ATTR_NBOOL_OFFSET].bitset) /* Attribute name/value tables. These are used to assist parsing of descriptions at run-time. */ @@ -162,7 +181,7 @@ struct { unsigned int num_nonbools; \ typedef struct { const char * name; - CGEN_ATTR_VALUE_TYPE value; + unsigned value; } CGEN_ATTR_ENTRY; /* For each domain (ifld,hw,operand,insn), list of attributes. */ @@ -174,6 +193,37 @@ typedef struct const CGEN_ATTR_ENTRY * vals; } CGEN_ATTR_TABLE; +/* Instruction set variants. */ + +typedef struct { + const char *name; + + /* Default instruction size (in bits). + This is used by the assembler when it encounters an unknown insn. */ + unsigned int default_insn_bitsize; + + /* Base instruction size (in bits). + For non-LIW cpus this is generally the length of the smallest insn. + For LIW cpus its wip (work-in-progress). For the m32r its 32. */ + unsigned int base_insn_bitsize; + + /* Minimum/maximum instruction size (in bits). */ + unsigned int min_insn_bitsize; + unsigned int max_insn_bitsize; +} CGEN_ISA; + +/* Machine variants. */ + +typedef struct { + const char *name; + /* The argument to bfd_arch_info->scan. */ + const char *bfd_name; + /* one of enum mach_attr */ + int num; + /* parameter from mach->cpu */ + unsigned int insn_chunk_bitsize; +} CGEN_MACH; + /* Parse result (also extraction result). The result of parsing an insn is stored here. @@ -212,9 +262,9 @@ typedef struct cgen_fields CGEN_FIELDS; typedef struct { /* A pointer to the disassemble_info struct. - We don't require dis-asm.h so we use PTR for the type here. + We don't require dis-asm.h so we use void * for the type here. If NULL, BYTES is full of valid data (VALID == -1). */ - PTR dis_info; + void *dis_info; /* Points to a working buffer of sufficient size. */ unsigned char *insn_bytes; /* Mask of bytes that are valid in INSN_BYTES. */ @@ -235,8 +285,8 @@ typedef struct { If not it is left alone. The result is NULL if success or an error message. */ typedef const char * (cgen_parse_fn) - PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *insn_, - const char **strp_, CGEN_FIELDS *fields_)); + (CGEN_CPU_DESC, const CGEN_INSN *insn_, + const char **strp_, CGEN_FIELDS *fields_); /* Insert handler. CD is a cpu table descriptor. @@ -247,11 +297,11 @@ typedef const char * (cgen_parse_fn) PC is the pc value of the insn. The result is an error message or NULL if success. */ -#ifdef BFD_VERSION +#ifdef __BFD_H_SEEN__ typedef const char * (cgen_insert_fn) - PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *insn_, - CGEN_FIELDS *fields_, CGEN_INSN_BYTES_PTR insnp_, - bfd_vma pc_)); + (CGEN_CPU_DESC, const CGEN_INSN *insn_, + CGEN_FIELDS *fields_, CGEN_INSN_BYTES_PTR insnp_, + bfd_vma pc_); #else typedef const char * (cgen_insert_fn) (); #endif @@ -268,11 +318,11 @@ typedef const char * (cgen_insert_fn) (); PC is the pc value of the insn. The result is the length of the insn in bits or zero if not recognized. */ -#ifdef BFD_VERSION +#ifdef __BFD_H_SEEN__ typedef int (cgen_extract_fn) - PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *insn_, - CGEN_EXTRACT_INFO *ex_info_, CGEN_INSN_INT base_insn_, - CGEN_FIELDS *fields_, bfd_vma pc_)); + (CGEN_CPU_DESC, const CGEN_INSN *insn_, + CGEN_EXTRACT_INFO *ex_info_, CGEN_INSN_INT base_insn_, + CGEN_FIELDS *fields_, bfd_vma pc_); #else typedef int (cgen_extract_fn) (); #endif @@ -287,10 +337,10 @@ typedef int (cgen_extract_fn) (); PC is the pc value of the insn. LEN is the length of the insn, in bits. */ -#ifdef BFD_VERSION +#ifdef __BFD_H_SEEN__ typedef void (cgen_print_fn) - PARAMS ((CGEN_CPU_DESC, PTR info_, const CGEN_INSN *insn_, - CGEN_FIELDS *fields_, bfd_vma pc_, int len_)); + (CGEN_CPU_DESC, void * info_, const CGEN_INSN *insn_, + CGEN_FIELDS *fields_, bfd_vma pc_, int len_); #else typedef void (cgen_print_fn) (); #endif @@ -339,7 +389,8 @@ enum cgen_parse_operand_type { CGEN_PARSE_OPERAND_INIT, CGEN_PARSE_OPERAND_INTEGER, - CGEN_PARSE_OPERAND_ADDRESS + CGEN_PARSE_OPERAND_ADDRESS, + CGEN_PARSE_OPERAND_SYMBOLIC }; /* Values for indicating what was parsed. */ @@ -352,11 +403,11 @@ enum cgen_parse_operand_result CGEN_PARSE_OPERAND_RESULT_ERROR }; -#ifdef BFD_VERSION /* Don't require bfd.h unnecessarily. */ +#ifdef __BFD_H_SEEN__ /* Don't require bfd.h unnecessarily. */ typedef const char * (cgen_parse_operand_fn) - PARAMS ((CGEN_CPU_DESC, - enum cgen_parse_operand_type, const char **, int, int, - enum cgen_parse_operand_result *, bfd_vma *)); + (CGEN_CPU_DESC, + enum cgen_parse_operand_type, const char **, int, int, + enum cgen_parse_operand_result *, bfd_vma *); #else typedef const char * (cgen_parse_operand_fn) (); #endif @@ -364,11 +415,11 @@ typedef const char * (cgen_parse_operand_fn) (); /* Set the cgen_parse_operand_fn callback. */ extern void cgen_set_parse_operand_fn - PARAMS ((CGEN_CPU_DESC, cgen_parse_operand_fn)); + (CGEN_CPU_DESC, cgen_parse_operand_fn); /* Called before trying to match a table entry with the insn. */ -extern void cgen_init_parse_operand PARAMS ((CGEN_CPU_DESC)); +extern void cgen_init_parse_operand (CGEN_CPU_DESC); /* Operand values (keywords, integers, symbols, etc.) */ @@ -376,20 +427,23 @@ extern void cgen_init_parse_operand PARAMS ((CGEN_CPU_DESC)); enum cgen_asm_type { - CGEN_ASM_KEYWORD, CGEN_ASM_MAX + CGEN_ASM_NONE, CGEN_ASM_KEYWORD, CGEN_ASM_MAX }; +#ifndef CGEN_ARCH +enum cgen_hw_type { CGEN_HW_MAX }; +#endif + /* List of hardware elements. */ -typedef struct cgen_hw_entry +typedef struct { - /* The type of this entry, one of `enum hw_type'. - This is an int and not the enum as the latter may not be declared yet. */ - int type; - const struct cgen_hw_entry * next; - char * name; + char *name; + enum cgen_hw_type type; + /* There is currently no example where both index specs and value specs + are required, so for now both are clumped under "asm_data". */ enum cgen_asm_type asm_type; - PTR asm_data; + void *asm_data; #ifndef CGEN_HW_NBOOL_ATTRS #define CGEN_HW_NBOOL_ATTRS 1 #endif @@ -402,13 +456,27 @@ typedef struct cgen_hw_entry #define CGEN_HW_ATTR_VALUE(hw, attr) \ CGEN_ATTR_VALUE ((hw), CGEN_HW_ATTRS (hw), (attr)) +/* Table of hardware elements for selected mach, computed at runtime. + enum cgen_hw_type is an index into this table (specifically `entries'). */ + +typedef struct { + /* Pointer to null terminated table of all compiled in entries. */ + const CGEN_HW_ENTRY *init_entries; + unsigned int entry_size; /* since the attribute member is variable sized */ + /* Array of all entries, initial and run-time added. */ + const CGEN_HW_ENTRY **entries; + /* Number of elements in `entries'. */ + unsigned int num_entries; + /* For now, xrealloc is called each time a new entry is added at runtime. + ??? May wish to keep track of some slop to reduce the number of calls to + xrealloc, except that there's unlikely to be many and not expected to be + in speed critical code. */ +} CGEN_HW_TABLE; + extern const CGEN_HW_ENTRY * cgen_hw_lookup_by_name - PARAMS ((CGEN_CPU_DESC, const char *)); + (CGEN_CPU_DESC, const char *); extern const CGEN_HW_ENTRY * cgen_hw_lookup_by_num - PARAMS ((CGEN_CPU_DESC, int)); - -/* The operand instance table refers to this directly. */ -extern const CGEN_HW_ENTRY CGEN_SYM (hw_table)[]; + (CGEN_CPU_DESC, unsigned int); /* This struct is used to describe things like register names, etc. */ @@ -437,6 +505,8 @@ typedef struct cgen_keyword_entry #endif CGEN_ATTR_TYPE (CGEN_KEYWORD_NBOOL_ATTRS) attrs; + /* ??? Putting these here means compiled in entries can't be const. + Not a really big deal, but something to consider. */ /* Next name hash table entry. */ struct cgen_keyword_entry *next_name; /* Next value hash table entry. */ @@ -467,6 +537,11 @@ typedef struct cgen_keyword /* Pointer to null keyword "" entry if present. */ const CGEN_KEYWORD_ENTRY *null_entry; + + /* String containing non-alphanumeric characters used + in keywords. + At present, the highest number of entries used is 1. */ + char nonalpha_chars[8]; } CGEN_KEYWORD; /* Structure used for searching. */ @@ -489,41 +564,41 @@ typedef struct /* Lookup a keyword from its name. */ const CGEN_KEYWORD_ENTRY *cgen_keyword_lookup_name - PARAMS ((CGEN_KEYWORD *, const char *)); + (CGEN_KEYWORD *, const char *); /* Lookup a keyword from its value. */ const CGEN_KEYWORD_ENTRY *cgen_keyword_lookup_value - PARAMS ((CGEN_KEYWORD *, int)); + (CGEN_KEYWORD *, int); /* Add a keyword. */ -void cgen_keyword_add PARAMS ((CGEN_KEYWORD *, CGEN_KEYWORD_ENTRY *)); +void cgen_keyword_add (CGEN_KEYWORD *, CGEN_KEYWORD_ENTRY *); /* Keyword searching. This can be used to retrieve every keyword, or a subset. */ CGEN_KEYWORD_SEARCH cgen_keyword_search_init - PARAMS ((CGEN_KEYWORD *, const char *)); + (CGEN_KEYWORD *, const char *); const CGEN_KEYWORD_ENTRY *cgen_keyword_search_next - PARAMS ((CGEN_KEYWORD_SEARCH *)); + (CGEN_KEYWORD_SEARCH *); /* Operand value support routines. */ extern const char *cgen_parse_keyword - PARAMS ((CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *)); -#ifdef BFD_VERSION /* Don't require bfd.h unnecessarily. */ + (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *); +#ifdef __BFD_H_SEEN__ /* Don't require bfd.h unnecessarily. */ extern const char *cgen_parse_signed_integer - PARAMS ((CGEN_CPU_DESC, const char **, int, long *)); + (CGEN_CPU_DESC, const char **, int, long *); extern const char *cgen_parse_unsigned_integer - PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *)); + (CGEN_CPU_DESC, const char **, int, unsigned long *); extern const char *cgen_parse_address - PARAMS ((CGEN_CPU_DESC, const char **, int, int, - enum cgen_parse_operand_result *, bfd_vma *)); + (CGEN_CPU_DESC, const char **, int, int, + enum cgen_parse_operand_result *, bfd_vma *); extern const char *cgen_validate_signed_integer - PARAMS ((long, long, long)); + (long, long, long); extern const char *cgen_validate_unsigned_integer - PARAMS ((unsigned long, unsigned long, unsigned long)); + (unsigned long, unsigned long, unsigned long); #endif /* Operand modes. */ @@ -547,23 +622,50 @@ enum cgen_mode { #define CGEN_MODE_VM CGEN_MODE_VOID +/* Operands. */ + +#ifndef CGEN_ARCH +enum cgen_operand_type { CGEN_OPERAND_MAX }; +#endif + +/* "nil" indicator for the operand instance table */ +#define CGEN_OPERAND_NIL CGEN_OPERAND_MAX + +/* A tree of these structs represents the multi-ifield + structure of an operand's hw-index value, if it exists. */ + +struct cgen_ifld; + +typedef struct cgen_maybe_multi_ifield +{ + int count; /* 0: indexed by single cgen_ifld (possibly null: dead entry); + n: indexed by array of more cgen_maybe_multi_ifields. */ + union + { + const void *p; + const struct cgen_maybe_multi_ifield * multi; + const struct cgen_ifld * leaf; + } val; +} +CGEN_MAYBE_MULTI_IFLD; + /* This struct defines each entry in the operand table. */ -typedef struct cgen_operand +typedef struct { /* Name as it appears in the syntax string. */ char *name; + /* Operand type. */ + enum cgen_operand_type type; + /* The hardware element associated with this operand. */ - const CGEN_HW_ENTRY *hw; + enum cgen_hw_type hw_type; /* FIXME: We don't yet record ifield definitions, which we should. When we do it might make sense to delete start/length (since they will be duplicated in the ifield's definition) and replace them with a - pointer to the ifield entry. Note that as more complicated situations - need to be handled, going more and more with an OOP paradigm will help - keep the complication under control. Of course, this was the goal from - the start, but getting there in one step was too much too soon. */ + pointer to the ifield entry. */ /* Bit position. This is just a hint, and may be unused in more complex operands. @@ -575,6 +677,11 @@ typedef struct cgen_operand May be unused for a modifier. */ unsigned char length; + /* The (possibly-multi) ifield used as an index for this operand, if it + is indexed by a field at all. This substitutes / extends the start and + length fields above, but unsure at this time whether they are used + anywhere. */ + CGEN_MAYBE_MULTI_IFLD index_fields; #if 0 /* ??? Interesting idea but relocs tend to get too complicated, and ABI dependent, for simple table lookups to work. */ /* Ideally this would be the internal (external?) reloc type. */ @@ -600,16 +707,28 @@ typedef struct cgen_operand #define CGEN_OPERAND_ATTR_VALUE(operand, attr) \ CGEN_ATTR_VALUE ((operand), CGEN_OPERAND_ATTRS (operand), (attr)) -/* The operand instance table refers to this directly. */ -extern const CGEN_OPERAND CGEN_SYM (operand_table)[]; - -enum cgen_operand_type; +/* Table of operands for selected mach/isa, computed at runtime. + enum cgen_operand_type is an index into this table (specifically + `entries'). */ -#define CGEN_OPERAND_INDEX(cd, operand) ((operand) - (cd)->operand_table) -/* FIXME: Rename, arch-desc.h defines this as the typedef of the enum. */ -#define CGEN_OPERAND_TYPE(cd, operand) \ - ((enum cgen_operand_type) CGEN_OPERAND_INDEX ((cd), (operand))) -#define CGEN_OPERAND_ENTRY(cd, n) (& (cd)->operand_table[n]) +typedef struct { + /* Pointer to null terminated table of all compiled in entries. */ + const CGEN_OPERAND *init_entries; + unsigned int entry_size; /* since the attribute member is variable sized */ + /* Array of all entries, initial and run-time added. */ + const CGEN_OPERAND **entries; + /* Number of elements in `entries'. */ + unsigned int num_entries; + /* For now, xrealloc is called each time a new entry is added at runtime. + ??? May wish to keep track of some slop to reduce the number of calls to + xrealloc, except that there's unlikely to be many and not expected to be + in speed critical code. */ +} CGEN_OPERAND_TABLE; + +extern const CGEN_OPERAND * cgen_operand_lookup_by_name + (CGEN_CPU_DESC, const char *); +extern const CGEN_OPERAND * cgen_operand_lookup_by_num + (CGEN_CPU_DESC, int); /* Instruction operand instances. @@ -626,23 +745,23 @@ enum cgen_opinst_type { typedef struct { - /* The type of this operand. */ + /* Input or output indicator. */ enum cgen_opinst_type type; /* Name of operand. */ const char *name; /* The hardware element referenced. */ - const CGEN_HW_ENTRY *hw; + enum cgen_hw_type hw_type; /* The mode in which the operand is being used. */ enum cgen_mode mode; - /* The operand table entry or NULL if there is none (i.e. an explicit - hardware reference). */ - const CGEN_OPERAND *operand; + /* The operand table entry CGEN_OPERAND_NIL if there is none + (i.e. an explicit hardware reference). */ + enum cgen_operand_type op_type; - /* If `operand' is NULL, the index (e.g. into array of registers). */ + /* If `operand' is "nil", the index (e.g. into array of registers). */ int index; /* Attributes. @@ -668,18 +787,27 @@ typedef struct into the operand table. The operand table doesn't exist in C, per se, as the data is recorded in the parse/insert/extract/print switch statements. */ -#ifndef CGEN_MAX_SYNTAX_BYTES -#define CGEN_MAX_SYNTAX_BYTES 16 +/* This should be at least as large as necessary for any target. */ +#define CGEN_MAX_SYNTAX_ELEMENTS 48 + +/* A target may know its own precise maximum. Assert that it falls below + the above limit. */ +#ifdef CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS +#if CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS > CGEN_MAX_SYNTAX_ELEMENTS +#error "CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS too high - enlarge CGEN_MAX_SYNTAX_ELEMENTS" +#endif #endif +typedef unsigned short CGEN_SYNTAX_CHAR_TYPE; + typedef struct { - unsigned char syntax[CGEN_MAX_SYNTAX_BYTES]; + CGEN_SYNTAX_CHAR_TYPE syntax[CGEN_MAX_SYNTAX_ELEMENTS]; } CGEN_SYNTAX; #define CGEN_SYNTAX_STRING(syn) (syn->syntax) #define CGEN_SYNTAX_CHAR_P(c) ((c) < 128) -#define CGEN_SYNTAX_CHAR(c) (c) +#define CGEN_SYNTAX_CHAR(c) ((unsigned char)c) #define CGEN_SYNTAX_FIELD(c) ((c) - 128) #define CGEN_SYNTAX_MAKE_FIELD(c) ((c) + 128) @@ -757,17 +885,25 @@ typedef struct { #define CGEN_IFMT_IFLD_IFLD(ii) ((ii)->ifld) } CGEN_IFMT_IFLD; -#ifndef CGEN_MAX_IFMT_OPERANDS -#define CGEN_MAX_IFMT_OPERANDS 1 +/* This should be at least as large as necessary for any target. */ +#define CGEN_MAX_IFMT_OPERANDS 16 + +/* A target may know its own precise maximum. Assert that it falls below + the above limit. */ +#ifdef CGEN_ACTUAL_MAX_IFMT_OPERANDS +#if CGEN_ACTUAL_MAX_IFMT_OPERANDS > CGEN_MAX_IFMT_OPERANDS +#error "CGEN_ACTUAL_MAX_IFMT_OPERANDS too high - enlarge CGEN_MAX_IFMT_OPERANDS" +#endif #endif + typedef struct { /* Length that MASK and VALUE have been calculated to [VALUE is recorded elsewhere]. - Normally it is CGEN_BASE_INSN_BITSIZE. On [V]LIW architectures where - the base insn size may be larger than the size of an insn, this field is - less than CGEN_BASE_INSN_BITSIZE. */ + Normally it is base_insn_bitsize. On [V]LIW architectures where the base + insn size may be larger than the size of an insn, this field is less than + base_insn_bitsize. */ unsigned char mask_length; #define CGEN_IFMT_MASK_LENGTH(ifmt) ((ifmt)->mask_length) @@ -847,8 +983,9 @@ typedef CGEN_ATTR_TYPE (CGEN_INSN_NBOOL_ATTRS) CGEN_INSN_ATTR_TYPE; #ifndef CGEN_ARCH /* ??? Numbers here are recorded in two places. */ typedef enum cgen_insn_attr { - CGEN_INSN_ALIAS = CGEN_ATTR_BOOL_OFFSET + CGEN_INSN_ALIAS = 0 } CGEN_INSN_ATTR; +#define CGEN_ATTR_CGEN_INSN_ALIAS_VALUE(attrs) ((attrs)->bool_ & (1 << CGEN_INSN_ALIAS)) #endif /* This struct defines each entry in the instruction table. */ @@ -900,6 +1037,8 @@ typedef struct /* Return value of attribute ATTR in INSN. */ #define CGEN_INSN_ATTR_VALUE(insn, attr) \ CGEN_ATTR_VALUE ((insn), CGEN_INSN_ATTRS (insn), (attr)) +#define CGEN_INSN_BITSET_ATTR_VALUE(insn, attr) \ + CGEN_BITSET_ATTR_VALUE ((insn), CGEN_INSN_ATTRS (insn), (attr)) } CGEN_IBASE; /* Return non-zero if INSN is the "invalid" insn marker. */ @@ -918,6 +1057,11 @@ struct cgen_insn const CGEN_IBASE *base; const CGEN_OPCODE *opcode; const CGEN_OPINST *opinst; + + /* Regex to disambiguate overloaded opcodes */ + void *rx; +#define CGEN_INSN_RX(insn) ((insn)->rx) +#define CGEN_MAX_RX_ELEMENTS (CGEN_MAX_SYNTAX_ELEMENTS * 5) }; /* Instruction lists. @@ -941,8 +1085,8 @@ typedef struct /* Return number of instructions. This includes any added at run-time. */ -extern int cgen_insn_count PARAMS ((CGEN_CPU_DESC)); -extern int cgen_macro_insn_count PARAMS ((CGEN_CPU_DESC)); +extern int cgen_insn_count (CGEN_CPU_DESC); +extern int cgen_macro_insn_count (CGEN_CPU_DESC); /* Macros to access the other insn elements not recorded in CGEN_IBASE. */ @@ -970,6 +1114,12 @@ extern int cgen_macro_insn_count PARAMS ((CGEN_CPU_DESC)); /* Return value of base part of INSN. */ #define CGEN_INSN_BASE_VALUE(insn) \ CGEN_OPCODE_BASE_VALUE (CGEN_INSN_OPCODE (insn)) + +/* Standard way to test whether INSN is supported by MACH. + MACH is one of enum mach_attr. + The "|1" is because the base mach is always selected. */ +#define CGEN_INSN_MACH_HAS_P(insn, mach) \ +((CGEN_INSN_ATTR_VALUE ((insn), CGEN_INSN_MACH) & ((1 << (mach)) | 1)) != 0) /* Macro instructions. Macro insns aren't real insns, they map to one or more real insns. @@ -1000,9 +1150,10 @@ typedef struct cgen_minsn_expansion { If the expansion fails (e.g. "no match") NULL is returned. Space for the expansion is obtained with malloc. It is up to the caller to free it. */ - const char * (* fn) PARAMS ((const struct cgen_minsn_expansion *, - const char *, const char **, int *, - CGEN_OPERAND **)); + const char * (* fn) + (const struct cgen_minsn_expansion *, + const char *, const char **, int *, + CGEN_OPERAND **); #define CGEN_MIEXPN_FN(ex) ((ex)->fn) /* Instruction(s) the macro expands to. @@ -1020,15 +1171,15 @@ typedef struct cgen_minsn_expansion { may contain further macro invocations. */ extern const char * cgen_expand_macro_insn - PARAMS ((CGEN_CPU_DESC, const struct cgen_minsn_expansion *, - const char *, const char **, int *, CGEN_OPERAND **)); + (CGEN_CPU_DESC, const struct cgen_minsn_expansion *, + const char *, const char **, int *, CGEN_OPERAND **); /* The assembler insn table is hashed based on some function of the mnemonic (the actually hashing done is up to the target, but we provide a few examples like the first letter or a function of the entire mnemonic). */ extern CGEN_INSN_LIST * cgen_asm_lookup_insn - PARAMS ((CGEN_CPU_DESC, const char *)); + (CGEN_CPU_DESC, const char *); #define CGEN_ASM_LOOKUP_INSN(cd, string) cgen_asm_lookup_insn ((cd), (string)) #define CGEN_ASM_NEXT_INSN(insn) ((insn)->next) @@ -1036,7 +1187,7 @@ extern CGEN_INSN_LIST * cgen_asm_lookup_insn instruction (the actually hashing done is up to the target). */ extern CGEN_INSN_LIST * cgen_dis_lookup_insn - PARAMS ((CGEN_CPU_DESC, const char *, CGEN_INSN_INT)); + (CGEN_CPU_DESC, const char *, CGEN_INSN_INT); /* FIXME: delete these two */ #define CGEN_DIS_LOOKUP_INSN(cd, buf, value) cgen_dis_lookup_insn ((cd), (buf), (value)) #define CGEN_DIS_NEXT_INSN(insn) ((insn)->next) @@ -1048,8 +1199,12 @@ extern CGEN_INSN_LIST * cgen_dis_lookup_insn typedef struct cgen_cpu_desc { - /* Current machine (a la BFD machine number). */ - int mach; + /* Bitmap of selected machine(s) (a la BFD machine number). */ + int machs; + + /* Bitmap of selected isa(s). */ + CGEN_BITSET *isas; +#define CGEN_CPU_ISAS(cd) ((cd)->isas) /* Current endian. */ enum cgen_endian endian; @@ -1059,15 +1214,49 @@ typedef struct cgen_cpu_desc enum cgen_endian insn_endian; #define CGEN_CPU_INSN_ENDIAN(cd) ((cd)->insn_endian) + /* Word size (in bits). */ + /* ??? Or maybe maximum word size - might we ever need to allow a cpu table + to be opened for both sparc32/sparc64? + ??? Another alternative is to create a table of selected machs and + lazily fetch the data from there. */ + unsigned int word_bitsize; + + /* Instruction chunk size (in bits), for purposes of endianness + conversion. */ + unsigned int insn_chunk_bitsize; + + /* Indicator if sizes are unknown. + This is used by default_insn_bitsize,base_insn_bitsize if there is a + difference between the selected isa's. */ +#define CGEN_SIZE_UNKNOWN 65535 + + /* Default instruction size (in bits). + This is used by the assembler when it encounters an unknown insn. */ + unsigned int default_insn_bitsize; + + /* Base instruction size (in bits). + For non-LIW cpus this is generally the length of the smallest insn. + For LIW cpus its wip (work-in-progress). For the m32r its 32. */ + unsigned int base_insn_bitsize; + + /* Minimum/maximum instruction size (in bits). */ + unsigned int min_insn_bitsize; + unsigned int max_insn_bitsize; + + /* Instruction set variants. */ + const CGEN_ISA *isa_table; + + /* Machine variants. */ + const CGEN_MACH *mach_table; + /* Hardware elements. */ - const CGEN_HW_ENTRY *hw_list; + CGEN_HW_TABLE hw_table; /* Instruction fields. */ const CGEN_IFLD *ifld_table; /* Operands. */ - const CGEN_OPERAND *operand_table; -#define CGEN_CPU_OPERAND_TABLE(cd) ((cd)->operand_table) + CGEN_OPERAND_TABLE operand_table; /* Main instruction table. */ CGEN_INSN_TABLE insn_table; @@ -1080,26 +1269,25 @@ typedef struct cgen_cpu_desc /* Copy of CGEN_INT_INSN_P. */ int int_insn_p; - /* Maximum length of any insn, in bytes. */ - unsigned int max_insn_size; + /* Called to rebuild the tables after something has changed. */ + void (*rebuild_tables) (CGEN_CPU_DESC); /* Operand parser callback. */ cgen_parse_operand_fn * parse_operand_fn; /* Parse/insert/extract/print cover fns for operands. */ const char * (*parse_operand) - PARAMS ((CGEN_CPU_DESC, int opindex_, const char **, - CGEN_FIELDS *fields_)); -#ifdef BFD_VERSION + (CGEN_CPU_DESC, int opindex_, const char **, CGEN_FIELDS *fields_); +#ifdef __BFD_H_SEEN__ const char * (*insert_operand) - PARAMS ((CGEN_CPU_DESC, int opindex_, CGEN_FIELDS *fields_, - CGEN_INSN_BYTES_PTR, bfd_vma pc_)); + (CGEN_CPU_DESC, int opindex_, CGEN_FIELDS *fields_, + CGEN_INSN_BYTES_PTR, bfd_vma pc_); int (*extract_operand) - PARAMS ((CGEN_CPU_DESC, int opindex_, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, - CGEN_FIELDS *fields_, bfd_vma pc_)); + (CGEN_CPU_DESC, int opindex_, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, + CGEN_FIELDS *fields_, bfd_vma pc_); void (*print_operand) - PARAMS ((CGEN_CPU_DESC, int opindex_, PTR info_, CGEN_FIELDS * fields_, - void const *attrs_, bfd_vma pc_, int length_)); + (CGEN_CPU_DESC, int opindex_, void * info_, CGEN_FIELDS * fields_, + void const *attrs_, bfd_vma pc_, int length_); #else const char * (*insert_operand) (); int (*extract_operand) (); @@ -1115,19 +1303,19 @@ typedef struct cgen_cpu_desc #define CGEN_CPU_SIZEOF_FIELDS(cd) ((cd)->sizeof_fields) /* Set the bitsize field. */ - void (*set_fields_bitsize) PARAMS ((CGEN_FIELDS *fields_, int size_)); + void (*set_fields_bitsize) (CGEN_FIELDS *fields_, int size_); #define CGEN_CPU_SET_FIELDS_BITSIZE(cd) ((cd)->set_fields_bitsize) /* CGEN_FIELDS accessors. */ int (*get_int_operand) - PARAMS ((int opindex_, const CGEN_FIELDS *fields_)); + (CGEN_CPU_DESC, int opindex_, const CGEN_FIELDS *fields_); void (*set_int_operand) - PARAMS ((int opindex_, CGEN_FIELDS *fields_, int value_)); -#ifdef BFD_VERSION + (CGEN_CPU_DESC, int opindex_, CGEN_FIELDS *fields_, int value_); +#ifdef __BFD_H_SEEN__ bfd_vma (*get_vma_operand) - PARAMS ((int opindex_, const CGEN_FIELDS *fields_)); + (CGEN_CPU_DESC, int opindex_, const CGEN_FIELDS *fields_); void (*set_vma_operand) - PARAMS ((int opindex_, CGEN_FIELDS *fields_, bfd_vma value_)); + (CGEN_CPU_DESC, int opindex_, CGEN_FIELDS *fields_, bfd_vma value_); #else long (*get_vma_operand) (); void (*set_vma_operand) (); @@ -1149,19 +1337,19 @@ typedef struct cgen_cpu_desc #define CGEN_PRINT_FN(cd, insn) (cd->print_handlers[(insn)->opcode->handlers.print]) /* Return non-zero if insn should be added to hash table. */ - int (* asm_hash_p) PARAMS ((const CGEN_INSN *)); + int (* asm_hash_p) (const CGEN_INSN *); /* Assembler hash function. */ - unsigned int (* asm_hash) PARAMS ((const char *)); + unsigned int (* asm_hash) (const char *); /* Number of entries in assembler hash table. */ unsigned int asm_hash_size; /* Return non-zero if insn should be added to hash table. */ - int (* dis_hash_p) PARAMS ((const CGEN_INSN *)); + int (* dis_hash_p) (const CGEN_INSN *); /* Disassembler hash function. */ - unsigned int (* dis_hash) PARAMS ((const char *, CGEN_INSN_INT)); + unsigned int (* dis_hash) (const char *, CGEN_INSN_INT); /* Number of entries in disassembler hash table. */ unsigned int dis_hash_size; @@ -1173,6 +1361,10 @@ typedef struct cgen_cpu_desc /* Disassembler instruction hash table. */ CGEN_INSN_LIST **dis_hash_table; CGEN_INSN_LIST *dis_hash_table_entries; + + /* This field could be turned into a bitfield if room for other flags is needed. */ + unsigned int signed_overflow_ok_p; + } CGEN_CPU_TABLE; /* wip */ @@ -1185,105 +1377,111 @@ typedef struct cgen_cpu_desc /* Prototypes of major functions. */ /* FIXME: Move more CGEN_SYM-defined functions into CGEN_CPU_DESC. - Note the init fns though, as that would drag in things that mightn't be + Not the init fns though, as that would drag in things that mightn't be used and might not even exist. */ -/* Open an ISA table for use. */ +/* Argument types to cpu_open. */ + +enum cgen_cpu_open_arg { + CGEN_CPU_OPEN_END, + /* Select instruction set(s), arg is bitmap or 0 meaning "unspecified". */ + CGEN_CPU_OPEN_ISAS, + /* Select machine(s), arg is bitmap or 0 meaning "unspecified". */ + CGEN_CPU_OPEN_MACHS, + /* Select machine, arg is mach's bfd name. + Multiple machines can be specified by repeated use. */ + CGEN_CPU_OPEN_BFDMACH, + /* Select endian, arg is CGEN_ENDIAN_*. */ + CGEN_CPU_OPEN_ENDIAN +}; + +/* Open a cpu descriptor table for use. + ??? We only support ISO C stdargs here, not K&R. + Laziness, plus experiment to see if anything requires K&R - eventually + K&R will no longer be supported - e.g. GDB is currently trying this. */ -extern CGEN_CPU_DESC CGEN_SYM (cpu_open) PARAMS ((int, enum cgen_endian)); +extern CGEN_CPU_DESC CGEN_SYM (cpu_open) (enum cgen_cpu_open_arg, ...); + +/* Cover fn to handle simple case. */ + +extern CGEN_CPU_DESC CGEN_SYM (cpu_open_1) + (const char *mach_name_, enum cgen_endian endian_); /* Close it. */ -extern void CGEN_SYM (cpu_close) PARAMS ((CGEN_CPU_DESC)); +extern void CGEN_SYM (cpu_close) (CGEN_CPU_DESC); /* Initialize the opcode table for use. Called by init_asm/init_dis. */ -extern void CGEN_SYM (init_opcode_table) PARAMS ((CGEN_CPU_DESC cd_)); +extern void CGEN_SYM (init_opcode_table) (CGEN_CPU_DESC cd_); + +/* build the insn selection regex. + called by init_opcode_table */ + +extern char * CGEN_SYM(build_insn_regex) (CGEN_INSN *insn_); /* Initialize the ibld table for use. Called by init_asm/init_dis. */ -extern void CGEN_SYM (init_ibld_table) PARAMS ((CGEN_CPU_DESC cd_)); +extern void CGEN_SYM (init_ibld_table) (CGEN_CPU_DESC cd_); /* Initialize an cpu table for assembler or disassembler use. These must be called immediately after cpu_open. */ -extern void CGEN_SYM (init_asm) PARAMS ((CGEN_CPU_DESC)); -extern void CGEN_SYM (init_dis) PARAMS ((CGEN_CPU_DESC)); +extern void CGEN_SYM (init_asm) (CGEN_CPU_DESC); +extern void CGEN_SYM (init_dis) (CGEN_CPU_DESC); /* Initialize the operand instance table for use. */ -extern void CGEN_SYM (init_opinst_table) PARAMS ((CGEN_CPU_DESC cd_)); - -/* Change the mach and/or endianness. */ +extern void CGEN_SYM (init_opinst_table) (CGEN_CPU_DESC cd_); -extern void cgen_set_cpu PARAMS ((CGEN_CPU_DESC, int, enum cgen_endian)); +/* Assemble an instruction. */ extern const CGEN_INSN * CGEN_SYM (assemble_insn) - PARAMS ((CGEN_CPU_DESC, const char *, CGEN_FIELDS *, - CGEN_INSN_BYTES_PTR, char **)); + (CGEN_CPU_DESC, const char *, CGEN_FIELDS *, + CGEN_INSN_BYTES_PTR, char **); extern const CGEN_KEYWORD CGEN_SYM (operand_mach); -extern int CGEN_SYM (get_mach) PARAMS ((const char *)); +extern int CGEN_SYM (get_mach) (const char *); /* Operand index computation. */ extern const CGEN_INSN * cgen_lookup_insn - PARAMS ((CGEN_CPU_DESC, const CGEN_INSN * insn_, - CGEN_INSN_INT int_value_, unsigned char *bytes_value_, - int length_, CGEN_FIELDS *fields_, int alias_p_)); + (CGEN_CPU_DESC, const CGEN_INSN * insn_, + CGEN_INSN_INT int_value_, unsigned char *bytes_value_, + int length_, CGEN_FIELDS *fields_, int alias_p_); extern void cgen_get_insn_operands - PARAMS ((CGEN_CPU_DESC, const CGEN_INSN * insn_, - const CGEN_FIELDS *fields_, int *indices_)); + (CGEN_CPU_DESC, const CGEN_INSN * insn_, + const CGEN_FIELDS *fields_, int *indices_); extern const CGEN_INSN * cgen_lookup_get_insn_operands - PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *insn_, - CGEN_INSN_INT int_value_, unsigned char *bytes_value_, - int length_, int *indices_, CGEN_FIELDS *fields_)); - -/* Get/set fields in the CGEN_FIELDS struct. */ - -extern int CGEN_SYM (get_int_operand) - PARAMS ((int opindex_, const CGEN_FIELDS *fields_)); -extern void CGEN_SYM (set_int_operand) - PARAMS ((int opindex_, CGEN_FIELDS *fields_, int value_)); -#ifdef BFD_VERSION /* Don't require bfd.h unnecessarily. */ -extern bfd_vma CGEN_SYM (get_vma_operand) - PARAMS ((int opindex_, const CGEN_FIELDS *fields_)); -extern void CGEN_SYM (set_vma_operand) - PARAMS ((int opindex_, CGEN_FIELDS *fields_, bfd_vma value_)); -#endif - -extern const char * CGEN_SYM (parse_operand) - PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *)); - -#ifdef BFD_VERSION /* Don't require bfd.h unnecessarily. */ -extern const char * CGEN_SYM (insert_operand) - PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, - bfd_vma)); -extern int CGEN_SYM (extract_operand) - PARAMS ((CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, - CGEN_FIELDS *, bfd_vma)); -extern void CGEN_SYM (print_operand) - PARAMS ((CGEN_CPU_DESC, int opindex_, PTR info_, CGEN_FIELDS * fields_, - void const *attrs_, bfd_vma pc_, int length_)); -#else -extern const char * CGEN_SYM (insert_operand) (); -extern int CGEN_SYM (extract_operand) (); -extern void CGEN_SYM (print_operand) (); -#endif + (CGEN_CPU_DESC, const CGEN_INSN *insn_, + CGEN_INSN_INT int_value_, unsigned char *bytes_value_, + int length_, int *indices_, CGEN_FIELDS *fields_); /* Cover fns to bfd_get/set. */ extern CGEN_INSN_INT cgen_get_insn_value - PARAMS ((CGEN_CPU_DESC, unsigned char *, int)); + (CGEN_CPU_DESC, unsigned char *, int); extern void cgen_put_insn_value - PARAMS ((CGEN_CPU_DESC, unsigned char *, int, CGEN_INSN_INT)); + (CGEN_CPU_DESC, unsigned char *, int, CGEN_INSN_INT); /* Read in a cpu description file. ??? For future concerns, including adding instructions to the assembler/ disassembler at run-time. */ -extern const char * cgen_read_cpu_file - PARAMS ((CGEN_CPU_DESC, const char * filename_)); +extern const char * cgen_read_cpu_file (CGEN_CPU_DESC, const char * filename_); + +/* Allow signed overflow of instruction fields. */ +extern void cgen_set_signed_overflow_ok (CGEN_CPU_DESC); + +/* Generate an error message if a signed field in an instruction overflows. */ +extern void cgen_clear_signed_overflow_ok (CGEN_CPU_DESC); + +/* Will an error message be generated if a signed field in an instruction overflows ? */ +extern unsigned int cgen_signed_overflow_ok_p (CGEN_CPU_DESC); + +#ifdef __cplusplus +} +#endif -#endif /* CGEN_H */ +#endif /* OPCODE_CGEN_H */