📄 cgen.h
字号:
/* Macro instructions. Macro insns aren't real insns, they map to one or more real insns. E.g. An architecture's "nop" insn may actually be an "mv r0,r0" or some such. Macro insns can expand to nothing (e.g. a nop that is optimized away). This is useful in multi-insn macros that build a constant in a register. Of course this isn't the default behaviour and must be explicitly enabled. Assembly of macro-insns is relatively straightforward. Disassembly isn't. However, disassembly of at least some kinds of macro insns is important in order that the disassembled code preserve the readability of the original insn. What is attempted here is to disassemble all "simple" macro-insns, where "simple" is currently defined to mean "expands to one real insn". Simple macro-insns are handled specially. They are emitted as ALIAS's of real insns. This simplifies their handling since there's usually more of them than any other kind of macro-insn, and proper disassembly of them falls out for free. *//* For each macro-insn there may be multiple expansion possibilities, depending on the arguments. This structure is accessed via the `data' member of CGEN_INSN. */typedef struct cgen_minsn_expansion { /* Function to do the 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) (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. The format of STR is defined by FN. It is typically the assembly code of the real insn, but it could also be the original Scheme expression or a tokenized form of it (with FN being an appropriate interpreter). */ const char * str;#define CGEN_MIEXPN_STR(ex) ((ex)->str)} CGEN_MINSN_EXPANSION;/* Normal expander. When supported, this function will convert the input string to another string and the parser will be invoked recursively. The output string may contain further macro invocations. */extern const char * cgen_expand_macro_insn (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 (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)/* The disassembler insn table is hashed based on some function of machine instruction (the actually hashing done is up to the target). */extern CGEN_INSN_LIST * cgen_dis_lookup_insn (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)/* The CPU description. A copy of this is created when the cpu table is "opened". All global state information is recorded here. Access macros are provided for "public" members. */typedef struct cgen_cpu_desc{ /* Bitmap of selected machine(s) (a la BFD machine number). */ int machs; /* Bitmap of selected isa(s). ??? Simultaneous multiple isas might not make sense, but it's not (yet) precluded. */ int isas; /* Current endian. */ enum cgen_endian endian;#define CGEN_CPU_ENDIAN(cd) ((cd)->endian) /* Current insn endian. */ 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. */ CGEN_HW_TABLE hw_table; /* Instruction fields. */ const CGEN_IFLD *ifld_table; /* Operands. */ CGEN_OPERAND_TABLE operand_table; /* Main instruction table. */ CGEN_INSN_TABLE insn_table;#define CGEN_CPU_INSN_TABLE(cd) (& (cd)->insn_table) /* Macro instructions are defined separately and are combined with real insns during hash table computation. */ CGEN_INSN_TABLE macro_insn_table; /* Copy of CGEN_INT_INSN_P. */ int int_insn_p; /* 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) (CGEN_CPU_DESC, int opindex_, const char **, CGEN_FIELDS *fields_);#ifdef __BFD_H_SEEN__ const char * (*insert_operand) (CGEN_CPU_DESC, int opindex_, CGEN_FIELDS *fields_, CGEN_INSN_BYTES_PTR, bfd_vma pc_); int (*extract_operand) (CGEN_CPU_DESC, int opindex_, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *fields_, bfd_vma pc_); void (*print_operand) (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) (); void (*print_operand) ();#endif#define CGEN_CPU_PARSE_OPERAND(cd) ((cd)->parse_operand)#define CGEN_CPU_INSERT_OPERAND(cd) ((cd)->insert_operand)#define CGEN_CPU_EXTRACT_OPERAND(cd) ((cd)->extract_operand)#define CGEN_CPU_PRINT_OPERAND(cd) ((cd)->print_operand) /* Size of CGEN_FIELDS struct. */ unsigned int sizeof_fields;#define CGEN_CPU_SIZEOF_FIELDS(cd) ((cd)->sizeof_fields) /* Set the bitsize field. */ 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) (CGEN_CPU_DESC, int opindex_, const CGEN_FIELDS *fields_); void (*set_int_operand) (CGEN_CPU_DESC, int opindex_, CGEN_FIELDS *fields_, int value_);#ifdef __BFD_H_SEEN__ bfd_vma (*get_vma_operand) (CGEN_CPU_DESC, int opindex_, const CGEN_FIELDS *fields_); void (*set_vma_operand) (CGEN_CPU_DESC, int opindex_, CGEN_FIELDS *fields_, bfd_vma value_);#else long (*get_vma_operand) (); void (*set_vma_operand) ();#endif#define CGEN_CPU_GET_INT_OPERAND(cd) ((cd)->get_int_operand)#define CGEN_CPU_SET_INT_OPERAND(cd) ((cd)->set_int_operand)#define CGEN_CPU_GET_VMA_OPERAND(cd) ((cd)->get_vma_operand)#define CGEN_CPU_SET_VMA_OPERAND(cd) ((cd)->set_vma_operand) /* Instruction parse/insert/extract/print handlers. */ /* FIXME: make these types uppercase. */ cgen_parse_fn * const *parse_handlers; cgen_insert_fn * const *insert_handlers; cgen_extract_fn * const *extract_handlers; cgen_print_fn * const *print_handlers;#define CGEN_PARSE_FN(cd, insn) (cd->parse_handlers[(insn)->opcode->handlers.parse])#define CGEN_INSERT_FN(cd, insn) (cd->insert_handlers[(insn)->opcode->handlers.insert])#define CGEN_EXTRACT_FN(cd, insn) (cd->extract_handlers[(insn)->opcode->handlers.extract])#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) (const CGEN_INSN *); /* Assembler hash function. */ 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) (const CGEN_INSN *); /* Disassembler hash function. */ unsigned int (* dis_hash) (const char *, CGEN_INSN_INT); /* Number of entries in disassembler hash table. */ unsigned int dis_hash_size; /* Assembler instruction hash table. */ CGEN_INSN_LIST **asm_hash_table; CGEN_INSN_LIST *asm_hash_table_entries; /* 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 */#ifndef CGEN_WORD_ENDIAN#define CGEN_WORD_ENDIAN(cd) CGEN_CPU_ENDIAN (cd)#endif#ifndef CGEN_INSN_WORD_ENDIAN#define CGEN_INSN_WORD_ENDIAN(cd) CGEN_CPU_INSN_ENDIAN (cd)#endif/* Prototypes of major functions. *//* FIXME: Move more CGEN_SYM-defined functions into CGEN_CPU_DESC. Not the init fns though, as that would drag in things that mightn't be used and might not even exist. *//* 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) (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) (CGEN_CPU_DESC);/* Initialize the opcode table for use. Called by init_asm/init_dis. */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) (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) (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) (CGEN_CPU_DESC cd_);/* Assemble an instruction. */extern const CGEN_INSN * CGEN_SYM (assemble_insn) (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) (const char *);/* Operand index computation. */extern const CGEN_INSN * cgen_lookup_insn (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 (CGEN_CPU_DESC, const CGEN_INSN * insn_, const CGEN_FIELDS *fields_, int *indices_);extern const CGEN_INSN * cgen_lookup_get_insn_operands (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 (CGEN_CPU_DESC, unsigned char *, int);extern void cgen_put_insn_value (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 (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);#endif /* CGEN_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -