diff mbox

[MIPS] NetLogic XLP scheduling

Message ID 4FFFF41B.7070803@codesourcery.com
State New
Headers show

Commit Message

Chung-Lin Tang July 13, 2012, 10:10 a.m. UTC
Hi Richard,
This patch adds scheduling support for the NetLogic XLP, including a new
pipeline description, and associated changes.

Asides from the new xlp.md description file, there are also some sync
primitive attribute modifications, for better scheduling of sync loops
(Maxim should be able to better explain this).

Other generic changes include a new "hilo" insn attribute, to mark which
of HI/LO does a m[ft]hilo insn access.

Can you see if this is okay for trunk?

Thanks,
Chung-Lin
From 014ff721a2e6cb96236dcf5e11d7f15c3b927386 Mon Sep 17 00:00:00 2001
From: Maxim Kuvyrkov <maxim@codesourcery.com>
Date: Mon, 18 Jun 2012 18:10:19 -0700
Subject: [PATCH] XLP scheduling.

2012-07-13  Chung-Lin Tang  <cltang@codesourcery.com>
	    Maxim Kuvyrkov  <maxim@codesourcery.com>
	    NetLogic Microsystems Inc.

	* config/mips/mips.md (define_attr "type"): New values "atomic" and
	"syncloop".
	(hilo): New attribute for indicating which of hi/lo accessed.
	(include xlp.md): New include.
	(mfhi<GPR:mode>_<HILO:mode>,mthi<GPR:mode>_<HILO:mode>):
	Set hilo" attribute.
	* config/mips/sync.md: Set "type" attribute for instructions.
	* config/mips/generic.md (generic_atomic, generic_syncloop):
	New reservations.
	* config/mips/xlp.md: New file.
	* config/mips/mips-proto.h (mips_hilo_use): Declare.
	* config/mips/mips.c (mips_issue_rate): Handle XLP.
	(mips_hilo_use): New function for computing "hilo" attribute.
---
 gcc/config/mips/generic.md    |   16 +++
 gcc/config/mips/mips-protos.h |    2 +
 gcc/config/mips/mips.c        |   28 ++++++
 gcc/config/mips/mips.md       |   18 +++-
 gcc/config/mips/sync.md       |   78 ++++++++++-----
 gcc/config/mips/xlp.md        |  217 +++++++++++++++++++++++++++++++++++++++++
 6 files changed, 332 insertions(+), 27 deletions(-)
 create mode 100644 gcc/config/mips/xlp.md
diff mbox

Patch

diff --git a/gcc/config/mips/generic.md b/gcc/config/mips/generic.md
index d61511f..02b1d8b 100644
--- a/gcc/config/mips/generic.md
+++ b/gcc/config/mips/generic.md
@@ -103,3 +103,19 @@ 
 (define_insn_reservation "generic_frecip_fsqrt_step" 5
   (eq_attr "type" "frdiv1,frdiv2,frsqrt1,frsqrt2")
   "alu")
+
+(define_insn_reservation "generic_atomic" 10
+  (eq_attr "type" "atomic")
+  "alu")
+
+;; Sync loop consists of (in order)
+;; (1) optional sync,
+;; (2) LL instruction,
+;; (3) branch and 1-2 ALU instructions,
+;; (4) SC instruction,
+;; (5) branch and ALU instruction.
+;; The net result of this reservation is a big delay with a flush of
+;; ALU pipeline.
+(define_insn_reservation "generic_sync_loop" 40
+  (eq_attr "type" "syncloop")
+  "alu*39")
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index d1fa160..1b1cbcb 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -334,6 +334,8 @@  extern void mips_final_prescan_insn (rtx, rtx *, int);
 extern int mips_trampoline_code_size (void);
 extern void mips_function_profiler (FILE *);
 
+extern int mips_hilo_use (rtx);
+
 typedef rtx (*mulsidi3_gen_fn) (rtx, rtx, rtx);
 #ifdef RTX_CODE
 extern mulsidi3_gen_fn mips_mulsidi3_gen_fn (enum rtx_code);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 7356ce5..f46eb49 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -12480,6 +12480,9 @@  mips_issue_rate (void)
     case PROCESSOR_LOONGSON_3A:
       return 4;
 
+    case PROCESSOR_XLP:
+      return (reload_completed ? 4 : 3);
+
     default:
       return 1;
     }
