summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog142
-rw-r--r--gcc/config/mips/loongson.md25
-rw-r--r--gcc/config/mips/loongson2ef.md7
-rw-r--r--gcc/config/mips/mips-dsp.md72
-rw-r--r--gcc/config/mips/mips-dspr2.md52
-rw-r--r--gcc/config/mips/mips-ps-3d.md24
-rw-r--r--gcc/config/mips/mips.c7
-rw-r--r--gcc/config/mips/mips.h53
-rw-r--r--gcc/config/mips/mips.md350
-rw-r--r--gcc/config/mips/sync.md12
-rw-r--r--gcc/doc/md.texi82
-rw-r--r--gcc/genconstants.c37
-rw-r--r--gcc/read-md.c179
-rw-r--r--gcc/read-md.h45
14 files changed, 764 insertions, 323 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1aab743ff68..f4630c7c410 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,147 @@
2010-06-10 Richard Sandiford <rdsandiford@googlemail.com>
+ * 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".
+
+2010-06-10 Richard Sandiford <rdsandiford@googlemail.com>
+
* configure.ac (tm_include_list): Add insn-constants.h.
* configure: Regenerate.
* Makefile.in (GTM_H): Move insn-constants.h here from...
diff --git a/gcc/config/mips/loongson.md b/gcc/config/mips/loongson.md
index f952cf672ee..10703bb7b08 100644
--- a/gcc/config/mips/loongson.md
+++ b/gcc/config/mips/loongson.md
@@ -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.
diff --git a/gcc/config/mips/loongson2ef.md b/gcc/config/mips/loongson2ef.md
index df3de33f809..1238f20ecae 100644
--- a/gcc/config/mips/loongson2ef.md
+++ b/gcc/config/mips/loongson2ef.md
@@ -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")
diff --git a/gcc/config/mips/mips-dsp.md b/gcc/config/mips/mips-dsp.md
index 9e02f7214f9..faa22bdd364 100644
--- a/gcc/config/mips/mips-dsp.md
+++ b/gcc/config/mips/mips-dsp.md
@@ -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)
diff --git a/gcc/config/mips/mips-dspr2.md b/gcc/config/mips/mips-dspr2.md
index 52495d43daa..9c3cbd58435 100644
--- a/gcc/config/mips/mips-dspr2.md
+++ b/gcc/config/mips/mips-dspr2.md
@@ -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")
diff --git a/gcc/config/mips/mips-ps-3d.md b/gcc/config/mips/mips-ps-3d.md
index c13c7a69b28..780fb03c706 100644
--- a/gcc/config/mips/mips-ps-3d.md
+++ b/gcc/config/mips/mips-ps-3d.md
@@ -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
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index a699238ba1c..29f0f0b74f3 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -504,11 +504,11 @@ struct mips_asm_switch mips_noat = { "at", 0 };
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 mips_rtx_cost_optimize_size = {
};
/* 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 */
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 5ecd59dfd74..4d791023f14 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -28,53 +28,6 @@ along with GCC; see the file COPYING3. If not see
/* 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;
@@ -3065,8 +3018,8 @@ extern int mips_dbx_regno[];
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;
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index a8543274328..0f287755891 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -23,247 +23,119 @@
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
+(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
+])
+
(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)
-
- (TLS_GET_TP_REGNUM 3)
+ [(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 @@
] (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 @@
; ST-Microelectronics Loongson-2E/2F-specific patterns.
(include "loongson.md")
+
+(define_c_enum "unspec" [
+ UNSPEC_ADDRESS_FIRST
+])
diff --git a/gcc/config/mips/sync.md b/gcc/config/mips/sync.md
index e28f56c601a..ee41d2c9740 100644
--- a/gcc/config/mips/sync.md
+++ b/gcc/config/mips/sync.md
@@ -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])
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index fb3a4c1bc73..990863acccc 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -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
diff --git a/gcc/genconstants.c b/gcc/genconstants.c
index 60526bbf716..b16a88bc3ea 100644
--- a/gcc/genconstants.c
+++ b/gcc/genconstants.c
@@ -35,12 +35,40 @@ along with GCC; see the file COPYING3. If not see
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 */");
diff --git a/gcc/read-md.c b/gcc/read-md.c
index af9800f8e2d..90707b356d3 100644
--- a/gcc/read-md.c
+++ b/gcc/read-md.c
@@ -92,6 +92,9 @@ static size_t max_include_len;
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_directive)
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, bool (*parse_opt) (const char *),
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 ();
diff --git a/gcc/read-md.h b/gcc/read-md.h
index ebe47cc3737..94a5fbbc241 100644
--- a/gcc/read-md.h
+++ b/gcc/read-md.h
@@ -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);