aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/mips/mips.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/config/mips/mips.md')
-rw-r--r--gcc-4.9/gcc/config/mips/mips.md452
1 files changed, 373 insertions, 79 deletions
diff --git a/gcc-4.9/gcc/config/mips/mips.md b/gcc-4.9/gcc/config/mips/mips.md
index 9bf8cb7f4..1366362f3 100644
--- a/gcc-4.9/gcc/config/mips/mips.md
+++ b/gcc-4.9/gcc/config/mips/mips.md
@@ -65,6 +65,9 @@
sr71000
xlr
xlp
+ p5600
+ w32
+ w64
])
(define_c_enum "unspec" [
@@ -239,6 +242,13 @@
(const_string "yes")]
(const_string "no")))
+;; True if the main data type is four times of the size of a word.
+(define_attr "qword_mode" "no,yes"
+ (cond [(and (eq_attr "mode" "TI,TF")
+ (not (match_test "TARGET_64BIT")))
+ (const_string "yes")]
+ (const_string "no")))
+
;; Attributes describing a sync loop. These loops have the form:
;;
;; if (RELEASE_BARRIER == YES) sync
@@ -396,6 +406,11 @@
(eq_attr "move_type" "constN,shift_shift")
(const_string "multi")
+ ;; These types of move are split for quadword modes only.
+ (and (eq_attr "move_type" "move,const")
+ (eq_attr "qword_mode" "yes"))
+ (const_string "multi")
+
;; These types of move are split for doubleword modes only.
(and (eq_attr "move_type" "move,const")
(eq_attr "dword_mode" "yes"))
@@ -431,11 +446,21 @@
(const_string "none"))
(define_attr "enabled" "no,yes"
- (if_then_else (ior (eq_attr "compression" "all,none")
- (and (eq_attr "compression" "micromips")
- (match_test "TARGET_MICROMIPS")))
- (const_string "yes")
- (const_string "no")))
+ (cond [;; The O32 FPXX ABI prohibits direct moves between GR_REG and FR_REG
+ ;; for 64-bit values.
+ (and (eq_attr "move_type" "mtc,mfc")
+ (match_test "(TARGET_FLOATXX && !ISA_HAS_MXHC1)
+ || (mips_abi == ABI_32
+ && TARGET_FLOAT64 && !TARGET_ODD_SPREG)")
+ (eq_attr "dword_mode" "yes"))
+ (const_string "no")
+
+ ;; The micromips compressed instruction alternatives should only be
+ ;; considered when targetting micromips.
+ (and (eq_attr "compression" "micromips")
+ (match_test "!TARGET_MICROMIPS"))
+ (const_string "no")]
+ (const_string "yes")))
;; The number of individual instructions that a non-branch pattern generates,
;; using units of BASE_INSN_LENGTH.
@@ -467,6 +492,18 @@
(eq_attr "dword_mode" "yes"))
(const_int 2)
+ ;; Check for quadword moves that are decomposed into four
+ ;; instructions.
+ (and (eq_attr "move_type" "mtc,mfc,move")
+ (eq_attr "qword_mode" "yes"))
+ (const_int 16)
+
+ ;; Quadword CONST moves are split into four word
+ ;; CONST moves.
+ (and (eq_attr "move_type" "const")
+ (eq_attr "qword_mode" "yes"))
+ (symbol_ref "mips_split_128bit_const_insns (operands[1]) * 4")
+
;; Constants, loads and stores are handled by external routines.
(and (eq_attr "move_type" "const,constN")
(eq_attr "dword_mode" "yes"))
@@ -508,7 +545,9 @@
(const_int 2)
(eq_attr "type" "idiv,idiv3")
- (symbol_ref "mips_idiv_insns ()")
+ (cond [(eq_attr "mode" "TI")
+ (symbol_ref "mips_msa_idiv_insns () * 4")]
+ (symbol_ref "mips_idiv_insns () * 4"))
(not (eq_attr "sync_mem" "none"))
(symbol_ref "mips_sync_loop_insns (insn, operands)")]
@@ -758,6 +797,11 @@
&& !TARGET_LOONGSON_2EF
&& !TARGET_MIPS5900")])
+;; This mode iterator allows :FPCC to be used anywhere that an FP condition
+;; is needed.
+(define_mode_iterator FPCC [(CC "!ISA_HAS_CCF")
+ (CCF "ISA_HAS_CCF")])
+
;; 32-bit integer moves for which we provide move patterns.
(define_mode_iterator IMOVE32
[SI
@@ -847,14 +891,16 @@
;; This attribute gives the best constraint to use for registers of
;; a given mode.
-(define_mode_attr reg [(SI "d") (DI "d") (CC "z")])
+(define_mode_attr reg [(SI "d") (DI "d") (CC "z") (CCF "f")])
;; This attribute gives the format suffix for floating-point operations.
(define_mode_attr fmt [(SF "s") (DF "d") (V2SF "ps")])
;; This attribute gives the upper-case mode name for one unit of a
-;; floating-point mode.
-(define_mode_attr UNITMODE [(SF "SF") (DF "DF") (V2SF "SF")])
+;; floating-point mode or vector mode.
+(define_mode_attr UNITMODE [(SF "SF") (DF "DF") (V2SF "SF") (V4SF "SF")
+ (V16QI "QI") (V8HI "HI") (V4SI "SI") (V2DI "DI")
+ (V2DF "DF")])
;; This attribute gives the integer mode that has the same size as a
;; fixed-point mode.
@@ -887,6 +933,9 @@
(define_mode_attr sqrt_condition
[(SF "!ISA_MIPS1") (DF "!ISA_MIPS1") (V2SF "TARGET_SB1")])
+;; This attribute provides the correct nmemonic for each FP condition mode.
+(define_mode_attr fpcmp [(CC "c") (CCF "cmp")])
+
;; This code iterator allows signed and unsigned widening multiplications
;; to use the same template.
(define_code_iterator any_extend [sign_extend zero_extend])
@@ -909,7 +958,10 @@
;; This code iterator allows all native floating-point comparisons to be
;; generated from the same template.
-(define_code_iterator fcond [unordered uneq unlt unle eq lt le])
+(define_code_iterator fcond [unordered uneq unlt unle eq lt le
+ (ordered "ISA_HAS_CCF")
+ (ltgt "ISA_HAS_CCF")
+ (ne "ISA_HAS_CCF")])
;; This code iterator is used for comparisons that can be implemented
;; by swapping the operands.
@@ -982,7 +1034,10 @@
(unle "ule")
(eq "eq")
(lt "lt")
- (le "le")])
+ (le "le")
+ (ordered "or")
+ (ltgt "ne")
+ (ne "une")])
;; Similar, but for swapped conditions.
(define_code_attr swapped_fcond [(ge "le")
@@ -996,6 +1051,10 @@
;; This is the inverse value of bbv.
(define_code_attr bbinv [(eq "1") (ne "0")])
+
+;; The sel nmemonic to use depending on the condition test.
+(define_code_attr sel [(eq "seleqz") (ne "selnez")])
+(define_code_attr selinv [(eq "selnez") (ne "seleqz")])
;; .........................
;;
@@ -1050,6 +1109,7 @@
(eq_attr "type" "ghost")
"nothing")
+(include "p5600.md")
(include "4k.md")
(include "5k.md")
(include "20kc.md")
@@ -1103,18 +1163,27 @@
[(match_operand:GPR 1 "reg_or_0_operand")
(match_operand:GPR 2 "arith_operand")])
(match_operand 3 "const_0_operand"))]
- "ISA_HAS_COND_TRAP"
+ "ISA_HAS_COND_TRAPI || ISA_HAS_COND_TRAP"
{
mips_expand_conditional_trap (operands[0]);
DONE;
})
+(define_insn "*conditional_trap_reg<mode>"
+ [(trap_if (match_operator:GPR 0 "trap_comparison_operator"
+ [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
+ (match_operand:GPR 2 "reg_or_0_operand" "dJ")])
+ (const_int 0))]
+ "ISA_HAS_COND_TRAP && !ISA_HAS_COND_TRAPI"
+ "t%C0\t%z1,%2"
+ [(set_attr "type" "trap")])
+
(define_insn "*conditional_trap<mode>"
[(trap_if (match_operator:GPR 0 "trap_comparison_operator"
[(match_operand:GPR 1 "reg_or_0_operand" "dJ")
(match_operand:GPR 2 "arith_operand" "dI")])
(const_int 0))]
- "ISA_HAS_COND_TRAP"
+ "ISA_HAS_COND_TRAPI"
"t%C0\t%z1,%2"
[(set_attr "type" "trap")])
@@ -1482,13 +1551,13 @@
[(set (match_operand:GPR 0 "register_operand")
(mult:GPR (match_operand:GPR 1 "register_operand")
(match_operand:GPR 2 "register_operand")))]
- "ISA_HAS_<D>MULT"
+ "ISA_HAS_<D>MULT || ISA_HAS_R6<D>MUL"
{
rtx lo;
- if (TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A)
- emit_insn (gen_mul<mode>3_mul3_loongson (operands[0], operands[1],
- operands[2]));
+ if (TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A || ISA_HAS_R6<D>MUL)
+ emit_insn (gen_mul<mode>3_mul3_nohilo (operands[0], operands[1],
+ operands[2]));
else if (ISA_HAS_<D>MUL3)
emit_insn (gen_mul<mode>3_mul3 (operands[0], operands[1], operands[2]));
else if (TARGET_MIPS16)
@@ -1505,16 +1574,18 @@
DONE;
})
-(define_insn "mul<mode>3_mul3_loongson"
+(define_insn "mul<mode>3_mul3_nohilo"
[(set (match_operand:GPR 0 "register_operand" "=d")
(mult:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand:GPR 2 "register_operand" "d")))]
- "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A"
+ "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A || ISA_HAS_R6<D>MUL"
{
if (TARGET_LOONGSON_2EF)
return "<d>multu.g\t%0,%1,%2";
- else
+ else if (TARGET_LOONGSON_3A)
return "gs<d>multu\t%0,%1,%2";
+ else
+ return "<d>mul\t%0,%1,%2";
}
[(set_attr "type" "imul3nc")
(set_attr "mode" "<MODE>")])
@@ -1622,40 +1693,66 @@
;; copy instructions. Reload therefore thinks that the second alternative
;; is two reloads more costly than the first. We add "*?*?" to the first
;; alternative as a counterweight.
+;;
+;; LRA simulates reload but the cost of reloading scratches is lower
+;; than of the classic reload. For the time being, removing the counterweight
+;; for LRA is more profitable.
(define_insn "*mul_acc_si"
- [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
- (match_operand:SI 2 "register_operand" "d,d"))
- (match_operand:SI 3 "register_operand" "0,d")))
- (clobber (match_scratch:SI 4 "=X,l"))
- (clobber (match_scratch:SI 5 "=X,&d"))]
+ [(set (match_operand:SI 0 "register_operand" "=l*?*?,l,d?")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
+ (match_operand:SI 2 "register_operand" "d,d,d"))
+ (match_operand:SI 3 "register_operand" "0,0,d")))
+ (clobber (match_scratch:SI 4 "=X,X,l"))
+ (clobber (match_scratch:SI 5 "=X,X,&d"))]
"GENERATE_MADD_MSUB && !TARGET_MIPS16"
"@
madd\t%1,%2
+ madd\t%1,%2
#"
[(set_attr "type" "imadd")
(set_attr "accum_in" "3")
(set_attr "mode" "SI")
- (set_attr "insn_count" "1,2")])
+ (set_attr "insn_count" "1,1,2")
+ (set (attr "enabled")
+ (cond [(and (eq_attr "alternative" "0")
+ (match_test "!mips_lra_flag"))
+ (const_string "yes")
+ (and (eq_attr "alternative" "1")
+ (match_test "mips_lra_flag"))
+ (const_string "yes")
+ (eq_attr "alternative" "2")
+ (const_string "yes")]
+ (const_string "no")))])
;; The same idea applies here. The middle alternative needs one less
;; clobber than the final alternative, so we add "*?" as a counterweight.
(define_insn "*mul_acc_si_r3900"
- [(set (match_operand:SI 0 "register_operand" "=l*?*?,d*?,d?")
- (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
- (match_operand:SI 2 "register_operand" "d,d,d"))
- (match_operand:SI 3 "register_operand" "0,l,d")))
- (clobber (match_scratch:SI 4 "=X,3,l"))
- (clobber (match_scratch:SI 5 "=X,X,&d"))]
+ [(set (match_operand:SI 0 "register_operand" "=l*?*?,l,d*?,d?")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d,d")
+ (match_operand:SI 2 "register_operand" "d,d,d,d"))
+ (match_operand:SI 3 "register_operand" "0,0,l,d")))
+ (clobber (match_scratch:SI 4 "=X,X,3,l"))
+ (clobber (match_scratch:SI 5 "=X,X,X,&d"))]
"TARGET_MIPS3900 && !TARGET_MIPS16"
"@
madd\t%1,%2
+ madd\t%1,%2
madd\t%0,%1,%2
#"
[(set_attr "type" "imadd")
(set_attr "accum_in" "3")
(set_attr "mode" "SI")
- (set_attr "insn_count" "1,1,2")])
+ (set_attr "insn_count" "1,1,1,2")
+ (set (attr "enabled")
+ (cond [(and (eq_attr "alternative" "0")
+ (match_test "!mips_lra_flag"))
+ (const_string "yes")
+ (and (eq_attr "alternative" "1")
+ (match_test "mips_lra_flag"))
+ (const_string "yes")
+ (eq_attr "alternative" "2,3")
+ (const_string "yes")]
+ (const_string "no")))])
;; Split *mul_acc_si if both the source and destination accumulator
;; values are GPRs.
@@ -1859,20 +1956,31 @@
;; See the comment above *mul_add_si for details.
(define_insn "*mul_sub_si"
- [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?")
- (minus:SI (match_operand:SI 1 "register_operand" "0,d")
- (mult:SI (match_operand:SI 2 "register_operand" "d,d")
- (match_operand:SI 3 "register_operand" "d,d"))))
- (clobber (match_scratch:SI 4 "=X,l"))
- (clobber (match_scratch:SI 5 "=X,&d"))]
+ [(set (match_operand:SI 0 "register_operand" "=l*?*?,l,d?")
+ (minus:SI (match_operand:SI 1 "register_operand" "0,0,d")
+ (mult:SI (match_operand:SI 2 "register_operand" "d,d,d")
+ (match_operand:SI 3 "register_operand" "d,d,d"))))
+ (clobber (match_scratch:SI 4 "=X,X,l"))
+ (clobber (match_scratch:SI 5 "=X,X,&d"))]
"GENERATE_MADD_MSUB"
"@
msub\t%2,%3
+ msub\t%2,%3
#"
[(set_attr "type" "imadd")
(set_attr "accum_in" "1")
(set_attr "mode" "SI")
- (set_attr "insn_count" "1,2")])
+ (set_attr "insn_count" "1,1,2")
+ (set (attr "enabled")
+ (cond [(and (eq_attr "alternative" "0")
+ (match_test "!mips_lra_flag"))
+ (const_string "yes")
+ (and (eq_attr "alternative" "1")
+ (match_test "mips_lra_flag"))
+ (const_string "yes")
+ (eq_attr "alternative" "2")
+ (const_string "yes")]
+ (const_string "no")))])
;; Split *mul_sub_si if both the source and destination accumulator
;; values are GPRs.
@@ -1913,6 +2021,24 @@
DONE;
})
+(define_expand "<u>mulsidi3_32bit_r6"
+ [(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 && ISA_HAS_R6MUL"
+{
+ rtx dest = gen_reg_rtx (DImode);
+ rtx low = mips_subword (dest, 0);
+ rtx high = mips_subword (dest, 1);
+
+ emit_insn (gen_mulsi3_mul3_nohilo (low, operands[1], operands[2]));
+ emit_insn (gen_<su>mulsi3_highpart_r6 (high, operands[1], operands[2]));
+
+ emit_move_insn (mips_subword (operands[0], 0), low);
+ emit_move_insn (mips_subword (operands[0], 1), high);
+ DONE;
+})
+
(define_expand "<u>mulsidi3_32bit_mips16"
[(set (match_operand:DI 0 "register_operand")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
@@ -1934,7 +2060,7 @@
[(set (match_operand:DI 0 "muldiv_target_operand" "=ka")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
(any_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
- "!TARGET_64BIT && (!TARGET_FIX_R4000 || ISA_HAS_DSP)"
+ "!TARGET_64BIT && (!TARGET_FIX_R4000 || ISA_HAS_DSP) && ISA_HAS_MULT"
{
if (ISA_HAS_DSP_MULT)
return "mult<u>\t%q0,%1,%2";
@@ -1949,7 +2075,7 @@
(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:DI 3 "=x"))]
- "!TARGET_64BIT && TARGET_FIX_R4000 && !ISA_HAS_DSP"
+ "!TARGET_64BIT && TARGET_FIX_R4000 && !ISA_HAS_DSP && ISA_HAS_MULT"
"mult<u>\t%1,%2\;mflo\t%L0\;mfhi\t%M0"
[(set_attr "type" "imul")
(set_attr "mode" "SI")
@@ -1961,7 +2087,8 @@
(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 && !ISA_HAS_DMUL3 && !TARGET_MIPS16"
+ "TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DMUL3
+ && !TARGET_MIPS16 && ISA_HAS_MULT"
"#"
"&& reload_completed"
[(const_int 0)]
@@ -2044,6 +2171,15 @@
[(set_attr "type" "imul3")
(set_attr "mode" "DI")])
+(define_insn "mulsidi3_64bit_r6dmul"
+ [(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"))))]
+ "ISA_HAS_R6DMUL"
+ "dmul\t%0,%1,%2"
+ [(set_attr "type" "imul3nc")
+ (set_attr "mode" "DI")])
+
;; Widening multiply with negation.
(define_insn "*muls<u>_di"
[(set (match_operand:DI 0 "muldiv_target_operand" "=x")
@@ -2101,12 +2237,27 @@
else if (TARGET_MIPS16)
emit_insn (gen_<su>mulsi3_highpart_split (operands[0], operands[1],
operands[2]));
+ else if (ISA_HAS_R6MUL)
+ emit_insn (gen_<su>mulsi3_highpart_r6 (operands[0], operands[1],
+ operands[2]));
else
emit_insn (gen_<su>mulsi3_highpart_internal (operands[0], operands[1],
operands[2]));
DONE;
})
+(define_insn "<su>mulsi3_highpart_r6"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
+ (const_int 32))))]
+ "ISA_HAS_R6MUL"
+ "muh<u>\t%0,%1,%2"
+ [(set_attr "type" "imul3nc")
+ (set_attr "mode" "SI")])
+
(define_insn_and_split "<su>mulsi3_highpart_internal"
[(set (match_operand:SI 0 "register_operand" "=d")
(truncate:SI
@@ -2115,7 +2266,7 @@
(any_extend:DI (match_operand:SI 2 "register_operand" "d")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=l"))]
- "!ISA_HAS_MULHI && !TARGET_MIPS16"
+ "ISA_HAS_MULT && !ISA_HAS_MULHI && !TARGET_MIPS16"
{ return TARGET_FIX_R4000 ? "mult<u>\t%1,%2\n\tmfhi\t%0" : "#"; }
"&& reload_completed && !TARGET_FIX_R4000"
[(const_int 0)]
@@ -2193,17 +2344,34 @@
(mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
(any_extend:TI (match_operand:DI 2 "register_operand")))
(const_int 64))))]
- "ISA_HAS_DMULT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
+ "ISA_HAS_R6DMUL
+ || (ISA_HAS_DMULT
+ && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120))"
{
if (TARGET_MIPS16)
emit_insn (gen_<su>muldi3_highpart_split (operands[0], operands[1],
operands[2]));
+ else if (ISA_HAS_R6DMUL)
+ emit_insn (gen_<su>muldi3_highpart_r6 (operands[0], operands[1],
+ operands[2]));
else
emit_insn (gen_<su>muldi3_highpart_internal (operands[0], operands[1],
operands[2]));
DONE;
})
+(define_insn "<su>muldi3_highpart_r6"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
+ (any_extend:TI (match_operand:DI 2 "register_operand" "d")))
+ (const_int 64))))]
+ "ISA_HAS_R6DMUL"
+ "dmuh<u>\t%0,%1,%2"
+ [(set_attr "type" "imul3nc")
+ (set_attr "mode" "DI")])
+
(define_insn_and_split "<su>muldi3_highpart_internal"
[(set (match_operand:DI 0 "register_operand" "=d")
(truncate:DI
@@ -2342,6 +2510,16 @@
(set_attr "accum_in" "3")
(set_attr "mode" "<UNITMODE>")])
+(define_insn "*maddf<mode>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (plus:ANYF (match_operand:ANYF 1 "register_operand" "0")
+ (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
+ (match_operand:ANYF 3 "register_operand" "f"))))]
+ "ISA_HAS_FP_MADDF_MSUBF"
+ "maddf.<fmt>\t%0,%2,%3"
+ [(set_attr "type" "fmadd")
+ (set_attr "mode" "<UNITMODE>")])
+
(define_insn "*madd3<mode>"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
@@ -2364,6 +2542,16 @@
(set_attr "accum_in" "3")
(set_attr "mode" "<UNITMODE>")])
+(define_insn "*msubf<mode>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (minus:ANYF (match_operand:ANYF 1 "register_operand" "0")
+ (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
+ (match_operand:ANYF 3 "register_operand" "f"))))]
+ "ISA_HAS_FP_MADDF_MSUBF"
+ "msubf.<fmt>\t%0,%2,%3"
+ [(set_attr "type" "fmadd")
+ (set_attr "mode" "<UNITMODE>")])
+
(define_insn "*msub3<mode>"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
@@ -2725,6 +2913,40 @@
{ return mips_output_division ("<GPR:d>div<u>\t%.,%1,%2", operands); }
[(set_attr "type" "idiv")
(set_attr "mode" "<GPR:MODE>")])
+
+;; Integer division and modulus.
+
+(define_insn "<u>div<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=&d")
+ (any_div:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "register_operand" "d")))]
+ "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A || ISA_HAS_R6<D>DIV"
+ {
+ if (TARGET_LOONGSON_2EF)
+ return mips_output_division ("<d>div<u>.g\t%0,%1,%2", operands);
+ else if (TARGET_LOONGSON_3A)
+ return mips_output_division ("gs<d>div<u>\t%0,%1,%2", operands);
+ else
+ return mips_output_division ("<d>div<u>\t%0,%1,%2", operands);
+ }
+ [(set_attr "type" "idiv3")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "<u>mod<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=&d")
+ (any_mod:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "register_operand" "d")))]
+ "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A || ISA_HAS_R6<D>DIV"
+ {
+ if (TARGET_LOONGSON_2EF)
+ return mips_output_division ("<d>mod<u>.g\t%0,%1,%2", operands);
+ else if (TARGET_LOONGSON_3A)
+ return mips_output_division ("gs<d>mod<u>\t%0,%1,%2", operands);
+ else
+ return mips_output_division ("<d>mod<u>\t%0,%1,%2", operands);
+ }
+ [(set_attr "type" "idiv3")
+ (set_attr "mode" "<MODE>")])
;;
;; ....................
@@ -3870,7 +4092,7 @@
(sign_extract:GPR (match_operand:BLK 1 "memory_operand")
(match_operand 2 "const_int_operand")
(match_operand 3 "const_int_operand")))]
- "!TARGET_MIPS16"
+ "ISA_HAS_LWL_LWR"
{
if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]),
@@ -3907,7 +4129,7 @@
(zero_extract:GPR (match_operand:BLK 1 "memory_operand")
(match_operand 2 "const_int_operand")
(match_operand 3 "const_int_operand")))]
- "!TARGET_MIPS16"
+ "ISA_HAS_LWL_LWR"
{
if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]),
@@ -3958,7 +4180,7 @@
(match_operand 1 "const_int_operand")
(match_operand 2 "const_int_operand"))
(match_operand:GPR 3 "reg_or_0_operand"))]
- "!TARGET_MIPS16"
+ "ISA_HAS_LWL_LWR"
{
if (mips_expand_ins_as_unaligned_store (operands[0], operands[3],
INTVAL (operands[1]),
@@ -4139,7 +4361,10 @@
[(set (match_operand:DI 0 "register_operand" "=d")
(match_operand:DI 1 "absolute_symbolic_operand" ""))
(clobber (match_scratch:DI 2 "=&d"))]
- "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS && cse_not_expected"
+ "!TARGET_MIPS16
+ && TARGET_EXPLICIT_RELOCS
+ && ABI_HAS_64BIT_SYMBOLS
+ && cse_not_expected"
"#"
"&& reload_completed"
[(set (match_dup 0) (high:DI (match_dup 3)))
@@ -4437,7 +4662,7 @@
(define_insn "*mov<mode>_internal"
[(set (match_operand:IMOVE32 0 "nonimmediate_operand" "=d,!u,!u,d,e,!u,!ks,d,ZS,ZT,m,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m")
- (match_operand:IMOVE32 1 "move_operand" "d,J,Udb7,Yd,Yf,ZT,ZS,m,!ks,!u,dJ,*d*J,*m,*f,*f,*z,*d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
+ (match_operand:IMOVE32 1 "move_operand" "d,J,Udb7,Yd,Yf,ZT,ZS,m,!ks,!kbJ,dJ,*d*J,*m,*f,*f,*z,*d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
"!TARGET_MIPS16
&& (register_operand (operands[0], <MODE>mode)
|| reg_or_0_operand (operands[1], <MODE>mode))"
@@ -4578,7 +4803,7 @@
(define_insn "*movhi_internal"
[(set (match_operand:HI 0 "nonimmediate_operand" "=d,!u,d,!u,d,ZU,m,*a,*d")
- (match_operand:HI 1 "move_operand" "d,J,I,ZU,m,!u,dJ,*d*J,*a"))]
+ (match_operand:HI 1 "move_operand" "d,J,I,ZU,m,!kbJ,dJ,*d*J,*a"))]
"!TARGET_MIPS16
&& (register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))"
@@ -4654,7 +4879,7 @@
(define_insn "*movqi_internal"
[(set (match_operand:QI 0 "nonimmediate_operand" "=d,!u,d,!u,d,ZV,m,*a,*d")
- (match_operand:QI 1 "move_operand" "d,J,I,ZW,m,!u,dJ,*d*J,*a"))]
+ (match_operand:QI 1 "move_operand" "d,J,I,ZW,m,!kbJ,dJ,*d*J,*a"))]
"!TARGET_MIPS16
&& (register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))"
@@ -4711,6 +4936,13 @@
DONE;
})
+(define_insn "movccf"
+ [(set (match_operand:CCF 0 "nonimmediate_operand" "=f,f,m")
+ (match_operand:CCF 1 "nonimmediate_operand" "f,m,f"))]
+ "ISA_HAS_CCF"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "move_type" "fmove,fpload,fpstore")])
+
(define_insn "*movsf_hardfloat"
[(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
(match_operand:SF 1 "move_operand" "f,G,m,f,G,*d,*f,*G*d,*m,*d"))]
@@ -4787,7 +5019,7 @@
(define_expand "movti"
[(set (match_operand:TI 0)
(match_operand:TI 1))]
- "TARGET_64BIT"
+ "TARGET_64BIT || TARGET_MSA"
{
if (mips_legitimize_move (TImode, operands[0], operands[1]))
DONE;
@@ -4797,6 +5029,7 @@
[(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,d,m,*a,*a,*d")
(match_operand:TI 1 "move_operand" "d,i,m,dJ,*J,*d,*a"))]
"TARGET_64BIT
+ && !TARGET_MSA
&& !TARGET_MIPS16
&& (register_operand (operands[0], TImode)
|| reg_or_0_operand (operands[1], TImode))"
@@ -4865,7 +5098,7 @@
(define_split
[(set (match_operand:MOVE128 0 "nonimmediate_operand")
(match_operand:MOVE128 1 "move_operand"))]
- "reload_completed && mips_split_move_insn_p (operands[0], operands[1], insn)"
+ "reload_completed && !TARGET_MSA && mips_split_move_insn_p (operands[0], operands[1], insn)"
[(const_int 0)]
{
mips_split_move_insn (operands[0], operands[1], curr_insn);
@@ -4954,7 +5187,7 @@
rtx low = mips_subword (operands[1], 0);
rtx high = mips_subword (operands[1], 1);
emit_insn (gen_load_low<mode> (operands[0], low));
- if (TARGET_FLOAT64 && !TARGET_64BIT)
+ if (ISA_HAS_MXHC1 && !TARGET_64BIT)
emit_insn (gen_mthc1<mode> (operands[0], high, operands[0]));
else
emit_insn (gen_load_high<mode> (operands[0], high, operands[0]));
@@ -4964,7 +5197,7 @@
rtx low = mips_subword (operands[0], 0);
rtx high = mips_subword (operands[0], 1);
emit_insn (gen_store_word<mode> (low, operands[1], const0_rtx));
- if (TARGET_FLOAT64 && !TARGET_64BIT)
+ if (ISA_HAS_MXHC1 && !TARGET_64BIT)
emit_insn (gen_mfhc1<mode> (high, operands[1]));
else
emit_insn (gen_store_word<mode> (high, operands[1], const1_rtx));
@@ -5229,7 +5462,7 @@
(define_insn "mips_cache"
[(set (mem:BLK (scratch))
(unspec:BLK [(match_operand:SI 0 "const_int_operand")
- (match_operand:QI 1 "address_operand" "p")]
+ (match_operand:QI 1 "address_operand" "ZD")]
UNSPEC_MIPS_CACHE))]
"ISA_HAS_CACHE"
"cache\t%X0,%a1")
@@ -5506,11 +5739,11 @@
;; Conditional branches on floating-point equality tests.
-(define_insn "*branch_fp"
+(define_insn "*branch_fp_<mode>"
[(set (pc)
(if_then_else
(match_operator 1 "equality_operator"
- [(match_operand:CC 2 "register_operand" "z")
+ [(match_operand:FPCC 2 "register_operand" "<reg>")
(const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
@@ -5522,11 +5755,11 @@
}
[(set_attr "type" "branch")])
-(define_insn "*branch_fp_inverted"
+(define_insn "*branch_fp_inverted_<mode>"
[(set (pc)
(if_then_else
(match_operator 1 "equality_operator"
- [(match_operand:CC 2 "register_operand" "z")
+ [(match_operand:FPCC 2 "register_operand" "<reg>")
(const_int 0)])
(pc)
(label_ref (match_operand 0 "" ""))))]
@@ -5870,21 +6103,21 @@
;;
;; ....................
-(define_insn "s<code>_<mode>"
- [(set (match_operand:CC 0 "register_operand" "=z")
- (fcond:CC (match_operand:SCALARF 1 "register_operand" "f")
- (match_operand:SCALARF 2 "register_operand" "f")))]
+(define_insn "s<code>_<SCALARF:mode>_using_<FPCC:mode>"
+ [(set (match_operand:FPCC 0 "register_operand" "=<reg>")
+ (fcond:FPCC (match_operand:SCALARF 1 "register_operand" "f")
+ (match_operand:SCALARF 2 "register_operand" "f")))]
""
- "c.<fcond>.<fmt>\t%Z0%1,%2"
+ "<fpcmp>.<fcond>.<fmt>\t%Z0%1,%2"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")])
-(define_insn "s<code>_<mode>"
- [(set (match_operand:CC 0 "register_operand" "=z")
- (swapped_fcond:CC (match_operand:SCALARF 1 "register_operand" "f")
- (match_operand:SCALARF 2 "register_operand" "f")))]
+(define_insn "s<code>_<SCALARF:mode>_using_<FPCC:mode>"
+ [(set (match_operand:FPCC 0 "register_operand" "=<reg>")
+ (swapped_fcond:FPCC (match_operand:SCALARF 1 "register_operand" "f")
+ (match_operand:SCALARF 2 "register_operand" "f")))]
""
- "c.<swapped_fcond>.<fmt>\t%Z0%2,%1"
+ "<fpcmp>.<swapped_fcond>.<fmt>\t%Z0%2,%1"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")])
@@ -6091,10 +6324,10 @@
rtx diff_vec = PATTERN (NEXT_INSN (operands[2]));
gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
-
+
output_asm_insn ("sltu\t%0, %1", operands);
output_asm_insn ("bteqz\t%3", operands);
-
+
switch (GET_MODE (diff_vec))
{
case HImode:
@@ -6904,6 +7137,41 @@
[(set_attr "type" "condmove")
(set_attr "mode" "<SCALARF:MODE>")])
+(define_insn "*sel<code><GPR:mode>_using_<GPR2:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (if_then_else:GPR
+ (equality_op:GPR2 (match_operand:GPR2 1 "register_operand" "d,d")
+ (const_int 0))
+ (match_operand:GPR 2 "reg_or_0_operand" "d,J")
+ (match_operand:GPR 3 "reg_or_0_operand" "J,d")))]
+ "ISA_HAS_SEL
+ && (register_operand (operands[2], <GPR:MODE>mode)
+ != register_operand (operands[3], <GPR:MODE>mode))"
+ "@
+ <sel>\t%0,%2,%1
+ <selinv>\t%0,%3,%1"
+ [(set_attr "type" "condmove")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;; sel.fmt copies the 3rd argument when the 1st is non-zero and the 2nd
+;; argument if the 1st is zero. This means operand 2 and 3 are
+;; inverted in the instruction.
+
+(define_insn "*sel<mode>"
+ [(set (match_operand:SCALARF 0 "register_operand" "=f,f,f")
+ (if_then_else:SCALARF
+ (ne:CCF (match_operand:CCF 1 "register_operand" "0,f,f")
+ (const_int 0))
+ (match_operand:SCALARF 2 "reg_or_0_operand" "f,G,f")
+ (match_operand:SCALARF 3 "reg_or_0_operand" "f,f,G")))]
+ "ISA_HAS_SEL && ISA_HAS_CCF"
+ "@
+ sel.<fmt>\t%0,%3,%2
+ seleqz.<fmt>\t%0,%3,%1
+ selnez.<fmt>\t%0,%2,%1"
+ [(set_attr "type" "condmove")
+ (set_attr "mode" "<SCALARF:MODE>")])
+
;; These are the main define_expand's used to make conditional moves.
(define_expand "mov<mode>cc"
@@ -6912,8 +7180,11 @@
(if_then_else:GPR (match_dup 5)
(match_operand:GPR 2 "reg_or_0_operand")
(match_operand:GPR 3 "reg_or_0_operand")))]
- "ISA_HAS_CONDMOVE"
+ "ISA_HAS_CONDMOVE || ISA_HAS_SEL"
{
+ if (ISA_HAS_SEL && !INTEGRAL_MODE_P (GET_MODE (XEXP (operands[1], 0))))
+ FAIL;
+
mips_expand_conditional_move (operands);
DONE;
})
@@ -6922,10 +7193,25 @@
[(set (match_dup 4) (match_operand 1 "comparison_operator"))
(set (match_operand:SCALARF 0 "register_operand")
(if_then_else:SCALARF (match_dup 5)
- (match_operand:SCALARF 2 "register_operand")
- (match_operand:SCALARF 3 "register_operand")))]
- "ISA_HAS_FP_CONDMOVE"
+ (match_operand:SCALARF 2 "reg_or_0_operand")
+ (match_operand:SCALARF 3 "reg_or_0_operand")))]
+ "ISA_HAS_FP_CONDMOVE
+ || (ISA_HAS_SEL && ISA_HAS_CCF)"
{
+ if (ISA_HAS_SEL && !FLOAT_MODE_P (GET_MODE (XEXP (operands[1], 0))))
+ FAIL;
+
+ /* Workaround an LRA bug which means that tied operands in the sel.fmt
+ pattern lead to the double precision destination of sel.d getting
+ reloaded with the full register file usable and the restrictions on
+ whether the CCFmode input can be used in odd-numbered single-precision
+ registers are ignored. For consistency reasons the CCF mode values
+ must be guaranteed to only exist in the even-registers because of
+ the unusual duality between single and double precision values. */
+ if (ISA_HAS_SEL && <MODE>mode == DFmode
+ && (!TARGET_ODD_SPREG || TARGET_FLOATXX))
+ FAIL;
+
mips_expand_conditional_move (operands);
DONE;
})
@@ -7040,7 +7326,12 @@
[(set (reg:P TLS_GET_TP_REGNUM)
(unspec:P [(const_int 0)] UNSPEC_TLS_GET_TP))]
"HAVE_AS_TLS && !TARGET_MIPS16"
- ".set\tpush\;.set\tmips32r2\t\;rdhwr\t$3,$29\;.set\tpop"
+ {
+ if (mips_isa_rev >= 2)
+ return "rdhwr\t$3,$29";
+
+ return ".set\tpush\;.set\tmips32r2\t\;rdhwr\t$3,$29\;.set\tpop";
+ }
[(set_attr "type" "unknown")
; Since rdhwr always generates a trap for now, putting it in a delay
; slot would make the kernel's emulation of it much slower.
@@ -7185,6 +7476,9 @@
; ST-Microelectronics Loongson-2E/2F-specific patterns.
(include "loongson.md")
+; The MIPS MSA Instructions.
+(include "mips-msa.md")
+
(define_c_enum "unspec" [
UNSPEC_ADDRESS_FIRST
])