@@ -17407,6 +17410,31 @@  mips_expand_vec_minmax (rtx target, rtx op0, rtx op1,
   x = gen_rtx_IOR (vmode, t0, t1);
   emit_insn (gen_rtx_SET (VOIDmode, target, x));
 }
+
+/* Determine HI/LO access on INSN, return 1 for HI, -1 for LO,
+   and 0 for no access. Used for determining "hilo" attribute.  */
+
+int
+mips_hilo_use (rtx insn)
+{
+  rtx pat, dest, src;
+  enum attr_type insn_type;
+
+  if (! (pat = single_set (insn)))
+    return 0;
+
+  insn_type = get_attr_type (insn);
+  dest = SET_DEST (pat);
+  src = SET_SRC (pat);
+
+  if ((insn_type == TYPE_MTHILO && REGNO (dest) == HI_REGNUM)
+      || (insn_type == TYPE_MFHILO && REGNO (src) == HI_REGNUM))
+    return 1;
+  if ((insn_type == TYPE_MTHILO && REGNO (dest) == LO_REGNUM)
+      || (insn_type == TYPE_MFHILO && REGNO (src) == LO_REGNUM))
+    return -1;
+  return 0;
+}
 
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 5b1735f..d2a304e 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -274,6 +274,8 @@ 
 ;; frsqrt1      floating point reciprocal square root step1
 ;; frsqrt2      floating point reciprocal square root step2
 ;; multi	multiword sequence (or user asm statements)
+;; atomic	atomic memory update instruction
+;; sync_loop	memory atomic operation implemented as a sync loop
 ;; nop		no operation
 ;; ghost	an instruction that produces no real code
 (define_attr "type"
@@ -281,7 +283,7 @@ 
    prefetch,prefetchx,condmove,mtc,mfc,mthilo,mfhilo,const,arith,logical,
    shift,slt,signext,clz,pop,trap,imul,imul3,imul3nc,imadd,idiv,idiv3,move,
    fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt,
-   frsqrt,frsqrt1,frsqrt2,multi,nop,ghost"
+   frsqrt,frsqrt1,frsqrt2,multi,atomic,syncloop,nop,ghost"
   (cond [(eq_attr "jal" "!unset") (const_string "call")
 	 (eq_attr "got" "load") (const_string "load")
 
@@ -589,6 +591,17 @@ 
 		(const_string "yes")
 		(const_string "no")))
 
+;; For mfhilo/mthilo insns, determine which of hi or lo is the operand
+(define_attr "hilo" "hi,lo,none"
+  (cond [(and (eq_attr "type" "mthilo,mfhilo")
+              (gt (symbol_ref "mips_hilo_use (insn)") (const_int 0)))
+         (const_string "hi")
+
+         (and (eq_attr "type" "mthilo,mfhilo")
+              (lt (symbol_ref "mips_hilo_use (insn)") (const_int 0)))
+         (const_string "lo")]
+        (const_string "none")))
+
 ;; Describe a user's asm statement.
 (define_asm_attributes
   [(set_attr "type" "multi")
@@ -936,6 +949,7 @@ 
 (include "sb1.md")
 (include "sr71k.md")
 (include "xlr.md")
+(include "xlp.md")
 (include "generic.md")
 
 ;;
@@ -4735,6 +4749,7 @@ 
   ""
   { return ISA_HAS_MACCHI ? "<GPR:d>macchi\t%0,%.,%." : "mfhi\t%0"; }
   [(set_attr "move_type" "mfhilo")
+   (set_attr "hilo" "hi")
    (set_attr "mode" "<GPR:MODE>")])
 
 ;; Set the high part of a HI/LO value, given that the low part has
@@ -4748,6 +4763,7 @@ 
   ""
   "mthi\t%z1"
   [(set_attr "move_type" "mthilo")
+   (set_attr "hilo" "hi")
    (set_attr "mode" "SI")])
 
 ;; Emit a doubleword move in which exactly one of the operands is
diff --git a/gcc/config/mips/sync.md b/gcc/config/mips/sync.md
index 0a7905a..6585d91 100644
--- a/gcc/config/mips/sync.md
+++ b/gcc/config/mips/sync.md
@@ -99,7 +99,8 @@ 
 			    UNSPEC_COMPARE_AND_SWAP_12))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_oldval" "0")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
    (set_attr "sync_inclusive_mask" "2")
    (set_attr "sync_exclusive_mask" "3")
