This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [0/13] .md-file enumerations


Richard Sandiford <rdsandiford@googlemail.com> writes:
> Hans-Peter Nilsson <hp@bitrange.com> writes:
>> On Mon, 17 May 2010, Richard Sandiford wrote:
>>> Hans-Peter Nilsson <hp@bitrange.com> writes:
>>> > ...except ;-) perhaps I'd have called define_md_enum
>>> > define_rtl_enum or just plain define_enum but definitely
>>> > bikeshed level; as long as it's not ambiguous, no (am)biggie.
>>>
>>> FWIW, I'm happy with either of these suggestions, so if there's
>>> one in particular you or anyone else like, let me know.
>>
>> As long as we discuss colors, I'd prefer define_enum, only
>> because it rings better with define_attr_enum.
>
> Works for me.  (And I'm happy to talk colours.  It's much easier
> to change them now than later.)
>
> I'll see what other feedback there is about the patches before
> posting an updated set.

Here are parts 11 and 12 with the name changed.  Tested as before.

Richard


gcc/
	* doc/md.texi (define_c_enum, define_enum): Document.
	* read-md.h (md_constant): Add a parent_enum field.
	(enum_value, enum_type): New structures.
	(upcase_string, traverse_enum_types): Declare.
	* read-md.c (enum_types): New variable.
	(upcase_string, add_constant): New functions.
	(handle_constants): Don't create the hash table here.
	Use add_constant.
	(traverse_md_constants): Don't check for a null md_constants.
	(decimal_string, handle_enum, traverse_enum_types): New functions.
	(read_md_files): Initialize md_constants and md_enums.
	* genconstants.c (print_md_constant): Ignore info argument.
	Only print constants that belong to no enum.
	(print_enum_type): New function.
	(main): Don't pass stdout to print_md_constant.  Call print_enum_type
	for each defined enum type.
	* config/mips/mips.md (processor): New define_enum.
	(unspec): New define_c_enum.
	(UNSPEC_COMPARE_AND_SWAP, UNSPEC_COMPARE_AND_SWAP_12)
	(UNSPEC_SYNC_OLD_OP, UNSPEC_SYNC_NEW_OP, UNSPEC_SYNC_NEW_OP_12)
	(UNSPEC_SYNC_OLD_OP_12, UNSPEC_SYNC_EXCHANGE, UNSPEC_SYNC_EXCHANGE_12)
	(UNSPEC_MEMORY_BARRIER): Moved to sync.md.
	(UNSPEC_ADDQ, UNSPEC_ADDQ_S, UNSPEC_SUBQ, UNSPEC_SUBQ_S, UNSPEC_ADDSC)
	(UNSPEC_ADDWC, UNSPEC_MODSUB, UNSPEC_RADDU_W_QB, UNSPEC_ABSQ_S)
	(UNSPEC_PRECRQ_QB_PH, UNSPEC_PRECRQ_PH_W, UNSPEC_PRECRQ_RS_PH_W)
	(UNSPEC_PRECRQU_S_QB_PH, UNSPEC_PRECEQ_W_PHL, UNSPEC_PRECEQ_W_PHR)
	(UNSPEC_PRECEQU_PH_QBL, UNSPEC_PRECEQU_PH_QBR, UNSPEC_PRECEQU_PH_QBLA)
	(UNSPEC_PRECEQU_PH_QBRA, UNSPEC_PRECEU_PH_QBL, UNSPEC_PRECEU_PH_QBR)
	(UNSPEC_PRECEU_PH_QBLA, UNSPEC_PRECEU_PH_QBRA, UNSPEC_SHLL)
	(UNSPEC_SHLL_S, UNSPEC_SHRL_QB, UNSPEC_SHRA_PH, UNSPEC_SHRA_R)
	(UNSPEC_MULEU_S_PH_QBL, UNSPEC_MULEU_S_PH_QBR, UNSPEC_MULQ_RS_PH)
	(UNSPEC_MULEQ_S_W_PHL, UNSPEC_MULEQ_S_W_PHR, UNSPEC_DPAU_H_QBL)
	(UNSPEC_DPAU_H_QBR, UNSPEC_DPSU_H_QBL, UNSPEC_DPSU_H_QBR)
	(UNSPEC_DPAQ_S_W_PH, UNSPEC_DPSQ_S_W_PH, UNSPEC_MULSAQ_S_W_PH)
	(UNSPEC_DPAQ_SA_L_W, UNSPEC_DPSQ_SA_L_W, UNSPEC_MAQ_S_W_PHL)
	(UNSPEC_MAQ_S_W_PHR, UNSPEC_MAQ_SA_W_PHL, UNSPEC_MAQ_SA_W_PHR)
	(UNSPEC_BITREV, UNSPEC_INSV, UNSPEC_REPL_QB, UNSPEC_REPL_PH)
	(UNSPEC_CMP_EQ, UNSPEC_CMP_LT, UNSPEC_CMP_LE, UNSPEC_CMPGU_EQ_QB)
	(UNSPEC_CMPGU_LT_QB, UNSPEC_CMPGU_LE_QB, UNSPEC_PICK, UNSPEC_PACKRL_PH)
	(UNSPEC_EXTR_W, UNSPEC_EXTR_R_W, UNSPEC_EXTR_RS_W, UNSPEC_EXTR_S_H)
	(UNSPEC_EXTP, UNSPEC_EXTPDP, UNSPEC_SHILO, UNSPEC_MTHLIP, UNSPEC_WRDSP)
	(UNSPEC_RDDSP): Move to mips-dsp.md.
	(UNSPEC_ABSQ_S_QB, UNSPEC_ADDU_PH, UNSPEC_ADDU_S_PH, UNSPEC_ADDUH_QB)
	(UNSPEC_ADDUH_R_QB, UNSPEC_APPEND, UNSPEC_BALIGN, UNSPEC_CMPGDU_EQ_QB)
	(UNSPEC_CMPGDU_LT_QB, UNSPEC_CMPGDU_LE_QB, UNSPEC_DPA_W_PH)
	(UNSPEC_DPS_W_PH, UNSPEC_MADD, UNSPEC_MADDU, UNSPEC_MSUB, UNSPEC_MSUBU)
	(UNSPEC_MUL_PH, UNSPEC_MUL_S_PH, UNSPEC_MULQ_RS_W, UNSPEC_MULQ_S_PH)
	(UNSPEC_MULQ_S_W, UNSPEC_MULSA_W_PH, UNSPEC_MULT, UNSPEC_MULTU)
	(UNSPEC_PRECR_QB_PH, UNSPEC_PRECR_SRA_PH_W, UNSPEC_PRECR_SRA_R_PH_W)
	(UNSPEC_PREPEND, UNSPEC_SHRA_QB, UNSPEC_SHRA_R_QB, UNSPEC_SHRL_PH)
	(UNSPEC_SUBU_PH, UNSPEC_SUBU_S_PH, UNSPEC_SUBUH_QB, UNSPEC_SUBUH_R_QB)
	(UNSPEC_ADDQH_PH, UNSPEC_ADDQH_R_PH, UNSPEC_ADDQH_W, UNSPEC_ADDQH_R_W)
	(UNSPEC_SUBQH_PH, UNSPEC_SUBQH_R_PH, UNSPEC_SUBQH_W, UNSPEC_SUBQH_R_W)
	(UNSPEC_DPAX_W_PH, UNSPEC_DPSX_W_PH, UNSPEC_DPAQX_S_W_PH)
	(UNSPEC_DPAQX_SA_W_PH, UNSPEC_DPSQX_S_W_PH, UNSPEC_DPSQX_SA_W_PH):
	Moved to mips-dspr2.md.
	(UNSPEC_MOVE_TF_PS, UNSPEC_C, UNSPEC_ALNV_PS, UNSPEC_CABS)
	(UNSPEC_ADDR_PS, UNSPEC_CVT_PW_PS, UNSPEC_CVT_PS_PW, UNSPEC_MULR_PS)
	(UNSPEC_ABS_PS, UNSPEC_RSQRT1, UNSPEC_RSQRT2, UNSPEC_RECIP1)
	(UNSPEC_RECIP2, UNSPEC_SINGLE_CC, UNSPEC_SCC): Moved from mips-ps-3d.md.
	(UNSPEC_LOONGSON_PAVG, UNSPEC_LOONGSON_PCMPEQ, UNSPEC_LOONGSON_PCMPGT)
	(UNSPEC_LOONGSON_PEXTR, UNSPEC_LOONGSON_PINSR_0)
	(UNSPEC_LOONGSON_PINSR_1, UNSPEC_LOONGSON_PINSR_2)
	(UNSPEC_LOONGSON_PINSR_3, UNSPEC_LOONGSON_PMADD)
	(UNSPEC_LOONGSON_PMOVMSK, UNSPEC_LOONGSON_PMULHU)
	(UNSPEC_LOONGSON_PMULH, UNSPEC_LOONGSON_PMULL, UNSPEC_LOONGSON_PMULU)
	(UNSPEC_LOONGSON_PASUBUB, UNSPEC_LOONGSON_BIADD, UNSPEC_LOONGSON_PSADBH)
	(UNSPEC_LOONGSON_PSHUFH, UNSPEC_LOONGSON_PUNPCKH)
	(UNSPEC_LOONGSON_PUNPCKL, UNSPEC_LOONGSON_PADDD)
	(UNSPEC_LOONGSON_PSUBD): Move to mips-loongson.md.
	(UNSPEC_LOONGSON_ALU1_TURN_ENABLED_INSN)
	(UNSPEC_LOONGSON_ALU2_TURN_ENABLED_INSN)
	(UNSPEC_LOONGSON_FALU1_TURN_ENABLED_INSN)
	(UNSPEC_LOONGSON_FALU2_TURN_ENABLED_INSN): Moved to mips-loongson2ef.md.
	(cpu): Update comment.
	* config/mips/sync.md (UNSPEC_COMPARE_AND_SWAP)
	(UNSPEC_COMPARE_AND_SWAP_12, UNSPEC_SYNC_OLD_OP, UNSPEC_SYNC_NEW_OP)
	(UNSPEC_SYNC_NEW_OP_12, UNSPEC_SYNC_OLD_OP_12, UNSPEC_SYNC_EXCHANGE)
	(UNSPEC_SYNC_EXCHANGE_12, UNSPEC_MEMORY_BARRIER): Moved from mips.md.
	* config/mips/loongson.md (UNSPEC_LOONGSON_PAVG, UNSPEC_LOONGSON_PCMPEQ)
	(UNSPEC_LOONGSON_PCMPGT, UNSPEC_LOONGSON_PEXTR, UNSPEC_LOONGSON_PINSR_0)
	(UNSPEC_LOONGSON_PINSR_1, UNSPEC_LOONGSON_PINSR_2)
	(UNSPEC_LOONGSON_PINSR_3, UNSPEC_LOONGSON_PMADD)
	(UNSPEC_LOONGSON_PMOVMSK, UNSPEC_LOONGSON_PMULHU)
	(UNSPEC_LOONGSON_PMULH, UNSPEC_LOONGSON_PMULL, UNSPEC_LOONGSON_PMULU)
	(UNSPEC_LOONGSON_PASUBUB, UNSPEC_LOONGSON_BIADD, UNSPEC_LOONGSON_PSADBH)
	(UNSPEC_LOONGSON_PSHUFH, UNSPEC_LOONGSON_PUNPCKH)
	(UNSPEC_LOONGSON_PUNPCKL, UNSPEC_LOONGSON_PADDD)
	(UNSPEC_LOONGSON_PSUBD): Moved from mips.md
	* config/mips/loongson2ef.md (UNSPEC_LOONGSON_ALU1_TURN_ENABLED_INSN)
	(UNSPEC_LOONGSON_ALU2_TURN_ENABLED_INSN)
	(UNSPEC_LOONGSON_FALU1_TURN_ENABLED_INSN)
	(UNSPEC_LOONGSON_FALU2_TURN_ENABLED_INSN): Moved from mips.md
	* config/mips/mips-dsp.md (UNSPEC_ADDQ, UNSPEC_ADDQ_S, UNSPEC_SUBQ)
	(UNSPEC_SUBQ_S, UNSPEC_ADDSC, UNSPEC_ADDWC, UNSPEC_MODSUB)
	(UNSPEC_RADDU_W_QB, UNSPEC_ABSQ_S, UNSPEC_PRECRQ_QB_PH)
	(UNSPEC_PRECRQ_PH_W, UNSPEC_PRECRQ_RS_PH_W, UNSPEC_PRECRQU_S_QB_PH)
	(UNSPEC_PRECEQ_W_PHL, UNSPEC_PRECEQ_W_PHR, UNSPEC_PRECEQU_PH_QBL)
	(UNSPEC_PRECEQU_PH_QBR, UNSPEC_PRECEQU_PH_QBLA, UNSPEC_PRECEQU_PH_QBRA)
	(UNSPEC_PRECEU_PH_QBL, UNSPEC_PRECEU_PH_QBR, UNSPEC_PRECEU_PH_QBLA)
	(UNSPEC_PRECEU_PH_QBRA, UNSPEC_SHLL, UNSPEC_SHLL_S, UNSPEC_SHRL_QB)
	(UNSPEC_SHRA_PH, UNSPEC_SHRA_R, UNSPEC_MULEU_S_PH_QBL)
	(UNSPEC_MULEU_S_PH_QBR, UNSPEC_MULQ_RS_PH, UNSPEC_MULEQ_S_W_PHL)
	(UNSPEC_MULEQ_S_W_PHR, UNSPEC_DPAU_H_QBL, UNSPEC_DPAU_H_QBR)
	(UNSPEC_DPSU_H_QBL, UNSPEC_DPSU_H_QBR, UNSPEC_DPAQ_S_W_PH)
	(UNSPEC_DPSQ_S_W_PH, UNSPEC_MULSAQ_S_W_PH, UNSPEC_DPAQ_SA_L_W)
	(UNSPEC_DPSQ_SA_L_W, UNSPEC_MAQ_S_W_PHL, UNSPEC_MAQ_S_W_PHR)
	(UNSPEC_MAQ_SA_W_PHL, UNSPEC_MAQ_SA_W_PHR, UNSPEC_BITREV, UNSPEC_INSV)
	(UNSPEC_REPL_QB, UNSPEC_REPL_PH, UNSPEC_CMP_EQ, UNSPEC_CMP_LT)
	(UNSPEC_CMP_LE, UNSPEC_CMPGU_EQ_QB, UNSPEC_CMPGU_LT_QB)
	(UNSPEC_CMPGU_LE_QB, UNSPEC_PICK, UNSPEC_PACKRL_PH, UNSPEC_EXTR_W)
	(UNSPEC_EXTR_R_W, UNSPEC_EXTR_RS_W, UNSPEC_EXTR_S_H, UNSPEC_EXTP)
	(UNSPEC_EXTPDP, UNSPEC_SHILO, UNSPEC_MTHLIP, UNSPEC_WRDSP)
	(UNSPEC_RDDSP): Moved from mips.md.
	* config/mips/mips-dspr2.md (UNSPEC_ABSQ_S_QB, UNSPEC_ADDU_PH)
	(UNSPEC_ADDU_S_PH, UNSPEC_ADDUH_QB, UNSPEC_ADDUH_R_QB, UNSPEC_APPEND)
	(UNSPEC_BALIGN, UNSPEC_CMPGDU_EQ_QB, UNSPEC_CMPGDU_LT_QB)
	(UNSPEC_CMPGDU_LE_QB, UNSPEC_DPA_W_PH, UNSPEC_DPS_W_PH, UNSPEC_MADD)
	(UNSPEC_MADDU, UNSPEC_MSUB, UNSPEC_MSUBU, UNSPEC_MUL_PH)
	(UNSPEC_MUL_S_PH, UNSPEC_MULQ_RS_W, UNSPEC_MULQ_S_PH, UNSPEC_MULQ_S_W)
	(UNSPEC_MULSA_W_PH, UNSPEC_MULT, UNSPEC_MULTU, UNSPEC_PRECR_QB_PH)
	(UNSPEC_PRECR_SRA_PH_W, UNSPEC_PRECR_SRA_R_PH_W, UNSPEC_PREPEND)
	(UNSPEC_SHRA_QB, UNSPEC_SHRA_R_QB, UNSPEC_SHRL_PH, UNSPEC_SUBU_PH)
	(UNSPEC_SUBU_S_PH, UNSPEC_SUBUH_QB, UNSPEC_SUBUH_R_QB, UNSPEC_ADDQH_PH)
	(UNSPEC_ADDQH_R_PH, UNSPEC_ADDQH_W, UNSPEC_ADDQH_R_W, UNSPEC_SUBQH_PH)
	(UNSPEC_SUBQH_R_PH, UNSPEC_SUBQH_W, UNSPEC_SUBQH_R_W, UNSPEC_DPAX_W_PH)
	(UNSPEC_DPSX_W_PH, UNSPEC_DPAQX_S_W_PH, UNSPEC_DPAQX_SA_W_PH)
	(UNSPEC_DPSQX_S_W_PH, UNSPEC_DPSQX_SA_W_PH): Moved from mips.md.
	* config/mips/mips-ps-3d.md (UNSPEC_MOVE_TF_PS, UNSPEC_C)
	(UNSPEC_ALNV_PS, UNSPEC_CABS, UNSPEC_ADDR_PS, UNSPEC_CVT_PW_PS)
	(UNSPEC_CVT_PS_PW, UNSPEC_MULR_PS, UNSPEC_ABS_PS, UNSPEC_RSQRT1)
	(UNSPEC_RSQRT2, UNSPEC_RECIP1, UNSPEC_RECIP2, UNSPEC_SINGLE_CC)
	(UNSPEC_SCC): Moved from mips.md.
	* config/mips/mips.c (mips_arch, mips_tune): Change enum from
	"processor_type" to "processor".
	(mips_rtx_cost_data): Replace PROCESSOR_MAX with NUM_PROCESSOR_VALUES.
	* config/mips/mips.h (processor_type): Delete.
	(mips_cpu_info.cpu, mips_arch, mips_tune): Change enum from
	"processor_type" to "processor".

Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi	2010-05-29 07:56:06.000000000 +0100
+++ gcc/doc/md.texi	2010-05-29 07:56:54.000000000 +0100
@@ -7902,6 +7902,88 @@ You could write:
 
 The constants that are defined with a define_constant are also output
 in the insn-codes.h header file as #defines.
