[PATCH] vr-series processors

Eric Christopher echristo@redhat.com
Thu Aug 15 23:56:00 GMT 2002


This has config.sub changes and unfortunately bje is on vacation so I
don't want to check it in without approval for them. :(

I've used the last known email address I had for people. Updates are
welcome.

This was the work of a lot of people. I apologize if I missed anyone.
Please let me know if I missed you.

-eric

-- 
I don't want a pony, I want a rocket
powered jetpack!

2002-08-15  Eric Christopher  <echristo@redhat.com>
            Richard Sandiford <rsandifo@redhat.com>
	    Aldy Hernandez  <aldyh@redhat.com>
	    Graham Stott    <grahams@redhat.com>
	    Michael Meissner  <meissner@redhat.com>
	    Gavin Romig-Koch  <gavin@redhat.com>
	    Ken Raeburn  <raeburn@cygnus.com>
	    Alexandre Oliva <aoliva@redhat.com>

	* config.gcc (mips64vr-elf): New target.
	* config/mips/5400.md: New file.
	* config/mips/5500.md: Ditto.
	* config/mips/mips.md: Use them.
	(frsqrt): New.
	* config/mips/mips.c (vr4111, vr4121, vr4320, vr5400, vr5500): 	New
cpus.
	(mips_issue_rate): Use them.
	(mips_use_dfa_pipeline_interface): New function. Use for 5400 	and
5500.
	(TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE): Define. Use above.
	* config/mips/mips.h (vr4111, vr4121, vr4320, vr5400, vr5500): 	New
cpus.
	(TARGET_MIPSx): Use them.
	(TUNE_MIPSx): Ditto.
	(GETNATE_MULT3_SI): Ditto.
	(ISA_HAS_BRANCHLIKELY): Ditto.
	(ISA_HAS_CONDMOVE): Ditto.
	(ISA_HAS_NMADD_NMSUB): Ditto.
	(ISA_HAS_MULHI): New. Ditto.
	(ISA_HAS_MULS): Ditto.
	(ISA_HAS_MSAC): Ditto.
	(ISA_HAS_MACC): Ditto.
	(ISA_HAS_ROTR_SI): Ditto.
	(ISA_HAS_ROTR_DI): Ditto.
	(RTX_COSTS): Use.
-------------- next part --------------
Index: config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.238
diff -u -p -w -r1.238 config.gcc
--- config.gcc	12 Aug 2002 03:40:15 -0000	1.238
+++ config.gcc	16 Aug 2002 06:42:38 -0000
@@ -1911,6 +1911,11 @@ mips64-*-elf* | mips64el-*-elf*)
 	target_cpu_default="MASK_64BIT|MASK_FLOAT64|MASK_GAS"
 	tm_defines="MIPS_ISA_DEFAULT=3 MIPS_ABI_DEFAULT=ABI_O64"
 	;;
+mips64vr-*-elf* | mips64vrel-*-elf*)
+        tm_file="mips/vr.h ${tm_file} mips/elf64.h"
+        tm_defines="MIPS_ABI_DEFAULT=ABI_O64"
+        tmake_file=mips/t-vr
+        ;;
 mips64orion-*-elf* | mips64orionel-*-elf*)
 	tm_file="${tm_file} mips/elforion.h mips/elf64.h"
 	tmake_file=mips/t-elf