@@ -114,7 +115,8 @@ 
 	  UNSPEC_SYNC_OLD_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "addiu,addu")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "addiu,addu")
    (set_attr "sync_mem" "0")
    (set_attr "sync_insn1_op2" "1")])
 
@@ -145,7 +147,8 @@ 
    (clobber (match_scratch:SI 4 "=&d"))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "<insn>")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "<insn>")
    (set_attr "sync_insn2" "and")
    (set_attr "sync_mem" "0")
    (set_attr "sync_inclusive_mask" "1")
@@ -186,7 +189,8 @@ 
    (clobber (match_scratch:SI 5 "=&d"))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "<insn>")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "<insn>")
    (set_attr "sync_insn2" "and")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
@@ -232,7 +236,8 @@ 
 	   (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "<insn>")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "<insn>")
    (set_attr "sync_insn2" "and")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_newval" "0")
@@ -268,7 +273,8 @@ 
    (clobber (match_scratch:SI 4 "=&d"))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "and")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "and")
    (set_attr "sync_insn2" "xor")
    (set_attr "sync_mem" "0")
    (set_attr "sync_inclusive_mask" "1")
@@ -307,7 +313,8 @@ 
    (clobber (match_scratch:SI 5 "=&d"))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "and")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "and")
    (set_attr "sync_insn2" "xor")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
@@ -351,7 +358,8 @@ 
 	   (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "and")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "and")
    (set_attr "sync_insn2" "xor")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_newval" "0")
@@ -368,7 +376,8 @@ 
 	 UNSPEC_SYNC_OLD_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "subu")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "subu")
    (set_attr "sync_mem" "0")
    (set_attr "sync_insn1_op2" "1")])
 
@@ -383,7 +392,8 @@ 
 	 UNSPEC_SYNC_OLD_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "addiu,addu")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "addiu,addu")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
    (set_attr "sync_insn1_op2" "2")])
@@ -398,7 +408,8 @@ 
 	 UNSPEC_SYNC_OLD_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "subu")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "subu")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
    (set_attr "sync_insn1_op2" "2")])
@@ -413,7 +424,8 @@ 
 	 UNSPEC_SYNC_NEW_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "addiu,addu")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "addiu,addu")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_newval" "0")
    (set_attr "sync_mem" "1")
@@ -429,7 +441,8 @@ 
 	 UNSPEC_SYNC_NEW_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "subu")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "subu")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_newval" "0")
    (set_attr "sync_mem" "1")
@@ -443,7 +456,8 @@ 
 	 UNSPEC_SYNC_OLD_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "<immediate_insn>,<insn>")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "<immediate_insn>,<insn>")
    (set_attr "sync_mem" "0")
    (set_attr "sync_insn1_op2" "1")])
 
@@ -457,7 +471,8 @@ 
 	 UNSPEC_SYNC_OLD_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "<immediate_insn>,<insn>")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "<immediate_insn>,<insn>")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
    (set_attr "sync_insn1_op2" "2")])
@@ -472,7 +487,8 @@ 
 	 UNSPEC_SYNC_NEW_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "<immediate_insn>,<insn>")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "<immediate_insn>,<insn>")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_newval" "0")
    (set_attr "sync_mem" "1")
@@ -484,7 +500,8 @@ 
 	 UNSPEC_SYNC_OLD_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "andi,and")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "andi,and")
    (set_attr "sync_insn2" "not")
    (set_attr "sync_mem" "0")
    (set_attr "sync_insn1_op2" "1")])
@@ -497,7 +514,8 @@ 
 	 UNSPEC_SYNC_OLD_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "andi,and")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "andi,and")
    (set_attr "sync_insn2" "not")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
@@ -511,7 +529,8 @@ 
 	 UNSPEC_SYNC_NEW_OP))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "andi,and")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "andi,and")
    (set_attr "sync_insn2" "not")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_newval" "0")
@@ -526,7 +545,8 @@ 
 	 UNSPEC_SYNC_EXCHANGE))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_memmodel" "11")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_memmodel" "11")
    (set_attr "sync_insn1" "li,move")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
@@ -555,7 +575,8 @@ 
 	  UNSPEC_SYNC_EXCHANGE_12))]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_memmodel" "11")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_memmodel" "11")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
    ;; Unused, but needed to give the number of operands expected by