+
+@cindex enumerations
+@findex define_c_enum
+You can also use the machine description file to define enumerations.
+Like the constants defined by @code{define_constant}, these enumerations
+are visible to both the machine description file and the main C code.
+
+The syntax is as follows:
+
+@smallexample
+(define_c_enum "@var{name}" [
+  @var{value0}
+  @var{value1}
+  @dots{}
+  @var{valuen}
+])
+@end smallexample
+
+This definition causes the equivalent of the following C code to appear
+in @file{insn-constants.h}:
+
+@smallexample
+enum @var{name} @{
+  @var{value0} = 0,
+  @var{value1} = 1,
+  @dots{}
+  @var{valuen} = @var{n}
+@};
+#define NUM_@var{cname}_VALUES (@var{n} + 1)
+@end smallexample
+
+where @var{cname} is the capitalized form of @var{name}.
+It also makes each @var{valuei} available in the machine description
+file, just as if it had been declared with:
+
+@smallexample
+(define_constants [(@var{valuei} @var{i})])
+@end smallexample
+
+Each @var{valuei} is usually an upper-case identifier and usually
+begins with @var{cname}.
+
+You can split the enumeration definition into as many statements as
+you like.  The above example is directly equivalent to:
+
+@smallexample
+(define_c_enum "@var{name}" [@var{value0}])
+(define_c_enum "@var{name}" [@var{value1}])
+@dots{}
+(define_c_enum "@var{name}" [@var{valuen}])
+@end smallexample
+
+Splitting the enumeration helps to improve the modularity of each
+individual @code{.md} file.  For example, if a port defines its
+synchronization instructions in a separate @file{sync.md} file,
+it is convenient to define all synchronization-specific enumeration
+values in @file{sync.md} rather than in the main @file{.md} file.
+
+@findex define_enum
+Another way of defining an enumeration is to use @code{define_enum}:
+
+@smallexample
+(define_enum "@var{name}" [
+  @var{value0}
+  @var{value1}
+  @dots{}
+  @var{valuen}
+])
+@end smallexample
+
+This directive implies:
+
+@smallexample
+(define_c_enum "@var{name}" [
+  @var{cname}_@var{cvalue0}
+  @var{cname}_@var{cvalue1}
+  @dots{}
+  @var{cname}_@var{cvaluen}
+])
+@end smallexample
+
+where @var{cvaluei} is the capitalized form of @var{valuei}.
 @end ifset
 @ifset INTERNALS
 @node Iterators
Index: gcc/read-md.h
===================================================================
--- gcc/read-md.h	2010-05-29 07:56:06.000000000 +0100
+++ gcc/read-md.h	2010-05-29 07:56:54.000000000 +0100
@@ -33,12 +33,49 @@ struct md_name {
   char *string;
 };
 
