This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
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