@@ -594,7 +615,8 @@ 
     UNSPEC_ATOMIC_COMPARE_AND_SWAP)]
   "GENERATE_LL_SC"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "li,move")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "li,move")
    (set_attr "sync_oldval" "1")
    (set_attr "sync_cmp" "0")
    (set_attr "sync_mem" "2")
@@ -639,7 +661,8 @@ 
     UNSPEC_ATOMIC_EXCHANGE)]
   "GENERATE_LL_SC && !ISA_HAS_SWAP"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "li,move")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "li,move")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
    (set_attr "sync_insn1_op2" "2")
@@ -654,7 +677,8 @@ 
 	(unspec_volatile:GPR [(match_operand:GPR 2 "register_operand" "0")]
 	 UNSPEC_ATOMIC_EXCHANGE))]
   "ISA_HAS_SWAP"
-  "swap<size>\t%0,%b1")
+  "swap<size>\t%0,%b1"
+  [(set_attr "type" "atomic")])
 
 (define_expand "atomic_fetch_add<mode>"
   [(match_operand:GPR 0 "register_operand")
@@ -695,7 +719,8 @@ 
     UNSPEC_ATOMIC_FETCH_OP)]
   "GENERATE_LL_SC && !ISA_HAS_LDADD"
   { return mips_output_sync_loop (insn, operands); }
-  [(set_attr "sync_insn1" "addiu,addu")
+  [(set_attr "type" "syncloop")
+   (set_attr "sync_insn1" "addiu,addu")
    (set_attr "sync_oldval" "0")
    (set_attr "sync_mem" "1")
    (set_attr "sync_insn1_op2" "2")
@@ -712,4 +737,5 @@ 
 		    (match_operand:GPR 2 "register_operand" "0"))]
 	 UNSPEC_ATOMIC_FETCH_OP))]
   "ISA_HAS_LDADD"
