X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Fsh%2Fsh.md;h=db00ec3ef9e4c83e6b89699dcf65fa420f91468e;hb=59312820e49658a8bf1f74d96fc59c14f6a8c564;hp=a10774a06fbb073c0b038ce71df75087ccbba648;hpb=1ca361fdc5eab22baf4c5eda2686df93de41c5c0;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index a10774a06fb..db00ec3ef9e 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -143,6 +143,13 @@ (UNSPEC_GOTTPOFF 24) (UNSPEC_TPOFF 25) (UNSPEC_RA 26) + (UNSPEC_DIV_INV_M0 30) + (UNSPEC_DIV_INV_M1 31) + (UNSPEC_DIV_INV_M2 32) + (UNSPEC_DIV_INV_M3 33) + (UNSPEC_DIV_INV20 34) + (UNSPEC_ASHIFTRT 35) + (UNSPEC_THUNK 36) ;; These are used with unspec_volatile. (UNSPECV_BLOCKAGE 0) @@ -247,7 +254,7 @@ ;; mcmp_media SHmedia multimedia compare, absolute, saturating ops ;; mac_media SHmedia mac-style fixed point operations ;; d2mpy_media SHmedia: two 32 bit integer multiplies -;; atrans SHmedia approximate transcendental functions +;; atrans_media SHmedia approximate transcendental functions ;; ustore_media SHmedia unaligned stores ;; nil no-op move, will be deleted. @@ -424,6 +431,9 @@ (eq_attr "type" "pt_media") (if_then_else (ne (symbol_ref "TARGET_SHMEDIA64") (const_int 0)) (const_int 20) (const_int 12)) + (and (eq_attr "type" "jump_media") + (ne (symbol_ref "TARGET_SH5_CUT2_WORKAROUND") (const_int 0))) + (const_int 8) ] (if_then_else (ne (symbol_ref "TARGET_SHMEDIA") (const_int 0)) (const_int 4) (const_int 2)))) @@ -434,6 +444,8 @@ (include "shmedia.md") (include "sh4.md") +(include "predicates.md") + ;; Definitions for filling delay slots (define_attr "needs_delay_slot" "yes,no" (const_string "no")) @@ -494,6 +506,9 @@ (const_string "yes")] (const_string "no"))) +(define_attr "highpart" "user, ignore, extend, depend, must_split" + (const_string "user")) + (define_delay (eq_attr "needs_delay_slot" "yes") [(eq_attr "in_delay_slot" "yes") (nil) (nil)]) @@ -537,7 +552,7 @@ ;; SH2e has a hardware bug that pretty much prohibits the use of ;; annuled delay slots. [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes") - (not (eq_attr "cpu" "sh2e"))) (nil)]) + (not (eq_attr "cpu" "sh2e"))) (nil)]) ;; ------------------------------------------------------------------------- ;; SImode signed integer comparisons @@ -616,7 +631,7 @@ [(set (reg:SI T_REG) (compare (match_operand:SI 0 "cmpsi_operand" "") (match_operand:SI 1 "arith_operand" "")))] - "TARGET_SH1" + "TARGET_SH1 || TARGET_SHMEDIA" " { if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG @@ -731,14 +746,30 @@ [(set_attr "length" "8") (set_attr "type" "arith3")]) +(define_insn "cmpeqsi_media" + [(set (match_operand:DI 0 "register_operand" "=r") + (eq:DI (match_operand:SI 1 "logical_operand" "%r") + (match_operand:SI 2 "cmp_operand" "Nr")))] + "TARGET_SHMEDIA" + "cmpeq %1, %N2, %0" + [(set_attr "type" "cmp_media")]) + (define_insn "cmpeqdi_media" [(set (match_operand:DI 0 "register_operand" "=r") (eq:DI (match_operand:DI 1 "register_operand" "%r") - (match_operand:DI 2 "arith_reg_or_0_operand" "Nr")))] + (match_operand:DI 2 "cmp_operand" "Nr")))] "TARGET_SHMEDIA" "cmpeq %1, %N2, %0" [(set_attr "type" "cmp_media")]) +(define_insn "cmpgtsi_media" + [(set (match_operand:DI 0 "register_operand" "=r") + (gt:DI (match_operand:SI 1 "cmp_operand" "Nr") + (match_operand:SI 2 "cmp_operand" "rN")))] + "TARGET_SHMEDIA" + "cmpgt %N1, %N2, %0" + [(set_attr "type" "cmp_media")]) + (define_insn "cmpgtdi_media" [(set (match_operand:DI 0 "register_operand" "=r") (gt:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") @@ -747,6 +778,14 @@ "cmpgt %N1, %N2, %0" [(set_attr "type" "cmp_media")]) +(define_insn "cmpgtusi_media" + [(set (match_operand:DI 0 "register_operand" "=r") + (gtu:DI (match_operand:SI 1 "cmp_operand" "Nr") + (match_operand:SI 2 "cmp_operand" "rN")))] + "TARGET_SHMEDIA" + "cmpgtu %N1, %N2, %0" + [(set_attr "type" "cmp_media")]) + (define_insn "cmpgtudi_media" [(set (match_operand:DI 0 "register_operand" "=r") (gtu:DI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") @@ -755,6 +794,69 @@ "cmpgtu %N1, %N2, %0" [(set_attr "type" "cmp_media")]) +(define_insn "cmpsieqsi_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (eq:SI (match_operand:SI 1 "logical_operand" "%r") + (match_operand:SI 2 "cmp_operand" "Nr")))] + "TARGET_SHMEDIA" + "cmpeq %1, %N2, %0" + [(set_attr "type" "cmp_media")]) + +(define_insn "cmpsieqdi_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (eq:SI (match_operand:DI 1 "register_operand" "%r") + (match_operand:DI 2 "cmp_operand" "Nr")))] + "TARGET_SHMEDIA" + "cmpeq %1, %N2, %0" + [(set_attr "type" "cmp_media")]) + +(define_insn "cmpsigtsi_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (gt:SI (match_operand:SI 1 "cmp_operand" "Nr") + (match_operand:SI 2 "cmp_operand" "rN")))] + "TARGET_SHMEDIA" + "cmpgt %N1, %N2, %0" + [(set_attr "type" "cmp_media")]) + +(define_insn "cmpsigtdi_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (gt:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") + (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] + "TARGET_SHMEDIA" + "cmpgt %N1, %N2, %0" + [(set_attr "type" "cmp_media")]) + +(define_insn "cmpsigtusi_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (gtu:SI (match_operand:SI 1 "cmp_operand" "Nr") + (match_operand:SI 2 "cmp_operand" "rN")))] + "TARGET_SHMEDIA" + "cmpgtu %N1, %N2, %0" + [(set_attr "type" "cmp_media")]) + +(define_insn "cmpsigtudi_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (gtu:SI (match_operand:DI 1 "arith_reg_or_0_operand" "Nr") + (match_operand:DI 2 "arith_reg_or_0_operand" "rN")))] + "TARGET_SHMEDIA" + "cmpgtu %N1, %N2, %0" + [(set_attr "type" "cmp_media")]) + +; These two patterns are for combine. +(define_insn "*cmpne0si_media" + [(set (match_operand:DI 0 "register_operand" "=r") + (ne:DI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))] + "TARGET_SHMEDIA" + "cmpgtu %1,r63,%0" + [(set_attr "type" "cmp_media")]) + +(define_insn "*cmpne0sisi_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (ne:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0)))] + "TARGET_SHMEDIA" + "cmpgtu %1,r63,%0" + [(set_attr "type" "cmp_media")]) + ;; We save the compare operands in the cmpxx patterns and use them when ;; we generate the branch. @@ -796,6 +898,37 @@ "cmvne %1, %N2, %0" [(set_attr "type" "arith_media")]) +(define_peephole2 + [(set (match_operand:DI 0 "arith_reg_dest" "") + (if_then_else:DI (match_operator 3 "equality_comparison_operator" + [(match_operand:DI 1 "arith_reg_operand" "") + (const_int 0)]) + (match_operand:DI 2 "arith_reg_dest" "") + (match_dup 0))) + (set (match_dup 2) (match_dup 0))] + "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" + [(set (match_dup 2) + (if_then_else:DI (match_dup 3) (match_dup 0) (match_dup 2)))] + " +{ + operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])), + VOIDmode, operands[1], CONST0_RTX (DImode)); +}") + +(define_peephole2 + [(set (match_operand:DI 0 "general_movdst_operand" "") + (match_operand:DI 1 "arith_reg_or_0_operand" "")) + (set (match_operand:DI 2 "arith_reg_dest" "") + (if_then_else:DI (match_operator 4 "equality_comparison_operator" + [(match_operand:DI 3 "arith_reg_operand" "") + (const_int 0)]) + (match_dup 0) + (match_dup 2)))] + "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" + [(set (match_dup 2) + (if_then_else:DI (match_dup 4) (match_dup 1) (match_dup 2)))] + "") + (define_expand "movdicc" [(set (match_operand:DI 0 "register_operand" "") (if_then_else:DI (match_operand 1 "comparison_operator" "") @@ -893,6 +1026,270 @@ } } }") + +;; Add SImode variants for cmveq / cmvne to compensate for not promoting +;; SImode to DImode. +(define_insn "movsicc_false" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (if_then_else:SI (eq (match_operand:SI 1 "arith_reg_operand" "r") + (const_int 0)) + (match_operand:SI 2 "arith_reg_or_0_operand" "rN") + (match_operand:SI 3 "arith_reg_operand" "0")))] + "TARGET_SHMEDIA" + "cmveq %1, %N2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "movsicc_true" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (if_then_else:SI (ne (match_operand:SI 1 "arith_reg_operand" "r") + (const_int 0)) + (match_operand:SI 2 "arith_reg_or_0_operand" "rN") + (match_operand:SI 3 "arith_reg_operand" "0")))] + "TARGET_SHMEDIA" + "cmvne %1, %N2, %0" + [(set_attr "type" "arith_media")]) + +(define_peephole2 + [(set (match_operand:SI 0 "arith_reg_dest" "") + (if_then_else:SI (match_operator 3 "equality_comparison_operator" + [(match_operand:SI 1 "arith_reg_operand" "") + (const_int 0)]) + (match_operand:SI 2 "arith_reg_dest" "") + (match_dup 0))) + (set (match_dup 2) (match_dup 0))] + "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0])" + [(set (match_dup 2) + (if_then_else:SI (match_dup 3) (match_dup 0) (match_dup 2)))] + " +{ + operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[3])), + VOIDmode, operands[1], CONST0_RTX (SImode)); +}") + +(define_peephole2 + [(set (match_operand:SI 0 "general_movdst_operand" "") + (match_operand:SI 1 "arith_reg_or_0_operand" "")) + (set (match_operand:SI 2 "arith_reg_dest" "") + (if_then_else:SI (match_operator 4 "equality_comparison_operator" + [(match_operand:SI 3 "arith_reg_operand" "") + (const_int 0)]) + (match_dup 0) + (match_dup 2)))] + "TARGET_SHMEDIA && peep2_reg_dead_p (2, operands[0]) + && (GET_CODE (operands[1]) != REG || GENERAL_REGISTER_P (REGNO (operands[1])))" + [(set (match_dup 2) + (if_then_else:SI (match_dup 4) (match_dup 1) (match_dup 2)))] + " +{ + replace_rtx (operands[4], operands[0], operands[1]); +}") + +(define_peephole2 + [(set (match_operand 0 "any_register_operand" "") + (match_operand 1 "any_register_operand" "")) + (set (match_operand 2 "any_register_operand" "") (match_operand 3 "" "")) + (set (match_operand 4 "" "") (match_operand 5 "" ""))] + "(HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[2])) + <= HARD_REGNO_NREGS (REGNO (operands[0]), GET_MODE (operands[0]))) + && peep2_reg_dead_p (3, operands[0]) && peep2_reg_dead_p (3, operands[2]) + && ! reg_overlap_mentioned_p (operands[0], operands[3]) + && ! reg_overlap_mentioned_p (operands[2], operands[0]) + && ! reg_overlap_mentioned_p (operands[0], operands[1]) + && (REGNO_REG_CLASS (REGNO (operands[0])) + == REGNO_REG_CLASS (REGNO (operands[2]))) + && (REGNO_REG_CLASS (REGNO (operands[1])) + == REGNO_REG_CLASS (REGNO (operands[0])))" + [(set (match_dup 0) (match_dup 3)) + (set (match_dup 4) (match_dup 5))] + " +{ + rtx set1, set2; + rtx replacements[4]; + + /* We want to replace occurences of operands[0] with operands[1] and + operands[2] with operands[0] in operands[4]/operands[5]. + Doing just two replace_rtx calls naiively would result in the second + replacement undoing all that the first did if operands[1] and operands[2] + are identical, so we must do this simultaneously. */ + replacements[0] = operands[0]; + replacements[1] = operands[1]; + replacements[2] = operands[2]; + replacements[3] = operands[0]; + if (!replace_n_hard_rtx (operands[5], replacements, 2, 0) + || !replace_n_hard_rtx (operands[4], replacements, 2, 0) + || !replace_n_hard_rtx (operands[2], replacements, 2, 0)) + FAIL; + + operands[5] = replace_n_hard_rtx (operands[5], replacements, 2, 1); + replace_n_hard_rtx (operands[4], replacements, 2, 1); + operands[2] = replace_n_hard_rtx (operands[2], replacements, 2, 1); + /* The operands array is aliased to recog_data.operand, which gets + clobbered by extract_insn, so finish with it now. */ + set1 = gen_rtx_SET (VOIDmode, operands[2], operands[3]); + set2 = gen_rtx_SET (VOIDmode, operands[4], operands[5]); + /* ??? The last insn might be a jump insn, but the generic peephole2 code + always uses emit_insn. */ + /* Check that we don't violate matching constraints or earlyclobbers. */ + extract_insn (emit_insn (set1)); + if (! constrain_operands (1)) + goto failure; + extract_insn (emit (set2)); + if (! constrain_operands (1)) + { + rtx tmp; + failure: + tmp = replacements[0]; + replacements[0] = replacements[1]; + replacements[1] = tmp; + tmp = replacements[2]; + replacements[2] = replacements[3]; + replacements[3] = tmp; + replace_n_hard_rtx (SET_DEST (set1), replacements, 2, 1); + replace_n_hard_rtx (SET_DEST (set2), replacements, 2, 1); + replace_n_hard_rtx (SET_SRC (set2), replacements, 2, 1); + FAIL; + } + DONE; +}") + +;; The register allocator is rather clumsy in handling multi-way conditional +;; moves, so allow the combiner to make them, and we split them up after +;; reload. */ +(define_insn_and_split "*movsicc_umin" + [(set (match_operand:SI 0 "arith_reg_dest" "=&r") + (umin:SI (if_then_else:SI + (eq (match_operand:SI 1 "arith_reg_operand" "r") + (const_int 0)) + (match_operand:SI 2 "arith_reg_or_0_operand" "rN") + (match_operand:SI 3 "register_operand" "0")) + (match_operand:SI 4 "arith_reg_or_0_operand" "r"))) + (clobber (match_scratch:SI 5 "=&r"))] + "TARGET_SHMEDIA && no_new_pseudos" + "#" + "TARGET_SHMEDIA && reload_completed" + [(pc)] + " +{ + emit_insn (gen_movsicc_false (operands[0], operands[1], operands[2], + operands[3])); + emit_insn (gen_cmpsigtusi_media (operands[5], operands[4], operands[0])); + emit_insn (gen_movsicc_false (operands[0], operands[5], operands[4], + operands[0])); + DONE; +}") + +(define_expand "movsicc" + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else:SI (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "register_operand" "")))] + "TARGET_SHMEDIA" + " +{ + if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) + && GET_MODE (sh_compare_op0) == SImode + && sh_compare_op1 == const0_rtx) + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), VOIDmode, + sh_compare_op0, sh_compare_op1); + else + { + rtx tmp; + + if (no_new_pseudos) + FAIL; + + tmp = gen_reg_rtx (SImode); + + switch (GET_CODE (operands[1])) + { + case EQ: + emit_insn (gen_seq (tmp)); + operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); + break; + + case NE: + emit_insn (gen_seq (tmp)); + operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); + break; + + case GT: + emit_insn (gen_sgt (tmp)); + operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); + break; + + case LT: + emit_insn (gen_slt (tmp)); + operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); + break; + + case GE: + emit_insn (gen_slt (tmp)); + operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); + break; + + case LE: + emit_insn (gen_sgt (tmp)); + operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); + break; + + case GTU: + emit_insn (gen_sgtu (tmp)); + operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); + break; + + case LTU: + emit_insn (gen_sltu (tmp)); + operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); + break; + + case GEU: + emit_insn (gen_sltu (tmp)); + operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); + break; + + case LEU: + emit_insn (gen_sgtu (tmp)); + operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); + break; + + case UNORDERED: + emit_insn (gen_sunordered (tmp)); + operands[1] = gen_rtx_NE (VOIDmode, tmp, const0_rtx); + break; + + case ORDERED: + emit_insn (gen_sunordered (tmp)); + operands[1] = gen_rtx_EQ (VOIDmode, tmp, const0_rtx); + break; + + case UNEQ: + case UNGE: + case UNGT: + case UNLE: + case UNLT: + case LTGT: + FAIL; + + default: + abort (); + } + } +}") + +(define_expand "movqicc" + [(set (match_operand:QI 0 "register_operand" "") + (if_then_else:QI (match_operand 1 "comparison_operator" "") + (match_operand:QI 2 "register_operand" "") + (match_operand:QI 3 "register_operand" "")))] + "TARGET_SHMEDIA" + " +{ + operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0); + operands[2] = simplify_gen_subreg (SImode, operands[2], QImode, 0); + operands[3] = simplify_gen_subreg (SImode, operands[3], QImode, 0); + emit (gen_movsicc (operands[0], operands[1], operands[2], operands[3])); + DONE; +}") ;; ------------------------------------------------------------------------- ;; Addition instructions @@ -916,7 +1313,7 @@ }") (define_insn "*adddi3_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") (match_operand:DI 2 "arith_operand" "r,I10")))] "TARGET_SHMEDIA" @@ -925,17 +1322,29 @@ addi %1, %2, %0" [(set_attr "type" "arith_media")]) +(define_insn "*adddisi3_media" + [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r,r") 0) + (plus:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") + (match_operand:DI 2 "arith_operand" "r,I10")))] + "TARGET_SHMEDIA" + "@ + add.l %1, %2, %0 + addi.l %1, %2, %0" + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) + (define_insn "adddi3z_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (zero_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand" "r") (match_operand:SI 2 "extend_reg_or_0_operand" "rN"))))] "TARGET_SHMEDIA" "addz.l %1, %N2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_insn "adddi3_compact" - [(set (match_operand:DI 0 "arith_reg_operand" "=&r") + [(set (match_operand:DI 0 "arith_reg_dest" "=&r") (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0") (match_operand:DI 2 "arith_reg_operand" "r"))) (clobber (reg:SI T_REG))] @@ -944,7 +1353,7 @@ [(set_attr "length" "6")]) (define_split - [(set (match_operand:DI 0 "arith_reg_operand" "") + [(set (match_operand:DI 0 "arith_reg_dest" "") (plus:DI (match_operand:DI 1 "arith_reg_operand" "") (match_operand:DI 2 "arith_reg_operand" ""))) (clobber (reg:SI T_REG))] @@ -966,7 +1375,7 @@ }") (define_insn "addc" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "r")) (reg:SI T_REG))) @@ -977,7 +1386,7 @@ [(set_attr "type" "arith")]) (define_insn "addc1" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "r")) (reg:SI T_REG))) @@ -998,17 +1407,31 @@ }") (define_insn "addsi3_media" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") (plus:SI (match_operand:SI 1 "extend_reg_operand" "%r,r") (match_operand:SI 2 "arith_operand" "r,I10")))] "TARGET_SHMEDIA" "@ add.l %1, %2, %0 addi.l %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) + +(define_insn "addsidi3_media" + [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") + (sign_extend:DI (plus:SI (match_operand:SI 1 "extend_reg_operand" + "%r,r") + (match_operand:SI 2 "arith_operand" + "r,I10"))))] + "TARGET_SHMEDIA" + "@ + add.l %1, %2, %0 + addi.l %1, %2, %0" + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_insn "*addsi3_compact" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (plus:SI (match_operand:SI 1 "arith_operand" "%0") (match_operand:SI 2 "arith_operand" "rI08")))] "TARGET_SH1" @@ -1035,15 +1458,24 @@ }") (define_insn "*subdi3_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN") (match_operand:DI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "sub %N1, %2, %0" [(set_attr "type" "arith_media")]) + +(define_insn "subdisi3_media" + [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) + (minus:DI (match_operand:DI 1 "arith_reg_or_0_operand" "rN") + (match_operand:DI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "sub.l %N1, %2, %0" + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_insn "subdi3_compact" - [(set (match_operand:DI 0 "arith_reg_operand" "=&r") + [(set (match_operand:DI 0 "arith_reg_dest" "=&r") (minus:DI (match_operand:DI 1 "arith_reg_operand" "0") (match_operand:DI 2 "arith_reg_operand" "r"))) (clobber (reg:SI T_REG))] @@ -1052,7 +1484,7 @@ [(set_attr "length" "6")]) (define_split - [(set (match_operand:DI 0 "arith_reg_operand" "") + [(set (match_operand:DI 0 "arith_reg_dest" "") (minus:DI (match_operand:DI 1 "arith_reg_operand" "") (match_operand:DI 2 "arith_reg_operand" ""))) (clobber (reg:SI T_REG))] @@ -1074,7 +1506,7 @@ }") (define_insn "subc" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "r")) (reg:SI T_REG))) @@ -1087,7 +1519,7 @@ [(set_attr "type" "arith")]) (define_insn "subc1" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "r")) (reg:SI T_REG))) @@ -1096,22 +1528,57 @@ "subc %2,%0" [(set_attr "type" "arith")]) +;; life_analysis thinks rn is live before subc rn,rn, so make a special +;; pattern for this case. This helps multimedia applications that compute +;; the sum of absolute differences. +(define_insn "mov_neg_si_t" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (reg:SI T_REG)))] + "TARGET_SH1" + "subc %0,%0" + [(set_attr "type" "arith")]) + (define_insn "*subsi3_internal" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (minus:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "r")))] "TARGET_SH1" "sub %2,%0" [(set_attr "type" "arith")]) -(define_insn "*subsi3_media" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") - (minus:SI (match_operand:SI 1 "extend_reg_or_0_operand" "rN") +(define_insn_and_split "*subsi3_media" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (minus:SI (match_operand:SI 1 "minuend_operand" "rN") (match_operand:SI 2 "extend_reg_operand" "r")))] - "TARGET_SHMEDIA" + "TARGET_SHMEDIA + && (operands[1] != constm1_rtx + || (GET_CODE (operands[2]) != TRUNCATE + && GET_CODE (operands[2]) != SUBREG))" "sub.l %N1, %2, %0" - [(set_attr "type" "arith_media")]) + "operands[1] == constm1_rtx" + [(set (match_dup 0) (xor:SI (match_dup 2) (match_dup 1)))] + "" + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) +(define_split + [(set (match_operand:SI 0 "arith_reg_dest" "") + (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1 + "general_extend_operand" + "") 0)) 0)))] + "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" + [(set (match_dup 0) (zero_extend:SI (match_dup 1))) + (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))] + "") + +(define_split + [(set (match_operand:SI 0 "arith_reg_dest" "") + (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1 + "general_extend_operand" + "") 0)) 3)))] + "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN" + [(set (match_dup 0) (zero_extend:SI (match_dup 1))) + (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))] + "") ;; Convert `constant - reg' to `neg rX; add rX, #const' since this ;; will sometimes save one instruction. Otherwise we might get ;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs @@ -1134,7 +1601,7 @@ { if (no_new_pseudos && ! arith_reg_or_0_operand (operands[1], SImode)) FAIL; - if (operands[1] != const0_rtx) + if (operands[1] != const0_rtx && GET_CODE (operands[1]) != SUBREG) operands[1] = force_reg (SImode, operands[1]); } }") @@ -1159,7 +1626,7 @@ [(set_attr "length" "0")]) (define_insn "udivsi3_sh2a" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (udiv:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "z")))] "TARGET_SH2A" @@ -1204,8 +1671,8 @@ (clobber (reg:DI TR0_REG)) (clobber (reg:DI TR1_REG)) (clobber (reg:DI TR2_REG)) - (use (match_operand:DI 1 "target_operand" "b"))] - "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU" + (use (match_operand 1 "target_operand" "b"))] + "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" "blink %1, r18" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) @@ -1290,7 +1757,7 @@ /* Emit the move of the address to a pseudo outside of the libcall. */ if (TARGET_HARD_SH4 && TARGET_SH2E) { - emit_move_insn (operands[3], function_symbol (\"__udivsi3_i4\")); + function_symbol (operands[3], \"__udivsi3_i4\", SFUNC_STATIC); if (TARGET_FPU_SINGLE) last = gen_udivsi3_i4_single (operands[0], operands[3]); else @@ -1312,17 +1779,12 @@ } else if (TARGET_SH5) { - emit_move_insn (operands[3], - function_symbol (TARGET_FPU_ANY - ? \"__udivsi3_i4\" - : \"__udivsi3\")); + function_symbol (operands[3], + TARGET_FPU_ANY ? \"__udivsi3_i4\" : \"__udivsi3\", + SFUNC_STATIC); if (TARGET_SHMEDIA) - last = gen_udivsi3_i1_media (operands[0], - Pmode == DImode - ? operands[3] - : gen_rtx_SUBREG (DImode, operands[3], - 0)); + last = gen_udivsi3_i1_media (operands[0], operands[3]); else if (TARGET_FPU_ANY) last = gen_udivsi3_i4_single (operands[0], operands[3]); else @@ -1330,7 +1792,7 @@ } else { - emit_move_insn (operands[3], function_symbol (\"__udivsi3\")); + function_symbol (operands[3], \"__udivsi3\", SFUNC_STATIC); last = gen_udivsi3_i1 (operands[0], operands[3]); } first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); @@ -1344,7 +1806,7 @@ }") (define_insn "divsi3_sh2a" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (div:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "z")))] "TARGET_SH2A" @@ -1366,30 +1828,110 @@ [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) -; Since shmedia-nofpu code could be linked against shcompact code, and -; the sdivsi3 libcall has the same name, we must consider all registers -; clobbered that are in the union of the registers clobbered by the -; shmedia and the shcompact implementation. Note, if the shcompact -; implementation actually used shcompact code, we'd need to clobber -; also r22, r23 and fr23. (define_insn "divsi3_i1_media" [(set (match_operand:SI 0 "register_operand" "=z") (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) (clobber (reg:SI T_MEDIA_REG)) (clobber (reg:SI PR_MEDIA_REG)) (clobber (reg:SI R1_REG)) - (clobber (reg:SI R2_REG)) - (clobber (reg:SI R3_REG)) (clobber (reg:SI R20_REG)) (clobber (reg:SI R21_REG)) - (clobber (reg:DI TR0_REG)) - (clobber (reg:DI TR1_REG)) - (clobber (reg:DI TR2_REG)) - (use (match_operand:DI 1 "target_operand" "b"))] - "TARGET_SHMEDIA && ! TARGET_SHMEDIA_FPU" + (clobber (reg:SI TR0_REG)) + (use (match_operand 1 "target_operand" "b"))] + "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" "blink %1, r18" [(set_attr "type" "sfunc")]) +(define_insn "divsi3_media_2" + [(set (match_operand:SI 0 "register_operand" "=z") + (div:SI (reg:SI R4_REG) (reg:SI R5_REG))) + (clobber (reg:SI T_MEDIA_REG)) + (clobber (reg:SI PR_MEDIA_REG)) + (clobber (reg:SI R1_REG)) + (clobber (reg:SI R21_REG)) + (clobber (reg:SI TR0_REG)) + (use (reg:SI R20_REG)) + (use (match_operand 1 "target_operand" "b"))] + "TARGET_SHMEDIA && (! TARGET_SHMEDIA_FPU || ! TARGET_DIVIDE_FP)" + "blink %1, r18" + [(set_attr "type" "sfunc")]) + +;; This pattern acts as a placeholder for -mdiv=inv:call to carry +;; hard reg clobbers and data dependencies that we need when we want +;; to rematerialize the division into a call. +(define_insn_and_split "divsi_inv_call" + [(set (match_operand:SI 0 "register_operand" "=r") + (div:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r"))) + (clobber (reg:SI R4_REG)) + (clobber (reg:SI R5_REG)) + (clobber (reg:SI T_MEDIA_REG)) + (clobber (reg:SI PR_MEDIA_REG)) + (clobber (reg:SI R1_REG)) + (clobber (reg:SI R21_REG)) + (clobber (reg:SI TR0_REG)) + (clobber (reg:SI R20_REG)) + (use (match_operand:SI 3 "register_operand" "r"))] + "TARGET_SHMEDIA" + "#" + "&& (high_life_started || reload_completed)" + [(set (match_dup 0) (match_dup 3))] + "" + [(set_attr "highpart" "must_split")]) + +;; This is the combiner pattern for -mdiv=inv:call . +(define_insn_and_split "*divsi_inv_call_combine" + [(set (match_operand:SI 0 "register_operand" "=z") + (div:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r"))) + (clobber (reg:SI R4_REG)) + (clobber (reg:SI R5_REG)) + (clobber (reg:SI T_MEDIA_REG)) + (clobber (reg:SI PR_MEDIA_REG)) + (clobber (reg:SI R1_REG)) + (clobber (reg:SI R21_REG)) + (clobber (reg:SI TR0_REG)) + (clobber (reg:SI R20_REG)) + (use (unspec:SI [(match_dup 1) + (match_operand:SI 3 "" "") + (unspec:SI [(match_operand:SI 4 "" "") + (match_dup 3) + (match_operand:DI 5 "" "")] + UNSPEC_DIV_INV_M2) + (match_operand:DI 6 "" "") + (const_int 0) + (const_int 0)] + UNSPEC_DIV_INV_M3))] + "TARGET_SHMEDIA" + "#" + "&& (high_life_started || reload_completed)" + [(pc)] + " +{ + const char *name = sh_divsi3_libfunc; + enum sh_function_kind kind = SFUNC_GOT; + rtx sym; + + emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]); + emit_move_insn (gen_rtx_REG (SImode, R5_REG), operands[2]); + while (TARGET_DIVIDE_INV_CALL2) + { + rtx x = operands[3]; + + if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_DIV_INV_M1) + break; + x = XVECEXP (x, 0, 0); + name = \"__sdivsi3_2\"; + kind = SFUNC_STATIC; + emit_move_insn (gen_rtx_REG (DImode, R20_REG), x); + break; + } + sym = function_symbol (NULL, name, kind); + emit_insn (gen_divsi3_media_2 (operands[0], sym)); + DONE; +}" + [(set_attr "highpart" "must_split")]) + (define_expand "divsi3_i4_media" [(set (match_dup 3) (float:DF (match_operand:SI 1 "register_operand" "r"))) (set (match_dup 4) (float:DF (match_operand:SI 2 "register_operand" "r"))) @@ -1453,7 +1995,7 @@ /* Emit the move of the address to a pseudo outside of the libcall. */ if (TARGET_HARD_SH4 && TARGET_SH2E) { - emit_move_insn (operands[3], function_symbol (\"__sdivsi3_i4\")); + function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC); if (TARGET_FPU_SINGLE) last = gen_divsi3_i4_single (operands[0], operands[3]); else @@ -1466,7 +2008,87 @@ emit_insn (gen_divsi3_sh2a (operands[0], operands[1], operands[2])); DONE; } - else if (TARGET_SHMEDIA_FPU) + else if (TARGET_DIVIDE_INV) + { + rtx dividend = operands[1]; + rtx divisor = operands[2]; + rtx tab_base; + rtx nsb_res = gen_reg_rtx (DImode); + rtx norm64 = gen_reg_rtx (DImode); + rtx tab_ix = gen_reg_rtx (DImode); + rtx norm32 = gen_reg_rtx (SImode); + rtx i92 = force_reg (DImode, GEN_INT (92)); + rtx scratch0a = gen_reg_rtx (DImode); + rtx scratch0b = gen_reg_rtx (DImode); + rtx inv0 = gen_reg_rtx (SImode); + rtx scratch1a = gen_reg_rtx (DImode); + rtx scratch1b = gen_reg_rtx (DImode); + rtx shift = gen_reg_rtx (DImode); + rtx i2p27, i43; + rtx inv1 = gen_reg_rtx (SImode); + rtx scratch2a = gen_reg_rtx (DImode); + rtx scratch2b = gen_reg_rtx (SImode); + rtx inv2 = gen_reg_rtx (SImode); + rtx scratch3a = gen_reg_rtx (DImode); + rtx scratch3b = gen_reg_rtx (DImode); + rtx scratch3c = gen_reg_rtx (DImode); + rtx scratch3d = gen_reg_rtx (SImode); + rtx scratch3e = gen_reg_rtx (DImode); + rtx result = gen_reg_rtx (SImode); + + if (! arith_reg_or_0_operand (dividend, SImode)) + dividend = force_reg (SImode, dividend); + if (! arith_reg_operand (divisor, SImode)) + divisor = force_reg (SImode, divisor); + if (flag_pic && Pmode != DImode) + { + tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\"); + tab_base = gen_datalabel_ref (tab_base); + tab_base = force_reg (DImode, gen_rtx_SIGN_EXTEND (DImode, tab_base)); + } + else + { + tab_base = gen_rtx_SYMBOL_REF (DImode, \"__div_table\"); + tab_base = gen_datalabel_ref (tab_base); + tab_base = force_reg (DImode, tab_base); + } + if (TARGET_DIVIDE_INV20U) + i2p27 = force_reg (DImode, GEN_INT (-2 << 27)); + else + i2p27 = GEN_INT (0); + if (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L) + i43 = force_reg (DImode, GEN_INT (43)); + else + i43 = GEN_INT (0); + emit_insn (gen_nsbdi (nsb_res, + simplify_gen_subreg (DImode, divisor, SImode, 0))); + emit_insn (gen_ashldi3_media (norm64, + gen_rtx_SUBREG (DImode, divisor, 0), + nsb_res)); + emit_insn (gen_ashrdi3_media (tab_ix, norm64, GEN_INT (58))); + emit_insn (gen_ashrdisi3_media_high (norm32, norm64, GEN_INT (32))); + emit_insn (gen_divsi_inv_m1 (inv1, tab_base, tab_ix, norm32, + inv0, scratch0a, scratch0b, + scratch1a, scratch1b)); + emit_insn (gen_subdi3 (shift, i92, nsb_res)); + emit_insn (gen_divsi_inv_m2 (inv2, norm32, inv1, i92, + scratch2a)); + emit_insn (gen_divsi_inv_m3 (result, dividend, inv1, inv2, shift, + i2p27, i43, + scratch3a, scratch3b, scratch3c, + scratch2a, scratch2b, scratch3d, scratch3e)); + if (TARGET_DIVIDE_INV_CALL || TARGET_DIVIDE_INV_CALL2) + emit_insn (gen_divsi_inv_call (operands[0], dividend, divisor, result)); + else if (TARGET_DIVIDE_INV_FP) + emit_insn (gen_divsi_inv_fp (operands[0], dividend, divisor, result, + gen_reg_rtx (SImode), gen_reg_rtx (SImode), + gen_reg_rtx (DFmode), gen_reg_rtx (DFmode), + gen_reg_rtx (DFmode))); + else + emit_move_insn (operands[0], result); + DONE; + } + else if (TARGET_SHMEDIA_FPU && TARGET_DIVIDE_FP) { operands[1] = force_reg (SImode, operands[1]); operands[2] = force_reg (SImode, operands[2]); @@ -1475,17 +2097,22 @@ } else if (TARGET_SH5) { - emit_move_insn (operands[3], - function_symbol (TARGET_FPU_ANY - ? \"__sdivsi3_i4\" - : \"__sdivsi3\")); + if (TARGET_DIVIDE_CALL2) + { + rtx tab_base = gen_rtx_SYMBOL_REF (Pmode, \"__div_table\"); + tab_base = gen_datalabel_ref (tab_base); + emit_move_insn (gen_rtx_REG (Pmode, R20_REG), tab_base); + } + if (TARGET_FPU_ANY && TARGET_SH1) + function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_STATIC); + else if (TARGET_DIVIDE_CALL2) + function_symbol (operands[3], \"__sdivsi3_2\", SFUNC_STATIC); + else + function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); if (TARGET_SHMEDIA) - last = gen_divsi3_i1_media (operands[0], - Pmode == DImode - ? operands[3] - : gen_rtx_SUBREG (DImode, operands[3], - 0)); + last = ((TARGET_DIVIDE_CALL2 ? gen_divsi3_media_2 : gen_divsi3_i1_media) + (operands[0], operands[3])); else if (TARGET_FPU_ANY) last = gen_divsi3_i4_single (operands[0], operands[3]); else @@ -1493,7 +2120,7 @@ } else { - emit_move_insn (operands[3], function_symbol (\"__sdivsi3\")); + function_symbol (operands[3], sh_divsi3_libfunc, SFUNC_GOT); last = gen_divsi3_i1 (operands[0], operands[3]); } first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); @@ -1505,6 +2132,411 @@ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); DONE; }") + +;; operands: inv0, tab_base, tab_ix, norm32 +;; scratch equiv in sdivsi3_2: r19, r21 +(define_expand "divsi_inv_m0" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "register_operand" "r") + (match_operand:SI 3 "register_operand" "r")] + UNSPEC_DIV_INV_M0)) + (clobber (match_operand:DI 4 "register_operand" "=r")) + (clobber (match_operand:DI 5 "register_operand" "=r"))] + "TARGET_SHMEDIA" + " +{ +/* +tab_base: r20 +tab_ix: r21 +norm32: r25 + ldx.ub r20, r21, r19 // u0.8 + shlli r21, 1, r21 + muls.l r25, r19, r19 // s2.38 + ldx.w r20, r21, r21 // s2.14 + shari r19, 24, r19 // truncate to s2.14 + sub r21, r19, r19 // some 11 bit inverse in s1.14 +*/ + + rtx inv0 = operands[0]; + rtx tab_base = operands[1]; + rtx tab_ix = operands[2]; + rtx norm32 = operands[3]; + rtx scratch0 = operands[4]; + rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF); + rtx scratch1 = operands[5]; + rtx mem; + + mem = gen_rtx_MEM (QImode, gen_rtx_PLUS (DImode, tab_base, tab_ix)); + emit_insn (gen_zero_extendqidi2 (scratch0, mem)); + emit_insn (gen_ashldi3_media (scratch1, tab_ix, GEN_INT (1))); + emit_insn (gen_mulsidi3_media (scratch0, norm32, scratch0_si)); + mem = gen_rtx_MEM (HImode, gen_rtx_PLUS (DImode, tab_base, scratch1)); + emit_insn (gen_extendhidi2 (scratch1, mem)); + emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (24))); + emit_insn (gen_subdisi3_media (inv0, scratch1, scratch0)); + DONE; +}") + +;; operands: inv1, tab_base, tab_ix, norm32 +(define_insn_and_split "divsi_inv_m1" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "register_operand" "r") + (match_operand:SI 3 "register_operand" "r")] + UNSPEC_DIV_INV_M1)) + (clobber (match_operand:SI 4 "register_operand" "=r")) + (clobber (match_operand:DI 5 "register_operand" "=r")) + (clobber (match_operand:DI 6 "register_operand" "=r")) + (clobber (match_operand:DI 7 "register_operand" "=r")) + (clobber (match_operand:DI 8 "register_operand" "=r"))] + "TARGET_SHMEDIA" + "#" + "&& no_new_pseudos" + [(pc)] + " +{ +/* inv0: r19 + muls.l r19, r19, r18 // u0.28 + muls.l r25, r18, r18 // s2.58 + shlli r19, 45, r0 // multiply by two and convert to s2.58 + sub r0, r18, r18 + shari r18, 28, r18 // some 18 bit inverse in s1.30 +*/ + + rtx inv1 = operands[0]; + rtx tab_base = operands[1]; + rtx tab_ix = operands[2]; + rtx norm32 = operands[3]; + rtx inv0 = operands[4]; + rtx inv0_di = simplify_gen_subreg (DImode, inv0, SImode, 0); + rtx scratch0a = operands[5]; + rtx scratch0b = operands[6]; + rtx scratch0 = operands[7]; + rtx scratch1 = operands[8]; + rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF); + + emit_insn (gen_divsi_inv_m0 (inv0, tab_base, tab_ix, norm32, + scratch0a, scratch0b)); + emit_insn (gen_mulsidi3_media (scratch1, inv0, inv0)); + emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si)); + emit_insn (gen_ashldi3_media (scratch0, inv0_di, GEN_INT (45))); + emit_insn (gen_subdi3 (scratch1, scratch0, scratch1)); + emit_insn (gen_ashrdisi3_media_opaque (inv1, scratch1, GEN_INT (28))); + DONE; +}") + +;; operands: inv2, norm32, inv1, i92 +(define_insn_and_split "divsi_inv_m2" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r") + (match_operand:DI 3 "register_operand" "r")] + UNSPEC_DIV_INV_M2)) + (clobber (match_operand:DI 4 "register_operand" "=r"))] + "TARGET_SHMEDIA" + "#" + "&& no_new_pseudos" + [(pc)] + " +{ +/* + muls.l r18, r25, r0 // s2.60 + shari r0, 16, r0 // s-16.44 + sub + muls.l r0, r18, r19 // s-16.74 + shari r19, 30, r19 // s-16.44 +*/ + rtx inv2 = operands[0]; + rtx norm32 = operands[1]; + rtx inv1 = operands[2]; + rtx i92 = operands[3]; + rtx scratch0 = operands[4]; + rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF); + + emit_insn (gen_mulsidi3_media (scratch0, inv1, norm32)); + emit_insn (gen_ashrdi3_media (scratch0, scratch0, GEN_INT (16))); + emit_insn (gen_subdi3 (scratch0, i92, scratch0)); + emit_insn (gen_mulsidi3_media (scratch0, scratch0_si, inv1)); + emit_insn (gen_ashrdisi3_media_opaque (inv2, scratch0, GEN_INT (30))); + DONE; +}") + +(define_insn_and_split "divsi_inv_m3" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") + (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "register_operand" "r") + (match_operand:DI 4 "register_operand" "r") + (match_operand:DI 5 "arith_reg_or_0_operand" "rN") + (match_operand:DI 6 "arith_reg_or_0_operand" "rN")] + UNSPEC_DIV_INV_M3)) + (clobber (match_operand:DI 7 "register_operand" "=r")) + (clobber (match_operand:DI 8 "register_operand" "=r")) + (clobber (match_operand:DI 9 "register_operand" "=r")) + (clobber (match_operand:DI 10 "register_operand" "=r")) + (clobber (match_operand:SI 11 "register_operand" "=r")) + (clobber (match_operand:SI 12 "register_operand" "=r")) + (clobber (match_operand:DI 13 "register_operand" "=r"))] + "TARGET_SHMEDIA" + "#" + "&& no_new_pseudos" + [(pc)] + " +{ +/* + r0: result r1: shift r4: dividend r18: inv1 r19: inv2 + r0: scratch0 r19: scratch1 r21: scratch2 + + muls.l r18, r4, r25 // s32.30 + muls.l r19, r4, r19 // s15.30 + shari r25, 63, r21 + shari r19, 14, r19 // s18.-14 + sub r25, r19, r0 + shard r0, r1, r0 + sub r0, r21, r0 +*/ + + rtx result = operands[0]; + rtx dividend = operands[1]; + rtx inv1 = operands[2]; + rtx inv2 = operands[3]; + rtx shift = operands[4]; + rtx scratch0 = operands[7]; + rtx scratch1 = operands[8]; + rtx scratch2 = operands[9]; + + emit_insn (gen_mulsidi3_media (scratch0, inv1, dividend)); + emit_insn (gen_mulsidi3_media (scratch1, inv2, dividend)); + emit_insn (gen_ashrdi3_media (scratch2, scratch0, GEN_INT (63))); + emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (14))); + emit_insn (gen_adddi3 (scratch0, scratch0, scratch1)); + emit_insn (gen_ashrdi3_media (scratch0, scratch0, shift)); + emit_insn (gen_subdisi3_media (result, scratch0, scratch2)); + DONE; +}") + +;; operands: quotient, dividend, inv1, inv2, shift, i2p27, i43 +;; inv1: tab_base, tab_ix, norm32 +;; inv2: norm32, inv1, i92 +(define_insn_and_split "divsi_inv_m1_3" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") + (unspec:SI [(match_operand:DI 2 "register_operand" "r") + (match_operand:DI 3 "register_operand" "r") + (match_operand:SI 4 "register_operand" "r")] + UNSPEC_DIV_INV_M1) + (unspec:SI [(match_dup 4) + (unspec:SI [(match_dup 2) + (match_dup 3) + (match_dup 4)] UNSPEC_DIV_INV_M1) + (match_operand:SI 5 "" "")] + UNSPEC_DIV_INV_M2) + (match_operand:DI 6 "register_operand" "r") + (match_operand:DI 7 "arith_reg_or_0_operand" "rN") + (match_operand:DI 8 "arith_reg_or_0_operand" "rN")] + UNSPEC_DIV_INV_M3)) + (clobber (match_operand:DI 9 "register_operand" "=r")) + (clobber (match_operand:DI 10 "register_operand" "=r")) + (clobber (match_operand:DI 11 "register_operand" "=r")) + (clobber (match_operand:DI 12 "register_operand" "=r")) + (clobber (match_operand:SI 13 "register_operand" "=r")) + (clobber (match_operand:SI 14 "register_operand" "=r")) + (clobber (match_operand:DI 15 "register_operand" "=r"))] + "TARGET_SHMEDIA + && (TARGET_DIVIDE_INV_MINLAT + || TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)" + "#" + "&& no_new_pseudos" + [(pc)] + " +{ + rtx result = operands[0]; + rtx dividend = operands[1]; + rtx tab_base = operands[2]; + rtx tab_ix = operands[3]; + rtx norm32 = operands[4]; + /* rtx i92 = operands[5]; */ + rtx shift = operands[6]; + rtx i2p27 = operands[7]; + rtx i43 = operands[8]; + rtx scratch0 = operands[9]; + rtx scratch0_si = simplify_gen_subreg (SImode, scratch0, DImode, SIDI_OFF); + rtx scratch1 = operands[10]; + rtx scratch1_si = simplify_gen_subreg (SImode, scratch1, DImode, SIDI_OFF); + rtx scratch2 = operands[11]; + rtx scratch3 = operands[12]; + rtx scratch4 = operands[13]; + rtx scratch4_di = simplify_gen_subreg (DImode, scratch4, SImode, 0); + rtx scratch5 = operands[14]; + rtx scratch5_di = simplify_gen_subreg (DImode, scratch5, SImode, 0); + rtx scratch6 = operands[15]; + + emit_insn (gen_divsi_inv_m0 (scratch4, tab_base, tab_ix, norm32, + scratch0, scratch1)); + /* inv0 == scratch4 */ + if (! TARGET_DIVIDE_INV20U) + { + emit_insn (gen_mulsidi3_media (scratch0, scratch4, scratch4)); + i2p27 = scratch0; + emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch0_si)); + } + else + { + emit_insn (gen_mulsidi3_media (scratch1, scratch4, scratch4)); + emit_insn (gen_mulsidi3_media (scratch1, norm32, scratch1_si)); + } + emit_insn (gen_ashldi3_media (scratch2, scratch4_di, GEN_INT (45))); + emit_insn (gen_subdi3 (scratch1, scratch2, scratch1)); + emit_insn (gen_ashrdisi3_media_opaque (scratch4, scratch1, GEN_INT (28))); + /* inv1 == scratch4 */ + + if (TARGET_DIVIDE_INV_MINLAT) + { + emit_insn (gen_mulsidi3_media (scratch1, scratch4, norm32)); + emit_insn (gen_mulsidi3_media (scratch2, dividend, scratch4)); + emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (16))); + emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch4)); + emit_insn (gen_ashrdi3_media (scratch3, scratch2, GEN_INT (63))); + emit_insn (gen_ashrsi3_media (scratch5, dividend, GEN_INT (14))); + emit_insn (gen_ashrdi3_media (scratch1, scratch1, GEN_INT (30))); + emit_insn (gen_mulsidi3_media (scratch1, scratch1_si, scratch5)); + emit_insn (gen_xordi3 (scratch0, scratch3, i2p27)); + emit_insn (gen_adddi3 (scratch2, scratch2, scratch0)); + emit_insn (gen_subdi3 (scratch2, scratch2, scratch1)); + } + else + { + rtx label = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ()); + /* Use separate scratch regs for nsb and sign to allow scheduling. */ + emit_insn (gen_nsbdi (scratch6, + simplify_gen_subreg (DImode, dividend, SImode, 0))); + emit_insn (gen_xorsi3 (scratch5, dividend, norm32)); + emit_insn (gen_ashrdi3_media (scratch3, scratch5_di, GEN_INT (63))); + emit_insn (gen_divsi_inv20 (scratch2, + norm32, scratch4, dividend, + scratch6, scratch3, i43, + /* scratch0 may be shared with i2p27. */ + scratch0, scratch1, scratch5, + label, label, i2p27)); + } + emit_insn (gen_ashrdi3_media (scratch2, scratch2, shift)); + emit_insn (gen_subdisi3_media (result, scratch2, scratch3)); + DONE; +}") + +(define_insn "divsi_inv20" + [(set (match_operand:DI 0 "register_operand" "=&r") + (unspec:DI [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "register_operand" "r") + (match_operand:DI 4 "register_operand" "r") + (match_operand:DI 5 "register_operand" "r") + (match_operand:DI 6 "register_operand" "r") + (match_operand:DI 12 "register_operand" "r") + (match_operand 10 "target_operand" "b") + (match_operand 11 "immediate_operand" "i")] + UNSPEC_DIV_INV20)) + (clobber (match_operand:DI 7 "register_operand" "=&r")) + (clobber (match_operand:DI 8 "register_operand" "=&r")) + (clobber (match_operand:SI 9 "register_operand" "=r"))] + "TARGET_SHMEDIA + && (TARGET_DIVIDE_INV20U || TARGET_DIVIDE_INV20L)" + "* +{ +/* operands: %0 div_result, %1 norm32, %2 inv1, %3 dividend, + %4 dividend_nsb, %5 result_sign, %6 i43, %12 i2p27, + %7 round_scratch, %8 scratch0 (di), %9 scratch1 (si) + %10 label (tr), %11 label (imm) + + muls.l inv1, norm32, scratch0 // s2.60 + muls.l inv1, dividend, result // s32.30 + xor i2p27, result_sign, round_scratch + bge/u dividend_nsb, i43, tr.. (label) + shari scratch0, 16, scratch0 // s-16.44 + muls.l sratch0_si, inv1, scratch0 // s-16.74 + sub result, round_scratch, result + shari dividend, 14, scratch1 // s19.-14 + shari scratch0, 30, scratch0 // s-16.44 + muls.l scratch0, scratch1, round_scratch // s15.30 +label: + sub result, round_scratch, result */ + + int likely = TARGET_DIVIDE_INV20L; + + if (! likely) output_asm_insn (\"muls.l\t%2, %1 , %8\", operands); + output_asm_insn (\"muls.l\t%2, %3, %0\;xor\t%12, %5, %7\", operands); + output_asm_insn (likely + ? \"bge/l\t%4, %6, %10\;muls.l\t%2, %1 , %8\" + : \"bge/u\t%4, %6, %10\", operands); + output_asm_insn (\"shari\t%8, 16, %8\;muls.l\t%8, %2, %8\", operands); + if (! likely) output_asm_insn (\"sub\t%0, %7, %0\", operands); + output_asm_insn (\"shari\t%3, 14, %9\;shari\t%8, 30, %8\", operands); + return (likely + ? \"muls.l\t%8, %9, %8\;sub\t%0, %8, %0\n%11:\tadd\t%0, %7, %0\" + : \"muls.l\t%8, %9, %7\n%11:\tsub\t%0, %7, %0\"); +}") + +(define_insn_and_split "divsi_inv_fp" + [(set (match_operand:SI 0 "general_movdst_operand" "=rf") + (div:SI (match_operand:SI 1 "general_movsrc_operand" "rf") + (match_operand:SI 2 "register_operand" "rf"))) + (use (match_operand:SI 3 "general_movsrc_operand" "r")) + (clobber (match_operand:SI 4 "register_operand" "=r")) + (clobber (match_operand:SI 5 "register_operand" "=r")) + (clobber (match_operand:DF 6 "register_operand" "=r")) + (clobber (match_operand:DF 7 "register_operand" "=r")) + (clobber (match_operand:DF 8 "register_operand" "=r"))] + "TARGET_SHMEDIA_FPU" + "#" + "&& (high_life_started || reload_completed)" + [(set (match_dup 0) (match_dup 3))] + "" + [(set_attr "highpart" "must_split")]) + +;; If a matching group of divide-by-inverse instructions is in the same +;; basic block after gcse & loop optimizations, we want to transform them +;; to a straight division using floating point for TARGET_DIVIDE_INV_FP. +(define_insn_and_split "*divsi_inv_fp_combine" + [(set (match_operand:SI 0 "register_operand" "=f") + (div:SI (match_operand:SI 1 "register_operand" "f") + (match_operand:SI 2 "register_operand" "f"))) + (use (unspec:SI [(match_dup 1) + (match_operand:SI 3 "" "") + (unspec:SI [(match_operand:SI 4 "" "") + (match_dup 3) + (match_operand:DI 5 "" "")] UNSPEC_DIV_INV_M2) + (match_operand:DI 6 "" "") + (const_int 0) + (const_int 0)] UNSPEC_DIV_INV_M3)) + (clobber (match_operand:SI 7 "fp_arith_reg_operand" "")) + (clobber (match_operand:SI 8 "fp_arith_reg_operand" "")) + (clobber (match_operand:DF 9 "fp_arith_reg_operand" "")) + (clobber (match_operand:DF 10 "fp_arith_reg_operand" "")) + (clobber (match_operand:DF 11 "fp_arith_reg_operand" ""))] + "TARGET_SHMEDIA_FPU && TARGET_DIVIDE_INV_FP && no_new_pseudos" + "#" + "&& 1" + [(set (match_dup 9) (float:DF (match_dup 1))) + (set (match_dup 10) (float:DF (match_dup 2))) + (set (match_dup 11) (div:DF (match_dup 9) (match_dup 10))) + (set (match_dup 8) + (fix:SI (match_dup 11))) + (set (match_dup 0) (match_dup 8))] + " +{ + if (! fp_arith_reg_operand (operands[1], SImode)) + { + emit_move_insn (operands[7], operands[1]); + operands[1] = operands[7]; + } + if (! fp_arith_reg_operand (operands[2], SImode)) + { + emit_move_insn (operands[8], operands[2]); + operands[2] = operands[8]; + } +}" + [(set_attr "highpart" "must_split")]) ;; ------------------------------------------------------------------------- ;; Multiplication instructions @@ -1625,7 +2657,7 @@ "") (define_insn "mul_r" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (mult:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "z")))] "TARGET_SH2A" @@ -1655,7 +2687,7 @@ { /* The address must be set outside the libcall, since it goes into a pseudo. */ - rtx sym = function_symbol (\"__mulsi3\"); + rtx sym = function_symbol (NULL, \"__mulsi3\", SFUNC_STATIC); rtx addr = force_reg (SImode, sym); rtx insns = gen_mulsi3_call (operands[0], operands[1], operands[2], addr); @@ -1710,15 +2742,16 @@ }") (define_insn "mulsidi3_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (mult:DI (sign_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r")) (sign_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))] "TARGET_SHMEDIA" "muls.l %1, %2, %0" - [(set_attr "type" "dmpy_media")]) + [(set_attr "type" "dmpy_media") + (set_attr "highpart" "ignore")]) (define_insn "mulsidi3_compact" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) @@ -1728,7 +2761,7 @@ "#") (define_split - [(set (match_operand:DI 0 "arith_reg_operand" "") + [(set (match_operand:DI 0 "arith_reg_dest" "") (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))) @@ -1781,15 +2814,16 @@ }") (define_insn "umulsidi3_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (mult:DI (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "%r")) (zero_extend:DI (match_operand:SI 2 "extend_reg_operand" "r"))))] "TARGET_SHMEDIA" "mulu.l %1, %2, %0" - [(set_attr "type" "dmpy_media")]) + [(set_attr "type" "dmpy_media") + (set_attr "highpart" "ignore")]) (define_insn "umulsidi3_compact" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) @@ -1799,7 +2833,7 @@ "#") (define_split - [(set (match_operand:DI 0 "arith_reg_operand" "") + [(set (match_operand:DI 0 "arith_reg_dest" "") (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))) (clobber (reg:SI MACH_REG)) @@ -1905,30 +2939,82 @@ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); DONE; }") + +(define_insn_and_split "muldi3" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (mult:DI (match_operand:DI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "arith_reg_operand" "r"))) + (clobber (match_scratch:DI 3 "=&r")) + (clobber (match_scratch:DI 4 "=r"))] + "TARGET_SHMEDIA" + "#" + "reload_completed" + [(const_int 0)] + " +{ + rtx op3_v2si, op2_v2si; + + op3_v2si = operands[3]; + if (GET_CODE (op3_v2si) == SIGN_EXTEND) + { + op3_v2si = XEXP (op3_v2si, 0); + op3_v2si = simplify_gen_subreg (DImode, op3_v2si, GET_MODE (op3_v2si), 0); + } + op3_v2si = simplify_gen_subreg (V2SImode, op3_v2si, DImode, 0); + op2_v2si = operands[2]; + if (GET_CODE (op2_v2si) == SIGN_EXTEND) + { + op2_v2si = XEXP (op2_v2si, 0); + op2_v2si = simplify_gen_subreg (DImode, op2_v2si, GET_MODE (op2_v2si), 0); + } + op2_v2si = simplify_gen_subreg (V2SImode, op2_v2si, DImode, 0); + emit_insn (gen_rotldi3 (operands[3], operands[1], GEN_INT (32))); + emit_insn (gen_mulv2si3 (op3_v2si, op3_v2si, op2_v2si)); + emit_insn (gen_umulsidi3_media (operands[4], + sh_gen_truncate (SImode, operands[1], 0), + sh_gen_truncate (SImode, operands[2], 0))); + emit_insn (gen_anddi3 (operands[0], operands[3], GEN_INT (0xffffffff00000000LL))); + emit_insn (gen_ashldi3_media (operands[3], operands[3], GEN_INT (32))); + emit_insn (gen_adddi3 (operands[0], operands[3], operands[0])); + emit_insn (gen_adddi3 (operands[0], operands[4], operands[0])); + DONE; +}") + ;; ------------------------------------------------------------------------- ;; Logical operations ;; ------------------------------------------------------------------------- (define_insn "*andsi3_compact" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,z") + [(set (match_operand:SI 0 "arith_reg_dest" "=r,z") (and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") (match_operand:SI 2 "logical_operand" "r,K08")))] "TARGET_SH1" "and %2,%0" [(set_attr "type" "arith")]) +(define_insn "*andsi3_media" + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") + (and:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") + (match_operand:SI 2 "logical_operand" "r,I10")))] + "TARGET_SHMEDIA" + "@ + and %1, %2, %0 + andi %1, %2, %0" + [(set_attr "type" "arith_media")]) + ;; If the constant is 255, then emit an extu.b instruction instead of an ;; and, since that will give better code. (define_expand "andsi3" [(set (match_operand:SI 0 "arith_reg_operand" "") - (and:SI (match_operand:SI 1 "arith_reg_operand" "") + (and:SI (match_operand:SI 1 "logical_reg_operand" "") (match_operand:SI 2 "logical_operand" "")))] - "TARGET_SH1" + "" " { - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255) + if (TARGET_SH1 + && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 255) { emit_insn (gen_zero_extendqisi2 (operands[0], gen_lowpart (QImode, operands[1]))); @@ -1937,7 +3023,7 @@ }") (define_insn_and_split "anddi3" - [(set (match_operand:DI 0 "arith_reg_operand" "=r,r,r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r,r,r") (and:DI (match_operand:DI 1 "arith_reg_operand" "%r,r,r") (match_operand:DI 2 "and_operand" "r,I10,J16")))] "TARGET_SHMEDIA" @@ -1958,24 +3044,49 @@ }" [(set_attr "type" "arith_media")]) +(define_insn "andcsi3" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (and:SI (match_operand:SI 1 "arith_reg_operand" "r") + (not:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] + "TARGET_SHMEDIA" + "andc %1,%2,%0" + [(set_attr "type" "arith_media")]) + (define_insn "andcdi3" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (and:DI (match_operand:DI 1 "arith_reg_operand" "r") (not:DI (match_operand:DI 2 "arith_reg_operand" "r"))))] "TARGET_SHMEDIA" "andc %1,%2,%0" [(set_attr "type" "arith_media")]) -(define_insn "iorsi3" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,z") +(define_expand "iorsi3" + [(set (match_operand:SI 0 "arith_reg_operand" "") + (ior:SI (match_operand:SI 1 "logical_reg_operand" "") + (match_operand:SI 2 "logical_operand" "")))] + "" + "") + +(define_insn "*iorsi3_compact" + [(set (match_operand:SI 0 "arith_reg_dest" "=r,z") (ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") (match_operand:SI 2 "logical_operand" "r,K08")))] "TARGET_SH1" "or %2,%0" [(set_attr "type" "arith")]) +(define_insn "*iorsi3_media" + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") + (ior:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") + (match_operand:SI 2 "logical_operand" "r,I10")))] + "TARGET_SHMEDIA" + "@ + or %1, %2, %0 + ori %1, %2, %0" + [(set_attr "type" "arith_media")]) + (define_insn "iordi3" - [(set (match_operand:DI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") (ior:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") (match_operand:DI 2 "logical_operand" "r,I10")))] "TARGET_SHMEDIA" @@ -1984,18 +3095,74 @@ ori %1, %2, %0" [(set_attr "type" "arith_media")]) -(define_insn "xorsi3" - [(set (match_operand:SI 0 "arith_reg_operand" "=z,r") +(define_insn_and_split "*logical_sidi3" + [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") + (sign_extend:DI (match_operator:SI 3 "logical_operator" + [(match_operand:SI 1 "arith_reg_operand" "%r,r") + (match_operand:SI 2 "logical_operand" "r,I10")])))] + "TARGET_SHMEDIA" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 3))] + " +{ + operands[3] + = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode, + simplify_gen_subreg (DImode, operands[1], SImode, 0), + simplify_gen_subreg (DImode, operands[2], SImode, 0)); +}") + +(define_insn_and_split "*logical_sidisi3" + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") + (truncate:SI (sign_extend:DI + (match_operator:SI 3 "logical_operator" + [(match_operand:SI 1 "arith_reg_operand" "%r,r") + (match_operand:SI 2 "logical_operand" "r,I10")]))))] + "TARGET_SHMEDIA" + "#" + "&& 1" + [(set (match_dup 0) (match_dup 3))]) + +(define_insn_and_split "*logical_sidi3_2" + [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") + (sign_extend:DI (truncate:SI (sign_extend:DI + (match_operator:SI 3 "logical_operator" + [(match_operand:SI 1 "arith_reg_operand" "%r,r") + (match_operand:SI 2 "logical_operand" "r,I10")])))))] + "TARGET_SHMEDIA" + "#" + "&& 1" + [(set (match_dup 0) (sign_extend:DI (match_dup 3)))]) + +(define_expand "xorsi3" + [(set (match_operand:SI 0 "arith_reg_operand" "") + (xor:SI (match_operand:SI 1 "logical_reg_operand" "") + (match_operand:SI 2 "xor_operand" "")))] + "" + "") + +(define_insn "*xorsi3_compact" + [(set (match_operand:SI 0 "arith_reg_dest" "=z,r") (xor:SI (match_operand:SI 1 "arith_reg_operand" "%0,0") (match_operand:SI 2 "logical_operand" "K08,r")))] "TARGET_SH1" "xor %2,%0" [(set_attr "type" "arith")]) +(define_insn "*xorsi3_media" + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") + (xor:SI (match_operand:SI 1 "logical_reg_operand" "%r,r") + (match_operand:SI 2 "xor_operand" "r,I06")))] + "TARGET_SHMEDIA" + "@ + xor %1, %2, %0 + xori %1, %2, %0" + [(set_attr "type" "arith_media")]) + (define_insn "xordi3" - [(set (match_operand:DI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") (xor:DI (match_operand:DI 1 "arith_reg_operand" "%r,r") - (match_operand:DI 2 "shmedia_6bit_operand" "r,I06")))] + (match_operand:DI 2 "xor_operand" "r,I06")))] "TARGET_SHMEDIA" "@ xor %1, %2, %0 @@ -2005,7 +3172,7 @@ ;; Combiner bridge pattern for 2 * sign extend -> logical op -> truncate. ;; converts 2 * sign extend -> logical op into logical op -> sign extend (define_split - [(set (match_operand:DI 0 "arith_reg_operand" "") + [(set (match_operand:DI 0 "arith_reg_dest" "") (sign_extend:DI (match_operator 4 "binary_logical_operator" [(match_operand 1 "any_register_operand" "") (match_operand 2 "any_register_operand" "")])))] @@ -2075,8 +3242,25 @@ }" [(set_attr "type" "arith_media")]) +(define_split + [(set (match_operand:DI 0 "arith_reg_dest" "") + (ior:DI (zero_extend:DI (mem:QI (match_operand 1 + "ua_address_operand" ""))) + (ashift:DI (match_operand:DI 2 "arith_reg_operand" "") + (const_int 8)))) + (clobber (match_operand:DI 3 "register_operand" ""))] + "TARGET_SHMEDIA" + [(match_dup 4) (match_dup 5)] + " +{ + operands[4] = ((TARGET_LITTLE_ENDIAN ? gen_ldhi_q : gen_ldlo_q) + (operands[3], operands[1])); + operands[5] = gen_mextr_rl (operands[0], operands[3], operands[2], + GEN_INT (56), GEN_INT (8)); +}") + (define_insn "rotlsi3_1" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1))) (set (reg:SI T_REG) @@ -2086,7 +3270,7 @@ [(set_attr "type" "arith")]) (define_insn "rotlsi3_31" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (rotate:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 31))) (clobber (reg:SI T_REG))] @@ -2095,7 +3279,7 @@ [(set_attr "type" "arith")]) (define_insn "rotlsi3_16" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (rotate:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 16)))] "TARGET_SH1" @@ -2103,7 +3287,7 @@ [(set_attr "type" "arith")]) (define_expand "rotlsi3" - [(set (match_operand:SI 0 "arith_reg_operand" "") + [(set (match_operand:SI 0 "arith_reg_dest" "") (rotate:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "immediate_operand" "")))] "TARGET_SH1" @@ -2159,7 +3343,7 @@ }") (define_insn "*rotlhi3_8" - [(set (match_operand:HI 0 "arith_reg_operand" "=r") + [(set (match_operand:HI 0 "arith_reg_dest" "=r") (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r") (const_int 8)))] "TARGET_SH1" @@ -2181,7 +3365,7 @@ ;; shift left (define_insn "ashlsi3_sh2a" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "arith_reg_operand" "r")))] "TARGET_SH2A" @@ -2193,7 +3377,7 @@ ;; insns. (define_insn_and_split "ashlsi3_std" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,r,r,r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r,r,r") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0") (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri"))) (clobber (match_scratch:SI 3 "=X,X,X,&r"))] @@ -2218,7 +3402,7 @@ (set_attr "type" "dyn_shift,arith,arith,arith")]) (define_insn "ashlhi3_k" - [(set (match_operand:HI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:HI 0 "arith_reg_dest" "=r,r") (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0") (match_operand:HI 2 "const_int_operand" "M,P27")))] "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2]))" @@ -2228,7 +3412,7 @@ [(set_attr "type" "arith")]) (define_insn "ashlsi3_n" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "const_int_operand" "n"))) (clobber (reg:SI T_REG))] @@ -2245,7 +3429,7 @@ (set_attr "type" "arith")]) (define_split - [(set (match_operand:SI 0 "arith_reg_operand" "") + [(set (match_operand:SI 0 "arith_reg_dest" "") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "const_int_operand" ""))) (clobber (reg:SI T_REG))] @@ -2258,14 +3442,15 @@ }") (define_insn "ashlsi3_media" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") (ashift:SI (match_operand:SI 1 "extend_reg_operand" "r,r") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] + (match_operand:SI 2 "shift_count_operand" "r,n")))] "TARGET_SHMEDIA" "@ shlld.l %1, %2, %0 shlli.l %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_expand "ashlsi3" [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") @@ -2293,7 +3478,7 @@ }") (define_insn "*ashlhi3_n" - [(set (match_operand:HI 0 "arith_reg_operand" "=r") + [(set (match_operand:HI 0 "arith_reg_dest" "=r") (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0") (match_operand:HI 2 "const_int_operand" "n"))) (clobber (reg:SI T_REG))] @@ -2324,7 +3509,7 @@ }") (define_split - [(set (match_operand:HI 0 "arith_reg_operand" "") + [(set (match_operand:HI 0 "arith_reg_dest" "") (ashift:HI (match_operand:HI 1 "arith_reg_operand" "") (match_operand:HI 2 "const_int_operand" ""))) (clobber (reg:SI T_REG))] @@ -2341,7 +3526,7 @@ ; (define_insn "ashrsi3_sh2a" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] "TARGET_SH2A" @@ -2350,7 +3535,7 @@ (set_attr "length" "4")]) (define_insn "ashrsi3_k" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "const_int_operand" "M"))) (clobber (reg:SI T_REG))] @@ -2367,7 +3552,7 @@ ;; ??? This should be a define expand. (define_insn "ashrsi2_16" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 16)))] "TARGET_SH1" @@ -2375,7 +3560,7 @@ [(set_attr "length" "4")]) (define_split - [(set (match_operand:SI 0 "arith_reg_operand" "") + [(set (match_operand:SI 0 "arith_reg_dest" "") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") (const_int 16)))] "TARGET_SH1" @@ -2386,7 +3571,7 @@ ;; ??? This should be a define expand. (define_insn "ashrsi2_31" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 31))) (clobber (reg:SI T_REG))] @@ -2395,7 +3580,7 @@ [(set_attr "length" "4")]) (define_split - [(set (match_operand:SI 0 "arith_reg_operand" "") + [(set (match_operand:SI 0 "arith_reg_dest" "") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") (const_int 31))) (clobber (reg:SI T_REG))] @@ -2404,12 +3589,26 @@ " { emit_insn (gen_ashlsi_c (operands[0], operands[1])); - emit_insn (gen_subc1 (operands[0], operands[0], operands[0])); + emit_insn (gen_mov_neg_si_t (operands[0])); + DONE; +}") + +(define_peephole2 + [(set (match_operand:SI 0 "arith_reg_dest" "") (const_int 0)) + (set (reg:SI T_REG) + (gt:SI (match_dup 0) (match_operand:SI 1 "arith_reg_operand" "")))] + "TARGET_SH1 + && peep2_reg_dead_p (2, operands[0]) + && peep2_reg_dead_p (2, operands[1])" + [(const_int 0)] + " +{ + emit_insn (gen_ashlsi_c (operands[1], operands[1])); DONE; }") (define_insn "ashlsi_c" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1))) (set (reg:SI T_REG) (lt:SI (match_dup 1) (const_int 0)))] @@ -2417,8 +3616,16 @@ "shll %0" [(set_attr "type" "arith")]) +(define_insn "*ashlsi_c_void" + [(set (reg:SI T_REG) + (lt:SI (match_operand:SI 0 "arith_reg_operand" "r") (const_int 0))) + (clobber (match_scratch:SI 1 "=0"))] + "TARGET_SH1 && cse_not_expected" + "shll %0" + [(set_attr "type" "arith")]) + (define_insn "ashrsi3_d" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] "TARGET_SH3" @@ -2438,14 +3645,15 @@ (set_attr "needs_delay_slot" "yes")]) (define_insn "ashrsi3_media" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") (ashiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] + (match_operand:SI 2 "shift_count_operand" "r,n")))] "TARGET_SHMEDIA" "@ shard.l %1, %2, %0 shari.l %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_expand "ashrsi3" [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") @@ -2469,7 +3677,7 @@ ;; logical shift right (define_insn "lshrsi3_sh2a" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] "TARGET_SH2A" @@ -2478,7 +3686,7 @@ (set_attr "length" "4")]) (define_insn "lshrsi3_d" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] "TARGET_SH3" @@ -2488,7 +3696,7 @@ ;; Only the single bit shift clobbers the T bit. (define_insn "lshrsi3_m" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "const_int_operand" "M"))) (clobber (reg:SI T_REG))] @@ -2497,7 +3705,7 @@ [(set_attr "type" "arith")]) (define_insn "lshrsi3_k" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "const_int_operand" "P27")))] "TARGET_SH1 && CONST_OK_FOR_P27 (INTVAL (operands[2])) @@ -2506,7 +3714,7 @@ [(set_attr "type" "arith")]) (define_insn "lshrsi3_n" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (match_operand:SI 2 "const_int_operand" "n"))) (clobber (reg:SI T_REG))] @@ -2523,7 +3731,7 @@ (set_attr "type" "arith")]) (define_split - [(set (match_operand:SI 0 "arith_reg_operand" "") + [(set (match_operand:SI 0 "arith_reg_dest" "") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "const_int_operand" ""))) (clobber (reg:SI T_REG))] @@ -2536,17 +3744,18 @@ }") (define_insn "lshrsi3_media" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") (lshiftrt:SI (match_operand:SI 1 "extend_reg_operand" "r,r") - (match_operand:SI 2 "nonmemory_operand" "r,n")))] + (match_operand:SI 2 "shift_count_operand" "r,n")))] "TARGET_SHMEDIA" "@ shlrd.l %1, %2, %0 shlri.l %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_expand "lshrsi3" - [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "") + [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "nonmemory_operand" ""))) (clobber (reg:SI T_REG))])] @@ -2575,7 +3784,7 @@ ;; ??? This should be a define expand. (define_insn "ashldi3_k" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0") (const_int 1))) (clobber (reg:SI T_REG))] @@ -2585,15 +3794,24 @@ (set_attr "type" "arith")]) (define_insn "ashldi3_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r,r") (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r") - (match_operand:DI 2 "nonmemory_operand" "r,n")))] + (match_operand:DI 2 "shift_count_operand" "r,n")))] "TARGET_SHMEDIA" "@ shlld %1, %2, %0 shlli %1, %2, %0" [(set_attr "type" "arith_media")]) +(define_insn "*ashldisi3_media" + [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) + (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "const_int_operand" "n")))] + "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" + "shlli.l %1, %2, %0" + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) + (define_expand "ashldi3" [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") (ashift:DI (match_operand:DI 1 "arith_reg_operand" "") @@ -2615,7 +3833,7 @@ ;; ??? This should be a define expand. (define_insn "lshrdi3_k" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") (const_int 1))) (clobber (reg:SI T_REG))] @@ -2625,15 +3843,26 @@ (set_attr "type" "arith")]) (define_insn "lshrdi3_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r") - (match_operand:DI 2 "nonmemory_operand" "r,n")))] - "TARGET_SHMEDIA" + (match_operand:DI 2 "shift_count_operand" "r,n")))] + "TARGET_SHMEDIA + && (arith_reg_dest (operands[0], DImode) + || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 32))" "@ shlrd %1, %2, %0 shlri %1, %2, %0" [(set_attr "type" "arith_media")]) +(define_insn "*lshrdisi3_media" + [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) + (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "const_int_operand" "n")))] + "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" + "shlri.l %1, %2, %0" + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) + (define_expand "lshrdi3" [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") (lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") @@ -2655,7 +3884,7 @@ ;; ??? This should be a define expand. (define_insn "ashrdi3_k" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0") (const_int 1))) (clobber (reg:SI T_REG))] @@ -2665,15 +3894,44 @@ (set_attr "type" "arith")]) (define_insn "ashrdi3_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r,r") - (match_operand:DI 2 "nonmemory_operand" "r,n")))] - "TARGET_SHMEDIA" + (match_operand:DI 2 "shift_count_operand" "r,n")))] + "TARGET_SHMEDIA + && (arith_reg_dest (operands[0], DImode) + || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32))" "@ shard %1, %2, %0 shari %1, %2, %0" [(set_attr "type" "arith_media")]) +(define_insn "*ashrdisi3_media" + [(set (subreg:DI (match_operand:SI 0 "arith_reg_operand" "=r") 0) + (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "const_int_operand" "n")))] + "TARGET_SHMEDIA && INTVAL (operands[2]) < 32" + "shari.l %1, %2, %0" + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) + +(define_insn "ashrdisi3_media_high" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (truncate:SI + (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "const_int_operand" "n"))))] + "TARGET_SHMEDIA && INTVAL (operands[2]) >= 32" + "shari %1, %2, %0" + [(set_attr "type" "arith_media")]) + +(define_insn "ashrdisi3_media_opaque" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (unspec:SI [(match_operand:DI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "const_int_operand" "n")] + UNSPEC_ASHIFTRT))] + "TARGET_SHMEDIA" + "shari %1, %2, %0" + [(set_attr "type" "arith_media")]) + (define_expand "ashrdi3" [(parallel [(set (match_operand:DI 0 "arith_reg_operand" "") (ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "") @@ -2890,7 +4148,7 @@ ;; allow the xtrct instruction to be generated from C source. (define_insn "xtrct_left" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 16)) (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0") @@ -2900,7 +4158,7 @@ [(set_attr "type" "arith")]) (define_insn "xtrct_right" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 16)) (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r") @@ -2914,7 +4172,7 @@ ;; ------------------------------------------------------------------------- (define_insn "negc" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (plus:SI (reg:SI T_REG) (match_operand:SI 1 "arith_reg_operand" "r")))) (set (reg:SI T_REG) @@ -2925,7 +4183,7 @@ [(set_attr "type" "arith")]) (define_insn "*negdi_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "sub r63, %1, %0" @@ -2956,35 +4214,61 @@ }") (define_insn "negsi2" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (neg:SI (match_operand:SI 1 "arith_reg_operand" "r")))] "TARGET_SH1" "neg %1,%0" [(set_attr "type" "arith")]) (define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (not:SI (match_operand:SI 1 "arith_reg_operand" "r")))] "TARGET_SH1" "not %1,%0" [(set_attr "type" "arith")]) -(define_expand "one_cmpldi2" - [(set (match_operand:DI 0 "arith_reg_operand" "") - (xor:DI (match_operand:DI 1 "arith_reg_operand" "") - (const_int -1)))] - "TARGET_SHMEDIA" "") +(define_expand "one_cmpldi2" + [(set (match_operand:DI 0 "arith_reg_dest" "") + (xor:DI (match_operand:DI 1 "arith_reg_operand" "") + (const_int -1)))] + "TARGET_SHMEDIA" "") + +/* The SH4 202 can do zero-offset branches without pipeline stalls. + This can be used as some kind of conditional execution, which is useful + for abs. */ +(define_split + [(set (match_operand:SI 0 "arith_reg_dest" "") + (plus:SI (xor:SI (neg:SI (reg:SI T_REG)) + (match_operand:SI 1 "arith_reg_operand" "")) + (reg:SI T_REG)))] + "TARGET_HARD_SH4" + [(const_int 0)] + "emit_insn (gen_movsi_i (operands[0], operands[1])); + emit_insn (gen_cneg (operands[0], operands[0], operands[0])); + DONE;") + +(define_insn "cneg" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0)) + (match_operand:SI 1 "arith_reg_operand" "0") + (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] + "TARGET_HARD_SH4" + "bf 0f\;neg %2,%0\\n0:" + [(set_attr "type" "arith") ;; poor approximation + (set_attr "length" "4")]) + ;; ------------------------------------------------------------------------- ;; Zero extension instructions ;; ------------------------------------------------------------------------- (define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (zero_extend:DI (match_operand:SI 1 "extend_reg_operand" "r")))] "TARGET_SHMEDIA" "addz.l %1, r63, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "extend")]) (define_insn "zero_extendhidi2" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -2993,7 +4277,11 @@ "@ # ld%M1.uw %m1, %0" - [(set_attr "type" "*,load_media")]) + [(set_attr "type" "*,load_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_split [(set (match_operand:DI 0 "register_operand" "") @@ -3010,7 +4298,7 @@ ;; ??? when a truncated input to a zero_extend is reloaded, reload will ;; reload the entire truncate expression. (define_insn_and_split "*loaddi_trunc" - [(set (match_operand 0 "int_gpr_dest" "=r") + [(set (match_operand 0 "any_register_operand" "=r") (truncate (match_operand:DI 1 "memory_operand" "m")))] "TARGET_SHMEDIA && reload_completed" "#" @@ -3025,7 +4313,11 @@ "@ andi %1, 255, %0 ld%M1.ub %m1, %0" - [(set_attr "type" "arith_media,load_media")]) + [(set_attr "type" "arith_media,load_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_expand "zero_extendhisi2" [(set (match_operand:SI 0 "arith_reg_operand" "") @@ -3038,7 +4330,7 @@ }") (define_insn "*zero_extendhisi2_compact" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r")))] "TARGET_SH1" "extu.w %1,%0" @@ -3051,18 +4343,27 @@ "@ # ld%M1.uw %m1, %0" - [(set_attr "type" "arith_media,load_media")]) + [(set_attr "type" "arith_media,load_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_split [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))] "TARGET_SHMEDIA && reload_completed" - [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 16))) + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))] " { - if (GET_CODE (operands[1]) == TRUNCATE) - operands[1] = XEXP (operands[1], 0); + rtx op1 = operands[1]; + + if (GET_CODE (op1) == TRUNCATE) + op1 = XEXP (op1, 0); + operands[2] + = simplify_gen_subreg (SImode, op1, GET_MODE (op1), + subreg_lowpart_offset (SImode, GET_MODE (op1))); }") (define_expand "zero_extendqisi2" @@ -3076,7 +4377,7 @@ }") (define_insn "*zero_extendqisi2_compact" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (zero_extend:SI (match_operand:QI 1 "arith_reg_operand" "r")))] "TARGET_SH1" "extu.b %1,%0" @@ -3089,10 +4390,14 @@ "@ andi %1, 255, %0 ld%M1.ub %m1, %0" - [(set_attr "type" "arith_media,load_media")]) + [(set_attr "type" "arith_media,load_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "arith_reg_operand" "=r") + [(set (match_operand:HI 0 "arith_reg_dest" "=r") (zero_extend:HI (match_operand:QI 1 "arith_reg_operand" "r")))] "TARGET_SH1" "extu.b %1,%0" @@ -3107,13 +4412,18 @@ ;; convert_move generates good code for SH[1-4]. (define_insn "extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))] + [(set (match_operand:DI 0 "register_operand" "=r,r,r") + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,?f")))] "TARGET_SHMEDIA" "@ add.l %1, r63, %0 - ld%M1.l %m1, %0" - [(set_attr "type" "arith_media,load_media")]) + ld%M1.l %m1, %0 + fmov.sl %1, %0" + [(set_attr "type" "arith_media,load_media,fpconv_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "extend")))]) (define_insn "extendhidi2" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -3122,7 +4432,11 @@ "@ # ld%M1.w %m1, %0" - [(set_attr "type" "*,load_media")]) + [(set_attr "type" "*,load_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_split [(set (match_operand:DI 0 "register_operand" "") @@ -3143,7 +4457,11 @@ "@ # ld%M1.b %m1, %0" - [(set_attr "type" "*,load_media")]) + [(set_attr "type" "*,load_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_split [(set (match_operand:DI 0 "register_operand" "") @@ -3158,13 +4476,13 @@ }") (define_expand "extendhisi2" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))] "" "") (define_insn "*extendhisi2_compact" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))] "TARGET_SH1" "@ @@ -3179,28 +4497,36 @@ "@ # ld%M1.w %m1, %0" - [(set_attr "type" "arith_media,load_media")]) + [(set_attr "type" "arith_media,load_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_split [(set (match_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:HI 1 "extend_reg_operand" "")))] "TARGET_SHMEDIA && reload_completed" - [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 16))) + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16))) (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))] " { - if (GET_CODE (operands[1]) == TRUNCATE) - operands[1] = XEXP (operands[1], 0); + rtx op1 = operands[1]; + if (GET_CODE (op1) == TRUNCATE) + op1 = XEXP (op1, 0); + operands[2] + = simplify_gen_subreg (SImode, op1, GET_MODE (op1), + subreg_lowpart_offset (SImode, GET_MODE (op1))); }") (define_expand "extendqisi2" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))] "" "") (define_insn "*extendqisi2_compact" - [(set (match_operand:SI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") (sign_extend:SI (match_operand:QI 1 "general_movsrc_operand" "r,m")))] "TARGET_SH1" "@ @@ -3215,22 +4541,30 @@ "@ # ld%M1.b %m1, %0" - [(set_attr "type" "arith_media,load_media")]) + [(set_attr "type" "arith_media,load_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_split [(set (match_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:QI 1 "extend_reg_operand" "")))] "TARGET_SHMEDIA && reload_completed" - [(set (match_dup 0) (ashift:SI (subreg:SI (match_dup 1) 0) (const_int 24))) + [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24))) (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))] " { - if (GET_CODE (operands[1]) == TRUNCATE) - operands[1] = XEXP (operands[1], 0); + rtx op1 = operands[1]; + if (GET_CODE (op1) == TRUNCATE) + op1 = XEXP (op1, 0); + operands[2] + = simplify_gen_subreg (SImode, op1, GET_MODE (op1), + subreg_lowpart_offset (SImode, GET_MODE (op1))); }") (define_insn "extendqihi2" - [(set (match_operand:HI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:HI 0 "arith_reg_dest" "=r,r") (sign_extend:HI (match_operand:QI 1 "general_movsrc_operand" "r,m")))] "TARGET_SH1" "@ @@ -3252,8 +4586,11 @@ fmov.ls %1, %0 fmov.sl %T1, %0 fmov.s %T1, %0" - [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media")]) - + [(set_attr "type" "arith_media,store_media,fstore_media,fload_media,fpconv_media,fmove_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "extend")))]) (define_insn "truncdihi2" [(set (match_operand:HI 0 "general_movdst_operand" "=?r,m") @@ -3263,7 +4600,11 @@ shlli\\t%1,48,%0\;shlri\\t%0,48,%0 st%M0.w %m0, %1" [(set_attr "type" "arith_media,store_media") - (set_attr "length" "8,4")]) + (set_attr "length" "8,4") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "extend")))]) ; N.B. This should agree with LOAD_EXTEND_OP and movqi. ; Because we use zero extension, we can't provide signed QImode compares @@ -3275,8 +4616,11 @@ "@ andi %1, 255, %0 st%M0.b %m0, %1" - [(set_attr "type" "arith_media,store")]) - + [(set_attr "type" "arith_media,store") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "extend")))]) ;; ------------------------------------------------------------------------- ;; Move instructions ;; ------------------------------------------------------------------------- @@ -3480,7 +4824,7 @@ (define_insn_and_split "load_ra" [(set (match_operand:SI 0 "general_movdst_operand" "") - (unspec:SI [(match_operand 1 "register_operand" "")] UNSPEC_RA))] + (unspec:SI [(match_operand:SI 1 "register_operand" "")] UNSPEC_RA))] "TARGET_SH1" "#" "&& ! currently_expanding_to_rtl" @@ -3491,14 +4835,18 @@ operands[1] = gen_rtx_MEM (SImode, return_address_pointer_rtx); }") +;; The '?'s in the following constraints may not reflect the time taken +;; to perform the move. They are there to discourage the use of floating- +;; point registers for storing integer values. (define_insn "*movsi_media" [(set (match_operand:SI 0 "general_movdst_operand" - "=r,r,r,r,m,f,m,f,r,f,*b,r,b") + "=r,r,r,r,m,f?,m,f?,r,f?,*b,r,b") (match_operand:SI 1 "general_movsrc_operand" - "r,I16C16,nCpg,m,rZ,m,f,rZ,f,f,r,*b,Csy"))] + "r,I16C16,nCpg,m,rZ,m,f?,rZ,f?,f?,r,*b,Csy"))] "TARGET_SHMEDIA_FPU && (register_operand (operands[0], SImode) - || sh_register_operand (operands[1], SImode))" + || sh_register_operand (operands[1], SImode) + || GET_CODE (operands[1]) == TRUNCATE)" "@ add.l %1, r63, %0 movi %1, %0 @@ -3514,16 +4862,21 @@ gettr %1, %0 pt %1, %0" [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,fload_media,fstore_media,fload_media,fpconv_media,fmove_media,ptabs_media,gettr_media,pt_media") - (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12")]) + (set_attr "length" "4,4,8,4,4,4,4,4,4,4,4,4,12") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_insn "*movsi_media_nofpu" [(set (match_operand:SI 0 "general_movdst_operand" - "=r,r,r,r,m,*b,r,b") + "=r,r,r,r,m,*b,r,*b") (match_operand:SI 1 "general_movsrc_operand" "r,I16C16,nCpg,m,rZ,r,*b,Csy"))] "TARGET_SHMEDIA && (register_operand (operands[0], SImode) - || sh_register_operand (operands[1], SImode))" + || sh_register_operand (operands[1], SImode) + || GET_CODE (operands[1]) == TRUNCATE)" "@ add.l %1, r63, %0 movi %1, %0 @@ -3534,18 +4887,72 @@ gettr %1, %0 pt %1, %0" [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media") - (set_attr "length" "4,4,8,4,4,4,4,12")]) + (set_attr "length" "4,4,8,4,4,4,4,12") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) + +(define_expand "movsi_const" + [(set (match_operand:SI 0 "arith_reg_operand" "=r") + (const:SI (sign_extend:SI + (truncate:HI + (ashiftrt:SI + (match_operand:DI 1 "immediate_operand" "s") + (const_int 16)))))) + (set (match_dup 0) + (ior:SI (ashift:SI (match_dup 0) (const_int 16)) + (zero_extend:SI + (truncate:HI + (const:SI + (sign_extend:SI + (truncate:HI (match_dup 1))))))))] + "TARGET_SHMEDIA && reload_completed + && MOVI_SHORI_BASE_OPERAND_P (operands[1])" + " +{ + if (GET_CODE (operands[1]) == LABEL_REF + && GET_CODE (XEXP (operands[1], 0)) == CODE_LABEL) + LABEL_NUSES (XEXP (operands[1], 0)) += 2; + else if (GOTOFF_P (operands[1])) + { + rtx unspec = XEXP (operands[1], 0); + + if (! UNSPEC_GOTOFF_P (unspec)) + { + unspec = XEXP (unspec, 0); + if (! UNSPEC_GOTOFF_P (unspec)) + abort (); + } + if (GET_CODE (XVECEXP (unspec , 0, 0)) == LABEL_REF + && (GET_CODE (XEXP (XVECEXP (unspec, 0, 0), 0)) == CODE_LABEL)) + LABEL_NUSES (XEXP (XVECEXP (unspec, 0, 0), 0)) += 2; + } +}") + +(define_expand "movsi_const_16bit" + [(set (match_operand:SI 0 "arith_reg_operand" "=r") + (const:SI (sign_extend:SI + (truncate:HI + (match_operand:DI 1 "immediate_operand" "s")))))] + "TARGET_SHMEDIA && flag_pic && reload_completed + && GET_CODE (operands[1]) == SYMBOL_REF" + "") (define_split - [(set (match_operand:SI 0 "arith_reg_operand" "") + [(set (match_operand:SI 0 "arith_reg_dest" "") (match_operand:SI 1 "immediate_operand" ""))] "TARGET_SHMEDIA && reload_completed && MOVI_SHORI_BASE_OPERAND_P (operands[1])" - [(set (subreg:DI (match_dup 0) 0) (match_dup 2))] + [(const_int 0)] " { - operands[2] = shallow_copy_rtx (operands[1]); - PUT_MODE (operands[2], DImode); + rtx insn = emit_insn (gen_movsi_const (operands[0], operands[1])); + + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], + REG_NOTES (insn)); + + DONE; }") (define_split @@ -3577,7 +4984,7 @@ } else if (TARGET_SHCOMPACT) { - operands[1] = function_symbol (\"__ic_invalidate\"); + operands[1] = function_symbol (NULL, \"__ic_invalidate\", SFUNC_STATIC); operands[1] = force_reg (Pmode, operands[1]); emit_insn (gen_ic_invalidate_line_compact (operands[0], operands[1])); DONE; @@ -3618,7 +5025,7 @@ ;; ??? could make arg 0 an offsettable memory operand to allow to save ;; an add in the code that calculates the address. (define_insn "ic_invalidate_line_media" - [(unspec_volatile [(match_operand 0 "register_operand" "r")] + [(unspec_volatile [(match_operand 0 "any_register_operand" "r")] UNSPEC_ICACHE)] "TARGET_SHMEDIA" "ocbwb %0,0\;synco\;icbi %0, 0\;synci" @@ -3645,7 +5052,8 @@ rtx sfun, tramp; tramp = force_reg (Pmode, operands[0]); - sfun = force_reg (Pmode, function_symbol (\"__init_trampoline\")); + sfun = force_reg (Pmode, function_symbol (NULL, \"__init_trampoline\", + SFUNC_STATIC)); emit_move_insn (gen_rtx_REG (SImode, R2_REG), operands[1]); emit_move_insn (gen_rtx_REG (SImode, R3_REG), operands[2]); @@ -3685,13 +5093,17 @@ (match_operand:QI 1 "general_movsrc_operand" "r,I16C16,m,rZ"))] "TARGET_SHMEDIA && (arith_reg_operand (operands[0], QImode) - || arith_reg_or_0_operand (operands[1], QImode))" + || extend_reg_or_0_operand (operands[1], QImode))" "@ add.l %1, r63, %0 movi %1, %0 ld%M1.ub %m1, %0 st%M0.b %m0, %N1" - [(set_attr "type" "arith_media,arith_media,load_media,store_media")]) + [(set_attr "type" "arith_media,arith_media,load_media,store_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") @@ -3749,7 +5161,11 @@ # ld%M1.w %m1, %0 st%M0.w %m0, %N1" - [(set_attr "type" "arith_media,arith_media,*,load_media,store_media")]) + [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_split [(set (match_operand:HI 0 "register_operand" "") @@ -3847,11 +5263,14 @@ FAIL; }") +;; The '?'s in the following constraints may not reflect the time taken +;; to perform the move. They are there to discourage the use of floating- +;; point registers for storing integer values. (define_insn "*movdi_media" [(set (match_operand:DI 0 "general_movdst_operand" - "=r,r,r,rl,m,f,m,f,r,f,*b,r,b") + "=r,r,r,rl,m,f?,m,f?,r,f?,*b,r,*b") (match_operand:DI 1 "general_movsrc_operand" - "r,I16C16,nCpgF,m,rlZ,m,f,rZ,f,f,r,*b,Csy"))] + "r,I16C16,nCpgF,m,rlZ,m,f?,rZ,f?,f?,r,*b,Csy"))] "TARGET_SHMEDIA_FPU && (register_operand (operands[0], DImode) || sh_register_operand (operands[1], DImode))" @@ -3873,7 +5292,7 @@ (set_attr "length" "4,4,16,4,4,4,4,4,4,4,4,4,*")]) (define_insn "*movdi_media_nofpu" - [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,b") + [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,rl,m,*b,r,*b"); (match_operand:DI 1 "general_movsrc_operand" "r,I16C16,nCpgF,m,rlZ,r,*b,Csy"))] "TARGET_SHMEDIA && (register_operand (operands[0], DImode) @@ -3890,8 +5309,16 @@ [(set_attr "type" "arith_media,arith_media,*,load_media,store_media,ptabs_media,gettr_media,pt_media") (set_attr "length" "4,4,16,4,4,4,4,*")]) +(define_insn "*movdi_media_I16" + [(set (match_operand:DI 0 "ext_dest_operand" "=r") + (match_operand:DI 1 "const_int_operand" "I16"))] + "TARGET_SHMEDIA && reload_completed" + "movi %1, %0" + [(set_attr "type" "arith_media") + (set_attr "length" "4")]) + (define_split - [(set (match_operand:DI 0 "arith_reg_operand" "") + [(set (match_operand:DI 0 "arith_reg_dest" "") (match_operand:DI 1 "immediate_operand" ""))] "TARGET_SHMEDIA && reload_completed && MOVI_SHORI_BASE_OPERAND_P (operands[1])" @@ -3985,7 +5412,7 @@ "") (define_split - [(set (match_operand:DI 0 "arith_reg_operand" "") + [(set (match_operand:DI 0 "ext_dest_operand" "") (match_operand:DI 1 "immediate_operand" ""))] "TARGET_SHMEDIA && reload_completed && GET_CODE (operands[1]) == CONST_INT @@ -4007,10 +5434,20 @@ /* Arithmetic shift right the word by 16 bits. */ high >>= 16; - sign = 1; - sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1); - high ^= sign; - high -= sign; + if (GET_CODE (operands[0]) == SUBREG + && GET_MODE (SUBREG_REG (operands[0])) == SImode) + { + high &= 0xffff; + high ^= 0x8000; + high -= 0x8000; + } + else + { + sign = 1; + sign <<= (HOST_BITS_PER_WIDE_INT - 16 - 1); + high ^= sign; + high -= sign; + } do { /* If we can't generate the constant with a two-insn movi / shori @@ -4084,7 +5521,7 @@ }") (define_split - [(set (match_operand:DI 0 "arith_reg_operand" "") + [(set (match_operand:DI 0 "ext_dest_operand" "") (match_operand:DI 1 "immediate_operand" ""))] "TARGET_SHMEDIA && reload_completed && GET_CODE (operands[1]) == CONST_DOUBLE" @@ -4124,18 +5561,28 @@ }") (define_insn "shori_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r,r") + [(set (match_operand:DI 0 "ext_dest_operand" "=r,r") (ior:DI (ashift:DI (match_operand:DI 1 "arith_reg_operand" "0,0") (const_int 16)) (zero_extend:DI (truncate:HI (match_operand:DI 2 "immediate_operand" "I16C16,nF")))))] - "TARGET_SHMEDIA" + "TARGET_SHMEDIA && (reload_completed || arith_reg_dest (operands[0], DImode))" "@ shori %u2, %0 #" [(set_attr "type" "arith_media,*")]) +(define_insn "*shori_media_si" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") + (const_int 16)) + (zero_extend:SI + (truncate:HI + (match_operand:SI 2 "immediate_operand" "I16C16")))))] + "TARGET_SHMEDIA" + "shori %u2, %0") + (define_expand "movdi" [(set (match_operand:DI 0 "general_movdst_operand" "") (match_operand:DI 1 "general_movsrc_operand" ""))] @@ -4174,7 +5621,7 @@ [(set_attr "type" "arith_media,*,load_media,store_media")]) (define_split - [(set (match_operand:DF 0 "arith_reg_operand" "") + [(set (match_operand:DF 0 "arith_reg_dest" "") (match_operand:DF 1 "immediate_operand" ""))] "TARGET_SHMEDIA && reload_completed" [(set (match_dup 3) (match_dup 2))] @@ -4607,7 +6054,8 @@ [(set (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "" "")) (clobber (match_operand 2 "register_operand" ""))] - "TARGET_SH1 && ! reload_in_progress && ! reload_completed" + "TARGET_SH1 && ! reload_in_progress && ! reload_completed + && ALLOW_INDEXED_ADDRESS" [(use (reg:SI R0_REG))] " { @@ -4634,7 +6082,8 @@ [(set (match_operand:SI 1 "" "") (match_operand:SI 0 "register_operand" "")) (clobber (match_operand 2 "register_operand" ""))] - "TARGET_SH1 && ! reload_in_progress && ! reload_completed" + "TARGET_SH1 && ! reload_in_progress && ! reload_completed + && ALLOW_INDEXED_ADDRESS" [(use (reg:SI R0_REG))] " { @@ -4873,7 +6322,11 @@ fst%M0.s %m0, %1 ld%M1.l %m1, %0 st%M0.l %m0, %N1" - [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media")]) + [(set_attr "type" "fmove_media,fload_media,fpconv_media,arith_media,*,fload_media,fstore_media,load_media,store_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_insn "movsf_media_nofpu" [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m") @@ -4886,10 +6339,14 @@ # ld%M1.l %m1, %0 st%M0.l %m0, %N1" - [(set_attr "type" "arith_media,*,load_media,store_media")]) + [(set_attr "type" "arith_media,*,load_media,store_media") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_split - [(set (match_operand:SF 0 "arith_reg_operand" "") + [(set (match_operand:SF 0 "arith_reg_dest" "") (match_operand:SF 1 "immediate_operand" ""))] "TARGET_SHMEDIA && reload_completed && ! FP_REGISTER_P (true_regnum (operands[0]))" @@ -5027,12 +6484,70 @@ "") (define_expand "reload_insi" - [(parallel [(set (match_operand:SF 0 "register_operand" "=y") - (match_operand:SF 1 "immediate_operand" "FQ")) + [(parallel [(set (match_operand:SI 0 "fpul_operand" "=y") + (match_operand:SI 1 "immediate_operand" "i")) (clobber (match_operand:SI 2 "register_operand" "=&z"))])] "TARGET_SH1" "") +(define_expand "ptabs" + [(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))] + "TARGET_SHMEDIA" + " +{ + if (!TARGET_PT_FIXED) + { + rtx eq = operands[1]; + + /* ??? For canonical RTL we really should remove any CONST from EQ + before wrapping it in the AND, and finally wrap the EQ into a + const if is constant. However, for reload we must expose the + input register or symbolic constant, and we can't have + different insn structures outside of the operands for different + alternatives of the same pattern. */ + eq = gen_rtx_EQ (SImode, gen_rtx_AND (Pmode, eq, GEN_INT (3)), + GEN_INT (3)); + operands[1] + = (gen_rtx_IF_THEN_ELSE + (PDImode, + eq, + gen_rtx_MEM (PDImode, operands[1]), + gen_rtx_fmt_e (TARGET_SHMEDIA32 ? SIGN_EXTEND : TRUNCATE, + PDImode, operands[1]))); + } +}") + +;; expanded by ptabs expander. +(define_insn "*extendsipdi_media" + [(set (match_operand:PDI 0 "target_reg_operand" "=b,b"); + (if_then_else:PDI (eq (and:SI (match_operand:SI 1 "target_operand" + "r,Csy") + (const_int 3)) + (const_int 3)) + (mem:PDI (match_dup 1)) + (sign_extend:PDI (match_dup 1))))] + "TARGET_SHMEDIA && !TARGET_PT_FIXED" + "@ + ptabs %1, %0 + pt %1, %0" + [(set_attr "type" "ptabs_media,pt_media") + (set_attr "length" "4,*")]) + +(define_insn "*truncdipdi_media" + [(set (match_operand:PDI 0 "target_reg_operand" "=b,b"); + (if_then_else:PDI (eq (and:DI (match_operand:DI 1 "target_operand" + "r,Csy") + (const_int 3)) + (const_int 3)) + (mem:PDI (match_dup 1)) + (truncate:PDI (match_dup 1))))] + "TARGET_SHMEDIA && !TARGET_PT_FIXED" + "@ + ptabs %1, %0 + pt %1, %0" + [(set_attr "type" "ptabs_media,pt_media") + (set_attr "length" "4,*")]) + (define_insn "*movsi_y" [(set (match_operand:SI 0 "register_operand" "=y,y") (match_operand:SI 1 "immediate_operand" "Qi,I08")) @@ -5109,8 +6624,8 @@ ;; jump around the unconditional jump because it was out of range. (define_insn "stuff_delay_slot" [(set (pc) - (unspec [(match_operand 0 "const_int_operand" "") (pc)] UNSPEC_BBR)) - (set (reg:SI T_REG) (match_operand 1 "const_int_operand" ""))] + (unspec [(match_operand:SI 0 "const_int_operand" "") (pc)] UNSPEC_BBR)) + (set (reg:SI T_REG) (match_operand:SI 1 "const_int_operand" ""))] "TARGET_SH1" "" [(set_attr "length" "0") @@ -5122,90 +6637,126 @@ [(set (pc) (if_then_else (eq (match_operand:DI 1 "arith_reg_operand" "r,r") (match_operand:DI 2 "arith_operand" "r,I06")) - (label_ref:DI (match_operand 0 "" "")) + (match_operand 0 "" "") (pc)))] "TARGET_SHMEDIA" - "") + "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") (define_insn "*beq_media_i" [(set (pc) (if_then_else (match_operator 3 "equality_comparison_operator" [(match_operand:DI 1 "arith_reg_operand" "r,r") (match_operand:DI 2 "arith_operand" "r,I06")]) - (match_operand:DI 0 "target_operand" "b,b") + (match_operand 0 "target_operand" "b,b") + (pc)))] + "TARGET_SHMEDIA" + "@ + b%o3%' %1, %2, %0%> + b%o3i%' %1, %2, %0%>" + [(set_attr "type" "cbranch_media")]) + +(define_insn "*beq_media_i32" + [(set (pc) + (if_then_else (match_operator 3 "equality_comparison_operator" + [(match_operand:SI 1 "arith_reg_operand" "r,r") + (match_operand:SI 2 "arith_operand" "r,I06")]) + (match_operand 0 "target_operand" "b,b") (pc)))] "TARGET_SHMEDIA" "@ - b%o3%' %1, %2, %0 - b%o3i%' %1, %2, %0" + b%o3%' %1, %2, %0%> + b%o3i%' %1, %2, %0%>" [(set_attr "type" "cbranch_media")]) (define_expand "bne_media" [(set (pc) (if_then_else (ne (match_operand:DI 1 "arith_reg_operand" "r,r") (match_operand:DI 2 "arith_operand" "r,I06")) - (label_ref:DI (match_operand 0 "" "")) + (match_operand 0 "" "") (pc)))] "TARGET_SHMEDIA" - "") + "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") (define_expand "bgt_media" [(set (pc) - (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "r") - (match_operand:DI 2 "arith_reg_or_0_operand" "r")) - (label_ref:DI (match_operand 0 "" "")) + (if_then_else (gt (match_operand:DI 1 "arith_reg_or_0_operand" "") + (match_operand:DI 2 "arith_reg_or_0_operand" "")) + (match_operand 0 "" "") (pc)))] "TARGET_SHMEDIA" - "") + "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") (define_expand "bge_media" [(set (pc) - (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "r") - (match_operand:DI 2 "arith_reg_or_0_operand" "r")) - (label_ref:DI (match_operand 0 "" "")) + (if_then_else (ge (match_operand:DI 1 "arith_reg_or_0_operand" "") + (match_operand:DI 2 "arith_reg_or_0_operand" "")) + (match_operand 0 "" "") (pc)))] "TARGET_SHMEDIA" - "") + "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") (define_expand "bgtu_media" [(set (pc) - (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "r") - (match_operand:DI 2 "arith_reg_or_0_operand" "r")) - (label_ref:DI (match_operand 0 "" "")) + (if_then_else (gtu (match_operand:DI 1 "arith_reg_or_0_operand" "") + (match_operand:DI 2 "arith_reg_or_0_operand" "")) + (match_operand 0 "" "") (pc)))] "TARGET_SHMEDIA" - "") + "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") (define_expand "bgeu_media" [(set (pc) - (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "r") - (match_operand:DI 2 "arith_reg_or_0_operand" "r")) - (label_ref:DI (match_operand 0 "" "")) + (if_then_else (geu (match_operand:DI 1 "arith_reg_or_0_operand" "") + (match_operand:DI 2 "arith_reg_or_0_operand" "")) + (match_operand 0 "" "") (pc)))] "TARGET_SHMEDIA" - "") + "operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]);") (define_insn "*bgt_media_i" [(set (pc) (if_then_else (match_operator 3 "greater_comparison_operator" [(match_operand:DI 1 "arith_reg_or_0_operand" "rN") (match_operand:DI 2 "arith_reg_or_0_operand" "rN")]) - (match_operand:DI 0 "target_operand" "b") + (match_operand 0 "target_operand" "b") + (pc)))] + "TARGET_SHMEDIA" + "b%o3%' %N1, %N2, %0%>" + [(set_attr "type" "cbranch_media")]) + +(define_insn "*bgt_media_i32" + [(set (pc) + (if_then_else (match_operator 3 "greater_comparison_operator" + [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") + (match_operand:SI 2 "arith_reg_or_0_operand" "rN")]) + (match_operand 0 "target_operand" "b") (pc)))] "TARGET_SHMEDIA" - "b%o3%' %N1, %N2, %0" + "b%o3%' %N1, %N2, %0%>" [(set_attr "type" "cbranch_media")]) -;; These are only needed to make invert_jump() happy. +;; These are only needed to make invert_jump() happy - otherwise, jump +;; optimization will be silently disabled. (define_insn "*blt_media_i" [(set (pc) (if_then_else (match_operator 3 "less_comparison_operator" [(match_operand:DI 1 "arith_reg_or_0_operand" "rN") (match_operand:DI 2 "arith_reg_or_0_operand" "rN")]) - (match_operand:DI 0 "target_operand" "b") + (match_operand 0 "target_operand" "b") (pc)))] "TARGET_SHMEDIA" - "b%o3%' %N2, %N1, %0" + "b%o3%' %N2, %N1, %0%>" + [(set_attr "type" "cbranch_media")]) + +(define_insn "*blt_media_i32" + [(set (pc) + (if_then_else (match_operator 3 "less_comparison_operator" + [(match_operand:SI 1 "arith_reg_or_0_operand" "rN") + (match_operand:SI 2 "arith_reg_or_0_operand" "rN")]) + (match_operand 0 "target_operand" "b") + (pc)))] + "TARGET_SHMEDIA" + "b%o3%' %N2, %N1, %0%>" [(set_attr "type" "cbranch_media")]) (define_expand "beq" @@ -5218,7 +6769,9 @@ { if (TARGET_SHMEDIA) { - if (GET_MODE (sh_compare_op0) != DImode) + enum machine_mode mode = GET_MODE (sh_compare_op0); + + if (mode != DImode && mode != SImode) { rtx tmp = gen_reg_rtx (DImode); @@ -5227,7 +6780,11 @@ DONE; } - sh_compare_op0 = force_reg (DImode, sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); + if (CONSTANT_P (sh_compare_op1) + && (GET_CODE (sh_compare_op1) != CONST_INT + || ! CONST_OK_FOR_I06 (INTVAL (sh_compare_op1)))) + sh_compare_op1 = force_reg (mode, sh_compare_op1); emit_jump_insn (gen_beq_media (operands[0], sh_compare_op0, sh_compare_op1)); DONE; @@ -5246,7 +6803,9 @@ { if (TARGET_SHMEDIA) { - if (GET_MODE (sh_compare_op0) != DImode) + enum machine_mode mode = GET_MODE (sh_compare_op0); + + if (mode != DImode && mode != SImode) { rtx tmp = gen_reg_rtx (DImode); @@ -5255,7 +6814,11 @@ DONE; } - sh_compare_op0 = force_reg (DImode, sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); + if (CONSTANT_P (sh_compare_op1) + && (GET_CODE (sh_compare_op1) != CONST_INT + || ! CONST_OK_FOR_I06 (INTVAL (sh_compare_op1)))) + sh_compare_op1 = force_reg (mode, sh_compare_op1); emit_jump_insn (gen_bne_media (operands[0], sh_compare_op0, sh_compare_op1)); DONE; @@ -5274,7 +6837,9 @@ { if (TARGET_SHMEDIA) { - if (GET_MODE (sh_compare_op0) != DImode) + enum machine_mode mode = GET_MODE (sh_compare_op0); + + if (mode != DImode && mode != SImode) { rtx tmp = gen_reg_rtx (DImode); @@ -5284,9 +6849,9 @@ } if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (DImode, sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (DImode, sh_compare_op1); + sh_compare_op1 = force_reg (mode, sh_compare_op1); emit_jump_insn (gen_bgt_media (operands[0], sh_compare_op0, sh_compare_op1)); DONE; @@ -5305,7 +6870,9 @@ { if (TARGET_SHMEDIA) { - if (GET_MODE (sh_compare_op0) != DImode) + enum machine_mode mode = GET_MODE (sh_compare_op0); + + if (mode != DImode && mode != SImode) { rtx tmp = gen_reg_rtx (DImode); @@ -5315,9 +6882,9 @@ } if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (DImode, sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (DImode, sh_compare_op1); + sh_compare_op1 = force_reg (mode, sh_compare_op1); emit_jump_insn (gen_bgt_media (operands[0], sh_compare_op1, sh_compare_op0)); DONE; @@ -5344,7 +6911,9 @@ { if (TARGET_SHMEDIA) { - if (GET_MODE (sh_compare_op0) != DImode) + enum machine_mode mode = GET_MODE (sh_compare_op0); + + if (mode != DImode && mode != SImode) { rtx tmp = gen_reg_rtx (DImode); @@ -5354,9 +6923,9 @@ } if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (DImode, sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (DImode, sh_compare_op1); + sh_compare_op1 = force_reg (mode, sh_compare_op1); emit_jump_insn (gen_bge_media (operands[0], sh_compare_op1, sh_compare_op0)); DONE; @@ -5385,7 +6954,9 @@ { if (TARGET_SHMEDIA) { - if (GET_MODE (sh_compare_op0) != DImode) + enum machine_mode mode = GET_MODE (sh_compare_op0); + + if (mode != DImode && mode != SImode) { rtx tmp = gen_reg_rtx (DImode); @@ -5395,9 +6966,9 @@ } if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (DImode, sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (DImode, sh_compare_op1); + sh_compare_op1 = force_reg (mode, sh_compare_op1); emit_jump_insn (gen_bge_media (operands[0], sh_compare_op0, sh_compare_op1)); DONE; @@ -5426,10 +6997,12 @@ { if (TARGET_SHMEDIA) { + enum machine_mode mode = GET_MODE (sh_compare_op0); + if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (DImode, sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (DImode, sh_compare_op1); + sh_compare_op1 = force_reg (mode, sh_compare_op1); emit_jump_insn (gen_bgtu_media (operands[0], sh_compare_op0, sh_compare_op1)); DONE; @@ -5448,10 +7021,12 @@ { if (TARGET_SHMEDIA) { + enum machine_mode mode = GET_MODE (sh_compare_op0); + if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (DImode, sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (DImode, sh_compare_op1); + sh_compare_op1 = force_reg (mode, sh_compare_op1); emit_jump_insn (gen_bgtu_media (operands[0], sh_compare_op1, sh_compare_op0)); DONE; @@ -5470,10 +7045,12 @@ { if (TARGET_SHMEDIA) { + enum machine_mode mode = GET_MODE (sh_compare_op0); + if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (DImode, sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (DImode, sh_compare_op1); + sh_compare_op1 = force_reg (mode, sh_compare_op1); emit_jump_insn (gen_bgeu_media (operands[0], sh_compare_op0, sh_compare_op1)); DONE; @@ -5492,10 +7069,12 @@ { if (TARGET_SHMEDIA) { + enum machine_mode mode = GET_MODE (sh_compare_op0); + if (sh_compare_op0 != const0_rtx) - sh_compare_op0 = force_reg (DImode, sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (DImode, sh_compare_op1); + sh_compare_op1 = force_reg (mode, sh_compare_op1); emit_jump_insn (gen_bgeu_media (operands[0], sh_compare_op1, sh_compare_op0)); DONE; @@ -5508,15 +7087,45 @@ [(set (match_dup 1) (unordered:DI (match_dup 2) (match_dup 3))) (set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) - (label_ref:DI (match_operand 0 "" "")) + (match_operand 0 "" "") (pc)))] "TARGET_SHMEDIA" " { + operands[0] = gen_rtx_LABEL_REF (Pmode, operands[0]); operands[1] = gen_reg_rtx (DImode); operands[2] = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); operands[3] = force_reg (GET_MODE (sh_compare_op1), sh_compare_op1); }") + +;; combiner splitter for test-and-branch on single bit in register. This +;; is endian dependent because the non-paradoxical subreg looks different +;; on big endian. +(define_split + [(set (pc) + (if_then_else + (match_operator 3 "equality_comparison_operator" + [(subreg:SI (zero_extract:DI (subreg:DI (match_operand:SI 1 + "extend_reg_operand" "") + 0) + (const_int 1) + (match_operand 2 + "const_int_operand" "")) 0) + (const_int 0)]) + (match_operand 0 "target_operand" "") + (pc))) + (clobber (match_operand:SI 4 "arith_reg_dest" ""))] + "TARGET_SHMEDIA && TARGET_LITTLE_ENDIAN" + [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 5))) + (set (pc) (if_then_else (match_dup 6) (match_dup 0) (pc)))] + + " +{ + operands[5] = GEN_INT (31 - INTVAL (operands[2])); + operands[6] = (GET_CODE (operands[3]) == EQ + ? gen_rtx_GE (VOIDmode, operands[4], const0_rtx) + : gen_rtx_GT (VOIDmode, const0_rtx, operands[4])); +}") ;; ------------------------------------------------------------------------ ;; Jump and linkage insns @@ -5552,9 +7161,9 @@ (define_insn "jump_media" [(set (pc) - (match_operand:DI 0 "target_operand" "b"))] + (match_operand 0 "target_operand" "b"))] "TARGET_SHMEDIA" - "blink %0, r63" + "blink %0, r63%>" [(set_attr "type" "jump_media")]) (define_expand "jump" @@ -5569,7 +7178,7 @@ { if (reload_in_progress || reload_completed) FAIL; - emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (DImode, + emit_jump_insn (gen_jump_media (gen_rtx_LABEL_REF (Pmode, operands[0]))); } DONE; @@ -5679,7 +7288,7 @@ (set_attr "needs_delay_slot" "yes")]) (define_insn "call_media" - [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "b")) + [(call (mem:DI (match_operand 0 "target_reg_operand" "b")) (match_operand 1 "" "")) (clobber (reg:DI PR_MEDIA_REG))] "TARGET_SHMEDIA" @@ -5786,7 +7395,7 @@ (define_insn "call_value_media" [(set (match_operand 0 "" "=rf") - (call (mem:DI (match_operand:DI 1 "target_reg_operand" "b")) + (call (mem:DI (match_operand 1 "target_reg_operand" "b")) (match_operand 2 "" ""))) (clobber (reg:DI PR_MEDIA_REG))] "TARGET_SHMEDIA" @@ -5804,48 +7413,7 @@ { if (TARGET_SHMEDIA) { - operands[0] = XEXP (operands[0], 0); - if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF) - { - if (! SYMBOL_REF_LOCAL_P (operands[0])) - { - rtx reg = gen_reg_rtx (Pmode); - - emit_insn (gen_symGOTPLT2reg (reg, operands[0])); - operands[0] = reg; - } - else - { - operands[0] = gen_sym2PIC (operands[0]); - PUT_MODE (operands[0], Pmode); - } - } - if (GET_MODE (operands[0]) == SImode) - { - if (GET_CODE (operands[0]) == REG) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); - else if (GET_CODE (operands[0]) == SUBREG) - { - operands[0] = SUBREG_REG (operands[0]); - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); - } - else if (TARGET_SHMEDIA64) - { - operands[0] = shallow_copy_rtx (operands[0]); - PUT_MODE (operands[0], DImode); - } - else - { - rtx reg = gen_reg_rtx (DImode); - - operands[0] = copy_to_mode_reg (SImode, operands[0]); - emit_insn (gen_extendsidi2 (reg, operands[0])); - operands[0] = reg; - } - } - if (! target_reg_operand (operands[0], DImode)) - operands[0] = copy_to_mode_reg (DImode, operands[0]); + operands[0] = shmedia_prepare_call_address (operands[0], 0); emit_call_insn (gen_call_media (operands[0], operands[1])); DONE; } @@ -5877,14 +7445,9 @@ run out of registers when adjusting fpscr for the call. */ emit_insn (gen_force_mode_for_call ()); - operands[0] = function_symbol (\"__GCC_shcompact_call_trampoline\"); - if (flag_pic) - { - rtx reg = gen_reg_rtx (Pmode); - - emit_insn (gen_symGOTPLT2reg (reg, operands[0])); - operands[0] = reg; - } + operands[0] + = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\", + SFUNC_GOT); operands[0] = force_reg (SImode, operands[0]); emit_move_insn (r0, func); @@ -6001,14 +7564,8 @@ run out of registers when adjusting fpscr for the call. */ emit_insn (gen_force_mode_for_call ()); - operands[0] = function_symbol (\"__GCC_shcompact_call_trampoline\"); - if (flag_pic) - { - rtx reg = gen_reg_rtx (Pmode); - - emit_insn (gen_symGOTPLT2reg (reg, operands[0])); - operands[0] = reg; - } + operands[0] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\", + SFUNC_GOT); operands[0] = force_reg (SImode, operands[0]); emit_move_insn (r0, func); @@ -6036,48 +7593,7 @@ { if (TARGET_SHMEDIA) { - operands[1] = XEXP (operands[1], 0); - if (flag_pic && GET_CODE (operands[1]) == SYMBOL_REF) - { - if (! SYMBOL_REF_LOCAL_P (operands[1])) - { - rtx reg = gen_reg_rtx (Pmode); - - emit_insn (gen_symGOTPLT2reg (reg, operands[1])); - operands[1] = reg; - } - else - { - operands[1] = gen_sym2PIC (operands[1]); - PUT_MODE (operands[1], Pmode); - } - } - if (GET_MODE (operands[1]) == SImode) - { - if (GET_CODE (operands[1]) == REG) - operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0); - else if (GET_CODE (operands[1]) == SUBREG) - { - operands[1] = SUBREG_REG (operands[1]); - if (GET_MODE (operands[1]) != DImode) - operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0); - } - else if (TARGET_SHMEDIA64) - { - operands[1] = shallow_copy_rtx (operands[1]); - PUT_MODE (operands[1], DImode); - } - else - { - rtx reg = gen_reg_rtx (DImode); - - operands[1] = copy_to_mode_reg (SImode, operands[1]); - emit_insn (gen_extendsidi2 (reg, operands[1])); - operands[1] = reg; - } - } - if (! target_reg_operand (operands[1], DImode)) - operands[1] = copy_to_mode_reg (DImode, operands[1]); + operands[1] = shmedia_prepare_call_address (operands[1], 0); emit_call_insn (gen_call_value_media (operands[0], operands[1], operands[2])); DONE; @@ -6110,14 +7626,9 @@ run out of registers when adjusting fpscr for the call. */ emit_insn (gen_force_mode_for_call ()); - operands[1] = function_symbol (\"__GCC_shcompact_call_trampoline\"); - if (flag_pic) - { - rtx reg = gen_reg_rtx (Pmode); - - emit_insn (gen_symGOTPLT2reg (reg, operands[1])); - operands[1] = reg; - } + operands[1] + = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\", + SFUNC_GOT); operands[1] = force_reg (SImode, operands[1]); emit_move_insn (r0, func); @@ -6185,6 +7696,22 @@ (const_string "single") (const_string "double"))) (set_attr "type" "jump_ind")]) +;; This uses an unspec to describe that the symbol_ref is very close. +(define_insn "sibcalli_thunk" + [(call (mem:SI (unspec:SI [(match_operand:SI 0 "symbol_ref_operand" "")] + UNSPEC_THUNK)) + (match_operand 1 "" "")) + (use (reg:PSI FPSCR_REG)) + (return)] + "TARGET_SH1" + "bra %O0" + [(set_attr "needs_delay_slot" "yes") + (set (attr "fp_mode") + (if_then_else (eq_attr "fpu_single" "yes") + (const_string "single") (const_string "double"))) + (set_attr "type" "jump") + (set_attr "length" "2")]) + (define_insn_and_split "sibcall_pcrel" [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "")) (match_operand 1 "" "")) @@ -6232,7 +7759,7 @@ (set_attr "type" "jump_ind")]) (define_insn "sibcall_media" - [(call (mem:DI (match_operand:DI 0 "target_reg_operand" "k")) + [(call (mem:DI (match_operand 0 "target_reg_operand" "k")) (match_operand 1 "" "")) (use (reg:SI PR_MEDIA_REG)) (return)] @@ -6252,42 +7779,7 @@ { if (TARGET_SHMEDIA) { - operands[0] = XEXP (operands[0], 0); - if (flag_pic && GET_CODE (operands[0]) == SYMBOL_REF) - { - if (! SYMBOL_REF_LOCAL_P (operands[0])) - { - rtx reg = gen_reg_rtx (Pmode); - - /* We must not use GOTPLT for sibcalls, because PIC_REG - must be restored before the PLT code gets to run. */ - emit_insn (gen_symGOT2reg (reg, operands[0])); - operands[0] = reg; - } - else - { - operands[0] = gen_sym2PIC (operands[0]); - PUT_MODE (operands[0], Pmode); - } - } - if (GET_MODE (operands[0]) == SImode) - { - if (GET_CODE (operands[0]) == REG) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); - else if (GET_CODE (operands[0]) == SUBREG) - { - operands[0] = SUBREG_REG (operands[0]); - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); - } - else - { - operands[0] = shallow_copy_rtx (operands[0]); - PUT_MODE (operands[0], DImode); - } - } - if (! target_reg_operand (operands[0], DImode)) - operands[0] = copy_to_mode_reg (DImode, operands[0]); + operands[0] = shmedia_prepare_call_address (operands[0], 1); emit_call_insn (gen_sibcall_media (operands[0], operands[1])); DONE; } @@ -6329,14 +7821,9 @@ run out of registers when adjusting fpscr for the call. */ emit_insn (gen_force_mode_for_call ()); - operands[0] = function_symbol (\"__GCC_shcompact_call_trampoline\"); - if (flag_pic) - { - rtx reg = gen_reg_rtx (Pmode); - - emit_insn (gen_symGOT2reg (reg, operands[0])); - operands[0] = reg; - } + operands[0] + = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\", + SFUNC_GOT); operands[0] = force_reg (SImode, operands[0]); /* We don't need a return trampoline, since the callee will @@ -6472,14 +7959,8 @@ run out of registers when adjusting fpscr for the call. */ emit_insn (gen_force_mode_for_call ()); - operands[1] = function_symbol (\"__GCC_shcompact_call_trampoline\"); - if (flag_pic) - { - rtx reg = gen_reg_rtx (Pmode); - - emit_insn (gen_symGOTPLT2reg (reg, operands[1])); - operands[1] = reg; - } + operands[1] = function_symbol (NULL, \"__GCC_shcompact_call_trampoline\", + SFUNC_GOT); operands[1] = force_reg (SImode, operands[1]); emit_move_insn (r0, func); @@ -6548,8 +8029,8 @@ "" " { - if (TARGET_SHMEDIA && GET_MODE (operands[0]) == SImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); + if (GET_MODE (operands[0]) != Pmode) + operands[0] = gen_rtx_SUBREG (Pmode, operands[0], 0); }") ;; The use of operand 1 / 2 helps us distinguish case table jumps @@ -6578,7 +8059,7 @@ (set_attr "type" "jump_ind")]) (define_insn "casesi_jump_media" - [(set (pc) (match_operand:DI 0 "target_reg_operand" "b")) + [(set (pc) (match_operand 0 "target_reg_operand" "b")) (use (label_ref (match_operand 1 "" "")))] "TARGET_SHMEDIA" "blink %0, r63" @@ -6620,7 +8101,7 @@ (define_insn "dect" [(set (reg:SI T_REG) - (eq:SI (match_operand:SI 0 "arith_reg_operand" "+r") (const_int 1))) + (eq:SI (match_operand:SI 0 "arith_reg_dest" "+r") (const_int 1))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] "TARGET_SH2" "dt %0" @@ -6664,40 +8145,35 @@ operands[0] = gen_rtx_REG (Pmode, PIC_REG); operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME); - if (TARGET_SH5) - operands[1] = gen_datalabel_ref (operands[1]); - if (TARGET_SHMEDIA) { - rtx tr = gen_rtx_REG (DImode, TR0_REG); - rtx dipic = operands[0]; + rtx tr = gen_rtx_REG (Pmode, TR0_REG); + rtx pic = operands[0]; rtx lab = PATTERN (gen_call_site ()); rtx insn, equiv; equiv = operands[1]; - operands[1] = gen_rtx_MINUS (DImode, + operands[1] = gen_rtx_MINUS (Pmode, operands[1], gen_rtx_CONST - (DImode, - gen_rtx_MINUS (DImode, - gen_rtx_CONST (DImode, + (Pmode, + gen_rtx_MINUS (Pmode, + gen_rtx_CONST (Pmode, lab), pc_rtx))); operands[1] = gen_sym2PIC (operands[1]); - PUT_MODE (operands[1], DImode); + PUT_MODE (operands[1], Pmode); - if (GET_MODE (dipic) != DImode) - dipic = gen_rtx_SUBREG (DImode, dipic, 0); - - if (TARGET_SHMEDIA64) - emit_insn (gen_movdi_const (dipic, operands[1])); + if (Pmode == SImode) + { + emit_insn (gen_movsi_const (pic, operands[1])); + emit_insn (gen_ptrel_si (tr, pic, lab)); + } else - emit_insn (gen_movdi_const_32bit (dipic, operands[1])); - - emit_insn (gen_ptrel (tr, dipic, lab)); - - if (GET_MODE (operands[0]) != GET_MODE (tr)) - tr = gen_lowpart (GET_MODE (operands[0]), tr); + { + emit_insn (gen_movdi_const (pic, operands[1])); + emit_insn (gen_ptrel_di (tr, pic, lab)); + } insn = emit_move_insn (operands[0], tr); @@ -6710,16 +8186,25 @@ ") (define_insn "*ptb" - [(set (match_operand:DI 0 "target_reg_operand" "=b") - (const:DI (unspec:DI [(match_operand:DI 1 "" "Csy")] + [(set (match_operand 0 "target_reg_operand" "=b") + (const (unspec [(match_operand 1 "" "Csy")] UNSPEC_DATALABEL)))] "TARGET_SHMEDIA && flag_pic && EXTRA_CONSTRAINT_Csy (operands[1])" "ptb/u datalabel %1, %0" - [(set_attr "type" "pt_media") + [(set_attr "type" "ptabs_media") (set_attr "length" "*")]) -(define_insn "ptrel" +(define_insn "ptrel_si" + [(set (match_operand:SI 0 "target_reg_operand" "=b") + (plus:SI (match_operand:SI 1 "register_operand" "r") + (pc))) + (match_operand:SI 2 "" "")] + "TARGET_SHMEDIA" + "%O2: ptrel/u %1, %0" + [(set_attr "type" "ptabs_media")]) + +(define_insn "ptrel_di" [(set (match_operand:DI 0 "target_reg_operand" "=b") (plus:DI (match_operand:DI 1 "register_operand" "r") (pc))) @@ -6774,13 +8259,20 @@ { rtx reg = operands[2]; - if (GET_MODE (reg) != DImode) - reg = gen_rtx_SUBREG (DImode, reg, 0); - - if (flag_pic > 1) - emit_insn (gen_movdi_const_32bit (reg, operands[1])); + if (Pmode == DImode) + { + if (flag_pic > 1) + emit_insn (gen_movdi_const_32bit (reg, operands[1])); + else + emit_insn (gen_movdi_const_16bit (reg, operands[1])); + } else - emit_insn (gen_movdi_const_16bit (reg, operands[1])); + { + if (flag_pic > 1) + emit_insn (gen_movsi_const (reg, operands[1])); + else + emit_insn (gen_movsi_const_16bit (reg, operands[1])); + } } else emit_move_insn (operands[2], operands[1]); @@ -6898,7 +8390,7 @@ (define_insn "tls_global_dynamic" [(set (match_operand:SI 0 "register_operand" "=&z") - (call (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] + (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_TLSGD)) (const_int 0))) (use (reg:PSI FPSCR_REG)) @@ -6927,7 +8419,7 @@ mov.l\\t1f,r4\\n\\ (define_insn "tls_local_dynamic" [(set (match_operand:SI 0 "register_operand" "=&z") - (call (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] + (call:SI (mem:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_TLSLDM)) (const_int 0))) (use (reg:PSI FPSCR_REG)) @@ -7050,9 +8542,10 @@ mov.l\\t1f,r0\\n\\ { rtx reg = gen_reg_rtx (DImode); rtx reg2 = gen_reg_rtx (DImode); - rtx reg3 = gen_reg_rtx (DImode); - rtx reg4 = gen_reg_rtx (DImode); - rtx reg5 = gen_reg_rtx (DImode); + rtx reg3 = gen_reg_rtx (Pmode); + rtx reg4 = gen_reg_rtx (Pmode); + rtx reg5 = gen_reg_rtx (Pmode); + rtx load; operands[0] = convert_modes (DImode, SImode, operands[0], 0); operands[1] = convert_modes (DImode, SImode, operands[1], 0); @@ -7063,9 +8556,18 @@ mov.l\\t1f,r0\\n\\ emit_jump_insn (gen_bgtu_media (operands[4], reg, operands[2])); emit_insn (gen_casesi_shift_media (reg2, reg, operands[3])); emit_move_insn (reg3, gen_datalabel_ref (gen_rtx_LABEL_REF - (DImode, operands[3]))); - emit_insn (gen_casesi_load_media (reg4, reg3, reg2, operands[3])); - emit_move_insn (reg5, gen_rtx_PLUS (DImode, reg3, reg4)); + (Pmode, operands[3]))); + /* Messy: can we subreg to clean this up? */ + if (Pmode == DImode) + load = gen_casesi_load_media (reg4, reg3, reg2, operands[3]); + else + load = gen_casesi_load_media (reg4, + gen_rtx_SUBREG (DImode, reg3, 0), + reg2, operands[3]); + PUT_MODE (SET_SRC (load), Pmode); + emit_insn (load); + /* ??? The following add could be eliminated if we used ptrel. */ + emit_move_insn (reg5, gen_rtx_PLUS (Pmode, reg3, reg4)); emit_jump_insn (gen_casesi_jump_media (reg5, operands[3])); emit_barrier (); DONE; @@ -7212,7 +8714,7 @@ mov.l\\t1f,r0\\n\\ [(set_attr "length" "8")]) (define_insn "casesi_shift_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") + [(set (match_operand:DI 0 "arith_reg_dest" "=r") (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r") (unspec:DI [(label_ref:DI (match_operand 2 "" ""))] UNSPEC_CASESI)))] @@ -7240,10 +8742,10 @@ mov.l\\t1f,r0\\n\\ [(set_attr "type" "arith_media")]) (define_insn "casesi_load_media" - [(set (match_operand:DI 0 "arith_reg_operand" "=r") - (mem:DI (unspec [(match_operand 1 "arith_reg_operand" "r") - (match_operand 2 "arith_reg_operand" "r") - (label_ref:DI (match_operand 3 "" ""))] 2)))] + [(set (match_operand 0 "any_arith_reg_dest" "=r") + (mem (unspec [(match_operand:DI 1 "arith_reg_operand" "r") + (match_operand:DI 2 "arith_reg_operand" "r") + (label_ref:DI (match_operand 3 "" ""))] UNSPEC_CASESI)))] "TARGET_SHMEDIA" "* { @@ -7307,13 +8809,8 @@ mov.l\\t1f,r0\\n\\ " { rtx reg = gen_rtx_REG (Pmode, R0_REG); - rtx sym = function_symbol (\"__GCC_shcompact_return_trampoline\"); - - if (flag_pic) - emit_insn (gen_symGOTPLT2reg (reg, sym)); - else - emit_move_insn (reg, sym); + function_symbol (reg, \"__GCC_shcompact_return_trampoline\", SFUNC_STATIC); emit_jump_insn (gen_shcompact_return_tramp_i ()); DONE; }") @@ -7327,7 +8824,7 @@ mov.l\\t1f,r0\\n\\ (set_attr "needs_delay_slot" "yes")]) (define_insn "return_media_i" - [(parallel [(return) (use (match_operand:DI 0 "target_reg_operand" "k"))])] + [(parallel [(return) (use (match_operand 0 "target_reg_operand" "k"))])] "TARGET_SHMEDIA && reload_completed" "blink %0, r63" [(set_attr "type" "jump_media")]) @@ -7353,15 +8850,15 @@ mov.l\\t1f,r0\\n\\ } if (tr_regno < 0) { - rtx r18 = gen_rtx_REG (DImode, PR_MEDIA_REG); + rtx r18 = gen_rtx_REG (Pmode, PR_MEDIA_REG); gcc_assert (call_really_used_regs[TR0_REG] && !fixed_regs[TR0_REG]); tr_regno = TR0_REG; - tr = gen_rtx_REG (DImode, tr_regno); + tr = gen_rtx_REG (Pmode, tr_regno); emit_move_insn (tr, r18); } else - tr = gen_rtx_REG (DImode, tr_regno); + tr = gen_rtx_REG (Pmode, tr_regno); emit_jump_insn (gen_return_media_i (tr)); DONE; @@ -7472,31 +8969,73 @@ mov.l\\t1f,r0\\n\\ ;; ------------------------------------------------------------------------ (define_insn "movt" - [(set (match_operand:SI 0 "arith_reg_operand" "=r") + [(set (match_operand:SI 0 "arith_reg_dest" "=r") (eq:SI (reg:SI T_REG) (const_int 1)))] "TARGET_SH1" "movt %0" [(set_attr "type" "arith")]) (define_expand "seq" - [(set (match_operand:SI 0 "arith_reg_operand" "") + [(set (match_operand:SI 0 "arith_reg_dest" "") (match_dup 1))] "" " { if (TARGET_SHMEDIA) { - if (GET_MODE (operands[0]) != DImode) - operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); if (sh_compare_op1 != const0_rtx) sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode ? GET_MODE (sh_compare_op0) : GET_MODE (sh_compare_op1), sh_compare_op1); + if (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4) + { + if (GET_MODE (operands[0]) != SImode) + operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0); + + switch (GET_MODE (sh_compare_op0)) + { + case SImode: + emit_insn (gen_cmpsieqsi_media (operands[0], + sh_compare_op0, sh_compare_op1)); + break; + + case DImode: + emit_insn (gen_cmpsieqdi_media (operands[0], + sh_compare_op0, sh_compare_op1)); + break; + + case SFmode: + if (! TARGET_SHMEDIA_FPU) + FAIL; + emit_insn (gen_cmpsieqsf_media (operands[0], + sh_compare_op0, sh_compare_op1)); + break; + + case DFmode: + if (! TARGET_SHMEDIA_FPU) + FAIL; + emit_insn (gen_cmpsieqdf_media (operands[0], + sh_compare_op0, sh_compare_op1)); + break; + + default: + FAIL; + } + DONE; + } + + if (GET_MODE (operands[0]) != DImode) + operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); switch (GET_MODE (sh_compare_op0)) { + case SImode: + emit_insn (gen_cmpeqsi_media (operands[0], + sh_compare_op0, sh_compare_op1)); + break; + case DImode: emit_insn (gen_cmpeqdi_media (operands[0], sh_compare_op0, sh_compare_op1)); @@ -7547,6 +9086,11 @@ mov.l\\t1f,r0\\n\\ switch (GET_MODE (sh_compare_op0)) { + case SImode: + emit_insn (gen_cmpgtsi_media (operands[0], + sh_compare_op1, sh_compare_op0)); + break; + case DImode: emit_insn (gen_cmpgtdi_media (operands[0], sh_compare_op1, sh_compare_op0)); @@ -7596,6 +9140,16 @@ mov.l\\t1f,r0\\n\\ switch (GET_MODE (sh_compare_op0)) { + case SImode: + { + tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); + + emit_insn (gen_cmpgtsi_media (tmp, + sh_compare_op0, sh_compare_op1)); + emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx)); + break; + } + case DImode: { tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); @@ -7651,6 +9205,11 @@ mov.l\\t1f,r0\\n\\ switch (GET_MODE (sh_compare_op0)) { + case SImode: + emit_insn (gen_cmpgtsi_media (operands[0], + sh_compare_op0, sh_compare_op1)); + break; + case DImode: emit_insn (gen_cmpgtdi_media (operands[0], sh_compare_op0, sh_compare_op1)); @@ -7688,17 +9247,28 @@ mov.l\\t1f,r0\\n\\ { if (TARGET_SHMEDIA) { + enum machine_mode mode = GET_MODE (sh_compare_op0); + + if ((mode) == VOIDmode) + mode = GET_MODE (sh_compare_op1); if (GET_MODE (operands[0]) != DImode) operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); - sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); + sh_compare_op0 = force_reg (mode, sh_compare_op0); if (sh_compare_op1 != const0_rtx) - sh_compare_op1 = force_reg (GET_MODE (sh_compare_op1) == VOIDmode - ? GET_MODE (sh_compare_op0) - : GET_MODE (sh_compare_op1), - sh_compare_op1); + sh_compare_op1 = force_reg (mode, sh_compare_op1); - switch (GET_MODE (sh_compare_op0)) + switch (mode) { + case SImode: + { + rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); + + emit_insn (gen_cmpgtsi_media (tmp, + sh_compare_op1, sh_compare_op0)); + emit_insn (gen_cmpeqdi_media (operands[0], tmp, const0_rtx)); + break; + } + case DImode: { rtx tmp = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode); @@ -7890,7 +9460,9 @@ mov.l\\t1f,r0\\n\\ if (GET_MODE (operands[0]) != DImode) operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0); - if (! TARGET_SHMEDIA_FPU && GET_MODE (sh_compare_op0) != DImode) + if (! TARGET_SHMEDIA_FPU + && GET_MODE (sh_compare_op0) != DImode + && GET_MODE (sh_compare_op0) != SImode) FAIL; sh_compare_op0 = force_reg (GET_MODE (sh_compare_op0), sh_compare_op0); @@ -7927,6 +9499,10 @@ mov.l\\t1f,r0\\n\\ }") ;; Use the same trick for FP sle / sge + +;; Apart from the constant use and the T setting, this is like movt, +;; except that it uses the logically negated value of T, i.e. +;; operand[0] := T ? 0 : 1. (define_expand "movnegt" [(set (match_dup 2) (const_int -1)) (parallel [(set (match_operand 0 "" "") @@ -7943,7 +9519,7 @@ mov.l\\t1f,r0\\n\\ ;; mov/neg for sne. (define_split - [(set (match_operand:SI 0 "arith_reg_operand" "") + [(set (match_operand:SI 0 "arith_reg_dest" "") (plus:SI (reg:SI T_REG) (const_int -1)))] "TARGET_SH1" @@ -8384,9 +9960,9 @@ mov.l\\t1f,r0\\n\\ [(set_attr "type" "fparith_media")]) (define_insn "addsf3_i" - [(set (match_operand:SF 0 "arith_reg_operand" "=f") - (plus:SF (match_operand:SF 1 "arith_reg_operand" "%0") - (match_operand:SF 2 "arith_reg_operand" "f"))) + [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") + (plus:SF (match_operand:SF 1 "fp_arith_reg_operand" "%0") + (match_operand:SF 2 "fp_arith_reg_operand" "f"))) (use (match_operand:PSI 3 "fpscr_operand" "c"))] "TARGET_SH2E" "fadd %2,%0" @@ -8471,7 +10047,7 @@ mov.l\\t1f,r0\\n\\ "fmul %2,%0" [(set_attr "type" "fp")]) -(define_insn "*mac_media" +(define_insn "mac_media" [(set (match_operand:SF 0 "fp_arith_reg_operand" "=f") (plus:SF (mult:SF (match_operand:SF 1 "fp_arith_reg_operand" "%f") (match_operand:SF 2 "fp_arith_reg_operand" "f")) @@ -8514,7 +10090,7 @@ mov.l\\t1f,r0\\n\\ [(set_attr "type" "fdiv_media")]) (define_insn "divsf3_i" - [(set (match_operand:SF 0 "arith_reg_operand" "=f") + [(set (match_operand:SF 0 "arith_reg_dest" "=f") (div:SF (match_operand:SF 1 "arith_reg_operand" "0") (match_operand:SF 2 "arith_reg_operand" "f"))) (use (match_operand:PSI 3 "fpscr_operand" "c"))] @@ -8567,7 +10143,7 @@ mov.l\\t1f,r0\\n\\ [(set_attr "type" "fp")]) (define_insn "fix_truncsfdi2" - [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f") + [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f") (fix:DI (match_operand:SF 1 "fp_arith_reg_operand" "f")))] "TARGET_SHMEDIA_FPU" "ftrc.sq %1, %0" @@ -8698,6 +10274,14 @@ mov.l\\t1f,r0\\n\\ "fcmpeq.s %1, %2, %0" [(set_attr "type" "fcmp_media")]) +(define_insn "cmpsieqsf_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (eq:SI (match_operand:SF 1 "fp_arith_reg_operand" "f") + (match_operand:SF 2 "fp_arith_reg_operand" "f")))] + "TARGET_SHMEDIA_FPU" + "fcmpeq.s %1, %2, %0" + [(set_attr "type" "fcmp_media")]) + (define_insn "cmpgtsf_media" [(set (match_operand:DI 0 "register_operand" "=r") (gt:DI (match_operand:SF 1 "fp_arith_reg_operand" "f") @@ -9098,7 +10682,7 @@ mov.l\\t1f,r0\\n\\ (set_attr "fp_mode" "double")]) (define_insn "fix_truncdfdi2" - [(set (match_operand:DI 0 "fp_arith_reg_operand" "=f") + [(set (match_operand:DI 0 "fp_arith_reg_dest" "=f") (fix:DI (match_operand:DF 1 "fp_arith_reg_operand" "f")))] "TARGET_SHMEDIA_FPU" "ftrc.dq %1, %0" @@ -9196,6 +10780,14 @@ mov.l\\t1f,r0\\n\\ "fcmpeq.d %1,%2,%0" [(set_attr "type" "fcmp_media")]) +(define_insn "cmpsieqdf_media" + [(set (match_operand:SI 0 "register_operand" "=r") + (eq:SI (match_operand:DF 1 "fp_arith_reg_operand" "f") + (match_operand:DF 2 "fp_arith_reg_operand" "f")))] + "TARGET_SHMEDIA_FPU" + "fcmpeq.d %1,%2,%0" + [(set_attr "type" "fcmp_media")]) + (define_insn "cmpgtdf_media" [(set (match_operand:DI 0 "register_operand" "=r") (gt:DI (match_operand:DF 1 "fp_arith_reg_operand" "f") @@ -9253,8 +10845,8 @@ mov.l\\t1f,r0\\n\\ [(set_attr "type" "fmove_media")]) (define_insn "negdf2_i" - [(set (match_operand:DF 0 "arith_reg_operand" "=f") - (neg:DF (match_operand:DF 1 "arith_reg_operand" "0"))) + [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") + (neg:DF (match_operand:DF 1 "fp_arith_reg_operand" "0"))) (use (match_operand:PSI 2 "fpscr_operand" "c"))] "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" "fneg %0" @@ -9282,8 +10874,8 @@ mov.l\\t1f,r0\\n\\ [(set_attr "type" "dfdiv_media")]) (define_insn "sqrtdf2_i" - [(set (match_operand:DF 0 "arith_reg_operand" "=f") - (sqrt:DF (match_operand:DF 1 "arith_reg_operand" "0"))) + [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") + (sqrt:DF (match_operand:DF 1 "fp_arith_reg_operand" "0"))) (use (match_operand:PSI 2 "fpscr_operand" "c"))] "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" "fsqrt %0" @@ -9311,8 +10903,8 @@ mov.l\\t1f,r0\\n\\ [(set_attr "type" "fmove_media")]) (define_insn "absdf2_i" - [(set (match_operand:DF 0 "arith_reg_operand" "=f") - (abs:DF (match_operand:DF 1 "arith_reg_operand" "0"))) + [(set (match_operand:DF 0 "fp_arith_reg_operand" "=f") + (abs:DF (match_operand:DF 1 "fp_arith_reg_operand" "0"))) (use (match_operand:PSI 2 "fpscr_operand" "c"))] "(TARGET_SH4 || TARGET_SH2A_DOUBLE)" "fabs %0" @@ -9753,8 +11345,7 @@ mov.l\\t1f,r0\\n\\ (match_operand 1 "sh_const_vec" ""))] "TARGET_SHMEDIA && reload_completed && GET_MODE (operands[0]) == GET_MODE (operands[1]) - && sh_vector_mode_supported_p (GET_MODE (operands[0])) - && operands[1] != CONST0_RTX (GET_MODE (operands[1]))" + && sh_vector_mode_supported_p (GET_MODE (operands[0]))" [(set (match_dup 0) (match_dup 1))] " { @@ -9780,13 +11371,17 @@ mov.l\\t1f,r0\\n\\ && (register_operand (operands[0], V2HImode) || sh_register_operand (operands[1], V2HImode))" "@ - addz.l %1, r63, %0 + add.l %1, r63, %0 movi %1, %0 # ld%M1.l %m1, %0 st%M0.l %m0, %N1" [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") - (set_attr "length" "4,4,16,4,4")]) + (set_attr "length" "4,4,16,4,4") + (set (attr "highpart") + (cond [(ne (symbol_ref "sh_contains_memref_p (insn)") (const_int 0)) + (const_string "user")] + (const_string "ignore")))]) (define_expand "movv4hi" [(set (match_operand:V4HI 0 "general_movdst_operand" "") @@ -9807,7 +11402,8 @@ mov.l\\t1f,r0\\n\\ ld%M1.q %m1, %0 st%M0.q %m0, %N1" [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") - (set_attr "length" "4,4,16,4,4")]) + (set_attr "length" "4,4,16,4,4") + (set_attr "highpart" "depend")]) (define_expand "movv2si" [(set (match_operand:V2SI 0 "general_movdst_operand" "") @@ -9828,7 +11424,8 @@ mov.l\\t1f,r0\\n\\ ld%M1.q %m1, %0 st%M0.q %m0, %N1" [(set_attr "type" "arith_media,arith_media,*,load_media,store_media") - (set_attr "length" "4,4,16,4,4")]) + (set_attr "length" "4,4,16,4,4") + (set_attr "highpart" "depend")]) ;; Multimedia Intrinsics @@ -9837,14 +11434,16 @@ mov.l\\t1f,r0\\n\\ (abs:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "mabs.l %1, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "absv4hi2" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") (abs:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "mabs.w %1, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "addv2si3" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -9852,7 +11451,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V2SI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "madd.l %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) (define_insn "addv4hi3" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -9860,7 +11460,30 @@ mov.l\\t1f,r0\\n\\ (match_operand:V4HI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "madd.w %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) + +(define_insn_and_split "addv2hi3" + [(set (match_operand:V2HI 0 "arith_reg_dest" "=r") + (plus:V2HI (match_operand:V2HI 1 "extend_reg_operand" "%r") + (match_operand:V2HI 2 "extend_reg_operand" "r")))] + "TARGET_SHMEDIA" + "#" + "TARGET_SHMEDIA" + [(const_int 0)] + " +{ + rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0); + rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0); + rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0); + rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0); + rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0); + + emit_insn (gen_addv4hi3 (v4hi_dst, src0, src1)); + emit_insn (gen_truncdisi2 (si_dst, di_dst)); + DONE; +}" + [(set_attr "highpart" "must_split")]) (define_insn "ssaddv2si3" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -9868,7 +11491,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V2SI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "madds.l %1, %2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "usaddv8qi3" [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") @@ -9876,7 +11500,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V8QI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "madds.ub %1, %2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "ssaddv4hi3" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -9884,7 +11509,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V4HI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "madds.w %1, %2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "negcmpeqv8qi" [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") @@ -9892,7 +11518,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))] "TARGET_SHMEDIA" "mcmpeq.b %N1, %N2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "negcmpeqv2si" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -9900,7 +11527,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] "TARGET_SHMEDIA" "mcmpeq.l %N1, %N2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "negcmpeqv4hi" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -9908,7 +11536,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] "TARGET_SHMEDIA" "mcmpeq.w %N1, %N2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "negcmpgtuv8qi" [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") @@ -9916,7 +11545,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V8QI 2 "arith_reg_or_0_operand" "rZ"))))] "TARGET_SHMEDIA" "mcmpgt.ub %N1, %N2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "negcmpgtv2si" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -9924,7 +11554,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V2SI 2 "arith_reg_or_0_operand" "rZ"))))] "TARGET_SHMEDIA" "mcmpgt.l %N1, %N2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "negcmpgtv4hi" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -9932,7 +11563,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V4HI 2 "arith_reg_or_0_operand" "rZ"))))] "TARGET_SHMEDIA" "mcmpgt.w %N1, %N2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "mcmv" [(set (match_operand:DI 0 "arith_reg_dest" "=r") @@ -9942,7 +11574,8 @@ mov.l\\t1f,r0\\n\\ (not:DI (match_dup 2)))))] "TARGET_SHMEDIA" "mcmv %N1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) (define_insn "mcnvs_lw" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -10104,6 +11737,8 @@ mov.l\\t1f,r0\\n\\ DONE; }") +;; This could be highpart ignore if it only had inputs 2 or 3, but input 1 +;; is depend (define_insn "mmacfx_wl_i" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") (ss_plus:V2SI @@ -10117,7 +11752,8 @@ mov.l\\t1f,r0\\n\\ (const_int 1)))))] "TARGET_SHMEDIA" "mmacfx.wl %2, %3, %0" - [(set_attr "type" "mac_media")]) + [(set_attr "type" "mac_media") + (set_attr "highpart" "depend")]) (define_expand "mmacnfx_wl" [(match_operand:V2SI 0 "arith_reg_dest" "") @@ -10145,7 +11781,8 @@ mov.l\\t1f,r0\\n\\ (const_int 1)))))] "TARGET_SHMEDIA" "mmacnfx.wl %2, %3, %0" - [(set_attr "type" "mac_media")]) + [(set_attr "type" "mac_media") + (set_attr "highpart" "depend")]) (define_insn "mulv2si3" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -10153,7 +11790,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V2SI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "mmul.l %1, %2, %0" - [(set_attr "type" "d2mpy_media")]) + [(set_attr "type" "d2mpy_media") + (set_attr "highpart" "depend")]) (define_insn "mulv4hi3" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -10161,7 +11799,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V4HI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "mmul.w %1, %2, %0" - [(set_attr "type" "dmpy_media")]) + [(set_attr "type" "dmpy_media") + (set_attr "highpart" "depend")]) (define_insn "mmulfx_l" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -10173,7 +11812,8 @@ mov.l\\t1f,r0\\n\\ (const_int 31))))] "TARGET_SHMEDIA" "mmulfx.l %1, %2, %0" - [(set_attr "type" "d2mpy_media")]) + [(set_attr "type" "d2mpy_media") + (set_attr "highpart" "depend")]) (define_insn "mmulfx_w" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -10185,7 +11825,8 @@ mov.l\\t1f,r0\\n\\ (const_int 15))))] "TARGET_SHMEDIA" "mmulfx.w %1, %2, %0" - [(set_attr "type" "dmpy_media")]) + [(set_attr "type" "dmpy_media") + (set_attr "highpart" "depend")]) (define_insn "mmulfxrp_w" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -10199,7 +11840,9 @@ mov.l\\t1f,r0\\n\\ (const_int 15))))] "TARGET_SHMEDIA" "mmulfxrp.w %1, %2, %0" - [(set_attr "type" "dmpy_media")]) + [(set_attr "type" "dmpy_media") + (set_attr "highpart" "depend")]) + (define_expand "mmulhi_wl" [(match_operand:V2SI 0 "arith_reg_dest" "") @@ -10236,7 +11879,10 @@ mov.l\\t1f,r0\\n\\ "* return (TARGET_LITTLE_ENDIAN ? \"mmulhi.wl %1, %2, %0\" : \"mmullo.wl %1, %2, %0\");" - [(set_attr "type" "dmpy_media")]) + [(set_attr "type" "dmpy_media") + (set (attr "highpart") + (cond [(eq_attr "endian" "big") (const_string "ignore")] + (const_string "user")))]) (define_insn "mmul01_wl" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -10249,7 +11895,11 @@ mov.l\\t1f,r0\\n\\ "* return (TARGET_LITTLE_ENDIAN ? \"mmullo.wl %1, %2, %0\" : \"mmulhi.wl %1, %2, %0\");" - [(set_attr "type" "dmpy_media")]) + [(set_attr "type" "dmpy_media") + (set (attr "highpart") + (cond [(eq_attr "endian" "little") (const_string "ignore")] + (const_string "user")))]) + (define_expand "mmulsum_wq" [(match_operand:DI 0 "arith_reg_dest" "") @@ -10338,7 +11988,8 @@ mov.l\\t1f,r0\\n\\ "trunc_hi_operand" "r"))))] "TARGET_SHMEDIA" "mperm.w %1, r63, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_expand "msad_ubq" [(match_operand:DI 0 "arith_reg_dest" "") @@ -10405,7 +12056,8 @@ mov.l\\t1f,r0\\n\\ (const_int 31)))))] "TARGET_SHMEDIA" "mshalds.l %1, %2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "mshalds_w" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -10416,7 +12068,8 @@ mov.l\\t1f,r0\\n\\ (const_int 15)))))] "TARGET_SHMEDIA" "mshalds.w %1, %2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "ashrv2si3" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -10424,7 +12077,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:DI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "mshard.l %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) (define_insn "ashrv4hi3" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -10432,7 +12086,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:DI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "mshard.w %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) (define_insn "mshards_q" [(set (match_operand:HI 0 "arith_reg_dest" "=r") @@ -10479,7 +12134,10 @@ mov.l\\t1f,r0\\n\\ "* return (TARGET_LITTLE_ENDIAN ? \"mshfhi.b %N1, %N2, %0\" : \"mshflo.b %N1, %N2, %0\");" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set (attr "highpart") + (cond [(eq_attr "endian" "big") (const_string "ignore")] + (const_string "user")))]) (define_insn "mshf0_b" [(set @@ -10493,7 +12151,10 @@ mov.l\\t1f,r0\\n\\ "* return (TARGET_LITTLE_ENDIAN ? \"mshflo.b %N1, %N2, %0\" : \"mshfhi.b %N1, %N2, %0\");" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set (attr "highpart") + (cond [(eq_attr "endian" "little") (const_string "ignore")] + (const_string "user")))]) (define_expand "mshfhi_l" [(match_operand:V2SI 0 "arith_reg_dest" "") @@ -10529,7 +12190,10 @@ mov.l\\t1f,r0\\n\\ "* return (TARGET_LITTLE_ENDIAN ? \"mshfhi.l %N1, %N2, %0\" : \"mshflo.l %N1, %N2, %0\");" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set (attr "highpart") + (cond [(eq_attr "endian" "big") (const_string "ignore")] + (const_string "user")))]) (define_insn "mshf0_l" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -10541,7 +12205,10 @@ mov.l\\t1f,r0\\n\\ "* return (TARGET_LITTLE_ENDIAN ? \"mshflo.l %N1, %N2, %0\" : \"mshfhi.l %N1, %N2, %0\");" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set (attr "highpart") + (cond [(eq_attr "endian" "little") (const_string "ignore")] + (const_string "user")))]) (define_expand "mshfhi_w" [(match_operand:V4HI 0 "arith_reg_dest" "") @@ -10577,7 +12244,10 @@ mov.l\\t1f,r0\\n\\ "* return (TARGET_LITTLE_ENDIAN ? \"mshfhi.w %N1, %N2, %0\" : \"mshflo.w %N1, %N2, %0\");" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set (attr "highpart") + (cond [(eq_attr "endian" "big") (const_string "ignore")] + (const_string "user")))]) (define_insn "mshf0_w" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -10589,7 +12259,10 @@ mov.l\\t1f,r0\\n\\ "* return (TARGET_LITTLE_ENDIAN ? \"mshflo.w %N1, %N2, %0\" : \"mshfhi.w %N1, %N2, %0\");" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set (attr "highpart") + (cond [(eq_attr "endian" "little") (const_string "ignore")] + (const_string "user")))]) (define_insn "mshflo_w_x" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -10599,7 +12272,8 @@ mov.l\\t1f,r0\\n\\ (parallel [(const_int 2) (const_int 0) (const_int 3) (const_int 1)])))] "TARGET_SHMEDIA" "mshflo.w %N1, %N2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) /* These are useful to expand ANDs and as combiner patterns. */ (define_insn_and_split "mshfhi_l_di" @@ -10663,7 +12337,8 @@ mov.l\\t1f,r0\\n\\ "TARGET_SHMEDIA" "mshflo.l %N1, %N2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_insn "*mshflo_l_di_rev" [(set (match_operand:DI 0 "arith_reg_dest" "=r") @@ -10674,7 +12349,8 @@ mov.l\\t1f,r0\\n\\ "TARGET_SHMEDIA" "mshflo.l %N2, %N1, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) ;; Combiner pattern for trampoline initialization. (define_insn_and_split "*double_shori" @@ -10696,7 +12372,8 @@ mov.l\\t1f,r0\\n\\ emit_insn (gen_shori_media (operands[0], operands[0], gen_int_mode (v, HImode))); DONE; -}") +}" + [(set_attr "highpart" "ignore")]) (define_insn "*mshflo_l_di_x" @@ -10708,7 +12385,8 @@ mov.l\\t1f,r0\\n\\ "TARGET_SHMEDIA" "mshflo.l %N1, %N2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_insn_and_split "concat_v2sf" [(set (match_operand:V2SF 0 "register_operand" "=r,f,f?") @@ -10730,7 +12408,8 @@ mov.l\\t1f,r0\\n\\ operands[3] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0); operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 4); }" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_insn "*mshflo_l_di_x_rev" [(set (match_operand:DI 0 "arith_reg_dest" "=r") @@ -10740,39 +12419,67 @@ mov.l\\t1f,r0\\n\\ "TARGET_SHMEDIA" "mshflo.l %N2, %N1, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "ignore")]) (define_insn "ashlv2si3" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") (ashift:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") - (match_operand:DI 2 "arith_reg_operand" "r")))] + (match_operand:DI 2 "shift_count_reg_operand" "r")))] "TARGET_SHMEDIA" "mshlld.l %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) + +(define_split + [(set (match_operand 0 "any_register_operand" "") + (match_operator 3 "shift_operator" + [(match_operand 1 "any_register_operand" "") + (match_operand 2 "shift_count_reg_operand" "")]))] + "TARGET_SHMEDIA && ! register_operand (operands[2], VOIDmode)" + [(set (match_dup 0) (match_dup 3))] + " +{ + rtx count = operands[2]; + enum machine_mode outer_mode = GET_MODE (operands[2]), inner_mode; + + while (GET_CODE (count) == ZERO_EXTEND || GET_CODE (count) == SIGN_EXTEND + || (GET_CODE (count) == SUBREG && SUBREG_BYTE (count) == 0) + || GET_CODE (count) == TRUNCATE) + count = XEXP (count, 0); + inner_mode = GET_MODE (count); + count = simplify_gen_subreg (outer_mode, count, inner_mode, + subreg_lowpart_offset (outer_mode, inner_mode)); + operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), GET_MODE (operands[3]), + operands[1], count); +}") (define_insn "ashlv4hi3" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") (ashift:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") - (match_operand:DI 2 "arith_reg_operand" "r")))] + (match_operand:DI 2 "shift_count_reg_operand" "r")))] "TARGET_SHMEDIA" "mshlld.w %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) (define_insn "lshrv2si3" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") (lshiftrt:V2SI (match_operand:V2SI 1 "arith_reg_operand" "r") - (match_operand:DI 2 "arith_reg_operand" "r")))] + (match_operand:DI 2 "shift_count_reg_operand" "r")))] "TARGET_SHMEDIA" "mshlrd.l %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) (define_insn "lshrv4hi3" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") (lshiftrt:V4HI (match_operand:V4HI 1 "arith_reg_operand" "r") - (match_operand:DI 2 "arith_reg_operand" "r")))] + (match_operand:DI 2 "shift_count_reg_operand" "r")))] "TARGET_SHMEDIA" "mshlrd.w %1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) (define_insn "subv2si3" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -10780,7 +12487,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V2SI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "msub.l %N1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) (define_insn "subv4hi3" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -10788,7 +12496,30 @@ mov.l\\t1f,r0\\n\\ (match_operand:V4HI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "msub.w %N1, %2, %0" - [(set_attr "type" "arith_media")]) + [(set_attr "type" "arith_media") + (set_attr "highpart" "depend")]) + +(define_insn_and_split "subv2hi3" + [(set (match_operand:V2HI 0 "arith_reg_dest" "=r") + (minus:V2HI (match_operand:V2HI 1 "arith_reg_or_0_operand" "rZ") + (match_operand:V2HI 2 "arith_reg_operand" "r")))] + "TARGET_SHMEDIA" + "#" + "TARGET_SHMEDIA" + [(const_int 0)] + " +{ + rtx src0 = simplify_gen_subreg (V4HImode, operands[1], V2HImode, 0); + rtx src1 = simplify_gen_subreg (V4HImode, operands[2], V2HImode, 0); + rtx v4hi_dst = simplify_gen_subreg (V4HImode, operands[0], V2HImode, 0); + rtx di_dst = simplify_gen_subreg (DImode, operands[0], V2HImode, 0); + rtx si_dst = simplify_gen_subreg (SImode, operands[0], V2HImode, 0); + + emit_insn (gen_subv4hi3 (v4hi_dst, src0, src1)); + emit_insn (gen_truncdisi2 (si_dst, di_dst)); + DONE; +}" + [(set_attr "highpart" "must_split")]) (define_insn "sssubv2si3" [(set (match_operand:V2SI 0 "arith_reg_dest" "=r") @@ -10796,15 +12527,17 @@ mov.l\\t1f,r0\\n\\ (match_operand:V2SI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "msubs.l %N1, %2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "ussubv8qi3" [(set (match_operand:V8QI 0 "arith_reg_dest" "=r") - (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_operand" "r") + (us_minus:V8QI (match_operand:V8QI 1 "arith_reg_or_0_operand" "rZ") (match_operand:V8QI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" - "msubs.ub %1, %2, %0" - [(set_attr "type" "mcmp_media")]) + "msubs.ub %N1, %2, %0" + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) (define_insn "sssubv4hi3" [(set (match_operand:V4HI 0 "arith_reg_dest" "=r") @@ -10812,7 +12545,8 @@ mov.l\\t1f,r0\\n\\ (match_operand:V4HI 2 "arith_reg_operand" "r")))] "TARGET_SHMEDIA" "msubs.w %N1, %2, %0" - [(set_attr "type" "mcmp_media")]) + [(set_attr "type" "mcmp_media") + (set_attr "highpart" "depend")]) ;; Floating Point Intrinsics @@ -10892,6 +12626,353 @@ mov.l\\t1f,r0\\n\\ "ftrv.s %1, %2, %0" [(set_attr "type" "fparith_media")]) +(define_insn "ldhi_l" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (zero_extract:SI + (mem:SI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p") + (const_int 3)) + (const_int -3))) + (plus:SI (and:SI (match_dup 1) (const_int 3)) (const_int 1)) + (const_int 0)))] + "TARGET_SHMEDIA32" + "ldhi.l %U1, %0" + [(set_attr "type" "load_media")]) + +(define_insn "ldhi_q" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (zero_extract:DI + (mem:DI (plus:SI (ior:SI (match_operand:QI 1 "ua_address_operand" "p") + (const_int 7)) + (const_int -7))) + (plus:SI (and:SI (match_dup 1) (const_int 7)) (const_int 1)) + (const_int 0)))] + "TARGET_SHMEDIA32" + "ldhi.q %U1, %0" + [(set_attr "type" "load_media")]) + +(define_insn_and_split "*ldhi_q_comb0" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (zero_extract:DI + (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1 + "register_operand" "r") + (match_operand:SI 2 + "ua_offset" "I06")) + (const_int 7)) + (const_int -7))) + (plus:SI (and:SI (match_dup 1) (const_int 7)) + (const_int 1)) + (const_int 0)))] + "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0" + "#" + "" + [(pc)] + "emit_insn (gen_ldhi_q (operands[0], + gen_rtx_PLUS (SImode, operands[1], operands[2]))); + DONE;") + + +(define_insn_and_split "*ldhi_q_comb1" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (zero_extract:DI + (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 1 + "register_operand" "r") + (match_operand:SI 2 + "ua_offset" "I06")) + (const_int 7)) + (const_int -7))) + (plus:SI (and:SI (plus:SI (match_dup 1) (match_operand:SI 3 + "ua_offset" "I06")) + (const_int 7)) + (const_int 1)) + (const_int 0)))] + "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8) + && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])" + "#" + "" + [(pc)] + "emit_insn (gen_ldhi_q (operands[0], + gen_rtx_PLUS (SImode, operands[1], operands[2]))); + DONE;") + + +(define_insn "ldlo_l" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (zero_extract:SI + (mem:SI (and:SI (match_operand:QI 1 "ua_address_operand" "p") + (const_int -4))) + (minus:SI (const_int 4) (and:SI (match_dup 1) (const_int 3))) + (and:SI (match_dup 1) (const_int 3))))] + "TARGET_SHMEDIA32" + "ldlo.l %U1, %0" + [(set_attr "type" "load_media")]) + +(define_insn "ldlo_q" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (zero_extract:DI + (mem:DI (and:SI (match_operand:QI 1 "ua_address_operand" "p") + (const_int -8))) + (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7))) + (and:SI (match_dup 1) (const_int 7))))] + "TARGET_SHMEDIA32" + "ldlo.q %U1, %0" + [(set_attr "type" "load_media")]) + +(define_insn_and_split "*ldlo_q_comb0" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (zero_extract:DI + (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "ua_offset" "I06")) + (const_int -8))) + (minus:SI (const_int 8) (and:SI (match_dup 1) (const_int 7))) + (and:SI (match_dup 1) (const_int 7))))] + "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & 7) == 0" + "#" + "" + [(pc)] + "emit_insn (gen_ldlo_q (operands[0], + gen_rtx_PLUS (SImode, operands[1], operands[2]))); + DONE;") + +(define_insn_and_split "*ldlo_q_comb1" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (zero_extract:DI + (mem:DI (and:SI (plus:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "ua_offset" "I06")) + (const_int -8))) + (minus:SI (const_int 8) + (and:SI (plus:SI (match_dup 1) + (match_operand:SI 3 "ua_offset" "I06")) + (const_int 7))) + (and:SI (plus:SI (match_dup 1) (match_dup 3)) (const_int 7))))] + "TARGET_SHMEDIA32 && (INTVAL (operands[2]) & -8) + && (INTVAL (operands[2]) & 7) == INTVAL (operands[3])" + "#" + "" + [(pc)] + "emit_insn (gen_ldlo_q (operands[0], + gen_rtx_PLUS (SImode, operands[1], operands[2]))); + DONE;") + +(define_insn "sthi_l" + [(set (zero_extract:SI + (mem:SI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p") + (const_int 3)) + (const_int -3))) + (plus:SI (and:SI (match_dup 0) (const_int 3)) (const_int 1)) + (const_int 0)) + (match_operand:SI 1 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA32" + "sthi.l %U0, %1" + [(set_attr "type" "ustore_media")]) + +;; All unaligned stores are considered to be 'narrow' because they typically +;; operate on less that a quadword, and when they operate on a full quadword, +;; the vanilla store high / store low sequence will cause a stall if not +;; scheduled apart. +(define_insn "sthi_q" + [(set (zero_extract:DI + (mem:DI (plus:SI (ior:SI (match_operand:QI 0 "ua_address_operand" "p") + (const_int 7)) + (const_int -7))) + (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1)) + (const_int 0)) + (match_operand:DI 1 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA32" + "sthi.q %U0, %1" + [(set_attr "type" "ustore_media")]) + +(define_insn_and_split "*sthi_q_comb0" + [(set (zero_extract:DI + (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0 + "register_operand" "r") + (match_operand:SI 1 "ua_offset" + "I06")) + (const_int 7)) + (const_int -7))) + (plus:SI (and:SI (match_dup 0) (const_int 7)) (const_int 1)) + (const_int 0)) + (match_operand:DI 2 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0" + "#" + "" + [(pc)] + "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), + operands[2])); + DONE;") + +(define_insn_and_split "*sthi_q_comb1" + [(set (zero_extract:DI + (mem:DI (plus:SI (ior:SI (plus:SI (match_operand:SI 0 + "register_operand" "r") + (match_operand:SI 1 "ua_offset" + "I06")) + (const_int 7)) + (const_int -7))) + (plus:SI (and:SI (plus:SI (match_dup 0) + (match_operand:SI 2 "ua_offset" "I06")) + (const_int 7)) + (const_int 1)) + (const_int 0)) + (match_operand:DI 3 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & -8) + && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])" + "#" + "" + [(pc)] + "emit_insn (gen_sthi_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), + operands[3])); + DONE;") + +;; This is highpart user because the address is used as full 64 bit. +(define_insn "stlo_l" + [(set (zero_extract:SI + (mem:SI (and:SI (match_operand:QI 0 "ua_address_operand" "p") + (const_int -4))) + (minus:SI (const_int 4) (and:SI (match_dup 0) (const_int 3))) + (and:SI (match_dup 0) (const_int 3))) + (match_operand:SI 1 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA32" + "stlo.l %U0, %1" + [(set_attr "type" "ustore_media")]) + +(define_insn "stlo_q" + [(set (zero_extract:DI + (mem:DI (and:SI (match_operand:QI 0 "ua_address_operand" "p") + (const_int -8))) + (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7))) + (and:SI (match_dup 0) (const_int 7))) + (match_operand:DI 1 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA32" + "stlo.q %U0, %1" + [(set_attr "type" "ustore_media")]) + +(define_insn_and_split "*stlo_q_comb0" + [(set (zero_extract:DI + (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "ua_offset" "I06")) + (const_int -8))) + (minus:SI (const_int 8) (and:SI (match_dup 0) (const_int 7))) + (and:SI (match_dup 0) (const_int 7))) + (match_operand:DI 2 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == 0" + "#" + "" + [(pc)] + "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), + operands[2])); + DONE;") + +(define_insn_and_split "*stlo_q_comb1" + [(set (zero_extract:DI + (mem:DI (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "ua_offset" "I06")) + (const_int -8))) + (minus:SI (const_int 8) (and:SI (plus:SI (match_dup 0) + (match_operand:SI 2 + "ua_offset" "I06")) + (const_int 7))) + (and:SI (plus:SI (match_dup 0) (match_dup 2)) (const_int 7))) + (match_operand:DI 3 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA32 && (INTVAL (operands[1]) & 7) == INTVAL (operands[2])" + "#" + "" + [(pc)] + "emit_insn (gen_stlo_q (gen_rtx_PLUS (SImode, operands[0], operands[1]), + operands[3])); + DONE;") + +(define_insn "ldhi_l64" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (zero_extract:SI + (mem:SI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p") + (const_int 3)) + (const_int -3))) + (plus:DI (and:DI (match_dup 1) (const_int 3)) (const_int 1)) + (const_int 0)))] + "TARGET_SHMEDIA64" + "ldhi.l %U1, %0" + [(set_attr "type" "load_media")]) + +(define_insn "ldhi_q64" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (zero_extract:DI + (mem:DI (plus:DI (ior:DI (match_operand:QI 1 "ua_address_operand" "p") + (const_int 7)) + (const_int -7))) + (plus:DI (and:DI (match_dup 1) (const_int 7)) (const_int 1)) + (const_int 0)))] + "TARGET_SHMEDIA64" + "ldhi.q %U1, %0" + [(set_attr "type" "load_media")]) + +(define_insn "ldlo_l64" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (zero_extract:SI + (mem:SI (and:DI (match_operand:QI 1 "ua_address_operand" "p") + (const_int -4))) + (minus:DI (const_int 4) (and:DI (match_dup 1) (const_int 3))) + (and:DI (match_dup 1) (const_int 3))))] + "TARGET_SHMEDIA64" + "ldlo.l %U1, %0" + [(set_attr "type" "load_media")]) + +(define_insn "ldlo_q64" + [(set (match_operand:DI 0 "arith_reg_dest" "=r") + (zero_extract:DI + (mem:DI (and:DI (match_operand:QI 1 "ua_address_operand" "p") + (const_int -8))) + (minus:DI (const_int 8) (and:DI (match_dup 1) (const_int 7))) + (and:DI (match_dup 1) (const_int 7))))] + "TARGET_SHMEDIA64" + "ldlo.q %U1, %0" + [(set_attr "type" "load_media")]) + +(define_insn "sthi_l64" + [(set (zero_extract:SI + (mem:SI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p") + (const_int 3)) + (const_int -3))) + (plus:DI (and:DI (match_dup 0) (const_int 3)) (const_int 1)) + (const_int 0)) + (match_operand:SI 1 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA64" + "sthi.l %U0, %1" + [(set_attr "type" "ustore_media")]) + +(define_insn "sthi_q64" + [(set (zero_extract:DI + (mem:DI (plus:DI (ior:DI (match_operand:QI 0 "ua_address_operand" "p") + (const_int 7)) + (const_int -7))) + (plus:DI (and:DI (match_dup 0) (const_int 7)) (const_int 1)) + (const_int 0)) + (match_operand:DI 1 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA64" + "sthi.q %U0, %1" + [(set_attr "type" "ustore_media")]) + +(define_insn "stlo_l64" + [(set (zero_extract:SI + (mem:SI (and:DI (match_operand:QI 0 "ua_address_operand" "p") + (const_int -4))) + (minus:DI (const_int 4) (and:DI (match_dup 0) (const_int 3))) + (and:DI (match_dup 0) (const_int 3))) + (match_operand:SI 1 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA64" + "stlo.l %U0, %1" + [(set_attr "type" "ustore_media")]) + +(define_insn "stlo_q64" + [(set (zero_extract:DI + (mem:DI (and:DI (match_operand:QI 0 "ua_address_operand" "p") + (const_int -8))) + (minus:DI (const_int 8) (and:DI (match_dup 0) (const_int 7))) + (and:DI (match_dup 0) (const_int 7))) + (match_operand:DI 1 "arith_reg_operand" "r"))] + "TARGET_SHMEDIA64" + "stlo.q %U0, %1" + [(set_attr "type" "ustore_media")]) + (define_insn "nsb" [(set (match_operand:QI 0 "arith_reg_dest" "=r") (unspec:QI [(match_operand:DI 1 "arith_reg_operand" "r")] @@ -10975,7 +13056,7 @@ mov.l\\t1f,r0\\n\\ "byterev %1, %0" [(set_attr "type" "arith_media")]) -(define_insn "prefetch_media" +(define_insn "*prefetch_media" [(prefetch (match_operand:QI 0 "address_operand" "p") (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "const_int_operand" "n"))] @@ -10988,11 +13069,11 @@ mov.l\\t1f,r0\\n\\ }" [(set_attr "type" "other")]) -(define_insn "prefetch_i4" +(define_insn "*prefetch_i4" [(prefetch (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "const_int_operand" "n"))] - "TARGET_HARD_SH4" + "TARGET_HARD_SH4 || TARGET_SHCOMPACT" "* { return \"pref @%0\"; @@ -11000,20 +13081,53 @@ mov.l\\t1f,r0\\n\\ [(set_attr "type" "other")]) (define_expand "prefetch" - [(prefetch (match_operand:QI 0 "address_operand" "p") + [(prefetch (match_operand 0 "address_operand" "p") (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "const_int_operand" "n"))] - "TARGET_SHMEDIA || TARGET_HARD_SH4" + "TARGET_HARD_SH4 || TARGET_SH5" " { - if (TARGET_HARD_SH4 && ! register_operand (operands[0], SImode)) + if (GET_MODE (operands[0]) != Pmode + || GET_CODE (operands[1]) != CONST_INT + || GET_CODE (operands[2]) != CONST_INT) + FAIL; + if (! TARGET_SHMEDIA) + operands[0] = force_reg (Pmode, operands[0]); +}") + +(define_insn "alloco_i" + [(set (mem:BLK (match_operand:QI 0 "cache_address_operand" "p")) + (unspec:BLK [(const_int 0)] UNSPEC_ALLOCO))] + "TARGET_SHMEDIA32" + "* +{ + rtx xops[2]; + + if (GET_CODE (operands[0]) == PLUS) + { + xops[0] = XEXP (operands[0], 0); + xops[1] = XEXP (operands[0], 1); + } + else { - rtx reg = gen_reg_rtx (SImode); - emit_move_insn (reg, operands[0]); - operands[0] = reg; + xops[0] = operands[0]; + xops[1] = const0_rtx; } + output_asm_insn (\"alloco %0, %1\", xops); + return \"\"; +}" + [(set_attr "type" "other")]) - emit_insn ((TARGET_SHMEDIA ? gen_prefetch_media : gen_prefetch_i4) - (operands[0], operands[1], operands[2])); - DONE; +(define_split + [(set (match_operand 0 "any_register_operand" "") + (match_operand 1 "" ""))] + "TARGET_SHMEDIA && reload_completed" + [(set (match_dup 0) (match_dup 1))] + " +{ + int n_changes = 0; + + for_each_rtx (&operands[1], shmedia_cleanup_truncate, &n_changes); + if (!n_changes) + FAIL; }")