* cgen.h (CGEN_ATTR_TYPE): Delete `const', moved to uses.
authorDoug Evans <dje@google.com>
Mon, 27 Apr 1998 17:31:38 +0000 (17:31 +0000)
committerDoug Evans <dje@google.com>
Mon, 27 Apr 1998 17:31:38 +0000 (17:31 +0000)
(cgen_asm_finish_insn): Update prototype.
(cgen_insn): New members num, data.
(CGEN_INSN_TABLE): Members asm_hash, asm_hash_table_size,
dis_hash, dis_hash_table_size moved to ...
(CGEN_OPCODE_TABLE).  Here.  Renamed from CGEN_OPCODE_DATA.
All uses updated.  New members asm_hash_p, dis_hash_p.
(CGEN_MINSN_EXPANSION): New struct.
(cgen_expand_macro_insn): Declare.
(cgen_macro_insn_count): Declare.
(get_insn_operands): Update prototype.
(lookup_get_insn_operands): Declare.

include/opcode/ChangeLog
include/opcode/cgen.h

index c8a778933f48692137b5cda6b1565c8136a0d55c..b18bc0b57392615ec8965c2d9ab7278b81c71212 100644 (file)
@@ -1,3 +1,18 @@
+Mon Apr 27 10:13:11 1998  Doug Evans  <devans@seba.cygnus.com>
+
+       * cgen.h (CGEN_ATTR_TYPE): Delete `const', moved to uses.
+       (cgen_asm_finish_insn): Update prototype.
+       (cgen_insn): New members num, data.
+       (CGEN_INSN_TABLE): Members asm_hash, asm_hash_table_size,
+       dis_hash, dis_hash_table_size moved to ...
+       (CGEN_OPCODE_TABLE).  Here.  Renamed from CGEN_OPCODE_DATA.
+       All uses updated.  New members asm_hash_p, dis_hash_p.
+       (CGEN_MINSN_EXPANSION): New struct.
+       (cgen_expand_macro_insn): Declare.
+       (cgen_macro_insn_count): Declare.
+       (get_insn_operands): Update prototype.
+       (lookup_get_insn_operands): Declare.
+
 Tue Apr 21 17:11:32 1998  Alan Modra  <alan@spri.levels.unisa.edu.au>
 
        * i386.h (i386_optab): Change iclrKludge and imulKludge to
index 5043c4c2412d3d111f016009e3b51025f00045c3..10c9724cd635b6a01c6c64e592e7a9e09ffe32a3 100644 (file)
@@ -87,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 char num_nonbools; \
-              unsigned int bool; \
-              unsigned int nonbool[(n) ? (n) : 1]; }
+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,14 +112,14 @@ const struct { unsigned char num_nonbools; \
 typedef struct
 {
   const char * name;
-  int          value;
+  int value;
 } CGEN_ATTR_ENTRY;
 
 /* For each domain (fld,operand,insn), list of attributes.  */
 
 typedef struct
 {
-  const char *            name;
+  const char * name;
   /* NULL for boolean attributes.  */
   const CGEN_ATTR_ENTRY * vals;
 } CGEN_ATTR_TABLE;
@@ -231,7 +235,9 @@ 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).  */
+     0 means use the default (what the default is is up to the code).
+     Using indices also keeps assembler code out of the disassembler and
+     vice versa.  */
   unsigned char parse, insert, extract, print;
 };
 \f
@@ -284,7 +290,7 @@ extern const char * (*cgen_parse_operand_fn)
 #endif
 
 /* Called before trying to match a table entry with the insn.  */
-void cgen_init_parse_operand PARAMS ((void));
+extern void cgen_init_parse_operand PARAMS ((void));
 
 /* Called from <cpu>-asm.c to initialize operand parsing.  */
 
@@ -292,33 +298,34 @@ void cgen_init_parse_operand PARAMS ((void));
    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));
+extern 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 *));
+extern 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));
+extern void cgen_save_fixups PARAMS ((void));
+extern void cgen_restore_fixups PARAMS ((void));
+extern 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));
+extern 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));
+extern char * cgen_asm_finish_insn PARAMS ((const struct cgen_insn *,
+                                           cgen_insn_t *, unsigned int, int));
 \f
 /* Operand values (keywords, integers, symbols, etc.)  */
 
@@ -335,14 +342,14 @@ 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;
+  int type;
   const struct cgen_hw_entry * next;
-  char *                       name;
-  enum cgen_asm_type           asm_type;
-  PTR                          asm_data;
+  char * name;
+  enum cgen_asm_type asm_type;
+  PTR asm_data;
 } CGEN_HW_ENTRY;
 
-const CGEN_HW_ENTRY * cgen_hw_lookup PARAMS ((const char *));
+extern const CGEN_HW_ENTRY * cgen_hw_lookup PARAMS ((const char *));
 
 /* This struct is used to describe things like register names, etc.  */
 