Index: config/mips/5400.md
===================================================================
RCS file: config/mips/5400.md
diff -N config/mips/5400.md
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ config/mips/5400.md	16 Aug 2002 06:42:41 -0000
@@ -0,0 +1,170 @@
+;; DFA-based pipeline description for 5400
+(define_automaton "vr54")
+(define_cpu_unit "vr54_dp0"     "vr54")
+(define_cpu_unit "vr54_dp1"     "vr54")
+(define_cpu_unit "vr54_mem"     "vr54")
+(define_cpu_unit "vr54_mac"     "vr54")
+
+;;
+;; The ordering of the instruction-execution-path/resource-usage
+;; descriptions (also known as reservation RTL) is roughly ordered
+;; based on the define attribute RTL for the "type" classification.
+;; When modifying, remember that the first test that matches is the
+;; reservation used!
+;;
+
+(define_insn_reservation "ir_vr54_unknown" 1
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "unknown"))
+  "vr54_dp0+vr54_dp1+vr54_mem+vr54_mac")
+
+;; Assume prediction fails.
+(define_insn_reservation "ir_vr54_branch" 3
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "branch,jump,call"))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_load" 2
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "load")
+            (eq_attr "mode" "!SF,DF,FPSW")))
+  "vr54_mem")
+
+(define_insn_reservation "ir_vr54_store" 1
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "store")
+            (eq_attr "mode" "!SF,DF,FPSW")))
+  "vr54_mem")
+
+(define_insn_reservation "ir_vr54_fstore" 1
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "store")
+            (eq_attr "mode" "SF,DF")))
+  "vr54_mem")
+
+
+;; This reservation is for conditional move based on integer
+;; or floating point CC.  This could probably use some refinement
+;; as "move" type attr seems to be overloaded in rtl.
+(define_insn_reservation "ir_vr54_move" 4
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "move"))
+  "vr54_dp0|vr54_dp1")
+
+;; Move to/from FPU registers
+(define_insn_reservation "ir_vr54_xfer" 2
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "xfer"))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_hilo" 1
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "hilo"))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_arith" 1
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "arith,darith,icmp,nop"))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_imul_si" 3
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "imul")
+            (eq_attr "mode" "SI")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_imul_di" 4
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "imul")
+            (eq_attr "mode" "DI")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_imadd_si" 3
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "imul"))
+  "vr54_mac")
+
+(define_insn_reservation "ir_vr54_idiv_si" 42
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "idiv")
+            (eq_attr "mode" "SI")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_idiv_di" 74
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "idiv")
+            (eq_attr "mode" "DI")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fadd" 4
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "fadd"))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fmul_sf" 5
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "fmul")
+            (eq_attr "mode" "SF")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fmul_df" 6
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "fmul")
+            (eq_attr "mode" "DF")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fmadd_sf" 9
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "fmadd")
+            (eq_attr "mode" "SF")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fmadd_df" 10
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "fmadd")
+            (eq_attr "mode" "DF")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fdiv_sf" 42
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "fdiv,fsqrt")
+            (eq_attr "mode" "SF")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fdiv_df" 72
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "fdiv,fsqrt")
+            (eq_attr "mode" "DF")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fabs" 2
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "fabs,fneg"))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fcmp" 2
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "fcmp"))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fcvt" 6
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "fcvt"))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_frsqrt_sf" 61
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "frsqrt")
+            (eq_attr "mode" "SF")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_frsqrt_df" 121
+  (and (eq_attr "cpu" "r5400")
+       (and (eq_attr "type" "frsqrt")
+            (eq_attr "mode" "DF")))
+  "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_multi" 1
+  (and (eq_attr "cpu" "r5400")
+       (eq_attr "type" "multi"))
+  "vr54_dp0+vr54_dp1+vr54_mem+vr54_mac")
Index: config/mips/5500.md
===================================================================
RCS file: config/mips/5500.md
diff -N config/mips/5500.md
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ config/mips/5500.md	16 Aug 2002 06:42:41 -0000
@@ -0,0 +1,172 @@
+;; DFA-based pipeline description for 5500
+(define_automaton "vr55")
+(define_cpu_unit "vr55_dp0"     "vr55")
+(define_cpu_unit "vr55_dp1"     "vr55")
+(define_cpu_unit "vr55_mem"     "vr55")
+(define_cpu_unit "vr55_mac"     "vr55")
+(define_cpu_unit "vr55_fp"      "vr55")
+(define_cpu_unit "vr55_bru"     "vr55")
+
+;;
+;; The ordering of the instruction-execution-path/resource-usage
+;; descriptions (also known as reservation RTL) is roughly ordered
+;; based on the define attribute RTL for the "type" classification.
+;; When modifying, remember that the first test that matches is the
+;; reservation used!
+;;
+
+(define_insn_reservation "ir_vr55_unknown" 1
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "unknown"))
+  "vr55_dp0+vr55_dp1+vr55_mem+vr55_mac+vr55_fp+vr55_bru")
+
+;; Assume prediction fails.
+(define_insn_reservation "ir_vr55_branch" 2
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "branch,jump,call"))
+  "vr55_bru")
+
+(define_insn_reservation "ir_vr55_load" 3
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "load"))
+  "vr55_mem")
+
+(define_insn_reservation "ir_vr55_store" 1
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "store"))
+  "vr55_mem")
+
+;; This reservation is for conditional move based on integer
+;; or floating point CC.  This could probably use some refinement
+;; as "move" type attr seems to be overloaded in rtl.
+(define_insn_reservation "ir_vr55_move" 2
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "move"))
+  "vr55_dp0|vr55_dp1")
+
+;; Move to/from FPU registers
+(define_insn_reservation "ir_vr55_xfer" 2
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "xfer"))
+  "vr55_dp0|vr55_dp1")
+
+(define_insn_reservation "ir_vr55_hilo" 2
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "hilo"))
+  "vr55_dp0|vr55_dp1")
+
+(define_insn_reservation "ir_vr55_arith" 1
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "arith,darith,icmp,nop"))
+  "vr55_dp0|vr55_dp1")
+
+(define_insn_reservation "ir_vr55_imul_si" 3
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "imul")
+            (eq_attr "mode" "SI")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_imul_di" 4
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "imul")
+            (eq_attr "mode" "DI")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_imadd_si" 3
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "imul"))
+  "vr55_mac")
+
+;; Divide algorithm is early out with best latency of 7 pcycles.
+;; Use worst case for scheduling purposes.
+(define_insn_reservation "ir_vr55_idiv_si" 42
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "idiv")
+            (eq_attr "mode" "SI")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_idiv_di" 74
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "idiv")
+            (eq_attr "mode" "DI")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fadd" 4
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "fadd"))
+  "vr55_fp")
+
+(define_insn_reservation "ir_vr55_fmul_sf" 5
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "fmul")
+            (eq_attr "mode" "SF")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fmul_df" 6
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "fmul")
+            (eq_attr "mode" "DF")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fmadd_sf" 9
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "fmadd")
+            (eq_attr "mode" "SF")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fmadd_df" 10
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "fmadd")
+            (eq_attr "mode" "DF")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fdiv_sf" 30
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "fdiv,fsqrt")
+            (eq_attr "mode" "SF")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fdiv_df" 59
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "fdiv,fsqrt")
+            (eq_attr "mode" "DF")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fabs" 2
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "fabs,fneg"))
+  "vr55_fp")
+
+(define_insn_reservation "ir_vr55_fcmp" 2
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "fcmp"))
+  "vr55_fp")
+
+(define_insn_reservation "ir_vr55_fcvt_sf" 4
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "fcvt")
+            (eq_attr "mode" "SF")))
+  "vr55_fp")
+
+(define_insn_reservation "ir_vr55_fcvt_df" 6
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "fcvt")
+            (eq_attr "mode" "DF")))
+  "vr55_fp")
+
+(define_insn_reservation "ir_vr55_frsqrt_sf" 60
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "frsqrt")
+            (eq_attr "mode" "SF")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_frsqrt_df" 118
+  (and (eq_attr "cpu" "r5500")
+       (and (eq_attr "type" "frsqrt")
+            (eq_attr "mode" "DF")))
+  "vr55_mac")
+
+(define_insn_reservation "ir_vr55_multi" 1
+  (and (eq_attr "cpu" "r5500")
+       (eq_attr "type" "multi"))
+  "vr55_dp0+vr55_dp1+vr55_mem+vr55_mac+vr55_fp+vr55_bru")
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.224
diff -u -p -w -r1.224 mips.c
--- config/mips/mips.c	7 Aug 2002 02:57:53 -0000	1.224
+++ config/mips/mips.c	16 Aug 2002 06:42:41 -0000
@@ -149,6 +149,7 @@ static void mips_unique_section			PARAMS
 	ATTRIBUTE_UNUSED;
 static void mips_select_rtx_section PARAMS ((enum machine_mode, rtx,
 					     unsigned HOST_WIDE_INT));
+static int mips_use_dfa_pipeline_interface      PARAMS ((void));
 static void mips_encode_section_info		PARAMS ((tree, int));
 
 /* Structure to be filled in by compute_frame_size with register
@@ -592,7 +593,10 @@ const struct mips_cpu_info mips_cpu_info
   /* MIPS III */
   { "r4000", PROCESSOR_R4000, 3 },
   { "vr4100", PROCESSOR_R4100, 3 },
+  { "vr4111", PROCESSOR_R4100, 3 },
+  { "vr4121", PROCESSOR_R4121, 3 },
   { "vr4300", PROCESSOR_R4300, 3 },
+  { "vr4320", PROCESSOR_R4320, 3 },
   { "r4400", PROCESSOR_R4000, 3 }, /* = r4000 */
   { "r4600", PROCESSOR_R4600, 3 },
   { "orion", PROCESSOR_R4600, 3 }, /* = r4600 */
@@ -601,6 +605,9 @@ const struct mips_cpu_info mips_cpu_info
   /* MIPS IV */
   { "r8000", PROCESSOR_R8000, 4 },
   { "vr5000", PROCESSOR_R5000, 4 },
+  { "vr5400", PROCESSOR_R5400, 4 },
+  { "vr5500", PROCESSOR_R5500, 4 },
+
 
   /* MIPS 32 */
   { "4kc", PROCESSOR_R4KC, 32 },
@@ -645,6 +652,8 @@ const struct mips_cpu_info mips_cpu_info
 #define TARGET_SCHED_ADJUST_COST mips_adjust_cost
 #undef TARGET_SCHED_ISSUE_RATE
 #define TARGET_SCHED_ISSUE_RATE mips_issue_rate
+#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
+#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE mips_use_dfa_pipeline_interface
 
 #undef TARGET_ENCODE_SECTION_INFO
 #define TARGET_ENCODE_SECTION_INFO mips_encode_section_info
