(const_string "yes")
(const_string "no")))
-;; Attribute defining whether or not we can use the branch-likely instructions
+;; Attribute defining whether or not we can use the branch-likely
+;; instructions.
(define_attr "branch_likely" "no,yes"
- (const
- (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0))
- (const_string "yes")
- (const_string "no"))))
+ (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0))
+ (const_string "yes")
+ (const_string "no")))
;; True if an instruction might assign to hi or lo when reloaded.
;; This is used by the TUNE_MACC_CHAINS code.
(HA "") (SA "") (DA "d")
(UHA "") (USA "") (UDA "d")])
+;; Same as d but upper-case.
+(define_mode_attr D [(SI "") (DI "D")
+ (QQ "") (HQ "") (SQ "") (DQ "D")
+ (UQQ "") (UHQ "") (USQ "") (UDQ "D")
+ (HA "") (SA "") (DA "D")
+ (UHA "") (USA "") (UDA "D")])
+
;; This attribute gives the length suffix for a sign- or zero-extension
;; instruction.
(define_mode_attr size [(QI "b") (HI "h")])
;; to use the same template.
(define_code_iterator any_extend [sign_extend zero_extend])
+;; This code iterator allows the two right shift instructions to be
+;; generated from the same template.
+(define_code_iterator any_shiftrt [ashiftrt lshiftrt])
+
;; This code iterator allows the three shift instructions to be generated
;; from the same template.
(define_code_iterator any_shift [ashift ashiftrt lshiftrt])
;; by swapping the operands.
(define_code_iterator swapped_fcond [ge gt unge ungt])
+;; Equality operators.
+(define_code_iterator equality_op [eq ne])
+
;; These code iterators allow the signed and unsigned scc operations to use
;; the same template.
(define_code_iterator any_gt [gt gtu])
(plus "addu")
(minus "subu")])
+;; <immediate_insn> expands to the name of the insn that implements
+;; a particular code to operate on immediate values.
+(define_code_attr immediate_insn [(ior "ori")
+ (xor "xori")
+ (and "andi")])
+
;; <fcond> is the c.cond.fmt condition associated with a particular code.
(define_code_attr fcond [(unordered "un")
(uneq "ueq")
(unge "ule")
(ungt "ult")])
-;; Atomic fetch bitwise operations.
-(define_code_iterator fetchop_bit [ior xor and])
+;; The value of the bit when the branch is taken for branch_bit patterns.
+;; Comparison is always against zero so this depends on the operator.
+(define_code_attr bbv [(eq "0") (ne "1")])
-;; <immediate_insn> expands to the name of the insn that implements
-;; a particular code to operate in immediate values.
-(define_code_attr immediate_insn [(ior "ori") (xor "xori") (and "andi")])
-
-;; Atomic HI and QI operations
-(define_code_iterator atomic_hiqi_op [plus minus ior xor and])
+;; This is the inverse value of bbv.
+(define_code_attr bbinv [(eq "1") (ne "0")])
\f
;; .........................
;;
;; .........................
(define_delay (and (eq_attr "type" "branch")
- (eq (symbol_ref "TARGET_MIPS16") (const_int 0)))
+ (eq (symbol_ref "TARGET_MIPS16") (const_int 0))
+ (eq_attr "branch_likely" "yes"))
+ [(eq_attr "can_delay" "yes")
+ (nil)
+ (eq_attr "can_delay" "yes")])
+
+;; Branches that don't have likely variants do not annul on false.
+(define_delay (and (eq_attr "type" "branch")
+ (eq (symbol_ref "TARGET_MIPS16") (const_int 0))
+ (eq_attr "branch_likely" "no"))
[(eq_attr "can_delay" "yes")
(nil)
- (and (eq_attr "branch_likely" "yes")
- (eq_attr "can_delay" "yes"))])
+ (nil)])
(define_delay (eq_attr "type" "jump")
[(eq_attr "can_delay" "yes")
;; These processors have PRId values of 0x00004220 and 0x00004300,
;; respectively.
-(define_expand "mulsi3"
- [(set (match_operand:SI 0 "register_operand")
- (mult:SI (match_operand:SI 1 "register_operand")
- (match_operand:SI 2 "register_operand")))]
+(define_expand "mul<mode>3"
+ [(set (match_operand:GPR 0 "register_operand")
+ (mult:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "register_operand")))]
""
{
- if (ISA_HAS_MUL3)
- emit_insn (gen_mulsi3_mult3 (operands[0], operands[1], operands[2]));
+ if (ISA_HAS_<D>MUL3)
+ emit_insn (gen_mul<mode>3_mul3 (operands[0], operands[1], operands[2]));
else if (TARGET_FIX_R4000)
- emit_insn (gen_mulsi3_r4000 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_mul<mode>3_r4000 (operands[0], operands[1], operands[2]));
else
- emit_insn (gen_mulsi3_internal (operands[0], operands[1], operands[2]));
+ emit_insn
+ (gen_mul<mode>3_internal (operands[0], operands[1], operands[2]));
DONE;
})
-(define_expand "muldi3"
- [(set (match_operand:DI 0 "register_operand")
- (mult:DI (match_operand:DI 1 "register_operand")
- (match_operand:DI 2 "register_operand")))]
- "TARGET_64BIT"
-{
- if (TARGET_FIX_R4000)
- emit_insn (gen_muldi3_r4000 (operands[0], operands[1], operands[2]));
- else
- emit_insn (gen_muldi3_internal (operands[0], operands[1], operands[2]));
- DONE;
-})
-
-(define_insn "mulsi3_mult3"
+(define_insn "mulsi3_mul3"
[(set (match_operand:SI 0 "register_operand" "=d,l")
(mult:SI (match_operand:SI 1 "register_operand" "d,d")
(match_operand:SI 2 "register_operand" "d,d")))
[(set_attr "type" "imul3,imul")
(set_attr "mode" "SI")])
+(define_insn "muldi3_mul3"
+ [(set (match_operand:DI 0 "register_operand" "=d,l")
+ (mult:DI (match_operand:DI 1 "register_operand" "d,d")
+ (match_operand:DI 2 "register_operand" "d,d")))
+ (clobber (match_scratch:DI 3 "=l,X"))]
+ "ISA_HAS_DMUL3"
+{
+ if (which_alternative == 1)
+ return "dmult\t%1,%2";
+ return "dmul\t%0,%1,%2";
+}
+ [(set_attr "type" "imul3,imul")
+ (set_attr "mode" "DI")])
+
;; If a register gets allocated to LO, and we spill to memory, the reload
;; will include a move from LO to a GPR. Merge it into the multiplication
;; if it can set the GPR directly.
;; Combiner patterns to optimize shift/truncate combinations.
-(define_insn ""
+(define_insn "*ashr_trunc<mode>"
[(set (match_operand:SUBDI 0 "register_operand" "=d")
(truncate:SUBDI
(ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
(match_operand:DI 2 "const_arith_operand" ""))))]
- "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) >= 32"
+ "TARGET_64BIT && !TARGET_MIPS16 && IN_RANGE (INTVAL (operands[2]), 32, 63)"
"dsra\t%0,%1,%2"
[(set_attr "type" "shift")
- (set_attr "mode" "SI")])
+ (set_attr "mode" "<MODE>")])
-(define_insn ""
+(define_insn "*lshr32_trunc<mode>"
[(set (match_operand:SUBDI 0 "register_operand" "=d")
(truncate:SUBDI
(lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
"TARGET_64BIT && !TARGET_MIPS16"
"dsra\t%0,%1,32"
[(set_attr "type" "shift")
- (set_attr "mode" "SI")])
+ (set_attr "mode" "<MODE>")])
+;; Logical shift by 32 or more results in proper SI values so
+;; truncation is removed by the middle end.
+(define_insn "*<optab>_trunc<mode>_exts"
+ [(set (match_operand:SUBDI 0 "register_operand" "=d")
+ (truncate:SUBDI
+ (any_shiftrt:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "const_arith_operand" ""))))]
+ "ISA_HAS_EXTS && TARGET_64BIT && UINTVAL (operands[2]) < 32"
+ "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_expand "extv"
[(set (match_operand 0 "register_operand")
- (sign_extract (match_operand:QI 1 "memory_operand")
- (match_operand 2 "immediate_operand")
- (match_operand 3 "immediate_operand")))]
+ (sign_extract (match_operand 1 "nonimmediate_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
"!TARGET_MIPS16"
{
if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]),
INTVAL (operands[3])))
DONE;
+ else if (register_operand (operands[1], GET_MODE (operands[0]))
+ && ISA_HAS_EXTS && UINTVAL (operands[2]) <= 32)
+ {
+ if (GET_MODE (operands[0]) == DImode)
+ emit_insn (gen_extvdi (operands[0], operands[1], operands[2],
+ operands[3]));
+ else
+ emit_insn (gen_extvsi (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
else
FAIL;
})
+(define_insn "extv<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (sign_extract:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand 2 "const_int_operand" "")
+ (match_operand 3 "const_int_operand" "")))]
+ "ISA_HAS_EXTS && UINTVAL (operands[2]) <= 32"
+ "exts\t%0,%1,%3,%m2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+
(define_expand "extzv"
[(set (match_operand 0 "register_operand")
(zero_extract (match_operand 1 "nonimmediate_operand")
- (match_operand 2 "immediate_operand")
- (match_operand 3 "immediate_operand")))]
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
"!TARGET_MIPS16"
{
if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
(define_insn "extzv<mode>"
[(set (match_operand:GPR 0 "register_operand" "=d")
(zero_extract:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:SI 2 "immediate_operand" "I")
- (match_operand:SI 3 "immediate_operand" "I")))]
+ (match_operand 2 "const_int_operand" "")
+ (match_operand 3 "const_int_operand" "")))]
"mips_use_ins_ext_p (operands[1], INTVAL (operands[2]),
INTVAL (operands[3]))"
"<d>ext\t%0,%1,%3,%2"
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
+(define_insn "*extzv_trunc<mode>_exts"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (truncate:GPR
+ (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>")])
+
(define_expand "insv"
[(set (zero_extract (match_operand 0 "nonimmediate_operand")
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
+;; Combiner pattern for cins (clear and insert bit field). We can
+;; implement mask-and-shift-left operation with this. Note that if
+;; the upper bit of the mask is set in an SImode operation, the mask
+;; itself will be sign-extended. mask_low_and_shift_len will
+;; therefore be greater than our threshold of 32.
+
+(define_insn "*cins<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (and:GPR
+ (ashift:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "const_int_operand" ""))
+ (match_operand:GPR 3 "const_int_operand" "")))]
+ "ISA_HAS_CINS
+ && mask_low_and_shift_p (<MODE>mode, operands[3], operands[2], 32)"
+{
+ operands[3] =
+ GEN_INT (mask_low_and_shift_len (<MODE>mode, operands[3], operands[2]));
+ return "cins\t%0,%1,%2,%m3";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<MODE>")])
+
;; Unaligned word moves generated by the bit field patterns.
;;
;; As far as the rtl is concerned, both the left-part and right-part
}
[(set_attr "length" "20")])
-;; Atomic memory operations.
-
-(define_insn "memory_barrier"
- [(set (mem:BLK (scratch))
- (unspec:BLK [(const_int 0)] UNSPEC_MEMORY_BARRIER))]
- "GENERATE_SYNC"
- "%|sync%-")
-
-(define_insn "sync_compare_and_swap<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
- (set (match_dup 1)
- (unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "dJ,dJ")
- (match_operand:GPR 3 "arith_operand" "I,d")]
- UNSPEC_COMPARE_AND_SWAP))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_COMPARE_AND_SWAP ("<d>", "li");
- else
- return MIPS_COMPARE_AND_SWAP ("<d>", "move");
-}
- [(set_attr "length" "32")])
-
-(define_expand "sync_compare_and_swap<mode>"
- [(match_operand:SHORT 0 "register_operand")
- (match_operand:SHORT 1 "memory_operand")
- (match_operand:SHORT 2 "general_operand")
- (match_operand:SHORT 3 "general_operand")]
- "GENERATE_LL_SC"
-{
- union mips_gen_fn_ptrs generator;
- generator.fn_6 = gen_compare_and_swap_12;
- mips_expand_atomic_qihi (generator,
- operands[0], operands[1], operands[2], operands[3]);
- DONE;
-})
-
-;; Helper insn for mips_expand_atomic_qihi.
-(define_insn "compare_and_swap_12"
- [(set (match_operand:SI 0 "register_operand" "=&d,&d")
- (match_operand:SI 1 "memory_operand" "+R,R"))
- (set (match_dup 1)
- (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d")
- (match_operand:SI 3 "register_operand" "d,d")
- (match_operand:SI 4 "reg_or_0_operand" "dJ,dJ")
- (match_operand:SI 5 "reg_or_0_operand" "d,J")]
- UNSPEC_COMPARE_AND_SWAP_12))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_NONZERO_OP);
- else
- return MIPS_COMPARE_AND_SWAP_12 (MIPS_COMPARE_AND_SWAP_12_ZERO_OP);
-}
- [(set_attr "length" "40,36")])
-
-(define_insn "sync_add<mode>"
- [(set (match_operand:GPR 0 "memory_operand" "+R,R")
- (unspec_volatile:GPR
- [(plus:GPR (match_dup 0)
- (match_operand:GPR 1 "arith_operand" "I,d"))]
- UNSPEC_SYNC_OLD_OP))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_OP ("<d>", "<d>addiu");
- else
- return MIPS_SYNC_OP ("<d>", "<d>addu");
-}
- [(set_attr "length" "28")])
-
-(define_expand "sync_<optab><mode>"
- [(set (match_operand:SHORT 0 "memory_operand")
- (unspec_volatile:SHORT
- [(atomic_hiqi_op:SHORT (match_dup 0)
- (match_operand:SHORT 1 "general_operand"))]
- UNSPEC_SYNC_OLD_OP))]
- "GENERATE_LL_SC"
-{
- union mips_gen_fn_ptrs generator;
- generator.fn_4 = gen_sync_<optab>_12;
- mips_expand_atomic_qihi (generator,
- NULL, operands[0], operands[1], NULL);
- DONE;
-})
-
-;; Helper insn for sync_<optab><mode>
-(define_insn "sync_<optab>_12"
- [(set (match_operand:SI 0 "memory_operand" "+R")
- (unspec_volatile:SI
- [(match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "register_operand" "d")
- (atomic_hiqi_op:SI (match_dup 0)
- (match_operand:SI 3 "register_operand" "dJ"))]
- UNSPEC_SYNC_OLD_OP_12))
- (clobber (match_scratch:SI 4 "=&d"))]
- "GENERATE_LL_SC"
-{
- return MIPS_SYNC_OP_12 ("<insn>", MIPS_SYNC_OP_12_NOT_NOP);
-}
- [(set_attr "length" "40")])
-
-(define_expand "sync_old_<optab><mode>"
- [(parallel [
- (set (match_operand:SHORT 0 "register_operand")
- (match_operand:SHORT 1 "memory_operand"))
- (set (match_dup 1)
- (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
- (match_dup 1)
- (match_operand:SHORT 2 "general_operand"))]
- UNSPEC_SYNC_OLD_OP))])]
- "GENERATE_LL_SC"
-{
- union mips_gen_fn_ptrs generator;
- generator.fn_5 = gen_sync_old_<optab>_12;
- mips_expand_atomic_qihi (generator,
- operands[0], operands[1], operands[2], NULL);
- DONE;
-})
-
-;; Helper insn for sync_old_<optab><mode>
-(define_insn "sync_old_<optab>_12"
- [(set (match_operand:SI 0 "register_operand" "=&d")
- (match_operand:SI 1 "memory_operand" "+R"))
- (set (match_dup 1)
- (unspec_volatile:SI
- [(match_operand:SI 2 "register_operand" "d")
- (match_operand:SI 3 "register_operand" "d")
- (atomic_hiqi_op:SI (match_dup 0)
- (match_operand:SI 4 "register_operand" "dJ"))]
- UNSPEC_SYNC_OLD_OP_12))
- (clobber (match_scratch:SI 5 "=&d"))]
- "GENERATE_LL_SC"
-{
- return MIPS_SYNC_OLD_OP_12 ("<insn>", MIPS_SYNC_OLD_OP_12_NOT_NOP,
- MIPS_SYNC_OLD_OP_12_NOT_NOP_REG);
-}
- [(set_attr "length" "40")])
-
-(define_expand "sync_new_<optab><mode>"
- [(parallel [
- (set (match_operand:SHORT 0 "register_operand")
- (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT
- (match_operand:SHORT 1 "memory_operand")
- (match_operand:SHORT 2 "general_operand"))]
- UNSPEC_SYNC_NEW_OP))
- (set (match_dup 1)
- (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
- UNSPEC_SYNC_NEW_OP))])]
- "GENERATE_LL_SC"
-{
- union mips_gen_fn_ptrs generator;
- generator.fn_5 = gen_sync_new_<optab>_12;
- mips_expand_atomic_qihi (generator,
- operands[0], operands[1], operands[2], NULL);
- DONE;
-})
-
-;; Helper insn for sync_new_<optab><mode>
-(define_insn "sync_new_<optab>_12"
- [(set (match_operand:SI 0 "register_operand" "=&d")
- (unspec_volatile:SI
- [(match_operand:SI 1 "memory_operand" "+R")
- (match_operand:SI 2 "register_operand" "d")
- (match_operand:SI 3 "register_operand" "d")
- (atomic_hiqi_op:SI (match_dup 0)
- (match_operand:SI 4 "register_operand" "dJ"))]
- UNSPEC_SYNC_NEW_OP_12))
- (set (match_dup 1)
- (unspec_volatile:SI
- [(match_dup 1)
- (match_dup 2)
- (match_dup 3)
- (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
- "GENERATE_LL_SC"
-{
- return MIPS_SYNC_NEW_OP_12 ("<insn>", MIPS_SYNC_NEW_OP_12_NOT_NOP);
-}
- [(set_attr "length" "40")])
-
-(define_expand "sync_nand<mode>"
- [(set (match_operand:SHORT 0 "memory_operand")
- (unspec_volatile:SHORT
- [(match_dup 0)
- (match_operand:SHORT 1 "general_operand")]
- UNSPEC_SYNC_OLD_OP))]
- "GENERATE_LL_SC"
-{
- union mips_gen_fn_ptrs generator;
- generator.fn_4 = gen_sync_nand_12;
- mips_expand_atomic_qihi (generator,
- NULL, operands[0], operands[1], NULL);
- DONE;
-})
-
-;; Helper insn for sync_nand<mode>
-(define_insn "sync_nand_12"
- [(set (match_operand:SI 0 "memory_operand" "+R")
- (unspec_volatile:SI
- [(match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "register_operand" "d")
- (match_dup 0)
- (match_operand:SI 3 "register_operand" "dJ")]
- UNSPEC_SYNC_OLD_OP_12))
- (clobber (match_scratch:SI 4 "=&d"))]
- "GENERATE_LL_SC"
-{
- return MIPS_SYNC_OP_12 ("and", MIPS_SYNC_OP_12_NOT_NOT);
-}
- [(set_attr "length" "44")])
-
-(define_expand "sync_old_nand<mode>"
- [(parallel [
- (set (match_operand:SHORT 0 "register_operand")
- (match_operand:SHORT 1 "memory_operand"))
- (set (match_dup 1)
- (unspec_volatile:SHORT [(match_dup 1)
- (match_operand:SHORT 2 "general_operand")]
- UNSPEC_SYNC_OLD_OP))])]
- "GENERATE_LL_SC"
-{
- union mips_gen_fn_ptrs generator;
- generator.fn_5 = gen_sync_old_nand_12;
- mips_expand_atomic_qihi (generator,
- operands[0], operands[1], operands[2], NULL);
- DONE;
-})
-
-;; Helper insn for sync_old_nand<mode>
-(define_insn "sync_old_nand_12"
- [(set (match_operand:SI 0 "register_operand" "=&d")
- (match_operand:SI 1 "memory_operand" "+R"))
- (set (match_dup 1)
- (unspec_volatile:SI
- [(match_operand:SI 2 "register_operand" "d")
- (match_operand:SI 3 "register_operand" "d")
- (match_operand:SI 4 "register_operand" "dJ")]
- UNSPEC_SYNC_OLD_OP_12))
- (clobber (match_scratch:SI 5 "=&d"))]
- "GENERATE_LL_SC"
-{
- return MIPS_SYNC_OLD_OP_12 ("and", MIPS_SYNC_OLD_OP_12_NOT_NOT,
- MIPS_SYNC_OLD_OP_12_NOT_NOT_REG);
-}
- [(set_attr "length" "44")])
-
-(define_expand "sync_new_nand<mode>"
- [(parallel [
- (set (match_operand:SHORT 0 "register_operand")
- (unspec_volatile:SHORT [(match_operand:SHORT 1 "memory_operand")
- (match_operand:SHORT 2 "general_operand")]
- UNSPEC_SYNC_NEW_OP))
- (set (match_dup 1)
- (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)]
- UNSPEC_SYNC_NEW_OP))])]
- "GENERATE_LL_SC"
-{
- union mips_gen_fn_ptrs generator;
- generator.fn_5 = gen_sync_new_nand_12;
- mips_expand_atomic_qihi (generator,
- operands[0], operands[1], operands[2], NULL);
- DONE;
-})
-
-;; Helper insn for sync_new_nand<mode>
-(define_insn "sync_new_nand_12"
- [(set (match_operand:SI 0 "register_operand" "=&d")
- (unspec_volatile:SI
- [(match_operand:SI 1 "memory_operand" "+R")
- (match_operand:SI 2 "register_operand" "d")
- (match_operand:SI 3 "register_operand" "d")
- (match_operand:SI 4 "register_operand" "dJ")]
- UNSPEC_SYNC_NEW_OP_12))
- (set (match_dup 1)
- (unspec_volatile:SI
- [(match_dup 1)
- (match_dup 2)
- (match_dup 3)
- (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))]
- "GENERATE_LL_SC"
-{
- return MIPS_SYNC_NEW_OP_12 ("and", MIPS_SYNC_NEW_OP_12_NOT_NOT);
-}
- [(set_attr "length" "40")])
-
-(define_insn "sync_sub<mode>"
- [(set (match_operand:GPR 0 "memory_operand" "+R")
- (unspec_volatile:GPR
- [(minus:GPR (match_dup 0)
- (match_operand:GPR 1 "register_operand" "d"))]
- UNSPEC_SYNC_OLD_OP))]
- "GENERATE_LL_SC"
-{
- return MIPS_SYNC_OP ("<d>", "<d>subu");
-}
- [(set_attr "length" "28")])
-
-(define_insn "sync_old_add<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
- (set (match_dup 1)
- (unspec_volatile:GPR
- [(plus:GPR (match_dup 1)
- (match_operand:GPR 2 "arith_operand" "I,d"))]
- UNSPEC_SYNC_OLD_OP))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_OLD_OP ("<d>", "<d>addiu");
- else
- return MIPS_SYNC_OLD_OP ("<d>", "<d>addu");
-}
- [(set_attr "length" "28")])
-
-(define_insn "sync_old_sub<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d")
- (match_operand:GPR 1 "memory_operand" "+R"))
- (set (match_dup 1)
- (unspec_volatile:GPR
- [(minus:GPR (match_dup 1)
- (match_operand:GPR 2 "register_operand" "d"))]
- UNSPEC_SYNC_OLD_OP))]
- "GENERATE_LL_SC"
-{
- return MIPS_SYNC_OLD_OP ("<d>", "<d>subu");
-}
- [(set_attr "length" "28")])
-
-(define_insn "sync_new_add<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (plus:GPR (match_operand:GPR 1 "memory_operand" "+R,R")
- (match_operand:GPR 2 "arith_operand" "I,d")))
- (set (match_dup 1)
- (unspec_volatile:GPR
- [(plus:GPR (match_dup 1) (match_dup 2))]
- UNSPEC_SYNC_NEW_OP))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_NEW_OP ("<d>", "<d>addiu");
- else
- return MIPS_SYNC_NEW_OP ("<d>", "<d>addu");
-}
- [(set_attr "length" "28")])
-
-(define_insn "sync_new_sub<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d")
- (minus:GPR (match_operand:GPR 1 "memory_operand" "+R")
- (match_operand:GPR 2 "register_operand" "d")))
- (set (match_dup 1)
- (unspec_volatile:GPR
- [(minus:GPR (match_dup 1) (match_dup 2))]
- UNSPEC_SYNC_NEW_OP))]
- "GENERATE_LL_SC"
-{
- return MIPS_SYNC_NEW_OP ("<d>", "<d>subu");
-}
- [(set_attr "length" "28")])
-
-(define_insn "sync_<optab><mode>"
- [(set (match_operand:GPR 0 "memory_operand" "+R,R")
- (unspec_volatile:GPR
- [(fetchop_bit:GPR (match_operand:GPR 1 "uns_arith_operand" "K,d")
- (match_dup 0))]
- UNSPEC_SYNC_OLD_OP))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_OP ("<d>", "<immediate_insn>");
- else
- return MIPS_SYNC_OP ("<d>", "<insn>");
-}
- [(set_attr "length" "28")])
-
-(define_insn "sync_old_<optab><mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
- (set (match_dup 1)
- (unspec_volatile:GPR
- [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
- (match_dup 1))]
- UNSPEC_SYNC_OLD_OP))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_OLD_OP ("<d>", "<immediate_insn>");
- else
- return MIPS_SYNC_OLD_OP ("<d>", "<insn>");
-}
- [(set_attr "length" "28")])
-
-(define_insn "sync_new_<optab><mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
- (set (match_dup 1)
- (unspec_volatile:GPR
- [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d")
- (match_dup 1))]
- UNSPEC_SYNC_NEW_OP))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_NEW_OP ("<d>", "<immediate_insn>");
- else
- return MIPS_SYNC_NEW_OP ("<d>", "<insn>");
-}
- [(set_attr "length" "28")])
-
-(define_insn "sync_nand<mode>"
- [(set (match_operand:GPR 0 "memory_operand" "+R,R")
- (unspec_volatile:GPR [(match_operand:GPR 1 "uns_arith_operand" "K,d")]
- UNSPEC_SYNC_OLD_OP))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_NAND ("<d>", "andi");
- else
- return MIPS_SYNC_NAND ("<d>", "and");
-}
- [(set_attr "length" "32")])
-
-(define_insn "sync_old_nand<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
- (set (match_dup 1)
- (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
- UNSPEC_SYNC_OLD_OP))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_OLD_NAND ("<d>", "andi");
- else
- return MIPS_SYNC_OLD_NAND ("<d>", "and");
-}
- [(set_attr "length" "32")])
-
-(define_insn "sync_new_nand<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
- (set (match_dup 1)
- (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")]
- UNSPEC_SYNC_NEW_OP))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_NEW_NAND ("<d>", "andi");
- else
- return MIPS_SYNC_NEW_NAND ("<d>", "and");
-}
- [(set_attr "length" "32")])
-
-(define_insn "sync_lock_test_and_set<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d,&d")
- (match_operand:GPR 1 "memory_operand" "+R,R"))
- (set (match_dup 1)
- (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")]
- UNSPEC_SYNC_EXCHANGE))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_EXCHANGE ("<d>", "li");
- else
- return MIPS_SYNC_EXCHANGE ("<d>", "move");
-}
- [(set_attr "length" "24")])
-
-(define_expand "sync_lock_test_and_set<mode>"
- [(match_operand:SHORT 0 "register_operand")
- (match_operand:SHORT 1 "memory_operand")
- (match_operand:SHORT 2 "general_operand")]
- "GENERATE_LL_SC"
-{
- union mips_gen_fn_ptrs generator;
- generator.fn_5 = gen_test_and_set_12;
- mips_expand_atomic_qihi (generator,
- operands[0], operands[1], operands[2], NULL);
- DONE;
-})
-
-(define_insn "test_and_set_12"
- [(set (match_operand:SI 0 "register_operand" "=&d,&d")
- (match_operand:SI 1 "memory_operand" "+R,R"))
- (set (match_dup 1)
- (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d")
- (match_operand:SI 3 "register_operand" "d,d")
- (match_operand:SI 4 "arith_operand" "d,J")]
- UNSPEC_SYNC_EXCHANGE_12))]
- "GENERATE_LL_SC"
-{
- if (which_alternative == 0)
- return MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_NONZERO_OP);
- else
- return MIPS_SYNC_EXCHANGE_12 (MIPS_SYNC_EXCHANGE_12_ZERO_OP);
-}
- [(set_attr "length" "28,24")])
\f
;; Block moves, see mips.c for more details.
;; Argument 0 is the destination
(if_then_else (match_operand 0)
(label_ref (match_operand 1))
(pc)))])
+
+;; Branch if bit is set/clear.
+
+(define_insn "*branch_bit<bbv><mode>"
+ [(set (pc)
+ (if_then_else
+ (equality_op (zero_extract:GPR
+ (match_operand:GPR 1 "register_operand" "d")
+ (const_int 1)
+ (match_operand 2 "const_int_operand" ""))
+ (const_int 0))
+ (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>", "%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 1 "register_operand" "d")
+ (const_int 1)
+ (match_operand 2 "const_int_operand" ""))
+ (const_int 0))
+ (pc)
+ (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>", "%1,%2,%0"),
+ MIPS_BRANCH ("bbit<bbv>", "%1,%2,%0"));
+}
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")
+ (set_attr "branch_likely" "no")])
\f
;;
;; ....................
""
{ if (mips_expand_scc (EQ, operands[0])) DONE; else FAIL; })
-(define_insn "*seq_<GPR:mode><GPR2:mode>"
+(define_insn "*seq_zero_<GPR:mode><GPR2:mode>"
[(set (match_operand:GPR2 0 "register_operand" "=d")
(eq:GPR2 (match_operand:GPR 1 "register_operand" "d")
(const_int 0)))]
- "!TARGET_MIPS16"
+ "!TARGET_MIPS16 && !ISA_HAS_SEQ_SNE"
"sltu\t%0,%1,1"
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
-(define_insn "*seq_<GPR:mode><GPR2:mode>_mips16"
+(define_insn "*seq_zero_<GPR:mode><GPR2:mode>_mips16"
[(set (match_operand:GPR2 0 "register_operand" "=t")
(eq:GPR2 (match_operand:GPR 1 "register_operand" "d")
(const_int 0)))]
- "TARGET_MIPS16"
+ "TARGET_MIPS16 && !ISA_HAS_SEQ_SNE"
"sltu\t%1,1"
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
+;; Generate sltiu unless using seq results in better code.
+(define_insn "*seq_<GPR:mode><GPR2:mode>_seq"
+ [(set (match_operand:GPR2 0 "register_operand" "=d,d,d")
+ (eq:GPR2 (match_operand:GPR 1 "register_operand" "%d,d,d")
+ (match_operand:GPR 2 "reg_imm10_operand" "d,J,YB")))]
+ "ISA_HAS_SEQ_SNE"
+ "@
+ seq\t%0,%1,%2
+ sltiu\t%0,%1,1
+ seqi\t%0,%1,%2"
+ [(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.
"!TARGET_MIPS16"
{ if (mips_expand_scc (NE, operands[0])) DONE; else FAIL; })
-(define_insn "*sne_<GPR:mode><GPR2:mode>"
+(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")
(const_int 0)))]
- "!TARGET_MIPS16"
+ "!TARGET_MIPS16 && !ISA_HAS_SEQ_SNE"
"sltu\t%0,%.,%1"
[(set_attr "type" "slt")
(set_attr "mode" "<GPR:MODE>")])
+;; Generate sltu unless using sne results in better code.
+(define_insn "*sne_<GPR:mode><GPR2:mode>_sne"
+ [(set (match_operand:GPR2 0 "register_operand" "=d,d,d")
+ (ne:GPR2 (match_operand:GPR 1 "register_operand" "%d,d,d")
+ (match_operand:GPR 2 "reg_imm10_operand" "d,J,YB")))]
+ "ISA_HAS_SEQ_SNE"
+ "@
+ sne\t%0,%1,%2
+ sltu\t%0,%.,%1
+ snei\t%0,%1,%2"
+ [(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)
(set_attr "can_delay" "no")
(set_attr "mode" "<MODE>")])
\f
+;; Synchronization instructions.
+
+(include "sync.md")
+
; The MIPS Paired-Single Floating Point and MIPS-3D Instructions.
(include "mips-ps-3d.md")