--- gcc/config/pa/pa.md 2018/04/24 18:10:27 1.1 +++ gcc/config/pa/pa.md 2018/04/24 18:23:31 1.1.1.3 @@ -30,51 +30,77 @@ ;; type "binary" insns have two input operands (1,2) and one output (0) (define_attr "type" - "move,unary,binary,compare,load,store,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmul,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,misc,milli" + "move,unary,binary,compare,load,store,uncond_branch,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmul,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,misc,milli" (const_string "binary")) ;; Length (in # of insns). (define_attr "length" "" (cond [(eq_attr "type" "load,fpload") (if_then_else (match_operand 1 "symbolic_memory_operand" "") - (const_int 2) (const_int 1)) + (const_int 8) (const_int 4)) (eq_attr "type" "store,fpstore") (if_then_else (match_operand 0 "symbolic_memory_operand" "") - (const_int 2) (const_int 1)) + (const_int 8) (const_int 4)) (eq_attr "type" "binary") (if_then_else (match_operand 2 "arith_operand" "") - (const_int 1) (const_int 3)) + (const_int 4) (const_int 12)) (eq_attr "type" "move,unary") (if_then_else (match_operand 1 "arith_operand" "") - (const_int 1) (const_int 2))] + (const_int 4) (const_int 8))] - (const_int 1))) + (const_int 4))) (define_asm_attributes - [(set_attr "length" "1") + [(set_attr "length" "4") (set_attr "type" "multi")]) ;; Attributes for instruction and branch scheduling +;; For conditional branches. (define_attr "in_branch_delay" "false,true" - (if_then_else (and (eq_attr "type" "!branch,cbranch,fbranch,call,dyncall,multi,milli") - (eq_attr "length" "1")) + (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli") + (eq_attr "length" "4")) (const_string "true") (const_string "false"))) ;; Disallow instructions which use the FPU since they will tie up the FPU ;; even if the instruction is nullified. (define_attr "in_nullified_branch_delay" "false,true" - (if_then_else (and (eq_attr "type" "!branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmul,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl") - (eq_attr "length" "1")) + (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmul,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl") + (eq_attr "length" "4")) (const_string "true") (const_string "false"))) -;; Unconditional branch, call, and millicode call delay slot description. -(define_delay (eq_attr "type" "branch,call,milli") +;; For calls and millicode calls. Allow unconditional branches in the +;; delay slot. +(define_attr "in_call_delay" "false,true" + (cond [(and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli") + (eq_attr "length" "4")) + (const_string "true") + (eq_attr "type" "uncond_branch") + (if_then_else (ne (symbol_ref "TARGET_JUMP_IN_DELAY") + (const_int 0)) + (const_string "true") + (const_string "false"))] + (const_string "false"))) + + +;; Unconditional branch and call delay slot description. +(define_delay (eq_attr "type" "uncond_branch,branch,call") + [(eq_attr "in_call_delay" "true") (nil) (nil)]) + +;; millicode call delay slot description. Note it disallows delay slot +;; when TARGET_LONG_CALLS is true. +(define_delay (eq_attr "type" "milli") + [(and (eq_attr "in_call_delay" "true") + (eq (symbol_ref "TARGET_LONG_CALLS") (const_int 0))) + (nil) (nil)]) + +;; Unconditional branch, return and other similar instructions. +(define_delay (eq_attr "type" "uncond_branch,branch") [(eq_attr "in_branch_delay" "true") (nil) (nil)]) ;; Floating point conditional branch delay slot description and @@ -85,13 +111,12 @@ ;; Integer conditional branch delay slot description. ;; Nullification of conditional branches on the PA is dependent on the -;; direction of the branch. Forward branches nullify true (direction > 0), -;; and backward branches nullify false (direction < 0). -;; If direction == 0, then the direction is unknown and we do not allow -;; any nullification. +;; direction of the branch. Forward branches nullify true and +;; backward branches nullify false. If the direction is unknown +;; then nullification is not allowed. (define_delay (eq_attr "type" "cbranch") - [(eq_attr "in_branch_delay" "true") - (and (eq_attr "in_nullified_branch_delay" "true") + [(eq_attr "in_branch_delay" "true") + (and (eq_attr "in_nullified_branch_delay" "true") (attr_flag "forward")) (and (eq_attr "in_nullified_branch_delay" "true") (attr_flag "backward"))]) @@ -196,22 +221,22 @@ }") (define_insn "" - [(set (reg:CCFP 0) - (match_operator:CCFP 2 "comparison_operator" - [(match_operand:SF 0 "reg_or_0_operand" "fxG") - (match_operand:SF 1 "reg_or_0_operand" "fxG")]))] - "" - "fcmp,sgl,%Y2 %r0,%r1" - [(set_attr "type" "fpcc")]) - -(define_insn "" - [(set (reg:CCFP 0) - (match_operator:CCFP 2 "comparison_operator" - [(match_operand:DF 0 "reg_or_0_operand" "fxG") - (match_operand:DF 1 "reg_or_0_operand" "fxG")]))] - "" - "fcmp,dbl,%Y2 %r0,%r1" - [(set_attr "type" "fpcc")]) + [(set (reg:CCFP 0) + (match_operator:CCFP 2 "comparison_operator" + [(match_operand:SF 0 "reg_or_0_operand" "fG") + (match_operand:SF 1 "reg_or_0_operand" "fG")]))] + "" + "fcmp,sgl,%Y2 %r0,%r1" + [(set_attr "type" "fpcc")]) + +(define_insn "" + [(set (reg:CCFP 0) + (match_operator:CCFP 2 "comparison_operator" + [(match_operand:DF 0 "reg_or_0_operand" "fG") + (match_operand:DF 1 "reg_or_0_operand" "fG")]))] + "" + "fcmp,dbl,%Y2 %r0,%r1" + [(set_attr "type" "fpcc")]) ;; scc insns. @@ -360,23 +385,36 @@ [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 3 "comparison_operator" [(match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "arith11_operand" "rI")]))] + (match_operand:SI 2 "arith11_operand" "rI")]))] "" "com%I2clr,%B3 %2,%1,%0\;ldi 1,%0" [(set_attr "type" "binary") - (set_attr "length" "2")]) + (set_attr "length" "8")]) + +(define_insn "iorscc" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (match_operator:SI 3 "comparison_operator" + [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "arith11_operand" "rI")]) + (match_operator:SI 6 "comparison_operator" + [(match_operand:SI 4 "register_operand" "r") + (match_operand:SI 5 "arith11_operand" "rI")])))] + "" + "com%I2clr,%S3 %2,%1,0\;com%I5clr,%B6 %5,%4,%0\;ldi 1,%0" + [(set_attr "type" "binary") + (set_attr "length" "8")]) ;; Combiner patterns for common operations performed with the output -;; from an scc insn (negscc and incscc). +;; from an scc insn (negscc and incscc). (define_insn "negscc" [(set (match_operand:SI 0 "register_operand" "=r") - (neg (match_operator:SI 3 "comparison_operator" + (neg:SI (match_operator:SI 3 "comparison_operator" [(match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "arith11_operand" "rI")])))] + (match_operand:SI 2 "arith11_operand" "rI")])))] "" "com%I2clr,%B3 %2,%1,%0\;ldi -1,%0" [(set_attr "type" "binary") - (set_attr "length" "2")]) + (set_attr "length" "8")]) ;; Patterns for adding/subtracting the result of a boolean expression from ;; a register. First we have special patterns that make use of the carry @@ -392,7 +430,7 @@ "" "sub%I3 %3,%2,0\;addc 0,%1,%0" [(set_attr "type" "binary") - (set_attr "length" "2")]) + (set_attr "length" "8")]) ; This need only accept registers for op3, since canonicalization ; replaces geu with gtu when op3 is an integer. @@ -404,7 +442,7 @@ "" "sub %2,%3,0\;addc 0,%1,%0" [(set_attr "type" "binary") - (set_attr "length" "2")]) + (set_attr "length" "8")]) ; Match only integers for op3 here. This is used as canonical form of the ; geu pattern when op3 is an integer. Don't match registers since we can't @@ -417,7 +455,7 @@ "" "addi %k3,%2,0\;addc 0,%1,%0" [(set_attr "type" "binary") - (set_attr "length" "2")]) + (set_attr "length" "8")]) (define_insn "incscc" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -430,7 +468,7 @@ com%I3clr,%B4 %3,%2,0\;addi 1,%0,%0 com%I3clr,%B4 %3,%2,0\;addi,tr 1,%1,%0\;copy %1,%0" [(set_attr "type" "binary,binary") - (set_attr "length" "2,3")]) + (set_attr "length" "8,12")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -440,7 +478,18 @@ "" "sub%I3 %3,%2,0\;subb %1,0,%0" [(set_attr "type" "binary") - (set_attr "length" "2")]) + (set_attr "length" "8")]) + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") + (gtu:SI (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "arith11_operand" "rI"))) + (match_operand:SI 4 "register_operand" "r")))] + "" + "sub%I3 %3,%2,0\;subb %1,%4,%0" + [(set_attr "type" "binary") + (set_attr "length" "8")]) ; This need only accept registers for op3, since canonicalization ; replaces ltu with leu when op3 is an integer. @@ -452,7 +501,18 @@ "" "sub %2,%3,0\;subb %1,0,%0" [(set_attr "type" "binary") - (set_attr "length" "2")]) + (set_attr "length" "8")]) + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") + (ltu:SI (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "register_operand" "r"))) + (match_operand:SI 4 "register_operand" "r")))] + "" + "sub %2,%3,0\;subb %1,%4,%0" + [(set_attr "type" "binary") + (set_attr "length" "8")]) ; Match only integers for op3 here. This is used as canonical form of the ; ltu pattern when op3 is an integer. Don't match registers since we can't @@ -465,7 +525,18 @@ "" "addi %k3,%2,0\;subb %1,0,%0" [(set_attr "type" "binary") - (set_attr "length" "2")]) + (set_attr "length" "8")]) + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (minus:SI (match_operand:SI 1 "register_operand" "r") + (leu:SI (match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "int11_operand" "I"))) + (match_operand:SI 4 "register_operand" "r")))] + "" + "addi %k3,%2,0\;subb %1,%4,%0" + [(set_attr "type" "binary") + (set_attr "length" "8")]) (define_insn "decscc" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -478,7 +549,7 @@ com%I3clr,%B4 %3,%2,0\;addi -1,%0,%0 com%I3clr,%B4 %3,%2,0\;addi,tr -1,%1,%0\;copy %1,%0" [(set_attr "type" "binary,binary") - (set_attr "length" "2,3")]) + (set_attr "length" "8,12")]) ; Patterns for max and min. (There is no need for an earlyclobber in the ; last alternative since the middle alternative will match if op0 == op1.) @@ -493,7 +564,7 @@ comiclr,> %2,%0,0\;ldi %2,%0 comclr,> %1,%2,%0\;copy %1,%0" [(set_attr "type" "multi,multi,multi") - (set_attr "length" "2,2,2")]) + (set_attr "length" "8,8,8")]) (define_insn "uminsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -504,7 +575,7 @@ comclr,>> %2,%0,0\;copy %2,%0 comiclr,>> %2,%0,0\;ldi %2,%0" [(set_attr "type" "multi,multi") - (set_attr "length" "2,2")]) + (set_attr "length" "8,8")]) (define_insn "smaxsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r") @@ -516,7 +587,7 @@ comiclr,< %2,%0,0\;ldi %2,%0 comclr,< %1,%2,%0\;copy %1,%0" [(set_attr "type" "multi,multi,multi") - (set_attr "length" "2,2,2")]) + (set_attr "length" "8,8,8")]) (define_insn "umaxsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -527,7 +598,7 @@ comclr,<< %2,%0,0\;copy %2,%0 comiclr,<< %2,%0,0\;ldi %2,%0" [(set_attr "type" "multi,multi") - (set_attr "length" "2,2")]) + (set_attr "length" "8,8")]) ;;; Experimental conditional move patterns ; We need the first constraint alternative in order to avoid @@ -548,7 +619,7 @@ com%I4clr,%B5 %4,%3,%0\;ldil L'%1,%0 com%I4clr,%B5 %4,%3,%0\;zdepi %Z1,%0" [(set_attr "type" "multi,multi,multi,multi,multi") - (set_attr "length" "2,2,2,2,2")]) + (set_attr "length" "8,8,8,8,8")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r") @@ -569,7 +640,7 @@ com%I4clr,%B5 %4,%3,0\;ldil L'%1,%0 com%I4clr,%B5 %4,%3,0\;zdepi %Z1,%0" [(set_attr "type" "multi,multi,multi,multi,multi,multi,multi,multi") - (set_attr "length" "2,2,2,2,2,2,2,2")]) + (set_attr "length" "8,8,8,8,8,8,8,8")]) ;; Conditional Branches @@ -743,7 +814,7 @@ ;; Note a long backward conditional branch with an annulled delay slot -;; has a length of 3. +;; has a length of 12. (define_insn "" [(set (pc) (if_then_else @@ -755,19 +826,15 @@ "" "* { - return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn), + return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn), get_attr_length (insn), 0, insn); }" [(set_attr "type" "cbranch") - (set (attr "length") - (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2)))) - (const_int 1023)) - (const_int 1) - (and (lt (match_dup 0) (pc)) - (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)") - (const_int 1))) - (const_int 3)] - (const_int 2)))]) + (set (attr "length") + (if_then_else (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4) + (const_int 8)))]) ;; Match the negated branch. @@ -782,19 +849,15 @@ "" "* { - return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn), + return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn), get_attr_length (insn), 1, insn); }" [(set_attr "type" "cbranch") - (set (attr "length") - (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2)))) - (const_int 1023)) - (const_int 1) - (and (lt (match_dup 0) (pc)) - (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)") - (const_int 1))) - (const_int 3)] - (const_int 2)))]) + (set (attr "length") + (if_then_else (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4) + (const_int 8)))]) ;; Branch on Bit patterns. (define_insn "" @@ -809,21 +872,17 @@ "" "* { - return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), + return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), + get_attr_length (insn), (operands[3] != pc_rtx), insn, 0); }" [(set_attr "type" "cbranch") - (set (attr "length") - (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2)))) - (const_int 1023)) - (const_int 1) - (and (lt (match_dup 0) (pc)) - (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)") - (const_int 1))) - (const_int 3)] - (const_int 2)))]) + (set (attr "length") + (if_then_else (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4) + (const_int 8)))]) (define_insn "" [(set (pc) @@ -837,24 +896,19 @@ "" "* { - return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), + return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), + get_attr_length (insn), (operands[3] != pc_rtx), insn, 1); }" [(set_attr "type" "cbranch") - (set (attr "length") - (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2)))) - (const_int 1023)) - (const_int 1) - (and (lt (match_dup 0) (pc)) - (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)") - (const_int 1))) - (const_int 3)] - (const_int 2)))]) + (set (attr "length") + (if_then_else (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4) + (const_int 8)))]) ;; Floating point branches - (define_insn "" [(set (pc) (if_then_else (ne (reg:CCFP 0) (const_int 0)) (label_ref (match_operand 0 "" "")) @@ -868,7 +922,7 @@ return \"ftest\;bl%* %0,0\"; }" [(set_attr "type" "fbranch") - (set_attr "length" "2")]) + (set_attr "length" "8")]) (define_insn "" [(set (pc) (if_then_else (ne (reg:CCFP 0) (const_int 0)) @@ -883,7 +937,7 @@ return \"ftest\;add,tr 0,0,0\;bl%* %0,0\"; }" [(set_attr "type" "fbranch") - (set_attr "length" "3")]) + (set_attr "length" "12")]) ;; Move instructions @@ -902,7 +956,7 @@ (define_expand "reload_insi" [(set (match_operand:SI 0 "register_operand" "=Z") - (match_operand:SI 1 "general_operand" "")) + (match_operand:SI 1 "non_hard_reg_operand" "")) (clobber (match_operand:SI 2 "register_operand" "=&r"))] "" " @@ -916,7 +970,7 @@ }") (define_expand "reload_outsi" - [(set (match_operand:SI 0 "general_operand" "") + [(set (match_operand:SI 0 "non_hard_reg_operand" "") (match_operand:SI 1 "register_operand" "Z")) (clobber (match_operand:SI 2 "register_operand" "=&r"))] "" @@ -939,17 +993,17 @@ "flag_pic && operands[1] == pic_offset_table_rtx" "ldw T'%2(%1),%0" [(set_attr "type" "load") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" - [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" - "=r,r,r,r,r,Q,*q,!fx,fx,*T") - (match_operand:SI 1 "move_operand" - "rM,J,N,K,Q,rM,rM,!fxM,*T,fx"))] + [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" + "=r,r,r,r,r,Q,*q,!f,f,*T") + (match_operand:SI 1 "move_operand" + "r,J,N,K,Q,rM,rM,!fM,*T,f"))] "register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode)" "@ - copy %r1,%0 + copy %1,%0 ldi %1,%0 ldil L'%1,%0 zdepi %Z1,%0 @@ -960,7 +1014,7 @@ fldws%F1 %1,%0 fstws%F0 %1,%0" [(set_attr "type" "move,move,move,move,load,store,move,fpalu,fpload,fpstore") - (set_attr "length" "1,1,1,1,1,1,1,1,1,1")]) + (set_attr "length" "4,4,4,4,4,4,4,4,4,4")]) ;; Load indexed. We don't use unscaled modes since they can't be used ;; unless we can tell which of the registers is the base and which is @@ -975,7 +1029,33 @@ "! TARGET_DISABLE_INDEXING" "ldwx,s %1(0,%2),%0" [(set_attr "type" "load") - (set_attr "length" "1")]) + (set_attr "length" "4")]) + +;; This variant of the above insn can occur if the second operand +;; is the frame pointer. This is a kludge, but there doesn't +;; seem to be a way around it. Only recognize it while reloading. +;; Note how operand 3 uses a predicate of "const_int_operand", but +;; has constraints allowing a register. I don't know how this works, +;; but it somehow makes sure that out-of-range constants are placed +;; in a register which somehow magically is a "const_int_operand". +;; (this was stolen from alpha.md, I'm not going to try and change it. +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "&=r") + (mem:SI (plus:SI (plus:SI + (mult:SI (match_operand:SI 1 "register_operand" "r") + (const_int 4)) + (match_operand:SI 2 "register_operand" "r")) + (match_operand:SI 3 "const_int_operand" "rI"))))] + "! TARGET_DISABLE_INDEXING && reload_in_progress" + "* +{ + if (GET_CODE (operands[3]) == CONST_INT) + return \"sh2addl %1,%2,%0\;ldw %3(0,%0),%0\"; + else + return \"sh2addl %1,%2,%0\;ldwx %3(0,%0),%0\"; +}" + [(set_attr "type" "load") + (set_attr "length" "8")]) ;; Load or store with base-register modification. @@ -993,7 +1073,7 @@ return \"ldws,mb %2(0,%0),%3\"; }" [(set_attr "type" "load") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "pre_stwm" [(set (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "0") @@ -1009,13 +1089,13 @@ return \"stws,mb %r3,%2(0,%0)\"; }" [(set_attr "type" "store") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "post_ldwm" [(set (match_operand:SI 3 "register_operand" "r") (mem:SI (match_operand:SI 1 "register_operand" "0"))) (set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (match_dup 1) + (plus:SI (match_dup 1) (match_operand:SI 2 "post_cint_operand" "")))] "" "* @@ -1025,13 +1105,13 @@ return \"ldws,ma %2(0,%0),%3\"; }" [(set_attr "type" "load") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "post_stwm" [(set (mem:SI (match_operand:SI 1 "register_operand" "0")) (match_operand:SI 3 "reg_or_0_operand" "rM")) (set (match_operand:SI 0 "register_operand" "=r") - (plus:SI (match_dup 1) + (plus:SI (match_dup 1) (match_operand:SI 2 "post_cint_operand" "")))] "" "* @@ -1041,7 +1121,7 @@ return \"stws,ma %r3,%2(0,%0)\"; }" [(set_attr "type" "store") - (set_attr "length" "1")]) + (set_attr "length" "4")]) ;; For pic (define_insn "" @@ -1065,107 +1145,105 @@ } " [(set_attr "type" "multi") - (set_attr "length" "3")]) + (set_attr "length" "12")]) -;; For kernel code always use addil; else we can lose due to a linker -;; bug involving absolute symbols and "ldil;add" style relocations +;; Always use addil rather than ldil;add sequences. This allows the +;; HP linker to eliminate the dp relocation if the symbolic operand +;; lives in the TEXT space. (define_insn "" [(set (match_operand:SI 0 "register_operand" "=a") (high:SI (match_operand 1 "" "")))] - "TARGET_KERNEL && symbolic_operand(operands[1], Pmode) + "symbolic_operand (operands[1], Pmode) && ! function_label_operand (operands[1]) && ! read_only_operand (operands[1])" "@ addil L'%G1,%%r27" [(set_attr "type" "binary") - (set_attr "length" "1")]) - -;; For all symbolic operands *except* function addresses and read-only -;; operands (which live in TEXT space and do not require relocation). -;; -;; The constraints are a little strange. -;; The basic idea is to prefer %r1 as much as possible for register -;; allocation (hence we do not allow regclass to know about the general -;; register case (via *r). -;; We also want to avoid spilling %r1 as that will cause every use -;; of %r1 to be reloaded, so we make the %r1 case very expensive -;; as far as reload is concerned (via !a). -;; -;; The real solution is to not spill all pseudos allocated to %r1 -;; when %r1 is needed as a spill register, but that is considerably -;; more difficult than coercing decent behavior via constraints. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=!a,*r") - (high:SI (match_operand 1 "" "")))] - "! TARGET_KERNEL && symbolic_operand(operands[1], Pmode) - && ! function_label_operand (operands[1]) - && ! read_only_operand (operands[1])" - "@ - addil L'%G1,%%r27 - ldil L'%G1,%0\;add %0,%%r27,%0" - [(set_attr "type" "binary,binary") - (set_attr "length" "1,2")]) + (set_attr "length" "4")]) -;; This is for use in the prologue/epilogue code. We need it +;; This is for use in the prologue/epilogue code. We need it ;; to add large constants to a stack pointer or frame pointer. ;; Because of the additional %r1 pressure, we probably do not ;; want to use this in general code, so make it available ;; only after reload. (define_insn "add_high_const" [(set (match_operand:SI 0 "register_operand" "=!a,*r") - (plus (match_operand:SI 1 "register_operand" "r,r") - (high:SI (match_operand 2 "const_int_operand" ""))))] + (plus:SI (match_operand:SI 1 "register_operand" "r,r") + (high:SI (match_operand 2 "const_int_operand" ""))))] "reload_completed" "@ addil L'%G2,%1 - ldil L'%G2,%0\;add %0,%1,%0" + ldil L'%G2,%0\;addl %0,%1,%0" [(set_attr "type" "binary,binary") - (set_attr "length" "1,2")]) + (set_attr "length" "4,8")]) -;; For function addresses when TARGET_SHARED_LIBS +;; For function addresses. (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (high:SI (match_operand:SI 1 "function_label_operand" "")))] - "TARGET_SHARED_LIBS" + "!TARGET_PORTABLE_RUNTIME" "ldil LP'%G1,%0" [(set_attr "type" "move") - (set_attr "length" "1")]) + (set_attr "length" "4")]) + +;; This version is used only for the portable runtime conventions model +;; (it does not use/support plabels) +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (high:SI (match_operand:SI 1 "function_label_operand" "")))] + "TARGET_PORTABLE_RUNTIME" + "ldil L'%G1,%0" + [(set_attr "type" "move") + (set_attr "length" "4")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (high:SI (match_operand 1 "" "")))] - "check_pic (1)" + "check_pic (1) && !is_function_label_plus_const (operands[1])" "ldil L'%G1,%0" [(set_attr "type" "move") - (set_attr "length" "1")]) + (set_attr "length" "4")]) + +;; lo_sum of a function address. +;; +;; Note since we are not supporting MPE style external calls we can +;; use the short ldil;ldo sequence. If one wanted to support +;; MPE external calls you would want to generate something like +;; ldil;ldo;extru;ldw;add. See the HP compiler's output for details. +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (lo_sum:SI (match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "function_label_operand" "")))] + "!TARGET_PORTABLE_RUNTIME" + "ldo RP'%G2(%1),%0" + [(set_attr "length" "4")]) -;; lo_sum of a function address when TARGET_SHARED_LIBS +;; This version is used only for the portable runtime conventions model +;; (it does not use/support plabels) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "function_label_operand" ""))) - (clobber (match_operand:SI 3 "register_operand" "=r"))] - "TARGET_SHARED_LIBS" - "ldo RP'%G2(%1),%0\;extru,= %0,31,1,%3\;ldw -4(0,%%r27),%3\;add %0,%3,%0" - [(set_attr "type" "multi") - (set_attr "length" "4")]) + (match_operand:SI 2 "function_label_operand" "")))] + "TARGET_PORTABLE_RUNTIME" + "ldo R'%G2(%1),%0" + [(set_attr "length" "4")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (lo_sum:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "immediate_operand" "i")))] - "" + "!is_function_label_plus_const (operands[2])" "ldo R'%G2(%1),%0" - [(set_attr "length" "1")]) + [(set_attr "length" "4")]) ;; Now that a symbolic_address plus a constant is broken up early ;; in the compilation phase (for better CSE) we need a special ;; combiner pattern to load the symbolic address plus the constant -;; in only 2 instructions. (For cases where the symbolic address +;; in only 2 instructions. (For cases where the symbolic address ;; was not a common subexpression.) (define_split [(set (match_operand:SI 0 "register_operand" "") - (match_operand 1 "symbolic_operand" "")) + (match_operand:SI 1 "symbolic_operand" "")) (clobber (match_operand:SI 2 "register_operand" ""))] "" [(set (match_dup 2) (high:SI (match_dup 1))) @@ -1183,12 +1261,12 @@ }") (define_insn "" - [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,*q,!fx") - (match_operand:HI 1 "move_operand" "rM,J,N,K,Q,rM,rM,!fxM"))] + [(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,*q,!f") + (match_operand:HI 1 "move_operand" "r,J,N,K,Q,rM,rM,!fM"))] "register_operand (operands[0], HImode) || reg_or_0_operand (operands[1], HImode)" "@ - copy %r1,%0 + copy %1,%0 ldi %1,%0 ldil L'%1,%0 zdepi %Z1,%0 @@ -1197,7 +1275,7 @@ mtsar %r1 fcpy,sgl %r1,%0" [(set_attr "type" "move,move,move,move,load,store,move,fpalu") - (set_attr "length" "1,1,1,1,1,1,1,1")]) + (set_attr "length" "4,4,4,4,4,4,4,4")]) (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") @@ -1207,7 +1285,33 @@ "! TARGET_DISABLE_INDEXING" "ldhx,s %2(0,%1),%0" [(set_attr "type" "load") - (set_attr "length" "1")]) + (set_attr "length" "4")]) + +;; This variant of the above insn can occur if the second operand +;; is the frame pointer. This is a kludge, but there doesn't +;; seem to be a way around it. Only recognize it while reloading. +;; Note how operand 3 uses a predicate of "const_int_operand", but +;; has constraints allowing a register. I don't know how this works, +;; but it somehow makes sure that out-of-range constants are placed +;; in a register which somehow magically is a "const_int_operand". +;; (this was stolen from alpha.md, I'm not going to try and change it. +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=&r") + (mem:HI (plus:SI (plus:SI + (mult:SI (match_operand:SI 2 "register_operand" "r") + (const_int 2)) + (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 3 "const_int_operand" "rI"))))] + "! TARGET_DISABLE_INDEXING && reload_in_progress" + "* +{ + if (GET_CODE (operands[3]) == CONST_INT) + return \"sh1addl %2,%1,%0\;ldh %3(0,%0),%0\"; + else + return \"sh1addl %2,%1,%0\;ldhx %3(0,%0),%0\"; +}" + [(set_attr "type" "load") + (set_attr "length" "8")]) (define_insn "" [(set (match_operand:HI 3 "register_operand" "=r") @@ -1218,7 +1322,7 @@ "" "ldhs,mb %2(0,%0),%3" [(set_attr "type" "load") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "0") @@ -1229,7 +1333,7 @@ "" "sths,mb %r3,%2(0,%0)" [(set_attr "type" "store") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") @@ -1237,7 +1341,7 @@ "check_pic (1)" "ldil L'%G1,%0" [(set_attr "type" "move") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") @@ -1245,7 +1349,7 @@ (match_operand 2 "immediate_operand" "i")))] "" "ldo R'%G2(%1),%0" - [(set_attr "length" "1")]) + [(set_attr "length" "4")]) (define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") @@ -1258,12 +1362,12 @@ }") (define_insn "" - [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,*q,!fx") - (match_operand:QI 1 "move_operand" "rM,J,N,K,Q,rM,rM,!fxM"))] + [(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,*q,!f") + (match_operand:QI 1 "move_operand" "r,J,N,K,Q,rM,rM,!fM"))] "register_operand (operands[0], QImode) || reg_or_0_operand (operands[1], QImode)" "@ - copy %r1,%0 + copy %1,%0 ldi %1,%0 ldil L'%1,%0 zdepi %Z1,%0 @@ -1272,7 +1376,7 @@ mtsar %r1 fcpy,sgl %r1,%0" [(set_attr "type" "move,move,move,move,load,store,move,fpalu") - (set_attr "length" "1,1,1,1,1,1,1,1")]) + (set_attr "length" "4,4,4,4,4,4,4,4")]) (define_insn "" [(set (match_operand:QI 3 "register_operand" "=r") @@ -1283,7 +1387,7 @@ "" "ldbs,mb %2(0,%0),%3" [(set_attr "type" "load") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "0") @@ -1294,15 +1398,15 @@ "" "stbs,mb %r3,%2(0,%0)" [(set_attr "type" "store") - (set_attr "length" "1")]) + (set_attr "length" "4")]) ;; The definition of this insn does not really explain what it does, ;; but it should suffice ;; that anything generated as this insn will be recognized as one ;; and that it will not successfully combine with anything. (define_expand "movstrsi" - [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "")) - (mem:BLK (match_operand:BLK 1 "general_operand" ""))) + [(parallel [(set (mem:BLK (match_operand:BLK 0 "" "")) + (mem:BLK (match_operand:BLK 1 "" ""))) (clobber (match_dup 0)) (clobber (match_dup 1)) (clobber (match_dup 4)) @@ -1318,7 +1422,7 @@ runtime and make the optimal decisions. */ if (INTVAL (operands[3]) < 4 && (GET_CODE (operands[2]) != CONST_INT - || (INTVAL (operands[2]) / INTVAL (operands[3]) > 16))) + || (INTVAL (operands[2]) / INTVAL (operands[3]) > 8))) FAIL; operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0)); @@ -1353,18 +1457,18 @@ ;; ;; For integer registers we use ldil;ldo to set the appropriate ;; value. -;; +;; ;; This must come before the movdf pattern, and it must be present ;; to handle obscure reloading cases. (define_insn "" - [(set (match_operand:DF 0 "general_operand" "=?r,fx") + [(set (match_operand:DF 0 "general_operand" "=?r,f") (match_operand:DF 1 "" "?E,m"))] "GET_CODE (operands[1]) == CONST_DOUBLE && operands[1] != CONST0_RTX (DFmode)" "* return (which_alternative == 0 ? output_move_double (operands) : \" fldds%F1 %1,%0\");" [(set_attr "type" "move,fpload") - (set_attr "length" "4,1")]) + (set_attr "length" "16,4")]) (define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") @@ -1376,42 +1480,133 @@ DONE; }") +;; Reloading an SImode or DImode value requires a scratch register if +;; going in to or out of float point registers. + +(define_expand "reload_indf" + [(set (match_operand:DF 0 "register_operand" "=Z") + (match_operand:DF 1 "non_hard_reg_operand" "")) + (clobber (match_operand:DF 2 "register_operand" "=&r"))] + "" + " +{ + if (emit_move_sequence (operands, DFmode, operands[2])) + DONE; + + /* We don't want the clobber emitted, so handle this ourselves. */ + emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); + DONE; +}") + +(define_expand "reload_outdf" + [(set (match_operand:DF 0 "non_hard_reg_operand" "") + (match_operand:DF 1 "register_operand" "Z")) + (clobber (match_operand:DF 2 "register_operand" "=&r"))] + "" + " +{ + if (emit_move_sequence (operands, DFmode, operands[2])) + DONE; + + /* We don't want the clobber emitted, so handle this ourselves. */ + emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); + DONE; +}") + (define_insn "" [(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand" - "=fx,*r,Q,?Q,fx,*&r") + "=f,*r,Q,?o,?Q,f,*&r,*&r") (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand" - "fxG,*rG,fx,*r,Q,Q"))] + "fG,*rG,f,*r,*r,Q,o,Q"))] "register_operand (operands[0], DFmode) || reg_or_0_operand (operands[1], DFmode)" "* { - if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]) + if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]) || operands[1] == CONST0_RTX (DFmode)) return output_fp_move_double (operands); return output_move_double (operands); }" - [(set_attr "type" "fpalu,move,fpstore,store,fpload,load") - (set_attr "length" "1,2,1,2,1,2")]) + [(set_attr "type" "fpalu,move,fpstore,store,store,fpload,load,load") + (set_attr "length" "4,8,4,8,16,4,8,16")]) (define_insn "" - [(set (match_operand:DF 0 "register_operand" "=fx") + [(set (match_operand:DF 0 "register_operand" "=f") (mem:DF (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") (const_int 8)) (match_operand:SI 2 "register_operand" "r"))))] "! TARGET_DISABLE_INDEXING" "flddx,s %1(0,%2),%0" [(set_attr "type" "fpload") - (set_attr "length" "1")]) + (set_attr "length" "4")]) + +;; This variant of the above insn can occur if the second operand +;; is the frame pointer. This is a kludge, but there doesn't +;; seem to be a way around it. Only recognize it while reloading. +;; Note how operand 3 uses a predicate of "const_int_operand", but +;; has constraints allowing a register. I don't know how this works, +;; but it somehow makes sure that out-of-range constants are placed +;; in a register which somehow magically is a "const_int_operand". +;; (this was stolen from alpha.md, I'm not going to try and change it. +;; Ugh. Output is a FP register; so we need to earlyclobber something +;; else as a temporary. +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f") + (mem:DF (plus:SI + (plus:SI + (mult:SI (match_operand:SI 1 "register_operand" "+&r") + (const_int 8)) + (match_operand:SI 2 "register_operand" "r")) + (match_operand:SI 3 "const_int_operand" "rL"))))] + "! TARGET_DISABLE_INDEXING && reload_in_progress" + "* +{ + if (GET_CODE (operands[3]) == CONST_INT) + return \"sh3addl %1,%2,%1\;fldds %3(0,%1),%0\"; + else + return \"sh3addl %1,%2,%1\;flddx %3(0,%1),%0\"; +}" + [(set_attr "type" "fpload") + (set_attr "length" "8")]) (define_insn "" [(set (mem:DF (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") (const_int 8)) (match_operand:SI 2 "register_operand" "r"))) - (match_operand:DF 0 "register_operand" "fx"))] + (match_operand:DF 0 "register_operand" "f"))] "! TARGET_DISABLE_INDEXING" "fstdx,s %0,%1(0,%2)" [(set_attr "type" "fpstore") - (set_attr "length" "1")]) + (set_attr "length" "4")]) + +;; This variant of the above insn can occur if the second operand +;; is the frame pointer. This is a kludge, but there doesn't +;; seem to be a way around it. Only recognize it while reloading. +;; Note how operand 3 uses a predicate of "const_int_operand", but +;; has constraints allowing a register. I don't know how this works, +;; but it somehow makes sure that out-of-range constants are placed +;; in a register which somehow magically is a "const_int_operand". +;; (this was stolen from alpha.md, I'm not going to try and change it. +;; Ugh. Output is a FP register; so we need to earlyclobber something +;; else as a temporary. +(define_insn "" + [(set (mem:DF (plus:SI + (plus:SI + (mult:SI (match_operand:SI 1 "register_operand" "+&r") + (const_int 8)) + (match_operand:SI 2 "register_operand" "r")) + (match_operand:SI 3 "const_int_operand" "rL"))) + (match_operand:DF 0 "register_operand" "f"))] + "! TARGET_DISABLE_INDEXING && reload_in_progress" + "* +{ + if (GET_CODE (operands[3]) == CONST_INT) + return \"sh3addl %1,%2,%1\;fstds %0,%3(0,%1)\"; + else + return \"sh3addl %1,%2,%1\;fstdx %0,%3(0,%1)\"; +}" + [(set_attr "type" "fpstore") + (set_attr "length" "8")]) (define_expand "movdi" [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "") @@ -1424,8 +1619,8 @@ }") (define_expand "reload_indi" - [(set (match_operand:DI 0 "register_operand" "=z") - (match_operand:DI 1 "general_operand" "")) + [(set (match_operand:DI 0 "register_operand" "=f") + (match_operand:DI 1 "non_hard_reg_operand" "")) (clobber (match_operand:SI 2 "register_operand" "=&r"))] "" " @@ -1440,7 +1635,7 @@ (define_expand "reload_outdi" [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "register_operand" "z")) + (match_operand:DI 1 "register_operand" "f")) (clobber (match_operand:SI 2 "register_operand" "=&r"))] "" " @@ -1489,15 +1684,15 @@ abort (); }" [(set_attr "type" "move") - (set_attr "length" "2")]) + (set_attr "length" "8")]) ;;; Experimental (define_insn "" [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" - "=r,Q,&r,&r,x,x,*T") + "=r,o,Q,&r,&r,&r,f,f,*T") (match_operand:DI 1 "general_operand" - "rM,r,Q,i,xM,*T,x"))] + "rM,r,r,o,Q,i,fM,*T,f"))] "register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode)" "* @@ -1507,11 +1702,11 @@ return output_fp_move_double (operands); return output_move_double (operands); }" - [(set_attr "type" "move,store,load,misc,fpalu,fpload,fpstore") - (set_attr "length" "2,3,3,3,1,1,1")]) + [(set_attr "type" "move,store,store,load,load,misc,fpalu,fpload,fpstore") + (set_attr "length" "8,8,16,8,16,16,4,4,4")]) (define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,r") + [(set (match_operand:DI 0 "register_operand" "=r,&r") (lo_sum:DI (match_operand:DI 1 "register_operand" "0,r") (match_operand:DI 2 "immediate_operand" "i,i")))] "" @@ -1527,7 +1722,7 @@ }" ;; Need to set length for this arith insn because operand2 ;; is not an "arith_operand". - [(set_attr "length" "1,2")]) + [(set_attr "length" "4,8")]) ;; This pattern forces (set (reg:SF ...) (const_double ...)) ;; to be reloaded by putting the constant into memory when @@ -1535,18 +1730,18 @@ ;; ;; For integer registers we use ldil;ldo to set the appropriate ;; value. -;; +;; ;; This must come before the movsf pattern, and it must be present ;; to handle obscure reloading cases. (define_insn "" - [(set (match_operand:SF 0 "general_operand" "=?r,fx") + [(set (match_operand:SF 0 "general_operand" "=?r,f") (match_operand:SF 1 "" "?E,m"))] "GET_CODE (operands[1]) == CONST_DOUBLE && operands[1] != CONST0_RTX (SFmode)" "* return (which_alternative == 0 ? singlemove_string (operands) : \" fldws%F1 %1,%0\");" [(set_attr "type" "move,fpload") - (set_attr "length" "2,1")]) + (set_attr "length" "8,4")]) (define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") @@ -1558,11 +1753,44 @@ DONE; }") +;; Reloading an SImode or DImode value requires a scratch register if +;; going in to or out of float point registers. + +(define_expand "reload_insf" + [(set (match_operand:SF 0 "register_operand" "=Z") + (match_operand:SF 1 "non_hard_reg_operand" "")) + (clobber (match_operand:SF 2 "register_operand" "=&r"))] + "" + " +{ + if (emit_move_sequence (operands, SFmode, operands[2])) + DONE; + + /* We don't want the clobber emitted, so handle this ourselves. */ + emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); + DONE; +}") + +(define_expand "reload_outsf" + [(set (match_operand:SF 0 "non_hard_reg_operand" "") + (match_operand:SF 1 "register_operand" "Z")) + (clobber (match_operand:SF 2 "register_operand" "=&r"))] + "" + " +{ + if (emit_move_sequence (operands, SFmode, operands[2])) + DONE; + + /* We don't want the clobber emitted, so handle this ourselves. */ + emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); + DONE; +}") + (define_insn "" [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" - "=fx,r,fx,r,Q,Q") + "=f,r,f,r,Q,Q") (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand" - "fxG,rG,Q,Q,fx,rG"))] + "fG,rG,Q,Q,f,rG"))] "register_operand (operands[0], SFmode) || reg_or_0_operand (operands[1], SFmode)" "@ @@ -1573,27 +1801,85 @@ fstws%F0 %r1,%0 stw%M0 %r1,%0" [(set_attr "type" "fpalu,move,fpload,load,fpstore,store") - (set_attr "length" "1,1,1,1,1,1")]) + (set_attr "length" "4,4,4,4,4,4")]) (define_insn "" - [(set (match_operand:SF 0 "register_operand" "=fx") + [(set (match_operand:SF 0 "register_operand" "=f") (mem:SF (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") (const_int 4)) (match_operand:SI 2 "register_operand" "r"))))] "! TARGET_DISABLE_INDEXING" "fldwx,s %1(0,%2),%0" [(set_attr "type" "fpload") - (set_attr "length" "1")]) + (set_attr "length" "4")]) + +;; This variant of the above insn can occur if the second operand +;; is the frame pointer. This is a kludge, but there doesn't +;; seem to be a way around it. Only recognize it while reloading. +;; Note how operand 3 uses a predicate of "const_int_operand", but +;; has constraints allowing a register. I don't know how this works, +;; but it somehow makes sure that out-of-range constants are placed +;; in a register which somehow magically is a "const_int_operand". +;; (this was stolen from alpha.md, I'm not going to try and change it. +;; Ugh. Output is a FP register; so we need to earlyclobber something +;; else as a temporary. +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f") + (mem:SF (plus:SI + (plus:SI + (mult:SI (match_operand:SI 1 "register_operand" "+&r") + (const_int 4)) + (match_operand:SI 2 "register_operand" "r")) + (match_operand:SI 3 "const_int_operand" "rL"))))] + "! TARGET_DISABLE_INDEXING && reload_in_progress" + "* +{ + if (GET_CODE (operands[3]) == CONST_INT) + return \"sh2addl %1,%2,%1\;fldws %3(0,%1),%0\"; + else + return \"sh2addl %1,%2,%1\;fldwx %3(0,%1),%0\"; +}" + [(set_attr "type" "fpload") + (set_attr "length" "8")]) (define_insn "" [(set (mem:SF (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") (const_int 4)) (match_operand:SI 2 "register_operand" "r"))) - (match_operand:SF 0 "register_operand" "fx"))] + (match_operand:SF 0 "register_operand" "f"))] "! TARGET_DISABLE_INDEXING" "fstwx,s %0,%1(0,%2)" [(set_attr "type" "fpstore") - (set_attr "length" "1")]) + (set_attr "length" "4")]) + +;; This variant of the above insn can occur if the second operand +;; is the frame pointer. This is a kludge, but there doesn't +;; seem to be a way around it. Only recognize it while reloading. +;; Note how operand 3 uses a predicate of "const_int_operand", but +;; has constraints allowing a register. I don't know how this works, +;; but it somehow makes sure that out-of-range constants are placed +;; in a register which somehow magically is a "const_int_operand". +;; (this was stolen from alpha.md, I'm not going to try and change it. +;; Ugh. Output is a FP register; so we need to earlyclobber something +;; else as a temporary. +(define_insn "" + [(set (mem:SF (plus:SI + (plus:SI + (mult:SI (match_operand:SI 1 "register_operand" "+&r") + (const_int 4)) + (match_operand:SI 2 "register_operand" "r")) + (match_operand:SI 3 "const_int_operand" "rL"))) + (match_operand:SF 0 "register_operand" "f"))] + "! TARGET_DISABLE_INDEXING && reload_in_progress" + "* +{ + if (GET_CODE (operands[3]) == CONST_INT) + return \"sh2addl %1,%2,%1\;fstws %0,%3(0,%1)\"; + else + return \"sh2addl %1,%2,%1\;fstwx %0,%3(0,%1)\"; +}" + [(set_attr "type" "fpstore") + (set_attr "length" "8")]) ;;- zero extension instructions @@ -1615,8 +1901,7 @@ "@ extru %1,31,8,%0 ldb%M1 %1,%0" - [(set_attr "type" "unary,load") - (set_attr "length" "1,1")]) + [(set_attr "type" "unary,load")]) (define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -1626,8 +1911,7 @@ "@ extru %1,31,8,%0 ldb%M1 %1,%0" - [(set_attr "type" "unary,load") - (set_attr "length" "1,1")]) + [(set_attr "type" "unary,load")]) ;;- sign extension instructions @@ -1655,17 +1939,17 @@ ;; Conversions between float and double. (define_insn "extendsfdf2" - [(set (match_operand:DF 0 "register_operand" "=fx") + [(set (match_operand:DF 0 "register_operand" "=f") (float_extend:DF - (match_operand:SF 1 "register_operand" "fx")))] + (match_operand:SF 1 "register_operand" "f")))] "" "fcnvff,sgl,dbl %1,%0" [(set_attr "type" "fpalu")]) (define_insn "truncdfsf2" - [(set (match_operand:SF 0 "register_operand" "=fx") + [(set (match_operand:SF 0 "register_operand" "=f") (float_truncate:SF - (match_operand:DF 1 "register_operand" "fx")))] + (match_operand:DF 1 "register_operand" "f")))] "" "fcnvff,dbl,sgl %1,%0" [(set_attr "type" "fpalu")]) @@ -1682,39 +1966,37 @@ ;; to be reloaded by putting the constant into memory. ;; It must come before the more general floatsisf2 pattern. (define_insn "" - [(set (match_operand:SF 0 "general_operand" "=fx") + [(set (match_operand:SF 0 "general_operand" "=f") (float:SF (match_operand:SI 1 "const_int_operand" "m")))] "" "fldws %1,%0\;fcnvxf,sgl,sgl %0,%0" [(set_attr "type" "fpalu") - (set_attr "length" "2")]) + (set_attr "length" "8")]) (define_insn "floatsisf2" - [(set (match_operand:SF 0 "general_operand" "=fx") - (float:SF (match_operand:SI 1 "register_operand" "fx")))] + [(set (match_operand:SF 0 "general_operand" "=f") + (float:SF (match_operand:SI 1 "register_operand" "f")))] "" "fcnvxf,sgl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "1")]) + [(set_attr "type" "fpalu")]) ;; This pattern forces (set (reg:DF ...) (float:DF (const_int ...))) ;; to be reloaded by putting the constant into memory. ;; It must come before the more general floatsidf2 pattern. (define_insn "" - [(set (match_operand:DF 0 "general_operand" "=fx") + [(set (match_operand:DF 0 "general_operand" "=f") (float:DF (match_operand:SI 1 "const_int_operand" "m")))] "" "fldws %1,%0\;fcnvxf,sgl,dbl %0,%0" [(set_attr "type" "fpalu") - (set_attr "length" "2")]) + (set_attr "length" "8")]) (define_insn "floatsidf2" - [(set (match_operand:DF 0 "general_operand" "=fx") - (float:DF (match_operand:SI 1 "register_operand" "fx")))] + [(set (match_operand:DF 0 "general_operand" "=f") + (float:DF (match_operand:SI 1 "register_operand" "f")))] "" "fcnvxf,sgl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "1")]) + [(set_attr "type" "fpalu")]) (define_expand "floatunssisf2" [(set (subreg:SI (match_dup 2) 1) @@ -1737,55 +2019,49 @@ "operands[2] = gen_reg_rtx (DImode);") (define_insn "floatdisf2" - [(set (match_operand:SF 0 "general_operand" "=x") - (float:SF (match_operand:DI 1 "register_operand" "x")))] + [(set (match_operand:SF 0 "general_operand" "=f") + (float:SF (match_operand:DI 1 "register_operand" "f")))] "TARGET_SNAKE" "fcnvxf,dbl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "1")]) + [(set_attr "type" "fpalu")]) (define_insn "floatdidf2" - [(set (match_operand:DF 0 "general_operand" "=x") - (float:DF (match_operand:DI 1 "register_operand" "x")))] + [(set (match_operand:DF 0 "general_operand" "=f") + (float:DF (match_operand:DI 1 "register_operand" "f")))] "TARGET_SNAKE" "fcnvxf,dbl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "1")]) + [(set_attr "type" "fpalu")]) ;; Convert a float to an actual integer. ;; Truncation is performed as part of the conversion. (define_insn "fix_truncsfsi2" - [(set (match_operand:SI 0 "register_operand" "=fx") - (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "fx"))))] + [(set (match_operand:SI 0 "register_operand" "=f") + (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] "" "fcnvfxt,sgl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "1")]) + [(set_attr "type" "fpalu")]) (define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "register_operand" "=fx") - (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "fx"))))] + [(set (match_operand:SI 0 "register_operand" "=f") + (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] "" "fcnvfxt,dbl,sgl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "1")]) + [(set_attr "type" "fpalu")]) (define_insn "fix_truncsfdi2" - [(set (match_operand:DI 0 "register_operand" "=x") - (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "x"))))] + [(set (match_operand:DI 0 "register_operand" "=f") + (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] "TARGET_SNAKE" "fcnvfxt,sgl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "1")]) + [(set_attr "type" "fpalu")]) (define_insn "fix_truncdfdi2" - [(set (match_operand:DI 0 "register_operand" "=x") - (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "x"))))] + [(set (match_operand:DI 0 "register_operand" "=f") + (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] "TARGET_SNAKE" "fcnvfxt,dbl,dbl %1,%0" - [(set_attr "type" "fpalu") - (set_attr "length" "1")]) + [(set_attr "type" "fpalu")]) ;;- arithmetic instructions @@ -1806,7 +2082,7 @@ else return \"add %R2,%R1,%R0\;addc %2,%1,%0\"; }" - [(set_attr "length" "2")]) + [(set_attr "length" "8")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -1822,7 +2098,7 @@ (plus:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "const_int_operand" ""))) (clobber (match_operand:SI 4 "register_operand" ""))] - "! cint_ok_for_move (INTVAL (operands[2])) + "! cint_ok_for_move (INTVAL (operands[2])) && VAL_14_BITS_P (INTVAL (operands[2]) >> 1)" [(set (match_dup 4) (plus:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (plus:SI (match_dup 4) (match_dup 3)))] @@ -1847,27 +2123,27 @@ (match_dup 1)))] " { - int intval = INTVAL (operands[2]); + HOST_WIDE_INT intval = INTVAL (operands[2]); - /* Try diving the constant by 2, then 4, and finally 8 to see + /* Try dividing the constant by 2, then 4, and finally 8 to see if we can get a constant which can be loaded into a register in a single instruction (cint_ok_for_move). */ if (intval % 2 == 0 && cint_ok_for_move (intval / 2)) { - operands[2] = GEN_INT (INTVAL (operands[2]) / 2); + operands[2] = GEN_INT (intval / 2); operands[3] = GEN_INT (2); } else if (intval % 4 == 0 && cint_ok_for_move (intval / 4)) { - operands[2] = GEN_INT (INTVAL (operands[2]) / 4); + operands[2] = GEN_INT (intval / 4); operands[3] = GEN_INT (4); } else if (intval % 8 == 0 && cint_ok_for_move (intval / 8)) { - operands[2] = GEN_INT (INTVAL (operands[2]) / 8); + operands[2] = GEN_INT (intval / 8); operands[3] = GEN_INT (8); } - else + else FAIL; }") @@ -1877,7 +2153,7 @@ (match_operand:SI 2 "arith_operand" "r,J")))] "" "@ - add %1,%2,%0 + addl %1,%2,%0 ldo %2(%1),%0") (define_insn "subdi3" @@ -1886,7 +2162,7 @@ (match_operand:DI 2 "register_operand" "r")))] "" "sub %R1,%R2,%R0\;subb %1,%2,%0" - [(set_attr "length" "2")]) + [(set_attr "length" "8")]) (define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -1906,7 +2182,7 @@ [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) (parallel [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_operand:SI 3 "register_operand" "")) + (clobber (match_dup 3)) (clobber (reg:SI 26)) (clobber (reg:SI 25)) (clobber (reg:SI 31))]) @@ -1925,33 +2201,45 @@ gen_rtx (SUBREG, SImode, scratch, 1))); DONE; } - operands[3] = gen_reg_rtx(SImode); + operands[3] = gen_reg_rtx (SImode); }") (define_insn "umulsidi3" - [(set (match_operand:DI 0 "register_operand" "=x") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "x")) - (zero_extend:DI (match_operand:SI 2 "register_operand" "x"))))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=f") + (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f")) + (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "f"))))] "TARGET_SNAKE && ! TARGET_DISABLE_FPREGS" "xmpyu %1,%2,%0" [(set_attr "type" "fpmul")]) (define_insn "" + [(set (match_operand:DI 0 "nonimmediate_operand" "=f") + (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f")) + (match_operand:DI 2 "uint32_operand" "f")))] + "TARGET_SNAKE && ! TARGET_DISABLE_FPREGS" + "xmpyu %1,%R2,%0" + [(set_attr "type" "fpmul")]) + +(define_insn "" [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25))) (clobber (match_operand:SI 0 "register_operand" "=a")) (clobber (reg:SI 26)) (clobber (reg:SI 25)) (clobber (reg:SI 31))] "" - "* return output_mul_insn (0);" - [(set_attr "type" "milli")]) + "* return output_mul_insn (0, insn);" + [(set_attr "type" "milli") + (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") + (const_int 0)) + (const_int 4) + (const_int 24)))]) ;;; Division and mod. (define_expand "divsi3" [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) (parallel [(set (reg:SI 29) (div:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_operand:SI 3 "register_operand" "")) + (clobber (match_dup 3)) (clobber (reg:SI 26)) (clobber (reg:SI 25)) (clobber (reg:SI 31))]) @@ -1987,16 +2275,20 @@ (clobber (reg:SI 26)) (clobber (reg:SI 25)) (clobber (reg:SI 31))] - "" - "* - return output_div_insn (operands, 0);" - [(set_attr "type" "milli")]) + "" + "* + return output_div_insn (operands, 0, insn);" + [(set_attr "type" "milli") + (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") + (const_int 0)) + (const_int 4) + (const_int 24)))]) (define_expand "udivsi3" [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) (parallel [(set (reg:SI 29) (udiv:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_operand:SI 3 "register_operand" "")) + (clobber (match_dup 3)) (clobber (reg:SI 26)) (clobber (reg:SI 25)) (clobber (reg:SI 31))]) @@ -2016,7 +2308,7 @@ gen_rtx (UDIV, SImode, gen_rtx (REG, SImode, 26), gen_rtx (REG, SImode, 25))), - gen_rtx (CLOBBER, VOIDmode, operands[3]), + gen_rtx (CLOBBER, VOIDmode, operands[3]), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 26)), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 25)), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 31))))); @@ -2032,16 +2324,20 @@ (clobber (reg:SI 26)) (clobber (reg:SI 25)) (clobber (reg:SI 31))] - "" - "* - return output_div_insn (operands, 1);" - [(set_attr "type" "milli")]) + "" + "* + return output_div_insn (operands, 1, insn);" + [(set_attr "type" "milli") + (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") + (const_int 0)) + (const_int 4) + (const_int 24)))]) (define_expand "modsi3" [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) (parallel [(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_operand:SI 3 "register_operand" "")) + (clobber (match_dup 3)) (clobber (reg:SI 26)) (clobber (reg:SI 25)) (clobber (reg:SI 31))]) @@ -2059,7 +2355,7 @@ gen_rtx (MOD, SImode, gen_rtx (REG, SImode, 26), gen_rtx (REG, SImode, 25))), - gen_rtx (CLOBBER, VOIDmode, operands[3]), + gen_rtx (CLOBBER, VOIDmode, operands[3]), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 26)), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 25)), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 31))))); @@ -2075,14 +2371,18 @@ (clobber (reg:SI 31))] "" "* - return output_mod_insn (0);" - [(set_attr "type" "milli")]) + return output_mod_insn (0, insn);" + [(set_attr "type" "milli") + (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") + (const_int 0)) + (const_int 4) + (const_int 24)))]) (define_expand "umodsi3" [(set (reg:SI 26) (match_operand:SI 1 "move_operand" "")) (set (reg:SI 25) (match_operand:SI 2 "move_operand" "")) (parallel [(set (reg:SI 29) (umod:SI (reg:SI 26) (reg:SI 25))) - (clobber (match_operand:SI 3 "register_operand" "")) + (clobber (match_dup 3)) (clobber (reg:SI 26)) (clobber (reg:SI 25)) (clobber (reg:SI 31))]) @@ -2100,7 +2400,7 @@ gen_rtx (UMOD, SImode, gen_rtx (REG, SImode, 26), gen_rtx (REG, SImode, 25))), - gen_rtx (CLOBBER, VOIDmode, operands[3]), + gen_rtx (CLOBBER, VOIDmode, operands[3]), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 26)), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 25)), gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, 31))))); @@ -2116,8 +2416,12 @@ (clobber (reg:SI 31))] "" "* - return output_mod_insn (1);" - [(set_attr "type" "milli")]) + return output_mod_insn (1, insn);" + [(set_attr "type" "milli") + (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") + (const_int 0)) + (const_int 4) + (const_int 24)))]) ;;- and instructions ;; We define DImode `and` so with DImode `not` we can get @@ -2142,16 +2446,18 @@ (match_operand:DI 2 "register_operand" "r")))] "" "and %1,%2,%0\;and %R1,%R2,%R0" - [(set_attr "length" "2")]) + [(set_attr "length" "8")]) +; The ? for op1 makes reload prefer zdepi instead of loading a huge +; constant with ldil;ldo. (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") - (and:SI (match_operand:SI 1 "register_operand" "%r,0") + (and:SI (match_operand:SI 1 "register_operand" "%?r,0") (match_operand:SI 2 "and_operand" "rO,P")))] "" "* return output_and (operands); " [(set_attr "type" "binary") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") @@ -2159,7 +2465,7 @@ (match_operand:DI 2 "register_operand" "r")))] "" "andcm %2,%1,%0\;andcm %R2,%R1,%R0" - [(set_attr "length" "2")]) + [(set_attr "length" "8")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2187,7 +2493,7 @@ (match_operand:DI 2 "register_operand" "r")))] "" "or %1,%2,%0\;or %R1,%R2,%R0" - [(set_attr "length" "2")]) + [(set_attr "length" "8")]) ;; Need a define_expand because we've run out of CONST_OK... characters. (define_expand "iorsi3" @@ -2208,7 +2514,7 @@ "" "* return output_ior (operands); " [(set_attr "type" "binary") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2236,7 +2542,7 @@ (match_operand:DI 2 "register_operand" "r")))] "" "xor %1,%2,%0\;xor %R1,%R2,%R0" - [(set_attr "length" "2")]) + [(set_attr "length" "8")]) (define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2251,7 +2557,7 @@ "" "sub 0,%R1,%R0\;subb 0,%1,%0" [(set_attr "type" "unary") - (set_attr "length" "2")]) + (set_attr "length" "8")]) (define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2276,7 +2582,7 @@ "" "uaddcm 0,%1,%0\;uaddcm 0,%R1,%R0" [(set_attr "type" "unary") - (set_attr "length" "2")]) + (set_attr "length" "8")]) (define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2288,107 +2594,107 @@ ;; Floating point arithmetic instructions. (define_insn "adddf3" - [(set (match_operand:DF 0 "register_operand" "=fx") - (plus:DF (match_operand:DF 1 "register_operand" "fx") - (match_operand:DF 2 "register_operand" "fx")))] + [(set (match_operand:DF 0 "register_operand" "=f") + (plus:DF (match_operand:DF 1 "register_operand" "f") + (match_operand:DF 2 "register_operand" "f")))] "" "fadd,dbl %1,%2,%0" [(set_attr "type" "fpalu")]) (define_insn "addsf3" - [(set (match_operand:SF 0 "register_operand" "=fx") - (plus:SF (match_operand:SF 1 "register_operand" "fx") - (match_operand:SF 2 "register_operand" "fx")))] + [(set (match_operand:SF 0 "register_operand" "=f") + (plus:SF (match_operand:SF 1 "register_operand" "f") + (match_operand:SF 2 "register_operand" "f")))] "" "fadd,sgl %1,%2,%0" [(set_attr "type" "fpalu")]) (define_insn "subdf3" - [(set (match_operand:DF 0 "register_operand" "=fx") - (minus:DF (match_operand:DF 1 "register_operand" "fx") - (match_operand:DF 2 "register_operand" "fx")))] + [(set (match_operand:DF 0 "register_operand" "=f") + (minus:DF (match_operand:DF 1 "register_operand" "f") + (match_operand:DF 2 "register_operand" "f")))] "" "fsub,dbl %1,%2,%0" [(set_attr "type" "fpalu")]) (define_insn "subsf3" - [(set (match_operand:SF 0 "register_operand" "=fx") - (minus:SF (match_operand:SF 1 "register_operand" "fx") - (match_operand:SF 2 "register_operand" "fx")))] + [(set (match_operand:SF 0 "register_operand" "=f") + (minus:SF (match_operand:SF 1 "register_operand" "f") + (match_operand:SF 2 "register_operand" "f")))] "" "fsub,sgl %1,%2,%0" [(set_attr "type" "fpalu")]) (define_insn "muldf3" - [(set (match_operand:DF 0 "register_operand" "=fx") - (mult:DF (match_operand:DF 1 "register_operand" "fx") - (match_operand:DF 2 "register_operand" "fx")))] + [(set (match_operand:DF 0 "register_operand" "=f") + (mult:DF (match_operand:DF 1 "register_operand" "f") + (match_operand:DF 2 "register_operand" "f")))] "" "fmpy,dbl %1,%2,%0" [(set_attr "type" "fpmul")]) (define_insn "mulsf3" - [(set (match_operand:SF 0 "register_operand" "=fx") - (mult:SF (match_operand:SF 1 "register_operand" "fx") - (match_operand:SF 2 "register_operand" "fx")))] + [(set (match_operand:SF 0 "register_operand" "=f") + (mult:SF (match_operand:SF 1 "register_operand" "f") + (match_operand:SF 2 "register_operand" "f")))] "" "fmpy,sgl %1,%2,%0" [(set_attr "type" "fpmul")]) (define_insn "divdf3" - [(set (match_operand:DF 0 "register_operand" "=fx") - (div:DF (match_operand:DF 1 "register_operand" "fx") - (match_operand:DF 2 "register_operand" "fx")))] + [(set (match_operand:DF 0 "register_operand" "=f") + (div:DF (match_operand:DF 1 "register_operand" "f") + (match_operand:DF 2 "register_operand" "f")))] "" "fdiv,dbl %1,%2,%0" [(set_attr "type" "fpdivdbl")]) (define_insn "divsf3" - [(set (match_operand:SF 0 "register_operand" "=fx") - (div:SF (match_operand:SF 1 "register_operand" "fx") - (match_operand:SF 2 "register_operand" "fx")))] + [(set (match_operand:SF 0 "register_operand" "=f") + (div:SF (match_operand:SF 1 "register_operand" "f") + (match_operand:SF 2 "register_operand" "f")))] "" "fdiv,sgl %1,%2,%0" [(set_attr "type" "fpdivsgl")]) (define_insn "negdf2" - [(set (match_operand:DF 0 "register_operand" "=fx") - (neg:DF (match_operand:DF 1 "register_operand" "fx")))] + [(set (match_operand:DF 0 "register_operand" "=f") + (neg:DF (match_operand:DF 1 "register_operand" "f")))] "" "fsub,dbl 0,%1,%0" [(set_attr "type" "fpalu")]) (define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=fx") - (neg:SF (match_operand:SF 1 "register_operand" "fx")))] + [(set (match_operand:SF 0 "register_operand" "=f") + (neg:SF (match_operand:SF 1 "register_operand" "f")))] "" "fsub,sgl 0,%1,%0" [(set_attr "type" "fpalu")]) (define_insn "absdf2" - [(set (match_operand:DF 0 "register_operand" "=fx") - (abs:DF (match_operand:DF 1 "register_operand" "fx")))] + [(set (match_operand:DF 0 "register_operand" "=f") + (abs:DF (match_operand:DF 1 "register_operand" "f")))] "" "fabs,dbl %1,%0" [(set_attr "type" "fpalu")]) (define_insn "abssf2" - [(set (match_operand:SF 0 "register_operand" "=fx") - (abs:SF (match_operand:SF 1 "register_operand" "fx")))] + [(set (match_operand:SF 0 "register_operand" "=f") + (abs:SF (match_operand:SF 1 "register_operand" "f")))] "" "fabs,sgl %1,%0" [(set_attr "type" "fpalu")]) (define_insn "sqrtdf2" - [(set (match_operand:DF 0 "register_operand" "=fx") - (sqrt:DF (match_operand:DF 1 "register_operand" "fx")))] + [(set (match_operand:DF 0 "register_operand" "=f") + (sqrt:DF (match_operand:DF 1 "register_operand" "f")))] "" "fsqrt,dbl %1,%0" [(set_attr "type" "fpsqrtdbl")]) (define_insn "sqrtsf2" - [(set (match_operand:SF 0 "register_operand" "=fx") - (sqrt:SF (match_operand:SF 1 "register_operand" "fx")))] + [(set (match_operand:SF 0 "register_operand" "=f") + (sqrt:SF (match_operand:SF 1 "register_operand" "f")))] "" "fsqrt,sgl %1,%0" [(set_attr "type" "fpsqrtsgl")]) @@ -2404,7 +2710,7 @@ "" "ldb%M1 %1,%0" [(set_attr "type" "load") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2413,7 +2719,7 @@ "" "ldh%M1 %1,%0" [(set_attr "type" "load") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2421,22 +2727,29 @@ (match_operand:SI 3 "shadd_operand" "")) (match_operand:SI 1 "register_operand" "r")))] "" - "sh%O3add %2,%1,%0") + "sh%O3addl %2,%1,%0") ;; This variant of the above insn can occur if the first operand ;; is the frame pointer. This is a kludge, but there doesn't -;; seem to be a way around it. Only recognize them while reloading. +;; seem to be a way around it. Only recognize it while reloading. +;; Note how operand 3 uses a predicate of "const_int_operand", but +;; has constraints allowing a register. I don't know how this works, +;; but it somehow makes sure that out-of-range constants are placed +;; in a register which somehow magically is a "const_int_operand". +;; (this was stolen from alpha.md, I'm not going to try and change it. (define_insn "" - [(set (match_operand:SI 0 "register_operand" "=&r") - (plus:SI (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r") + [(set (match_operand:SI 0 "register_operand" "=&r,r") + (plus:SI (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r,r") (match_operand:SI 4 "shadd_operand" "")) - (match_operand:SI 1 "register_operand" "r")) - (match_operand:SI 3 "const_int_operand" "rI")))] + (match_operand:SI 1 "register_operand" "r,r")) + (match_operand:SI 3 "const_int_operand" "r,J")))] "reload_in_progress" - "sh%O4add %2,%1,%0\;add%I3 %3,%0,%0" + "@ + sh%O4addl %2,%1,%0\;addl %3,%0,%0 + sh%O4addl %2,%1,%0\;ldo %3(%0),%0" [(set_attr "type" "multi") - (set_attr "length" "2")]) + (set_attr "length" "8")]) (define_expand "ashlsi3" [(set (match_operand:SI 0 "register_operand" "") @@ -2455,7 +2768,7 @@ emit_insn (gen_zvdep32 (operands[0], operands[1], temp)); DONE; } - /* Make sure both inputs are not constants, + /* Make sure both inputs are not constants, the recognizer can't handle that. */ operands[1] = force_reg (SImode, operands[1]); }") @@ -2467,7 +2780,7 @@ "" "zdep %1,%P2,%L2,%0" [(set_attr "type" "binary") - (set_attr "length" "1")]) + (set_attr "length" "4")]) ; Match cases of op1 a CONST_INT here that zvdep_imm doesn't handle. ; Doing it like this makes slightly better code since reload can @@ -2499,6 +2812,36 @@ return \"zvdepi %1,%2,%0\"; }") +(define_insn "vdepi_ior" + [(set (match_operand:SI 0 "register_operand" "=r") + (ior:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "") + (minus:SI (const_int 31) + (match_operand:SI 2 "register_operand" "q"))) + (match_operand:SI 3 "register_operand" "0")))] + ; accept ...0001...1, can this be generalized? + "exact_log2 (INTVAL (operands[1]) + 1) >= 0" + "* +{ + int x = INTVAL (operands[1]); + operands[2] = GEN_INT (exact_log2 (x + 1)); + return \"vdepi -1,%2,%0\"; +}") + +(define_insn "vdepi_and" + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (rotate:SI (match_operand:SI 1 "const_int_operand" "") + (minus:SI (const_int 31) + (match_operand:SI 2 "register_operand" "q"))) + (match_operand:SI 3 "register_operand" "0")))] + ; this can be generalized...! + "INTVAL (operands[1]) == -2" + "* +{ + int x = INTVAL (operands[1]); + operands[2] = GEN_INT (exact_log2 ((~x) + 1)); + return \"vdepi 0,%2,%0\"; +}") + (define_expand "ashrsi3" [(set (match_operand:SI 0 "register_operand" "") (ashiftrt:SI (match_operand:SI 1 "register_operand" "") @@ -2522,7 +2865,7 @@ "" "extrs %1,%P2,%L2,%0" [(set_attr "type" "binary") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "vextrs32" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2541,7 +2884,7 @@ vshd 0,%1,%0 extru %1,%P2,%L2,%0" [(set_attr "type" "binary") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "rotrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -2559,7 +2902,7 @@ return \"vshd %1,%1,%0\"; }" [(set_attr "type" "binary") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "rotlsi3" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2572,7 +2915,7 @@ return \"shd %1,%1,%2,%0\"; }" [(set_attr "type" "binary") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2584,7 +2927,7 @@ "INTVAL (operands[3]) + INTVAL (operands[4]) == 32" "shd %1,%2,%4,%0" [(set_attr "type" "binary") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2596,7 +2939,7 @@ "INTVAL (operands[3]) + INTVAL (operands[4]) == 32" "shd %1,%2,%4,%0" [(set_attr "type" "binary") - (set_attr "length" "1")]) + (set_attr "length" "4")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2612,7 +2955,7 @@ return \"zdep %1,%2,%3,%0\"; }" [(set_attr "type" "binary") - (set_attr "length" "1")]) + (set_attr "length" "4")]) ;; Unconditional and other jump instructions. @@ -2622,7 +2965,7 @@ "bv%* 0(%%r2)" [(set_attr "type" "branch")]) -;; Use a different pattern for functions which have non-trivial +;; Use a different pattern for functions which have non-trivial ;; epilogues so as not to confuse jump and reorg. (define_insn "return_internal" [(use (reg:SI 2)) @@ -2641,7 +2984,7 @@ "" " { - /* Try to use the trivial return first. Else use the full + /* Try to use the trivial return first. Else use the full epilogue. */ if (hppa_can_use_return_insn_p ()) emit_jump_insn (gen_return ()); @@ -2661,7 +3004,7 @@ (use (match_operand:SI 0 "const_int_operand" ""))] "" "bl _mcount,%%r2\;ldo %0(%%r2),%%r25" - [(set_attr "length" "2")]) + [(set_attr "length" "8")]) (define_insn "blockage" [(unspec_volatile [(const_int 2)] 0)] @@ -2673,7 +3016,17 @@ [(set (pc) (label_ref (match_operand 0 "" "")))] "" "bl%* %l0,0" - [(set_attr "type" "branch")]) + [(set_attr "type" "uncond_branch") + (set (attr "length") + (cond [(eq (symbol_ref "jump_in_call_delay (insn)") (const_int 0)) + (const_int 4) +;; If the jump is in the delay slot of a call, then its length depends +;; on whether or not we can add the proper offset to %r2 with an ldo +;; instruction. + (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4)] + (const_int 8)))]) ;; Subroutines of "casesi". ;; operand 0 is index @@ -2735,53 +3088,85 @@ return \"sub,>> %0,%1,0\;blr,n %0,0\;b,n %l3\"; } }" - [(set_attr "length" "3")]) + [(set_attr "length" "12")]) ;; Need nops for the calls because execution is supposed to continue ;; past; we don't want to nullify an instruction that we need. ;;- jump to subroutine (define_expand "call" - [(parallel [(call (match_operand:SI 0 "" "") - (match_operand 1 "" "")) - (clobber (reg:SI 2))])] - "" - " + [(parallel [(call (match_operand:SI 0 "" "") + (match_operand 1 "" "")) + (clobber (reg:SI 2))])] + "" + " { rtx op; - - if (TARGET_LONG_CALLS) + + if (flag_pic) + emit_insn (gen_rtx (USE, VOIDmode, + gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))); + + if (TARGET_LONG_CALLS) op = force_reg (SImode, XEXP (operands[0], 0)); else op = XEXP (operands[0], 0); - emit_call_insn (gen_call_internal (op, operands[1])); + + /* Use two different patterns for calls to explicitly named functions + and calls through function pointers. This is necessary as these two + types of calls use different calling conventions, and CSE might try + to change the named call into an indirect call in some cases (using + two patterns keeps CSE from performing this optimization). */ + if (GET_CODE (op) == SYMBOL_REF) + emit_call_insn (gen_call_internal_symref (op, operands[1])); + else + emit_call_insn (gen_call_internal_reg (force_reg (SImode, op), + operands[1])); + if (flag_pic) { if (!hppa_save_pic_table_rtx) hppa_save_pic_table_rtx = gen_reg_rtx (Pmode); emit_insn (gen_rtx (SET, VOIDmode, - gen_rtx (REG, Pmode, 19), hppa_save_pic_table_rtx)); + gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM), + hppa_save_pic_table_rtx)); } DONE; }") -(define_insn "call_internal" - [(call (mem:SI (match_operand:SI 0 "call_operand_address" "r,S")) - (match_operand 1 "" "i,i")) - (clobber (reg:SI 2))] - "" - "* +(define_insn "call_internal_symref" + [(call (mem:SI (match_operand:SI 0 "call_operand_address" "")) + (match_operand 1 "" "i")) + (clobber (reg:SI 2)) + (use (const_int 0))] + "! TARGET_LONG_CALLS" + "* +{ + output_arg_descriptor (insn); + return output_call (insn, operands[0], gen_rtx (REG, SImode, 2)); +}" + [(set_attr "type" "call") + (set_attr "length" "4")]) + +(define_insn "call_internal_reg" + [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) + (match_operand 1 "" "i")) + (clobber (reg:SI 2)) + (use (const_int 1))] + "" + "* { - if (which_alternative == 0) - return \"copy %0,22\;.CALL\\tARGW0=GR\;bl $$dyncall,31\;copy 31,2\"; + /* Yuk! bl may not be able to reach $$dyncall. */ + if (TARGET_LONG_CALLS) + return \"copy %r0,%%r22\;ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\"; else - { - output_arg_descriptor (insn); - return \"bl %0,2%#\"; - } + return \"copy %r0,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\"; }" - [(set_attr "type" "dyncall,call") - (set_attr "length" "3,1")]) + [(set_attr "type" "dyncall") + (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") + (const_int 0)) + (const_int 12) + (const_int 24)))]) (define_expand "call_value" [(parallel [(set (match_operand 0 "" "") @@ -2793,42 +3178,106 @@ " { rtx op; - - if (TARGET_LONG_CALLS) + + if (flag_pic) + emit_insn (gen_rtx (USE, VOIDmode, + gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))); + + if (TARGET_LONG_CALLS) op = force_reg (SImode, XEXP (operands[1], 0)); else op = XEXP (operands[1], 0); - emit_call_insn (gen_call_value_internal (operands[0], op, operands[2])); + + /* Use two different patterns for calls to explicitly named functions + and calls through function pointers. This is necessary as these two + types of calls use different calling conventions, and CSE might try + to change the named call into an indirect call in some cases (using + two patterns keeps CSE from performing this optimization). */ + if (GET_CODE (op) == SYMBOL_REF) + emit_call_insn (gen_call_value_internal_symref (operands[0], op, + operands[2])); + else + emit_call_insn (gen_call_value_internal_reg (operands[0], + force_reg (SImode, op), + operands[2])); + if (flag_pic) { if (!hppa_save_pic_table_rtx) hppa_save_pic_table_rtx = gen_reg_rtx (Pmode); emit_insn (gen_rtx (SET, VOIDmode, - gen_rtx (REG, Pmode, 19), hppa_save_pic_table_rtx)); + gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM), + hppa_save_pic_table_rtx)); } DONE; }") -(define_insn "call_value_internal" - [(set (match_operand 0 "" "=rfx,rfx") - (call (mem:SI (match_operand:SI 1 "call_operand_address" "r,S")) - (match_operand 2 "" "i,i"))) - (clobber (reg:SI 2))] +(define_insn "call_value_internal_symref" + [(set (match_operand 0 "" "=rf") + (call (mem:SI (match_operand:SI 1 "call_operand_address" "")) + (match_operand 2 "" "i"))) + (clobber (reg:SI 2)) + (use (const_int 0))] + ;;- Don't use operand 1 for most machines. + "! TARGET_LONG_CALLS" + "* +{ + output_arg_descriptor (insn); + return output_call (insn, operands[1], gen_rtx (REG, SImode, 2)); +}" + [(set_attr "type" "call") + (set_attr "length" "4")]) + +(define_insn "call_value_internal_reg" + [(set (match_operand 0 "" "=rf") + (call (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand 2 "" "i"))) + (clobber (reg:SI 2)) + (use (const_int 1))] ;;- Don't use operand 1 for most machines. "" "* { - if (which_alternative == 0) - return \"copy %1,22\;.CALL\\tARGW0=GR\;bl $$dyncall,31\;copy 31,2\"; + /* Yuk! bl may not be able to reach $$dyncall. */ + if (TARGET_LONG_CALLS) + return \"copy %r1,%%r22\;ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\"; else + return \"copy %r1,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\"; +}" + [(set_attr "type" "dyncall") + (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") + (const_int 0)) + (const_int 12) + (const_int 24)))]) + +;; Call subroutine returning any type. + +(define_expand "untyped_call" + [(parallel [(call (match_operand 0 "" "") + (const_int 0)) + (match_operand 1 "" "") + (match_operand 2 "" "")])] + "" + " +{ + int i; + + emit_call_insn (gen_call (operands[0], const0_rtx)); + + for (i = 0; i < XVECLEN (operands[2], 0); i++) { - output_arg_descriptor (insn); - return \"bl %1,2%#\"; + rtx set = XVECEXP (operands[2], 0, i); + emit_move_insn (SET_DEST (set), SET_SRC (set)); } -}" - [(set_attr "type" "dyncall,call") - (set_attr "length" "3,1")]) + /* The optimizer does not know that the call sets the function value + registers we stored in the result block. We avoid problems by + claiming that all hard registers are used and clobbered at this + point. */ + emit_insn (gen_blockage ()); + + DONE; +}") (define_insn "nop" [(const_int 0)] "" @@ -2838,8 +3287,8 @@ (define_insn "indirect_jump" [(set (pc) (match_operand:SI 0 "register_operand" "r"))] "" - "bv%* 0(%0)" - [(set_attr "type" "branch")]) + "bv%* 0(%0)" + [(set_attr "type" "branch")]) (define_insn "extzv" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2849,6 +3298,14 @@ "" "extru %1,%3+%2-1,%2,%0") +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (zero_extract:SI (match_operand:SI 1 "register_operand" "r") + (const_int 1) + (match_operand:SI 3 "register_operand" "q")))] + "" + "vextru %1,1,%0") + (define_insn "extv" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extract:SI (match_operand:SI 1 "register_operand" "r") @@ -2857,6 +3314,14 @@ "" "extrs %1,%3+%2-1,%2,%0") +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extract:SI (match_operand:SI 1 "register_operand" "r") + (const_int 1) + (match_operand:SI 3 "register_operand" "q")))] + "" + "vextrs %1,1,%0") + (define_insn "insv" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,r") (match_operand:SI 1 "uint5_operand" "") @@ -2881,7 +3346,6 @@ return \"depi %3,%2+%1-1,%1,%0\"; }") -;; The dbra pattern from hell. ;; This insn is used for some loop tests, typically loops reversed when ;; strength reduction is used. It is actually created when the instruction ;; combination phase combines the special loop test. Since this insn @@ -2892,127 +3356,216 @@ [(set (pc) (if_then_else (match_operator 2 "comparison_operator" - [(plus:SI (match_operand:SI 0 "register_operand" "+!r,m") - (match_operand:SI 1 "int5_operand" "L,L")) + [(plus:SI (match_operand:SI 0 "register_operand" "+!r,!*f,!*m") + (match_operand:SI 1 "int5_operand" "L,L,L")) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1))) - (clobber (match_scratch:SI 4 "=X,r"))] - "0" -"* -{ - if (INSN_ANNULLED_BRANCH_P (insn)) - { - /* Loop counter is in a register. */ - if (which_alternative == 0) - /* Short branch. Normal handling of nullification. */ - if (get_attr_length (insn) == 1) - return \"addib,%C2,n %1,%0,%3\"; - /* Long Conditional branch forward with delay slot nullified if - branch is taken. */ - else if (get_attr_length (insn) == 2) - return \"addi,%N2 %1,%0,%0\;bl,n %3,0\"; - /* Long Conditional branch backwards with delay slot nullified - if branch is not taken. */ - else - return \"addib,%N2 %1,%0,.+16\;nop\;bl %3,0\"; - else - { - /* Must reload loop counter from memory. Ugly. */ - output_asm_insn (\"ldw %0,%4\;ldo %1(%4),%4\;stw %4,%0\", operands); - /* Short branch. Normal handling of nullification. */ - if (get_attr_length (insn) == 4) - return \"comb,%S2,n 0,%4,%3\"; - /* Long Conditional branch forward with delay slot nullified if - branch is taken. */ - else if (get_attr_length (insn) == 5) - return \"comclr,%B2 0,%4,0\;bl,n %3,0\"; - else - /* Long Conditional branch backwards with delay slot nullified - if branch is not taken. */ - return \"comb,%B2 0,%4,.+16\;nop\;bl %3,0\"; - } - } - else - { - /* We are not nullifying the delay slot. Much simpler. */ - if (which_alternative == 0) - if (get_attr_length (insn) == 1) - /* Short form. */ - return \"addib,%C2 %1,%0,%3%#\"; - else - /* Long form. */ - return \"addi,%N2 %1,%0,%0\;bl%* %3,0\"; - else - { - /* Reload loop counter from memory. */ - output_asm_insn (\"ldw %0,%4\;ldo %1(%4),%4\;stw %4,%0\", operands); - /* Short form. */ - if (get_attr_length (insn) == 4) - return \"comb,%S2 0,%4,%3%#\"; - /* Long form. */ - else - return \"comclr,%B2 0,%4,0\;bl%* %3,0\"; - } - } -}" -;; Do not expect to understand this the first time through. -[(set_attr "type" "cbranch") + (clobber (match_scratch:SI 4 "=X,r,r"))] + "" + "* return output_dbra (operands, insn, which_alternative); " +;; Do not expect to understand this the first time through. +[(set_attr "type" "cbranch,multi,multi") + (set (attr "length") + (if_then_else (eq_attr "alternative" "0") +;; Loop counter in register case +;; Short branch has length of 4 +;; Long branch has length of 8 + (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4) + (const_int 8)) + +;; Loop counter in FP reg case. +;; Extra goo to deal with additional reload insns. + (if_then_else (eq_attr "alternative" "1") + (if_then_else (lt (match_dup 3) (pc)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24)))) + (const_int 8188)) + (const_int 24) + (const_int 28)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 24) + (const_int 28))) +;; Loop counter in memory case. +;; Extra goo to deal with additional reload insns. + (if_then_else (lt (match_dup 3) (pc)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12)))) + (const_int 8188)) + (const_int 12) + (const_int 16)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 12) + (const_int 16))))))]) + +;; Simply another variant of the dbra pattern. More restrictive +;; in testing the comparison operator as it must worry about overflow +;; problems. +(define_insn "" + [(set (pc) + (if_then_else + (match_operator 2 "eq_neq_comparison_operator" + [(match_operand:SI 0 "register_operand" "+!r,!*f,!*m") + (match_operand:SI 5 "const_int_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) (match_operand:SI 1 "int5_operand" "L,L,L"))) + (clobber (match_scratch:SI 4 "=X,r,r"))] + "INTVAL (operands[5]) == - INTVAL (operands[1])" +"* return output_dbra (operands, insn, which_alternative);" +;; Do not expect to understand this the first time through. +[(set_attr "type" "cbranch,multi,multi") + (set (attr "length") + (if_then_else (eq_attr "alternative" "0") +;; Loop counter in register case +;; Short branch has length of 4 +;; Long branch has length of 8 + (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4) + (const_int 8)) + +;; Loop counter in FP reg case. +;; Extra goo to deal with additional reload insns. + (if_then_else (eq_attr "alternative" "1") + (if_then_else (lt (match_dup 3) (pc)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24)))) + (const_int 8188)) + (const_int 24) + (const_int 28)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 24) + (const_int 28))) +;; Loop counter in memory case. +;; Extra goo to deal with additional reload insns. + (if_then_else (lt (match_dup 3) (pc)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12)))) + (const_int 8188)) + (const_int 12) + (const_int 16)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 12) + (const_int 16))))))]) + +(define_insn "" + [(set (pc) + (if_then_else + (match_operator 2 "movb_comparison_operator" + [(match_operand:SI 1 "register_operand" "r,r,r") (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc))) + (set (match_operand:SI 0 "register_operand" "=!r,!*f,!*m") + (match_dup 1))] + "" +"* return output_movb (operands, insn, which_alternative, 0); " +;; Do not expect to understand this the first time through. +[(set_attr "type" "cbranch,multi,multi") (set (attr "length") - (if_then_else - (eq_attr "alternative" "0") -;; Loop counter in register case. - (cond [(lt (abs (minus (match_dup 1) (plus (pc) (const_int 2)))) - (const_int 1023)) -;; Short branch has a length of 1. - (const_int 1) -;; Long backward branch with nullified delay slot has length of 3. - (and (lt (match_dup 1) (pc)) - (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)") - (const_int 1))) - (const_int 3)] -;; Default others to 2. -;; Long branches with unfilled delay slots --or-- -;; Long forward with nullified delay slot. - (const_int 2)) -;; Loop counter in memory case. Similar to above except we pay -;; 3 extra insns in each case for reloading the counter into a register. - (if_then_else (lt (match_dup 1) (pc)) - (cond [(lt (abs (minus (match_dup 1) (plus (pc) (const_int 5)))) - (const_int 1023)) -;; Short branch has length of 4 (the reloading costs 3 insns) - (const_int 4) - (and (lt (match_dup 1) (pc)) - (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)") - (const_int 1))) -;; Long backward branch with nullified delay slot has length of 6. - (const_int 6)] -;; Default others to 5. -;; Long branches with unfilled delay slots --or-- -;; Long forward with nullified delay slot. - (const_int 5)) - (if_then_else (lt (abs (minus (match_dup 1) - (plus (pc) (const_int 2)))) - (const_int 1023)) - (const_int 4) - (const_int 5)))))]) + (if_then_else (eq_attr "alternative" "0") +;; Loop counter in register case +;; Short branch has length of 4 +;; Long branch has length of 8 + (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4) + (const_int 8)) + +;; Loop counter in FP reg case. +;; Extra goo to deal with additional reload insns. + (if_then_else (eq_attr "alternative" "1") + (if_then_else (lt (match_dup 3) (pc)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12)))) + (const_int 8188)) + (const_int 12) + (const_int 16)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 12) + (const_int 16))) +;; Loop counter in memory case. +;; Extra goo to deal with additional reload insns. + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 8) + (const_int 12)))))]) +;; Handle negated branch. +(define_insn "" + [(set (pc) + (if_then_else + (match_operator 2 "movb_comparison_operator" + [(match_operand:SI 1 "register_operand" "r,r,r") (const_int 0)]) + (pc) + (label_ref (match_operand 3 "" "")))) + (set (match_operand:SI 0 "register_operand" "=!r,!*f,!*m") + (match_dup 1))] + "" +"* return output_movb (operands, insn, which_alternative, 1); " +;; Do not expect to understand this the first time through. +[(set_attr "type" "cbranch,multi,multi") + (set (attr "length") + (if_then_else (eq_attr "alternative" "0") +;; Loop counter in register case +;; Short branch has length of 4 +;; Long branch has length of 8 + (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4) + (const_int 8)) + +;; Loop counter in FP reg case. +;; Extra goo to deal with additional reload insns. + (if_then_else (eq_attr "alternative" "1") + (if_then_else (lt (match_dup 3) (pc)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12)))) + (const_int 8188)) + (const_int 12) + (const_int 16)) + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 12) + (const_int 16))) +;; Loop counter in memory case. +;; Extra goo to deal with additional reload insns. + (if_then_else + (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 8) + (const_int 12)))))]) -;; The next four peepholes take advantage of the new 5 operand +;; The next four peepholes take advantage of the new 5 operand ;; fmpy{add,sub} instructions available on 1.1 CPUS. Basically ;; fmpyadd performs a multiply and add/sub of independent operands ;; at the same time. Because the operands must be independent ;; combine will not try to combine such insns... Thus we have ;; to use a peephole. (define_peephole - [(set (match_operand 0 "register_operand" "=fx") - (mult (match_operand 1 "register_operand" "fx") - (match_operand 2 "register_operand" "fx"))) - (set (match_operand 3 "register_operand" "+fx") - (plus (match_operand 4 "register_operand" "fx") - (match_operand 5 "register_operand" "fx")))] + [(set (match_operand 0 "register_operand" "=f") + (mult (match_operand 1 "register_operand" "f") + (match_operand 2 "register_operand" "f"))) + (set (match_operand 3 "register_operand" "+f") + (plus (match_operand 4 "register_operand" "f") + (match_operand 5 "register_operand" "f")))] "TARGET_SNAKE && fmpyaddoperands (operands)" "* { @@ -3032,13 +3585,13 @@ } }") -(define_peephole - [(set (match_operand 3 "register_operand" "+fx") - (plus (match_operand 4 "register_operand" "fx") - (match_operand 5 "register_operand" "fx"))) - (set (match_operand 0 "register_operand" "=fx") - (mult (match_operand 1 "register_operand" "fx") - (match_operand 2 "register_operand" "fx")))] +(define_peephole + [(set (match_operand 3 "register_operand" "+f") + (plus (match_operand 4 "register_operand" "f") + (match_operand 5 "register_operand" "f"))) + (set (match_operand 0 "register_operand" "=f") + (mult (match_operand 1 "register_operand" "f") + (match_operand 2 "register_operand" "f")))] "TARGET_SNAKE && fmpyaddoperands (operands)" "* { @@ -3061,12 +3614,12 @@ ;; Note fsub subtracts the second operand from the first while fmpysub ;; does the opposite for the subtraction operands! (define_peephole - [(set (match_operand 0 "register_operand" "=fx") - (mult (match_operand 1 "register_operand" "fx") - (match_operand 2 "register_operand" "fx"))) - (set (match_operand 3 "register_operand" "+fx") - (minus (match_operand 4 "register_operand" "fx") - (match_operand 5 "register_operand" "fx")))] + [(set (match_operand 0 "register_operand" "=f") + (mult (match_operand 1 "register_operand" "f") + (match_operand 2 "register_operand" "f"))) + (set (match_operand 3 "register_operand" "+f") + (minus (match_operand 4 "register_operand" "f") + (match_operand 5 "register_operand" "f")))] "TARGET_SNAKE && fmpysuboperands (operands)" "* { @@ -3077,12 +3630,12 @@ }") (define_peephole - [(set (match_operand 3 "register_operand" "+fx") - (minus (match_operand 4 "register_operand" "fx") - (match_operand 5 "register_operand" "fx"))) - (set (match_operand 0 "register_operand" "=fx") - (mult (match_operand 1 "register_operand" "fx") - (match_operand 2 "register_operand" "fx")))] + [(set (match_operand 3 "register_operand" "+f") + (minus (match_operand 4 "register_operand" "f") + (match_operand 5 "register_operand" "f"))) + (set (match_operand 0 "register_operand" "=f") + (mult (match_operand 1 "register_operand" "f") + (match_operand 2 "register_operand" "f")))] "TARGET_SNAKE && fmpysuboperands (operands)" "* { @@ -3096,10 +3649,22 @@ ;; This is used by the trampoline code for nested functions. ;; So long as the trampoline itself is less than 32 bytes this ;; is sufficient. -(define_insn "cacheflush" + +(define_insn "dcacheflush" [(unspec_volatile [(const_int 1)] 0) (use (mem:SI (match_operand:SI 0 "register_operand" "r"))) (use (mem:SI (match_operand:SI 1 "register_operand" "r")))] "" - "fdc 0(0,%0)\;sync\;fic 0(0,%0)\;sync\;fdc 0(0,%1)\;sync\;fic 0(0,%1)\;sync\;nop\;nop\;nop\;nop\;nop\;nop\;nop" - [(set_attr "length" "15")]) + "fdc 0(0,%0)\;fdc 0(0,%1)\;sync" + [(set_attr "length" "12")]) + +(define_insn "icacheflush" + [(unspec_volatile [(const_int 2)] 0) + (use (mem:SI (match_operand:SI 0 "register_operand" "r"))) + (use (mem:SI (match_operand:SI 1 "register_operand" "r"))) + (use (match_operand:SI 2 "register_operand" "r")) + (clobber (match_operand:SI 3 "register_operand" "=&r")) + (clobber (match_operand:SI 4 "register_operand" "=&r"))] + "" + "mfsp %%sr0,%4\;ldsid (0,%2),%3\;mtsp %3,%%sr0\;fic 0(%%sr0,%0)\;fic 0(%%sr0,%1)\;sync\;mtsp %4,%%sr0\;nop\;nop\;nop\;nop\;nop\;nop" + [(set_attr "length" "52")])