@@ -10455,8 +10464,9 @@ mips_issue_rate ()
 {
   switch (mips_tune)
     {
-    case PROCESSOR_R3000:
-      return 1;
+    case PROCESSOR_R3000: return 1;
+    case PROCESSOR_R5400: return 2;
+    case PROCESSOR_R5500: return 2;
 
     default:
       return 1;
@@ -10465,6 +10475,24 @@ mips_issue_rate ()
   abort ();
 
 }
+
+/* Implements TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE.  Return true for
+   processors that have a DFA pipeline description.  */
+
+static int
+mips_use_dfa_pipeline_interface ()
+{
+  switch (mips_tune)
+    {
+    case PROCESSOR_R5400:
+    case PROCESSOR_R5500:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
 
 const char *
 mips_emit_prefetch (operands)
Index: config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.212
diff -u -p -w -r1.212 mips.h
--- config/mips/mips.h	11 Aug 2002 06:20:08 -0000	1.212
+++ config/mips/mips.h	16 Aug 2002 06:42:41 -0000
@@ -63,10 +63,14 @@ enum processor_type {
   PROCESSOR_R6000,
   PROCESSOR_R4000,
   PROCESSOR_R4100,
+  PROCESSOR_R4121,
   PROCESSOR_R4300,
+  PROCESSOR_R4320,
   PROCESSOR_R4600,
   PROCESSOR_R4650,
   PROCESSOR_R5000,
+  PROCESSOR_R5400,
+  PROCESSOR_R5500,
   PROCESSOR_R8000,
   PROCESSOR_R4KC,
   PROCESSOR_R5KC,
@@ -351,10 +355,14 @@ extern void		sbss_section PARAMS ((void)
 /* Architecture target defines.  */
 #define TARGET_MIPS3900             (mips_arch == PROCESSOR_R3900)
 #define TARGET_MIPS4000             (mips_arch == PROCESSOR_R4000)
-#define TARGET_MIPS4100             (mips_arch == PROCESSOR_R4100)
+#define TARGET_MIPS4100             (mips_arch == PROCESSOR_R4100
+#define TARGET_MIPS4121             (mips_arch == PROCESSOR_R4121)
 #define TARGET_MIPS4300             (mips_arch == PROCESSOR_R4300)
+#define TARGET_MIPS4320             (mips_arch == PROCESSOR_R4320)
 #define TARGET_MIPS4KC              (mips_arch == PROCESSOR_R4KC)
 #define TARGET_MIPS5KC              (mips_arch == PROCESSOR_R5KC)
+#define TARGET_MIPS5400             (mips_arch == PROCESSOR_R5400)
+#define TARGET_MIPS5500             (mips_arch == PROCESSOR_R5500)
 #define TARGET_SB1                  (mips_arch == PROCESSOR_SB1)
 
 /* Scheduling target defines.  */
@@ -362,6 +370,8 @@ extern void		sbss_section PARAMS ((void)
 #define TUNE_MIPS3900               (mips_tune == PROCESSOR_R3900)
 #define TUNE_MIPS4000               (mips_tune == PROCESSOR_R4000)
 #define TUNE_MIPS5000               (mips_tune == PROCESSOR_R5000)
+#define TUNE_MIPS5400               (mips_tune == PROCESSOR_R5400)
+#define TUNE_MIPS5500               (mips_tune == PROCESSOR_R5500)
 #define TUNE_MIPS6000               (mips_tune == PROCESSOR_R6000)
 #define TUNE_SB1                    (mips_tune == PROCESSOR_SB1)
 
@@ -753,6 +763,9 @@ extern void		sbss_section PARAMS ((void)
 
 /* Generate three-operand multiply instructions for SImode.  */
 #define GENERATE_MULT3_SI       ((TARGET_MIPS3900                       \
+                                  || TARGET_MIPS4320                    \
+                                  || TARGET_MIPS5400                    \
+                                  || TARGET_MIPS5500                    \
                                   || ISA_MIPS32	                        \
                                   || ISA_MIPS64)                        \
                                  && !TARGET_MIPS16)
@@ -784,12 +797,14 @@ extern void		sbss_section PARAMS ((void)
 /* ISA has branch likely instructions (eg. mips2).  */
 /* Disable branchlikely for tx39 until compare rewrite.  They haven't
    been generated up to this point.  */
-#define ISA_HAS_BRANCHLIKELY	(!ISA_MIPS1)
+#define ISA_HAS_BRANCHLIKELY	(!ISA_MIPS1                             \
+				 && !TARGET_MIPS5500)
 
 /* ISA has the conditional move instructions introduced in mips4.  */
 #define ISA_HAS_CONDMOVE        ((ISA_MIPS4				\
 				  || ISA_MIPS32	                        \
 				  || ISA_MIPS64)			\
+                                 && !TARGET_MIPS5500                    \
 				 && !TARGET_MIPS16)
 
 /* ISA has just the integer condition move instructions (movn,movz) */
@@ -820,6 +835,7 @@ extern void		sbss_section PARAMS ((void)
 /* ISA has floating-point nmadd and nmsub instructions.  */
 #define ISA_HAS_NMADD_NMSUB	((ISA_MIPS4				\
 				  || ISA_MIPS64)       			\
+                                 && (!TARGET_MIPS5400 || TARGET_MAD)    \
 				 && ! TARGET_MIPS16)
 
 /* ISA has count leading zeroes/ones instruction (not implemented).  */
@@ -832,6 +848,41 @@ extern void		sbss_section PARAMS ((void)
 #define ISA_HAS_DCLZ_DCLO       (ISA_MIPS64				\
 				 && !TARGET_MIPS16)
 
+/* ISA has three operand multiply instructions that put
+   the high part in an accumulator: mulhi or mulhiu.  */
+#define ISA_HAS_MULHI           (TARGET_MIPS5400                        \
+                                 || TARGET_MIPS5500                     \
+                                 )
+
+/* ISA has three operand multiply instructions that
+   negates the result and puts the result in an accumulator.  */
+#define ISA_HAS_MULS            (TARGET_MIPS5400                        \
+                                 || TARGET_MIPS5500                     \
+                                 )
+
+/* ISA has three operand multiply instructions that subtracts the
+   result from a 4th operand and puts the result in an accumulator.  */
+#define ISA_HAS_MSAC            (TARGET_MIPS5400                        \
+                                 || TARGET_MIPS5500                     \
+                                 )
+/* ISA has three operand multiply instructions that  the result
+   from a 4th operand and puts the result in an accumulator.  */
+#define ISA_HAS_MACC            (TARGET_MIPS5400                        \
+                                 || TARGET_MIPS5500                     \
+                                 )
+
+/* ISA has 32-bit rotate right instruction.  */
+#define ISA_HAS_ROTR_SI         (TARGET_MIPS5400                        \
+                                 || TARGET_MIPS5500                     \
+                                 )
+
+/* ISA has 32-bit rotate right instruction.  */
+#define ISA_HAS_ROTR_DI         (TARGET_64BIT                           \
+                                 && (TARGET_MIPS5400                    \
+                                     || TARGET_MIPS5500                 \
+                                     ))
+
+
 /* ISA has data prefetch instruction.  */
 #define ISA_HAS_PREFETCH	((ISA_MIPS4				\
 				  || ISA_MIPS32				\
@@ -3517,7 +3568,9 @@ typedef struct mips_args {
 	      || TUNE_MIPS3900						\
 	      || TUNE_MIPS5000)						\
 	    return COSTS_N_INSNS (4);					\