-/* This structure represents a constant defined by define_constant.
-   NAME is the name of the constant and VALUE is the string it
-   expands to.  */
+/* This structure represents a constant defined by define_constant,
+   define_enum, or such-like.  */
 struct md_constant {
+  /* The name of the constant.  */
   char *name;
+
+  /* The string to which the constants expands.  */
   char *value;
+
+  /* If the constant is associated with a enumeration, this field
+     points to that enumeration, otherwise it is null.  */
+  struct enum_type *parent_enum;
+};
+
+/* This structure represents one value in an enum_type.  */
+struct enum_value {
+  /* The next value in the enum, or null if this is the last.  */
+  struct enum_value *next;
+
+  /* The name of the value as it appears in the .md file.  */
+  char *name;
+
+  /* The definition of the related C value.  */
+  struct md_constant *def;
+};
+
+/* This structure represents an enum defined by define_enum or the like.  */
+struct enum_type {
+  /* The C name of the enumeration.  */
+  char *name;
+
+  /* True if this is an md-style enum (DEFINE_ENUM) rather than
+     a C-style enum (DEFINE_C_ENUM).  */
+  bool md_p;
+
+  /* The values of the enumeration.  There is always at least one.  */
+  struct enum_value *values;
+
+  /* A pointer to the null terminator in VALUES.  */
+  struct enum_value **tail_ptr;
+
+  /* The number of enumeration values.  */
+  unsigned int num_values;
 };
 
 /* A callback that handles a single .md-file directive, up to but not
@@ -95,6 +132,8 @@ extern char *read_string (int);
 extern void read_skip_construct (int, int);
 extern int n_comma_elts (const char *);
 extern const char *scan_comma_elt (const char **);
+extern void upcase_string (char *);
 extern void traverse_md_constants (htab_trav, void *);
+extern void traverse_enum_types (htab_trav, void *);
 extern bool read_md_files (int, char **, bool (*) (const char *),
 			   directive_handler_t);
Index: gcc/read-md.c
===================================================================
--- gcc/read-md.c	2010-05-29 07:56:06.000000000 +0100
+++ gcc/read-md.c	2010-05-29 07:56:54.000000000 +0100
@@ -92,6 +92,9 @@ void (*include_callback) (const char *);
    constant expansion should occur.  */
 static htab_t md_constants;
 
+/* A table of enum_type structures, hashed by name.  */
+static htab_t enum_types;
+
 static void handle_file (directive_handler_t);
 
 /* Given an object that starts with a char * name field, return a hash
@@ -671,6 +674,52 @@ scan_comma_elt (const char **pstr)
   return start;
 }
 
+/* Convert STRING to uppercase.  */
+
+void
+upcase_string (char *string)
+{
+  int i;
+
+  for (i = 0; string[i]; i++)
+    string[i] = TOUPPER (string[i]);
+}
+
+/* Add a NAME = VALUE definition to md_constants-style hash table DEFS,
+   where both NAME and VALUE are malloc()ed strings.  PARENT_ENUM is the
+   enum to which NAME belongs, or null if NAME is a stand-alone constant.  */
+
+static struct md_constant *
+add_constant (htab_t defs, char *name, char *value,
+	      struct enum_type *parent_enum)
+{
+  struct md_constant *def, tmp_def;
+  void **entry_ptr;
+
+  tmp_def.name = name;
+  entry_ptr = htab_find_slot (defs, &tmp_def, INSERT);
+  if (*entry_ptr)
+    {
+      def = (struct md_constant *) *entry_ptr;
+      if (strcmp (def->value, value) != 0)
+	fatal_with_file_and_line ("redefinition of `%s', was `%s', now `%s'",
+				  def->name, def->value, value);
+      else if (parent_enum || def->parent_enum)
+	fatal_with_file_and_line ("redefinition of `%s'", def->name);
+      free (name);
+      free (value);
+    }
+  else
+    {
+      def = XNEW (struct md_constant);
+      def->name = name;
+      def->value = value;
+      def->parent_enum = parent_enum;
+      *entry_ptr = def;
+    }
+  return def;
+}
+
 /* Process a define_constants directive, starting with the optional space
    after the "define_constants".  */
 
@@ -680,45 +729,23 @@ handle_constants (void)
   int c;
   htab_t defs;
 
-  defs = md_constants;
-  if (! defs)
-    defs = htab_create (32, leading_string_hash,
-			leading_string_eq_p, (htab_del) 0);
-
   c = read_skip_spaces ();
   if (c != '[')
     fatal_expected_char ('[', c);
 
   /* Disable constant expansion during definition processing.  */