@@ -367,7 +374,7 @@ typedef struct cgen_keyword_entry
 #ifndef CGEN_KEYWORD_NBOOL_ATTRS
 #define CGEN_KEYWORD_NBOOL_ATTRS 1
 #endif
-  CGEN_ATTR_TYPE (CGEN_KEYWORD_NBOOL_ATTRS) attrs;
+  const CGEN_ATTR_TYPE (CGEN_KEYWORD_NBOOL_ATTRS) attrs;
 
   /* Next name hash table entry.  */
   struct cgen_keyword_entry *next_name;
@@ -436,19 +443,20 @@ const CGEN_KEYWORD_ENTRY *cgen_keyword_search_next
 /* 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 **,
-                                        CGEN_KEYWORD *,
-                                        long *));
-const char * cgen_parse_signed_integer PARAMS ((const char **, int, long *));
-const char * cgen_parse_unsigned_integer PARAMS ((const char **, int,
-                                                 unsigned 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));
+extern const char * cgen_parse_keyword PARAMS ((const char **,
+                                               CGEN_KEYWORD *,
+                                               long *));
+extern const char * cgen_parse_signed_integer PARAMS ((const char **, int,
+                                                      long *));
+extern const char * cgen_parse_unsigned_integer PARAMS ((const char **, int,
+                                                        unsigned long *));
+extern const char * cgen_parse_address PARAMS ((const char **, int, int,
+                                               enum cgen_parse_operand_result *,
+                                               long *));
+extern const char * cgen_validate_signed_integer PARAMS ((long, long, long));
+extern const char * cgen_validate_unsigned_integer PARAMS ((unsigned long,
+                                                           unsigned long,
+                                                           unsigned long));
 \f
 /* Operand modes.  */
 
@@ -510,7 +518,7 @@ typedef struct cgen_operand
 #ifndef CGEN_OPERAND_NBOOL_ATTRS
 #define CGEN_OPERAND_NBOOL_ATTRS 1
 #endif
-  CGEN_ATTR_TYPE (CGEN_OPERAND_NBOOL_ATTRS) attrs;
+  const CGEN_ATTR_TYPE (CGEN_OPERAND_NBOOL_ATTRS) attrs;
 #define CGEN_OPERAND_ATTRS(operand) (&(operand)->attrs)
 } CGEN_OPERAND;
 
@@ -639,14 +647,17 @@ typedef struct
 
 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.  */
+  /* This field is an array of functions that operand on this entry.  */
   struct cgen_base base;
-  
-/* Given a pointer to a cgen_insn struct, return a pointer to `base'.  */
 #define CGEN_INSN_BASE(insn) (&(insn)->base)
 
+  /* Each real instruction is enumerated.  This is used, for example, to do
+     insn profiling in the simulator.
+     Macro-insns are not enumerated.  The simulator doesn't use them and there
+     is currently no other need for it.  */
+  int num;
+#define CGEN_INSN_NUM(insn) ((insn)->num)
+
   /* 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.  */
@@ -674,10 +685,16 @@ struct cgen_insn
 #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)
+  /* Opaque pointer to "subclass" specific data.
+     In the case of real insns this points to a NULL entry terminated
+     table of operands used, or NULL if none.
+     In the case of macro insns this points to data to control the expansion.
+     ??? I'd rather not get carried away and lay things out with pedantic
+     purity right now.  Sure, other fields might better be tucked away in
+     `data'.  Not now.  */
+  PTR data;
+#define CGEN_INSN_DATA(insn) ((insn)->data)
+#define CGEN_INSN_OPERANDS(insn) ((CGEN_OPERAND_INSTANCE *) (insn)->data)
 
   /* Attributes.
      This must appear last.  It is a variable sized array in that one
@@ -687,7 +704,7 @@ struct cgen_insn
 #ifndef CGEN_INSN_NBOOL_ATTRS
 #define CGEN_INSN_NBOOL_ATTRS 1
 #endif
-  CGEN_ATTR_TYPE (CGEN_INSN_NBOOL_ATTRS) attrs;
+  const 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) \
@@ -718,82 +735,147 @@ typedef struct
   
   /* Values added at runtime.  */
   CGEN_INSN_LIST * new_entries;
-  
-  /* Assembler hash function.  */
-  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));
-  
-  /* Number of entries in disassembler hash table.  */
-  unsigned int dis_hash_table_size;
 } CGEN_INSN_TABLE;
 
-/* ??? This is currently used by the simulator.
-   We want this to be fast and the simulator currently doesn't handle
-   runtime added instructions so this is ok.  An alternative would be to
-   store the index in the table.  */
+/* ??? This is currently used by the simulator.  */
 extern const CGEN_INSN CGEN_SYM (insn_table_entries)[];
