Mercurial > hg > CbC > CbC_gcc
diff gcc/config/bfin/bfin.md @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | 04ced10e8804 |
line wrap: on
line diff
--- a/gcc/config/bfin/bfin.md Sun Feb 07 18:28:00 2010 +0900 +++ b/gcc/config/bfin/bfin.md Fri Feb 12 23:39:51 2010 +0900 @@ -138,15 +138,16 @@ ;; Distinguish a 32-bit version of an insn from a 16-bit version. (UNSPEC_32BIT 11) (UNSPEC_NOP 12) - (UNSPEC_ONES 12)]) + (UNSPEC_ONES 13) + (UNSPEC_ATOMIC 14)]) (define_constants - [(UNSPEC_VOLATILE_EH_RETURN 0) - (UNSPEC_VOLATILE_CSYNC 1) + [(UNSPEC_VOLATILE_CSYNC 1) (UNSPEC_VOLATILE_SSYNC 2) (UNSPEC_VOLATILE_LOAD_FUNCDESC 3) (UNSPEC_VOLATILE_STORE_EH_HANDLER 4) - (UNSPEC_VOLATILE_DUMMY 5)]) + (UNSPEC_VOLATILE_DUMMY 5) + (UNSPEC_VOLATILE_STALL 6)]) (define_constants [(MACFLAG_NONE 0) @@ -163,28 +164,42 @@ (MACFLAG_IH 11)]) (define_attr "type" - "move,movcc,mvi,mcld,mcst,dsp32,mult,alu0,shft,brcc,br,call,misc,sync,compare,dummy" + "move,movcc,mvi,mcld,mcst,dsp32,dsp32shiftimm,mult,alu0,shft,brcc,br,call,misc,sync,compare,dummy,stall" (const_string "misc")) -(define_attr "addrtype" "32bit,preg,ireg" +(define_attr "addrtype" "32bit,preg,spreg,ireg" (cond [(and (eq_attr "type" "mcld") - (and (match_operand 0 "d_register_operand" "") + (and (match_operand 0 "dp_register_operand" "") (match_operand 1 "mem_p_address_operand" ""))) (const_string "preg") (and (eq_attr "type" "mcld") - (and (match_operand 0 "d_register_operand" "") + (and (match_operand 0 "dp_register_operand" "") + (match_operand 1 "mem_spfp_address_operand" ""))) + (const_string "spreg") + (and (eq_attr "type" "mcld") + (and (match_operand 0 "dp_register_operand" "") (match_operand 1 "mem_i_address_operand" ""))) (const_string "ireg") (and (eq_attr "type" "mcst") - (and (match_operand 1 "d_register_operand" "") + (and (match_operand 1 "dp_register_operand" "") (match_operand 0 "mem_p_address_operand" ""))) (const_string "preg") (and (eq_attr "type" "mcst") - (and (match_operand 1 "d_register_operand" "") + (and (match_operand 1 "dp_register_operand" "") + (match_operand 0 "mem_spfp_address_operand" ""))) + (const_string "spreg") + (and (eq_attr "type" "mcst") + (and (match_operand 1 "dp_register_operand" "") (match_operand 0 "mem_i_address_operand" ""))) (const_string "ireg")] (const_string "32bit"))) +(define_attr "storereg" "preg,other" + (cond [(and (eq_attr "type" "mcst") + (match_operand 1 "p_register_operand" "")) + (const_string "preg")] + (const_string "other"))) + ;; Scheduling definitions (define_automaton "bfin") @@ -199,6 +214,13 @@ (define_cpu_unit "store" "bfin") (define_cpu_unit "pregs" "bfin") +;; A dummy unit used to delay scheduling of loads after a conditional +;; branch. +(define_cpu_unit "load" "bfin") + +;; A logical unit used to work around anomaly 05000074. +(define_cpu_unit "anomaly_05000074" "bfin") + (define_reservation "core" "slot0+slot1+slot2") (define_insn_reservation "alu" 1 @@ -213,20 +235,37 @@ (eq_attr "type" "dsp32") "slot0") +(define_insn_reservation "dsp32shiftimm" 1 + (and (eq_attr "type" "dsp32shiftimm") + (eq (symbol_ref "ENABLE_WA_05000074") + (const_int 0))) + "slot0") + +(define_insn_reservation "dsp32shiftimm_anomaly_05000074" 1 + (and (eq_attr "type" "dsp32shiftimm") + (ne (symbol_ref "ENABLE_WA_05000074") + (const_int 0))) + "slot0+anomaly_05000074") + (define_insn_reservation "load32" 1 (and (not (eq_attr "seq_insns" "multi")) (and (eq_attr "type" "mcld") (eq_attr "addrtype" "32bit"))) - "core") + "core+load") (define_insn_reservation "loadp" 1 (and (not (eq_attr "seq_insns" "multi")) (and (eq_attr "type" "mcld") (eq_attr "addrtype" "preg"))) - "(slot1|slot2)+pregs") + "slot1+pregs+load") + +(define_insn_reservation "loadsp" 1 + (and (not (eq_attr "seq_insns" "multi")) + (and (eq_attr "type" "mcld") (eq_attr "addrtype" "spreg"))) + "slot1+pregs") (define_insn_reservation "loadi" 1 (and (not (eq_attr "seq_insns" "multi")) (and (eq_attr "type" "mcld") (eq_attr "addrtype" "ireg"))) - "(slot1|slot2)") + "(slot1|slot2)+load") (define_insn_reservation "store32" 1 (and (not (eq_attr "seq_insns" "multi")) @@ -234,19 +273,55 @@ "core") (define_insn_reservation "storep" 1 - (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcst") (eq_attr "addrtype" "preg"))) - "(slot1|slot2)+pregs+store") + (and (and (not (eq_attr "seq_insns" "multi")) + (and (eq_attr "type" "mcst") + (ior (eq_attr "addrtype" "preg") + (eq_attr "addrtype" "spreg")))) + (ior (eq (symbol_ref "ENABLE_WA_05000074") + (const_int 0)) + (eq_attr "storereg" "other"))) + "slot1+pregs+store") + +(define_insn_reservation "storep_anomaly_05000074" 1 + (and (and (not (eq_attr "seq_insns" "multi")) + (and (eq_attr "type" "mcst") + (ior (eq_attr "addrtype" "preg") + (eq_attr "addrtype" "spreg")))) + (and (ne (symbol_ref "ENABLE_WA_05000074") + (const_int 0)) + (eq_attr "storereg" "preg"))) + "slot1+anomaly_05000074+pregs+store") (define_insn_reservation "storei" 1 - (and (not (eq_attr "seq_insns" "multi")) - (and (eq_attr "type" "mcst") (eq_attr "addrtype" "ireg"))) + (and (and (not (eq_attr "seq_insns" "multi")) + (and (eq_attr "type" "mcst") (eq_attr "addrtype" "ireg"))) + (ior (eq (symbol_ref "ENABLE_WA_05000074") + (const_int 0)) + (eq_attr "storereg" "other"))) "(slot1|slot2)+store") +(define_insn_reservation "storei_anomaly_05000074" 1 + (and (and (not (eq_attr "seq_insns" "multi")) + (and (eq_attr "type" "mcst") (eq_attr "addrtype" "ireg"))) + (and (ne (symbol_ref "ENABLE_WA_05000074") + (const_int 0)) + (eq_attr "storereg" "preg"))) + "((slot1+anomaly_05000074)|slot2)+store") + (define_insn_reservation "multi" 2 (eq_attr "seq_insns" "multi") "core") +(define_insn_reservation "load_stall1" 1 + (and (eq_attr "type" "stall") + (match_operand 0 "const1_operand" "")) + "core+load*2") + +(define_insn_reservation "load_stall3" 1 + (and (eq_attr "type" "stall") + (match_operand 0 "const3_operand" "")) + "core+load*4") + (absence_set "slot0" "slot1,slot2") (absence_set "slot1" "slot2") @@ -303,6 +378,7 @@ (eq_attr "type" "move") (const_int 2) (eq_attr "type" "dsp32") (const_int 4) + (eq_attr "type" "dsp32shiftimm") (const_int 4) (eq_attr "type" "call") (const_int 4) (eq_attr "type" "br") @@ -532,20 +608,22 @@ ;; with a PLUS. We generally require fewer secondary reloads this way. (define_insn "*movsi_insn" - [(set (match_operand:SI 0 "nonimmediate_operand" "=da,x*y,da,x,x,x,da,mr") - (match_operand:SI 1 "general_operand" "da,x*y,xKs7,xKsh,xKuh,ix,mr,da"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=da,x,da,y,da,x,x,x,da,mr") + (match_operand:SI 1 "general_operand" "da,x,y,da,xKs7,xKsh,xKuh,ix,mr,da"))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG" "@ %0 = %1; %0 = %1; + %0 = %1; + %0 = %1; %0 = %1 (X); %0 = %1 (X); %0 = %1 (Z); # %0 = %1%! %0 = %1%!" - [(set_attr "type" "move,move,mvi,mvi,mvi,*,mcld,mcst") - (set_attr "length" "2,2,2,4,4,*,*,*")]) + [(set_attr "type" "move,move,move,move,mvi,mvi,mvi,*,mcld,mcst") + (set_attr "length" "2,2,2,2,2,4,4,*,*,*")]) (define_insn "*movsi_insn32" [(set (match_operand:SI 0 "register_operand" "=d,d") @@ -554,7 +632,7 @@ "@ %0 = ROT %1 BY 0%! %0 = %0 -|- %0%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32shiftimm,dsp32")]) (define_split [(set (match_operand:SI 0 "d_register_operand" "") @@ -677,7 +755,7 @@ "@ %d0 = %h1 << 0%! %d0 = %1;" - [(set_attr "type" "dsp32,mvi")]) + [(set_attr "type" "dsp32shiftimm,mvi")]) (define_expand "insv" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "") @@ -1587,7 +1665,7 @@ [(set (match_dup 0) (ashift:SI (match_dup 1) (const_int 2))) (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 3)))] "operands[3] = GEN_INT (INTVAL (operands[2]) - 2);" - [(set_attr "type" "shft,dsp32,shft,shft,*")]) + [(set_attr "type" "shft,dsp32shiftimm,shft,shft,*")]) (define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=d,d") @@ -1597,7 +1675,7 @@ "@ %0 >>>= %2; %0 = %1 >>> %2%!" - [(set_attr "type" "shft,dsp32")]) + [(set_attr "type" "shft,dsp32shiftimm")]) (define_insn "rotl16" [(set (match_operand:SI 0 "register_operand" "=d") @@ -1638,7 +1716,7 @@ (zero_extract:BI (match_dup 1) (const_int 1) (const_int 0)))] "" "%0 = ROT %1 BY -1%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32shiftimm")]) (define_insn "rol_one" [(set (match_operand:SI 0 "register_operand" "+d") @@ -1648,7 +1726,7 @@ (zero_extract:BI (match_dup 1) (const_int 31) (const_int 0)))] "" "%0 = ROT %1 BY 1%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32shiftimm")]) (define_expand "lshrdi3" [(set (match_operand:DI 0 "register_operand" "") @@ -1723,7 +1801,7 @@ %0 >>= %2; %0 = %1 >> %2%! %0 = %1 >> %2;" - [(set_attr "type" "shft,dsp32,shft")]) + [(set_attr "type" "shft,dsp32shiftimm,shft")]) (define_insn "lshrpdi3" [(set (match_operand:PDI 0 "register_operand" "=e") @@ -1731,7 +1809,7 @@ (match_operand:SI 2 "nonmemory_operand" "Ku5")))] "" "%0 = %1 >> %2%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32shiftimm")]) (define_insn "ashrpdi3" [(set (match_operand:PDI 0 "register_operand" "=e") @@ -1739,7 +1817,7 @@ (match_operand:SI 2 "nonmemory_operand" "Ku5")))] "" "%0 = %1 >>> %2%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32shiftimm")]) ;; A pattern to reload the equivalent of ;; (set (Dreg) (plus (FP) (large_constant))) @@ -1763,9 +1841,11 @@ DONE; }) -(define_insn "reload_inpdi" - [(set (match_operand:PDI 0 "register_operand" "=e") - (match_operand:PDI 1 "memory_operand" "m")) +(define_mode_iterator AREG [PDI V2PDI]) + +(define_insn "reload_in<mode>" + [(set (match_operand:AREG 0 "register_operand" "=e") + (match_operand:AREG 1 "memory_operand" "m")) (clobber (match_operand:SI 2 "register_operand" "=d"))] "" { @@ -1783,9 +1863,9 @@ (set_attr "type" "mcld") (set_attr "length" "12")]) -(define_insn "reload_outpdi" - [(set (match_operand:PDI 0 "memory_operand" "=m") - (match_operand:PDI 1 "register_operand" "e")) +(define_insn "reload_out<mode>" + [(set (match_operand:AREG 0 "memory_operand" "=m") + (match_operand:AREG 1 "register_operand" "e")) (clobber (match_operand:SI 2 "register_operand" "=d"))] "" { @@ -1908,7 +1988,7 @@ (const_int -1))) (unspec [(const_int 0)] UNSPEC_LSETUP_END) (clobber (match_scratch:SI 2 "=&r"))] - "reload_completed" + "splitting_loops" [(set (match_dup 2) (match_dup 0)) (set (match_dup 2) (plus:SI (match_dup 2) (const_int -1))) (set (match_dup 0) (match_dup 2)) @@ -2004,7 +2084,8 @@ [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q")) (match_operand 1 "general_operand" "g")) (use (match_operand:SI 2 "register_operand" "Z")) - (use (match_operand 3 "" ""))] + (use (match_operand 3 "" "")) + (clobber (reg:SI REG_RETS))] "! SIBLING_CALL_P (insn) && GET_CODE (operands[0]) == SYMBOL_REF && !bfin_longcall_p (operands[0], INTVAL (operands[3]))" @@ -2030,7 +2111,8 @@ (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q")) (match_operand 2 "general_operand" "g"))) (use (match_operand:SI 3 "register_operand" "Z")) - (use (match_operand 4 "" ""))] + (use (match_operand 4 "" "")) + (clobber (reg:SI REG_RETS))] "! SIBLING_CALL_P (insn) && GET_CODE (operands[1]) == SYMBOL_REF && !bfin_longcall_p (operands[1], INTVAL (operands[4]))" @@ -2056,7 +2138,8 @@ [(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "Y")) (match_operand 1 "general_operand" "g")) (use (match_operand:SI 2 "register_operand" "Z")) - (use (match_operand 3 "" ""))] + (use (match_operand 3 "" "")) + (clobber (reg:SI REG_RETS))] "! SIBLING_CALL_P (insn)" "call (%0);" [(set_attr "type" "call") @@ -2078,7 +2161,8 @@ (call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "Y")) (match_operand 2 "general_operand" "g"))) (use (match_operand:SI 3 "register_operand" "Z")) - (use (match_operand 4 "" ""))] + (use (match_operand 4 "" "")) + (clobber (reg:SI REG_RETS))] "! SIBLING_CALL_P (insn)" "call (%1);" [(set_attr "type" "call") @@ -2099,7 +2183,8 @@ (define_insn "*call_symbol" [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q")) (match_operand 1 "general_operand" "g")) - (use (match_operand 2 "" ""))] + (use (match_operand 2 "" "")) + (clobber (reg:SI REG_RETS))] "! SIBLING_CALL_P (insn) && (!TARGET_ID_SHARED_LIBRARY || TARGET_LEAF_ID_SHARED_LIBRARY) && GET_CODE (operands[0]) == SYMBOL_REF @@ -2125,7 +2210,8 @@ [(set (match_operand 0 "register_operand" "=d") (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q")) (match_operand 2 "general_operand" "g"))) - (use (match_operand 3 "" ""))] + (use (match_operand 3 "" "")) + (clobber (reg:SI REG_RETS))] "! SIBLING_CALL_P (insn) && (!TARGET_ID_SHARED_LIBRARY || TARGET_LEAF_ID_SHARED_LIBRARY) && GET_CODE (operands[1]) == SYMBOL_REF @@ -2151,7 +2237,8 @@ (define_insn "*call_insn" [(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "a")) (match_operand 1 "general_operand" "g")) - (use (match_operand 2 "" ""))] + (use (match_operand 2 "" "")) + (clobber (reg:SI REG_RETS))] "! SIBLING_CALL_P (insn)" "call (%0);" [(set_attr "type" "call") @@ -2171,7 +2258,8 @@ [(set (match_operand 0 "register_operand" "=d") (call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "a")) (match_operand 2 "general_operand" "g"))) - (use (match_operand 3 "" ""))] + (use (match_operand 3 "" "")) + (clobber (reg:SI REG_RETS))] "! SIBLING_CALL_P (insn)" "call (%1);" [(set_attr "type" "call") @@ -2253,29 +2341,6 @@ ;; Conditional branch patterns ;; The Blackfin has only few condition codes: eq, lt, lte, ltu, leu -;; The only outcome of this pattern is that global variables -;; bfin_compare_op[01] are set for use in bcond patterns. - -(define_expand "cmpbi" - [(set (cc0) (compare (match_operand:BI 0 "register_operand" "") - (match_operand:BI 1 "immediate_operand" "")))] - "" -{ - bfin_compare_op0 = operands[0]; - bfin_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmpsi" - [(set (cc0) (compare (match_operand:SI 0 "register_operand" "") - (match_operand:SI 1 "reg_or_const_int_operand" "")))] - "" -{ - bfin_compare_op0 = operands[0]; - bfin_compare_op1 = operands[1]; - DONE; -}) - (define_insn "compare_eq" [(set (match_operand:BI 0 "register_operand" "=C,C") (eq:BI (match_operand:SI 1 "register_operand" "d,a") @@ -2324,106 +2389,6 @@ "cc =%1<%2 (iu);" [(set_attr "type" "compare")]) -(define_expand "beq" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1; - operands[1] = bfin_cc_rtx; /* hard register: CC */ - operands[2] = gen_rtx_EQ (BImode, op0, op1); - /* If we have a BImode input, then we already have a compare result, and - do not need to emit another comparison. */ - if (GET_MODE (bfin_compare_op0) == BImode) - { - gcc_assert (bfin_compare_op1 == const0_rtx); - emit_insn (gen_cbranchbi4 (operands[2], op0, op1, operands[0])); - DONE; - } - - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - -(define_expand "bne" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1; - /* If we have a BImode input, then we already have a compare result, and - do not need to emit another comparison. */ - if (GET_MODE (bfin_compare_op0) == BImode) - { - rtx cmp = gen_rtx_NE (BImode, op0, op1); - - gcc_assert (bfin_compare_op1 == const0_rtx); - emit_insn (gen_cbranchbi4 (cmp, op0, op1, operands[0])); - DONE; - } - - operands[1] = bfin_cc_rtx; /* hard register: CC */ - operands[2] = gen_rtx_EQ (BImode, op0, op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "bgt" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LE (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "bgtu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LEU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "blt" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LT (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - -(define_expand "bltu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LTU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - ;; Same as above, but and CC with the overflow bit generated by the first ;; multiplication. (define_insn "flag_mul_macv2hi_parts_acconly_andcc0" @@ -2488,63 +2453,25 @@ (set_attr "length" "6") (set_attr "seq_insns" "multi")]) -(define_expand "bge" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LT (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "bgeu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "reg_or_const_int_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] "" { - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LTU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx); -}) - -(define_expand "ble" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LE (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); -}) - -(define_expand "bleu" - [(set (match_dup 1) (match_dup 2)) - (set (pc) - (if_then_else (match_dup 3) - (label_ref (match_operand 0 "" "")) - (pc))) - ] - "" -{ - operands[1] = bfin_cc_rtx; - operands[2] = gen_rtx_LEU (BImode, bfin_compare_op0, bfin_compare_op1); - operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx); + rtx bi_compare = bfin_gen_compare (operands[0], SImode); + emit_jump_insn (gen_cbranchbi4 (bi_compare, bfin_cc_rtx, CONST0_RTX (BImode), + operands[3])); + DONE; }) (define_insn "cbranchbi4" [(set (pc) (if_then_else - (match_operator 0 "bfin_cbranch_operator" + (match_operator 0 "bfin_bimode_comparison_operator" [(match_operand:BI 1 "register_operand" "C") (match_operand:BI 2 "immediate_operand" "P0")]) (label_ref (match_operand 3 "" "")) @@ -2562,7 +2489,7 @@ (define_insn "cbranch_predicted_taken" [(set (pc) (if_then_else - (match_operator 0 "bfin_cbranch_operator" + (match_operator 0 "bfin_bimode_comparison_operator" [(match_operand:BI 1 "register_operand" "C") (match_operand:BI 2 "immediate_operand" "P0")]) (label_ref (match_operand 3 "" "")) @@ -2578,7 +2505,7 @@ (define_insn "cbranch_with_nops" [(set (pc) (if_then_else - (match_operator 0 "bfin_cbranch_operator" + (match_operator 0 "bfin_bimode_comparison_operator" [(match_operand:BI 1 "register_operand" "C") (match_operand:BI 2 "immediate_operand" "P0")]) (label_ref (match_operand 3 "" "")) @@ -2592,60 +2519,49 @@ [(set_attr "type" "brcc") (set_attr "length" "8")]) -;; setcc insns. */ -(define_expand "seq" - [(set (match_dup 1) (eq:BI (match_dup 2) (match_dup 3))) +;; setcc insns. + +(define_expand "cstorebi4" + [(set (match_dup 4) + (match_operator:BI 1 "bfin_bimode_comparison_operator" + [(match_operand:BI 2 "register_operand" "") + (match_operand:BI 3 "reg_or_const_int_operand" "")])) (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; -}) - -(define_expand "slt" - [(set (match_dup 1) (lt:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] + (ne:SI (match_dup 4) (const_int 0)))] "" { - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; + /* It could be expanded as a movbisi instruction, but the portable + alternative produces better code. */ + if (GET_CODE (operands[1]) == NE) + FAIL; + + operands[4] = bfin_cc_rtx; }) -(define_expand "sle" - [(set (match_dup 1) (le:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] +(define_expand "cstoresi4" + [(set (match_operand:SI 0 "register_operand") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "reg_or_const_int_operand" "")]))] "" { - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; -}) - -(define_expand "sltu" - [(set (match_dup 1) (ltu:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; -}) - -(define_expand "sleu" - [(set (match_dup 1) (leu:BI (match_dup 2) (match_dup 3))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 1) (const_int 0)))] - "" -{ - operands[2] = bfin_compare_op0; - operands[3] = bfin_compare_op1; - operands[1] = bfin_cc_rtx; + rtx bi_compare, test; + + if (!bfin_direct_comparison_operator (operands[1], SImode)) + { + if (!register_operand (operands[3], SImode) + || GET_CODE (operands[1]) == NE) + FAIL; + test = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])), + SImode, operands[3], operands[2]); + } + else + test = operands[1]; + + bi_compare = bfin_gen_compare (test, SImode); + gcc_assert (GET_CODE (bi_compare) == NE); + emit_insn (gen_movbisi (operands[0], bfin_cc_rtx)); + DONE; }) (define_insn "nop" @@ -2674,13 +2590,16 @@ "CC = %1;" [(set_attr "length" "2")]) -(define_insn "movbisi" +(define_insn_and_split "movbisi" [(set (match_operand:SI 0 "register_operand" "=d") (ne:SI (match_operand:BI 1 "register_operand" "C") (const_int 0)))] "" - "%0 = CC;" - [(set_attr "length" "2")]) + "#" + "" + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:BI 1 "register_operand" "")))] + "") (define_insn "notbi" [(set (match_operand:BI 0 "register_operand" "=C") @@ -2740,8 +2659,7 @@ "bfin_expand_epilogue (0, 0, 1); DONE;") (define_expand "eh_return" - [(unspec_volatile [(match_operand:SI 0 "register_operand" "")] - UNSPEC_VOLATILE_EH_RETURN)] + [(use (match_operand:SI 0 "register_operand" ""))] "" { emit_insn (gen_eh_store_handler (EH_RETURN_HANDLER_RTX, operands[0])); @@ -2759,11 +2677,10 @@ [(set_attr "type" "mcst")]) (define_insn_and_split "eh_return_internal" - [(set (pc) - (unspec_volatile [(reg:SI REG_P2)] UNSPEC_VOLATILE_EH_RETURN))] + [(eh_return)] "" "#" - "reload_completed" + "epilogue_completed" [(const_int 1)] "bfin_expand_epilogue (1, 1, 0); DONE;") @@ -2811,23 +2728,26 @@ (define_insn "return_internal" [(return) - (unspec [(match_operand 0 "immediate_operand" "i")] UNSPEC_RETURN)] + (use (match_operand 0 "register_operand" ""))] "reload_completed" { - switch (INTVAL (operands[0])) + switch (REGNO (operands[0])) { - case EXCPT_HANDLER: + case REG_RETX: return "rtx;"; - case NMI_HANDLER: + case REG_RETN: return "rtn;"; - case INTERRUPT_HANDLER: + case REG_RETI: return "rti;"; - case SUBROUTINE: + case REG_RETS: return "rts;"; } gcc_unreachable (); }) +;; When used at a location where CC contains 1, causes a speculative load +;; that is later cancelled. This is used for certain workarounds in +;; interrupt handler prologues. (define_insn "dummy_load" [(unspec_volatile [(match_operand 0 "register_operand" "a") (match_operand 1 "register_operand" "C")] @@ -2838,6 +2758,17 @@ (set_attr "length" "4") (set_attr "seq_insns" "multi")]) +;; A placeholder insn inserted before the final scheduling pass. It is used +;; to improve scheduling of loads when workarounds for speculative loads are +;; needed, by not placing them in the first few cycles after a conditional +;; branch. +(define_insn "stall" + [(unspec_volatile [(match_operand 0 "const_int_operand" "P1P3")] + UNSPEC_VOLATILE_STALL)] + "" + "" + [(set_attr "type" "stall")]) + (define_insn "csync" [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_CSYNC)] "" @@ -2877,7 +2808,7 @@ (parallel [(const_int 1)]))))] "" "%h0 = %h2 << 0%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32shiftimm")]) (define_insn "movhiv2hi_high" [(set (match_operand:V2HI 0 "register_operand" "=d") @@ -2887,7 +2818,7 @@ (match_operand:HI 2 "register_operand" "d")))] "" "%d0 = %h2 << 0%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32shiftimm")]) ;; No earlyclobber on alternative two since our sequence ought to be safe. ;; The order of operands is intentional to match the VDSP builtin (high word @@ -2910,7 +2841,7 @@ (match_dup 2) (vec_select:HI (match_dup 0) (parallel [(const_int 1)]))))] "" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32shiftimm")]) ; Like composev2hi, but operating on elements of V2HI vectors. ; Useful on its own, and as a combiner bridge for the multiply and @@ -2933,7 +2864,7 @@ %0 = PACK (%h2,%d1)%! %0 = PACK (%d2,%h1)%! %0 = PACK (%d2,%d1)%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32shiftimm,dsp32shiftimm,dsp32shiftimm,dsp32shiftimm,dsp32,dsp32,dsp32,dsp32")]) (define_insn "movv2hi_hi" [(set (match_operand:HI 0 "register_operand" "=d,d,d") @@ -2944,7 +2875,7 @@ /* optimized out */ %h0 = %h1 << 0%! %h0 = %d1 << 0%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32shiftimm")]) (define_expand "movv2hi_hi_low" [(set (match_operand:HI 0 "register_operand" "") @@ -2962,74 +2893,82 @@ ;; Unusual arithmetic operations on 16-bit registers. -(define_insn "ssaddhi3" +(define_code_iterator sp_or_sm [ss_plus ss_minus]) +(define_code_attr spm_string [(ss_plus "+") (ss_minus "-")]) +(define_code_attr spm_name [(ss_plus "add") (ss_minus "sub")]) + +(define_insn "ss<spm_name>hi3" [(set (match_operand:HI 0 "register_operand" "=d") - (ss_plus:HI (match_operand:HI 1 "register_operand" "d") + (sp_or_sm:HI (match_operand:HI 1 "register_operand" "d") (match_operand:HI 2 "register_operand" "d")))] "" - "%h0 = %h1 + %h2 (S)%!" + "%h0 = %h1 <spm_string> %h2 (S)%!" [(set_attr "type" "dsp32")]) -(define_insn "ssaddhi3_parts" - [(set (vec_select:HI - (match_operand:V2HI 0 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) - (ss_plus:HI (vec_select:HI - (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 4 "const01_operand" "P0P1")])) - (vec_select:HI - (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 5 "const01_operand" "P0P1")]))))] - "" +(define_insn "ss<spm_name>hi3_parts" + [(set (match_operand:HI 0 "register_operand" "=d") + (sp_or_sm:HI (vec_select:HI + (match_operand:V2HI 1 "register_operand" "d") + (parallel [(match_operand 3 "const01_operand" "P0P1")])) + (vec_select:HI + (match_operand:V2HI 2 "register_operand" "d") + (parallel [(match_operand 4 "const01_operand" "P0P1")]))))] + "" { const char *templates[] = { - "%h0 = %h1 + %h2 (S)%!", - "%d0 = %h1 + %h2 (S)%!", - "%h0 = %d1 + %h2 (S)%!", - "%d0 = %d1 + %h2 (S)%!", - "%h0 = %h1 + %d2 (S)%!", - "%d0 = %h1 + %d2 (S)%!", - "%h0 = %d1 + %d2 (S)%!", - "%d0 = %d1 + %d2 (S)%!" }; - int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1) - + (INTVAL (operands[5]) << 2); + "%h0 = %h1 <spm_string> %h2 (S)%!", + "%h0 = %d1 <spm_string> %h2 (S)%!", + "%h0 = %h1 <spm_string> %d2 (S)%!", + "%h0 = %d1 <spm_string> %d2 (S)%!" }; + int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1); return templates[alt]; } [(set_attr "type" "dsp32")]) -(define_insn "sssubhi3_parts" - [(set (vec_select:HI - (match_operand:V2HI 0 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) - (ss_minus:HI (vec_select:HI - (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 4 "const01_operand" "P0P1")])) - (vec_select:HI - (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 5 "const01_operand" "P0P1")]))))] - "" +(define_insn "ss<spm_name>hi3_low_parts" + [(set (match_operand:V2HI 0 "register_operand" "=d") + (vec_concat:V2HI + (vec_select:HI (match_operand:V2HI 1 "register_operand" "0") + (parallel [(const_int 0)])) + (sp_or_sm:HI (vec_select:HI + (match_operand:V2HI 2 "register_operand" "d") + (parallel [(match_operand 4 "const01_operand" "P0P1")])) + (vec_select:HI + (match_operand:V2HI 3 "register_operand" "d") + (parallel [(match_operand 5 "const01_operand" "P0P1")])))))] + "" { const char *templates[] = { - "%h0 = %h1 - %h2 (S)%!", - "%d0 = %h1 - %h2 (S)%!", - "%h0 = %d1 - %h2 (S)%!", - "%d0 = %d1 - %h2 (S)%!", - "%h0 = %h1 - %d2 (S)%!", - "%d0 = %h1 - %d2 (S)%!", - "%h0 = %d1 - %d2 (S)%!", - "%d0 = %d1 - %d2 (S)%!" }; - int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1) - + (INTVAL (operands[5]) << 2); + "%h0 = %h2 <spm_string> %h3 (S)%!", + "%h0 = %d2 <spm_string> %h3 (S)%!", + "%h0 = %h2 <spm_string> %d3 (S)%!", + "%h0 = %d2 <spm_string> %d3 (S)%!" }; + int alt = INTVAL (operands[4]) + (INTVAL (operands[5]) << 1); return templates[alt]; } [(set_attr "type" "dsp32")]) -(define_insn "sssubhi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (ss_minus:HI (match_operand:HI 1 "register_operand" "d") - (match_operand:HI 2 "register_operand" "d")))] - "" - "%h0 = %h1 - %h2 (S)%!" +(define_insn "ss<spm_name>hi3_high_parts" + [(set (match_operand:V2HI 0 "register_operand" "=d") + (vec_concat:V2HI + (sp_or_sm:HI (vec_select:HI + (match_operand:V2HI 2 "register_operand" "d") + (parallel [(match_operand 4 "const01_operand" "P0P1")])) + (vec_select:HI + (match_operand:V2HI 3 "register_operand" "d") + (parallel [(match_operand 5 "const01_operand" "P0P1")]))) + (vec_select:HI (match_operand:V2HI 1 "register_operand" "0") + (parallel [(const_int 1)]))))] + "" +{ + const char *templates[] = { + "%d0 = %h2 <spm_string> %h3 (S)%!", + "%d0 = %d2 <spm_string> %h3 (S)%!", + "%d0 = %h2 <spm_string> %d3 (S)%!", + "%d0 = %d2 <spm_string> %d3 (S)%!" }; + int alt = INTVAL (operands[4]) + (INTVAL (operands[5]) << 1); + return templates[alt]; +} [(set_attr "type" "dsp32")]) ;; V2HI vector insns @@ -3239,30 +3178,23 @@ [(set_attr "type" "dsp32")]) (define_insn "flag_mulhi_parts" - [(set (vec_select:HI - (match_operand:V2HI 0 "register_operand" "d") - (parallel [(match_operand 3 "const01_operand" "P0P1")])) + [(set (match_operand:HI 0 "register_operand" "=d") (unspec:HI [(vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(match_operand 4 "const01_operand" "P0P1")])) + (parallel [(match_operand 3 "const01_operand" "P0P1")])) (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(match_operand 5 "const01_operand" "P0P1")])) - (match_operand 6 "const_int_operand" "n")] + (parallel [(match_operand 4 "const01_operand" "P0P1")])) + (match_operand 5 "const_int_operand" "n")] UNSPEC_MUL_WITH_FLAG))] "" { const char *templates[] = { - "%h0 = %h1 * %h2 %M6%!", - "%d0 = %h1 * %h2 %M6%!", - "%h0 = %d1 * %h2 %M6%!", - "%d0 = %d1 * %h2 %M6%!", - "%h0 = %h1 * %d2 %M6%!", - "%d0 = %h1 * %d2 %M6%!", - "%h0 = %d1 * %d2 %M6%!", - "%d0 = %d1 * %d2 %M6%!" }; - int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1) - + (INTVAL (operands[5]) << 2); + "%h0 = %h1 * %h2 %M5%!", + "%h0 = %d1 * %h2 %M5%!", + "%h0 = %h1 * %d2 %M5%!", + "%h0 = %d1 * %d2 %M5%!" }; + int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1); return templates[alt]; } [(set_attr "type" "dsp32")]) @@ -4207,7 +4139,7 @@ %0 = ASHIFT %1 BY %h2 (V, S)%! %0 = %1 << %2 (V,S)%! %0 = %1 >>> %N2 (V,S)%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")]) (define_insn "ssashifthi3" [(set (match_operand:HI 0 "register_operand" "=d,d,d") @@ -4221,7 +4153,7 @@ %0 = ASHIFT %1 BY %h2 (V, S)%! %0 = %1 << %2 (V,S)%! %0 = %1 >>> %N2 (V,S)%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")]) (define_insn "ssashiftsi3" [(set (match_operand:SI 0 "register_operand" "=d,d,d") @@ -4235,7 +4167,7 @@ %0 = ASHIFT %1 BY %h2 (S)%! %0 = %1 << %2 (S)%! %0 = %1 >>> %N2 (S)%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")]) (define_insn "lshiftv2hi3" [(set (match_operand:V2HI 0 "register_operand" "=d,d,d") @@ -4249,7 +4181,7 @@ %0 = LSHIFT %1 BY %h2 (V)%! %0 = %1 << %2 (V)%! %0 = %1 >> %N2 (V)%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")]) (define_insn "lshifthi3" [(set (match_operand:HI 0 "register_operand" "=d,d,d") @@ -4263,7 +4195,7 @@ %0 = LSHIFT %1 BY %h2 (V)%! %0 = %1 << %2 (V)%! %0 = %1 >> %N2 (V)%!" - [(set_attr "type" "dsp32")]) + [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")]) ;; Load without alignment exception (masking off low bits) @@ -4275,3 +4207,5 @@ "DISALGNEXCPT || %0 = [%1];" [(set_attr "type" "mcld") (set_attr "length" "8")]) + +(include "sync.md")