* cgen.h (*): Clean up pass over `struct foo' usage.
(CGEN_ATTR): Make unsigned char. (CGEN_ATTR_TYPE): Update. (CGEN_ATTR_{ENTRY,TABLE}): New types. (cgen_base): Move member `attrs' to cgen_insn. (CGEN_KEYWORD): New member `null_entry'. (CGEN_{SYNTAX,FORMAT}): New types. (cgen_insn): Format and syntax separated from each other.
This commit is contained in:
parent
e21fb2aec6
commit
19d45995ed
@ -1,3 +1,14 @@
|
||||
Mon Jan 12 11:37:36 1998 Doug Evans <devans@seba.cygnus.com>
|
||||
|
||||
* cgen.h (*): Clean up pass over `struct foo' usage.
|
||||
(CGEN_ATTR): Make unsigned char.
|
||||
(CGEN_ATTR_TYPE): Update.
|
||||
(CGEN_ATTR_{ENTRY,TABLE}): New types.
|
||||
(cgen_base): Move member `attrs' to cgen_insn.
|
||||
(CGEN_KEYWORD): New member `null_entry'.
|
||||
(CGEN_{SYNTAX,FORMAT}): New types.
|
||||
(cgen_insn): Format and syntax separated from each other.
|
||||
|
||||
start-sanitize-sky
|
||||
Mon Jan 5 13:33:21 1998 Doug Evans <devans@seba.cygnus.com>
|
||||
|
||||
|
@ -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,9 +14,9 @@ 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
|
||||
@ -82,7 +82,7 @@ enum cgen_endian {
|
||||
|
||||
/* Struct to record attribute information. */
|
||||
typedef struct {
|
||||
unsigned int num_nonbools;
|
||||
unsigned char num_nonbools;
|
||||
unsigned int bool;
|
||||
unsigned int nonbool[1];
|
||||
} CGEN_ATTR;
|
||||
@ -94,7 +94,7 @@ 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]; }
|
||||
|
||||
@ -108,6 +108,22 @@ 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).
|
||||
|
||||
@ -207,11 +223,12 @@ 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
|
||||
@ -223,71 +240,81 @@ struct cgen_base {
|
||||
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;
|
||||
|
||||
#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;
|
||||
#endif
|
||||
|
||||
/* Mnemonic (or name if expression). */
|
||||
char *mnemonic;
|
||||
|
||||
/* 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];
|
||||
|
||||
#define CGEN_SYNTAX_CHAR_P(c) ((c) < 128)
|
||||
#define CGEN_SYNTAX_CHAR(c) (c)
|
||||
#define CGEN_SYNTAX_FIELD(c) ((c) - 128)
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
/* 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));
|
||||
|
||||
/* Operand values (keywords, integers, symbols, etc.) */
|
||||
|
||||
@ -325,7 +352,13 @@ typedef struct cgen_keyword_entry {
|
||||
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;
|
||||
|
||||
@ -340,61 +373,63 @@ typedef struct cgen_keyword_entry {
|
||||
|
||||
This struct supports runtime entry of new values, and hashed lookups. */
|
||||
|
||||
typedef struct cgen_keyword {
|
||||
typedef struct {
|
||||
/* 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;
|
||||
/* 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_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,
|
||||
@ -406,27 +441,33 @@ const char * cgen_validate_unsigned_integer PARAMS ((unsigned long,
|
||||
#define CGEN_MAX_OPERAND_ATTRS 1
|
||||
#endif
|
||||
|
||||
typedef struct cgen_operand {
|
||||
/* For debugging. */
|
||||
typedef struct {
|
||||
/* Name as it appears in the syntax string. */
|
||||
char *name;
|
||||
|
||||
/* 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. */
|
||||
CGEN_ATTR_TYPE (CGEN_MAX_OPERAND_ATTRS) attrs;
|
||||
#define CGEN_OPERAND_ATTRS(operand) (&(operand)->attrs)
|
||||
} CGEN_OPERAND;
|
||||
|
||||
/* Return value of attribute ATTR in OPERAND. */
|
||||
@ -443,41 +484,132 @@ enum cgen_operand_type;
|
||||
#define CGEN_OPERAND_TYPE(operand) ((enum cgen_operand_type) CGEN_OPERAND_INDEX (operand))
|
||||
#define CGEN_OPERAND_ENTRY(n) (& CGEN_SYM (operand_table) [n])
|
||||
|
||||
/* 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)
|
||||
|
||||
/* ??? 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_P(ch) ((ch) == 1)
|
||||
|
||||
/* Instruction formats.
|
||||
|
||||
Instructions are grouped by format. Associated with an instruction is its
|
||||
format. Each opcode table entry contains a pointer into the format table.
|
||||
This cuts down on the size of the opcode table as there are relatively few
|
||||
formats compared with the number of instructions. */
|
||||
|
||||
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. */
|
||||
unsigned char length;
|
||||
|
||||
/* Mask to apply to the first BASE_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 {
|
||||
/* ??? 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.
|
||||
For now this only points to CGEN_SYNTAX elements, but it can point
|
||||
to other things (e.g. something different for macros?). */
|
||||
const CGEN_SYNTAX *syntax;
|
||||
#define CGEN_INSN_SYNTAX(insn) ((CGEN_SYNTAX *) (insn)->syntax)
|
||||
|
||||
/* Format entry.
|
||||
For now this only points to CGEN_FORMAT elements, but it can point
|
||||
to other things (e.g. something different for macros?). */
|
||||
const CGEN_FORMAT *format;
|
||||
#define CGEN_INSN_MASK_BITSIZE(insn) (((CGEN_FORMAT *) (insn)->format)->mask_length)
|
||||
#define CGEN_INSN_BITSIZE(insn) (((CGEN_FORMAT *) (insn)->format)->length)
|
||||
|
||||
/* Instruction opcode value. */
|
||||
unsigned int value;
|
||||
#define CGEN_INSN_VALUE(insn) ((insn)->value)
|
||||
#define CGEN_INSN_MASK(insn) (((CGEN_FORMAT *) (insn)->format)->mask)
|
||||
|
||||
/* 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. */
|
||||
CGEN_ATTR_TYPE (CGEN_MAX_INSN_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;
|
||||
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 *));
|
||||
/* Number of entries in assembler hash table. */
|
||||
@ -498,7 +630,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,7 +673,7 @@ CGEN_INSN_LIST * cgen_dis_lookup_insn PARAMS ((const char *, unsigned long));
|
||||
|
||||
/* Top level structures and functions. */
|
||||
|
||||
typedef struct cgen_opcode_data {
|
||||
typedef struct {
|
||||
CGEN_HW_ENTRY *hw_list;
|
||||
/*CGEN_OPERAND_TABLE *operand_table; - FIXME:wip */
|
||||
CGEN_INSN_TABLE *insn_table;
|
||||
@ -580,12 +712,12 @@ void CGEN_SYM (init_extract) PARAMS ((void));
|
||||
const struct cgen_insn *
|
||||
CGEN_SYM (assemble_insn) PARAMS ((const char *, struct 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 *));
|
||||
|
||||
CGEN_INLINE void
|
||||
@ -608,63 +740,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_asm_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 *. */
|
||||
|
||||
enum cgen_asm_result {
|
||||
CGEN_ASM_NUMBER, CGEN_ASM_REGISTER, CGEN_ASM_QUEUED, CGEN_ASM_ERROR
|
||||
};
|
||||
|
||||
/* Don't require bfd.h unnecessarily. */
|
||||
#ifdef BFD_VERSION
|
||||
extern const char * (*cgen_asm_parse_operand_fn)
|
||||
PARAMS ((const char **, int, int, enum cgen_asm_result *, bfd_vma *));
|
||||
#endif
|
||||
|
||||
/* These are GAS specific. They're not here as part of the interface,
|
||||
but rather that we need to put them somewhere. */
|
||||
|
||||
/* Call this for each insn to initialize the assembler callback interface. */
|
||||
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_asm_parse_operand PARAMS ((const char **, int, int,
|
||||
enum cgen_asm_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 */
|
||||
|
Loading…
Reference in New Issue
Block a user