-#define CGEN_INSN_INDEX(insn) ((int) ((insn) - CGEN_SYM (insn_table_entries)))
-#define CGEN_INSN_ENTRY(n) (& CGEN_SYM (insn_table_entries) [n])
 
 /* Return number of instructions.  This includes any added at runtime.  */
 
-int cgen_insn_count PARAMS ((void));
-
+extern int cgen_insn_count PARAMS ((void));
+\f
+/* 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) PARAMS ((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
+     PARAMS ((const struct cgen_minsn_expansion *,
+             const char *, const char **, int *, CGEN_OPERAND **));
+\f
 /* 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).
-   The index of each entry is the index of the corresponding table entry.
-   The value of each entry is the index of the next entry, with a 0
-   terminating (thus the first entry is reserved).  */
+   examples like the first letter or a function of the entire mnemonic).  */
+
+#ifndef CGEN_ASM_HASH_P
+#define CGEN_ASM_HASH_P(insn) 1
+#endif
 
+/* INSN is the CGEN_INSN entry when building the hash table and NULL
+   when looking up the insn during assembly.  */
 #ifndef CGEN_ASM_HASH
-#ifdef CGEN_MNEMONIC_OPERANDS
 #define CGEN_ASM_HASH_SIZE 127
-#define CGEN_ASM_HASH(string) (*(unsigned char *) (string) % CGEN_ASM_HASH_SIZE)
+#ifdef CGEN_MNEMONIC_OPERANDS
+#define CGEN_ASM_HASH(mnem) (*(unsigned char *) (mnem) % CGEN_ASM_HASH_SIZE)
 #else
-#define CGEN_ASM_HASH_SIZE 128
-#define CGEN_ASM_HASH(string) (*(unsigned char *) (string) % CGEN_ASM_HASH_SIZE) /*FIXME*/
+#define CGEN_ASM_HASH(mnem) (*(unsigned char *) (mnem) % CGEN_ASM_HASH_SIZE) /*FIXME*/
 #endif
 #endif
 
-unsigned int CGEN_SYM (asm_hash_insn) PARAMS ((const char *));
-CGEN_INSN_LIST * cgen_asm_lookup_insn PARAMS ((const char *));
-#define CGEN_ASM_LOOKUP_INSN(insn) cgen_asm_lookup_insn (insn)
+extern CGEN_INSN_LIST * cgen_asm_lookup_insn PARAMS ((const char *));
+#define CGEN_ASM_LOOKUP_INSN(string) cgen_asm_lookup_insn (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).  */
 
+#ifndef CGEN_DIS_HASH_P
+#define CGEN_DIS_HASH_P(insn) 1
+#endif
+
 /* It doesn't make much sense to provide a default here,
    but while this is under development we do.
+   INSN is the CGEN_INSN entry when building the hash table and NULL
+   when looking up the insn during assembly.
    BUFFER is a pointer to the bytes of the insn.
-   INSN is the first CGEN_BASE_INSN_SIZE bytes as an int in host order.  */
+   VALUE is the first CGEN_BASE_INSN_SIZE bytes as an int in host order.  */
 #ifndef CGEN_DIS_HASH
 #define CGEN_DIS_HASH_SIZE 256
-#define CGEN_DIS_HASH(buffer, insn) (*(unsigned char *) (buffer))
+#define CGEN_DIS_HASH(buffer, value) (*(unsigned char *) (buffer))
 #endif
 
-unsigned int CGEN_SYM (dis_hash_insn) PARAMS ((const char *, unsigned long));
-CGEN_INSN_LIST * cgen_dis_lookup_insn PARAMS ((const char *, unsigned long));
-#define CGEN_DIS_LOOKUP_INSN(buf, insn) cgen_dis_lookup_insn (buf, insn)
+extern CGEN_INSN_LIST * cgen_dis_lookup_insn PARAMS ((const char *,
+                                                     unsigned long));
+#define CGEN_DIS_LOOKUP_INSN(buf, value) cgen_dis_lookup_insn ((buf), (value))
 #define CGEN_DIS_NEXT_INSN(insn) ((insn)->next)
 \f
 /* Top level structures and functions.  */
 
 typedef struct
 {
-  const CGEN_HW_ENTRY *  hw_list;
+  const CGEN_HW_ENTRY * hw_list;
+
   /*CGEN_OPERAND_TABLE * operand_table; - FIXME:wip */
-  CGEN_INSN_TABLE *      insn_table;
-} CGEN_OPCODE_DATA;
+
+  CGEN_INSN_TABLE * insn_table;
+
+  /* Macro instructions are defined separately and are combined with real
+     insns during hash table computation.  */
+  CGEN_INSN_TABLE * macro_insn_table;
+
+  /* Return non-zero if insn should be added to hash table.  */
+  int (* asm_hash_p) PARAMS ((const CGEN_INSN *));
+
+  /* Assembler hash function.  */
+  unsigned int (* asm_hash) PARAMS ((const char *));
+
+  /* Number of entries in assembler hash table.  */
+  unsigned int asm_hash_table_size;
+
+  /* Return non-zero if insn should be added to hash table.  */
+  int (* dis_hash_p) PARAMS ((const CGEN_INSN *));
+
+  /* Disassembler hash function.  */
+  unsigned int (* dis_hash) PARAMS ((const char *, unsigned long));
+
+  /* Number of entries in disassembler hash table.  */
+  unsigned int dis_hash_table_size;
+} CGEN_OPCODE_TABLE;
 
 /* Each CPU has one of these.  */
