Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1091)

Unified Diff: gcc/gcc/config/mips/mips.md

Issue 3050029: [gcc] GCC 4.5.0=>4.5.1 (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/nacl-toolchain.git
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gcc/gcc/config/mips/irix-crti.asm ('k') | gcc/gcc/config/mips/mips.opt » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gcc/gcc/config/mips/mips.md
diff --git a/gcc/gcc/config/mips/mips.md b/gcc/gcc/config/mips/mips.md
index 10572743e754eb8b6e05bbe2b2686b402fc35130..a854327432862f61ca6fe68c1bf2d9d98fa16f23 100644
--- a/gcc/gcc/config/mips/mips.md
+++ b/gcc/gcc/config/mips/mips.md
@@ -1,6 +1,6 @@
;; Mips.md Machine Description for MIPS based processors
;; Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
;; Free Software Foundation, Inc.
;; Contributed by A. Lichnewsky, lich@inria.inria.fr
;; Changes by Michael Meissner, meissner@osf.org
@@ -29,11 +29,13 @@
(UNSPEC_STORE_WORD 2)
(UNSPEC_GET_FNADDR 3)
(UNSPEC_BLOCKAGE 4)
- (UNSPEC_CPRESTORE 5)
- (UNSPEC_RESTORE_GP 6)
- (UNSPEC_EH_RETURN 7)
- (UNSPEC_CONSTTABLE_INT 8)
- (UNSPEC_CONSTTABLE_FLOAT 9)
+ (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)
@@ -67,10 +69,21 @@
(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)
+ (RETURN_ADDR_REGNUM 31)
+ (CPRESTORE_SLOT_REGNUM 76)
(GOT_VERSION_REGNUM 79)
;; For MIPS Paired-Singled Floating Point Instructions.
@@ -250,6 +263,9 @@
(UNSPEC_MIPS_CACHE 600)
(UNSPEC_R10K_CACHE_BARRIER 601)
+
+ ;; PIC long branch sequences are never longer than 100 bytes.
+ (MAX_PIC_BRANCH_LENGTH 100)
]
)
@@ -275,14 +291,15 @@
;;
;; jal is always a macro for TARGET_CALL_CLOBBERED_GP because it includes
;; an instruction to restore $gp. Direct jals are also macros for
-;; flag_pic && !TARGET_ABSOLUTE_ABICALLS because they first load
-;; the target address into a register.
+;; !TARGET_ABSOLUTE_JUMPS because they first load the target address
+;; into a register.
(define_attr "jal_macro" "no,yes"
(cond [(eq_attr "jal" "direct")
- (symbol_ref "TARGET_CALL_CLOBBERED_GP
- || (flag_pic && !TARGET_ABSOLUTE_ABICALLS)")
+ (symbol_ref "(TARGET_CALL_CLOBBERED_GP || !TARGET_ABSOLUTE_JUMPS
+ ? JAL_MACRO_YES : JAL_MACRO_NO)")
(eq_attr "jal" "indirect")
- (symbol_ref "TARGET_CALL_CLOBBERED_GP")]
+ (symbol_ref "(TARGET_CALL_CLOBBERED_GP
+ ? JAL_MACRO_YES : JAL_MACRO_NO)")]
(const_string "no")))
;; Classification of moves, extensions and truncations. Most values
@@ -293,6 +310,7 @@
;; sll0 "sll DEST,SRC,0", which on 64-bit targets is guaranteed
;; to produce a sign-extended DEST, even if SRC is not
;; properly sign-extended
+;; ext_ins EXT, DEXT, INS or DINS instruction
;; andi a single ANDI instruction
;; loadpool move a constant into a MIPS16 register by loading it
;; from the pool
@@ -305,7 +323,8 @@
;; scheduling type to be "multi" instead.
(define_attr "move_type"
"unknown,load,fpload,store,fpstore,mtc,mfc,mthilo,mfhilo,move,fmove,
- const,constN,signext,sll0,andi,loadpool,shift_shift,lui_movf"
+ const,constN,signext,ext_ins,logical,arith,sll0,andi,loadpool,
+ shift_shift,lui_movf"
(const_string "unknown"))
;; Main data type used by the insn
@@ -400,6 +419,9 @@
(eq_attr "move_type" "fmove") (const_string "fmove")
(eq_attr "move_type" "loadpool") (const_string "load")
(eq_attr "move_type" "signext") (const_string "signext")
+ (eq_attr "move_type" "ext_ins") (const_string "arith")
+ (eq_attr "move_type" "arith") (const_string "arith")
+ (eq_attr "move_type" "logical") (const_string "logical")
(eq_attr "move_type" "sll0") (const_string "shift")
(eq_attr "move_type" "andi") (const_string "logical")
@@ -436,15 +458,59 @@
(const_string "yes")
(const_string "no")))
+;; Attributes describing a sync loop. These loops have the form:
+;;
+;; if (RELEASE_BARRIER == YES) sync
+;; 1: OLDVAL = *MEM
+;; if ((OLDVAL & INCLUSIVE_MASK) != REQUIRED_OLDVAL) goto 2
+;; $TMP1 = OLDVAL & EXCLUSIVE_MASK
+;; $TMP2 = INSN1 (OLDVAL, INSN1_OP2)
+;; $TMP3 = INSN2 ($TMP2, INCLUSIVE_MASK)
+;; $AT |= $TMP1 | $TMP3
+;; if (!commit (*MEM = $AT)) goto 1.
+;; if (INSN1 != MOVE && INSN1 != LI) NEWVAL = $TMP3 [delay slot]
+;; sync
+;; 2:
+;;
+;; where "$" values are temporaries and where the other values are
+;; specified by the attributes below. Values are specified as operand
+;; numbers and insns are specified as enums. If no operand number is
+;; specified, the following values are used instead:
+;;
+;; - OLDVAL: $AT
+;; - NEWVAL: $AT
+;; - INCLUSIVE_MASK: -1
+;; - REQUIRED_OLDVAL: OLDVAL & INCLUSIVE_MASK
+;; - EXCLUSIVE_MASK: 0
+;;
+;; MEM and INSN1_OP2 are required.
+;;
+;; Ideally, the operand attributes would be integers, with -1 meaning "none",
+;; but the gen* programs don't yet support that.
+(define_attr "sync_mem" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_oldval" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_newval" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_inclusive_mask" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_exclusive_mask" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_required_oldval" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_insn1_op2" "none,0,1,2,3,4,5" (const_string "none"))
+(define_attr "sync_insn1" "move,li,addu,addiu,subu,and,andi,or,ori,xor,xori"
+ (const_string "move"))
+(define_attr "sync_insn2" "nop,and,xor,not"
+ (const_string "nop"))
+(define_attr "sync_release_barrier" "yes,no"
+ (const_string "yes"))
+
;; Length of instruction in bytes.
(define_attr "length" ""
(cond [(and (eq_attr "extended_mips16" "yes")
(ne (symbol_ref "TARGET_MIPS16") (const_int 0)))
(const_int 8)
- ;; Direct branch instructions have a range of [-0x40000,0x3fffc].
- ;; If a branch is outside this range, we have a choice of two
- ;; sequences. For PIC, an out-of-range branch like:
+ ;; Direct branch instructions have a range of [-0x20000,0x1fffc],
+ ;; relative to the address of the delay slot. If a branch is
+ ;; outside this range, we have a choice of two sequences.
+ ;; For PIC, an out-of-range branch like:
;;
;; bne r1,r2,target
;; dslot
@@ -458,9 +524,6 @@
;; nop
;; 1:
;;
- ;; where the load address can be up to three instructions long
- ;; (lw, nop, addiu).
- ;;
;; The non-PIC case is similar except that we use a direct
;; jump instead of an la/jr pair. Since the target of this
;; jump is an absolute 28-bit bit address (the other bits
@@ -475,12 +538,21 @@
;; will add the length of the implicit nop. The values for
;; forward and backward branches will be different as well.
(eq_attr "type" "branch")
- (cond [(and (le (minus (match_dup 1) (pc)) (const_int 131064))
- (le (minus (pc) (match_dup 1)) (const_int 131068)))
- (const_int 4)
- (ne (symbol_ref "flag_pic") (const_int 0))
- (const_int 24)
- ] (const_int 12))
+ (cond [(and (le (minus (match_dup 0) (pc)) (const_int 131064))
+ (le (minus (pc) (match_dup 0)) (const_int 131068)))
+ (const_int 4)
+
+ ;; The non-PIC case: branch, first delay slot, and J.
+ (ne (symbol_ref "TARGET_ABSOLUTE_JUMPS") (const_int 0))
+ (const_int 12)]
+
+ ;; Use MAX_PIC_BRANCH_LENGTH as a (gross) overestimate.
+ ;; mips_adjust_insn_length substitutes the correct length.
+ ;;
+ ;; Note that we can't simply use (symbol_ref ...) here
+ ;; because genattrtab needs to know the maximum length
+ ;; of an insn.
+ (const_int MAX_PIC_BRANCH_LENGTH))
;; "Ghost" instructions occupy no space.
(eq_attr "type" "ghost")
@@ -559,13 +631,16 @@
(eq_attr "type" "idiv,idiv3")
(symbol_ref "mips_idiv_insns () * 4")
+
+ (not (eq_attr "sync_mem" "none"))
+ (symbol_ref "mips_sync_loop_insns (insn, operands) * 4")
] (const_int 4)))
;; Attribute describing the processor. This attribute must match exactly
;; with the processor_type enumeration in mips.h.
(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")))
+ (const (symbol_ref "mips_tune_attr")))
;; The type of hardware hazard associated with this instruction.
;; DELAY means that the next instruction cannot read the result
@@ -596,7 +671,8 @@
;; Is it a single instruction?
(define_attr "single_insn" "no,yes"
- (symbol_ref "get_attr_length (insn) == (TARGET_MIPS16 ? 2 : 4)"))
+ (symbol_ref "(get_attr_length (insn) == (TARGET_MIPS16 ? 2 : 4)
+ ? SINGLE_INSN_YES : SINGLE_INSN_NO)"))
;; Can the instruction be put into a delay slot?
(define_attr "can_delay" "no,yes"
@@ -718,9 +794,10 @@
;; This attributes gives the mode mask of a SHORT.
(define_mode_attr mask [(QI "0x00ff") (HI "0xffff")])
-;; Mode attributes for GPR loads and stores.
+;; Mode attributes for GPR loads.
(define_mode_attr load [(SI "lw") (DI "ld")])
-(define_mode_attr store [(SI "sw") (DI "sd")])
+;; Instruction names for stores.
+(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd")])
;; Similarly for MIPS IV indexed FPR loads and stores.
(define_mode_attr loadx [(SF "lwxc1") (DF "ldxc1") (V2SF "ldxc1")])
@@ -782,11 +859,6 @@
(DF "ISA_HAS_FP4 && TARGET_FLOAT64")
(V2SF "TARGET_SB1")])
-;; This code iterator allows all branch instructions to be generated from
-;; a single define_expand template.
-(define_code_iterator any_cond [unordered ordered unlt unge uneq ltgt unle ungt
- eq ne gt ge lt le gtu geu ltu leu])
-
;; This code iterator allows signed and unsigned widening multiplications
;; to use the same template.
(define_code_iterator any_extend [sign_extend zero_extend])
@@ -985,19 +1057,15 @@
}
[(set_attr "type" "trap")])
-(define_expand "conditional_trap"
+(define_expand "ctrap<mode>4"
[(trap_if (match_operator 0 "comparison_operator"
- [(match_dup 2) (match_dup 3)])
- (match_operand 1 "const_int_operand"))]
+ [(match_operand:GPR 1 "reg_or_0_operand")
+ (match_operand:GPR 2 "arith_operand")])
+ (match_operand 3 "const_0_operand"))]
"ISA_HAS_COND_TRAP"
{
- if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT
- && operands[1] == const0_rtx)
- {
- mips_expand_conditional_trap (GET_CODE (operands[0]));
- DONE;
- }
- FAIL;
+ mips_expand_conditional_trap (operands[0]);
+ DONE;
})
(define_insn "*conditional_trap<mode>"
@@ -1779,15 +1847,10 @@
[(set (match_operand:DI 0 "register_operand")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
(any_extend:DI (match_operand:SI 2 "register_operand"))))]
- "!TARGET_64BIT || !TARGET_FIX_R4000"
+ "mips_mulsidi3_gen_fn (<CODE>) != NULL"
{
- if (TARGET_64BIT)
- emit_insn (gen_<u>mulsidi3_64bit (operands[0], operands[1], operands[2]));
- else if (TARGET_FIX_R4000)
- emit_insn (gen_<u>mulsidi3_32bit_r4000 (operands[0], operands[1],
- operands[2]));
- else
- emit_insn (gen_<u>mulsidi3_32bit (operands[0], operands[1], operands[2]));
+ mulsidi3_gen_fn fn = mips_mulsidi3_gen_fn (<CODE>);
+ emit_insn (fn (operands[0], operands[1], operands[2]));
DONE;
})
@@ -1811,45 +1874,75 @@
(set_attr "mode" "SI")
(set_attr "length" "12")])
-(define_insn_and_split "<u>mulsidi3_64bit"
+(define_insn "<u>mulsidi3_64bit"
[(set (match_operand:DI 0 "register_operand" "=d")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
(clobber (match_scratch:TI 3 "=x"))
(clobber (match_scratch:DI 4 "=d"))]
- "TARGET_64BIT && !TARGET_FIX_R4000"
+ "TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DMUL3"
"#"
- "&& reload_completed"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "SI")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "ISA_HAS_EXT_INS") (const_int 0))
+ (const_int 16)
+ (const_int 28)))])
+
+(define_split
+ [(set (match_operand:DI 0 "d_operand")
+ (mult:DI (any_extend:DI (match_operand:SI 1 "d_operand"))
+ (any_extend:DI (match_operand:SI 2 "d_operand"))))
+ (clobber (match_operand:TI 3 "hilo_operand"))
+ (clobber (match_operand:DI 4 "d_operand"))]
+ "TARGET_64BIT && !TARGET_FIX_R4000 && ISA_HAS_EXT_INS && reload_completed"
[(set (match_dup 3)
(unspec:TI [(mult:DI (any_extend:DI (match_dup 1))
(any_extend:DI (match_dup 2)))]
UNSPEC_SET_HILO))
- ;; OP4 <- LO, OP0 <- HI
- (set (match_dup 4) (match_dup 5))
- (set (match_dup 0) (unspec:DI [(match_dup 3)] UNSPEC_MFHI))
+ ;; OP0 <- LO, OP4 <- HI
+ (set (match_dup 0) (match_dup 5))
+ (set (match_dup 4) (unspec:DI [(match_dup 3)] UNSPEC_MFHI))
- ;; Zero-extend OP4.
- (set (match_dup 4)
- (ashift:DI (match_dup 4)
- (const_int 32)))
- (set (match_dup 4)
- (lshiftrt:DI (match_dup 4)
- (const_int 32)))
+ (set (zero_extract:DI (match_dup 0) (const_int 32) (const_int 32))
+ (match_dup 4))]
+ { operands[5] = gen_rtx_REG (DImode, LO_REGNUM); })
- ;; Shift OP0 into place.
+(define_split
+ [(set (match_operand:DI 0 "d_operand")
+ (mult:DI (any_extend:DI (match_operand:SI 1 "d_operand"))
+ (any_extend:DI (match_operand:SI 2 "d_operand"))))
+ (clobber (match_operand:TI 3 "hilo_operand"))
+ (clobber (match_operand:DI 4 "d_operand"))]
+ "TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_EXT_INS && reload_completed"
+ [(set (match_dup 3)
+ (unspec:TI [(mult:DI (any_extend:DI (match_dup 1))
+ (any_extend:DI (match_dup 2)))]
+ UNSPEC_SET_HILO))
+
+ ;; OP0 <- LO, OP4 <- HI
+ (set (match_dup 0) (match_dup 5))
+ (set (match_dup 4) (unspec:DI [(match_dup 3)] UNSPEC_MFHI))
+
+ ;; Zero-extend OP0.
(set (match_dup 0)
(ashift:DI (match_dup 0)
(const_int 32)))
+ (set (match_dup 0)
+ (lshiftrt:DI (match_dup 0)
+ (const_int 32)))
+
+ ;; Shift OP4 into place.
+ (set (match_dup 4)
+ (ashift:DI (match_dup 4)
+ (const_int 32)))
;; OR the two halves together
(set (match_dup 0)
(ior:DI (match_dup 0)
(match_dup 4)))]
- { operands[5] = gen_rtx_REG (DImode, LO_REGNUM); }
- [(set_attr "type" "imul")
- (set_attr "mode" "SI")
- (set_attr "length" "24")])
+ { operands[5] = gen_rtx_REG (DImode, LO_REGNUM); })
(define_insn "<u>mulsidi3_64bit_hilo"
[(set (match_operand:TI 0 "register_operand" "=x")
@@ -1863,6 +1956,17 @@
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
+;; See comment before the ISA_HAS_DMUL3 case in mips_mulsidi3_gen_fn.
+(define_insn "mulsidi3_64bit_dmul"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))
+ (clobber (match_scratch:DI 3 "=l"))]
+ "TARGET_64BIT && ISA_HAS_DMUL3"
+ "dmul\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "DI")])
+
;; Widening multiply with negation.
(define_insn "*muls<u>_di"
[(set (match_operand:DI 0 "register_operand" "=x")
@@ -2559,31 +2663,91 @@
(define_expand "and<mode>3"
[(set (match_operand:GPR 0 "register_operand")
(and:GPR (match_operand:GPR 1 "register_operand")
- (match_operand:GPR 2 "uns_arith_operand")))]
- ""
-{
- if (TARGET_MIPS16)
- operands[2] = force_reg (<MODE>mode, operands[2]);
-})
+ (match_operand:GPR 2 "and_reg_operand")))])
+
+;; The middle-end is not allowed to convert ANDing with 0xffff_ffff into a
+;; zero_extendsidi2 because of TRULY_NOOP_TRUNCATION, so handle these here.
+;; Note that this variant does not trigger for SI mode because we require
+;; a 64-bit HOST_WIDE_INT and 0xffff_ffff wouldn't be a canonical
+;; sign-extended SImode value.
+;;
+;; These are possible combinations for operand 1 and 2. The table
+;; includes both MIPS and MIPS16 cases. (r=register, mem=memory,
+;; 16=MIPS16, x=match, S=split):
+;;
+;; \ op1 r/EXT r/!EXT mem r/16 mem/16
+;; op2
+;;
+;; andi x x
+;; 0xff x x x x
+;; 0xffff x x x x
+;; 0xffff_ffff x S x S x
+;; low-bitmask x
+;; register x x
+;; register =op1 x
(define_insn "*and<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (and:GPR (match_operand:GPR 1 "register_operand" "%d,d")
- (match_operand:GPR 2 "uns_arith_operand" "d,K")))]
- "!TARGET_MIPS16"
- "@
- and\t%0,%1,%2
- andi\t%0,%1,%x2"
- [(set_attr "type" "logical")
+ [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d,d,d")
+ (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "o,o,W,d,d,d,d")
+ (match_operand:GPR 2 "and_operand" "Yb,Yh,Yw,K,Yx,Yw,d")))]
+ "!TARGET_MIPS16 && and_operands_ok (<MODE>mode, operands[1], operands[2])"
+{
+ int len;
+
+ switch (which_alternative)
+ {
+ case 0:
+ operands[1] = gen_lowpart (QImode, operands[1]);
+ return "lbu\t%0,%1";
+ case 1:
+ operands[1] = gen_lowpart (HImode, operands[1]);
+ return "lhu\t%0,%1";
+ case 2:
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ return "lwu\t%0,%1";
+ case 3:
+ return "andi\t%0,%1,%x2";
+ case 4:
+ len = low_bitmask_len (<MODE>mode, INTVAL (operands[2]));
+ operands[2] = GEN_INT (len);
+ return "<d>ext\t%0,%1,0,%2";
+ case 5:
+ return "#";
+ case 6:
+ return "and\t%0,%1,%2";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "move_type" "load,load,load,andi,ext_ins,shift_shift,logical")
(set_attr "mode" "<MODE>")])
(define_insn "*and<mode>3_mips16"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (and:GPR (match_operand:GPR 1 "register_operand" "%0")
- (match_operand:GPR 2 "register_operand" "d")))]
- "TARGET_MIPS16"
- "and\t%0,%2"
- [(set_attr "type" "logical")
+ [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+ (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "%o,o,W,d,0")
+ (match_operand:GPR 2 "and_operand" "Yb,Yh,Yw,Yw,d")))]
+ "TARGET_MIPS16 && and_operands_ok (<MODE>mode, operands[1], operands[2])"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ operands[1] = gen_lowpart (QImode, operands[1]);
+ return "lbu\t%0,%1";
+ case 1:
+ operands[1] = gen_lowpart (HImode, operands[1]);
+ return "lhu\t%0,%1";
+ case 2:
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ return "lwu\t%0,%1";
+ case 3:
+ return "#";
+ case 4:
+ return "and\t%0,%2";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "move_type" "load,load,load,shift_shift,logical")
(set_attr "mode" "<MODE>")])
(define_expand "ior<mode>3"
@@ -2692,33 +2856,13 @@
;;
;; Step A needs a real instruction but step B does not.
-(define_insn "truncdisi2"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,m")
- (truncate:SI (match_operand:DI 1 "register_operand" "d,d")))]
+(define_insn "truncdi<mode>2"
+ [(set (match_operand:SUBDI 0 "nonimmediate_operand" "=d,m")
+ (truncate:SUBDI (match_operand:DI 1 "register_operand" "d,d")))]
"TARGET_64BIT"
"@
sll\t%0,%1,0
- sw\t%1,%0"
- [(set_attr "move_type" "sll0,store")
- (set_attr "mode" "SI")])
-
-(define_insn "truncdihi2"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
- (truncate:HI (match_operand:DI 1 "register_operand" "d,d")))]
- "TARGET_64BIT"
- "@
- sll\t%0,%1,0
- sh\t%1,%0"
- [(set_attr "move_type" "sll0,store")
- (set_attr "mode" "SI")])
-
-(define_insn "truncdiqi2"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
- (truncate:QI (match_operand:DI 1 "register_operand" "d,d")))]
- "TARGET_64BIT"
- "@
- sll\t%0,%1,0
- sb\t%1,%0"
+ <store>\t%1,%0"
[(set_attr "move_type" "sll0,store")
(set_attr "mode" "SI")])
@@ -2744,8 +2888,9 @@
[(set_attr "type" "shift")
(set_attr "mode" "<MODE>")])
-;; Logical shift by 32 or more results in proper SI values so
-;; truncation is removed by the middle end.
+;; Logical shift by more than 32 results in proper SI values so truncation is
+;; removed by the middle end. Note that a logical shift by 32 is handled by
+;; the previous pattern.
(define_insn "*<optab>_trunc<mode>_exts"
[(set (match_operand:SUBDI 0 "register_operand" "=d")
(truncate:SUBDI
@@ -2755,74 +2900,6 @@
"exts\t%0,%1,%2,31"
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
-
-;; Combiner patterns for truncate/sign_extend combinations. The SI versions
-;; use the shift/truncate patterns above.
-
-(define_insn_and_split "*extenddi_truncate<mode>"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI
- (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "#"
- "&& reload_completed"
- [(set (match_dup 2)
- (ashift:DI (match_dup 1)
- (match_dup 3)))
- (set (match_dup 0)
- (ashiftrt:DI (match_dup 2)
- (match_dup 3)))]
-{
- operands[2] = gen_lowpart (DImode, operands[0]);
- operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode));
-})
-
-(define_insn_and_split "*extendsi_truncate<mode>"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (sign_extend:SI
- (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "#"
- "&& reload_completed"
- [(set (match_dup 2)
- (ashift:DI (match_dup 1)
- (match_dup 3)))
- (set (match_dup 0)
- (truncate:SI (ashiftrt:DI (match_dup 2)
- (match_dup 3))))]
-{
- operands[2] = gen_lowpart (DImode, operands[0]);
- operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode));
-})
-
-;; Combiner patterns to optimize truncate/zero_extend combinations.
-
-(define_insn "*zero_extend<mode>_trunchi"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (zero_extend:GPR
- (truncate:HI (match_operand:DI 1 "register_operand" "d"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "andi\t%0,%1,0xffff"
- [(set_attr "type" "logical")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "*zero_extend<mode>_truncqi"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (zero_extend:GPR
- (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "andi\t%0,%1,0xff"
- [(set_attr "type" "logical")
- (set_attr "mode" "<MODE>")])
-
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=d")
- (zero_extend:HI
- (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "andi\t%0,%1,0xff"
- [(set_attr "type" "logical")
- (set_attr "mode" "HI")])
;;
;; ....................
@@ -2833,10 +2910,15 @@
;; Extension insns.
-(define_insn_and_split "zero_extendsidi2"
+(define_expand "zero_extendsidi2"
+ [(set (match_operand:DI 0 "register_operand")
+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
+ "TARGET_64BIT")
+
+(define_insn_and_split "*zero_extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,W")))]
- "TARGET_64BIT"
+ "TARGET_64BIT && !ISA_HAS_EXT_INS"
"@
#
lwu\t%0,%1"
@@ -2849,29 +2931,28 @@
[(set_attr "move_type" "shift_shift,load")
(set_attr "mode" "DI")])
-;; Combine is not allowed to convert this insn into a zero_extendsidi2
-;; because of TRULY_NOOP_TRUNCATION.
-
-(define_insn_and_split "*clear_upper32"
+(define_insn "*zero_extendsidi2_dext"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,W")
- (const_int 4294967295)))]
- "TARGET_64BIT"
-{
- if (which_alternative == 0)
- return "#";
+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,W")))]
+ "TARGET_64BIT && ISA_HAS_EXT_INS"
+ "@
+ dext\t%0,%1,0,32
+ lwu\t%0,%1"
+ [(set_attr "move_type" "arith,load")
+ (set_attr "mode" "DI")])
- operands[1] = gen_lowpart (SImode, operands[1]);
- return "lwu\t%0,%1";
-}
- "&& reload_completed && REG_P (operands[1])"
+;; See the comment before the *and<mode>3 pattern why this is generated by
+;; combine.
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand")
+ (and:DI (match_operand:DI 1 "register_operand")
+ (const_int 4294967295)))]
+ "TARGET_64BIT && !ISA_HAS_EXT_INS && reload_completed"
[(set (match_dup 0)
(ashift:DI (match_dup 1) (const_int 32)))
(set (match_dup 0)
- (lshiftrt:DI (match_dup 0) (const_int 32)))]
- ""
- [(set_attr "move_type" "shift_shift,load")
- (set_attr "mode" "DI")])
+ (lshiftrt:DI (match_dup 0) (const_int 32)))])
(define_expand "zero_extend<SHORT:mode><GPR:mode>2"
[(set (match_operand:GPR 0 "register_operand")
@@ -2947,6 +3028,29 @@
"lbu\t%0,%1"
[(set_attr "move_type" "load")
(set_attr "mode" "HI")])
+
+;; Combiner patterns to optimize truncate/zero_extend combinations.
+
+(define_insn "*zero_extend<GPR:mode>_trunc<SHORT:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (zero_extend:GPR
+ (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+{
+ operands[2] = GEN_INT (GET_MODE_MASK (<SHORT:MODE>mode));
+ return "andi\t%0,%1,%x2";
+}
+ [(set_attr "type" "logical")
+ (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn "*zero_extendhi_truncqi"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (zero_extend:HI
+ (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "andi\t%0,%1,0xff"
+ [(set_attr "type" "logical")
+ (set_attr "mode" "HI")])
;;
;; ....................
@@ -3073,6 +3177,89 @@
[(set_attr "move_type" "signext,load")
(set_attr "mode" "SI")])
+;; Combiner patterns for truncate/sign_extend combinations. The SI versions
+;; use the shift/truncate patterns.
+
+(define_insn_and_split "*extenddi_truncate<mode>"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (sign_extend:DI
+ (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16 && !ISA_HAS_EXTS"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (ashift:DI (match_dup 1)
+ (match_dup 3)))
+ (set (match_dup 0)
+ (ashiftrt:DI (match_dup 2)
+ (match_dup 3)))]
+{
+ operands[2] = gen_lowpart (DImode, operands[0]);
+ operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode));
+}
+ [(set_attr "move_type" "shift_shift")
+ (set_attr "mode" "DI")])
+
+(define_insn_and_split "*extendsi_truncate<mode>"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (sign_extend:SI
+ (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16 && !ISA_HAS_EXTS"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (ashift:DI (match_dup 1)
+ (match_dup 3)))
+ (set (match_dup 0)
+ (truncate:SI (ashiftrt:DI (match_dup 2)
+ (match_dup 3))))]
+{
+ operands[2] = gen_lowpart (DImode, operands[0]);
+ operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode));
+}
+ [(set_attr "move_type" "shift_shift")
+ (set_attr "mode" "SI")])
+
+(define_insn_and_split "*extendhi_truncateqi"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (sign_extend:HI
+ (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16 && !ISA_HAS_EXTS"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (ashift:DI (match_dup 1)
+ (const_int 56)))
+ (set (match_dup 0)
+ (truncate:HI (ashiftrt:DI (match_dup 2)
+ (const_int 56))))]
+{
+ operands[2] = gen_lowpart (DImode, operands[0]);
+}
+ [(set_attr "move_type" "shift_shift")
+ (set_attr "mode" "SI")])
+
+(define_insn "*extend<GPR:mode>_truncate<SHORT:mode>_exts"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (sign_extend:GPR
+ (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16 && ISA_HAS_EXTS"
+{
+ operands[2] = GEN_INT (GET_MODE_BITSIZE (<SHORT:MODE>mode));
+ return "exts\t%0,%1,0,%m2";
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn "*extendhi_truncateqi_exts"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (sign_extend:HI
+ (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16 && ISA_HAS_EXTS"
+ "exts\t%0,%1,0,7"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
@@ -3116,7 +3303,7 @@
(clobber (match_scratch:DF 2 "=d"))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !ISA_HAS_TRUNC_W"
{
- if (set_nomacro)
+ if (mips_nomacro.nesting_level > 0)
return ".set\tmacro\;trunc.w.d %0,%1,%2\;.set\tnomacro";
else
return "trunc.w.d %0,%1,%2";
@@ -3153,7 +3340,7 @@
(clobber (match_scratch:SF 2 "=d"))]
"TARGET_HARD_FLOAT && !ISA_HAS_TRUNC_W"
{
- if (set_nomacro)
+ if (mips_nomacro.nesting_level > 0)
return ".set\tmacro\;trunc.w.s %0,%1,%2\;.set\tnomacro";
else
return "trunc.w.s %0,%1,%2";
@@ -3234,6 +3421,7 @@
rtx reg3 = gen_reg_rtx (SImode);
rtx label1 = gen_label_rtx ();
rtx label2 = gen_label_rtx ();
+ rtx test;
REAL_VALUE_TYPE offset;
real_2expN (&offset, 31, DFmode);
@@ -3243,8 +3431,8 @@
mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode));
do_pending_stack_adjust ();
- emit_insn (gen_cmpdf (operands[1], reg1));
- emit_jump_insn (gen_bge (label1));
+ test = gen_rtx_GE (VOIDmode, operands[1], reg1);
+ emit_jump_insn (gen_cbranchdf4 (test, operands[1], reg1, label1));
emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1]));
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
@@ -3279,6 +3467,7 @@
rtx reg3 = gen_reg_rtx (DImode);
rtx label1 = gen_label_rtx ();
rtx label2 = gen_label_rtx ();
+ rtx test;
REAL_VALUE_TYPE offset;
real_2expN (&offset, 63, DFmode);
@@ -3286,8 +3475,8 @@
mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode));
do_pending_stack_adjust ();
- emit_insn (gen_cmpdf (operands[1], reg1));
- emit_jump_insn (gen_bge (label1));
+ test = gen_rtx_GE (VOIDmode, operands[1], reg1);
+ emit_jump_insn (gen_cbranchdf4 (test, operands[1], reg1, label1));
emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1]));
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
@@ -3321,6 +3510,7 @@
rtx reg3 = gen_reg_rtx (SImode);
rtx label1 = gen_label_rtx ();
rtx label2 = gen_label_rtx ();
+ rtx test;
REAL_VALUE_TYPE offset;
real_2expN (&offset, 31, SFmode);
@@ -3328,8 +3518,8 @@
mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode));
do_pending_stack_adjust ();
- emit_insn (gen_cmpsf (operands[1], reg1));
- emit_jump_insn (gen_bge (label1));
+ test = gen_rtx_GE (VOIDmode, operands[1], reg1);
+ emit_jump_insn (gen_cbranchsf4 (test, operands[1], reg1, label1));
emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
@@ -3363,6 +3553,7 @@
rtx reg3 = gen_reg_rtx (DImode);
rtx label1 = gen_label_rtx ();
rtx label2 = gen_label_rtx ();
+ rtx test;
REAL_VALUE_TYPE offset;
real_2expN (&offset, 63, SFmode);
@@ -3370,8 +3561,8 @@
mips_emit_move (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode));
do_pending_stack_adjust ();
- emit_insn (gen_cmpsf (operands[1], reg1));
- emit_jump_insn (gen_bge (label1));
+ test = gen_rtx_GE (VOIDmode, operands[1], reg1);
+ emit_jump_insn (gen_cbranchsf4 (test, operands[1], reg1, label1));
emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1]));
emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
@@ -3477,16 +3668,16 @@
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
-(define_insn "*extzv_trunc<mode>_exts"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (truncate:GPR
+(define_insn "*extzv_truncsi_exts"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI
(zero_extract:DI (match_operand:DI 1 "register_operand" "d")
(match_operand 2 "const_int_operand" "")
(match_operand 3 "const_int_operand" ""))))]
"ISA_HAS_EXTS && TARGET_64BIT && IN_RANGE (INTVAL (operands[2]), 32, 63)"
"exts\t%0,%1,%3,31"
[(set_attr "type" "arith")
- (set_attr "mode" "<MODE>")])
+ (set_attr "mode" "SI")])
(define_expand "insv"
@@ -3858,7 +4049,7 @@
(define_insn "*mov<mode>_ra"
[(set (match_operand:GPR 0 "stack_operand" "=m")
- (reg:GPR 31))]
+ (reg:GPR RETURN_ADDR_REGNUM))]
"TARGET_MIPS16"
"<store>\t$31,%0"
[(set_attr "move_type" "store")
@@ -4096,7 +4287,7 @@
;; instructions will still work correctly.
;; ??? Perhaps it would be better to support these instructions by
-;; modifying GO_IF_LEGITIMATE_ADDRESS and friends. However, since
+;; modifying TARGET_LEGITIMATE_ADDRESS_P and friends. However, since
;; these instructions can only be used to load and store floating
;; point registers, that would probably cause trouble in reload.
@@ -4125,9 +4316,9 @@
(define_insn "*lwxs"
[(set (match_operand:IMOVE32 0 "register_operand" "=d")
(mem:IMOVE32
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
- (const_int 4))
- (match_operand:SI 2 "register_operand" "d"))))]
+ (plus:P (mult:P (match_operand:P 1 "register_operand" "d")
+ (const_int 4))
+ (match_operand:P 2 "register_operand" "d"))))]
"ISA_HAS_LWXS"
"lwxs\t%0,%1(%2)"
[(set_attr "type" "load")
@@ -4616,12 +4807,12 @@
;; function address.
(define_insn_and_split "loadgp_newabi_<mode>"
[(set (match_operand:P 0 "register_operand" "=d")
- (unspec_volatile:P [(match_operand:P 1)
- (match_operand:P 2 "register_operand" "d")]
- UNSPEC_LOADGP))]
+ (unspec:P [(match_operand:P 1)
+ (match_operand:P 2 "register_operand" "d")]
+ UNSPEC_LOADGP))]
"mips_current_loadgp_style () == LOADGP_NEWABI"
- "#"
- ""
+ { return mips_must_initialize_gp_p () ? "#" : ""; }
+ "&& mips_must_initialize_gp_p ()"
[(set (match_dup 0) (match_dup 3))
(set (match_dup 0) (match_dup 4))
(set (match_dup 0) (match_dup 5))]
@@ -4630,21 +4821,21 @@
operands[4] = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
operands[5] = gen_rtx_LO_SUM (Pmode, operands[0], operands[1]);
}
- [(set_attr "length" "12")])
+ [(set_attr "type" "ghost")])
;; Likewise, for -mno-shared code. Operand 0 is the __gnu_local_gp symbol.
(define_insn_and_split "loadgp_absolute_<mode>"
[(set (match_operand:P 0 "register_operand" "=d")
- (unspec_volatile:P [(match_operand:P 1)] UNSPEC_LOADGP))]
+ (unspec:P [(match_operand:P 1)] UNSPEC_LOADGP))]
"mips_current_loadgp_style () == LOADGP_ABSOLUTE"
- "#"
- ""
+ { return mips_must_initialize_gp_p () ? "#" : ""; }
+ "&& mips_must_initialize_gp_p ()"
[(const_int 0)]
{
mips_emit_move (operands[0], operands[1]);
DONE;
}
- [(set_attr "length" "8")])
+ [(set_attr "type" "ghost")])
;; This blockage instruction prevents the gp load from being
;; scheduled after an implicit use of gp. It also prevents
@@ -4653,19 +4844,18 @@
[(unspec_volatile [(reg:SI 28)] UNSPEC_BLOCKAGE)]
""
""
- [(set_attr "type" "ghost")
- (set_attr "mode" "none")])
+ [(set_attr "type" "ghost")])
;; Initialize $gp for RTP PIC. Operand 0 is the __GOTT_BASE__ symbol
;; and operand 1 is the __GOTT_INDEX__ symbol.
(define_insn_and_split "loadgp_rtp_<mode>"
[(set (match_operand:P 0 "register_operand" "=d")
- (unspec_volatile:P [(match_operand:P 1 "symbol_ref_operand")
- (match_operand:P 2 "symbol_ref_operand")]
- UNSPEC_LOADGP))]
+ (unspec:P [(match_operand:P 1 "symbol_ref_operand")
+ (match_operand:P 2 "symbol_ref_operand")]
+ UNSPEC_LOADGP))]
"mips_current_loadgp_style () == LOADGP_RTP"
- "#"
- ""
+ { return mips_must_initialize_gp_p () ? "#" : ""; }
+ "&& mips_must_initialize_gp_p ()"
[(set (match_dup 0) (high:P (match_dup 3)))
(set (match_dup 0) (unspec:P [(match_dup 0)
(match_dup 3)] UNSPEC_LOAD_GOT))
@@ -4675,37 +4865,72 @@
operands[3] = mips_unspec_address (operands[1], SYMBOL_ABSOLUTE);
operands[4] = mips_unspec_address (operands[2], SYMBOL_HALF);
}
- [(set_attr "length" "12")])
+ [(set_attr "type" "ghost")])
;; Initialize the global pointer for MIPS16 code. Operand 0 is the
;; global pointer and operand 1 is the MIPS16 register that holds
;; the required value.
(define_insn_and_split "copygp_mips16"
[(set (match_operand:SI 0 "register_operand" "=y")
- (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "d")]
- UNSPEC_COPYGP))]
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")]
+ UNSPEC_COPYGP))]
"TARGET_MIPS16"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (match_dup 1))])
+ { return mips_must_initialize_gp_p () ? "#" : ""; }
+ "&& mips_must_initialize_gp_p ()"
+ [(set (match_dup 0) (match_dup 1))]
+ ""
+ [(set_attr "type" "ghost")])
+
+;; A placeholder for where the cprestore instruction should go,
+;; if we decide we need one. Operand 0 and operand 1 are as for
+;; "cprestore". Operand 2 is a register that holds the gp value.
+;;
+;; The "cprestore" pattern requires operand 2 to be pic_offset_table_rtx,
+;; otherwise any register that holds the correct value will do.
+(define_insn_and_split "potential_cprestore"
+ [(set (match_operand:SI 0 "cprestore_save_slot_operand" "=X,X")
+ (unspec:SI [(match_operand:SI 1 "const_int_operand" "I,i")
+ (match_operand:SI 2 "register_operand" "d,d")]
+ UNSPEC_POTENTIAL_CPRESTORE))
+ (clobber (match_operand:SI 3 "scratch_operand" "=X,&d"))]
+ "!TARGET_CPRESTORE_DIRECTIVE || operands[2] == pic_offset_table_rtx"
+ { return mips_must_initialize_gp_p () ? "#" : ""; }
+ "mips_must_initialize_gp_p ()"
+ [(const_int 0)]
+{
+ mips_save_gp_to_cprestore_slot (operands[0], operands[1],
+ operands[2], operands[3]);
+ DONE;
+}
+ [(set_attr "type" "ghost")])
;; Emit a .cprestore directive, which normally expands to a single store
-;; instruction. Note that we continue to use .cprestore for explicit reloc
-;; code so that jals inside inline asms will work correctly.
+;; instruction. Operand 0 is a (possibly illegitimate) sp-based MEM
+;; for the cprestore slot. Operand 1 is the offset of the slot from
+;; the stack pointer. (This is redundant with operand 0, but it makes
+;; things a little simpler.)
(define_insn "cprestore"
- [(unspec_volatile [(match_operand 0 "const_int_operand" "I,i")
- (use (reg:SI 28))]
- UNSPEC_CPRESTORE)]
- ""
-{
- if (set_nomacro && which_alternative == 1)
- return ".set\tmacro\;.cprestore\t%0\;.set\tnomacro";
+ [(set (match_operand:SI 0 "cprestore_save_slot_operand" "=X,X")
+ (unspec:SI [(match_operand:SI 1 "const_int_operand" "I,i")
+ (reg:SI 28)]
+ UNSPEC_CPRESTORE))]
+ "TARGET_CPRESTORE_DIRECTIVE"
+{
+ if (mips_nomacro.nesting_level > 0 && which_alternative == 1)
+ return ".set\tmacro\;.cprestore\t%1\;.set\tnomacro";
else
- return ".cprestore\t%0";
+ return ".cprestore\t%1";
}
[(set_attr "type" "store")
(set_attr "length" "4,12")])
+(define_insn "use_cprestore"
+ [(set (reg:SI CPRESTORE_SLOT_REGNUM)
+ (match_operand:SI 0 "cprestore_load_slot_operand"))]
+ ""
+ ""
+ [(set_attr "type" "ghost")])
+
;; Expand in-line code to clear the instruction cache between operand[0] and
;; operand[1].
(define_expand "clear_cache"
@@ -4714,7 +4939,7 @@
""
"
{
- if (ISA_HAS_SYNCI)
+ if (TARGET_SYNCI)
{
mips_expand_synci_loop (operands[0], operands[1]);
emit_insn (gen_sync ());
@@ -4734,12 +4959,12 @@
(define_insn "sync"
[(unspec_volatile [(const_int 0)] UNSPEC_SYNC)]
"GENERATE_SYNC"
- "%|sync%-")
+ { return mips_output_sync (); })
(define_insn "synci"
[(unspec_volatile [(match_operand 0 "pmode_register_operand" "d")]
UNSPEC_SYNCI)]
- "ISA_HAS_SYNCI"
+ "TARGET_SYNCI"
"synci\t0(%0)")
(define_insn "rdhwr_synci_step_<mode>"
@@ -4751,7 +4976,7 @@
(define_insn "clear_hazard_<mode>"
[(unspec_volatile [(const_int 0)] UNSPEC_CLEAR_HAZARD)
- (clobber (reg:P 31))]
+ (clobber (reg:P RETURN_ADDR_REGNUM))]
"ISA_HAS_SYNCI"
{
return "%(%<bal\t1f\n"
@@ -4823,7 +5048,7 @@
reload pass. */
if (TARGET_MIPS16
&& optimize
- && GET_CODE (operands[2]) == CONST_INT
+ && CONST_INT_P (operands[2])
&& INTVAL (operands[2]) > 8
&& INTVAL (operands[2]) <= 16
&& !reload_in_progress
@@ -4844,7 +5069,7 @@
(match_operand:SI 2 "arith_operand" "dI")))]
"!TARGET_MIPS16"
{
- if (GET_CODE (operands[2]) == CONST_INT)
+ if (CONST_INT_P (operands[2]))
operands[2] = GEN_INT (INTVAL (operands[2])
& (GET_MODE_BITSIZE (<MODE>mode) - 1));
@@ -4860,7 +5085,7 @@
(match_operand:SI 2 "arith_operand" "dI"))))]
"TARGET_64BIT && !TARGET_MIPS16"
{
- if (GET_CODE (operands[2]) == CONST_INT)
+ if (CONST_INT_P (operands[2]))
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
return "<insn>\t%0,%1,%2";
@@ -4916,7 +5141,7 @@
(match_operand:SI 2 "arith_operand" "d,I")))]
"TARGET_64BIT && TARGET_MIPS16"
{
- if (GET_CODE (operands[2]) == CONST_INT)
+ if (CONST_INT_P (operands[2]))
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
return "dsra\t%0,%2";
@@ -4935,7 +5160,7 @@
(match_operand:SI 2 "arith_operand" "d,I")))]
"TARGET_64BIT && TARGET_MIPS16"
{
- if (GET_CODE (operands[2]) == CONST_INT)
+ if (CONST_INT_P (operands[2]))
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
return "dsrl\t%0,%2";
@@ -4990,7 +5215,7 @@
(match_operand:SI 2 "arith_operand" "dI")))]
"ISA_HAS_ROR"
{
- if (GET_CODE (operands[2]) == CONST_INT)
+ if (CONST_INT_P (operands[2]))
gcc_assert (INTVAL (operands[2]) >= 0
&& INTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode));
@@ -5002,50 +5227,6 @@
;;
;; ....................
;;
-;; COMPARISONS
-;;
-;; ....................
-
-;; Flow here is rather complex:
-;;
-;; 1) The cmp{si,di,sf,df} routine is called. It deposits the arguments
-;; into cmp_operands[] but generates no RTL.
-;;
-;; 2) The appropriate branch define_expand is called, which then
-;; creates the appropriate RTL for the comparison and branch.
-;; Different CC modes are used, based on what type of branch is
-;; done, so that we can constrain things appropriately. There
-;; are assumptions in the rest of GCC that break if we fold the
-;; operands into the branches for integer operations, and use cc0
-;; for floating point, so we use the fp status register instead.
-;; If needed, an appropriate temporary is created to hold the
-;; of the integer compare.
-
-(define_expand "cmp<mode>"
- [(set (cc0)
- (compare:CC (match_operand:GPR 0 "register_operand")
- (match_operand:GPR 1 "nonmemory_operand")))]
- ""
-{
- cmp_operands[0] = operands[0];
- cmp_operands[1] = operands[1];
- DONE;
-})
-
-(define_expand "cmp<mode>"
- [(set (cc0)
- (compare:CC (match_operand:SCALARF 0 "register_operand")
- (match_operand:SCALARF 1 "register_operand")))]
- ""
-{
- cmp_operands[0] = operands[0];
- cmp_operands[1] = operands[1];
- DONE;
-})
-
-;;
-;; ....................
-;;
;; CONDITIONAL BRANCHES
;;
;; ....................
@@ -5055,100 +5236,94 @@
(define_insn "*branch_fp"
[(set (pc)
(if_then_else
- (match_operator 0 "equality_operator"
+ (match_operator 1 "equality_operator"
[(match_operand:CC 2 "register_operand" "z")
(const_int 0)])
- (label_ref (match_operand 1 "" ""))
+ (label_ref (match_operand 0 "" ""))
(pc)))]
"TARGET_HARD_FLOAT"
{
return mips_output_conditional_branch (insn, operands,
- MIPS_BRANCH ("b%F0", "%Z2%1"),
- MIPS_BRANCH ("b%W0", "%Z2%1"));
+ MIPS_BRANCH ("b%F1", "%Z2%0"),
+ MIPS_BRANCH ("b%W1", "%Z2%0"));
}
- [(set_attr "type" "branch")
- (set_attr "mode" "none")])
+ [(set_attr "type" "branch")])
(define_insn "*branch_fp_inverted"
[(set (pc)
(if_then_else
- (match_operator 0 "equality_operator"
+ (match_operator 1 "equality_operator"
[(match_operand:CC 2 "register_operand" "z")
(const_int 0)])
(pc)
- (label_ref (match_operand 1 "" ""))))]
+ (label_ref (match_operand 0 "" ""))))]
"TARGET_HARD_FLOAT"
{
return mips_output_conditional_branch (insn, operands,
- MIPS_BRANCH ("b%W0", "%Z2%1"),
- MIPS_BRANCH ("b%F0", "%Z2%1"));
+ MIPS_BRANCH ("b%W1", "%Z2%0"),
+ MIPS_BRANCH ("b%F1", "%Z2%0"));
}
- [(set_attr "type" "branch")
- (set_attr "mode" "none")])
+ [(set_attr "type" "branch")])
;; Conditional branches on ordered comparisons with zero.
(define_insn "*branch_order<mode>"
[(set (pc)
(if_then_else
- (match_operator 0 "order_operator"
+ (match_operator 1 "order_operator"
[(match_operand:GPR 2 "register_operand" "d")
(const_int 0)])
- (label_ref (match_operand 1 "" ""))
+ (label_ref (match_operand 0 "" ""))
(pc)))]
"!TARGET_MIPS16"
{ return mips_output_order_conditional_branch (insn, operands, false); }
- [(set_attr "type" "branch")
- (set_attr "mode" "none")])
+ [(set_attr "type" "branch")])
(define_insn "*branch_order<mode>_inverted"
[(set (pc)
(if_then_else
- (match_operator 0 "order_operator"
+ (match_operator 1 "order_operator"
[(match_operand:GPR 2 "register_operand" "d")
(const_int 0)])
(pc)
- (label_ref (match_operand 1 "" ""))))]
+ (label_ref (match_operand 0 "" ""))))]
"!TARGET_MIPS16"
{ return mips_output_order_conditional_branch (insn, operands, true); }
- [(set_attr "type" "branch")
- (set_attr "mode" "none")])
+ [(set_attr "type" "branch")])
;; Conditional branch on equality comparison.
(define_insn "*branch_equality<mode>"
[(set (pc)
(if_then_else
- (match_operator 0 "equality_operator"
+ (match_operator 1 "equality_operator"
[(match_operand:GPR 2 "register_operand" "d")
(match_operand:GPR 3 "reg_or_0_operand" "dJ")])
- (label_ref (match_operand 1 "" ""))
+ (label_ref (match_operand 0 "" ""))
(pc)))]
"!TARGET_MIPS16"
{
return mips_output_conditional_branch (insn, operands,
- MIPS_BRANCH ("b%C0", "%2,%z3,%1"),
- MIPS_BRANCH ("b%N0", "%2,%z3,%1"));
+ MIPS_BRANCH ("b%C1", "%2,%z3,%0"),
+ MIPS_BRANCH ("b%N1", "%2,%z3,%0"));
}
- [(set_attr "type" "branch")
- (set_attr "mode" "none")])
+ [(set_attr "type" "branch")])
(define_insn "*branch_equality<mode>_inverted"
[(set (pc)
(if_then_else
- (match_operator 0 "equality_operator"
+ (match_operator 1 "equality_operator"
[(match_operand:GPR 2 "register_operand" "d")
(match_operand:GPR 3 "reg_or_0_operand" "dJ")])
(pc)
- (label_ref (match_operand 1 "" ""))))]
+ (label_ref (match_operand 0 "" ""))))]
"!TARGET_MIPS16"
{
return mips_output_conditional_branch (insn, operands,
- MIPS_BRANCH ("b%N0", "%2,%z3,%1"),
- MIPS_BRANCH ("b%C0", "%2,%z3,%1"));
+ MIPS_BRANCH ("b%N1", "%2,%z3,%0"),
+ MIPS_BRANCH ("b%C1", "%2,%z3,%0"));
}
- [(set_attr "type" "branch")
- (set_attr "mode" "none")])
+ [(set_attr "type" "branch")])
;; MIPS16 branches
@@ -5177,18 +5352,31 @@
return "bt%N0z\t%3";
}
}
- [(set_attr "type" "branch")
- (set_attr "mode" "none")])
+ [(set_attr "type" "branch")])
-(define_expand "b<code>"
+(define_expand "cbranch<mode>4"
[(set (pc)
- (if_then_else (any_cond:CC (cc0)
- (const_int 0))
- (label_ref (match_operand 0 ""))
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "nonmemory_operand")])
+ (label_ref (match_operand 3 ""))
(pc)))]
""
{
- mips_expand_conditional_branch (operands, <CODE>);
+ mips_expand_conditional_branch (operands);
+ DONE;
+})
+
+(define_expand "cbranch<mode>4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:SCALARF 1 "register_operand")
+ (match_operand:SCALARF 2 "register_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ ""
+{
+ mips_expand_conditional_branch (operands);
DONE;
})
@@ -5205,42 +5393,40 @@
[(set (pc)
(if_then_else
(equality_op (zero_extract:GPR
- (match_operand:GPR 0 "register_operand" "d")
+ (match_operand:GPR 1 "register_operand" "d")
(const_int 1)
(match_operand 2 "const_int_operand" ""))
(const_int 0))
- (label_ref (match_operand 1 ""))
+ (label_ref (match_operand 0 ""))
(pc)))]
"ISA_HAS_BBIT && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
{
return
mips_output_conditional_branch (insn, operands,
- MIPS_BRANCH ("bbit<bbv>", "%0,%2,%1"),
- MIPS_BRANCH ("bbit<bbinv>", "%0,%2,%1"));
+ MIPS_BRANCH ("bbit<bbv>", "%1,%2,%0"),
+ MIPS_BRANCH ("bbit<bbinv>", "%1,%2,%0"));
}
[(set_attr "type" "branch")
- (set_attr "mode" "none")
(set_attr "branch_likely" "no")])
(define_insn "*branch_bit<bbv><mode>_inverted"
[(set (pc)
(if_then_else
(equality_op (zero_extract:GPR
- (match_operand:GPR 0 "register_operand" "d")
+ (match_operand:GPR 1 "register_operand" "d")
(const_int 1)
(match_operand 2 "const_int_operand" ""))
(const_int 0))
(pc)
- (label_ref (match_operand 1 ""))))]
+ (label_ref (match_operand 0 ""))))]
"ISA_HAS_BBIT && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
{
return
mips_output_conditional_branch (insn, operands,
- MIPS_BRANCH ("bbit<bbinv>", "%0,%2,%1"),
- MIPS_BRANCH ("bbit<bbv>", "%0,%2,%1"));
+ MIPS_BRANCH ("bbit<bbinv>", "%1,%2,%0"),
+ MIPS_BRANCH ("bbit<bbv>", "%1,%2,%0"));
}
[(set_attr "type" "branch")
- (set_attr "mode" "none")
(set_attr "branch_likely" "no")])
;;
@@ -5252,12 +5438,16 @@
;; Destination is always set in SI mode.
-(define_expand "seq"
+(define_expand "cstore<mode>4"
[(set (match_operand:SI 0 "register_operand")
- (eq:SI (match_dup 1)
- (match_dup 2)))]
+ (match_operator:SI 1 "mips_cstore_operator"
+ [(match_operand:GPR 2 "register_operand")
+ (match_operand:GPR 3 "nonmemory_operand")]))]
""
- { if (mips_expand_scc (EQ, operands[0])) DONE; else FAIL; })
+{
+ mips_expand_scc (operands);
+ DONE;
+})
(define_insn "*seq_zero_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
@@ -5290,16 +5480,6 @@
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
-;; "sne" uses sltu instructions in which the first operand is $0.
-;; This isn't possible in mips16 code.
-
-(define_expand "sne"
- [(set (match_operand:SI 0 "register_operand")
- (ne:SI (match_dup 1)
- (match_dup 2)))]
- "!TARGET_MIPS16"
- { if (mips_expand_scc (NE, operands[0])) DONE; else FAIL; })
-
(define_insn "*sne_zero_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(ne:GPR2 (match_operand:GPR 1 "register_operand" "d")
@@ -5322,13 +5502,6 @@
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
-(define_expand "sgt<u>"
- [(set (match_operand:SI 0 "register_operand")
- (any_gt:SI (match_dup 1)
- (match_dup 2)))]
- ""
- { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; })
-
(define_insn "*sgt<u>_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(any_gt:GPR2 (match_operand:GPR 1 "register_operand" "d")
@@ -5347,13 +5520,6 @@
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
-(define_expand "sge<u>"
- [(set (match_operand:SI 0 "register_operand")
- (any_ge:SI (match_dup 1)
- (match_dup 2)))]
- ""
- { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; })
-
(define_insn "*sge<u>_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(any_ge:GPR2 (match_operand:GPR 1 "register_operand" "d")
@@ -5363,13 +5529,6 @@
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
-(define_expand "slt<u>"
- [(set (match_operand:SI 0 "register_operand")
- (any_lt:SI (match_dup 1)
- (match_dup 2)))]
- ""
- { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; })
-
(define_insn "*slt<u>_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(any_lt:GPR2 (match_operand:GPR 1 "register_operand" "d")
@@ -5393,13 +5552,6 @@
(const_int 4)
(const_int 8))])])
-(define_expand "sle<u>"
- [(set (match_operand:SI 0 "register_operand")
- (any_le:SI (match_dup 1)
- (match_dup 2)))]
- ""
- { if (mips_expand_scc (<CODE>, operands[0])) DONE; else FAIL; })
-
(define_insn "*sle<u>_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(any_le:GPR2 (match_operand:GPR 1 "register_operand" "d")
@@ -5461,47 +5613,41 @@
;; Unconditional branches.
-(define_insn "jump"
+(define_expand "jump"
[(set (pc)
- (label_ref (match_operand 0 "" "")))]
- "!TARGET_MIPS16"
+ (label_ref (match_operand 0)))])
+
+(define_insn "*jump_absolute"
+ [(set (pc)
+ (label_ref (match_operand 0)))]
+ "!TARGET_MIPS16 && TARGET_ABSOLUTE_JUMPS"
+ { return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/"); }
+ [(set_attr "type" "jump")])
+
+(define_insn "*jump_pic"
+ [(set (pc)
+ (label_ref (match_operand 0)))]
+ "!TARGET_MIPS16 && !TARGET_ABSOLUTE_JUMPS"
{
- if (flag_pic)
+ if (get_attr_length (insn) <= 8)
+ return "%*b\t%l0%/";
+ else
{
- if (get_attr_length (insn) <= 8)
- return "%*b\t%l0%/";
- else
- {
- output_asm_insn (mips_output_load_label (), operands);
- return "%*jr\t%@%/%]";
- }
+ mips_output_load_label (operands[0]);
+ return "%*jr\t%@%/%]";
}
- else
- return "%*j\t%l0%/";
}
- [(set_attr "type" "jump")
- (set_attr "mode" "none")
- (set (attr "length")
- ;; We can't use `j' when emitting PIC. Emit a branch if it's
- ;; in range, otherwise load the address of the branch target into
- ;; $at and then jump to it.
- (if_then_else
- (ior (eq (symbol_ref "flag_pic") (const_int 0))
- (lt (abs (minus (match_dup 0)
- (plus (pc) (const_int 4))))
- (const_int 131072)))
- (const_int 4) (const_int 16)))])
+ [(set_attr "type" "branch")])
;; We need a different insn for the mips16, because a mips16 branch
;; does not have a delay slot.
-(define_insn ""
+(define_insn "*jump_mips16"
[(set (pc)
(label_ref (match_operand 0 "" "")))]
"TARGET_MIPS16"
"b\t%l0"
- [(set_attr "type" "branch")
- (set_attr "mode" "none")])
+ [(set_attr "type" "branch")])
(define_expand "indirect_jump"
[(set (pc) (match_operand 0 "register_operand"))]
@@ -5679,6 +5825,60 @@
[(set_attr "type" "jump")
(set_attr "mode" "none")])
+;; Exception return.
+(define_insn "mips_eret"
+ [(return)
+ (unspec_volatile [(const_int 0)] UNSPEC_ERET)]
+ ""
+ "eret"
+ [(set_attr "type" "trap")
+ (set_attr "mode" "none")])
+
+;; Debug exception return.
+(define_insn "mips_deret"
+ [(return)
+ (unspec_volatile [(const_int 0)] UNSPEC_DERET)]
+ ""
+ "deret"
+ [(set_attr "type" "trap")
+ (set_attr "mode" "none")])
+
+;; Disable interrupts.
+(define_insn "mips_di"
+ [(unspec_volatile [(const_int 0)] UNSPEC_DI)]
+ ""
+ "di"
+ [(set_attr "type" "trap")
+ (set_attr "mode" "none")])
+
+;; Execution hazard barrier.
+(define_insn "mips_ehb"
+ [(unspec_volatile [(const_int 0)] UNSPEC_EHB)]
+ ""
+ "ehb"
+ [(set_attr "type" "trap")
+ (set_attr "mode" "none")])
+
+;; Read GPR from previous shadow register set.
+(define_insn "mips_rdpgpr"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "d")]
+ UNSPEC_RDPGPR))]
+ ""
+ "rdpgpr\t%0,%1"
+ [(set_attr "type" "move")
+ (set_attr "mode" "SI")])
+
+;; Move involving COP0 registers.
+(define_insn "cop0_move"
+ [(set (match_operand:SI 0 "register_operand" "=B,d")
+ (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "d,B")]
+ UNSPEC_COP0))]
+ ""
+{ return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "mtc,mfc")
+ (set_attr "mode" "SI")])
+
;; This is used in compiling the unwind routines.
(define_expand "eh_return"
[(use (match_operand 0 "general_operand"))]
@@ -5748,14 +5948,28 @@
(clobber (match_scratch:SI 0 "=&d"))]
"TARGET_CALL_CLOBBERED_GP"
"#"
- "&& reload_completed"
+ "&& epilogue_completed"
[(const_int 0)]
{
- mips_restore_gp (operands[0]);
+ mips_restore_gp_from_cprestore_slot (operands[0]);
DONE;
}
- [(set_attr "type" "load")
- (set_attr "length" "12")])
+ [(set_attr "type" "ghost")])
+
+;; Move between $gp and its register save slot.
+(define_insn_and_split "move_gp<mode>"
+ [(set (match_operand:GPR 0 "nonimmediate_operand" "=d,m")
+ (unspec:GPR [(match_operand:GPR 1 "move_operand" "m,d")]
+ UNSPEC_MOVE_GP))]
+ ""
+ { return mips_must_initialize_gp_p () ? "#" : ""; }
+ "mips_must_initialize_gp_p ()"
+ [(const_int 0)]
+{
+ mips_emit_move (operands[0], operands[1]);
+ DONE;
+}
+ [(set_attr "type" "ghost")])
;;
;; ....................
@@ -5808,12 +6022,6 @@
;; The register is therefore not a valid register_operand
;; and cannot be moved to or from other registers.
-;; Convenience expander that generates the rhs of a load_call<mode> insn.
-(define_expand "unspec_call<mode>"
- [(unspec:P [(match_operand:P 0)
- (match_operand:P 1)
- (reg:SI GOT_VERSION_REGNUM)] UNSPEC_LOAD_CALL)])
-
(define_insn "load_call<mode>"
[(set (match_operand:P 0 "register_operand" "=d")
(unspec:P [(match_operand:P 1 "register_operand" "d")
@@ -5867,7 +6075,7 @@
[(call (mem:SI (match_operand 0 "call_insn_operand" "j,S"))
(match_operand 1 "" ""))]
"TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
- { return MIPS_CALL ("j", operands, 0); }
+ { return MIPS_CALL ("j", operands, 0, 1); }
[(set_attr "type" "call")])
(define_expand "sibcall_value"
@@ -5887,7 +6095,7 @@
(call (mem:SI (match_operand 1 "call_insn_operand" "j,S"))
(match_operand 2 "" "")))]
"TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
- { return MIPS_CALL ("j", operands, 1); }
+ { return MIPS_CALL ("j", operands, 1, 2); }
[(set_attr "type" "call")])
(define_insn "sibcall_value_multiple_internal"
@@ -5898,7 +6106,7 @@
(call (mem:SI (match_dup 1))
(match_dup 2)))]
"TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
- { return MIPS_CALL ("j", operands, 1); }
+ { return MIPS_CALL ("j", operands, 1, 2); }
[(set_attr "type" "call")])
(define_expand "call"
@@ -5953,9 +6161,9 @@
(define_insn_and_split "call_internal"
[(call (mem:SI (match_operand 0 "call_insn_operand" "c,S"))
(match_operand 1 "" ""))
- (clobber (reg:SI 31))]
+ (clobber (reg:SI RETURN_ADDR_REGNUM))]
""
- { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0); }
+ { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0, 1); }
"reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)"
[(const_int 0)]
{
@@ -5967,10 +6175,10 @@
(define_insn "call_split"
[(call (mem:SI (match_operand 0 "call_insn_operand" "cS"))
(match_operand 1 "" ""))
- (clobber (reg:SI 31))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
(clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS"
- { return MIPS_CALL ("jal", operands, 0); }
+ { return MIPS_CALL ("jal", operands, 0, 1); }
[(set_attr "type" "call")])
;; A pattern for calls that must be made directly. It is used for
@@ -5981,9 +6189,9 @@
[(call (mem:SI (match_operand 0 "const_call_insn_operand"))
(match_operand 1))
(const_int 1)
- (clobber (reg:SI 31))]
+ (clobber (reg:SI RETURN_ADDR_REGNUM))]
""
- { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0); }
+ { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0, -1); }
"reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)"
[(const_int 0)]
{
@@ -5997,10 +6205,10 @@
[(call (mem:SI (match_operand 0 "const_call_insn_operand"))
(match_operand 1))
(const_int 1)
- (clobber (reg:SI 31))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
(clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS"
- { return MIPS_CALL ("jal", operands, 0); }
+ { return MIPS_CALL ("jal", operands, 0, -1); }
[(set_attr "type" "call")])
(define_expand "call_value"
@@ -6020,9 +6228,9 @@
[(set (match_operand 0 "register_operand" "")
(call (mem:SI (match_operand 1 "call_insn_operand" "c,S"))
(match_operand 2 "" "")))
- (clobber (reg:SI 31))]
+ (clobber (reg:SI RETURN_ADDR_REGNUM))]
""
- { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); }
+ { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, 2); }
"reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)"
[(const_int 0)]
{
@@ -6037,10 +6245,10 @@
[(set (match_operand 0 "register_operand" "")
(call (mem:SI (match_operand 1 "call_insn_operand" "cS"))
(match_operand 2 "" "")))
- (clobber (reg:SI 31))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
(clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS"
- { return MIPS_CALL ("jal", operands, 1); }
+ { return MIPS_CALL ("jal", operands, 1, 2); }
[(set_attr "type" "call")])
;; See call_internal_direct.
@@ -6049,9 +6257,9 @@
(call (mem:SI (match_operand 1 "const_call_insn_operand"))
(match_operand 2)))
(const_int 1)
- (clobber (reg:SI 31))]
+ (clobber (reg:SI RETURN_ADDR_REGNUM))]
""
- { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); }
+ { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, -1); }
"reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)"
[(const_int 0)]
{
@@ -6067,10 +6275,10 @@
(call (mem:SI (match_operand 1 "const_call_insn_operand"))
(match_operand 2)))
(const_int 1)
- (clobber (reg:SI 31))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
(clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS"
- { return MIPS_CALL ("jal", operands, 1); }
+ { return MIPS_CALL ("jal", operands, 1, -1); }
[(set_attr "type" "call")])
;; See comment for call_internal.
@@ -6081,9 +6289,9 @@
(set (match_operand 3 "register_operand" "")
(call (mem:SI (match_dup 1))
(match_dup 2)))
- (clobber (reg:SI 31))]
+ (clobber (reg:SI RETURN_ADDR_REGNUM))]
""
- { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); }
+ { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, 2); }
"reload_completed && TARGET_SPLIT_CALLS && (operands[4] = insn)"
[(const_int 0)]
{
@@ -6101,10 +6309,10 @@
(set (match_operand 3 "register_operand" "")
(call (mem:SI (match_dup 1))
(match_dup 2)))
- (clobber (reg:SI 31))
+ (clobber (reg:SI RETURN_ADDR_REGNUM))
(clobber (reg:SI 28))]
"TARGET_SPLIT_CALLS"
- { return MIPS_CALL ("jal", operands, 1); }
+ { return MIPS_CALL ("jal", operands, 1, 2); }
[(set_attr "type" "call")])
;; Call subroutine returning any type.
@@ -6177,7 +6385,7 @@
[(const_int 1)]
""
{
- if (set_noreorder)
+ if (mips_noreorder.nesting_level > 0)
return "nop";
else
return "#nop";
« no previous file with comments | « gcc/gcc/config/mips/irix-crti.asm ('k') | gcc/gcc/config/mips/mips.opt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698