diff options
Diffstat (limited to 'gcc-4.9/gcc/config/mips/mips.md')
-rw-r--r-- | gcc-4.9/gcc/config/mips/mips.md | 452 |
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 9bf8cb7..1366362 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 ]) |