-extern CGEN_OPCODE_DATA CGEN_SYM (opcode_data);
+extern const CGEN_OPCODE_TABLE CGEN_SYM (opcode_table);
 
 /* Global state access macros.
    Some of these are tucked away and accessed with cover fns.
@@ -808,42 +890,42 @@ extern enum cgen_endian cgen_current_endian;
 /* Prototypes of major functions.  */
 
 /* Set the current cpu (+ mach number, endian, etc.).  */
-void cgen_set_cpu PARAMS ((CGEN_OPCODE_DATA *, int, enum cgen_endian));
+extern void cgen_set_cpu PARAMS ((const CGEN_OPCODE_TABLE *, int,
+                                 enum cgen_endian));
 
 /* Initialize the assembler, disassembler.  */
-void cgen_asm_init PARAMS ((void));
-void cgen_dis_init PARAMS ((void));
+extern void cgen_asm_init PARAMS ((void));
+extern void cgen_dis_init PARAMS ((void));
 
 /* `init_tables' must be called before `xxx_supported'.  */
-void CGEN_SYM (init_tables) PARAMS ((int));
-void CGEN_SYM (init_asm) PARAMS ((int, enum cgen_endian));
-void CGEN_SYM (init_dis) PARAMS ((int, enum cgen_endian));
-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));
+extern void CGEN_SYM (init_tables) PARAMS ((int));
+extern void CGEN_SYM (init_asm) PARAMS ((int, enum cgen_endian));
+extern void CGEN_SYM (init_dis) PARAMS ((int, enum cgen_endian));
 
 /* 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 *
+extern const struct cgen_insn *
 CGEN_SYM (assemble_insn) PARAMS ((const char *, CGEN_FIELDS *,
                                  cgen_insn_t *, char **));
 #if 0 /* old */
-int CGEN_SYM (insn_supported) PARAMS ((const struct cgen_insn *));
-int CGEN_SYM (opval_supported) PARAMS ((const struct cgen_opval *));
+extern int CGEN_SYM (insn_supported) PARAMS ((const struct cgen_insn *));
+extern int CGEN_SYM (opval_supported) PARAMS ((const struct cgen_opval *));
 #endif
 
 extern const CGEN_KEYWORD  CGEN_SYM (operand_mach);
-int CGEN_SYM (get_mach) PARAMS ((const char *));
+extern 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 *
+extern const CGEN_INSN *
 CGEN_SYM (lookup_insn) PARAMS ((const CGEN_INSN *, cgen_insn_t,
                                int, CGEN_FIELDS *, int));
+extern void
+CGEN_SYM (get_insn_operands) PARAMS ((const CGEN_INSN *, const CGEN_FIELDS *,
+                                     int *));
+extern const CGEN_INSN *
+CGEN_SYM (lookup_get_insn_operands) PARAMS ((const CGEN_INSN *, cgen_insn_t,
+                                            int, int *));
 
 CGEN_INLINE void
 CGEN_SYM (put_operand) PARAMS ((int, const long *,
@@ -851,10 +933,10 @@ CGEN_SYM (put_operand) PARAMS ((int, const long *,
 CGEN_INLINE long
 CGEN_SYM (get_operand) PARAMS ((int, const CGEN_FIELDS *));
 
-const char *
+extern const char *
 CGEN_SYM (parse_operand) PARAMS ((int, const char **, CGEN_FIELDS *));
 
-const char *
+extern const char *
 CGEN_SYM (insert_operand) PARAMS ((int, CGEN_FIELDS *, char *));
 
 /* Default insn parser, printer.  */
@@ -864,6 +946,6 @@ extern cgen_extract_fn CGEN_SYM (extract_insn);
 extern cgen_print_fn CGEN_SYM (print_insn);
 
 /* Read in a cpu description file.  */
-const char * cgen_read_cpu_file PARAMS ((const char *));
+extern const char * cgen_read_cpu_file PARAMS ((const char *));
 
 #endif /* CGEN_H */