summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/include/opcode/cgen.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/binutils/include/opcode/cgen.h')
-rw-r--r--contrib/binutils/include/opcode/cgen.h671
1 files changed, 429 insertions, 242 deletions
diff --git a/contrib/binutils/include/opcode/cgen.h b/contrib/binutils/include/opcode/cgen.h
index cda3373..ab59f24 100644
--- a/contrib/binutils/include/opcode/cgen.h
+++ b/contrib/binutils/include/opcode/cgen.h
@@ -1,6 +1,6 @@
/* Header file for targets using CGEN: Cpu tools GENerator.
-Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of GDB, the GNU debugger, and the GNU Binutils.
@@ -14,22 +14,13 @@ 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.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef CGEN_H
#define CGEN_H
-#ifndef CGEN_CAT3
-#if defined(__STDC__) || defined(ALMOST_STDC)
-#define CGEN_XCAT3(a,b,c) a ## b ## c
-#define CGEN_CAT3(a,b,c) CGEN_XCAT3 (a, b, c)
-#else
-#define CGEN_CAT3(a,b,c) a/**/b/**/c
-#endif
-#endif
-
/* Prepend the cpu name, defined in cpu-opc.h, and _cgen_ to symbol S.
The lack of spaces in the arg list is important for non-stdc systems.
This file is included by <cpu>-opc.h.
@@ -37,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
dependent portions will be declared as "unknown_cgen_foo". */
#ifndef CGEN_SYM
-#define CGEN_SYM(s) CGEN_CAT3 (unknown,_cgen_,s)
+#define CGEN_SYM(s) CONCAT3 (unknown,_cgen_,s)
#endif
/* This file contains the static (unchanging) pieces and as much other stuff
@@ -60,7 +51,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef CGEN_INT_INSN
typedef unsigned int cgen_insn_t;
#else
-typedef char *cgen_insn_t;
+typedef char * cgen_insn_t;
#endif
#ifdef __GNUC__
@@ -71,7 +62,8 @@ typedef char *cgen_insn_t;
/* Perhaps we should just use bfd.h, but it's not clear
one would want to require that yet. */
-enum cgen_endian {
+enum cgen_endian
+{
CGEN_ENDIAN_UNKNOWN,
CGEN_ENDIAN_LITTLE,
CGEN_ENDIAN_BIG
@@ -81,8 +73,9 @@ enum cgen_endian {
Attributes are used to describe various random things. */
/* Struct to record attribute information. */
-typedef struct {
- unsigned int num_nonbools;
+typedef struct
+{
+ unsigned char num_nonbools;
unsigned int bool;
unsigned int nonbool[1];
} CGEN_ATTR;
@@ -94,13 +87,17 @@ typedef struct {
nonbool: values of non-boolean attributes
There is a maximum of 32 attributes total. */
#define CGEN_ATTR_TYPE(n) \
-const struct { unsigned int num_nonbools; \
+const struct { unsigned char num_nonbools; \
unsigned int bool; \
unsigned int nonbool[(n) ? (n) : 1]; }
/* Given an attribute number, return its mask. */
#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.
It's not used at present but is reserved for future purposes. */
@@ -108,6 +105,24 @@ const struct { unsigned int num_nonbools; \
((unsigned int) (attr) < (attr_table)->num_nonbools \
? ((attr_table)->nonbool[attr]) \
: (((attr_table)->bool & (1 << (attr))) != 0))
+
+/* Attribute name/value tables.
+ These are used to assist parsing of descriptions at runtime. */
+
+typedef struct
+{
+ const char * name;
+ int value;
+} CGEN_ATTR_ENTRY;
+
+/* For each domain (fld,operand,insn), list of attributes. */
+
+typedef struct
+{
+ const char * name;
+ /* NULL for boolean attributes. */
+ const CGEN_ATTR_ENTRY * vals;
+} CGEN_ATTR_TABLE;
/* Parse result (also extraction result).
@@ -125,7 +140,7 @@ const struct { unsigned int num_nonbools; \
where it varies.
*/
-struct cgen_fields;
+typedef struct cgen_fields CGEN_FIELDS;
/* Total length of the insn, as recorded in the `fields' struct. */
/* ??? The field insert handler has lots of opportunities for optimization
@@ -151,7 +166,7 @@ typedef struct cgen_insn CGEN_INSN;
The result is NULL if success or an error message. */
typedef const char * (cgen_parse_fn) PARAMS ((const struct cgen_insn *,
const char **,
- struct cgen_fields *));
+ CGEN_FIELDS *));
/* Print handler.
The first argument is a pointer to the disassembly info.
@@ -165,7 +180,7 @@ typedef const char * (cgen_parse_fn) PARAMS ((const struct cgen_insn *,
/* Don't require bfd.h unnecessarily. */
#ifdef BFD_VERSION
typedef void (cgen_print_fn) PARAMS ((PTR, const struct cgen_insn *,
- struct cgen_fields *, bfd_vma, int));
+ CGEN_FIELDS *, bfd_vma, int));
#else
typedef void (cgen_print_fn) ();
#endif
@@ -175,9 +190,10 @@ typedef void (cgen_print_fn) ();
parsed.
The second argument is a pointer to a cgen_fields struct
from which the values are fetched.
- The third argument is a pointer to a buffer in which to place the insn. */
-typedef void (cgen_insert_fn) PARAMS ((const struct cgen_insn *,
- struct cgen_fields *, cgen_insn_t *));
+ The third argument is a pointer to a buffer in which to place the insn.
+ The result is an error message or NULL if success. */
+typedef const char * (cgen_insert_fn) PARAMS ((const struct cgen_insn *,
+ CGEN_FIELDS *, cgen_insn_t *));
/* Extract handler.
The first argument is a pointer to a struct describing the insn being
@@ -190,7 +206,7 @@ typedef void (cgen_insert_fn) PARAMS ((const struct cgen_insn *,
The result is the length of the insn or zero if not recognized. */
typedef int (cgen_extract_fn) PARAMS ((const struct cgen_insn *,
void *, cgen_insn_t,
- struct cgen_fields *));
+ CGEN_FIELDS *));
/* The `parse' and `insert' fields are indices into these tables.
The elements are pointer to specialized handler functions.
@@ -207,127 +223,155 @@ extern cgen_print_fn * CGEN_SYM (print_handlers) [];
#define CGEN_PRINT_FN(x) (CGEN_SYM (print_handlers)[(x)->base.print])
/* Base class of parser/printer.
- (Don't read too much into the use of the phrase "base class").
+ (Don't read too much into the use of the phrase "base class".
+ It's a name I'm using to organize my thoughts.)
Instructions and expressions all share this data in common.
- It's a collection of the common elements needed to parse and print
- each of them. */
+ It's a collection of the common elements needed to parse, insert, extract,
+ and print each of them. */
-#ifndef CGEN_MAX_INSN_ATTRS
-#define CGEN_MAX_INSN_ATTRS 1
-#endif
-
-struct cgen_base {
+struct cgen_base
+{
/* Indices into the handler tables.
We could use pointers here instead, but in the case of the insn table,
90% of them would be identical and that's a lot of redundant data.
0 means use the default (what the default is is up to the code). */
unsigned char parse, insert, extract, print;
-
- /* Attributes. */
- CGEN_ATTR_TYPE (CGEN_MAX_INSN_ATTRS) attrs;
};
-/* Syntax table.
+/* Assembler interface.
- Each insn and subexpression has one of these.
+ The interface to the assembler is intended to be clean in the sense that
+ libopcodes.a is a standalone entity and could be used with any assembler.
+ Not that one would necessarily want to do that but rather that it helps
+ keep a clean interface. The interface will obviously be slanted towards
+ GAS, but at least it's a start.
- The syntax "string" consists of characters (n > 0 && n < 128), and operand
- values (n >= 128), and is terminated by 0. Operand values are 128 + index
- 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.
+ Parsing is controlled by the assembler which calls
+ CGEN_SYM (assemble_insn). If it can parse and build the entire insn
+ it doesn't call back to the assembler. If it needs/wants to call back
+ to the assembler, (*cgen_parse_operand_fn) is called which can either
- ??? Whether we want to use yacc instead is unclear, but we do make an
- effort to not make doing that difficult. At least that's the intent.
-*/
+ - return a number to be inserted in the insn
+ - return a "register" value to be inserted
+ (the register might not be a register per pe)
+ - queue the argument and return a marker saying the expression has been
+ queued (eg: a fix-up)
+ - return an error message indicating the expression wasn't recognizable
-struct cgen_syntax {
- /* Original syntax string, for debugging purposes. */
- char *orig;
+ The result is an error message or NULL for success.
+ The parsed value is stored in the bfd_vma *. */
- /* Name of entry (that distinguishes it from all other entries).
- This is used, for example, in simulator profiling results. */
- char *name;
+/* Values for indicating what the caller wants. */
+enum cgen_parse_operand_type
+{
+ CGEN_PARSE_OPERAND_INIT,
+ CGEN_PARSE_OPERAND_INTEGER,
+ CGEN_PARSE_OPERAND_ADDRESS
+};
+
+/* Values for indicating what was parsed.
+ ??? Not too useful at present but in time. */
+enum cgen_parse_operand_result
+{
+ CGEN_PARSE_OPERAND_RESULT_NUMBER,
+ CGEN_PARSE_OPERAND_RESULT_REGISTER,
+ CGEN_PARSE_OPERAND_RESULT_QUEUED,
+ CGEN_PARSE_OPERAND_RESULT_ERROR
+};
-#if 0 /* not needed yet */
- /* Format of this insn.
- This doesn't closely follow the notion of instruction formats for more
- complex instruction sets. This is the value computed at runtime. */
- enum cgen_fmt_type fmt;
+/* Don't require bfd.h unnecessarily. */
+#ifdef BFD_VERSION
+extern const char * (*cgen_parse_operand_fn)
+ PARAMS ((enum cgen_parse_operand_type, const char **, int, int,
+ enum cgen_parse_operand_result *, bfd_vma *));
#endif
- /* Mnemonic (or name if expression). */
- char *mnemonic;
+/* Called before trying to match a table entry with the insn. */
+void cgen_init_parse_operand PARAMS ((void));
- /* Syntax string. */
- /* FIXME: If each insn's mnemonic is constant, do we want to record just
- the arguments here? */
-#ifndef CGEN_MAX_SYNTAX_BYTES
-#define CGEN_MAX_SYNTAX_BYTES 16
-#endif
- unsigned char syntax[CGEN_MAX_SYNTAX_BYTES];
+/* Called from <cpu>-asm.c to initialize operand parsing. */
-#define CGEN_SYNTAX_CHAR_P(c) ((c) < 128)
-#define CGEN_SYNTAX_CHAR(c) (c)
-#define CGEN_SYNTAX_FIELD(c) ((c) - 128)
+/* These are GAS specific. They're not here as part of the interface,
+ but rather that we need to put them somewhere. */
- /* recognize insn if (op & mask) == value
- For architectures with variable length insns, this is just a preliminary
- test. */
- /* FIXME: Might want a selectable type (rather than always
- unsigned long). */
- unsigned long mask, value;
+/* Call this from md_assemble to initialize the assembler callback. */
+void cgen_asm_init_parse PARAMS ((void));
- /* length, in bits
- This is the size that `mask' and `value' have been calculated to.
- Normally it is CGEN_BASE_INSN_BITSIZE. On vliw architectures where
- the base insn size may be larger than the size of an insn, this field is
- less than CGEN_BASE_INSN_BITSIZE.
- On architectures like the 386 and m68k the real size of the insn may
- be computed while parsing. */
- /* FIXME: wip, of course */
- int length;
-};
+/* Don't require bfd.h unnecessarily. */
+#ifdef BFD_VERSION
+/* The result is an error message or NULL for success.
+ The parsed value is stored in the bfd_vma *. */
+const char * cgen_parse_operand PARAMS ((enum cgen_parse_operand_type,
+ const char **, int, int,
+ enum cgen_parse_operand_result *,
+ bfd_vma *));
+#endif
+
+void cgen_save_fixups PARAMS ((void));
+void cgen_restore_fixups PARAMS ((void));
+void cgen_swap_fixups PARAMS ((void));
+
+/* Add a register to the assembler's hash table.
+ This makes lets GAS parse registers for us.
+ ??? This isn't currently used, but it could be in the future. */
+void cgen_asm_record_register PARAMS ((char *, int));
+
+/* After CGEN_SYM (assemble_insn) is done, this is called to
+ output the insn and record any fixups. The address of the
+ assembled instruction is returned in case it is needed by
+ the caller. */
+char * cgen_asm_finish_insn PARAMS ((const struct cgen_insn *, cgen_insn_t *,
+ unsigned int));
/* Operand values (keywords, integers, symbols, etc.) */
/* Types of assembler elements. */
-enum cgen_asm_type {
+enum cgen_asm_type
+{
CGEN_ASM_KEYWORD, CGEN_ASM_MAX
};
/* List of hardware elements. */
-typedef struct cgen_hw_entry {
- struct cgen_hw_entry *next;
- char *name;
- enum cgen_asm_type asm_type;
- PTR asm_data;
+typedef struct cgen_hw_entry
+{
+ /* 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;
+ enum cgen_asm_type asm_type;
+ PTR asm_data;
} CGEN_HW_ENTRY;
-extern CGEN_HW_ENTRY *CGEN_SYM (hw_list);
-
-CGEN_HW_ENTRY *cgen_hw_lookup PARAMS ((const char *));
-
-#ifndef CGEN_MAX_KEYWORD_ATTRS
-#define CGEN_MAX_KEYWORD_ATTRS 1
-#endif
+const CGEN_HW_ENTRY * cgen_hw_lookup PARAMS ((const char *));
/* This struct is used to describe things like register names, etc. */
-typedef struct cgen_keyword_entry {
+typedef struct cgen_keyword_entry
+{
/* Name (as in register name). */
- char *name;
+ char * name;
/* Value (as in register number).
The value cannot be -1 as that is used to indicate "not found".
IDEA: Have "FUNCTION" attribute? [function is called to fetch value]. */
int value;
- /* Attributes. */
+ /* Attributes.
+ This should, but technically needn't, appear last. It is a variable sized
+ array in that one architecture may have 1 nonbool attribute and another
+ may have more. Having this last means the non-architecture specific code
+ needn't care. */
+ /* ??? Moving this last should be done by treating keywords like insn lists
+ and moving the `next' fields into a CGEN_KEYWORD_LIST struct. */
/* FIXME: Not used yet. */
- CGEN_ATTR_TYPE (CGEN_MAX_KEYWORD_ATTRS) attrs;
+#ifndef CGEN_KEYWORD_NBOOL_ATTRS
+#define CGEN_KEYWORD_NBOOL_ATTRS 1
+#endif
+ CGEN_ATTR_TYPE (CGEN_KEYWORD_NBOOL_ATTRS) attrs;
/* Next name hash table entry. */
struct cgen_keyword_entry *next_name;
@@ -340,93 +384,138 @@ typedef struct cgen_keyword_entry {
This struct supports runtime entry of new values, and hashed lookups. */
-typedef struct cgen_keyword {
+typedef struct cgen_keyword
+{
/* Pointer to initial [compiled in] values. */
- struct cgen_keyword_entry *init_entries;
+ CGEN_KEYWORD_ENTRY * init_entries;
+
/* Number of entries in `init_entries'. */
unsigned int num_init_entries;
+
/* Hash table used for name lookup. */
- struct cgen_keyword_entry **name_hash_table;
+ CGEN_KEYWORD_ENTRY ** name_hash_table;
+
/* Hash table used for value lookup. */
- struct cgen_keyword_entry **value_hash_table;
+ CGEN_KEYWORD_ENTRY ** value_hash_table;
+
/* Number of entries in the hash_tables. */
unsigned int hash_table_size;
+
+ /* Pointer to null keyword "" entry if present. */
+ const CGEN_KEYWORD_ENTRY * null_entry;
} CGEN_KEYWORD;
/* Structure used for searching. */
-typedef struct cgen_keyword_search {
+typedef struct
+{
/* Table being searched. */
- const struct cgen_keyword *table;
+ const CGEN_KEYWORD * table;
+
/* Specification of what is being searched for. */
- const char *spec;
+ const char * spec;
+
/* Current index in hash table. */
unsigned int current_hash;
+
/* Current element in current hash chain. */
- struct cgen_keyword_entry *current_entry;
+ CGEN_KEYWORD_ENTRY * current_entry;
} CGEN_KEYWORD_SEARCH;
/* Lookup a keyword from its name. */
-const struct cgen_keyword_entry * cgen_keyword_lookup_name
- PARAMS ((struct cgen_keyword *, const char *));
+const CGEN_KEYWORD_ENTRY * cgen_keyword_lookup_name
+ PARAMS ((CGEN_KEYWORD *, const char *));
/* Lookup a keyword from its value. */
-const struct cgen_keyword_entry * cgen_keyword_lookup_value
- PARAMS ((struct cgen_keyword *, int));
+const CGEN_KEYWORD_ENTRY * cgen_keyword_lookup_value
+ PARAMS ((CGEN_KEYWORD *, int));
/* Add a keyword. */
-void cgen_keyword_add PARAMS ((struct cgen_keyword *,
- struct cgen_keyword_entry *));
+void cgen_keyword_add PARAMS ((CGEN_KEYWORD *, CGEN_KEYWORD_ENTRY *));
/* Keyword searching.
This can be used to retrieve every keyword, or a subset. */
-struct cgen_keyword_search cgen_keyword_search_init
- PARAMS ((struct cgen_keyword *, const char *));
-const struct cgen_keyword_entry *cgen_keyword_search_next
- PARAMS ((struct cgen_keyword_search *));
+CGEN_KEYWORD_SEARCH cgen_keyword_search_init
+ PARAMS ((CGEN_KEYWORD *, const char *));
+const CGEN_KEYWORD_ENTRY *cgen_keyword_search_next
+ PARAMS ((CGEN_KEYWORD_SEARCH *));
/* Operand value support routines. */
/* FIXME: some of the long's here will need to be bfd_vma or some such. */
const char * cgen_parse_keyword PARAMS ((const char **,
- struct cgen_keyword *,
+ CGEN_KEYWORD *,
long *));
-const char * cgen_parse_signed_integer PARAMS ((const char **, int,
- long, long, long *));
+const char * cgen_parse_signed_integer PARAMS ((const char **, int, long *));
const char * cgen_parse_unsigned_integer PARAMS ((const char **, int,
- unsigned long, unsigned long,
unsigned long *));
-const char * cgen_parse_address PARAMS ((const char **, int,
- int, long *));
+const char * cgen_parse_address PARAMS ((const char **, int, int,
+ enum cgen_parse_operand_result *,
+ long *));
const char * cgen_validate_signed_integer PARAMS ((long, long, long));
const char * cgen_validate_unsigned_integer PARAMS ((unsigned long,
unsigned long,
unsigned long));
+/* Operand modes. */
+
+/* ??? This duplicates the values in arch.h. Revisit.
+ These however need the CGEN_ prefix [as does everything in this file]. */
+/* ??? Targets may need to add their own modes so we may wish to move this
+ to <arch>-opc.h, or add a hook. */
+
+enum cgen_mode {
+ CGEN_MODE_VOID, /* FIXME: rename simulator's VM to VOID */
+ CGEN_MODE_BI, CGEN_MODE_QI, CGEN_MODE_HI, CGEN_MODE_SI, CGEN_MODE_DI,
+ CGEN_MODE_UBI, CGEN_MODE_UQI, CGEN_MODE_UHI, CGEN_MODE_USI, CGEN_MODE_UDI,
+ CGEN_MODE_SF, CGEN_MODE_DF, CGEN_MODE_XF, CGEN_MODE_TF,
+ CGEN_MODE_MAX
+};
+
+/* FIXME: Until simulator is updated. */
+#define CGEN_MODE_VM CGEN_MODE_VOID
+
/* This struct defines each entry in the operand table. */
-#ifndef CGEN_MAX_OPERAND_ATTRS
-#define CGEN_MAX_OPERAND_ATTRS 1
-#endif
+typedef struct cgen_operand
+{
+ /* Name as it appears in the syntax string. */
+ char * name;
-typedef struct cgen_operand {
- /* For debugging. */
- char *name;
+ /* The hardware element associated with this operand. */
+ const CGEN_HW_ENTRY *hw;
+
+ /* 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. */
/* Bit position (msb of first byte = bit 0).
+ This is just a hint, and may be unused in more complex operands.
May be unused for a modifier. */
unsigned char start;
/* The number of bits in the operand.
+ This is just a hint, and may be unused in more complex operands.
May be unused for a modifier. */
unsigned char length;
- /* Attributes. */
- CGEN_ATTR_TYPE (CGEN_MAX_OPERAND_ATTRS) attrs;
-#define CGEN_OPERAND_ATTRS(operand) (&(operand)->attrs)
-
-#if 0 /* ??? Interesting idea but relocs tend to get too complicated for
- simple table lookups to work. */
+#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. */
int reloc_type;
#endif
+
+ /* Attributes.
+ This should, but technically needn't, appear last. It is a variable sized
+ array in that one architecture may have 1 nonbool attribute and another
+ may have more. Having this last means the non-architecture specific code
+ needn't care, now or tomorrow. */
+#ifndef CGEN_OPERAND_NBOOL_ATTRS
+#define CGEN_OPERAND_NBOOL_ATTRS 1
+#endif
+ CGEN_ATTR_TYPE (CGEN_OPERAND_NBOOL_ATTRS) attrs;
+#define CGEN_OPERAND_ATTRS(operand) (&(operand)->attrs)
} CGEN_OPERAND;
/* Return value of attribute ATTR in OPERAND. */
@@ -442,48 +531,207 @@ enum cgen_operand_type;
/* FIXME: Rename, cpu-opc.h defines this as the typedef of the enum. */
#define CGEN_OPERAND_TYPE(operand) ((enum cgen_operand_type) CGEN_OPERAND_INDEX (operand))
#define CGEN_OPERAND_ENTRY(n) (& CGEN_SYM (operand_table) [n])
+
+/* Types of parse/insert/extract/print cover-fn handlers. */
+/* FIXME: move opindex first to match caller. */
+/* FIXME: also need types of insert/extract/print fns. */
+/* FIXME: not currently used as type of 3rd arg varies. */
+typedef const char * (CGEN_PARSE_OPERAND_FN) PARAMS ((const char **, int,
+ long *));
+
+/* Instruction operand instances.
+
+ For each instruction, a list of the hardware elements that are read and
+ written are recorded. */
+
+/* The type of the instance. */
+enum cgen_operand_instance_type {
+ /* End of table marker. */
+ CGEN_OPERAND_INSTANCE_END = 0,
+ CGEN_OPERAND_INSTANCE_INPUT, CGEN_OPERAND_INSTANCE_OUTPUT
+};
+
+typedef struct
+{
+ /* The type of this operand. */
+ enum cgen_operand_instance_type type;
+#define CGEN_OPERAND_INSTANCE_TYPE(opinst) ((opinst)->type)
+
+ /* The hardware element referenced. */
+ const CGEN_HW_ENTRY *hw;
+#define CGEN_OPERAND_INSTANCE_HW(opinst) ((opinst)->hw)
+
+ /* The mode in which the operand is being used. */
+ enum cgen_mode mode;
+#define CGEN_OPERAND_INSTANCE_MODE(opinst) ((opinst)->mode)
+
+ /* The operand table entry or NULL if there is none (i.e. an explicit
+ hardware reference). */
+ const CGEN_OPERAND *operand;
+#define CGEN_OPERAND_INSTANCE_OPERAND(opinst) ((opinst)->operand)
+
+ /* If `operand' is NULL, the index (e.g. into array of registers). */
+ int index;
+#define CGEN_OPERAND_INSTANCE_INDEX(opinst) ((opinst)->index)
+} CGEN_OPERAND_INSTANCE;
+
+/* Syntax string.
+
+ Each insn format and subexpression has one of these.
+
+ The syntax "string" consists of characters (n > 0 && n < 128), and operand
+ values (n >= 128), and is terminated by 0. Operand values are 128 + index
+ 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
+#endif
+
+typedef struct
+{
+ unsigned char syntax[CGEN_MAX_SYNTAX_BYTES];
+} 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_FIELD(c) ((c) - 128)
+#define CGEN_SYNTAX_MAKE_FIELD(c) ((c) + 128)
+
+/* ??? I can't currently think of any case where the mnemonic doesn't come
+ first [and if one ever doesn't building the hash tables will be tricky].
+ However, we treat mnemonics as just another operand of the instruction.
+ A value of 1 means "this is where the mnemonic appears". 1 isn't
+ special other than it's a non-printable ASCII char. */
+#define CGEN_SYNTAX_MNEMONIC 1
+#define CGEN_SYNTAX_MNEMONIC_P(ch) ((ch) == CGEN_SYNTAX_MNEMONIC)
+
+/* Instruction formats.
+
+ Instructions are grouped by format. Associated with an instruction is its
+ format. Each opcode table entry contains a format table entry.
+ ??? There is usually very few formats compared with the number of insns,
+ so one can reduce the size of the opcode table by recording the format table
+ as a separate entity. Given that we currently don't, format table entries
+ are also distinguished by their operands. This increases the size of the
+ table, but reduces the number of tables. It's all minutiae anyway so it
+ doesn't really matter [at this point in time].
+
+ ??? Support for variable length ISA's is wip. */
+
+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. */
+ unsigned char mask_length;
+
+ /* Total length of instruction, in bits. */
+ unsigned char length;
+
+ /* Mask to apply to the first MASK_LENGTH bits.
+ Each insn's value is stored with the insn.
+ The first step in recognizing an insn for disassembly is
+ (opcode & mask) == value. */
+ unsigned int mask;
+} CGEN_FORMAT;
/* This struct defines each entry in the instruction table. */
-struct cgen_insn {
+struct cgen_insn
+{
+ /* ??? Further table size reductions can be had by moving this element
+ either to the format table or to a separate table of its own. Not
+ sure this is desirable yet. */
struct cgen_base base;
+
/* Given a pointer to a cgen_insn struct, return a pointer to `base'. */
#define CGEN_INSN_BASE(insn) (&(insn)->base)
-#define CGEN_INSN_ATTRS(insn) (&(insn)->base.attrs)
- struct cgen_syntax syntax;
-#define CGEN_INSN_SYNTAX(insn) (&(insn)->syntax)
-#define CGEN_INSN_FMT(insn) ((insn)->syntax.fmt)
-#define CGEN_INSN_BITSIZE(insn) ((insn)->syntax.length)
-};
+ /* Name of entry (that distinguishes it from all other entries).
+ This is used, for example, in simulator profiling results. */
+ /* ??? If mnemonics have operands, try to print full mnemonic. */
+ const char * name;
+#define CGEN_INSN_NAME(insn) ((insn)->name)
+ /* Mnemonic. This is used when parsing and printing the insn.
+ In the case of insns that have operands on the mnemonics, this is
+ only the constant part. E.g. for conditional execution of an `add' insn,
+ where the full mnemonic is addeq, addne, etc., this is only "add". */
+ const char * mnemonic;
+#define CGEN_INSN_MNEMONIC(insn) ((insn)->mnemonic)
+
+ /* Syntax string. */
+ const CGEN_SYNTAX syntax;
+#define CGEN_INSN_SYNTAX(insn) (& (insn)->syntax)
+
+ /* Format entry. */
+ const CGEN_FORMAT format;
+#define CGEN_INSN_MASK_BITSIZE(insn) ((insn)->format.mask_length)
+#define CGEN_INSN_BITSIZE(insn) ((insn)->format.length)
+
+ /* Instruction opcode value. */
+ unsigned int value;
+#define CGEN_INSN_VALUE(insn) ((insn)->value)
+#define CGEN_INSN_MASK(insn) ((insn)->format.mask)
+
+ /* Pointer to NULL entry terminated table of operands used,
+ or NULL if none. */
+ const CGEN_OPERAND_INSTANCE *operands;
+#define CGEN_INSN_OPERANDS(insn) ((insn)->operands)
+
+ /* Attributes.
+ This must appear last. It is a variable sized array in that one
+ architecture may have 1 nonbool attribute and another may have more.
+ Having this last means the non-architecture specific code needn't
+ care. */
+#ifndef CGEN_INSN_NBOOL_ATTRS
+#define CGEN_INSN_NBOOL_ATTRS 1
+#endif
+ CGEN_ATTR_TYPE (CGEN_INSN_NBOOL_ATTRS) attrs;
+#define CGEN_INSN_ATTRS(insn) (&(insn)->attrs)
/* Return value of attribute ATTR in INSN. */
#define CGEN_INSN_ATTR(insn, attr) \
CGEN_ATTR_VALUE (insn, CGEN_INSN_ATTRS (insn), attr)
+};
/* Instruction lists.
This is used for adding new entries and for creating the hash lists. */
-typedef struct cgen_insn_list {
- struct cgen_insn_list *next;
- const struct cgen_insn *insn;
+typedef struct cgen_insn_list
+{
+ struct cgen_insn_list * next;
+ const CGEN_INSN * insn;
} CGEN_INSN_LIST;
/* The table of instructions. */
-typedef struct cgen_insn_table {
+typedef struct
+{
/* Pointer to initial [compiled in] entries. */
- const struct cgen_insn *init_entries;
+ const CGEN_INSN * init_entries;
+
+ /* Size of an entry (since the attribute member is variable sized). */
+ unsigned int entry_size;
+
/* Number of entries in `init_entries', including trailing NULL entry. */
unsigned int num_init_entries;
+
/* Values added at runtime. */
- struct cgen_insn_list *new_entries;
+ CGEN_INSN_LIST * new_entries;
+
/* Assembler hash function. */
- unsigned int (*asm_hash) PARAMS ((const char *));
+ unsigned int (* asm_hash) PARAMS ((const char *));
+
/* Number of entries in assembler hash table. */
unsigned int asm_hash_table_size;
+
/* Disassembler hash function. */
- unsigned int (*dis_hash) PARAMS ((const char *, unsigned long));
+ unsigned int (* dis_hash) PARAMS ((const char *, unsigned long));
+
/* Number of entries in disassembler hash table. */
unsigned int dis_hash_table_size;
} CGEN_INSN_TABLE;
@@ -498,7 +746,7 @@ extern const CGEN_INSN CGEN_SYM (insn_table_entries)[];
/* Return number of instructions. This includes any added at runtime. */
-int cgen_insn_count PARAMS (());
+int cgen_insn_count PARAMS ((void));
/* 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
@@ -541,10 +789,11 @@ CGEN_INSN_LIST * cgen_dis_lookup_insn PARAMS ((const char *, unsigned long));
/* Top level structures and functions. */
-typedef struct cgen_opcode_data {
- CGEN_HW_ENTRY *hw_list;
- /*CGEN_OPERAND_TABLE *operand_table; - FIXME:wip */
- CGEN_INSN_TABLE *insn_table;
+typedef struct
+{
+ const CGEN_HW_ENTRY * hw_list;
+ /*CGEN_OPERAND_TABLE * operand_table; - FIXME:wip */
+ CGEN_INSN_TABLE * insn_table;
} CGEN_OPCODE_DATA;
/* Each CPU has one of these. */
@@ -562,7 +811,7 @@ extern enum cgen_endian cgen_current_endian;
/* Prototypes of major functions. */
-/* Set the current cpu (+ mach number, endian, etc.). *?
+/* Set the current cpu (+ mach number, endian, etc.). */
void cgen_set_cpu PARAMS ((CGEN_OPCODE_DATA *, int, enum cgen_endian));
/* Initialize the assembler, disassembler. */
@@ -577,28 +826,40 @@ void CGEN_SYM (init_parse) PARAMS ((void));
void CGEN_SYM (init_print) PARAMS ((void));
void CGEN_SYM (init_insert) PARAMS ((void));
void CGEN_SYM (init_extract) PARAMS ((void));
+
+/* FIXME: This prototype is wrong ifndef CGEN_INT_INSN.
+ Furthermore, ifdef CGEN_INT_INSN, the insn is created in
+ target byte order (in which case why use int's at all).
+ Perhaps replace cgen_insn_t * with char *? */
const struct cgen_insn *
-CGEN_SYM (assemble_insn) PARAMS ((const char *, struct cgen_fields *,
+CGEN_SYM (assemble_insn) PARAMS ((const char *, CGEN_FIELDS *,
cgen_insn_t *, char **));
-int CGEN_SYM (insn_supported) PARAMS ((const struct cgen_syntax *));
#if 0 /* old */
+int CGEN_SYM (insn_supported) PARAMS ((const struct cgen_insn *));
int CGEN_SYM (opval_supported) PARAMS ((const struct cgen_opval *));
#endif
-extern const struct cgen_keyword CGEN_SYM (operand_mach);
+extern const CGEN_KEYWORD CGEN_SYM (operand_mach);
int CGEN_SYM (get_mach) PARAMS ((const char *));
+const CGEN_INSN *
+CGEN_SYM (get_insn_operands) PARAMS ((const CGEN_INSN *, cgen_insn_t,
+ int, int *));
+const CGEN_INSN *
+CGEN_SYM (lookup_insn) PARAMS ((const CGEN_INSN *, cgen_insn_t,
+ int, CGEN_FIELDS *, int));
+
CGEN_INLINE void
CGEN_SYM (put_operand) PARAMS ((int, const long *,
- struct cgen_fields *));
+ CGEN_FIELDS *));
CGEN_INLINE long
-CGEN_SYM (get_operand) PARAMS ((int, const struct cgen_fields *));
+CGEN_SYM (get_operand) PARAMS ((int, const CGEN_FIELDS *));
-CGEN_INLINE const char *
-CGEN_SYM (parse_operand) PARAMS ((int, const char **, struct cgen_fields *));
+const char *
+CGEN_SYM (parse_operand) PARAMS ((int, const char **, CGEN_FIELDS *));
-CGEN_INLINE const char *
-CGEN_SYM (validate_operand) PARAMS ((int, const struct cgen_fields *));
+const char *
+CGEN_SYM (insert_operand) PARAMS ((int, CGEN_FIELDS *, char *));
/* Default insn parser, printer. */
extern cgen_parse_fn CGEN_SYM (parse_insn);
@@ -608,79 +869,5 @@ extern cgen_print_fn CGEN_SYM (print_insn);
/* Read in a cpu description file. */
const char * cgen_read_cpu_file PARAMS ((const char *));
-
-/* Assembler interface.
-
- The interface to the assembler is intended to be clean in the sense that
- libopcodes.a is a standalone entity and could be used with any assembler.
- Not that one would necessarily want to do that but rather that it helps
- keep a clean interface. The interface will obviously be slanted towards
- GAS, but at least it's a start.
-
- Parsing is controlled by the assembler which calls
- CGEN_SYM (assemble_insn). If it can parse and build the entire insn
- it doesn't call back to the assembler. If it needs/wants to call back
- to the assembler, (*cgen_parse_operand_fn) is called which can either
-
- - return a number to be inserted in the insn
- - return a "register" value to be inserted
- (the register might not be a register per pe)
- - queue the argument and return a marker saying the expression has been
- queued (eg: a fix-up)
- - return an error message indicating the expression wasn't recognizable
-
- The result is an error message or NULL for success.
- The parsed value is stored in the bfd_vma *. */
-
-/* Values for indicating what the caller wants. */
-enum cgen_parse_operand_type {
- CGEN_PARSE_OPERAND_INIT, CGEN_PARSE_OPERAND_INTEGER,
- CGEN_PARSE_OPERAND_ADDRESS
-};
-
-/* Values for indicating what was parsed.
- ??? Not too useful at present but in time. */
-enum cgen_parse_operand_result {
- CGEN_PARSE_OPERAND_RESULT_NUMBER, CGEN_PARSE_OPERAND_RESULT_REGISTER,
- CGEN_PARSE_OPERAND_RESULT_QUEUED, CGEN_PARSE_OPERAND_RESULT_ERROR
-};
-
-/* Don't require bfd.h unnecessarily. */
-#ifdef BFD_VERSION
-extern const char * (*cgen_parse_operand_fn)
- PARAMS ((enum cgen_parse_operand_type, const char **, int, int,
- enum cgen_parse_operand_result *, bfd_vma *));
-#endif
-
-/* Called before trying to match a table entry with the insn. */
-void cgen_init_parse_operand PARAMS ((void));
-
-/* Called from <cpu>-asm.c to initialize operand parsing. */
-
-/* These are GAS specific. They're not here as part of the interface,
- but rather that we need to put them somewhere. */
-
-/* Call this from md_assemble to initialize the assembler callback. */
-void cgen_asm_init_parse PARAMS ((void));
-
-/* Don't require bfd.h unnecessarily. */
-#ifdef BFD_VERSION
-/* The result is an error message or NULL for success.
- The parsed value is stored in the bfd_vma *. */
-const char *cgen_parse_operand PARAMS ((enum cgen_parse_operand_type,
- const char **, int, int,
- enum cgen_parse_operand_result *,
- bfd_vma *));
-#endif
-
-/* Add a register to the assembler's hash table.
- This makes lets GAS parse registers for us.
- ??? This isn't currently used, but it could be in the future. */
-void cgen_asm_record_register PARAMS ((char *, int));
-
-/* After CGEN_SYM (assemble_insn) is done, this is called to
- output the insn and record any fixups. */
-void cgen_asm_finish_insn PARAMS ((const struct cgen_insn *, cgen_insn_t *,
- unsigned int));
#endif /* CGEN_H */
OpenPOWER on IntegriCloud