+  defs = md_constants;
   md_constants = 0;
   while ( (c = read_skip_spaces ()) != ']')
     {
       struct md_name name, value;
-      struct md_constant *def, tmp_def;
-      void **entry_ptr;
 
       if (c != '(')
 	fatal_expected_char ('(', c);
 
       read_name (&name);
       read_name (&value);
-
-      tmp_def.name = name.string;
-      entry_ptr = htab_find_slot (defs, &tmp_def, INSERT);
-      if (*entry_ptr)
-	{
-	  def = (struct md_constant *) *entry_ptr;
-	  if (strcmp (def->value, value.string) != 0)
-	    fatal_with_file_and_line ("redefinition of %s, was %s, now %s",
-				      def->name, def->value, value.string);
-	}
-      else
-	{
-	  def = XNEW (struct md_constant);
-	  def->name = xstrdup (name.string);
-	  def->value = xstrdup (value.string);
-	  *entry_ptr = def;
-	}
+      add_constant (defs, xstrdup (name.string), xstrdup (value.string), 0);
 
       c = read_skip_spaces ();
       if (c != ')')
@@ -734,8 +761,100 @@ handle_constants (void)
 void
 traverse_md_constants (htab_trav callback, void *info)
 {
-  if (md_constants)
-    htab_traverse (md_constants, callback, info);
+  htab_traverse (md_constants, callback, info);
+}
+
+/* Return a malloc()ed decimal string that represents number NUMBER.  */
+
+static char *
+decimal_string (int number)
+{
+  /* A safe overestimate.  +1 for sign, +1 for null terminator.  */
+  char buffer[sizeof (int) * CHAR_BIT + 1 + 1];
+
+  sprintf (buffer, "%d", number);
+  return xstrdup (buffer);
+}
+
+/* Process a define_enum or define_c_enum directive, starting with
+   the optional space after the "define_enum".  LINENO is the line
+   number on which the directive started and MD_P is true if the
+   directive is a define_enum rather than a define_c_enum.  */
+
+static void
+handle_enum (int lineno, bool md_p)
+{
+  char *enum_name, *value_name;
+  struct md_name name;
+  struct enum_type *def;
+  struct enum_value *ev;
+  void **slot;
+  int c;
+
+  enum_name = read_string (false);
+  slot = htab_find_slot (enum_types, &enum_name, INSERT);
+  if (*slot)
+    {
+      def = (struct enum_type *) *slot;
+      if (def->md_p != md_p)
+	error_with_line (lineno, "redefining `%s' as a different type of enum",
+			 enum_name);
+    }
+  else
+    {
+      def = XNEW (struct enum_type);
+      def->name = enum_name;
+      def->md_p = md_p;
+      def->values = 0;
+      def->tail_ptr = &def->values;
+      def->num_values = 0;
+      *slot = def;
+    }
+
+  c = read_skip_spaces ();
+  if (c != '[')
+    fatal_expected_char ('[', c);
+
+  while ((c = read_skip_spaces ()) != ']')
+    {
+      if (c == EOF)
+	{
+	  error_with_line (lineno, "unterminated construct");
+	  exit (1);
+	}
+      unread_char (c);
+      read_name (&name);
+
+      ev = XNEW (struct enum_value);
+      ev->next = 0;
+      if (md_p)
+	{
+	  value_name = concat (def->name, "_", name.string, NULL);
+	  upcase_string (value_name);
+	  ev->name = xstrdup (name.string);
+	}
+      else
+	{
+	  value_name = xstrdup (name.string);
+	  ev->name = value_name;
+	}
+      ev->def = add_constant (md_constants, value_name,
+			      decimal_string (def->num_values), def);
+
+      *def->tail_ptr = ev;
+      def->tail_ptr = &ev->next;
+      def->num_values++;
+    }
+}
+
+/* For every enum definition, call CALLBACK with two arguments:
+   a pointer to the constant definition and INFO.  Stop when CALLBACK
+   returns zero.  */
+
+void
+traverse_enum_types (htab_trav callback, void *info)
+{
+  htab_traverse (enum_types, callback, info);
 }
 
 /* Process an "include" directive, starting with the optional space
@@ -834,6 +953,10 @@ handle_file (directive_handler_t handle_
       read_name (&directive);
       if (strcmp (directive.string, "define_constants") == 0)
 	handle_constants ();
+      else if (strcmp (directive.string, "define_enum") == 0)
+	handle_enum (lineno, true);
+      else if (strcmp (directive.string, "define_c_enum") == 0)
+	handle_enum (lineno, false);
       else if (strcmp (directive.string, "include") == 0)
 	handle_include (lineno, handle_directive);
       else if (handle_directive)
@@ -911,6 +1034,10 @@ read_md_files (int argc, char **argv, bo
   obstack_init (&ptr_loc_obstack);
   joined_conditions = htab_create (161, leading_ptr_hash, leading_ptr_eq_p, 0);
   obstack_init (&joined_conditions_obstack);
+  md_constants = htab_create (31, leading_string_hash,
+			      leading_string_eq_p, (htab_del) 0);
+  enum_types = htab_create (31, leading_string_hash,
+			    leading_string_eq_p, (htab_del) 0);
 
   /* Unlock the stdio streams.  */
   unlock_std_streams ();
Index: gcc/genconstants.c
===================================================================
--- gcc/genconstants.c	2010-05-29 07:56:06.000000000 +0100
+++ gcc/genconstants.c	2010-05-29 07:56:54.000000000 +0100
@@ -35,12 +35,40 @@ the Free Software Foundation; either ver
    the current constant definition.  */
 
 static int
-print_md_constant (void **slot, void *info)
+print_md_constant (void **slot, void *info ATTRIBUTE_UNUSED)
 {
   struct md_constant *def = (struct md_constant *) *slot;
-  FILE *file = (FILE *) info;
 
-  fprintf (file, "#define %s %s\n", def->name, def->value);
+  if (!def->parent_enum)
+    printf ("#define %s %s\n", def->name, def->value);
+  return 1;
+}
+
+/* Called via traverse_enums.  Emit an enum definition for
+   enum_type *SLOT.  */
+
+static int
+print_enum_type (void **slot, void *info ATTRIBUTE_UNUSED)
+{
+  struct enum_type *def;
+  struct enum_value *value;
+  char *value_name;
+
+  def = (struct enum_type *) *slot;
+  printf ("\nenum %s {", def->name);
+  for (value = def->values; value; value = value->next)
+    {
+      printf ("\n  %s = %s", value->def->name, value->def->value);
+      if (value->next)
+	putc (',', stdout);
+    }
+  printf ("\n};\n");
+
+  /* Define NUM_<enum>_VALUES to be the largest enum value + 1.  */
+  value_name = ACONCAT (("num_", def->name, "_values", NULL));
+  upcase_string (value_name);
+  printf ("#define %s %d\n", value_name, def->num_values);
+
   return 1;
 }
 
@@ -60,7 +88,8 @@ main (int argc, char **argv)
   puts ("#ifndef GCC_INSN_CONSTANTS_H");
   puts ("#define GCC_INSN_CONSTANTS_H\n");
 
-  traverse_md_constants (print_md_constant, stdout);
+  traverse_md_constants (print_md_constant, 0);
+  traverse_enum_types (print_enum_type, 0);
 
   puts ("\n#endif /* GCC_INSN_CONSTANTS_H */");
 
Index: gcc/config/mips/mips.md
===================================================================
--- gcc/config/mips/mips.md	2010-05-29 07:56:06.000000000 +0100
+++ gcc/config/mips/mips.md	2010-05-29 07:56:54.000000000 +0100
@@ -23,247 +23,119 @@
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
-(define_constants
-  [(UNSPEC_LOAD_LOW		 0)
-   (UNSPEC_LOAD_HIGH		 1)
-   (UNSPEC_STORE_WORD		 2)
-   (UNSPEC_GET_FNADDR		 3)
-   (UNSPEC_BLOCKAGE		 4)
-   (UNSPEC_POTENTIAL_CPRESTORE	 5)
-   (UNSPEC_CPRESTORE		 6)
-   (UNSPEC_RESTORE_GP		 7)
-   (UNSPEC_MOVE_GP		 8)
-   (UNSPEC_EH_RETURN		 9)
-   (UNSPEC_CONSTTABLE_INT	10)
-   (UNSPEC_CONSTTABLE_FLOAT	11)
-   (UNSPEC_ALIGN		14)
-   (UNSPEC_HIGH			17)
-   (UNSPEC_LOAD_LEFT		18)
-   (UNSPEC_LOAD_RIGHT		19)
-   (UNSPEC_STORE_LEFT		20)
-   (UNSPEC_STORE_RIGHT		21)
-   (UNSPEC_LOADGP		22)
-   (UNSPEC_LOAD_CALL		23)
-   (UNSPEC_LOAD_GOT		24)
-   (UNSPEC_GP			25)
-   (UNSPEC_MFHI			26)
-   (UNSPEC_MTHI			27)
-   (UNSPEC_SET_HILO		28)
-   (UNSPEC_TLS_LDM		29)
-   (UNSPEC_TLS_GET_TP		30)
-   (UNSPEC_MFHC1		31)
-   (UNSPEC_MTHC1		32)
-   (UNSPEC_CLEAR_HAZARD		33)
-   (UNSPEC_RDHWR		34)
-   (UNSPEC_SYNCI		35)
-   (UNSPEC_SYNC			36)
-   (UNSPEC_COMPARE_AND_SWAP	37)
-   (UNSPEC_COMPARE_AND_SWAP_12	38)
-   (UNSPEC_SYNC_OLD_OP		39)
-   (UNSPEC_SYNC_NEW_OP		40)
-   (UNSPEC_SYNC_NEW_OP_12	41)
-   (UNSPEC_SYNC_OLD_OP_12	42)
-   (UNSPEC_SYNC_EXCHANGE	43)
-   (UNSPEC_SYNC_EXCHANGE_12	44)
-   (UNSPEC_MEMORY_BARRIER	45)
-   (UNSPEC_SET_GOT_VERSION	46)
-   (UNSPEC_UPDATE_GOT_VERSION	47)
-   (UNSPEC_COPYGP		48)
-   (UNSPEC_ERET			49)
-   (UNSPEC_DERET		50)
-   (UNSPEC_DI			51)
-   (UNSPEC_EHB			52)
-   (UNSPEC_RDPGPR		53)
-   (UNSPEC_COP0			54)
-   ;; Used in a call expression in place of args_size.  It's present for PIC
-   ;; indirect calls where it contains args_size and the function symbol.
-   (UNSPEC_CALL_ATTR		55)
-   
-   (UNSPEC_ADDRESS_FIRST	100)
+(define_enum "processor" [
+  r3000
+  4kc
+  4kp
+  5kc
+  5kf
+  20kc
+  24kc
+  24kf2_1
+  24kf1_1
+  74kc
+  74kf2_1
+  74kf1_1
+  74kf3_2
+  loongson_2e
+  loongson_2f
+  m4k
+  octeon
+  r3900
+  r6000
+  r4000
+  r4100
+  r4111
+  r4120
+  r4130
+  r4300
+  r4600
+  r4650
+  r5000
+  r5400
+  r5500
+  r7000
+  r8000
+  r9000
+  r10000
+  sb1
+  sb1a
+  sr71000
+  xlr
+])
+
+(define_c_enum "unspec" [
+  ;; Unaligned accesses.
+  UNSPEC_LOAD_LEFT
+  UNSPEC_LOAD_RIGHT
+  UNSPEC_STORE_LEFT
+  UNSPEC_STORE_RIGHT
+
+  ;; Floating-point moves.
+  UNSPEC_LOAD_LOW
+  UNSPEC_LOAD_HIGH
+  UNSPEC_STORE_WORD
+  UNSPEC_MFHC1
+  UNSPEC_MTHC1
+
+  ;; HI/LO moves.
+  UNSPEC_MFHI
+  UNSPEC_MTHI
+  UNSPEC_SET_HILO
+
+  ;; GP manipulation.
+  UNSPEC_LOADGP
+  UNSPEC_COPYGP
+  UNSPEC_MOVE_GP
+  UNSPEC_POTENTIAL_CPRESTORE
+  UNSPEC_CPRESTORE
+  UNSPEC_RESTORE_GP
+  UNSPEC_EH_RETURN
+  UNSPEC_GP
+  UNSPEC_SET_GOT_VERSION
+  UNSPEC_UPDATE_GOT_VERSION
+
+  ;; Symbolic accesses.
+  UNSPEC_LOAD_CALL
+  UNSPEC_LOAD_GOT
+  UNSPEC_TLS_LDM
+  UNSPEC_TLS_GET_TP
+
+  ;; MIPS16 constant pools.
+  UNSPEC_ALIGN
+  UNSPEC_CONSTTABLE_INT
+  UNSPEC_CONSTTABLE_FLOAT
+
+  ;; Blockage and synchronisation.
+  UNSPEC_BLOCKAGE
+  UNSPEC_CLEAR_HAZARD
+  UNSPEC_RDHWR
+  UNSPEC_SYNCI
+  UNSPEC_SYNC
+
+  ;; Cache manipulation.
+  UNSPEC_MIPS_CACHE
+  UNSPEC_R10K_CACHE_BARRIER
+
+  ;; Interrupt handling.
+  UNSPEC_ERET
+  UNSPEC_DERET
+  UNSPEC_DI
+  UNSPEC_EHB
+  UNSPEC_RDPGPR
+  UNSPEC_COP0
+
+  ;; Used in a call expression in place of args_size.  It's present for PIC
+  ;; indirect calls where it contains args_size and the function symbol.
+  UNSPEC_CALL_ATTR
+])
 
-   (TLS_GET_TP_REGNUM		3)
+(define_constants
+  [(TLS_GET_TP_REGNUM		3)
    (RETURN_ADDR_REGNUM		31)
    (CPRESTORE_SLOT_REGNUM	76)
    (GOT_VERSION_REGNUM		79)
 
-   ;; For MIPS Paired-Singled Floating Point Instructions.
-
-   (UNSPEC_MOVE_TF_PS		200)
-   (UNSPEC_C			201)
-
-   ;; MIPS64/MIPS32R2 alnv.ps
-   (UNSPEC_ALNV_PS		202)
-
-   ;; MIPS-3D instructions
-   (UNSPEC_CABS			203)
-
-   (UNSPEC_ADDR_PS		204)
-   (UNSPEC_CVT_PW_PS		205)
-   (UNSPEC_CVT_PS_PW		206)
-   (UNSPEC_MULR_PS		207)
-   (UNSPEC_ABS_PS		208)
-
-   (UNSPEC_RSQRT1		209)
-   (UNSPEC_RSQRT2		210)
-   (UNSPEC_RECIP1		211)
-   (UNSPEC_RECIP2		212)
-   (UNSPEC_SINGLE_CC		213)
-   (UNSPEC_SCC			214)
-
-   ;; MIPS DSP ASE Revision 0.98 3/24/2005
-   (UNSPEC_ADDQ			300)
-   (UNSPEC_ADDQ_S		301)
-   (UNSPEC_SUBQ			302)
-   (UNSPEC_SUBQ_S		303)
-   (UNSPEC_ADDSC		304)
-   (UNSPEC_ADDWC		305)
-   (UNSPEC_MODSUB		306)
-   (UNSPEC_RADDU_W_QB		307)
-   (UNSPEC_ABSQ_S		308)
-   (UNSPEC_PRECRQ_QB_PH		309)
-   (UNSPEC_PRECRQ_PH_W		310)
-   (UNSPEC_PRECRQ_RS_PH_W	311)
-   (UNSPEC_PRECRQU_S_QB_PH	312)
-   (UNSPEC_PRECEQ_W_PHL		313)
-   (UNSPEC_PRECEQ_W_PHR		314)
-   (UNSPEC_PRECEQU_PH_QBL	315)
-   (UNSPEC_PRECEQU_PH_QBR	316)
-   (UNSPEC_PRECEQU_PH_QBLA	317)
-   (UNSPEC_PRECEQU_PH_QBRA	318)
-   (UNSPEC_PRECEU_PH_QBL	319)
-   (UNSPEC_PRECEU_PH_QBR	320)
-   (UNSPEC_PRECEU_PH_QBLA	321)
-   (UNSPEC_PRECEU_PH_QBRA	322)
-   (UNSPEC_SHLL			323)
-   (UNSPEC_SHLL_S		324)
-   (UNSPEC_SHRL_QB		325)
-   (UNSPEC_SHRA_PH		326)
-   (UNSPEC_SHRA_R		327)
-   (UNSPEC_MULEU_S_PH_QBL	328)
-   (UNSPEC_MULEU_S_PH_QBR	329)
-   (UNSPEC_MULQ_RS_PH		330)
-   (UNSPEC_MULEQ_S_W_PHL	331)
-   (UNSPEC_MULEQ_S_W_PHR	332)
-   (UNSPEC_DPAU_H_QBL		333)
-   (UNSPEC_DPAU_H_QBR		334)
-   (UNSPEC_DPSU_H_QBL		335)
-   (UNSPEC_DPSU_H_QBR		336)
-   (UNSPEC_DPAQ_S_W_PH		337)
-   (UNSPEC_DPSQ_S_W_PH		338)
-   (UNSPEC_MULSAQ_S_W_PH	339)
-   (UNSPEC_DPAQ_SA_L_W		340)
-   (UNSPEC_DPSQ_SA_L_W		341)
-   (UNSPEC_MAQ_S_W_PHL		342)
-   (UNSPEC_MAQ_S_W_PHR		343)
-   (UNSPEC_MAQ_SA_W_PHL		344)
-   (UNSPEC_MAQ_SA_W_PHR		345)
-   (UNSPEC_BITREV		346)
-   (UNSPEC_INSV			347)
-   (UNSPEC_REPL_QB		348)
-   (UNSPEC_REPL_PH		349)
-   (UNSPEC_CMP_EQ		350)
-   (UNSPEC_CMP_LT		351)
-   (UNSPEC_CMP_LE		352)
-   (UNSPEC_CMPGU_EQ_QB		353)
-   (UNSPEC_CMPGU_LT_QB		354)
-   (UNSPEC_CMPGU_LE_QB		355)
-   (UNSPEC_PICK			356)
-   (UNSPEC_PACKRL_PH		357)
-   (UNSPEC_EXTR_W		358)
-   (UNSPEC_EXTR_R_W		359)
-   (UNSPEC_EXTR_RS_W		360)
-   (UNSPEC_EXTR_S_H		361)
-   (UNSPEC_EXTP			362)
-   (UNSPEC_EXTPDP		363)
-   (UNSPEC_SHILO		364)
-   (UNSPEC_MTHLIP		365)
-   (UNSPEC_WRDSP		366)
-   (UNSPEC_RDDSP		367)
-
-   ;; MIPS DSP ASE REV 2 Revision 0.02 11/24/2006
-   (UNSPEC_ABSQ_S_QB		400)
-   (UNSPEC_ADDU_PH		401)
-   (UNSPEC_ADDU_S_PH		402)
-   (UNSPEC_ADDUH_QB		403)
-   (UNSPEC_ADDUH_R_QB		404)
-   (UNSPEC_APPEND		405)
-   (UNSPEC_BALIGN		406)
-   (UNSPEC_CMPGDU_EQ_QB		407)
-   (UNSPEC_CMPGDU_LT_QB		408)
-   (UNSPEC_CMPGDU_LE_QB		409)
-   (UNSPEC_DPA_W_PH		410)
-   (UNSPEC_DPS_W_PH		411)
-   (UNSPEC_MADD			412)
-   (UNSPEC_MADDU		413)
-   (UNSPEC_MSUB			414)
-   (UNSPEC_MSUBU		415)
-   (UNSPEC_MUL_PH		416)
-   (UNSPEC_MUL_S_PH		417)
-   (UNSPEC_MULQ_RS_W		418)
-   (UNSPEC_MULQ_S_PH		419)
-   (UNSPEC_MULQ_S_W		420)
-   (UNSPEC_MULSA_W_PH		421)
-   (UNSPEC_MULT			422)
-   (UNSPEC_MULTU		423)
-   (UNSPEC_PRECR_QB_PH		424)
-   (UNSPEC_PRECR_SRA_PH_W	425)
-   (UNSPEC_PRECR_SRA_R_PH_W	426)
-   (UNSPEC_PREPEND		427)
-   (UNSPEC_SHRA_QB		428)
-   (UNSPEC_SHRA_R_QB		429)
-   (UNSPEC_SHRL_PH		430)
-   (UNSPEC_SUBU_PH		431)
-   (UNSPEC_SUBU_S_PH		432)
-   (UNSPEC_SUBUH_QB		433)
-   (UNSPEC_SUBUH_R_QB		434)
-   (UNSPEC_ADDQH_PH		435)
-   (UNSPEC_ADDQH_R_PH		436)
-   (UNSPEC_ADDQH_W		437)
-   (UNSPEC_ADDQH_R_W		438)
-   (UNSPEC_SUBQH_PH		439)
-   (UNSPEC_SUBQH_R_PH		440)
-   (UNSPEC_SUBQH_W		441)
-   (UNSPEC_SUBQH_R_W		442)
-   (UNSPEC_DPAX_W_PH		443)
-   (UNSPEC_DPSX_W_PH		444)
-   (UNSPEC_DPAQX_S_W_PH		445)
-   (UNSPEC_DPAQX_SA_W_PH	446)
-   (UNSPEC_DPSQX_S_W_PH		447)
-   (UNSPEC_DPSQX_SA_W_PH	448)
-
-   ;; ST Microelectronics Loongson-2E/2F.
-   (UNSPEC_LOONGSON_PAVG	500)
-   (UNSPEC_LOONGSON_PCMPEQ	501)
-   (UNSPEC_LOONGSON_PCMPGT	502)
-   (UNSPEC_LOONGSON_PEXTR	503)
-   (UNSPEC_LOONGSON_PINSR_0	504)
-   (UNSPEC_LOONGSON_PINSR_1	505)
-   (UNSPEC_LOONGSON_PINSR_2	506)
-   (UNSPEC_LOONGSON_PINSR_3	507)
-   (UNSPEC_LOONGSON_PMADD	508)
-   (UNSPEC_LOONGSON_PMOVMSK	509)
-   (UNSPEC_LOONGSON_PMULHU	510)
-   (UNSPEC_LOONGSON_PMULH	511)
-   (UNSPEC_LOONGSON_PMULL	512)
-   (UNSPEC_LOONGSON_PMULU	513)
-   (UNSPEC_LOONGSON_PASUBUB	514)
-   (UNSPEC_LOONGSON_BIADD	515)
-   (UNSPEC_LOONGSON_PSADBH	516)
-   (UNSPEC_LOONGSON_PSHUFH	517)
-   (UNSPEC_LOONGSON_PUNPCKH	518)
-   (UNSPEC_LOONGSON_PUNPCKL	519)
-   (UNSPEC_LOONGSON_PADDD	520)
-   (UNSPEC_LOONGSON_PSUBD	521)
-
-   ;; Used in loongson2ef.md
-   (UNSPEC_LOONGSON_ALU1_TURN_ENABLED_INSN   530)
-   (UNSPEC_LOONGSON_ALU2_TURN_ENABLED_INSN   531)
-   (UNSPEC_LOONGSON_FALU1_TURN_ENABLED_INSN  532)
-   (UNSPEC_LOONGSON_FALU2_TURN_ENABLED_INSN  533)
-
-   (UNSPEC_MIPS_CACHE		600)
-   (UNSPEC_R10K_CACHE_BARRIER	601)
-
    ;; PIC long branch sequences are never longer than 100 bytes.
    (MAX_PIC_BRANCH_LENGTH	100)
   ]
@@ -637,7 +509,7 @@ (define_attr "length" ""
 	  ] (const_int 4)))
 
 ;; Attribute describing the processor.  This attribute must match exactly
-;; with the processor_type enumeration in mips.h.
+;; with the processor enumeration above.
 (define_attr "cpu"
   "r3000,4kc,4kp,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,74kc,74kf2_1,74kf1_1,74kf3_2,loongson_2e,loongson_2f,m4k,octeon,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,r10000,sb1,sb1a,sr71000,xlr"
   (const (symbol_ref "mips_tune_attr")))
@@ -6581,3 +6453,7 @@ (include "mips-fixed.md")
 
 ; ST-Microelectronics Loongson-2E/2F-specific patterns.
 (include "loongson.md")
+
+(define_c_enum "unspec" [
+  UNSPEC_ADDRESS_FIRST
+])
Index: gcc/config/mips/sync.md
===================================================================
--- gcc/config/mips/sync.md	2010-05-29 07:56:06.000000000 +0100
+++ gcc/config/mips/sync.md	2010-05-29 07:56:54.000000000 +0100
@@ -19,6 +19,18 @@
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
+(define_c_enum "unspec" [
+  UNSPEC_COMPARE_AND_SWAP
+  UNSPEC_COMPARE_AND_SWAP_12
+  UNSPEC_SYNC_OLD_OP
+  UNSPEC_SYNC_NEW_OP
+  UNSPEC_SYNC_NEW_OP_12
+  UNSPEC_SYNC_OLD_OP_12
+  UNSPEC_SYNC_EXCHANGE
+  UNSPEC_SYNC_EXCHANGE_12
+  UNSPEC_MEMORY_BARRIER
+])
+
 ;; Atomic fetch bitwise operations.
 (define_code_iterator fetchop_bit [ior xor and])
 
Index: gcc/config/mips/loongson.md
===================================================================
--- gcc/config/mips/loongson.md	2010-05-29 07:56:06.000000000 +0100
+++ gcc/config/mips/loongson.md	2010-05-29 07:56:54.000000000 +0100
@@ -18,6 +18,31 @@
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
+(define_c_enum "unspec" [
+  UNSPEC_LOONGSON_PAVG
+  UNSPEC_LOONGSON_PCMPEQ
+  UNSPEC_LOONGSON_PCMPGT
+  UNSPEC_LOONGSON_PEXTR
+  UNSPEC_LOONGSON_PINSR_0
+  UNSPEC_LOONGSON_PINSR_1
+  UNSPEC_LOONGSON_PINSR_2
+  UNSPEC_LOONGSON_PINSR_3
+  UNSPEC_LOONGSON_PMADD
+  UNSPEC_LOONGSON_PMOVMSK
+  UNSPEC_LOONGSON_PMULHU
+  UNSPEC_LOONGSON_PMULH
+  UNSPEC_LOONGSON_PMULL
+  UNSPEC_LOONGSON_PMULU
+  UNSPEC_LOONGSON_PASUBUB
+  UNSPEC_LOONGSON_BIADD
+  UNSPEC_LOONGSON_PSADBH
+  UNSPEC_LOONGSON_PSHUFH
+  UNSPEC_LOONGSON_PUNPCKH
+  UNSPEC_LOONGSON_PUNPCKL
+  UNSPEC_LOONGSON_PADDD
+  UNSPEC_LOONGSON_PSUBD
+])
+
 ;; Mode iterators and attributes.
 
 ;; 64-bit vectors of bytes.
Index: gcc/config/mips/loongson2ef.md
===================================================================
--- gcc/config/mips/loongson2ef.md	2010-05-29 07:56:06.000000000 +0100
+++ gcc/config/mips/loongson2ef.md	2010-05-29 07:56:54.000000000 +0100
@@ -17,6 +17,13 @@
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
+(define_c_enum "unspec" [
+  UNSPEC_LOONGSON_ALU1_TURN_ENABLED_INSN
+  UNSPEC_LOONGSON_ALU2_TURN_ENABLED_INSN
+  UNSPEC_LOONGSON_FALU1_TURN_ENABLED_INSN
+  UNSPEC_LOONGSON_FALU2_TURN_ENABLED_INSN
+])
+
 ;; Automaton for integer instructions.
 (define_automaton "ls2_alu")
 
Index: gcc/config/mips/mips-dsp.md
===================================================================
--- gcc/config/mips/mips-dsp.md	2010-05-29 07:56:06.000000000 +0100
+++ gcc/config/mips/mips-dsp.md	2010-05-29 07:56:54.000000000 +0100
@@ -16,6 +16,78 @@
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
+;; MIPS DSP ASE Revision 0.98 3/24/2005
+(define_c_enum "unspec" [
+  UNSPEC_ADDQ
+  UNSPEC_ADDQ_S
+  UNSPEC_SUBQ
+  UNSPEC_SUBQ_S
+  UNSPEC_ADDSC
+  UNSPEC_ADDWC
+  UNSPEC_MODSUB
+  UNSPEC_RADDU_W_QB
+  UNSPEC_ABSQ_S
+  UNSPEC_PRECRQ_QB_PH
+  UNSPEC_PRECRQ_PH_W
+  UNSPEC_PRECRQ_RS_PH_W
+  UNSPEC_PRECRQU_S_QB_PH
+  UNSPEC_PRECEQ_W_PHL
+  UNSPEC_PRECEQ_W_PHR
+  UNSPEC_PRECEQU_PH_QBL
+  UNSPEC_PRECEQU_PH_QBR
+  UNSPEC_PRECEQU_PH_QBLA
+  UNSPEC_PRECEQU_PH_QBRA
+  UNSPEC_PRECEU_PH_QBL
+  UNSPEC_PRECEU_PH_QBR
+  UNSPEC_PRECEU_PH_QBLA
+  UNSPEC_PRECEU_PH_QBRA
+  UNSPEC_SHLL
+  UNSPEC_SHLL_S
+  UNSPEC_SHRL_QB
+  UNSPEC_SHRA_PH
+  UNSPEC_SHRA_R
+  UNSPEC_MULEU_S_PH_QBL
+  UNSPEC_MULEU_S_PH_QBR
+  UNSPEC_MULQ_RS_PH
+  UNSPEC_MULEQ_S_W_PHL
+  UNSPEC_MULEQ_S_W_PHR
+  UNSPEC_DPAU_H_QBL
+  UNSPEC_DPAU_H_QBR
+  UNSPEC_DPSU_H_QBL
+  UNSPEC_DPSU_H_QBR
+  UNSPEC_DPAQ_S_W_PH
+  UNSPEC_DPSQ_S_W_PH
+  UNSPEC_MULSAQ_S_W_PH
+  UNSPEC_DPAQ_SA_L_W
+  UNSPEC_DPSQ_SA_L_W
+  UNSPEC_MAQ_S_W_PHL
+  UNSPEC_MAQ_S_W_PHR
+  UNSPEC_MAQ_SA_W_PHL
+  UNSPEC_MAQ_SA_W_PHR
+  UNSPEC_BITREV
+  UNSPEC_INSV
+  UNSPEC_REPL_QB
+  UNSPEC_REPL_PH
+  UNSPEC_CMP_EQ
+  UNSPEC_CMP_LT
+  UNSPEC_CMP_LE
+  UNSPEC_CMPGU_EQ_QB
+  UNSPEC_CMPGU_LT_QB
+  UNSPEC_CMPGU_LE_QB
+  UNSPEC_PICK
+  UNSPEC_PACKRL_PH
+  UNSPEC_EXTR_W
+  UNSPEC_EXTR_R_W
+  UNSPEC_EXTR_RS_W
+  UNSPEC_EXTR_S_H
+  UNSPEC_EXTP
+  UNSPEC_EXTPDP
+  UNSPEC_SHILO
+  UNSPEC_MTHLIP
+  UNSPEC_WRDSP
+  UNSPEC_RDDSP
+])
+
 (define_constants
   [(CCDSP_PO_REGNUM	182)
    (CCDSP_SC_REGNUM	183)
Index: gcc/config/mips/mips-dspr2.md
===================================================================
--- gcc/config/mips/mips-dspr2.md	2010-05-29 07:56:06.000000000 +0100
+++ gcc/config/mips/mips-dspr2.md	2010-05-29 07:56:54.000000000 +0100
@@ -18,6 +18,58 @@
 ;;
 ; MIPS DSP ASE REV 2 Revision 0.02 11/24/2006
 
+(define_c_enum "unspec" [
+  UNSPEC_ABSQ_S_QB
+  UNSPEC_ADDU_PH
+  UNSPEC_ADDU_S_PH
+  UNSPEC_ADDUH_QB
+  UNSPEC_ADDUH_R_QB
+  UNSPEC_APPEND
+  UNSPEC_BALIGN
+  UNSPEC_CMPGDU_EQ_QB
+  UNSPEC_CMPGDU_LT_QB
+  UNSPEC_CMPGDU_LE_QB
+  UNSPEC_DPA_W_PH
+  UNSPEC_DPS_W_PH
+  UNSPEC_MADD
+  UNSPEC_MADDU
+  UNSPEC_MSUB
+  UNSPEC_MSUBU
+  UNSPEC_MUL_PH
+  UNSPEC_MUL_S_PH
+  UNSPEC_MULQ_RS_W
+  UNSPEC_MULQ_S_PH
+  UNSPEC_MULQ_S_W
+  UNSPEC_MULSA_W_PH
+  UNSPEC_MULT
+  UNSPEC_MULTU
+  UNSPEC_PRECR_QB_PH
+  UNSPEC_PRECR_SRA_PH_W
+  UNSPEC_PRECR_SRA_R_PH_W
+  UNSPEC_PREPEND
+  UNSPEC_SHRA_QB
+  UNSPEC_SHRA_R_QB
+  UNSPEC_SHRL_PH
+  UNSPEC_SUBU_PH
+  UNSPEC_SUBU_S_PH
+  UNSPEC_SUBUH_QB
+  UNSPEC_SUBUH_R_QB
+  UNSPEC_ADDQH_PH
+  UNSPEC_ADDQH_R_PH
+  UNSPEC_ADDQH_W
+  UNSPEC_ADDQH_R_W
+  UNSPEC_SUBQH_PH
+  UNSPEC_SUBQH_R_PH
+  UNSPEC_SUBQH_W
+  UNSPEC_SUBQH_R_W
+  UNSPEC_DPAX_W_PH
+  UNSPEC_DPSX_W_PH
+  UNSPEC_DPAQX_S_W_PH
+  UNSPEC_DPAQX_SA_W_PH
+  UNSPEC_DPSQX_S_W_PH
+  UNSPEC_DPSQX_SA_W_PH
+])
+
 (define_insn "mips_absq_s_qb"
   [(parallel
     [(set (match_operand:V4QI 0 "register_operand" "=d")
Index: gcc/config/mips/mips-ps-3d.md
===================================================================
--- gcc/config/mips/mips-ps-3d.md	2010-05-29 07:56:06.000000000 +0100
+++ gcc/config/mips/mips-ps-3d.md	2010-05-29 07:56:54.000000000 +0100
@@ -17,6 +17,30 @@
 ;; along with GCC; see the file COPYING3.  If not see
 ;; <http://www.gnu.org/licenses/>.
 
+(define_c_enum "unspec" [
+  UNSPEC_MOVE_TF_PS
+  UNSPEC_C
+
+  ;; MIPS64/MIPS32R2 alnv.ps
+  UNSPEC_ALNV_PS
+
+  ;; MIPS-3D instructions
+  UNSPEC_CABS
+
+  UNSPEC_ADDR_PS
+  UNSPEC_CVT_PW_PS
+  UNSPEC_CVT_PS_PW
+  UNSPEC_MULR_PS
+  UNSPEC_ABS_PS
+
+  UNSPEC_RSQRT1
+  UNSPEC_RSQRT2
+  UNSPEC_RECIP1
+  UNSPEC_RECIP2
+  UNSPEC_SINGLE_CC
+  UNSPEC_SCC
+])
+
 (define_insn "*movcc_v2sf_<mode>"
   [(set (match_operand:V2SF 0 "register_operand" "=f,f")
 	(if_then_else:V2SF
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2010-05-29 07:56:06.000000000 +0100
+++ gcc/config/mips/mips.c	2010-05-29 07:56:54.000000000 +0100
@@ -504,11 +504,11 @@ struct mips_asm_switch mips_noat = { "at
 static bool mips_branch_likely;
 
 /* The current instruction-set architecture.  */
-enum processor_type mips_arch;
+enum processor mips_arch;
 const struct mips_cpu_info *mips_arch_info;
 
 /* The processor that we should tune the code for.  */
-enum processor_type mips_tune;
+enum processor mips_tune;
 const struct mips_cpu_info *mips_tune_info;
 
 /* The ISA level associated with mips_arch.  */
@@ -797,7 +797,8 @@ static const struct mips_rtx_cost_data m
 };
 
 /* Costs to use when optimizing for speed, indexed by processor.  */
-static const struct mips_rtx_cost_data mips_rtx_cost_data[PROCESSOR_MAX] = {
+static const struct mips_rtx_cost_data
+  mips_rtx_cost_data[NUM_PROCESSOR_VALUES] = {
   { /* R3000 */
     COSTS_N_INSNS (2),            /* fp_add */
     COSTS_N_INSNS (4),            /* fp_mult_sf */
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	2010-05-29 07:56:06.000000000 +0100
+++ gcc/config/mips/mips.h	2010-05-29 07:56:54.000000000 +0100
@@ -28,53 +28,6 @@ the Free Software Foundation; either ver
 
 /* MIPS external variables defined in mips.c.  */
 
-/* Which processor to schedule for.  Since there is no difference between
-   a R2000 and R3000 in terms of the scheduler, we collapse them into
-   just an R3000.  The elements of the enumeration must match exactly
-   the cpu attribute in the mips.md machine description.  */
-
-enum processor_type {
-  PROCESSOR_R3000,
-  PROCESSOR_4KC,
-  PROCESSOR_4KP,
-  PROCESSOR_5KC,
-  PROCESSOR_5KF,
-  PROCESSOR_20KC,
-  PROCESSOR_24KC,
-  PROCESSOR_24KF2_1,
-  PROCESSOR_24KF1_1,
-  PROCESSOR_74KC,
-  PROCESSOR_74KF2_1,
-  PROCESSOR_74KF1_1,
-  PROCESSOR_74KF3_2,
-  PROCESSOR_LOONGSON_2E,
-  PROCESSOR_LOONGSON_2F,
-  PROCESSOR_M4K,
-  PROCESSOR_OCTEON,
-  PROCESSOR_R3900,
-  PROCESSOR_R6000,
-  PROCESSOR_R4000,
-  PROCESSOR_R4100,
-  PROCESSOR_R4111,
-  PROCESSOR_R4120,
-  PROCESSOR_R4130,
-  PROCESSOR_R4300,
-  PROCESSOR_R4600,
-  PROCESSOR_R4650,
-  PROCESSOR_R5000,
-  PROCESSOR_R5400,
-  PROCESSOR_R5500,
-  PROCESSOR_R7000,
-  PROCESSOR_R8000,
-  PROCESSOR_R9000,
-  PROCESSOR_R10000,
-  PROCESSOR_SB1,
-  PROCESSOR_SB1A,
-  PROCESSOR_SR71000,
-  PROCESSOR_XLR,
-  PROCESSOR_MAX
-};
-
 /* Costs of various operations on the different architectures.  */
 
 struct mips_rtx_cost_data
@@ -121,7 +74,7 @@ struct mips_cpu_info {
   /* The internal processor number that most closely matches this
      entry.  Several processors can have the same value, if there's no
      difference between them from GCC's point of view.  */
-  enum processor_type cpu;
+  enum processor cpu;
 
   /* The ISA level that the processor implements.  */
   int isa;
@@ -3070,8 +3023,8 @@ struct mips_asm_switch {
 extern int mips_dwarf_regno[];
 extern bool mips_split_p[];
 extern bool mips_split_hi_p[];
-extern enum processor_type mips_arch;   /* which cpu to codegen for */
-extern enum processor_type mips_tune;   /* which cpu to schedule for */
+extern enum processor mips_arch;        /* which cpu to codegen for */
+extern enum processor mips_tune;        /* which cpu to schedule for */
 extern int mips_isa;			/* architectural level */
 extern int mips_abi;			/* which ABI to use */
 extern const struct mips_cpu_info *mips_arch_info;
gcc/
	* doc/md.texi (define_enum_attr): Document.
	* rtl.def (DEFINE_ENUM_ATTR): New rtx.
	* read-md.h (lookup_enum_type): Declare.
	* read-md.c (lookup_enum_type): New function.
	* genattr.c (gen_attr, main): Handle DEFINE_ENUM_ATTR.
	* genattrtab.c (attr_desc): Add an enum_name field.
	(evaluate_eq_attr): Take the associated attribute as argument.
	Get the enum prefix from the enum_name field, if defined.
	Use ACONCAT rather than a fixed-length buffer.  Update recursive calls.
	(simplify_test_exp): Pass attr to evaluate_eq_attr.
	(add_attr_value): New function, split out from...
	(gen_attr): ...here.  Handle DEFINE_ENUM_ATTR.
	(write_test_expr): Pass attr to evaluate_eq_attr.
	(write_attr_get): Use the enum_name as the enum tag, if defined.
	(write_attr_valueq): Use the enum_name as a prefix, if defined.
	(find_attr): Initialize enum_name.
	(main): Handle DEFINE_ENUM_ATTR.
	* gensupport.c (process_rtx): Likewise.
	* config/mips/mips.h (mips_tune_attr): Delete.
	* config/mips/mips.md (cpu): Use define_attr_enum.

Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi	2010-05-29 07:56:54.000000000 +0100
+++ gcc/doc/md.texi	2010-05-29 07:58:22.000000000 +0100
@@ -6700,9 +6700,46 @@ distances. @xref{Insn Lengths}.
 The @code{enabled} attribute can be defined to prevent certain
 alternatives of an insn definition from being used during code
 generation. @xref{Disable Insn Alternatives}.
-
 @end table
 
+@findex define_enum_attr
+@anchor{define_enum_attr}
+Another way of defining an attribute is to use:
+
+@smallexample
+(define_enum_attr "@var{attr}" "@var{enum}" @var{default})
+@end smallexample
+
+This works in just the same way as @code{define_attr}, except that
+the list of values is taken from a separate enumeration called
+@var{enum} (@pxref{define_enum}).  This form allows you to use
+the same list of values for several attributes without having to
+repeat the list each time.  For example:
+
+@smallexample
+(define_enum "processor" [
+  model_a
+  model_b
+  @dots{}
+])
+(define_enum_attr "arch" "processor"
+  (const (symbol_ref "target_arch")))
+(define_enum_attr "tune" "processor"
+  (const (symbol_ref "target_tune")))
+@end smallexample
+
+defines the same attributes as:
+
+@smallexample
+(define_attr "arch" "model_a,model_b,@dots{}"
+  (const (symbol_ref "target_arch")))
+(define_attr "tune" "model_a,model_b,@dots{}"
+  (const (symbol_ref "target_tune")))
+@end smallexample
+
+but without duplicating the processor list.  The second example defines two
+separate C enums (@code{attr_arch} and @code{attr_tune}) whereas the first
+defines a single C enum (@code{processor}).
 @end ifset
 @ifset INTERNALS
 @node Expressions
@@ -7961,6 +7998,7 @@ it is convenient to define all synchroni
 values in @file{sync.md} rather than in the main @file{.md} file.
 
 @findex define_enum
+@anchor{define_enum}
 Another way of defining an enumeration is to use @code{define_enum}:
 
 @smallexample
@@ -7983,7 +8021,11 @@ This directive implies:
 ])
 @end smallexample
 
+@findex define_enum_attr
 where @var{cvaluei} is the capitalized form of @var{valuei}.
+However, unlike @code{define_c_enum}, the enumerations defined
+by @code{define_enum} can be used in attribute specifications
+(@pxref{define_enum_attr}).
 @end ifset
 @ifset INTERNALS
 @node Iterators
Index: gcc/rtl.def
===================================================================
--- gcc/rtl.def	2010-05-29 07:55:59.000000000 +0100
+++ gcc/rtl.def	2010-05-29 07:58:22.000000000 +0100
@@ -1198,6 +1198,12 @@ DEF_RTL_EXPR(DEFINE_INSN_RESERVATION, "d
    3rd operand: expression for the default value of the attribute.  */
 DEF_RTL_EXPR(DEFINE_ATTR, "define_attr", "sse", RTX_EXTRA)
 
+/* Definition of an insn attribute that uses an existing enumerated type.
+   1st operand: name of the attribute
+   2nd operand: the name of the enumerated type
+   3rd operand: expression for the default value of the attribute.  */
+DEF_RTL_EXPR(DEFINE_ENUM_ATTR, "define_enum_attr", "sse", RTX_EXTRA)
+
 /* Marker for the name of an attribute.  */
 DEF_RTL_EXPR(ATTR, "attr", "s", RTX_EXTRA)
 
Index: gcc/read-md.h
===================================================================
--- gcc/read-md.h	2010-05-29 07:56:54.000000000 +0100
+++ gcc/read-md.h	2010-05-29 07:58:22.000000000 +0100
@@ -135,5 +135,6 @@ extern const char *scan_comma_elt (const
 extern void upcase_string (char *);
 extern void traverse_md_constants (htab_trav, void *);
 extern void traverse_enum_types (htab_trav, void *);
+extern struct enum_type *lookup_enum_type (const char *);
 extern bool read_md_files (int, char **, bool (*) (const char *),
 			   directive_handler_t);
Index: gcc/read-md.c
===================================================================
--- gcc/read-md.c	2010-05-29 07:56:54.000000000 +0100
+++ gcc/read-md.c	2010-05-29 07:58:22.000000000 +0100
@@ -847,6 +847,14 @@ handle_enum (int lineno, bool md_p)
     }
 }
 
+/* Try to find the definition of the given enum.  Return null on failure.  */
+
+struct enum_type *
+lookup_enum_type (const char *name)
+{
+  return (struct enum_type *) htab_find (enum_types, &name);
+}
+
 /* For every enum definition, call CALLBACK with two arguments:
    a pointer to the constant definition and INFO.  Stop when CALLBACK
    returns zero.  */
Index: gcc/genattr.c
===================================================================
--- gcc/genattr.c	2010-05-29 07:55:59.000000000 +0100
+++ gcc/genattr.c	2010-05-29 07:58:22.000000000 +0100
@@ -49,27 +49,33 @@ gen_attr (rtx attr)
   printf ("#define HAVE_ATTR_%s\n", XSTR (attr, 0));
 
   /* If numeric attribute, don't need to write an enum.  */
-  p = XSTR (attr, 1);
-  if (*p == '\0')
-    printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
-	    (is_const ? "void" : "rtx"));
+  if (GET_CODE (attr) == DEFINE_ENUM_ATTR)
+    printf ("extern enum %s get_attr_%s (%s);\n\n",
+	    XSTR (attr, 1), XSTR (attr, 0), (is_const ? "void" : "rtx"));
   else
     {
-      printf ("enum attr_%s {", XSTR (attr, 0));
-
-      while ((tag = scan_comma_elt (&p)) != 0)
+      p = XSTR (attr, 1);
+      if (*p == '\0')
+	printf ("extern int get_attr_%s (%s);\n", XSTR (attr, 0),
+		(is_const ? "void" : "rtx"));
+      else
 	{
-	  write_upcase (XSTR (attr, 0));
-	  putchar ('_');
-	  while (tag != p)
-	    putchar (TOUPPER (*tag++));
-	  if (*p == ',')
-	    fputs (", ", stdout);
-	}
+	  printf ("enum attr_%s {", XSTR (attr, 0));
 
-      fputs ("};\n", stdout);
-      printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
-	      XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
+	  while ((tag = scan_comma_elt (&p)) != 0)
+	    {
+	      write_upcase (XSTR (attr, 0));
+	      putchar ('_');
+	      while (tag != p)
+		putchar (TOUPPER (*tag++));
+	      if (*p == ',')
+		fputs (", ", stdout);
+	    }
+	  fputs ("};\n", stdout);
+
+	  printf ("extern enum attr_%s get_attr_%s (%s);\n\n",
+		  XSTR (attr, 0), XSTR (attr, 0), (is_const ? "void" : "rtx"));
+	}
     }
 
   /* If `length' attribute, write additional function definitions and define
@@ -122,7 +128,8 @@ main (int argc, char **argv)
       if (desc == NULL)
 	break;
 
-      if (GET_CODE (desc) == DEFINE_ATTR)
+      if (GET_CODE (desc) == DEFINE_ATTR
+	  || GET_CODE (desc) == DEFINE_ENUM_ATTR)
 	gen_attr (desc);
 
       else if (GET_CODE (desc) == DEFINE_DELAY)
Index: gcc/genattrtab.c
===================================================================
--- gcc/genattrtab.c	2010-05-29 07:55:59.000000000 +0100
+++ gcc/genattrtab.c	2010-05-29 07:58:22.000000000 +0100
@@ -171,6 +171,7 @@ struct attr_value
 struct attr_desc
 {
   char *name;			/* Name of attribute.  */
+  const char *enum_name;	/* Enum name for DEFINE_ENUM_NAME.  */
   struct attr_desc *next;	/* Next attribute.  */
   struct attr_value *first_value; /* First value of this attribute.  */
   struct attr_value *default_val; /* Default value for this attribute.  */
@@ -1901,11 +1902,13 @@ make_alternative_compare (int mask)
    computation.  If a test condition involves an address, we leave the EQ_ATTR
    intact because addresses are only valid for the `length' attribute.
 
-   EXP is the EQ_ATTR expression and VALUE is the value of that attribute
-   for the insn corresponding to INSN_CODE and INSN_INDEX.  */
+   EXP is the EQ_ATTR expression and ATTR is the attribute to which
+   it refers.  VALUE is the value of that attribute for the insn
+   corresponding to INSN_CODE and INSN_INDEX.  */
 
 static rtx
-evaluate_eq_attr (rtx exp, rtx value, int insn_code, int insn_index)
+evaluate_eq_attr (rtx exp, struct attr_desc *attr, rtx value,
+		  int insn_code, int insn_index)
 {
   rtx orexp, andexp;
   rtx right;
@@ -1923,16 +1926,12 @@ evaluate_eq_attr (rtx exp, rtx value, in
 
     case SYMBOL_REF:
       {
-	char *p;
-	char string[256];
+	const char *prefix;
+	char *string, *p;
 
 	gcc_assert (GET_CODE (exp) == EQ_ATTR);
-	gcc_assert (strlen (XSTR (exp, 0)) + strlen (XSTR (exp, 1)) + 2
-		    <= 256);
-
-	strcpy (string, XSTR (exp, 0));
-	strcat (string, "_");
-	strcat (string, XSTR (exp, 1));
+	prefix = attr->enum_name ? attr->enum_name : attr->name;
+	string = ACONCAT ((prefix, "_", XSTR (exp, 1), NULL));
 	for (p = string; *p; p++)
 	  *p = TOUPPER (*p);
 
@@ -1966,7 +1965,7 @@ evaluate_eq_attr (rtx exp, rtx value, in
 	  right = insert_right_side (AND, andexp, this_cond,
 				     insn_code, insn_index);
 	  right = insert_right_side (AND, right,
-				     evaluate_eq_attr (exp,
+				     evaluate_eq_attr (exp, attr,
 						       XVECEXP (value, 0,
 								i + 1),
 						       insn_code, insn_index),
@@ -1982,7 +1981,7 @@ evaluate_eq_attr (rtx exp, rtx value, in
 
       /* Handle the default case.  */
       right = insert_right_side (AND, andexp,
-				 evaluate_eq_attr (exp, XEXP (value, 1),
+				 evaluate_eq_attr (exp, attr, XEXP (value, 1),
 						   insn_code, insn_index),
 				 insn_code, insn_index);
       newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
@@ -2732,7 +2731,8 @@ simplify_test_exp (rtx exp, int insn_cod
 	  if (av)
 	    {
 	    got_av:
-	      x = evaluate_eq_attr (exp, av->value, insn_code, insn_index);
+	      x = evaluate_eq_attr (exp, attr, av->value,
+				    insn_code, insn_index);
 	      x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index);
 	      if (attr_rtx_cost(x) < 20)
 		return x;
@@ -2900,13 +2900,30 @@ clear_struct_flag (rtx x)
     }
 }
 
-/* Create table entries for DEFINE_ATTR.  */
+/* Add attribute value NAME to the beginning of ATTR's list.  */
+
+static void
+add_attr_value (struct attr_desc *attr, const char *name)
+{
+  struct attr_value *av;
+
+  av = oballoc (struct attr_value);
+  av->value = attr_rtx (CONST_STRING, name);
+  av->next = attr->first_value;
+  attr->first_value = av;
+  av->first_insn = NULL;
+  av->num_insns = 0;
+  av->has_asm_insn = 0;
+}
+
+/* Create table entries for DEFINE_ATTR or DEFINE_ENUM_ATTR.  */
 
 static void
 gen_attr (rtx exp, int lineno)
 {
+  struct enum_type *et;
+  struct enum_value *ev;
   struct attr_desc *attr;
-  struct attr_value *av;
   const char *name_ptr;
   char *p;
 
@@ -2922,21 +2939,23 @@ gen_attr (rtx exp, int lineno)
     }
   attr->lineno = lineno;
 
-  if (*XSTR (exp, 1) == '\0')
+  if (GET_CODE (exp) == DEFINE_ENUM_ATTR)
+    {
+      attr->enum_name = XSTR (exp, 1);
+      et = lookup_enum_type (XSTR (exp, 1));
+      if (!et || !et->md_p)
+	error_with_line (lineno, "No define_enum called `%s' defined",
+			 attr->name);
+      for (ev = et->values; ev; ev = ev->next)
+	add_attr_value (attr, ev->name);
+    }
+  else if (*XSTR (exp, 1) == '\0')
     attr->is_numeric = 1;
   else
     {
       name_ptr = XSTR (exp, 1);
       while ((p = next_comma_elt (&name_ptr)) != NULL)
-	{
-	  av = oballoc (struct attr_value);
-	  av->value = attr_rtx (CONST_STRING, p);
-	  av->next = attr->first_value;
-	  attr->first_value = av;
-	  av->first_insn = NULL;
-	  av->num_insns = 0;
-	  av->has_asm_insn = 0;
-	}
+	add_attr_value (attr, p);
     }
 
   if (GET_CODE (XEXP (exp, 2)) == CONST)
@@ -3319,8 +3338,8 @@ write_test_expr (rtx exp, int flags)
       /* Now is the time to expand the value of a constant attribute.  */
       if (attr->is_const)
 	{
-	  write_test_expr (evaluate_eq_attr (exp, attr->default_val->value,
-					     -2, -2),
+	  write_test_expr (evaluate_eq_attr (exp, attr,
+					     attr->default_val->value, -2, -2),
 			   flags);
 	}
       else
@@ -3612,7 +3631,9 @@ write_attr_get (struct attr_desc *attr)
 
   /* Write out start of function, then all values with explicit `case' lines,
      then a `default', then the value with the most uses.  */
-  if (!attr->is_numeric)
+  if (attr->enum_name)
+    printf ("enum %s\n", attr->enum_name);
+  else if (!attr->is_numeric)
     printf ("enum attr_%s\n", attr->name);
   else
     printf ("int\n");
@@ -3869,7 +3890,7 @@ write_attr_valueq (struct attr_desc *att
     }
   else
     {
-      write_upcase (attr->name);
+      write_upcase (attr->enum_name ? attr->enum_name : attr->name);
       printf ("_");
       write_upcase (s);
     }
@@ -4133,6 +4154,7 @@ find_attr (const char **name_p, int crea
 
   attr = oballoc (struct attr_desc);
   attr->name = DEF_ATTR_STRING (name);
+  attr->enum_name = 0;
   attr->first_value = attr->default_val = NULL;
   attr->is_numeric = attr->is_const = attr->is_special = 0;
   attr->next = attrs[index];
@@ -4459,6 +4481,7 @@ main (int argc, char **argv)
 	  break;
 
 	case DEFINE_ATTR:
+	case DEFINE_ENUM_ATTR:
 	  gen_attr (desc, lineno);
 	  break;
 
Index: gcc/gensupport.c
===================================================================
--- gcc/gensupport.c	2010-05-29 07:55:59.000000000 +0100
+++ gcc/gensupport.c	2010-05-29 07:58:22.000000000 +0100
@@ -173,6 +173,7 @@ process_rtx (rtx desc, int lineno)
       break;
 
     case DEFINE_ATTR:
+    case DEFINE_ENUM_ATTR:
       queue_pattern (desc, &define_attr_tail, read_md_filename, lineno);
       break;
 
Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	2010-05-29 07:56:54.000000000 +0100
+++ gcc/config/mips/mips.h	2010-05-29 07:58:22.000000000 +0100
@@ -3040,10 +3040,6 @@ #define CPU_UNITS_QUERY 1
 #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS)	\
   mips_final_prescan_insn (INSN, OPVEC, NOPERANDS)
 
-/* This is necessary to avoid a warning about comparing different enum
-   types.  */
-#define mips_tune_attr ((enum attr_cpu) mips_tune)
-
 /* As on most targets, we want the .eh_frame section to be read-only where
    possible.  And as on most targets, this means two things:
 
Index: gcc/config/mips/mips.md
===================================================================
--- gcc/config/mips/mips.md	2010-05-29 07:56:54.000000000 +0100
+++ gcc/config/mips/mips.md	2010-05-29 07:58:22.000000000 +0100
@@ -508,11 +508,9 @@ (define_attr "length" ""
 	  (symbol_ref "mips_sync_loop_insns (insn, operands) * 4")
 	  ] (const_int 4)))
 
-;; Attribute describing the processor.  This attribute must match exactly
-;; with the processor enumeration above.
-(define_attr "cpu"
-  "r3000,4kc,4kp,5kc,5kf,20kc,24kc,24kf2_1,24kf1_1,74kc,74kf2_1,74kf1_1,74kf3_2,loongson_2e,loongson_2f,m4k,octeon,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,r10000,sb1,sb1a,sr71000,xlr"
-  (const (symbol_ref "mips_tune_attr")))
+;; Attribute describing the processor.
+(define_enum_attr "cpu" "processor"
+  (const (symbol_ref "mips_tune")))
 
 ;; The type of hardware hazard associated with this instruction.
 ;; DELAY means that the next instruction cannot read the result

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]