-	  else if (TUNE_MIPS6000)					\
+	  else if (TUNE_MIPS6000                                        \
+		   || TUNE_MIPS5400                                     \
+		   || TUNE_MIPS5500)					\
 	    return COSTS_N_INSNS (5);					\
 	  else								\
 	    return COSTS_N_INSNS (7);					\
@@ -3529,7 +3582,9 @@ typedef struct mips_args {
 	      || TUNE_MIPS3900						\
 	      || TUNE_MIPS5000)						\
 	    return COSTS_N_INSNS (5);					\
-	  else if (TUNE_MIPS6000)					\
+	  else if (TUNE_MIPS6000                                        \
+		   || TUNE_MIPS5400                                     \
+		   || TUNE_MIPS5500)					\
 	    return COSTS_N_INSNS (6);					\
 	  else								\
 	    return COSTS_N_INSNS (8);					\
@@ -3539,6 +3594,8 @@ typedef struct mips_args {
 	return COSTS_N_INSNS (12);					\
       else if (TUNE_MIPS3900)						\
 	return COSTS_N_INSNS (2);					\
+     else if (TUNE_MIPS5400 || TUNE_MIPS5500)                           \
+        return COSTS_N_INSNS ((xmode == DImode) ? 4 : 3);               \
       else if (TUNE_MIPS6000)						\
 	return COSTS_N_INSNS (17);					\
       else if (TUNE_MIPS5000)						\
@@ -3558,6 +3615,8 @@ typedef struct mips_args {
 	    return COSTS_N_INSNS (12);					\
 	  else if (TUNE_MIPS6000)					\
 	    return COSTS_N_INSNS (15);					\
+         else if (TUNE_MIPS5400 || TUNE_MIPS5500)                       \
+            return COSTS_N_INSNS (30);                                  \
 	  else								\
 	    return COSTS_N_INSNS (23);					\
 	}								\
@@ -3567,6 +3626,8 @@ typedef struct mips_args {
 	  if (TUNE_MIPS3000						\
               || TUNE_MIPS3900)						\
 	    return COSTS_N_INSNS (19);					\
+          else if (TUNE_MIPS5400 || TUNE_MIPS5500)                      \
+            return COSTS_N_INSNS (59);                                  \
 	  else if (TUNE_MIPS6000)					\
 	    return COSTS_N_INSNS (16);					\
 	  else								\
@@ -3584,6 +3645,8 @@ typedef struct mips_args {
       return COSTS_N_INSNS (38);					\
     else if (TUNE_MIPS5000)						\
       return COSTS_N_INSNS (36);					\
+    else if (TUNE_MIPS5400 || TUNE_MIPS5500)                            \
+      return COSTS_N_INSNS ((GET_MODE (X) == SImode) ? 42 : 74);        \
     else								\
       return COSTS_N_INSNS (69);					\
 									\
Index: config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v
retrieving revision 1.140
diff -u -p -w -r1.140 mips.md
--- config/mips/mips.md	7 Aug 2002 17:42:56 -0000	1.140
+++ config/mips/mips.md	16 Aug 2002 06:42:42 -0000
@@ -80,11 +80,12 @@
 ;; fcmp		floating point compare
 ;; fcvt		floating point convert
 ;; fsqrt	floating point square root
+;; frsqrt       floating point reciprocal square root
 ;; multi	multiword sequence (or user asm statements)
 ;; nop		no operation
 
 (define_attr "type"
-  "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,imadd,idiv,icmp,fadd,fmul,fmadd,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,multi,nop"
+  "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,imadd,idiv,icmp,fadd,fmul,fmadd,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,frsqrt,multi,nop"
   (const_string "unknown"))
 
 ;; Main data type used by the insn
@@ -121,7 +122,7 @@
 
 ;; ??? Fix everything that tests this attribute.
 (define_attr "cpu"
-  "default,r3000,r3900,r6000,r4000,r4100,r4300,r4600,r4650,r5000,r8000,r4kc,r5kc,r20kc"
+  "default,r3000,r3900,r6000,r4000,r4100,r4121,r4300,r4320,r4600,r4650,r5000,r5400,r5500,r8000,r4kc,r5kc,r20kc"
   (const (symbol_ref "mips_cpu_attr")))
 
 ;; Does the instruction have a mandatory delay slot?
@@ -206,12 +207,12 @@
 
 (define_function_unit "memory" 1 0
   (and (eq_attr "type" "load")
-       (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4100,r4300,r5000"))
+       (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4100,r4121,r4300,r4320,r5000"))
   3 0)
 
 (define_function_unit "memory" 1 0
   (and (eq_attr "type" "load")
-       (eq_attr "cpu" "r3000,r3900,r4600,r4650,r4100,r4300,r5000"))
+       (eq_attr "cpu" "r3000,r3900,r4600,r4650,r4100,r4121,r4300,r4320,r5000"))
   2 0)
 
 (define_function_unit "memory"   1 0 (eq_attr "type" "store") 1 0)
@@ -224,7 +225,7 @@
 
 (define_function_unit "imuldiv"  1 0
   (and (eq_attr "type" "imul,imadd")
-       (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000"))
+       (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4121,r4300,r4320,r5000"))
   17 17)
 
 ;; On them mips16, we want to stronly discourage a mult from appearing
@@ -251,22 +252,22 @@
 
 (define_function_unit "imuldiv"  1 0
   (and (eq_attr "type" "imul,imadd")
-       (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100")))
+       (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100,r4121")))
   1 1)
 
 (define_function_unit "imuldiv"  1 0
   (and (eq_attr "type" "imul,imadd")
-       (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100")))
+       (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100,r4121")))
   4 4)
 
 (define_function_unit "imuldiv"  1 0
   (and (eq_attr "type" "imul,imadd")
-       (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300,r5000")))
+       (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300,r4320,r5000")))
   5 5)
 
 (define_function_unit "imuldiv"  1 0
   (and (eq_attr "type" "imul,imadd")
-       (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300")))
+       (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300,r4320")))
   8 8)
 
 (define_function_unit "imuldiv"  1 0
@@ -276,7 +277,7 @@
 
 (define_function_unit "imuldiv"  1 0
   (and (eq_attr "type" "idiv")
-       (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000"))
+       (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4121,r4300,r4320,r5000"))
   38 38)
 
 (define_function_unit "imuldiv"  1 0
@@ -297,22 +298,22 @@
 
 (define_function_unit "imuldiv" 1 0
   (and (eq_attr "type" "idiv")
-       (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100")))
+       (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100,r4121")))
   35 35)
 
 (define_function_unit "imuldiv" 1 0
   (and (eq_attr "type" "idiv")
-       (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100")))
+       (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100,r4121")))
   67 67)
 
 (define_function_unit "imuldiv" 1 0
   (and (eq_attr "type" "idiv")
-       (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300")))
+       (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300,r4320")))
   37 37)
 
 (define_function_unit "imuldiv" 1 0
   (and (eq_attr "type" "idiv")
-       (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300")))
+       (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300,r4320")))
   69 69)
 
 (define_function_unit "imuldiv" 1 0
@@ -333,7 +334,7 @@
 ;; instructions to be processed in the "imuldiv" unit.
 
 (define_function_unit "adder" 1 1
-  (and (eq_attr "type" "fcmp") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000"))
+  (and (eq_attr "type" "fcmp") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r4320,r5000"))
   3 0)
 
 (define_function_unit "adder" 1 1
@@ -345,7 +346,7 @@
   1 0)
 
 (define_function_unit "adder" 1 1
-  (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r3900,r6000,r4300"))
+  (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r4320"))
   4 0)
 
 (define_function_unit "adder" 1 1
@@ -358,7 +359,7 @@
 
 (define_function_unit "adder" 1 1
   (and (eq_attr "type" "fabs,fneg")
-       (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4300,r5000"))
+       (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4300,r4320,r5000"))
   2 0)
 
 (define_function_unit "adder" 1 1
@@ -368,7 +369,7 @@
 (define_function_unit "mult" 1 1
   (and (eq_attr "type" "fmul")
        (and (eq_attr "mode" "SF")
-	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000")))
+	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r4320,r5000")))
   7 0)
 
 (define_function_unit "mult" 1 1
@@ -388,7 +389,7 @@
 
 (define_function_unit "mult" 1 1
   (and (eq_attr "type" "fmul")
-       (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000")))
+       (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r4320,r5000")))
   8 0)
 
 (define_function_unit "mult" 1 1
@@ -404,7 +405,7 @@
 (define_function_unit "divide" 1 1
   (and (eq_attr "type" "fdiv")
        (and (eq_attr "mode" "SF")
-	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000")))
+	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r4320,r5000")))
   23 0)
 
 (define_function_unit "divide" 1 1
@@ -430,7 +431,7 @@
 (define_function_unit "divide" 1 1
   (and (eq_attr "type" "fdiv")
        (and (eq_attr "mode" "DF")
-	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300")))
+	    (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r4320")))
   36 0)
 
 (define_function_unit "divide" 1 1
@@ -450,33 +451,33 @@
 
 ;;; ??? Is this number right?
 (define_function_unit "divide" 1 1
-  (and (eq_attr "type" "fsqrt")
-       (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000")))
+  (and (eq_attr "type" "fsqrt,frsqrt")
+       (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650,r4300,r4320,r5000")))
   54 0)
 
 (define_function_unit "divide" 1 1
-  (and (eq_attr "type" "fsqrt")
+  (and (eq_attr "type" "fsqrt,frsqrt")
        (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
   31 0)
 
 (define_function_unit "divide" 1 1
-  (and (eq_attr "type" "fsqrt")
+  (and (eq_attr "type" "fsqrt,frsqrt")
        (and (eq_attr "mode" "SF") (eq_attr "cpu" "r5000")))
   21 0)
 
 ;;; ??? Is this number right?
 (define_function_unit "divide" 1 1
-  (and (eq_attr "type" "fsqrt")
-       (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000")))
+  (and (eq_attr "type" "fsqrt,frsqrt")
+       (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650,r4300,r4320,r5000")))
   112 0)
 
 (define_function_unit "divide" 1 1
-  (and (eq_attr "type" "fsqrt")
+  (and (eq_attr "type" "fsqrt,frsqrt")
        (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650")))
   60 0)
 
 (define_function_unit "divide" 1 1
-  (and (eq_attr "type" "fsqrt")
+  (and (eq_attr "type" "fsqrt,frsqrt")
        (and (eq_attr "mode" "DF") (eq_attr "cpu" "r5000")))
   36 0)
 
@@ -484,27 +485,27 @@
 ;; functional unit:
 
 (define_function_unit "imuldiv" 1 0
-  (and (eq_attr "type" "fadd") (eq_attr "cpu" "r4300"))
+  (and (eq_attr "type" "fadd") (eq_attr "cpu" "r4300,r4320"))
   3 3)
 
 (define_function_unit "imuldiv" 1 0
-  (and (eq_attr "type" "fcmp,fabs,fneg") (eq_attr "cpu" "r4300"))
+  (and (eq_attr "type" "fcmp,fabs,fneg") (eq_attr "cpu" "r4300,r4320"))
   1 1)
 
 (define_function_unit "imuldiv" 1 0
-  (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300")))
+  (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300,r4320")))
   5 5)
 (define_function_unit "imuldiv" 1 0
-  (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300")))
+  (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300,r4320")))
   8 8)
 
 (define_function_unit "imuldiv" 1 0
-  (and (and (eq_attr "type" "fdiv") (eq_attr "type" "fsqrt"))
-       (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300")))
+  (and (and (eq_attr "type" "fdiv") (eq_attr "type" "fsqrt,frsqrt"))
+       (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300,r4320")))
   29 29)
 (define_function_unit "imuldiv" 1 0
-  (and (and (eq_attr "type" "fdiv") (eq_attr "type" "fsqrt"))
-       (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300")))
+  (and (and (eq_attr "type" "fdiv") (eq_attr "type" "fsqrt,frsqrt"))
+       (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300,r4320")))
   58 58)
 
 ;; The following functional units do not use the cpu type, and use
@@ -533,6 +534,12 @@
 ;; (define_function_unit "sqrt"     1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF"))  54 0)
 ;; (define_function_unit "sqrt"     1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 0)
 
+;; Include scheduling descriptions.
+
+(include "5400.md")
+(include "5500.md")
+
+
 ;;
 ;;  ....................
 ;;
@@ -1686,7 +1693,8 @@
   "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
   "
 {
-  if (!TARGET_MIPS4300)
+  if (!TARGET_MIPS4300
+      && !TARGET_MIPS4320)
     emit_insn (gen_muldf3_internal (operands[0], operands[1], operands[2]));
   else
     emit_insn (gen_muldf3_r4300 (operands[0], operands[1], operands[2]));
@@ -1697,7 +1705,8 @@
   [(set (match_operand:DF 0 "register_operand" "=f")
 	(mult:DF (match_operand:DF 1 "register_operand" "f")
 		 (match_operand:DF 2 "register_operand" "f")))]
-  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_MIPS4300"
+  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
+   && !TARGET_MIPS4300 &&!TARGET_MIPS4320"
   "mul.d\\t%0,%1,%2"
   [(set_attr "type"	"fmul")
    (set_attr "mode"	"DF")])
@@ -1706,7 +1715,8 @@
   [(set (match_operand:DF 0 "register_operand" "=f")
 	(mult:DF (match_operand:DF 1 "register_operand" "f")
 		 (match_operand:DF 2 "register_operand" "f")))]
-  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_MIPS4300"
+  "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT
+   && (TARGET_MIPS4300 || TARGET_MIPS4320)"
   "*
 {
   output_asm_insn (\"mul.d\\t%0,%1,%2\", operands);
@@ -1725,7 +1735,7 @@
   "TARGET_HARD_FLOAT"
   "
 {
-  if (!TARGET_MIPS4300)
+  if (!TARGET_MIPS4300 && !TARGET_MIPS4320)
     emit_insn( gen_mulsf3_internal (operands[0], operands[1], operands[2]));
   else
     emit_insn( gen_mulsf3_r4300 (operands[0], operands[1], operands[2]));
@@ -1736,7 +1746,8 @@
   [(set (match_operand:SF 0 "register_operand" "=f")
 	(mult:SF (match_operand:SF 1 "register_operand" "f")
 		 (match_operand:SF 2 "register_operand" "f")))]
-  "TARGET_HARD_FLOAT && !TARGET_MIPS4300"
+  "TARGET_HARD_FLOAT
+   && !TARGET_MIPS4300 && !TARGET_MIPS4320"
   "mul.s\\t%0,%1,%2"
   [(set_attr "type"	"fmul")
    (set_attr "mode"	"SF")])
@@ -1745,7 +1756,8 @@
   [(set (match_operand:SF 0 "register_operand" "=f")
 	(mult:SF (match_operand:SF 1 "register_operand" "f")
 		 (match_operand:SF 2 "register_operand" "f")))]
-  "TARGET_HARD_FLOAT && TARGET_MIPS4300"
+  "TARGET_HARD_FLOAT
+   && (TARGET_MIPS4300 || TARGET_MIPS4320)"
   "*
 {
   output_asm_insn (\"mul.s\\t%0,%1,%2\", operands);
@@ -1794,6 +1806,9 @@
   if (which_alternative == 1)
     return \"mult\\t%1,%2\";
   if (TARGET_MAD
+      || TARGET_MIPS5400
+      || TARGET_MIPS5500
+      || TARGET_MIPS4320
       || ISA_MIPS32
       || ISA_MIPS64)
     return \"mul\\t%0,%1,%2\";
@@ -1858,15 +1873,34 @@
    (clobber (match_scratch:SI 6 "=a,a,a"))
    (clobber (match_scratch:SI 7 "=X,X,d"))]
   "(TARGET_MIPS3900
+   || TARGET_MIPS4320
+   || TARGET_MIPS5400
+   || TARGET_MIPS5500
    || ISA_HAS_MADD_MSUB)
    && !TARGET_MIPS16"
   "*
 {
   static const char *const madd[] = { \"madd\\t%1,%2\", \"madd\\t%0,%1,%2\" };
+  static const char *const macc[] = { \"macc\\t$0,%1,%2\", \"macc\\t%0,%1,%2\" };
   if (which_alternative == 2)
     return \"#\";
   if (ISA_HAS_MADD_MSUB && which_alternative != 0)
     return \"#\";
+
+  if (TARGET_MIPS5400)
+    return macc[which_alternative];
+
+  if (TARGET_MIPS5500)
+    {
+      if (which_alternative == 0)
+        return madd[0];
+      else
+        return macc[which_alternative];
+    }
+
+  if (TARGET_MIPS4320)
+    return macc[which_alternative];
+
   return madd[which_alternative];
 }"
   [(set_attr "type"	"imadd,imadd,multi")
@@ -1917,6 +1951,62 @@
    (set (match_dup 0) (match_dup 3))]
   "")
 
+;; "macc" stores the product in both LO and a general purpose register.
+;; Rather than asking reload to choose one or the other, we tell it
+;; only about the LO destination, and use a peephole to mop up any
+;; unneeded reloads.
+(define_insn "*macc"
+  [(set (match_operand:SI 0 "register_operand" "=l")
+        (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
+                          (match_operand:SI 2 "register_operand" "d"))
+                 (match_operand:SI 3 "register_operand" "0")))
+   (clobber (match_scratch:SI 4 "=h"))
+   (clobber (match_scratch:SI 5 "=a"))]
+  "TARGET_MIPS4121 && !TARGET_MIPS16"
+  "macc\\t%.,%1,%2"
+  [(set_attr "type" "imadd")
+   (set_attr "mode" "SI")])
+
+;; Generated by the peephole below.
+(define_insn "*macc_2way"
+  [(set (match_operand:SI 0 "register_operand" "=l")
+        (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
+                          (match_operand:SI 2 "register_operand" "d"))
+                 (match_operand:SI 3 "register_operand" "0")))
+   (set (match_operand:SI 4 "register_operand" "=d")
+        (plus:SI (mult:SI (match_dup 1)
+                          (match_dup 2))
+                 (match_dup 3)))
+   (clobber (match_scratch:SI 5 "=h"))
+   (clobber (match_scratch:SI 6 "=a"))]
+  "TARGET_MIPS4121 && !TARGET_MIPS16"
+  "macc\\t%4,%1,%2"
+  [(set_attr "type" "imadd")
+   (set_attr "mode" "SI")])
+
+(define_peephole2
+  [(parallel
+        [(set (match_operand:SI 0 "register_operand" "")
+              (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "")
+                                (match_operand:SI 2 "register_operand" ""))
+                       (match_dup 0)))
+         (clobber (match_operand:SI 3 "register_operand" ""))
+         (clobber (match_operand:SI 4 "register_operand" ""))])
+   (set (match_operand:SI 5 "register_operand" "")
+        (match_dup 0))]
+  "TARGET_MIPS4121 && !TARGET_MIPS16 && true_regnum (operands[0]) == LO_REGNUM"
+  [(parallel [(set (match_dup 0)
+                   (plus:SI (mult:SI (match_dup 1)
+                                     (match_dup 2))
+                            (match_dup 0)))
+              (set (match_dup 5)
+                   (plus:SI (mult:SI (match_dup 1)
+                                     (match_dup 2))
+                            (match_dup 0)))
+              (clobber (match_dup 3))
+              (clobber (match_dup 4))])]
+  "")
+
 (define_insn "*mul_sub_si"
   [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
         (minus:SI (match_operand:SI 1 "register_operand" "0,l,*d")
@@ -1981,6 +2071,38 @@
    (set (match_dup 0) (match_dup 1))]
   "")
 
+(define_insn "*muls"
+  [(set (match_operand:SI                  0 "register_operand" "=l,d")
+        (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
+                         (match_operand:SI 2 "register_operand" "d,d"))))
+   (clobber (match_scratch:SI              3                    "=h,h"))
+   (clobber (match_scratch:SI              4                    "=a,a"))
+   (clobber (match_scratch:SI              5                    "=X,l"))]
+  "ISA_HAS_MULS && TARGET_64BIT"
+  "@
+   muls\\t$0,%1,%2
+   muls\\t%0,%1,%2"
+  [(set_attr "type"     "imul")
+   (set_attr "mode"     "SI")])
+
+;; See comments above for mul_acc_si.
+(define_insn "*msac"
+  [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
+        (minus:SI (match_operand:SI 1 "register_operand" "0,l,*d")
+                  (mult:SI (match_operand:SI 2 "register_operand" "d,d,d")
+                           (match_operand:SI 3 "register_operand" "d,d,d"))))
+   (clobber (match_scratch:SI 4 "=h,h,h"))
+   (clobber (match_scratch:SI 5 "=X,1,l"))
+   (clobber (match_scratch:SI 6 "=a,a,a"))
+   (clobber (match_scratch:SI 7 "=X,X,d"))]
+  "ISA_HAS_MSAC && TARGET_64BIT"
+  "@
+   msac\\t$0,%2,%3
+   msac\\t%0,%2,%3
+   #"
+  [(set_attr "type"     "imadd,imadd,multi")
+   (set_attr "mode"     "SI")
+   (set_attr "length"   "4,4,8")])
 
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
@@ -2137,6 +2259,67 @@
   [(set_attr "type"	"imul")
    (set_attr "mode"	"SI")])
 
+;; widening multiply with accumulator and/or negation
+;; These don't match yet for zero-extending; too complex for combine?
+;; Possible additions we should have:
+;;  "=x" variants for when !TARGET_64BIT ?
+;;  all-d alternatives with splits like pure SImode versions
+(define_insn "*muls_di"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+        (neg:DI
+         (mult:DI (match_operator:DI 3 "extend_operator"
+                                     [(match_operand:SI 1 "register_operand" "d")])
+                  (match_operator:DI 4 "extend_operator"
+                                     [(match_operand:SI 2 "register_operand" "d")]))))
+   (clobber (match_scratch:SI 5 "=h"))
+   (clobber (match_scratch:SI 6 "=l"))]
+  "TARGET_64BIT
+   && ISA_HAS_MULS
+   && GET_CODE (operands[3]) == GET_CODE (operands[4])"
+  "*
+{
+  if (GET_CODE (operands[3]) == SIGN_EXTEND)
+    return \"muls\\t$0,%1,%2\";
+  else
+    return \"mulsu\\t$0,%1,%2\";
+}"
+  [(set_attr "type"     "imul")
+   (set_attr "length"   "4")
+   (set_attr "mode"     "SI")])
+
+(define_insn "*msac_di"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+        (minus:DI (match_operand:DI 3 "register_operand" "0")
+                  (mult:DI (match_operator:DI 4 "extend_operator"
+                                              [(match_operand:SI 1 "register_operand" "d")])
+                           (match_operator:DI 5 "extend_operator"
+                                              [(match_operand:SI 2 "register_operand" "d")]))))
+   (clobber (match_scratch:SI 6 "=h"))
+   (clobber (match_scratch:SI 7 "=l"))]
+  "TARGET_64BIT
+   && ISA_HAS_MSAC
+   && GET_CODE (operands[4]) == GET_CODE (operands[5])"
+  "*
+{
+  if (GET_CODE (operands[4]) == SIGN_EXTEND)
+     {
+       if (TARGET_MIPS5500)
+         return \"msub\\t%1,%2\";
+       else
+    return \"msac\\t$0,%1,%2\";
+    }
+  else
+     {
+       if (TARGET_MIPS5500)
+         return \"msubu\\t%1,%2\";
+       else
+    return \"msacu\\t$0,%1,%2\";
+    }
+}"
+  [(set_attr "type"     "imadd")
+   (set_attr "length"   "4")
+   (set_attr "mode"     "SI")])
+
 ;; _highpart patterns
 (define_expand "smulsi3_highpart"
   [(set (match_operand:SI 0 "register_operand" "=h")
@@ -2154,6 +2337,9 @@
 #else
   rtx (*genfn) ();
 #endif
+ if (ISA_HAS_MULHI && TARGET_64BIT)
+    genfn = gen_xmulsi3_highpart_mulhi;
+ else
   genfn = gen_xmulsi3_highpart_internal;
   emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy,
 		       dummy, dummy2));
@@ -2176,6 +2362,9 @@
 #else
   rtx (*genfn) ();
 #endif
+  if (ISA_HAS_MULHI && TARGET_64BIT)
+    genfn = gen_xmulsi3_highpart_mulhi;
+  else
   genfn = gen_xmulsi3_highpart_internal;
   emit_insn ((*genfn) (operands[0], operands[1], operands[2], dummy,
 		       dummy, dummy2));
@@ -2204,6 +2393,64 @@
   [(set_attr "type"	"imul")
    (set_attr "mode"	"SI")])
 
+(define_insn "xmulsi3_highpart_mulhi"
+  [(set (match_operand:SI 0 "register_operand" "=h,d")
+        (truncate:SI
+         (match_operator:DI 5 "highpart_shift_operator"
+                            [(mult:DI (match_operator:DI 3 "extend_operator"
+                                                         [(match_operand:SI 1 "register_operand" "d,d")])
+                                      (match_operator:DI 4 "extend_operator"
+                                                         [(match_operand:SI 2 "register_operand" "d,d")]))
+                             (const_int 32)])))
+   (clobber (match_scratch:SI 6 "=l,l"))
+   (clobber (match_scratch:SI 7 "=a,a"))
+   (clobber (match_scratch:SI 8 "=X,h"))]
+  "ISA_HAS_MULHI
+   && TARGET_64BIT
+   && GET_CODE (operands[3]) == GET_CODE (operands[4])"
+  "*
+{
+  static char const *const sign[] = { \"mult\\t%1,%2\",  \"mulhi\\t%0,%1,%2\"  };
+  static char const *const zero[] = { \"multu\\t%1,%2\", \"mulhiu\\t%0,%1,%2\" };
+  if (GET_CODE (operands[3]) == SIGN_EXTEND)
+    return sign[which_alternative];
+  else
+    return zero[which_alternative];
+}"
+  [(set_attr "type"     "imul")
+   (set_attr "mode"     "SI")
+   (set_attr "length"   "4")])
+
+(define_insn "*xmulsi3_neg_highpart_mulhi"
+  [(set (match_operand:SI 0 "register_operand" "=h,d")
+        (truncate:SI
+         (match_operator:DI 5 "highpart_shift_operator"
+                            [(neg:DI
+                              (mult:DI (match_operator:DI 3 "extend_operator"
+                                                          [(match_operand:SI 1 "register_operand" "d,d")])
+                                       (match_operator:DI 4 "extend_operator"
+                                                          [(match_operand:SI 2 "register_operand" "d,d")])))
+                             (const_int 32)])))
+   (clobber (match_scratch:SI 6 "=l,l"))
+   (clobber (match_scratch:SI 7 "=a,a"))
+   (clobber (match_scratch:SI 8 "=X,h"))]
+  "ISA_HAS_MULHI
+   && TARGET_64BIT
+   && GET_CODE (operands[3]) == GET_CODE (operands[4])"
+  "*
+{
+  static char const *const sign[] = { \"mulshi\\t$0,%1,%2\",  \"mulshi\\t%0,%1,%2\"  };
+  static char const *const zero[] = { \"mulshiu\\t$0,%1,%2\", \"mulshiu\\t%0,%1,%2\" };
+  if (GET_CODE (operands[3]) == SIGN_EXTEND)
+    return sign[which_alternative];
+  else
+    return zero[which_alternative];
+}"
+  [(set_attr "type"     "imul")
+   (set_attr "mode"     "SI")
+   (set_attr "length"   "4")])
+
+
 (define_insn "smuldi3_highpart"
   [(set (match_operand:DI 0 "register_operand" "=h")
 	(truncate:DI
@@ -2280,10 +2527,33 @@
    && GET_CODE (operands[3]) == GET_CODE (operands[4])"
   "*
 {
+  if (TARGET_MAD)
+    {
   if (GET_CODE (operands[3]) == SIGN_EXTEND)
     return \"mad\\t%1,%2\";
   else
     return \"madu\\t%1,%2\";
+    }
+  else if (ISA_HAS_MACC)
+    {
+      if (GET_CODE (operands[3]) == SIGN_EXTEND)
+        {
+          if (TARGET_MIPS5500)
+            return \"madd\\t%1,%2\";
+          else
+        return \"macc\\t$0,%1,%2\";
+        }
+      else
+        {
+          if (TARGET_MIPS5500)
+            return \"maddu\\t%1,%2\";
+          else
+        return \"maccu\\t$0,%1,%2\";
+        }
+    }
+  else
+    abort ();
+
 }"
   [(set_attr "type"	"imadd")
    (set_attr "mode"	"SI")])
@@ -3016,7 +3286,7 @@
 		(sqrt:DF (match_operand:DF 2 "register_operand" "f"))))]
   "ISA_HAS_FP4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_unsafe_math_optimizations"
   "rsqrt.d\\t%0,%2"
-  [(set_attr "type"	"fsqrt")
+  [(set_attr "type"	"frsqrt")
    (set_attr "mode"	"DF")])
 
 (define_insn ""
@@ -3025,7 +3295,7 @@
 		(sqrt:SF (match_operand:SF 2 "register_operand" "f"))))]
   "ISA_HAS_FP4 && TARGET_HARD_FLOAT && flag_unsafe_math_optimizations"
   "rsqrt.s\\t%0,%2"
-  [(set_attr "type"	"fsqrt")
+  [(set_attr "type"	"frsqrt")
    (set_attr "mode"	"SF")])
 
 
@@ -7577,6 +7847,39 @@ move\\t%0,%z4\\n\\
 		 (if_then_else (match_operand:VOID 2 "m16_uimm3_b" "")
 			       (const_int 4)
 			       (const_int 8))])])
+
+(define_insn "rotrsi3"
+  [(set (match_operand:SI              0 "register_operand" "=d")
+        (rotatert:SI (match_operand:SI 1 "register_operand" "d")
+                     (match_operand:SI 2 "arith_operand"    "dn")))]
+  "ISA_HAS_ROTR_SI"
+  "*
+{
+  if ((GET_CODE (operands[2]) == CONST_INT)
+      && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) >= 32))
+    abort ();
+
+  return \"ror\\t%0,%1,%2\";
+}"
+  [(set_attr "type"     "arith")
+   (set_attr "mode"     "SI")])
+
+(define_insn "rotrdi3"
+  [(set (match_operand:DI              0 "register_operand" "=d")
+        (rotatert:DI (match_operand:DI 1 "register_operand" "d")
+                     (match_operand:DI 2 "arith_operand"    "dn")))]
+  "ISA_HAS_ROTR_DI"
+  "*
+{
+  if ((GET_CODE (operands[2]) == CONST_INT)
+      && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) >= 64))
+    abort ();
+
+  return \"dror\\t%0,%1,%2\";
+}"
+  [(set_attr "type"     "arith")
+   (set_attr "mode"     "DI")])
+
 
 ;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts.
 
Index: config/mips/t-vr
===================================================================
RCS file: config/mips/t-vr
diff -N config/mips/t-vr
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ config/mips/t-vr	16 Aug 2002 06:42:42 -0000
@@ -0,0 +1,94 @@
+# BEGIN boiler-plate MIPS stuff
+
+# Don't let CTOR_LIST end up in sdata section.
+CRTSTUFF_T_CFLAGS = -G 0
+
+# We must build libgcc2.a with -G 0, in case the user wants to link
+# without the $gp register.
+TARGET_LIBGCC2_CFLAGS = -G 0
+
+LIB2FUNCS_EXTRA = $(srcdir)/config/mips/mips16.S
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
+
+# Assemble startup files.
+$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm
+
+$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES)
+	$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+	-c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm
+
+# END boiler-plate
+
+# Endianness: EB or EL
+#
+# ABIs: mabi=32
+#	mabi=o64
+#	mabi=eabi
+#	meabi=eabi/mlong32
+#	mabi=eabi/mgp32
+#	mabi=eabi/mgp32/mlong64
+#
+# Architecture: march=vr5400
+#		march=vr4100
+#		march=vr4100/mips16
+#
+# Total: 2 * 6 * 3 = 36 multilibs.
+MULTILIB_OPTIONS =			\
+	EL/EB				\
+	mabi=32/mabi=o64/mabi=eabi	\
+	mgp32				\
+	mlong32/mlong64			\
+	mips16				\
+	march=vr5400/march=vr4100
+
+MULTILIB_DIRNAMES =	\
+	el eb		\
+	o32 o64 eabi	\
+	gp32		\
+	long32 long64	\
+	mips16		\
+	vr5400 vr4100
+
+# Assume a 4000-series is the default: we'd need a *mips16 entry if
+# the default processor didn't support mips16.  Also assume o64,
+# which means we need to extend the o64 exceptions to combinations
+# without a -mabi flag.
+MULTILIB_EXCEPTIONS =				\
+	*mabi=32/mlong64*			\
+	*mabi=32/mgp32/mlong64*			\
+	*mabi=o64/mgp32*			\
+	*mabi=o64/mlong64*			\
+	mgp32* E[LB]/mgp32*			\
+	mlong64* E[LB]/mlong64*			\
+	*mips16/march=vr5*
+
+# The real value of this macro is very long, so generate it using a
+# shell fragment.  The idea is to tell the GCC driver how -mabi,
+# -mgp32, -mlong32 and -mlong64 interact, so that it choses the right
+# library when some options are specified redundantly (for example,
+# -mabi=32 -mgp32).
+
+# The core equalities are listed after "for changes in ".  The first
+# entry assumes o64 is the default ABI.
+MULTILIB_REDUNDANT_DIRS=` \
+	for endian in '' 'el' 'eb'; do					\
+	  for arch in '' 'vr5400' 'vr4100'				\
+		      'mips16' 'mips16/vr100'; do			\
+	    for changes in long32=					\
+			   o32/gp32=o32					\
+			   o32/gp32/long32=o32				\
+			   o32/long32=o32				\
+			   o64/long32=o64				\
+			   eabi/gp32/long32=eabi/gp32			\
+			   eabi/long64=eabi; do				\
+	      from=\`echo \$${changes} | sed 's/=.*//'\`;		\
+	      to=\`echo \$${changes} | sed 's/.*=//'\`;			\
+	      echo \$$endian \$$from \$$arch=\$$endian \$$to \$$arch	\
+		| sed -e 's: *= *:=:'					\
+		      -e 's:  *:/:g'					\
+		      -e 's:=$$:=.:';					\
+	    done;							\
+	  done;								\
+	done`
Index: config/mips/vr.h
===================================================================
RCS file: config/mips/vr.h
diff -N config/mips/vr.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ config/mips/vr.h	16 Aug 2002 06:42:42 -0000
@@ -0,0 +1,24 @@
+/* Definitions of target machine for GNU compiler.
+   NEC VR Series Processors
+   Copyright (c) 2002 Free Software Foundation, Inc.
+   Contributed by Red Hat, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#define MIPS_CPU_STRING_DEFAULT "vr4100"
+#define MULTILIB_DEFAULTS \
+	{ MULTILIB_ENDIAN_DEFAULT, MULTILIB_ABI_DEFAULT, "march=vr4100" }


More information about the Gcc-patches mailing list