--- gcc/config/pa/pa.md 2018/04/24 18:17:21 1.1.1.2 +++ gcc/config/pa/pa.md 2018/04/24 18:31:13 1.1.1.4 @@ -1,5 +1,5 @@ ;;- Machine description for HP PA-RISC architecture for GNU C compiler -;; Copyright (C) 1992 Free Software Foundation, Inc. +;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. ;; Contributed by the Center for Software Science at the University ;; of Utah. @@ -17,7 +17,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +;; the Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. ;; This gcc Version 2 machine description is inspired by sparc.md and ;; mips.md. @@ -30,9 +31,16 @@ ;; type "binary" insns have two input operands (1,2) and one output (0) (define_attr "type" - "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" + "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli" (const_string "binary")) +;; Processor type (for scheduling, not code generation) -- this attribute +;; must exactly match the processor_type enumeration in pa.h. +;; +;; FIXME: Add 800 scheduling for completeness? + +(define_attr "cpu" "700,7100,7100LC" (const (symbol_ref "pa_cpu_attr"))) + ;; Length (in # of insns). (define_attr "length" "" (cond [(eq_attr "type" "load,fpload") @@ -43,11 +51,11 @@ (if_then_else (match_operand 0 "symbolic_memory_operand" "") (const_int 8) (const_int 4)) - (eq_attr "type" "binary") + (eq_attr "type" "binary,shift,nullshift") (if_then_else (match_operand 2 "arith_operand" "") (const_int 4) (const_int 12)) - (eq_attr "type" "move,unary") + (eq_attr "type" "move,unary,shift,nullshift") (if_then_else (match_operand 1 "arith_operand" "") (const_int 4) (const_int 8))] @@ -69,12 +77,12 @@ ;; 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" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmul,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl") + (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl") (eq_attr "length" "4")) (const_string "true") (const_string "false"))) -;; For calls and millicode calls. Allow unconditional branches in the +;; 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") @@ -86,13 +94,20 @@ (const_string "true") (const_string "false"))] (const_string "false"))) - -;; Unconditional branch, call, and millicode call delay slot description. -(define_delay (eq_attr "type" "uncond_branch,branch,call,milli") +;; 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_PORTABLE_RUNTIME or TARGET_MILLICODE_LONG_CALLS is true. +(define_delay (eq_attr "type" "milli") + [(and (eq_attr "in_call_delay" "true") + (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0)) + (eq (symbol_ref "TARGET_MILLICODE_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)]) @@ -109,14 +124,14 @@ ;; 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"))]) -;; Function units of the HPPA. The following data is for the "Snake" -;; (Mustang CPU + Timex FPU) because that's what I have the docs for. +;; Function units of the HPPA. The following data is for the 700 CPUs +;; (Mustang CPU + Timex FPU aka PA-89) because that's what I have the docs for. ;; Scheduling instructions for PA-83 machines according to the Snake ;; constraints shouldn't hurt. @@ -128,19 +143,23 @@ ;; be specified.) ;; (define_function_unit "alu" 1 0 -;; (eq_attr "type" "unary,binary,move,address") 1 0) +;; (and (eq_attr "type" "unary,shift,nullshift,binary,move,address") +;; (eq_attr "cpu" "700")) +;; 1 0) ;; Memory. Disregarding Cache misses, the Mustang memory times are: -;; load: 2 +;; load: 2, fpload: 3 ;; store, fpstore: 3, no D-cache operations should be scheduled. -;; fpload: 3 (really 2 for flops, but I don't think we can specify that). -(define_function_unit "memory" 1 0 (eq_attr "type" "load") 2 0) -(define_function_unit "memory" 1 0 (eq_attr "type" "store,fpstore") 3 3) -(define_function_unit "memory" 1 0 (eq_attr "type" "fpload") 2 0) +(define_function_unit "pa700memory" 1 0 + (and (eq_attr "type" "load,fpload") + (eq_attr "cpu" "700")) 2 0) +(define_function_unit "pa700memory" 1 0 + (and (eq_attr "type" "store,fpstore") + (eq_attr "cpu" "700")) 3 3) -;; The Timex has two floating-point units: ALU, and MUL/DIV/SQRT unit. +;; The Timex (aka 700) has two floating-point units: ALU, and MUL/DIV/SQRT. ;; Timings: ;; Instruction Time Unit Minimum Distance (unit contention) ;; fcpy 3 ALU 2 @@ -159,13 +178,160 @@ ;; fsqrt,sgl 14 MPY 14 ;; fsqrt,dbl 18 MPY 18 -(define_function_unit "fp_alu" 1 0 (eq_attr "type" "fpcc") 4 2) -(define_function_unit "fp_alu" 1 0 (eq_attr "type" "fpalu") 3 2) -(define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpmul") 3 2) -(define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpdivsgl") 10 10) -(define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpdivdbl") 12 12) -(define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpsqrtsgl") 14 14) -(define_function_unit "fp_mpy" 1 0 (eq_attr "type" "fpsqrtdbl") 18 18) +(define_function_unit "pa700fp_alu" 1 0 + (and (eq_attr "type" "fpcc") + (eq_attr "cpu" "700")) 4 2) +(define_function_unit "pa700fp_alu" 1 0 + (and (eq_attr "type" "fpalu") + (eq_attr "cpu" "700")) 3 2) +(define_function_unit "pa700fp_mpy" 1 0 + (and (eq_attr "type" "fpmulsgl,fpmuldbl") + (eq_attr "cpu" "700")) 3 2) +(define_function_unit "pa700fp_mpy" 1 0 + (and (eq_attr "type" "fpdivsgl") + (eq_attr "cpu" "700")) 10 10) +(define_function_unit "pa700fp_mpy" 1 0 + (and (eq_attr "type" "fpdivdbl") + (eq_attr "cpu" "700")) 12 12) +(define_function_unit "pa700fp_mpy" 1 0 + (and (eq_attr "type" "fpsqrtsgl") + (eq_attr "cpu" "700")) 14 14) +(define_function_unit "pa700fp_mpy" 1 0 + (and (eq_attr "type" "fpsqrtdbl") + (eq_attr "cpu" "700")) 18 18) + +;; Function units for the 7100 and 7150. The 7100/7150 can dual-issue +;; floating point computations with non-floating point computations (fp loads +;; and stores are not fp computations). +;; +;; As with the alpha we multiply the ready delay by two to encourage +;; schedules which will allow the 7100/7150 to dual issue as many instructions +;; as possible. + +;; Memory. Disregarding Cache misses, memory loads take two cycles; stores also +;; take two cycles, during which no Dcache operations should be scheduled. +;; Any special cases are handled in pa_adjust_cost. The 7100, 7150 and 7100LC +;; all have the same memory characteristics if one disregards cache misses. +(define_function_unit "pa7100memory" 1 0 + (and (eq_attr "type" "load,fpload") + (eq_attr "cpu" "7100,7100LC")) 4 0) +(define_function_unit "pa7100memory" 1 0 + (and (eq_attr "type" "store,fpstore") + (eq_attr "cpu" "7100,7100LC")) 4 4) + +;; The 7100/7150 has three floating-point units: ALU, MUL, and DIV. +;; Timings: +;; Instruction Time Unit Minimum Distance (unit contention) +;; fcpy 2 ALU 1 +;; fabs 2 ALU 1 +;; fadd 2 ALU 1 +;; fsub 2 ALU 1 +;; fcmp 2 ALU 1 +;; fcnv 2 ALU 1 +;; fmpyadd 2 ALU,MPY 1 +;; fmpysub 2 ALU,MPY 1 +;; fmpycfxt 2 ALU,MPY 1 +;; fmpy 2 MPY 1 +;; fmpyi 2 MPY 1 +;; fdiv,sgl 8 DIV 8 +;; fdiv,dbl 15 DIV 15 +;; fsqrt,sgl 8 DIV 8 +;; fsqrt,dbl 15 DIV 15 + +(define_function_unit "pa7100fp_alu" 1 0 + (and (eq_attr "type" "fpcc,fpalu") + (eq_attr "cpu" "7100")) 4 2) +(define_function_unit "pa7100fp_mpy" 1 0 + (and (eq_attr "type" "fpmulsgl,fpmuldbl") + (eq_attr "cpu" "7100")) 4 2) +(define_function_unit "pa7100fp_div" 1 0 + (and (eq_attr "type" "fpdivsgl,fpsqrtsgl") + (eq_attr "cpu" "7100")) 16 16) +(define_function_unit "pa7100fp_div" 1 0 + (and (eq_attr "type" "fpdivdbl,fpsqrtdbl") + (eq_attr "cpu" "7100")) 30 30) + +;; To encourage dual issue we define function units corresponding to +;; the instructions which can be dual issued. This is a rather crude +;; approximation, the "pa7100nonflop" test in particular could be refined. +(define_function_unit "pa7100flop" 1 1 + (and + (eq_attr "type" "fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl") + (eq_attr "cpu" "7100,7100LC")) 2 2) + +(define_function_unit "pa7100nonflop" 1 1 + (and + (eq_attr "type" "!fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl") + (eq_attr "cpu" "7100")) 2 2) + + +;; Memory subsystem works just like 7100/7150 (except for cache miss times which +;; we don't model here). + +;; The 7100LC has three floating-point units: ALU, MUL, and DIV. +;; Note divides and sqrt flops lock the cpu until the flop is +;; finished. fmpy and xmpyu (fmpyi) lock the cpu for one cycle. +;; There's no way to avoid the penalty. +;; Timings: +;; Instruction Time Unit Minimum Distance (unit contention) +;; fcpy 2 ALU 1 +;; fabs 2 ALU 1 +;; fadd 2 ALU 1 +;; fsub 2 ALU 1 +;; fcmp 2 ALU 1 +;; fcnv 2 ALU 1 +;; fmpyadd,sgl 2 ALU,MPY 1 +;; fmpyadd,dbl 3 ALU,MPY 2 +;; fmpysub,sgl 2 ALU,MPY 1 +;; fmpysub,dbl 3 ALU,MPY 2 +;; fmpycfxt,sgl 2 ALU,MPY 1 +;; fmpycfxt,dbl 3 ALU,MPY 2 +;; fmpy,sgl 2 MPY 1 +;; fmpy,dbl 3 MPY 2 +;; fmpyi 3 MPY 2 +;; fdiv,sgl 8 DIV 8 +;; fdiv,dbl 15 DIV 15 +;; fsqrt,sgl 8 DIV 8 +;; fsqrt,dbl 15 DIV 15 + +(define_function_unit "pa7100LCfp_alu" 1 0 + (and (eq_attr "type" "fpcc,fpalu") + (eq_attr "cpu" "7100LC")) 4 2) +(define_function_unit "pa7100LCfp_mpy" 1 0 + (and (eq_attr "type" "fpmulsgl") + (eq_attr "cpu" "7100LC")) 4 2) +(define_function_unit "pa7100LCfp_mpy" 1 0 + (and (eq_attr "type" "fpmuldbl") + (eq_attr "cpu" "7100LC")) 6 4) +(define_function_unit "pa7100LCfp_div" 1 0 + (and (eq_attr "type" "fpdivsgl,fpsqrtsgl") + (eq_attr "cpu" "7100LC")) 16 16) +(define_function_unit "pa7100LCfp_div" 1 0 + (and (eq_attr "type" "fpdivdbl,fpsqrtdbl") + (eq_attr "cpu" "7100LC")) 30 30) + +;; Define the various functional units for dual-issue. +;; The 7100LC shares the generic "flop" unit specification with the 7100/7150. + +;; The 7100LC has two basic integer which allow dual issue of most integer +;; instructions. This needs further refinement to deal with the nullify, +;; carry/borrow possible the ldw/ldw stw/stw special dual issue cases, and +;; of course it needs to know about hte 2nd alu. +(define_function_unit "pa7100LCnonflop" 1 1 + (and + (eq_attr "type" "!fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpsqrtsgl,fpdivdbl,fpsqrtdbl,load,fpload,store,fpstore,shift,nullshift") + (eq_attr "cpu" "7100LC")) 2 2) + +(define_function_unit "pa7100LCshifter" 1 1 + (and + (eq_attr "type" "shift,nullshift") + (eq_attr "cpu" "7100LC")) 2 2) + +(define_function_unit "pa7100LCmem" 1 1 + (and + (eq_attr "type" "load,fpload,store,fpstore") + (eq_attr "cpu" "7100LC")) 2 2) + ;; Compare instructions. ;; This controls RTL generation and register allocation. @@ -192,7 +358,7 @@ [(set (reg:CCFP 0) (compare:CCFP (match_operand:SF 0 "reg_or_0_operand" "") (match_operand:SF 1 "reg_or_0_operand" "")))] - "" + "! TARGET_SOFT_FLOAT" " { hppa_compare_op0 = operands[0]; @@ -205,7 +371,7 @@ [(set (reg:CCFP 0) (compare:CCFP (match_operand:DF 0 "reg_or_0_operand" "") (match_operand:DF 1 "reg_or_0_operand" "")))] - "" + "! TARGET_SOFT_FLOAT" " { hppa_compare_op0 = operands[0]; @@ -215,22 +381,24 @@ }") (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")]))] + "! TARGET_SOFT_FLOAT" + "fcmp,sgl,%Y2 %r0,%r1" + [(set_attr "length" "4") + (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")]))] + "! TARGET_SOFT_FLOAT" + "fcmp,dbl,%Y2 %r0,%r1" + [(set_attr "length" "4") + (set_attr "type" "fpcc")]) ;; scc insns. @@ -379,19 +547,32 @@ [(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" "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" "12")]) + ;; 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: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") @@ -461,6 +642,17 @@ [(set_attr "type" "binary") (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. (define_insn "" @@ -473,6 +665,17 @@ [(set_attr "type" "binary") (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 ; make better code than the general incscc pattern. @@ -486,6 +689,17 @@ [(set_attr "type" "binary") (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") (minus:SI (match_operand:SI 1 "register_operand" "0,?r") @@ -549,6 +763,29 @@ (set_attr "length" "8,8")]) ;;; Experimental conditional move patterns +(define_expand "movsicc" + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else:SI + (match_operator 1 "comparison_operator" + [(match_dup 4) + (match_dup 5)]) + (match_operand:SI 2 "reg_or_cint_move_operand" "") + (match_operand:SI 3 "reg_or_cint_move_operand" "")))] + "" + " +{ + enum rtx_code code = GET_CODE (operands[1]); + + if (hppa_branch_type != CMP_SI) + FAIL; + + /* operands[1] is currently the result of compare_from_rtx. We want to + emit a compare of the original operands. */ + operands[1] = gen_rtx (code, SImode, hppa_compare_op0, hppa_compare_op1); + operands[4] = hppa_compare_op0; + operands[5] = hppa_compare_op1; +}") + ; We need the first constraint alternative in order to avoid ; earlyclobbers on all other alternatives. (define_insn "" @@ -566,7 +803,7 @@ com%I4clr,%B5 %4,%3,%0\;ldi %1,%0 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 "type" "multi,multi,multi,multi,nullshift") (set_attr "length" "8,8,8,8,8")]) (define_insn "" @@ -587,7 +824,7 @@ com%I4clr,%B5 %4,%3,0\;ldi %1,%0 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 "type" "multi,multi,multi,nullshift,multi,multi,multi,nullshift") (set_attr "length" "8,8,8,8,8,8,8,8")]) ;; Conditional Branches @@ -762,7 +999,7 @@ ;; Note a long backward conditional branch with an annulled delay slot -;; has a length of 12. +;; has a length of 12. (define_insn "" [(set (pc) (if_then_else @@ -774,11 +1011,11 @@ "" "* { - 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") + (set (attr "length") (if_then_else (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) (const_int 8188)) (const_int 4) @@ -797,11 +1034,11 @@ "" "* { - 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") + (set (attr "length") (if_then_else (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) (const_int 8188)) (const_int 4) @@ -815,19 +1052,39 @@ (const_int 1) (match_operand:SI 1 "uint5_operand" "")) (const_int 0)) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] + (label_ref (match_operand 2 "" "")) + (pc)))] "" "* { - return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), - (operands[3] != pc_rtx), - insn, 0); + return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), + get_attr_length (insn), 0, insn, 0); }" [(set_attr "type" "cbranch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) + (set (attr "length") + (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4) + (const_int 8)))]) + +(define_insn "" + [(set (pc) + (if_then_else + (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand:SI 1 "uint5_operand" "")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "" + "* +{ + return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), + get_attr_length (insn), 1, insn, 0); +}" +[(set_attr "type" "cbranch") + (set (attr "length") + (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) (const_int 8188)) (const_int 4) (const_int 8)))]) @@ -839,19 +1096,39 @@ (const_int 1) (match_operand:SI 1 "uint5_operand" "")) (const_int 0)) - (match_operand 2 "pc_or_label_operand" "") - (match_operand 3 "pc_or_label_operand" "")))] + (label_ref (match_operand 2 "" "")) + (pc)))] "" "* { - return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), - get_attr_length (insn), - (operands[3] != pc_rtx), - insn, 1); + return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), + get_attr_length (insn), 0, insn, 1); }" [(set_attr "type" "cbranch") - (set (attr "length") - (if_then_else (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8)))) + (set (attr "length") + (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) + (const_int 8188)) + (const_int 4) + (const_int 8)))]) + +(define_insn "" + [(set (pc) + (if_then_else + (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") + (const_int 1) + (match_operand:SI 1 "uint5_operand" "")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "" + "* +{ + return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), + get_attr_length (insn), 1, insn, 1); +}" +[(set_attr "type" "cbranch") + (set (attr "length") + (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8)))) (const_int 8188)) (const_int 4) (const_int 8)))]) @@ -861,7 +1138,7 @@ [(set (pc) (if_then_else (ne (reg:CCFP 0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] - "" + "! TARGET_SOFT_FLOAT" "* { if (INSN_ANNULLED_BRANCH_P (insn)) @@ -876,7 +1153,7 @@ [(set (pc) (if_then_else (ne (reg:CCFP 0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] - "" + "! TARGET_SOFT_FLOAT" "* { if (INSN_ANNULLED_BRANCH_P (insn)) @@ -904,7 +1181,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"))] "" " @@ -918,7 +1195,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"))] "" @@ -944,14 +1221,15 @@ (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"))] - "register_operand (operands[0], SImode) - || reg_or_0_operand (operands[1], SImode)" + [(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)) + && ! TARGET_SOFT_FLOAT" "@ - copy %r1,%0 + copy %1,%0 ldi %1,%0 ldil L'%1,%0 zdepi %Z1,%0 @@ -961,9 +1239,28 @@ fcpy,sgl %r1,%0 fldws%F1 %1,%0 fstws%F0 %1,%0" - [(set_attr "type" "move,move,move,move,load,store,move,fpalu,fpload,fpstore") + [(set_attr "type" "move,move,move,shift,load,store,move,fpalu,fpload,fpstore") (set_attr "length" "4,4,4,4,4,4,4,4,4,4")]) +(define_insn "" + [(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" + "=r,r,r,r,r,Q,*q") + (match_operand:SI 1 "move_operand" + "r,J,N,K,Q,rM,rM"))] + "(register_operand (operands[0], SImode) + || reg_or_0_operand (operands[1], SImode)) + && TARGET_SOFT_FLOAT" + "@ + copy %1,%0 + ldi %1,%0 + ldil L'%1,%0 + zdepi %Z1,%0 + ldw%M1 %1,%0 + stw%M0 %r1,%0 + mtsar %r1" + [(set_attr "type" "move,move,move,move,load,store,move") + (set_attr "length" "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 ;; the index, due to PA's idea of segment selection using the top bits @@ -982,9 +1279,14 @@ ;; 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 + (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")) @@ -993,9 +1295,9 @@ "* { if (GET_CODE (operands[3]) == CONST_INT) - return \"sh2add %1,%2,%0\;ldw %3(0,%0),%0\"; + return \"sh2addl %1,%2,%0\;ldw %3(0,%0),%0\"; else - return \"sh2add %1,%2,%0\;ldwx %3(0,%0),%0\"; + return \"sh2addl %1,%2,%0\;ldwx %3(0,%0),%0\"; }" [(set_attr "type" "load") (set_attr "length" "8")]) @@ -1038,7 +1340,7 @@ [(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" "")))] "" "* @@ -1054,7 +1356,7 @@ [(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" "")))] "" "* @@ -1067,10 +1369,11 @@ (set_attr "length" "4")]) ;; For pic -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "pic_operand" "i")) - (clobber (match_scratch:SI 2 "=a"))] +;; Note since this pattern can be created at reload time (via movsi), all +;; the same rules for movsi apply here. (no new pseudos, no temporaries). +(define_insn "pic_load_label" + [(set (match_operand:SI 0 "register_operand" "=a") + (match_operand:SI 1 "pic_label_operand" ""))] "" "* { @@ -1081,14 +1384,60 @@ xoperands[0] = operands[0]; xoperands[1] = operands[1]; xoperands[2] = label_rtx; - output_asm_insn (\"bl .+8,%0\;addil L'%1-%2,%0\", xoperands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label_rtx)); - output_asm_insn (\"ldo R'%1-%2(1),%0\", xoperands); + output_asm_insn (\"bl .+8,%0\", xoperands); + output_asm_insn (\"depi 0,31,2,%0\", xoperands); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (label_rtx)); + + /* If we're trying to load the address of a label that happens to be + close, then we can use a shorter sequence. */ + if (GET_CODE (operands[1]) == LABEL_REF + && insn_addresses + && abs (insn_addresses[INSN_UID (XEXP (operands[1], 0))] + - insn_current_address) < 8100) + { + /* Prefixing with R% here is wrong, it extracts just 11 bits and is + always non-negative. */ + output_asm_insn (\"ldo %1-%2(%0),%0\", xoperands); + } + else + { + output_asm_insn (\"addil L%%%1-%2,%0\", xoperands); + output_asm_insn (\"ldo R%%%1-%2(%0),%0\", xoperands); + } return \"\"; - } -" +}" [(set_attr "type" "multi") - (set_attr "length" "12")]) + (set_attr "length" "16")]) ; 12 or 16 + +(define_insn "pic2_highpart" + [(set (match_operand:SI 0 "register_operand" "=a") + (plus:SI (match_operand:SI 1 "register_operand" "r") + (high:SI (match_operand 2 "" ""))))] + "symbolic_operand (operands[2], Pmode) + && ! function_label_operand (operands[2]) + && flag_pic == 2" + "addil LT'%G2,%1" + [(set_attr "type" "binary") + (set_attr "length" "4")]) + +; We need this to make sure CSE doesn't simplify a memory load with a +; symbolic address, whose content it think it knows. For PIC, what CSE +; think is the real value will be the address of that value. +(define_insn "pic2_lo_sum" + [(set (match_operand:SI 0 "register_operand" "=r") + (mem:SI (lo_sum:SI (match_operand:SI 1 "register_operand" "r") + (unspec:SI [(match_operand:SI 2 "symbolic_operand" "")] 0))))] + "" + "* +{ + if (flag_pic != 2) + abort (); + return \"ldw RT'%G2(%1),%0\"; +}" + [(set_attr "type" "load") + (set_attr "length" "4")]) + ;; Always use addil rather than ldil;add sequences. This allows the ;; HP linker to eliminate the dp relocation if the symbolic operand @@ -1096,27 +1445,27 @@ (define_insn "" [(set (match_operand:SI 0 "register_operand" "=a") (high:SI (match_operand 1 "" "")))] - "symbolic_operand(operands[1], Pmode) + "symbolic_operand (operands[1], Pmode) && ! function_label_operand (operands[1]) - && ! read_only_operand (operands[1])" - "@ - addil L'%G1,%%r27" + && ! read_only_operand (operands[1]) + && ! flag_pic" + "addil LR'%G1,%%r27" [(set_attr "type" "binary") (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" "4,8")]) @@ -1124,48 +1473,89 @@ (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (high:SI (match_operand:SI 1 "function_label_operand" "")))] - "" + "!TARGET_PORTABLE_RUNTIME" "ldil LP'%G1,%0" [(set_attr "type" "move") (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 1 "" "")))] - "check_pic (1)" + (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 "" "")))] + "(!flag_pic || !symbolic_operand (operands[1]), Pmode) + && !is_function_label_plus_const (operands[1])" + "* +{ + if (symbolic_operand (operands[1], Pmode)) + return \"ldil LR'%G1,%0\"; + else + return \"ldil L'%G1,%0\"; +}" + [(set_attr "type" "move") + (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" ""))) - (clobber (match_operand:SI 3 "register_operand" "=r"))] - "" - "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" "16")]) + (match_operand:SI 2 "function_label_operand" "")))] + "!TARGET_PORTABLE_RUNTIME" + "ldo RP'%G2(%1),%0" + [(set_attr "type" "move") + (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") (lo_sum:SI (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "immediate_operand" "i")))] - "" + (match_operand:SI 2 "function_label_operand" "")))] + "TARGET_PORTABLE_RUNTIME" "ldo R'%G2(%1),%0" - [(set_attr "length" "4")]) + [(set_attr "type" "move") + (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])" + "* +{ + if (flag_pic && symbolic_operand (operands[2], Pmode)) + abort (); + else if (symbolic_operand (operands[2], Pmode)) + return \"ldo RR'%G2(%1),%0\"; + else + return \"ldo R'%G2(%1),%0\"; +}" + [(set_attr "type" "move") + (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" ""))] - "" + "! (flag_pic && pic_label_operand (operands[1], SImode))" [(set (match_dup 2) (high:SI (match_dup 1))) (set (match_dup 0) (lo_sum:SI (match_dup 2) (match_dup 1)))] "") @@ -1181,12 +1571,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 @@ -1194,7 +1584,7 @@ sth%M0 %r1,%0 mtsar %r1 fcpy,sgl %r1,%0" - [(set_attr "type" "move,move,move,move,load,store,move,fpalu") + [(set_attr "type" "move,move,move,shift,load,store,move,fpalu") (set_attr "length" "4,4,4,4,4,4,4,4")]) (define_insn "" @@ -1210,9 +1600,14 @@ ;; 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 + (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")) @@ -1221,9 +1616,9 @@ "* { if (GET_CODE (operands[3]) == CONST_INT) - return \"sh1add %2,%1,%0\;ldh %3(0,%0),%0\"; + return \"sh1addl %2,%1,%0\;ldh %3(0,%0),%0\"; else - return \"sh1add %2,%1,%0\;ldhx %3(0,%0),%0\"; + return \"sh1addl %2,%1,%0\;ldhx %3(0,%0),%0\"; }" [(set_attr "type" "load") (set_attr "length" "8")]) @@ -1252,8 +1647,8 @@ (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") - (high:HI (match_operand 1 "" "")))] - "check_pic (1)" + (high:HI (match_operand 1 "const_int_operand" "")))] + "" "ldil L'%G1,%0" [(set_attr "type" "move") (set_attr "length" "4")]) @@ -1261,10 +1656,11 @@ (define_insn "" [(set (match_operand:HI 0 "register_operand" "=r") (lo_sum:HI (match_operand:HI 1 "register_operand" "r") - (match_operand 2 "immediate_operand" "i")))] + (match_operand 2 "const_int_operand" "")))] "" "ldo R'%G2(%1),%0" - [(set_attr "length" "4")]) + [(set_attr "type" "move") + (set_attr "length" "4")]) (define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") @@ -1277,12 +1673,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 @@ -1290,7 +1686,7 @@ stb%M0 %r1,%0 mtsar %r1 fcpy,sgl %r1,%0" - [(set_attr "type" "move,move,move,move,load,store,move,fpalu") + [(set_attr "type" "move,move,move,shift,load,store,move,fpalu") (set_attr "length" "4,4,4,4,4,4,4,4")]) (define_insn "" @@ -1320,8 +1716,8 @@ ;; 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)) @@ -1337,7 +1733,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)); @@ -1372,14 +1768,15 @@ ;; ;; 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") - (match_operand:DF 1 "" "?E,m"))] + [(set (match_operand:DF 0 "general_operand" "=?r,f") + (match_operand:DF 1 "" "?F,m"))] "GET_CODE (operands[1]) == CONST_DOUBLE - && operands[1] != CONST0_RTX (DFmode)" + && operands[1] != CONST0_RTX (DFmode) + && ! TARGET_SOFT_FLOAT" "* return (which_alternative == 0 ? output_move_double (operands) : \" fldds%F1 %1,%0\");" [(set_attr "type" "move,fpload") @@ -1395,16 +1792,50 @@ 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,?o,?Q,fx,*&r,*&r") + "=f,*r,Q,?o,?Q,f,*&r,*&r") (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand" - "fxG,*rG,fx,*r,*r,Q,o,Q"))] - "register_operand (operands[0], DFmode) - || reg_or_0_operand (operands[1], DFmode)" + "fG,*rG,f,*r,*r,Q,o,Q"))] + "(register_operand (operands[0], DFmode) + || reg_or_0_operand (operands[1], DFmode)) + && ! TARGET_SOFT_FLOAT" "* { - 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); @@ -1413,11 +1844,26 @@ (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 "reg_or_nonsymb_mem_operand" + "=r,?o,?Q,&r,&r") + (match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand" + "rG,r,r,o,Q"))] + "(register_operand (operands[0], DFmode) + || reg_or_0_operand (operands[1], DFmode)) + && TARGET_SOFT_FLOAT" + "* +{ + return output_move_double (operands); +}" + [(set_attr "type" "move,store,store,load,load") + (set_attr "length" "8,8,16,8,16")]) + +(define_insn "" + [(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" + "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" "flddx,s %1(0,%2),%0" [(set_attr "type" "fpload") (set_attr "length" "4")]) @@ -1425,23 +1871,28 @@ ;; 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. +;; else as a temporary. (define_insn "" - [(set (match_operand:DF 0 "register_operand" "=fx") - (mem:DF (plus:SI - (plus:SI + [(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" + "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT && reload_in_progress" "* { if (GET_CODE (operands[3]) == CONST_INT) - return \"sh3add %1,%2,%1\;fldds %3(0,%1),%0\"; + return \"sh3addl %1,%2,%1\;fldds %3(0,%1),%0\"; else - return \"sh3add %1,%2,%1\;flddx %3(0,%1),%0\"; + return \"sh3addl %1,%2,%1\;flddx %3(0,%1),%0\"; }" [(set_attr "type" "fpload") (set_attr "length" "8")]) @@ -1450,8 +1901,8 @@ [(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"))] - "! TARGET_DISABLE_INDEXING" + (match_operand:DF 0 "register_operand" "f"))] + "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" "fstdx,s %0,%1(0,%2)" [(set_attr "type" "fpstore") (set_attr "length" "4")]) @@ -1459,23 +1910,28 @@ ;; 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. +;; else as a temporary. (define_insn "" - [(set (mem:DF (plus:SI - (plus:SI + [(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" "=fx"))] - "! TARGET_DISABLE_INDEXING && reload_in_progress" + (match_operand:DF 0 "register_operand" "f"))] + "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT && reload_in_progress" "* { if (GET_CODE (operands[3]) == CONST_INT) - return \"sh3add %1,%2,%1\;fstds %3(0,%1),%0\"; + return \"sh3addl %1,%2,%1\;fstds %0,%3(0,%1)\"; else - return \"sh3add %1,%2,%1\;fstdx %3(0,%1),%0\"; + return \"sh3addl %1,%2,%1\;fstdx %0,%3(0,%1)\"; }" [(set_attr "type" "fpstore") (set_attr "length" "8")]) @@ -1491,8 +1947,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"))] "" " @@ -1507,7 +1963,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"))] "" " @@ -1523,7 +1979,7 @@ (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (high:DI (match_operand 1 "" "")))] - "check_pic (1)" + "" "* { rtx op0 = operands[0]; @@ -1544,11 +2000,11 @@ else if (GET_CODE (op1) == CONST_DOUBLE) { operands[0] = operand_subword (op0, 1, 0, DImode); - operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1)); + operands[1] = GEN_INT (CONST_DOUBLE_LOW (op1)); output_asm_insn (\"ldil L'%1,%0\", operands); operands[0] = operand_subword (op0, 0, 0, DImode); - operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1)); + operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1)); output_asm_insn (singlemove_string (operands), operands); return \"\"; } @@ -1562,11 +2018,12 @@ (define_insn "" [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" - "=r,o,Q,&r,&r,&r,x,x,*T") + "=r,o,Q,&r,&r,&r,f,f,*T") (match_operand:DI 1 "general_operand" - "rM,r,r,o,Q,i,xM,*T,x"))] - "register_operand (operands[0], DImode) - || reg_or_0_operand (operands[1], DImode)" + "rM,r,r,o,Q,i,fM,*T,f"))] + "(register_operand (operands[0], DImode) + || reg_or_0_operand (operands[1], DImode)) + && ! TARGET_SOFT_FLOAT" "* { if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]) @@ -1574,11 +2031,26 @@ return output_fp_move_double (operands); return output_move_double (operands); }" - [(set_attr "type" "move,store,store,load,load,misc,fpalu,fpload,fpstore") + [(set_attr "type" "move,store,store,load,load,multi,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 "reg_or_nonsymb_mem_operand" + "=r,o,Q,&r,&r,&r") + (match_operand:DI 1 "general_operand" + "rM,r,r,o,Q,i"))] + "(register_operand (operands[0], DImode) + || reg_or_0_operand (operands[1], DImode)) + && TARGET_SOFT_FLOAT" + "* +{ + return output_move_double (operands); +}" + [(set_attr "type" "move,store,store,load,load,multi") + (set_attr "length" "8,8,16,8,16,16")]) + +(define_insn "" + [(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")))] "" @@ -1587,14 +2059,13 @@ /* Don't output a 64 bit constant, since we can't trust the assembler to handle it correctly. */ if (GET_CODE (operands[2]) == CONST_DOUBLE) - operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2])); + operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2])); if (which_alternative == 1) output_asm_insn (\"copy %1,%0\", operands); return \"ldo R'%G2(%R1),%R0\"; }" - ;; Need to set length for this arith insn because operand2 - ;; is not an "arith_operand". - [(set_attr "length" "4,8")]) + [(set_attr "type" "move,move") + (set_attr "length" "4,8")]) ;; This pattern forces (set (reg:SF ...) (const_double ...)) ;; to be reloaded by putting the constant into memory when @@ -1602,14 +2073,15 @@ ;; ;; 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") - (match_operand:SF 1 "" "?E,m"))] + [(set (match_operand:SF 0 "general_operand" "=?r,f") + (match_operand:SF 1 "" "?F,m"))] "GET_CODE (operands[1]) == CONST_DOUBLE - && operands[1] != CONST0_RTX (SFmode)" + && operands[1] != CONST0_RTX (SFmode) + && ! TARGET_SOFT_FLOAT" "* return (which_alternative == 0 ? singlemove_string (operands) : \" fldws%F1 %1,%0\");" [(set_attr "type" "move,fpload") @@ -1625,13 +2097,47 @@ 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"))] - "register_operand (operands[0], SFmode) - || reg_or_0_operand (operands[1], SFmode)" + "fG,rG,Q,Q,f,rG"))] + "(register_operand (operands[0], SFmode) + || reg_or_0_operand (operands[1], SFmode)) + && ! TARGET_SOFT_FLOAT" "@ fcpy,sgl %r1,%0 copy %r1,%0 @@ -1643,11 +2149,26 @@ (set_attr "length" "4,4,4,4,4,4")]) (define_insn "" - [(set (match_operand:SF 0 "register_operand" "=fx") + [(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand" + "=r,r,Q") + (match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand" + "rG,Q,rG"))] + "(register_operand (operands[0], SFmode) + || reg_or_0_operand (operands[1], SFmode)) + && TARGET_SOFT_FLOAT" + "@ + copy %r1,%0 + ldw%M1 %1,%0 + stw%M0 %r1,%0" + [(set_attr "type" "move,load,store") + (set_attr "length" "4,4,4")]) + +(define_insn "" + [(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" + "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" "fldwx,s %1(0,%2),%0" [(set_attr "type" "fpload") (set_attr "length" "4")]) @@ -1655,23 +2176,28 @@ ;; 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. +;; else as a temporary. (define_insn "" - [(set (match_operand:SF 0 "register_operand" "=fx") - (mem:SF (plus:SI - (plus:SI + [(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" + "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT && reload_in_progress" "* { if (GET_CODE (operands[3]) == CONST_INT) - return \"sh2add %1,%2,%1\;fldws %3(0,%1),%0\"; + return \"sh2addl %1,%2,%1\;fldws %3(0,%1),%0\"; else - return \"sh2add %1,%2,%1\;fldwx %3(0,%1),%0\"; + return \"sh2addl %1,%2,%1\;fldwx %3(0,%1),%0\"; }" [(set_attr "type" "fpload") (set_attr "length" "8")]) @@ -1680,8 +2206,8 @@ [(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"))] - "! TARGET_DISABLE_INDEXING" + (match_operand:SF 0 "register_operand" "f"))] + "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT" "fstwx,s %0,%1(0,%2)" [(set_attr "type" "fpstore") (set_attr "length" "4")]) @@ -1689,23 +2215,28 @@ ;; 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. +;; else as a temporary. (define_insn "" - [(set (mem:SF (plus:SI - (plus:SI + [(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" "=fx"))] - "! TARGET_DISABLE_INDEXING && reload_in_progress" + (match_operand:SF 0 "register_operand" "f"))] + "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT && reload_in_progress" "* { if (GET_CODE (operands[3]) == CONST_INT) - return \"sh2add %1,%2,%1\;fstds %3(0,%1),%0\"; + return \"sh2addl %1,%2,%1\;fstws %0,%3(0,%1)\"; else - return \"sh2add %1,%2,%1\;fstdx %3(0,%1),%0\"; + return \"sh2addl %1,%2,%1\;fstwx %0,%3(0,%1)\"; }" [(set_attr "type" "fpstore") (set_attr "length" "8")]) @@ -1720,7 +2251,8 @@ "@ extru %1,31,16,%0 ldh%M1 %1,%0" - [(set_attr "type" "unary,load")]) + [(set_attr "type" "shift,load") + (set_attr "length" "4,4")]) (define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r,r") @@ -1730,7 +2262,8 @@ "@ extru %1,31,8,%0 ldb%M1 %1,%0" - [(set_attr "type" "unary,load")]) + [(set_attr "type" "shift,load") + (set_attr "length" "4,4")]) (define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -1740,7 +2273,8 @@ "@ extru %1,31,8,%0 ldb%M1 %1,%0" - [(set_attr "type" "unary,load")]) + [(set_attr "type" "shift,load") + (set_attr "length" "4,4")]) ;;- sign extension instructions @@ -1749,39 +2283,44 @@ (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))] "" "extrs %1,31,16,%0" - [(set_attr "type" "unary")]) + [(set_attr "type" "shift") + (set_attr "length" "4")]) (define_insn "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" "extrs %1,31,8,%0" - [(set_attr "type" "unary")]) + [(set_attr "type" "shift") + (set_attr "length" "4")]) (define_insn "extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))] "" "extrs %1,31,8,%0" - [(set_attr "type" "unary")]) + [(set_attr "type" "shift") + (set_attr "length" "4")]) ;; 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")))] + "! TARGET_SOFT_FLOAT" "fcnvff,sgl,dbl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fcnvff,dbl,sgl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) ;; Conversion between fixed point and floating point. ;; Note that among the fix-to-float insns @@ -1795,37 +2334,39 @@ ;; 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")))] - "" + "! TARGET_SOFT_FLOAT" "fldws %1,%0\;fcnvxf,sgl,sgl %0,%0" [(set_attr "type" "fpalu") (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")))] + "! TARGET_SOFT_FLOAT" "fcnvxf,sgl,sgl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) ;; 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")))] - "" + "! TARGET_SOFT_FLOAT" "fldws %1,%0\;fcnvxf,sgl,dbl %0,%0" [(set_attr "type" "fpalu") (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")))] + "! TARGET_SOFT_FLOAT" "fcnvxf,sgl,dbl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (define_expand "floatunssisf2" [(set (subreg:SI (match_dup 2) 1) @@ -1834,7 +2375,7 @@ (const_int 0)) (set (match_operand:SF 0 "general_operand" "") (float:SF (match_dup 2)))] - "TARGET_SNAKE" + "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" "operands[2] = gen_reg_rtx (DImode);") (define_expand "floatunssidf2" @@ -1844,53 +2385,59 @@ (const_int 0)) (set (match_operand:DF 0 "general_operand" "") (float:DF (match_dup 2)))] - "TARGET_SNAKE" + "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" "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")))] - "TARGET_SNAKE" + [(set (match_operand:SF 0 "general_operand" "=f") + (float:SF (match_operand:DI 1 "register_operand" "f")))] + "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" "fcnvxf,dbl,sgl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (define_insn "floatdidf2" - [(set (match_operand:DF 0 "general_operand" "=x") - (float:DF (match_operand:DI 1 "register_operand" "x")))] - "TARGET_SNAKE" + [(set (match_operand:DF 0 "general_operand" "=f") + (float:DF (match_operand:DI 1 "register_operand" "f")))] + "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" "fcnvxf,dbl,dbl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) ;; 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"))))] + "! TARGET_SOFT_FLOAT" "fcnvfxt,sgl,sgl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (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"))))] + "! TARGET_SOFT_FLOAT" "fcnvfxt,dbl,sgl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (define_insn "fix_truncsfdi2" - [(set (match_operand:DI 0 "register_operand" "=x") - (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "x"))))] - "TARGET_SNAKE" + [(set (match_operand:DI 0 "register_operand" "=f") + (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))] + "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" "fcnvfxt,sgl,dbl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (define_insn "fix_truncdfdi2" - [(set (match_operand:DI 0 "register_operand" "=x") - (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "x"))))] - "TARGET_SNAKE" + [(set (match_operand:DI 0 "register_operand" "=f") + (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))] + "TARGET_SNAKE && ! TARGET_SOFT_FLOAT" "fcnvfxt,dbl,dbl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) ;;- arithmetic instructions @@ -1911,14 +2458,17 @@ else return \"add %R2,%R1,%R0\;addc %2,%1,%0\"; }" - [(set_attr "length" "8")]) + [(set_attr "type" "binary") + (set_attr "length" "8")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (not:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")))] "" - "uaddcm %2,%1,%0") + "uaddcm %2,%1,%0" + [(set_attr "type" "binary") + (set_attr "length" "4")]) ;; define_splits to optimize cases of adding a constant integer ;; to a register when the constant does not fit in 14 bits. */ @@ -1927,7 +2477,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)))] @@ -1952,27 +2502,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; }") @@ -1982,8 +2532,29 @@ (match_operand:SI 2 "arith_operand" "r,J")))] "" "@ - add %1,%2,%0 - ldo %2(%1),%0") + addl %1,%2,%0 + ldo %2(%1),%0" + [(set_attr "type" "binary,binary") + (set_attr "length" "4,4")]) + +;; Disgusting kludge to work around reload bugs with frame pointer +;; elimination. Similar to other magic reload patterns in the +;; indexed memory operations. +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=&r") + (plus:SI (plus:SI (match_operand:SI 1 "register_operand" "%r") + (match_operand:SI 2 "register_operand" "r")) + (match_operand:SI 3 "const_int_operand" "rL")))] + "reload_in_progress" + "* +{ + if (GET_CODE (operands[3]) == CONST_INT) + return \"ldo %3(%2),%0\;addl %1,%0,%0\"; + else + return \"addl %3,%2,%0\;addl %1,%0,%0\"; +}" + [(set_attr "type" "binary") + (set_attr "length" "8")]) (define_insn "subdi3" [(set (match_operand:DI 0 "register_operand" "=r") @@ -1991,7 +2562,8 @@ (match_operand:DI 2 "register_operand" "r")))] "" "sub %R1,%R2,%R0\;subb %1,%2,%0" - [(set_attr "length" "8")]) + [(set_attr "type" "binary") + (set_attr "length" "8")]) (define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -2000,7 +2572,9 @@ "" "@ sub %1,%2,%0 - subi %1,%2,%0") + subi %1,%2,%0" + [(set_attr "type" "binary,binary") + (set_attr "length" "4,4")]) ;; Clobbering a "register_operand" instead of a match_scratch ;; in operand3 of millicode calls avoids spilling %r1 and @@ -2011,7 +2585,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))]) @@ -2019,7 +2593,7 @@ "" " { - if (TARGET_SNAKE && ! TARGET_DISABLE_FPREGS) + if (TARGET_SNAKE && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT) { rtx scratch = gen_reg_rtx (DImode); operands[1] = force_reg (SImode, operands[1]); @@ -2030,16 +2604,26 @@ 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"))))] - "TARGET_SNAKE && ! TARGET_DISABLE_FPREGS" + [(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 && ! TARGET_SOFT_FLOAT" "xmpyu %1,%2,%0" - [(set_attr "type" "fpmul")]) + [(set_attr "type" "fpmuldbl") + (set_attr "length" "4")]) + +(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 && ! TARGET_SOFT_FLOAT" + "xmpyu %1,%R2,%0" + [(set_attr "type" "fpmuldbl") + (set_attr "length" "4")]) (define_insn "" [(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25))) @@ -2049,14 +2633,21 @@ (clobber (reg:SI 31))] "" "* return output_mul_insn (0, insn);" - [(set_attr "type" "milli")]) + [(set_attr "type" "milli") + (set (attr "length") + (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") + (const_int 0)) + (eq (symbol_ref "TARGET_MILLICODE_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))]) @@ -2064,44 +2655,35 @@ "" " { - operands[3] = gen_reg_rtx(SImode); - if (!(GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const(operands, 0))) - { - emit_move_insn (gen_rtx (REG, SImode, 26), operands[1]); - emit_move_insn (gen_rtx (REG, SImode, 25), operands[2]); - emit - (gen_rtx - (PARALLEL, VOIDmode, - gen_rtvec (5, gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 29), - gen_rtx (DIV, SImode, - gen_rtx (REG, SImode, 26), - gen_rtx (REG, SImode, 25))), - 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))))); - emit_move_insn (operands[0], gen_rtx (REG, SImode, 29)); - } - DONE; + operands[3] = gen_reg_rtx (SImode); + if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 0)) + DONE; }") (define_insn "" [(set (reg:SI 29) - (div:SI (reg:SI 26) (match_operand:SI 0 "div_operand" ""))) + (div:SI (reg:SI 26) (match_operand:SI 0 "div_operand" ""))) (clobber (match_operand:SI 1 "register_operand" "=a")) (clobber (reg:SI 26)) (clobber (reg:SI 25)) (clobber (reg:SI 31))] - "" - "* - return output_div_insn (operands, 0, insn);" - [(set_attr "type" "milli")]) + "" + "* + return output_div_insn (operands, 0, insn);" + [(set_attr "type" "milli") + (set (attr "length") + (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") + (const_int 0)) + (eq (symbol_ref "TARGET_MILLICODE_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))]) @@ -2109,44 +2691,35 @@ "" " { - operands[3] = gen_reg_rtx(SImode); - if (!(GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const(operands, 1))) - { - emit_move_insn (gen_rtx (REG, SImode, 26), operands[1]); - emit_move_insn (gen_rtx (REG, SImode, 25), operands[2]); - emit - (gen_rtx - (PARALLEL, VOIDmode, - gen_rtvec (5, gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 29), - gen_rtx (UDIV, SImode, - gen_rtx (REG, SImode, 26), - gen_rtx (REG, SImode, 25))), - 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))))); - emit_move_insn (operands[0], gen_rtx (REG, SImode, 29)); - } - DONE; + operands[3] = gen_reg_rtx (SImode); + if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 1)) + DONE; }") (define_insn "" [(set (reg:SI 29) - (udiv:SI (reg:SI 26) (match_operand:SI 0 "div_operand" ""))) + (udiv:SI (reg:SI 26) (match_operand:SI 0 "div_operand" ""))) (clobber (match_operand:SI 1 "register_operand" "=a")) (clobber (reg:SI 26)) (clobber (reg:SI 25)) (clobber (reg:SI 31))] - "" - "* - return output_div_insn (operands, 1, insn);" - [(set_attr "type" "milli")]) + "" + "* + return output_div_insn (operands, 1, insn);" + [(set_attr "type" "milli") + (set (attr "length") + (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") + (const_int 0)) + (eq (symbol_ref "TARGET_MILLICODE_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))]) @@ -2154,22 +2727,7 @@ "" " { - operands[3] = gen_reg_rtx(SImode); - emit_move_insn (gen_rtx (REG, SImode, 26), operands[1]); - emit_move_insn (gen_rtx (REG, SImode, 25), operands[2]); - emit - (gen_rtx - (PARALLEL, VOIDmode, - gen_rtvec (5, gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 29), - gen_rtx (MOD, SImode, - gen_rtx (REG, SImode, 26), - gen_rtx (REG, SImode, 25))), - 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))))); - emit_move_insn (operands[0], gen_rtx (REG, SImode, 29)); - DONE; + operands[3] = gen_reg_rtx (SImode); }") (define_insn "" @@ -2181,13 +2739,20 @@ "" "* return output_mod_insn (0, insn);" - [(set_attr "type" "milli")]) + [(set_attr "type" "milli") + (set (attr "length") + (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") + (const_int 0)) + (eq (symbol_ref "TARGET_MILLICODE_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))]) @@ -2195,22 +2760,7 @@ "" " { - operands[3] = gen_reg_rtx(SImode); - emit_move_insn (gen_rtx (REG, SImode, 26), operands[1]); - emit_move_insn (gen_rtx (REG, SImode, 25), operands[2]); - emit - (gen_rtx - (PARALLEL, VOIDmode, - gen_rtvec (5, gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 29), - gen_rtx (UMOD, SImode, - gen_rtx (REG, SImode, 26), - gen_rtx (REG, SImode, 25))), - 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))))); - emit_move_insn (operands[0], gen_rtx (REG, SImode, 29)); - DONE; + operands[3] = gen_reg_rtx (SImode); }") (define_insn "" @@ -2222,7 +2772,14 @@ "" "* return output_mod_insn (1, insn);" - [(set_attr "type" "milli")]) + [(set_attr "type" "milli") + (set (attr "length") + (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") + (const_int 0)) + (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS") + (const_int 0))) + (const_int 4) + (const_int 24)))]) ;;- and instructions ;; We define DImode `and` so with DImode `not` we can get @@ -2247,16 +2804,19 @@ (match_operand:DI 2 "register_operand" "r")))] "" "and %1,%2,%0\;and %R1,%R2,%R0" - [(set_attr "length" "8")]) + [(set_attr "type" "binary") + (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" "4")]) + [(set_attr "type" "binary,shift") + (set_attr "length" "4,4")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") @@ -2264,14 +2824,17 @@ (match_operand:DI 2 "register_operand" "r")))] "" "andcm %2,%1,%0\;andcm %R2,%R1,%R0" - [(set_attr "length" "8")]) + [(set_attr "type" "binary") + (set_attr "length" "8")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (and:SI (not:SI (match_operand:SI 1 "register_operand" "r")) (match_operand:SI 2 "register_operand" "r")))] "" - "andcm %2,%1,%0") + "andcm %2,%1,%0" + [(set_attr "type" "binary") + (set_attr "length" "4")]) (define_expand "iordi3" [(set (match_operand:DI 0 "register_operand" "") @@ -2292,7 +2855,8 @@ (match_operand:DI 2 "register_operand" "r")))] "" "or %1,%2,%0\;or %R1,%R2,%R0" - [(set_attr "length" "8")]) + [(set_attr "type" "binary") + (set_attr "length" "8")]) ;; Need a define_expand because we've run out of CONST_OK... characters. (define_expand "iorsi3" @@ -2307,20 +2871,22 @@ }") (define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (ior:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "ior_operand" "")))] + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ior:SI (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "ior_operand" "M,i")))] "" "* return output_ior (operands); " - [(set_attr "type" "binary") - (set_attr "length" "4")]) + [(set_attr "type" "binary,shift") + (set_attr "length" "4,4")]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (ior:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r")))] "" - "or %1,%2,%0") + "or %1,%2,%0" + [(set_attr "type" "binary") + (set_attr "length" "4")]) (define_expand "xordi3" [(set (match_operand:DI 0 "register_operand" "") @@ -2341,14 +2907,17 @@ (match_operand:DI 2 "register_operand" "r")))] "" "xor %1,%2,%0\;xor %R1,%R2,%R0" - [(set_attr "length" "8")]) + [(set_attr "type" "binary") + (set_attr "length" "8")]) (define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r") (xor:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "register_operand" "r")))] "" - "xor %1,%2,%0") + "xor %1,%2,%0" + [(set_attr "type" "binary") + (set_attr "length" "4")]) (define_insn "negdi2" [(set (match_operand:DI 0 "register_operand" "=r") @@ -2363,7 +2932,8 @@ (neg:SI (match_operand:SI 1 "register_operand" "r")))] "" "sub 0,%1,%0" - [(set_attr "type" "unary")]) + [(set_attr "type" "unary") + (set_attr "length" "4")]) (define_expand "one_cmpldi2" [(set (match_operand:DI 0 "register_operand" "") @@ -2388,115 +2958,130 @@ (not:SI (match_operand:SI 1 "register_operand" "r")))] "" "uaddcm 0,%1,%0" - [(set_attr "type" "unary")]) + [(set_attr "type" "unary") + (set_attr "length" "4")]) ;; 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")))] + "! TARGET_SOFT_FLOAT" "fadd,dbl %1,%2,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fadd,sgl %1,%2,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fsub,dbl %1,%2,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fsub,sgl %1,%2,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fmpy,dbl %1,%2,%0" - [(set_attr "type" "fpmul")]) + [(set_attr "type" "fpmuldbl") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fmpy,sgl %1,%2,%0" - [(set_attr "type" "fpmul")]) + [(set_attr "type" "fpmulsgl") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fdiv,dbl %1,%2,%0" - [(set_attr "type" "fpdivdbl")]) + [(set_attr "type" "fpdivdbl") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fdiv,sgl %1,%2,%0" - [(set_attr "type" "fpdivsgl")]) + [(set_attr "type" "fpdivsgl") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fsub,dbl 0,%1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fsub,sgl 0,%1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fabs,dbl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fabs,sgl %1,%0" - [(set_attr "type" "fpalu")]) + [(set_attr "type" "fpalu") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fsqrt,dbl %1,%0" - [(set_attr "type" "fpsqrtdbl")]) + [(set_attr "type" "fpsqrtdbl") + (set_attr "length" "4")]) (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")))] + "! TARGET_SOFT_FLOAT" "fsqrt,sgl %1,%0" - [(set_attr "type" "fpsqrtsgl")]) + [(set_attr "type" "fpsqrtsgl") + (set_attr "length" "4")]) ;;- Shift instructions @@ -2526,20 +3111,29 @@ (match_operand:SI 3 "shadd_operand" "")) (match_operand:SI 1 "register_operand" "r")))] "" - "sh%O3add %2,%1,%0") + "sh%O3addl %2,%1,%0" + [(set_attr "type" "binary") + (set_attr "length" "4")]) ;; 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 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" "8")]) @@ -2554,14 +3148,14 @@ { rtx temp = gen_reg_rtx (SImode); emit_insn (gen_subsi3 (temp, GEN_INT (31), operands[2])); - if (GET_CODE (operands[1]) == CONST_INT) - emit_insn (gen_zvdep_imm (operands[0], operands[1], temp)); - else - emit_insn (gen_zvdep32 (operands[0], operands[1], temp)); + if (GET_CODE (operands[1]) == CONST_INT) + emit_insn (gen_zvdep_imm (operands[0], operands[1], temp)); + else + emit_insn (gen_zvdep32 (operands[0], operands[1], temp)); DONE; } - /* Make sure both inputs are not constants, - the recognizer can't handle that. */ + /* Make sure both inputs are not constants, + there are no patterns for that. */ operands[1] = force_reg (SImode, operands[1]); }") @@ -2571,7 +3165,7 @@ (match_operand:SI 2 "const_int_operand" "n")))] "" "zdep %1,%P2,%L2,%0" - [(set_attr "type" "binary") + [(set_attr "type" "shift") (set_attr "length" "4")]) ; Match cases of op1 a CONST_INT here that zvdep_imm doesn't handle. @@ -2588,7 +3182,9 @@ "" "@ zvdep %1,32,%0 - zvdepi %1,32,%0") + zvdepi %1,32,%0" + [(set_attr "type" "shift,shift") + (set_attr "length" "4,4")]) (define_insn "zvdep_imm" [(set (match_operand:SI 0 "register_operand" "=r") @@ -2602,7 +3198,43 @@ operands[2] = GEN_INT (4 + exact_log2 ((x >> 4) + 1)); operands[1] = GEN_INT ((x & 0xf) - 0x10); return \"zvdepi %1,%2,%0\"; -}") +}" + [(set_attr "type" "shift") + (set_attr "length" "4")]) + +(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\"; +}" + [(set_attr "type" "shift") + (set_attr "length" "4")]) + +(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\"; +}" + [(set_attr "type" "shift") + (set_attr "length" "4")]) (define_expand "ashrsi3" [(set (match_operand:SI 0 "register_operand" "") @@ -2626,7 +3258,7 @@ (match_operand:SI 2 "const_int_operand" "n")))] "" "extrs %1,%P2,%L2,%0" - [(set_attr "type" "binary") + [(set_attr "type" "shift") (set_attr "length" "4")]) (define_insn "vextrs32" @@ -2635,7 +3267,9 @@ (minus:SI (const_int 31) (match_operand:SI 2 "register_operand" "q"))))] "" - "vextrs %1,32,%0") + "vextrs %1,32,%0" + [(set_attr "type" "shift") + (set_attr "length" "4")]) (define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -2645,7 +3279,7 @@ "@ vshd 0,%1,%0 extru %1,%P2,%L2,%0" - [(set_attr "type" "binary") + [(set_attr "type" "shift") (set_attr "length" "4")]) (define_insn "rotrsi3" @@ -2663,7 +3297,7 @@ else return \"vshd %1,%1,%0\"; }" - [(set_attr "type" "binary") + [(set_attr "type" "shift") (set_attr "length" "4")]) (define_insn "rotlsi3" @@ -2676,7 +3310,7 @@ operands[2] = GEN_INT ((32 - INTVAL (operands[2])) & 31); return \"shd %1,%1,%2,%0\"; }" - [(set_attr "type" "binary") + [(set_attr "type" "shift") (set_attr "length" "4")]) (define_insn "" @@ -2688,7 +3322,7 @@ (match_operand:SI 4 "const_int_operand" "n"))]))] "INTVAL (operands[3]) + INTVAL (operands[4]) == 32" "shd %1,%2,%4,%0" - [(set_attr "type" "binary") + [(set_attr "type" "shift") (set_attr "length" "4")]) (define_insn "" @@ -2700,7 +3334,7 @@ (match_operand:SI 3 "const_int_operand" "n"))]))] "INTVAL (operands[3]) + INTVAL (operands[4]) == 32" "shd %1,%2,%4,%0" - [(set_attr "type" "binary") + [(set_attr "type" "shift") (set_attr "length" "4")]) (define_insn "" @@ -2716,7 +3350,7 @@ operands[2] = GEN_INT (31 - cnt); return \"zdep %1,%2,%3,%0\"; }" - [(set_attr "type" "binary") + [(set_attr "type" "shift") (set_attr "length" "4")]) ;; Unconditional and other jump instructions. @@ -2725,16 +3359,18 @@ [(return)] "hppa_can_use_return_insn_p ()" "bv%* 0(%%r2)" - [(set_attr "type" "branch")]) + [(set_attr "type" "branch") + (set_attr "length" "4")]) -;; 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)) (return)] "" "bv%* 0(%%r2)" - [(set_attr "type" "branch")]) + [(set_attr "type" "branch") + (set_attr "length" "4")]) (define_expand "prologue" [(const_int 0)] @@ -2746,7 +3382,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 ()); @@ -2766,7 +3402,8 @@ (use (match_operand:SI 0 "const_int_operand" ""))] "" "bl _mcount,%%r2\;ldo %0(%%r2),%%r25" - [(set_attr "length" "8")]) + [(set_attr "type" "multi") + (set_attr "length" "8")]) (define_insn "blockage" [(unspec_volatile [(const_int 2)] 0)] @@ -2774,6 +3411,13 @@ "" [(set_attr "length" "0")]) +(define_insn "switch_jump" + [(set:DI (pc) (label_ref (match_operand 0 "" "")))] + "" + "bl %l0,0%#" + [(set_attr "type" "uncond_branch") + (set_attr "length" "4")]) + (define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" @@ -2782,7 +3426,7 @@ (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 +;; 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)))) @@ -2850,22 +3494,24 @@ return \"sub,>> %0,%1,0\;blr,n %0,0\;b,n %l3\"; } }" - [(set_attr "length" "12")]) + [(set_attr "type" "multi") + (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) + rtx call_insn; + + if (TARGET_PORTABLE_RUNTIME) op = force_reg (SImode, XEXP (operands[0], 0)); else op = XEXP (operands[0], 0); @@ -2876,56 +3522,86 @@ 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])); + call_insn = emit_call_insn (gen_call_internal_symref (op, operands[1])); else - emit_call_insn (gen_call_internal_reg (op, operands[1])); + call_insn = 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)); + use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx); + + /* After each call we must restore the PIC register, even if it + doesn't appear to be used. + + This will set regs_ever_live for the callee saved register we + stored the PIC register in. */ + emit_move_insn (pic_offset_table_rtx, + gen_rtx (REG, SImode, PIC_OFFSET_TABLE_REGNUM_SAVED)); + emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx)); } DONE; }") (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" - "* + [(call (mem:SI (match_operand:SI 0 "call_operand_address" "")) + (match_operand 1 "" "i")) + (clobber (reg:SI 2)) + (use (const_int 0))] + "! TARGET_PORTABLE_RUNTIME" + "* { output_arg_descriptor (insn); return output_call (insn, operands[0], gen_rtx (REG, SImode, 2)); }" - [(set_attr "type" "call") - (set_attr "length" "4")]) + [(set_attr "type" "call") + (set (attr "length") + (if_then_else (lt (plus (symbol_ref "total_code_bytes") (pc)) + (const_int 240000)) + (const_int 4) + (if_then_else (ne (symbol_ref "TARGET_MILLICODE_LONG_CALLS") + (const_int 0)) + (const_int 64) + (const_int 52))))]) (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))] - "" - "copy %r0,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2" - [(set_attr "type" "dyncall") - (set_attr "length" "12")]) + [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) + (match_operand 1 "" "i")) + (clobber (reg:SI 2)) + (use (const_int 1))] + "" + "* +{ + if (TARGET_FAST_INDIRECT_CALLS) + return \"ble 0(%%sr4,%r0)\;copy %%r31,%%r2\"; + + /* Yuk! bl may not be able to reach $$dyncall. */ + if (TARGET_PORTABLE_RUNTIME || TARGET_MILLICODE_LONG_CALLS) + return \"copy %r0,%%r22\;ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\"; + else + return \"copy %r0,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\"; +}" + [(set_attr "type" "dyncall") + (set (attr "length") + (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") + (const_int 0)) + (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS") + (const_int 0))) + (const_int 12) + (const_int 24)))]) (define_expand "call_value" [(parallel [(set (match_operand 0 "" "") (call (match_operand:SI 1 "" "") (match_operand 2 "" ""))) (clobber (reg:SI 2))])] - ;;- Don't use operand 1 for most machines. "" " { rtx op; - - if (TARGET_LONG_CALLS) + rtx call_insn; + + if (TARGET_PORTABLE_RUNTIME) op = force_reg (SImode, XEXP (operands[1], 0)); else op = XEXP (operands[1], 0); @@ -2936,48 +3612,99 @@ 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])); + call_insn = emit_call_insn (gen_call_value_internal_symref (operands[0], + op, + operands[2])); else - emit_call_insn (gen_call_value_internal_reg (operands[0], op, operands[2])); + call_insn = 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)); + use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx); + + /* After each call we must restore the PIC register, even if it + doesn't appear to be used. + + This will set regs_ever_live for the callee saved register we + stored the PIC register in. */ + emit_move_insn (pic_offset_table_rtx, + gen_rtx (REG, SImode, PIC_OFFSET_TABLE_REGNUM_SAVED)); + emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx)); + + /* Gross. We have to keep the scheduler from moving the restore + of the PIC register away from the call. SCHED_GROUP_P is + supposed to do this, but for some reason the compiler will + go into an infinite loop when we use that. + + This method (blockage insn) may make worse code (then again + it may not since calls are nearly blockages anyway), but at + least it should work. */ + emit_insn (gen_blockage ()); + + /* Gross. We have to keep the scheduler from moving the restore + of the PIC register away from the call. SCHED_GROUP_P is + supposed to do this, but for some reason the compiler will + go into an infinite loop when we use that. + + This method (blockage insn) may make worse code (then again + it may not since calls are nearly blockages anyway), but at + least it should work. */ + emit_insn (gen_blockage ()); } DONE; }") (define_insn "call_value_internal_symref" - [(set (match_operand 0 "" "=rfx") + [(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" + "! TARGET_PORTABLE_RUNTIME" "* { output_arg_descriptor (insn); return output_call (insn, operands[1], gen_rtx (REG, SImode, 2)); }" - [(set_attr "type" "call") - (set_attr "length" "4")]) + [(set_attr "type" "call") + (set (attr "length") + (if_then_else (lt (plus (symbol_ref "total_code_bytes") (pc)) + (const_int 240000)) + (const_int 4) + (if_then_else (ne (symbol_ref "TARGET_MILLICODE_LONG_CALLS") + (const_int 0)) + (const_int 64) + (const_int 52))))]) (define_insn "call_value_internal_reg" - [(set (match_operand 0 "" "=rfx") + [(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. "" - "copy %r1,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2" - [(set_attr "type" "dyncall") - (set_attr "length" "12")]) + "* +{ + if (TARGET_FAST_INDIRECT_CALLS) + return \"ble 0(%%sr4,%r1)\;copy %%r31,%%r2\"; + + /* Yuk! bl may not be able to reach $$dyncall. */ + if (TARGET_PORTABLE_RUNTIME || TARGET_MILLICODE_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 (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") + (const_int 0)) + (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS") + (const_int 0))) + (const_int 12) + (const_int 24)))]) ;; Call subroutine returning any type. @@ -3010,14 +3737,17 @@ (define_insn "nop" [(const_int 0)] "" - "nop") + "nop" + [(set_attr "type" "move") + (set_attr "length" "4")]) ;;; Hope this is only within a function... (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") + (set_attr "length" "4")]) (define_insn "extzv" [(set (match_operand:SI 0 "register_operand" "=r") @@ -3025,7 +3755,19 @@ (match_operand:SI 2 "uint5_operand" "") (match_operand:SI 3 "uint5_operand" "")))] "" - "extru %1,%3+%2-1,%2,%0") + "extru %1,%3+%2-1,%2,%0" + [(set_attr "type" "shift") + (set_attr "length" "4")]) + +(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" + [(set_attr "type" "shift") + (set_attr "length" "4")]) (define_insn "extv" [(set (match_operand:SI 0 "register_operand" "=r") @@ -3033,7 +3775,19 @@ (match_operand:SI 2 "uint5_operand" "") (match_operand:SI 3 "uint5_operand" "")))] "" - "extrs %1,%3+%2-1,%2,%0") + "extrs %1,%3+%2-1,%2,%0" + [(set_attr "type" "shift") + (set_attr "length" "4")]) + +(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" + [(set_attr "type" "shift") + (set_attr "length" "4")]) (define_insn "insv" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,r") @@ -3043,7 +3797,9 @@ "" "@ dep %3,%2+%1-1,%1,%0 - depi %3,%2+%1-1,%1,%0") + depi %3,%2+%1-1,%1,%0" + [(set_attr "type" "shift,shift") + (set_attr "length" "4,4")]) ;; Optimize insertion of const_int values of type 1...1xxxx. (define_insn "" @@ -3057,7 +3813,9 @@ { operands[3] = GEN_INT ((INTVAL (operands[3]) & 0xf) - 0x10); return \"depi %3,%2+%1-1,%1,%0\"; -}") +}" + [(set_attr "type" "shift") + (set_attr "length" "4")]) ;; This insn is used for some loop tests, typically loops reversed when ;; strength reduction is used. It is actually created when the instruction @@ -3069,7 +3827,7 @@ [(set (pc) (if_then_else (match_operator 2 "comparison_operator" - [(plus:SI (match_operand:SI 0 "register_operand" "+!r,!*f*x,!*m") + [(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 "" "")) @@ -3079,7 +3837,7 @@ (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. +;; 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") @@ -3095,12 +3853,12 @@ ;; 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 + (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 + (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) (const_int 8188)) (const_int 24) @@ -3108,25 +3866,25 @@ ;; Loop counter in memory case. ;; Extra goo to deal with additional reload insns. (if_then_else (lt (match_dup 3) (pc)) - (if_then_else + (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 + (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 +;; 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*x,!*m") + [(match_operand:SI 0 "register_operand" "+!r,!*f,!*m") (match_operand:SI 5 "const_int_operand" "")]) (label_ref (match_operand 3 "" "")) (pc))) @@ -3135,7 +3893,7 @@ (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. +;; 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") @@ -3151,12 +3909,12 @@ ;; 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 + (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 + (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) (const_int 8188)) (const_int 24) @@ -3164,12 +3922,12 @@ ;; Loop counter in memory case. ;; Extra goo to deal with additional reload insns. (if_then_else (lt (match_dup 3) (pc)) - (if_then_else + (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 + (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) (const_int 8188)) (const_int 12) @@ -3182,11 +3940,11 @@ [(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*x,!*m") + (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. +;; 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") @@ -3202,19 +3960,19 @@ ;; 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 + (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 + (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 + (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8)))) (const_int 8188)) (const_int 8) @@ -3228,11 +3986,11 @@ [(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*x,!*m") + (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. +;; 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") @@ -3248,37 +4006,37 @@ ;; 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 + (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 + (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 + (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)" "* { @@ -3298,13 +4056,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)" "* { @@ -3327,12 +4085,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)" "* { @@ -3343,12 +4101,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)" "* { @@ -3369,7 +4127,8 @@ (use (mem:SI (match_operand:SI 1 "register_operand" "r")))] "" "fdc 0(0,%0)\;fdc 0(0,%1)\;sync" - [(set_attr "length" "12")]) + [(set_attr "type" "multi") + (set_attr "length" "12")]) (define_insn "icacheflush" [(unspec_volatile [(const_int 2)] 0) @@ -3380,4 +4139,5 @@ (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")]) + [(set_attr "type" "multi") + (set_attr "length" "52")])