-  "ldadd<size>\t%0,%b1")
+  "ldadd<size>\t%0,%b1"
+  [(set_attr "type" "atomic")])
diff --git a/gcc/config/mips/xlp.md b/gcc/config/mips/xlp.md
new file mode 100644
index 0000000..e57133f
--- /dev/null
+++ b/gcc/config/mips/xlp.md
@@ -0,0 +1,217 @@ 
+;; DFA-based pipeline description for the XLP.
+;; Copyright (C) 2012 Free Software Foundation, Inc.
+;;
+;; xlp.md   Machine Description for the Broadcom XLP Microprocessor
+;; This file is part of GCC.
+
+;; GCC 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 3, or (at your
+;; option) any later version.
+
+;; GCC 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 GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_automaton "xlp_cpu")
+
+;; CPU function units.
+(define_cpu_unit "xlp_ex0" "xlp_cpu")
+(define_cpu_unit "xlp_ex1" "xlp_cpu")
+(define_cpu_unit "xlp_ex2" "xlp_cpu")
+(define_cpu_unit "xlp_ex3" "xlp_cpu")
+
+;; Integer Multiply Unit
+(define_cpu_unit "xlp_div" "xlp_cpu")
+
+;; ALU2 completion port.
+(define_cpu_unit "xlp_ex2_wrb" "xlp_cpu")
+
+(define_automaton "xlp_fpu")
+
+;; Floating-point units.
+(define_cpu_unit "xlp_fp" "xlp_fpu")
+
+;; Floating Point Sqrt/Divide
+(define_cpu_unit "xlp_divsq" "xlp_fpu")
+
+;; FPU completion port.
+(define_cpu_unit "xlp_fp_wrb" "xlp_fpu")
+
+;; Define reservations for common combinations.
+
+;;
+;; 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_xlp_unknown" 1
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "unknown,multi"))
+  "xlp_ex0+xlp_ex1+xlp_ex2+xlp_ex3")
+
+(define_insn_reservation "ir_xlp_branch" 1
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "branch,jump,call"))
+  "xlp_ex3")
+
+(define_insn_reservation "ir_xlp_prefetch" 1
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "prefetch,prefetchx"))
+  "xlp_ex0|xlp_ex1")
+
+(define_insn_reservation "ir_xlp_load" 4
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "load"))
+  "xlp_ex0|xlp_ex1")
+
+(define_insn_reservation "ir_xlp_fpload" 5
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "fpload,fpidxload"))
+  "xlp_ex0|xlp_ex1")
+
+(define_insn_reservation "ir_xlp_alu" 1
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "const,arith,shift,slt,clz,signext,logical,move,trap,nop"))
+  "xlp_ex0|xlp_ex1|(xlp_ex2,xlp_ex2_wrb)|xlp_ex3")
+
+(define_insn_reservation "ir_xlp_condmov" 1
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "condmove")
+       (eq_attr "mode" "SI,DI"))
+  "xlp_ex2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_mul" 5
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "imul,imadd"))
+  "xlp_ex2,nothing*4,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_mul3" 3
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "imul3"))
+  "xlp_ex2,nothing*2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_div" 24
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "mode" "SI")
+       (eq_attr "type" "idiv"))
+  "xlp_ex2+xlp_div,xlp_div*23,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_ddiv" 48
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "mode" "DI")
+       (eq_attr "type" "idiv"))
+  "xlp_ex2+xlp_div,xlp_div*47,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_store" 1
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "store,fpstore,fpidxstore"))
+  "xlp_ex0|xlp_ex1")
+
+(define_insn_reservation "ir_xlp_fpmove" 2
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "mfc"))
+ "xlp_ex3,xlp_fp,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_mfhi" 1
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "mfhilo")
+       (eq_attr "hilo" "hi"))
+  "xlp_ex2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_mflo" 1
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "mfhilo")
+       (eq_attr "hilo" "lo"))
+  "xlp_ex2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_mthi" 1
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "mthilo")
+       (eq_attr "hilo" "hi"))
+  "xlp_ex2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_mtlo" 3
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "mthilo")
+       (eq_attr "hilo" "lo"))
+  "xlp_ex2,nothing*2,xlp_ex2_wrb")
+
+(define_insn_reservation "ir_xlp_fp2" 2
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "fmove,fneg,fabs,condmove"))
+  "xlp_fp,nothing,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp3" 3
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "fcmp"))
+  "xlp_fp,nothing*2,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp4" 4
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "fcvt"))
+  "xlp_fp,nothing*3,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp5" 5
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "mode" "SF")
+       (eq_attr "type" "fadd,fmul"))
+  "xlp_fp,nothing*4,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp6" 6
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "mode" "DF")
+       (eq_attr "type" "fadd,fmul"))
+  "xlp_fp,nothing*5,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp9" 9
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "mode" "SF")
+       (eq_attr "type" "fmadd"))
+  "xlp_fp,nothing*3,xlp_fp,nothing*3,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fp11" 11
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "mode" "DF")
+       (eq_attr "type" "fmadd"))
+  "xlp_fp,nothing*4,xlp_fp,nothing*4,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fpcomplex_s" 23
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "mode" "SF")
+       (eq_attr "type" "fdiv,frdiv,frdiv1,frdiv2,fsqrt,frsqrt,frsqrt1,frsqrt2"))
+  "xlp_fp+xlp_divsq,xlp_divsq*22,xlp_fp_wrb")
+
+(define_insn_reservation "ir_xlp_fpcomplex_d" 38
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "mode" "DF")
+       (eq_attr "type" "fdiv,frdiv,frdiv1,frdiv2,fsqrt,frsqrt,frsqrt1,frsqrt2"))
+  "xlp_fp+xlp_divsq,xlp_divsq*37,xlp_fp_wrb")
+
+(define_bypass 3 "ir_xlp_mul" "ir_xlp_mfhi")
+
+(define_insn_reservation "ir_xlp_atomic" 15
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "atomic"))
+  "xlp_ex0|xlp_ex1")
+
+;; Sync loop consists of (in order)
+;; (1) optional sync,
+;; (2) LL instruction,
+;; (3) branch and 1-2 ALU instructions,
+;; (4) SC instruction,
+;; (5) optional sync,
+;; (6) branch and ALU instruction.
+;; The net result of this reservation is a big delay with flush of
+;; ALU pipeline and outgoing reservations discouraging use of EX3.
+(define_insn_reservation "ir_xlp_sync_loop" 40
+  (and (eq_attr "cpu" "xlp")
+       (eq_attr "type" "syncloop"))
+  "(xlp_ex0+xlp_ex1+xlp_ex2+xlp_ex3)*39,xlp_ex3+(xlp_ex0|xlp_ex1|(xlp_ex2,xlp_ex2_wrb))")