📄 cgen.h
字号:
/* The hardware element referenced. */ enum cgen_hw_type hw_type; /* The mode in which the operand is being used. */ enum cgen_mode mode; /* 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 "nil", the index (e.g. into array of registers). */ int index; /* Attributes. ??? This perhaps should be a real attribute struct but there's no current need, so we save a bit of space and just have a set of flags. The interface is such that this can easily be made attributes should it prove useful. */ unsigned int attrs;#define CGEN_OPINST_ATTRS(opinst) ((opinst)->attrs)/* Return value of attribute ATTR in OPINST. */#define CGEN_OPINST_ATTR(opinst, attr) \((CGEN_OPINST_ATTRS (opinst) & (attr)) != 0)/* Operand is conditionally referenced (read/written). */#define CGEN_OPINST_COND_REF 1} CGEN_OPINST;/* 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. *//* 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#endiftypedef unsigned short CGEN_SYNTAX_CHAR_TYPE;typedef struct{ 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) ((unsigned char)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 fields. ??? We currently don't allow adding fields at run-time. Easy to fix when needed. */typedef struct cgen_ifld { /* Enum of ifield. */ int num;#define CGEN_IFLD_NUM(f) ((f)->num) /* Name of the field, distinguishes it from all other fields. */ const char *name;#define CGEN_IFLD_NAME(f) ((f)->name) /* Default offset, in bits, from the start of the insn to the word containing the field. */ int word_offset;#define CGEN_IFLD_WORD_OFFSET(f) ((f)->word_offset) /* Default length of the word containing the field. */ int word_size;#define CGEN_IFLD_WORD_SIZE(f) ((f)->word_size) /* Default starting bit number. Whether lsb=0 or msb=0 is determined by CGEN_INSN_LSB0_P. */ int start;#define CGEN_IFLD_START(f) ((f)->start) /* Length of the field, in bits. */ int length;#define CGEN_IFLD_LENGTH(f) ((f)->length)#ifndef CGEN_IFLD_NBOOL_ATTRS#define CGEN_IFLD_NBOOL_ATTRS 1#endif CGEN_ATTR_TYPE (CGEN_IFLD_NBOOL_ATTRS) attrs;#define CGEN_IFLD_ATTRS(f) (&(f)->attrs)} CGEN_IFLD;/* Return value of attribute ATTR in IFLD. */#define CGEN_IFLD_ATTR_VALUE(ifld, attr) \CGEN_ATTR_VALUE ((ifld), CGEN_IFLD_ATTRS (ifld), (attr))/* Instruction data. *//* Instruction formats. Instructions are grouped by format. Associated with an instruction is its format. Each insn's 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. *//* Accompanying each iformat description is a list of its fields. */typedef struct { const CGEN_IFLD *ifld;#define CGEN_IFMT_IFLD_IFLD(ii) ((ii)->ifld)} CGEN_IFMT_IFLD;/* 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#endiftypedef struct{ /* Length that MASK and VALUE have been calculated to [VALUE is recorded elsewhere]. 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) /* Total length of instruction, in bits. */ unsigned char length;#define CGEN_IFMT_LENGTH(ifmt) ((ifmt)->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. */ CGEN_INSN_INT mask;#define CGEN_IFMT_MASK(ifmt) ((ifmt)->mask) /* Instruction fields. +1 for trailing NULL. */ CGEN_IFMT_IFLD iflds[CGEN_MAX_IFMT_OPERANDS + 1];#define CGEN_IFMT_IFLDS(ifmt) ((ifmt)->iflds)} CGEN_IFMT;/* Instruction values. */typedef struct{ /* The opcode portion of the base insn. */ CGEN_INSN_INT base_value;#ifdef CGEN_MAX_EXTRA_OPCODE_OPERANDS /* Extra opcode values beyond base_value. */ unsigned long ifield_values[CGEN_MAX_EXTRA_OPCODE_OPERANDS];#endif} CGEN_IVALUE;/* Instruction opcode table. This contains the syntax and format data of an instruction. *//* ??? Some ports already have an opcode table yet still need to use the rest of what cgen_insn has. Plus keeping the opcode data with the operand instance data can create a pretty big file. So we keep them separately. Not sure this is a good idea in the long run. */typedef struct{ /* Indices into parse/insert/extract/print handler tables. */ struct cgen_opcode_handler handlers;#define CGEN_OPCODE_HANDLERS(opc) (& (opc)->handlers) /* Syntax string. */ CGEN_SYNTAX syntax;#define CGEN_OPCODE_SYNTAX(opc) (& (opc)->syntax) /* Format entry. */ const CGEN_IFMT *format;#define CGEN_OPCODE_FORMAT(opc) ((opc)->format)#define CGEN_OPCODE_MASK_BITSIZE(opc) CGEN_IFMT_MASK_LENGTH (CGEN_OPCODE_FORMAT (opc))#define CGEN_OPCODE_BITSIZE(opc) CGEN_IFMT_LENGTH (CGEN_OPCODE_FORMAT (opc))#define CGEN_OPCODE_IFLDS(opc) CGEN_IFMT_IFLDS (CGEN_OPCODE_FORMAT (opc)) /* Instruction opcode value. */ CGEN_IVALUE value;#define CGEN_OPCODE_VALUE(opc) (& (opc)->value)#define CGEN_OPCODE_BASE_VALUE(opc) (CGEN_OPCODE_VALUE (opc)->base_value)#define CGEN_OPCODE_BASE_MASK(opc) CGEN_IFMT_MASK (CGEN_OPCODE_FORMAT (opc))} CGEN_OPCODE;/* Instruction attributes. This is made a published type as applications can cache a pointer to the attributes for speed. */#ifndef CGEN_INSN_NBOOL_ATTRS#define CGEN_INSN_NBOOL_ATTRS 1#endiftypedef CGEN_ATTR_TYPE (CGEN_INSN_NBOOL_ATTRS) CGEN_INSN_ATTR_TYPE;/* Enum of architecture independent attributes. */#ifndef CGEN_ARCH/* ??? Numbers here are recorded in two places. */typedef enum cgen_insn_attr { CGEN_INSN_ALIAS = 0} CGEN_INSN_ATTR;#endif/* This struct defines each entry in the instruction table. */typedef struct{ /* Each real instruction is enumerated. */ /* ??? This may go away in time. */ int num;#define CGEN_INSN_NUM(insn) ((insn)->base->num) /* Name of entry (that distinguishes it from all other entries). */ /* ??? If mnemonics have operands, try to print full mnemonic. */ const char *name;#define CGEN_INSN_NAME(insn) ((insn)->base->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., and the condition is treated as an operand, this is only "add". */ const char *mnemonic;#define CGEN_INSN_MNEMONIC(insn) ((insn)->base->mnemonic) /* Total length of instruction, in bits. */ int bitsize;#define CGEN_INSN_BITSIZE(insn) ((insn)->base->bitsize)#if 0 /* ??? Disabled for now as there is a problem with embedded newlines and the table is already pretty big. Should perhaps be moved to a file of its own. */ /* Semantics, as RTL. */ /* ??? Plain text or bytecodes? */ /* ??? Note that the operand instance table could be computed at run-time if we parse this and cache the results. Something to eventually do. */ const char *rtx;#define CGEN_INSN_RTX(insn) ((insn)->base->rtx)#endif /* 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. The goal is to eventually record attributes in their raw form, evaluate them at run-time, and cache the values, so this worry will go away anyway. */ CGEN_INSN_ATTR_TYPE attrs;#define CGEN_INSN_ATTRS(insn) (&(insn)->base->attrs)/* Return value of attribute ATTR in INSN. */#define CGEN_INSN_ATTR_VALUE(insn, attr) \CGEN_ATTR_VALUE ((insn), CGEN_INSN_ATTRS (insn), (attr))} CGEN_IBASE;/* Return non-zero if INSN is the "invalid" insn marker. */#define CGEN_INSN_INVALID_P(insn) (CGEN_INSN_MNEMONIC (insn) == 0)/* Main struct contain instruction information. BASE is always present, the rest is present only if asked for. */struct cgen_insn{ /* ??? May be of use to put a type indicator here. Then this struct could different info for different classes of insns. */ /* ??? A speedup can be had by moving `base' into this struct. Maybe later. */ 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. This is used for adding new entries and for creating the hash lists. */typedef struct cgen_insn_list{ struct cgen_insn_list *next; const CGEN_INSN *insn;} CGEN_INSN_LIST;/* Table of instructions. */typedef struct{ const CGEN_INSN *init_entries; unsigned int entry_size; /* since the attribute member is variable sized */ unsigned int num_init_entries; CGEN_INSN_LIST *new_entries;} CGEN_INSN_TABLE;/* Return number of instructions. This includes any added at run-time. */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. *//* Fetch INSN's operand instance table. *//* ??? Doesn't handle insns added at runtime. */#define CGEN_INSN_OPERANDS(insn) ((insn)->opinst)/* Return INSN's opcode table entry. */#define CGEN_INSN_OPCODE(insn) ((insn)->opcode)/* Return INSN's handler data. */#define CGEN_INSN_HANDLERS(insn) CGEN_OPCODE_HANDLERS (CGEN_INSN_OPCODE (insn))/* Return INSN's syntax. */#define CGEN_INSN_SYNTAX(insn) CGEN_OPCODE_SYNTAX (CGEN_INSN_OPCODE (insn))/* Return size of base mask in bits. */#define CGEN_INSN_MASK_BITSIZE(insn) \ CGEN_OPCODE_MASK_BITSIZE (CGEN_INSN_OPCODE (insn))/* Return mask of base part of INSN. */#define CGEN_INSN_BASE_MASK(insn) \ CGEN_OPCODE_BASE_MASK (CGEN_INSN_OPCODE (insn))/* 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -