Home | History | Annotate | Line # | Download | only in ia64
      1 ;; Copyright (C) 2007-2022 Free Software Foundation, Inc.
      2 ;;
      3 ;; This file is part of GCC.
      4 ;;
      5 ;; GCC is free software; you can redistribute it and/or modify
      6 ;; it under the terms of the GNU General Public License as published by
      7 ;; the Free Software Foundation; either version 3, or (at your option)
      8 ;; any later version.
      9 ;;
     10 ;; GCC is distributed in the hope that it will be useful,
     11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 ;; GNU General Public License for more details.
     14 ;;
     15 ;; You should have received a copy of the GNU General Public License
     16 ;; along with GCC; see the file COPYING3.  If not see
     17 ;; <http://www.gnu.org/licenses/>.
     18 
     19 ;; For the internal conditional math routines:
     20 
     21 ;; operand 0 is always the result
     22 ;; operand 1 is always the predicate
     23 ;; operand 2, 3, and sometimes 4 are the input values.
     24 ;; operand 4 or 5 is the floating point status register to use.
     25 ;; operand 5 or 6 is the rounding to do. (0 = single, 1 = double, 2 = none)
     26 ;;
     27 ;; addrf3_cond   - F0 = F2 + F3
     28 ;; subrf3_cond   - F0 = F2 - F3
     29 ;; mulrf3_cond   - F0 = F2 * F3
     30 ;; nmulrf3_cond  - F0 = - (F2 * F3)
     31 ;; m1addrf4_cond - F0 = (F2 * F3) + F4
     32 ;; m1subrf4_cond - F0 = (F2 * F3) - F4
     33 ;; m2addrf4_cond - F0 = F2 + (F3 * F4)
     34 ;; m2subrf4_cond - F0 = F2 - (F3 * F4)
     35 
     36 ;; Basic plus/minus/mult operations
     37 
     38 (define_insn "addrf3_cond"
     39   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
     40         (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
     41                                 (const_int 0))
     42           (plus:RF
     43             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
     44             (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG"))
     45           (match_operand:RF 4 "fr_reg_or_0_operand" "0,H")))
     46    (use (match_operand:SI 5 "const_int_operand" ""))
     47    (use (match_operand:SI 6 "const_int_operand" ""))]
     48   ""
     49   "(%1) fadd%R6.s%5 %0 = %F2, %F3"
     50   [(set_attr "itanium_class" "fmac")
     51    (set_attr "predicable" "no")])
     52 
     53 (define_insn "subrf3_cond"
     54   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
     55         (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
     56                                 (const_int 0))
     57           (minus:RF
     58             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
     59             (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG"))
     60           (match_operand:RF 4 "fr_reg_or_0_operand" "0,H")))
     61    (use (match_operand:SI 5 "const_int_operand" ""))
     62    (use (match_operand:SI 6 "const_int_operand" ""))]
     63   ""
     64   "(%1) fsub%R6.s%5 %0 = %F2, %F3"
     65   [(set_attr "itanium_class" "fmac")
     66    (set_attr "predicable" "no")])
     67 
     68 (define_insn "mulrf3_cond"
     69   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
     70         (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
     71                                 (const_int 0))
     72           (mult:RF
     73             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
     74             (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG"))
     75           (match_operand:RF 4 "fr_reg_or_0_operand" "0,H")))
     76    (use (match_operand:SI 5 "const_int_operand" ""))
     77    (use (match_operand:SI 6 "const_int_operand" ""))]
     78   ""
     79   "(%1) fmpy%R6.s%5 %0 = %F2, %F3"
     80   [(set_attr "itanium_class" "fmac")
     81    (set_attr "predicable" "no")])
     82 
     83 ;; neg-mult operation
     84 
     85 (define_insn "nmulrf3_cond"
     86   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
     87         (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
     88                                 (const_int 0))
     89           (neg:RF (mult:RF
     90             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
     91             (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG")))
     92           (match_operand:RF 4 "fr_reg_or_0_operand" "0,H")))
     93    (use (match_operand:SI 5 "const_int_operand" ""))
     94    (use (match_operand:SI 6 "const_int_operand" ""))]
     95   ""
     96   "(%1) fnmpy%R6.s%5 %0 = %F2, %F3"
     97   [(set_attr "itanium_class" "fmac")
     98    (set_attr "predicable" "no")])
     99 
    100 ;; add-mult/sub-mult operations (mult as op1)
    101 
    102 (define_insn "m1addrf4_cond"
    103   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
    104         (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
    105                                 (const_int 0))
    106           (plus:RF
    107             (mult:RF
    108               (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
    109               (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG"))
    110             (match_operand:RF 4 "fr_reg_or_fp01_operand" "fG,fG"))
    111           (match_operand:RF 5 "fr_reg_or_0_operand" "0,H")))
    112    (use (match_operand:SI 6 "const_int_operand" ""))
    113    (use (match_operand:SI 7 "const_int_operand" ""))]
    114   ""
    115   "(%1) fma%R7.s%6 %0 = %F2, %F3, %F4"
    116   [(set_attr "itanium_class" "fmac")
    117    (set_attr "predicable" "no")])
    118 
    119 (define_insn "m1subrf4_cond"
    120   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
    121         (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
    122                                 (const_int 0))
    123           (minus:RF
    124             (mult:RF
    125               (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
    126               (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG"))
    127             (match_operand:RF 4 "fr_reg_or_fp01_operand" "fG,fG"))
    128           (match_operand:RF 5 "fr_reg_or_0_operand" "0,H")))
    129    (use (match_operand:SI 6 "const_int_operand" ""))
    130    (use (match_operand:SI 7 "const_int_operand" ""))]
    131   ""
    132   "(%1) fms%R7.s%6 %0 = %F2, %F3, %F4"
    133   [(set_attr "itanium_class" "fmac")
    134    (set_attr "predicable" "no")])
    135 
    136 ;; add-mult/sub-mult operations (mult as op2)
    137 
    138 (define_insn "m2addrf4_cond"
    139   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
    140         (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
    141                                 (const_int 0))
    142           (plus:RF
    143             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
    144             (mult:RF
    145               (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG")
    146               (match_operand:RF 4 "fr_reg_or_fp01_operand" "fG,fG")))
    147           (match_operand:RF 5 "fr_reg_or_0_operand" "0,H")))
    148    (use (match_operand:SI 6 "const_int_operand" ""))
    149    (use (match_operand:SI 7 "const_int_operand" ""))]
    150   ""
    151   "(%1) fma%R7.s%6 %0 = %F3, %F4, %F2"
    152   [(set_attr "itanium_class" "fmac")
    153    (set_attr "predicable" "no")])
    154 
    155 (define_insn "m2subrf4_cond"
    156   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
    157         (if_then_else:RF (ne:RF (match_operand:CCI 1 "register_operand"  "c,c")
    158                                 (const_int 0))
    159           (minus:RF
    160             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
    161             (mult:RF
    162               (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG")
    163               (match_operand:RF 4 "fr_reg_or_fp01_operand" "fG,fG")))
    164           (match_operand:RF 5 "fr_reg_or_0_operand" "0,H")))
    165    (use (match_operand:SI 6 "const_int_operand" ""))
    166    (use (match_operand:SI 7 "const_int_operand" ""))]
    167   ""
    168   "(%1) fnma%R7.s%6 %0 = %F3, %F4, %F2"
    169   [(set_attr "itanium_class" "fmac")
    170    (set_attr "predicable" "no")])
    171 
    172 ;; Conversions to/from RF and SF/DF/XF
    173 ;; These conversions should not generate any code but make it possible
    174 ;; for all the instructions used to implement floating point division
    175 ;; to be written for RFmode only and to not have to handle multiple
    176 ;; modes or to have to handle a register in more than one mode.
    177 
    178 (define_mode_iterator SDX_F [SF DF XF])
    179 
    180 (define_insn "extend<mode>rf2"
    181   [(set (match_operand:RF 0 "fr_register_operand" "=f")
    182         (float_extend:RF (match_operand:SDX_F 1 "fr_reg_or_fp01_operand" "fG")))]
    183   ""
    184   "#"
    185   [(set_attr "itanium_class" "fmisc")
    186    (set_attr "predicable" "yes")])
    187 
    188 (define_split
    189   [(set (match_operand:RF 0 "fr_register_operand" "")
    190         (float_extend:RF (match_operand:SDX_F 1 "fr_reg_or_fp01_operand" "")))]
    191    "reload_completed"
    192    [(set (match_dup 0) (match_dup 2))]
    193 {
    194    if (operands[1] == CONST0_RTX (<MODE>mode))
    195      operands[2] = gen_rtx_REG (RFmode, FR_REG (0));
    196    else if (operands[1] == CONST1_RTX (<MODE>mode))
    197      operands[2] = gen_rtx_REG (RFmode, FR_REG (1));
    198    else
    199      operands[2] = gen_rtx_REG (RFmode, REGNO (operands[1]));
    200 })
    201 
    202 
    203 (define_insn "truncrf<mode>2"
    204   [(set (match_operand:SDX_F 0 "fr_register_operand" "=f")
    205         (float_truncate:SDX_F (match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")))]
    206   ""
    207   "#"
    208   [(set_attr "itanium_class" "fmisc")
    209    (set_attr "predicable" "yes")])
    210 
    211 (define_split
    212   [(set (match_operand:SDX_F 0 "fr_register_operand" "")
    213         (float_truncate:SDX_F (match_operand:RF 1 "fr_reg_or_fp01_operand" "")))]
    214    "reload_completed"
    215    [(set (match_dup 0) (match_dup 2))]
    216 {
    217    if (operands[1] == CONST0_RTX (RFmode))
    218      operands[2] = gen_rtx_REG (<MODE>mode, FR_REG (0));
    219    else if (operands[1] == CONST1_RTX (RFmode))
    220      operands[2] = gen_rtx_REG (<MODE>mode, FR_REG (1));
    221    else
    222      operands[2] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
    223 })
    224 
    225 ;; Float to integer truncations using an alternative status register. 
    226 
    227 (define_insn "fix_truncrfdi2_alts"
    228   [(set (match_operand:DI 0 "fr_register_operand" "=f")
    229         (fix:DI (match_operand:RF 1 "fr_register_operand" "f")))
    230    (use (match_operand:SI 2 "const_int_operand" ""))]
    231   ""
    232   "fcvt.fx.trunc.s%2 %0 = %1"
    233   [(set_attr "itanium_class" "fcvtfx")])
    234 
    235 (define_insn "fixuns_truncrfdi2_alts"
    236   [(set (match_operand:DI 0 "fr_register_operand" "=f")
    237         (unsigned_fix:DI (match_operand:RF 1 "fr_register_operand" "f")))
    238    (use (match_operand:SI 2 "const_int_operand" ""))]
    239   ""
    240   "fcvt.fxu.trunc.s%2 %0 = %1"
    241   [(set_attr "itanium_class" "fcvtfx")])
    242 
    243 (define_insn "setf_exp_rf"
    244   [(set (match_operand:RF 0 "fr_register_operand" "=f")
    245         (unspec:RF [(match_operand:DI 1 "register_operand" "r")]
    246                   UNSPEC_SETF_EXP))]
    247   ""
    248   "setf.exp %0 = %1"
    249   [(set_attr "itanium_class" "frfr")])
    250 
    251 ;; Reciprocal approximation
    252 
    253 (define_insn "recip_approx_rf"
    254   [(set (match_operand:RF 0 "fr_register_operand" "=f")
    255         (unspec:RF [(match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")
    256 		    (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG")]
    257 		   UNSPEC_FR_RECIP_APPROX_RES))
    258    (set (match_operand:CCI 3 "register_operand" "=c")
    259         (unspec:CCI [(match_dup 1) (match_dup 2)] UNSPEC_FR_RECIP_APPROX))
    260    (use (match_operand:SI 4 "const_int_operand" ""))]
    261   ""
    262   "frcpa.s%4 %0, %3 = %F1, %F2"
    263   [(set_attr "itanium_class" "fmisc")
    264    (set_attr "predicable" "no")])
    265 
    266 ;; Single precision floating point division
    267 
    268 (define_expand "divsf3"
    269   [(set (match_operand:SF 0 "fr_register_operand" "")
    270 	(div:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "")
    271 		(match_operand:SF 2 "fr_reg_or_fp01_operand" "")))]
    272   "TARGET_INLINE_FLOAT_DIV"
    273 {
    274   rtx insn;
    275   if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
    276     insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
    277   else
    278     insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
    279   emit_insn (insn);
    280   DONE;
    281 })
    282 
    283 ;; Single precision floating point division (maximum throughput algorithm).
    284 
    285 (define_expand "divsf3_internal_thr"
    286   [(set (match_operand:SF 0 "fr_register_operand" "")
    287         (div:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "")
    288                 (match_operand:SF 2 "fr_reg_or_fp01_operand" "")))]
    289   "TARGET_INLINE_FLOAT_DIV"
    290 {
    291   rtx y     = gen_reg_rtx (RFmode);
    292   rtx a     = gen_reg_rtx (RFmode);
    293   rtx b     = gen_reg_rtx (RFmode);
    294   rtx e     = gen_reg_rtx (RFmode);
    295   rtx y1    = gen_reg_rtx (RFmode);
    296   rtx y2    = gen_reg_rtx (RFmode);
    297   rtx q     = gen_reg_rtx (RFmode);
    298   rtx r     = gen_reg_rtx (RFmode);
    299   rtx q_res = gen_reg_rtx (RFmode);
    300   rtx cond  = gen_reg_rtx (CCImode);
    301   rtx zero    = CONST0_RTX (RFmode);
    302   rtx one     = CONST1_RTX (RFmode);
    303   rtx status0 = CONST0_RTX (SImode);
    304   rtx status1 = CONST1_RTX (SImode);
    305   rtx trunc_sgl = CONST0_RTX (SImode);
    306   rtx trunc_off    = CONST2_RTX (SImode);
    307 
    308   /* Empty conversions to put inputs into RFmode.  */
    309   emit_insn (gen_extendsfrf2 (a, operands[1]));
    310   emit_insn (gen_extendsfrf2 (b, operands[2]));
    311   /* y = 1 / b				*/
    312   emit_insn (gen_recip_approx_rf (y, a, b, cond, status0));
    313   /* e = 1 - (b * y)			*/
    314   emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
    315   /* y1 = y + (y * e)			*/
    316   emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e, zero, status1, trunc_off));
    317   /* y2 = y + (y1 * e)			*/
    318   emit_insn (gen_m2addrf4_cond (y2, cond, y, y1, e, zero, status1, trunc_off));
    319   /* q = single(a * y2)			*/
    320   emit_insn (gen_mulrf3_cond (q, cond, a, y2, zero, status1, trunc_sgl));
    321   /* r = a - (q * b)			*/
    322   emit_insn (gen_m2subrf4_cond (r, cond, a, q, b, zero, status1, trunc_off));
    323   /* Q = single (q + (r * y2))		*/
    324   emit_insn (gen_m2addrf4_cond (q_res, cond, q, r, y2, y, status0, trunc_sgl));
    325   /* Conversion back into SFmode.	*/
    326   emit_insn (gen_truncrfsf2 (operands[0], q_res));
    327   DONE;
    328 })
    329 
    330 ;; Single precision floating point division (minimum latency algorithm).
    331 
    332 (define_expand "divsf3_internal_lat"
    333   [(set (match_operand:SF 0 "fr_register_operand" "")
    334         (div:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "")
    335                 (match_operand:SF 2 "fr_reg_or_fp01_operand" "")))]
    336   "TARGET_INLINE_FLOAT_DIV"
    337 {
    338   rtx y         = gen_reg_rtx (RFmode);
    339   rtx a         = gen_reg_rtx (RFmode);
    340   rtx b         = gen_reg_rtx (RFmode);
    341   rtx e         = gen_reg_rtx (RFmode);
    342   rtx q         = gen_reg_rtx (RFmode);
    343   rtx e1        = gen_reg_rtx (RFmode);
    344   rtx y1        = gen_reg_rtx (RFmode);
    345   rtx q1        = gen_reg_rtx (RFmode);
    346   rtx r         = gen_reg_rtx (RFmode);
    347   rtx q_res     = gen_reg_rtx (RFmode);
    348   rtx cond      = gen_reg_rtx (CCImode);
    349   rtx zero      = CONST0_RTX (RFmode);
    350   rtx one       = CONST1_RTX (RFmode);
    351   rtx status0   = CONST0_RTX (SImode);
    352   rtx status1   = CONST1_RTX (SImode);
    353   rtx trunc_sgl = CONST0_RTX (SImode);
    354   rtx trunc_off = CONST2_RTX (SImode);
    355 
    356   /* Empty conversions to put inputs into RFmode.  */
    357   emit_insn (gen_extendsfrf2 (a, operands[1]));
    358   emit_insn (gen_extendsfrf2 (b, operands[2]));
    359   /* y = 1 / b				*/
    360   emit_insn (gen_recip_approx_rf (y, a, b, cond, status0));
    361   /* q = a * y				*/
    362   emit_insn (gen_mulrf3_cond (q, cond, a, y, zero, status1, trunc_off));
    363   /* e = 1 - (b * y)			*/
    364   emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
    365   /* e1 = e + (e * e)			*/
    366   emit_insn (gen_m2addrf4_cond (e1, cond, e, e, e, zero, status1, trunc_off));
    367   /* q1 = single(q + (q * e1))		*/
    368   emit_insn (gen_m2addrf4_cond (q1, cond, q, q, e1, zero, status1, trunc_sgl));
    369   /* y1 = y + (y * e1)			*/
    370   emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e1, zero, status1, trunc_off));
    371   /* r = a - (q1 * b)			*/
    372   emit_insn (gen_m2subrf4_cond (r, cond, a, q1, b, zero, status1, trunc_off));
    373   /* Q = single (q1 + (r * y1))		*/
    374   emit_insn (gen_m2addrf4_cond (q_res, cond, q1, r, y1, y, status0, trunc_sgl));
    375   /* Conversion back into SFmode.	*/
    376   emit_insn (gen_truncrfsf2 (operands[0], q_res));
    377   DONE;
    378 })
    379 
    380 ;; Double precision floating point division
    381 
    382 (define_expand "divdf3"
    383   [(set (match_operand:DF 0 "fr_register_operand" "")
    384 	(div:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "")
    385 		(match_operand:DF 2 "fr_reg_or_fp01_operand" "")))]
    386   "TARGET_INLINE_FLOAT_DIV"
    387 {
    388   rtx insn;
    389   if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
    390     insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
    391   else
    392     insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
    393   emit_insn (insn);
    394   DONE;
    395 })
    396 
    397 ;; Double precision floating point division (maximum throughput algorithm).
    398 
    399 (define_expand "divdf3_internal_thr"
    400   [(set (match_operand:DF 0 "fr_register_operand" "")
    401         (div:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "")
    402                 (match_operand:DF 2 "fr_reg_or_fp01_operand" "")))]
    403   "TARGET_INLINE_FLOAT_DIV"
    404 {
    405   rtx q_res = gen_reg_rtx (RFmode);
    406   rtx a     = gen_reg_rtx (RFmode);
    407   rtx b     = gen_reg_rtx (RFmode);
    408   rtx y     = gen_reg_rtx (RFmode);
    409   rtx e     = gen_reg_rtx (RFmode);
    410   rtx y1    = gen_reg_rtx (RFmode);
    411   rtx e1    = gen_reg_rtx (RFmode);
    412   rtx y2    = gen_reg_rtx (RFmode);
    413   rtx e2    = gen_reg_rtx (RFmode);
    414   rtx y3    = gen_reg_rtx (RFmode);
    415   rtx q     = gen_reg_rtx (RFmode);
    416   rtx r     = gen_reg_rtx (RFmode);
    417   rtx cond  = gen_reg_rtx (CCImode);
    418   rtx zero    = CONST0_RTX (RFmode);
    419   rtx one     = CONST1_RTX (RFmode);
    420   rtx status0 = CONST0_RTX (SImode);
    421   rtx status1 = CONST1_RTX (SImode);
    422   rtx trunc_dbl = CONST1_RTX (SImode);
    423   rtx trunc_off = CONST2_RTX (SImode);
    424   /* Empty conversions to put inputs into RFmode */
    425   emit_insn (gen_extenddfrf2 (a, operands[1]));
    426   emit_insn (gen_extenddfrf2 (b, operands[2]));
    427   /* y  = 1 / b			*/
    428   emit_insn (gen_recip_approx_rf (y, a, b, cond, status0));
    429   /* e  = 1 - (b * y)		*/
    430   emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
    431   /* y1 = y + (y * e)		*/
    432   emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e, zero, status1, trunc_off));
    433   /* e1 = e * e			*/
    434   emit_insn (gen_mulrf3_cond (e1, cond, e, e, zero, status1, trunc_off));
    435   /* y2 = y1 + (y1 * e1)	*/
    436   emit_insn (gen_m2addrf4_cond (y2, cond, y1, y1, e1, zero, status1, trunc_off));
    437   /* e2 = e1 * e1		*/
    438   emit_insn (gen_mulrf3_cond (e2, cond, e1, e1, zero, status1, trunc_off));
    439   /* y3 = y2 + (y2 * e2)	*/
    440   emit_insn (gen_m2addrf4_cond (y3, cond, y2, y2, e2, zero, status1, trunc_off));
    441   /* q  = double (a * y3)	*/
    442   emit_insn (gen_mulrf3_cond (q, cond, a, y3, zero, status1, trunc_dbl));
    443   /* r  = a - (b * q)		*/
    444   emit_insn (gen_m2subrf4_cond (r, cond, a, b, q, zero, status1, trunc_off));
    445   /* Q  = double (q + (r * y3))	*/
    446   emit_insn (gen_m2addrf4_cond (q_res, cond, q, r, y3, y, status0, trunc_dbl));
    447   /* Conversion back into DFmode */
    448   emit_insn (gen_truncrfdf2 (operands[0], q_res));
    449   DONE;
    450 })
    451 
    452 ;; Double precision floating point division (minimum latency algorithm).
    453 
    454 (define_expand "divdf3_internal_lat"
    455   [(set (match_operand:DF 0 "fr_register_operand" "")
    456         (div:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "")
    457                 (match_operand:DF 2 "fr_reg_or_fp01_operand" "")))]
    458   "TARGET_INLINE_FLOAT_DIV"
    459 {
    460   rtx q_res     = gen_reg_rtx (RFmode);
    461   rtx a         = gen_reg_rtx (RFmode);
    462   rtx b         = gen_reg_rtx (RFmode);
    463   rtx y         = gen_reg_rtx (RFmode);
    464   rtx e         = gen_reg_rtx (RFmode);
    465   rtx y1        = gen_reg_rtx (RFmode);
    466   rtx e1        = gen_reg_rtx (RFmode);
    467   rtx q1        = gen_reg_rtx (RFmode);
    468   rtx y2        = gen_reg_rtx (RFmode);
    469   rtx e2        = gen_reg_rtx (RFmode);
    470   rtx q2        = gen_reg_rtx (RFmode);
    471   rtx e3        = gen_reg_rtx (RFmode);
    472   rtx q         = gen_reg_rtx (RFmode);
    473   rtx r1        = gen_reg_rtx (RFmode);
    474   rtx cond      = gen_reg_rtx (CCImode);
    475   rtx zero      = CONST0_RTX (RFmode);
    476   rtx one       = CONST1_RTX (RFmode);
    477   rtx status0   = CONST0_RTX (SImode);
    478   rtx status1   = CONST1_RTX (SImode);
    479   rtx trunc_dbl = CONST1_RTX (SImode);
    480   rtx trunc_off = CONST2_RTX (SImode);
    481 
    482   /* Empty conversions to put inputs into RFmode */
    483   emit_insn (gen_extenddfrf2 (a, operands[1]));
    484   emit_insn (gen_extenddfrf2 (b, operands[2]));
    485   /* y  = 1 / b			*/
    486   emit_insn (gen_recip_approx_rf (y, a, b, cond, status0));
    487   /* e  = 1 - (b * y)		*/
    488   emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
    489   /* q  = a * y                 */
    490   emit_insn (gen_mulrf3_cond (q, cond, a, y, zero, status1, trunc_off));
    491   /* e2 = e + (e * e)		*/
    492   emit_insn (gen_m2addrf4_cond (e2, cond, e, e, e, zero, status1, trunc_off));
    493   /* e1 = e * e                 */
    494   emit_insn (gen_mulrf3_cond (e1, cond, e, e, zero, status1, trunc_off));
    495   /* e3 = e + (e1 * e1)		*/
    496   emit_insn (gen_m2addrf4_cond (e3, cond, e, e1, e1, zero, status1, trunc_off));
    497   /* q1 = q + (q * e2)		*/
    498   emit_insn (gen_m2addrf4_cond (q1, cond, q, q, e2, zero, status1, trunc_off));
    499   /* y1 = y + (y * e2)		*/
    500   emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e2, zero, status1, trunc_off));
    501   /* q2 = double(q + (q1 * e3))	*/
    502   emit_insn (gen_m2addrf4_cond (q2, cond, q, q1, e3, zero, status1, trunc_dbl));
    503   /* y2 = y + (y1 * e3)		*/
    504   emit_insn (gen_m2addrf4_cond (y2, cond, y, y1, e3, zero, status1, trunc_off));
    505   /* r1  = a - (b * q2)		*/
    506   emit_insn (gen_m2subrf4_cond (r1, cond, a, b, q2, zero, status1, trunc_off));
    507   /* Q  = double (q2 + (r1 * y2))	*/
    508   emit_insn (gen_m2addrf4_cond (q_res, cond, q2, r1, y2, y, status0, trunc_dbl));
    509   /* Conversion back into DFmode */
    510   emit_insn (gen_truncrfdf2 (operands[0], q_res));
    511   DONE;
    512 })
    513 
    514 ;; Extended precision floating point division.
    515 
    516 (define_expand "divxf3"
    517   [(set (match_operand:XF 0 "fr_register_operand" "")
    518         (div:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "")
    519                 (match_operand:XF 2 "fr_reg_or_fp01_operand" "")))]
    520   "TARGET_INLINE_FLOAT_DIV"
    521 {
    522   rtx q_res     = gen_reg_rtx (RFmode);
    523   rtx a         = gen_reg_rtx (RFmode);
    524   rtx b         = gen_reg_rtx (RFmode);
    525   rtx y         = gen_reg_rtx (RFmode);
    526   rtx e         = gen_reg_rtx (RFmode);
    527   rtx y1        = gen_reg_rtx (RFmode);
    528   rtx e1        = gen_reg_rtx (RFmode);
    529   rtx q1        = gen_reg_rtx (RFmode);
    530   rtx y2        = gen_reg_rtx (RFmode);
    531   rtx e2        = gen_reg_rtx (RFmode);
    532   rtx y3        = gen_reg_rtx (RFmode);
    533   rtx e3        = gen_reg_rtx (RFmode);
    534   rtx e4        = gen_reg_rtx (RFmode);
    535   rtx q         = gen_reg_rtx (RFmode);
    536   rtx r         = gen_reg_rtx (RFmode);
    537   rtx r1        = gen_reg_rtx (RFmode);
    538   rtx cond      = gen_reg_rtx (CCImode);
    539   rtx zero      = CONST0_RTX (RFmode);
    540   rtx one       = CONST1_RTX (RFmode);
    541   rtx status0   = CONST0_RTX (SImode);
    542   rtx status1   = CONST1_RTX (SImode);
    543   rtx trunc_off = CONST2_RTX (SImode);
    544 
    545   /* Empty conversions to put inputs into RFmode */
    546   emit_insn (gen_extendxfrf2 (a, operands[1]));
    547   emit_insn (gen_extendxfrf2 (b, operands[2]));
    548   /* y  = 1 / b			*/
    549   emit_insn (gen_recip_approx_rf (y, a, b, cond, status0));
    550   /* e  = 1 - (b * y)		*/
    551   emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
    552   /* q  = a * y                 */
    553   emit_insn (gen_mulrf3_cond (q, cond, a, y, zero, status1, trunc_off));
    554   /* e2 = e + (e * e)		*/
    555   emit_insn (gen_m2addrf4_cond (e2, cond, e, e, e, zero, status1, trunc_off));
    556   /* e1 = e * e                 */
    557   emit_insn (gen_mulrf3_cond (e1, cond, e, e, zero, status1, trunc_off));
    558   /* y1 = y + (y * e2)		*/
    559   emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e2, zero, status1, trunc_off));
    560   /* e3 = e + (e1 * e1)		*/
    561   emit_insn (gen_m2addrf4_cond (e3, cond, e, e1, e1, zero, status1, trunc_off));
    562   /* y2 = y + (y1 * e3)		*/
    563   emit_insn (gen_m2addrf4_cond (y2, cond, y, y1, e3, zero, status1, trunc_off));
    564   /* r  = a - (b * q)		*/
    565   emit_insn (gen_m2subrf4_cond (r, cond, a, b, q, zero, status1, trunc_off));
    566   /* e4  = 1 - (b * y2)		*/
    567   emit_insn (gen_m2subrf4_cond (e4, cond, one, b, y2, zero, status1, trunc_off));
    568   /* q1 = q + (r * y2)		*/
    569   emit_insn (gen_m2addrf4_cond (q1, cond, q, r, y2, zero, status1, trunc_off));
    570   /* y3 = y2 + (y2 * e4)	*/
    571   emit_insn (gen_m2addrf4_cond (y3, cond, y2, y2, e4, zero, status1, trunc_off));
    572   /* r1  = a - (b * q1)		*/
    573   emit_insn (gen_m2subrf4_cond (r1, cond, a, b, q1, zero, status1, trunc_off));
    574   /* Q  = q1 + (r1 * y3)	*/
    575   emit_insn (gen_m2addrf4_cond (q_res, cond, q1, r1, y3, y, status0, trunc_off));
    576   /* Conversion back into XFmode */
    577   emit_insn (gen_truncrfxf2 (operands[0], q_res));
    578   DONE;
    579 })
    580 
    581 
    582 ;; Integer division operations
    583 
    584 (define_expand "divsi3"
    585   [(set (match_operand:SI 0 "register_operand" "")
    586 	(div:SI (match_operand:SI 1 "general_operand" "")
    587 		(match_operand:SI 2 "general_operand" "")))]
    588   "TARGET_INLINE_INT_DIV"
    589 {
    590   rtx op1_rf, op2_rf, op0_rf, op0_di;
    591 
    592   op0_rf = gen_reg_rtx (RFmode);
    593   op0_di = gen_reg_rtx (DImode);
    594 
    595   if (! register_operand (operands[1], SImode))
    596     operands[1] = force_reg (SImode, operands[1]);
    597   op1_rf = gen_reg_rtx (RFmode);
    598   expand_float (op1_rf, operands[1], 0);
    599 
    600   if (! register_operand (operands[2], SImode))
    601     operands[2] = force_reg (SImode, operands[2]);
    602   op2_rf = gen_reg_rtx (RFmode);
    603   expand_float (op2_rf, operands[2], 0);
    604 
    605   emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
    606 			    CONST1_RTX (SImode)));
    607   
    608   emit_insn (gen_divsi3_internal (op0_rf, op1_rf, op2_rf));
    609 
    610   emit_insn (gen_fix_truncrfdi2_alts (op0_di, op0_rf, const1_rtx));
    611   emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
    612   DONE;
    613 })
    614 
    615 (define_expand "modsi3"
    616   [(set (match_operand:SI 0 "register_operand" "")
    617 	(mod:SI (match_operand:SI 1 "general_operand" "")
    618 		(match_operand:SI 2 "general_operand" "")))]
    619   "TARGET_INLINE_INT_DIV"
    620 {
    621   rtx op2_neg, op1_di, div;
    622 
    623   div = gen_reg_rtx (SImode);
    624   emit_insn (gen_divsi3 (div, operands[1], operands[2]));
    625 
    626   op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
    627 
    628   /* This is a trick to get us to reuse the value that we're sure to
    629      have already copied to the FP regs.  */
    630   op1_di = gen_reg_rtx (DImode);
    631   convert_move (op1_di, operands[1], 0);
    632 
    633   emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
    634 			  gen_lowpart (SImode, op1_di)));
    635   DONE;
    636 })
    637 
    638 (define_expand "udivsi3"
    639   [(set (match_operand:SI 0 "register_operand" "")
    640 	(udiv:SI (match_operand:SI 1 "general_operand" "")
    641 		 (match_operand:SI 2 "general_operand" "")))]
    642   "TARGET_INLINE_INT_DIV"
    643 {
    644   rtx op1_rf, op2_rf, op0_rf, op0_di;
    645 
    646   op0_rf = gen_reg_rtx (RFmode);
    647   op0_di = gen_reg_rtx (DImode);
    648 
    649   if (! register_operand (operands[1], SImode))
    650     operands[1] = force_reg (SImode, operands[1]);
    651   op1_rf = gen_reg_rtx (RFmode);
    652   expand_float (op1_rf, operands[1], 1);
    653 
    654   if (! register_operand (operands[2], SImode))
    655     operands[2] = force_reg (SImode, operands[2]);
    656   op2_rf = gen_reg_rtx (RFmode);
    657   expand_float (op2_rf, operands[2], 1);
    658 
    659   emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
    660                             CONST1_RTX (SImode)));
    661   
    662   emit_insn (gen_divsi3_internal (op0_rf, op1_rf, op2_rf));
    663 
    664   emit_insn (gen_fixuns_truncrfdi2_alts (op0_di, op0_rf, const1_rtx));
    665   emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
    666   DONE;
    667 })
    668 
    669 (define_expand "umodsi3"
    670   [(set (match_operand:SI 0 "register_operand" "")
    671 	(umod:SI (match_operand:SI 1 "general_operand" "")
    672 		 (match_operand:SI 2 "general_operand" "")))]
    673   "TARGET_INLINE_INT_DIV"
    674 {
    675   rtx op2_neg, op1_di, div;
    676 
    677   div = gen_reg_rtx (SImode);
    678   emit_insn (gen_udivsi3 (div, operands[1], operands[2]));
    679 
    680   op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
    681 
    682   /* This is a trick to get us to reuse the value that we're sure to
    683      have already copied to the FP regs.  */
    684   op1_di = gen_reg_rtx (DImode);
    685   convert_move (op1_di, operands[1], 1);
    686 
    687   emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
    688 			  gen_lowpart (SImode, op1_di)));
    689   DONE;
    690 })
    691 
    692 (define_expand "divsi3_internal"
    693   [(set (match_operand:RF 0 "fr_register_operand" "")
    694         (float:RF (div:SI (match_operand:RF 1 "fr_register_operand" "")
    695                           (match_operand:RF 2 "fr_register_operand" ""))))]
    696   "TARGET_INLINE_INT_DIV"
    697 {
    698   rtx a         = operands[1];
    699   rtx b         = operands[2];
    700   rtx y         = gen_reg_rtx (RFmode);
    701   rtx e         = gen_reg_rtx (RFmode);
    702   rtx e1        = gen_reg_rtx (RFmode);
    703   rtx q         = gen_reg_rtx (RFmode);
    704   rtx q1        = gen_reg_rtx (RFmode);
    705   rtx cond      = gen_reg_rtx (CCImode);
    706   rtx zero      = CONST0_RTX (RFmode);
    707   rtx one       = CONST1_RTX (RFmode);
    708   rtx status1   = CONST1_RTX (SImode);
    709   rtx trunc_off = CONST2_RTX (SImode);
    710   rtx twon34_exp = gen_reg_rtx (DImode);
    711   rtx twon34    = gen_reg_rtx (RFmode);
    712 
    713   /* Load cosntant 2**(-34) */
    714   emit_move_insn (twon34_exp, GEN_INT (65501));
    715   emit_insn (gen_setf_exp_rf (twon34, twon34_exp));
    716 
    717   /* y  = 1 / b			*/
    718   emit_insn (gen_recip_approx_rf (y, a, b, cond, status1));
    719   /* e  = 1 - (b * y)		*/
    720   emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
    721   /* q  = a * y                 */
    722   emit_insn (gen_mulrf3_cond (q, cond, a, y, zero, status1, trunc_off));
    723   /* q1 = q + (q * e)		*/
    724   emit_insn (gen_m2addrf4_cond (q1, cond, q, q, e, zero, status1, trunc_off));
    725   /* e1 = (2**-34) + (e * e)		*/
    726   emit_insn (gen_m2addrf4_cond (e1, cond, twon34, e, e, zero, status1, trunc_off));
    727   /* q2 = q1 + (e1 * q1)		*/
    728   emit_insn (gen_m2addrf4_cond (operands[0], cond, q1, e1, q1, y, status1, trunc_off));
    729   DONE;
    730 })
    731 
    732 (define_expand "divdi3"
    733   [(set (match_operand:DI 0 "register_operand" "")
    734 	(div:DI (match_operand:DI 1 "general_operand" "")
    735 		(match_operand:DI 2 "general_operand" "")))]
    736   "TARGET_INLINE_INT_DIV"
    737 {
    738   rtx op1_rf, op2_rf, op0_rf;
    739 
    740   op0_rf = gen_reg_rtx (RFmode);
    741 
    742   if (! register_operand (operands[1], DImode))
    743     operands[1] = force_reg (DImode, operands[1]);
    744   op1_rf = gen_reg_rtx (RFmode);
    745   expand_float (op1_rf, operands[1], 0);
    746 
    747   if (! register_operand (operands[2], DImode))
    748     operands[2] = force_reg (DImode, operands[2]);
    749   op2_rf = gen_reg_rtx (RFmode);
    750   expand_float (op2_rf, operands[2], 0);
    751 
    752   emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
    753                             CONST1_RTX (DImode)));
    754 
    755   if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
    756     emit_insn (gen_divdi3_internal_lat (op0_rf, op1_rf, op2_rf));
    757   else
    758     emit_insn (gen_divdi3_internal_thr (op0_rf, op1_rf, op2_rf));
    759 
    760   emit_insn (gen_fix_truncrfdi2_alts (operands[0], op0_rf, const1_rtx));
    761   DONE;
    762 })
    763 
    764 (define_expand "moddi3"
    765   [(set (match_operand:DI 0 "register_operand" "")
    766 	(mod:SI (match_operand:DI 1 "general_operand" "")
    767 		(match_operand:DI 2 "general_operand" "")))]
    768   "TARGET_INLINE_INT_DIV"
    769 {
    770   rtx op2_neg, div;
    771 
    772   div = gen_reg_rtx (DImode);
    773   emit_insn (gen_divdi3 (div, operands[1], operands[2]));
    774 
    775   op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
    776 
    777   emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
    778   DONE;
    779 })
    780 
    781 (define_expand "udivdi3"
    782   [(set (match_operand:DI 0 "register_operand" "")
    783 	(udiv:DI (match_operand:DI 1 "general_operand" "")
    784 		 (match_operand:DI 2 "general_operand" "")))]
    785   "TARGET_INLINE_INT_DIV"
    786 {
    787   rtx op1_rf, op2_rf, op0_rf;
    788 
    789   op0_rf = gen_reg_rtx (RFmode);
    790 
    791   if (! register_operand (operands[1], DImode))
    792     operands[1] = force_reg (DImode, operands[1]);
    793   op1_rf = gen_reg_rtx (RFmode);
    794   expand_float (op1_rf, operands[1], 1);
    795 
    796   if (! register_operand (operands[2], DImode))
    797     operands[2] = force_reg (DImode, operands[2]);
    798   op2_rf = gen_reg_rtx (RFmode);
    799   expand_float (op2_rf, operands[2], 1);
    800 
    801   emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
    802                             CONST1_RTX (DImode)));
    803 
    804   if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
    805     emit_insn (gen_divdi3_internal_lat (op0_rf, op1_rf, op2_rf));
    806   else
    807     emit_insn (gen_divdi3_internal_thr (op0_rf, op1_rf, op2_rf));
    808 
    809   emit_insn (gen_fixuns_truncrfdi2_alts (operands[0], op0_rf, const1_rtx));
    810   DONE;
    811 })
    812 
    813 (define_expand "umoddi3"
    814   [(set (match_operand:DI 0 "register_operand" "")
    815 	(umod:DI (match_operand:DI 1 "general_operand" "")
    816 		 (match_operand:DI 2 "general_operand" "")))]
    817   "TARGET_INLINE_INT_DIV"
    818 {
    819   rtx op2_neg, div;
    820 
    821   div = gen_reg_rtx (DImode);
    822   emit_insn (gen_udivdi3 (div, operands[1], operands[2]));
    823 
    824   op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
    825 
    826   emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
    827   DONE;
    828 })
    829 
    830 (define_expand "divdi3_internal_lat"
    831   [(set (match_operand:RF 0 "fr_register_operand" "")
    832         (float:RF (div:DI (match_operand:RF 1 "fr_register_operand" "")
    833                           (match_operand:RF 2 "fr_register_operand" ""))))]
    834   "TARGET_INLINE_INT_DIV"
    835 {
    836   rtx a         = operands[1];
    837   rtx b         = operands[2];
    838   rtx y         = gen_reg_rtx (RFmode);
    839   rtx y1        = gen_reg_rtx (RFmode);
    840   rtx y2        = gen_reg_rtx (RFmode);
    841   rtx e         = gen_reg_rtx (RFmode);
    842   rtx e1        = gen_reg_rtx (RFmode);
    843   rtx q         = gen_reg_rtx (RFmode);
    844   rtx q1        = gen_reg_rtx (RFmode);
    845   rtx q2        = gen_reg_rtx (RFmode);
    846   rtx r         = gen_reg_rtx (RFmode);
    847   rtx cond      = gen_reg_rtx (CCImode);
    848   rtx zero      = CONST0_RTX (RFmode);
    849   rtx one       = CONST1_RTX (RFmode);
    850   rtx status1   = CONST1_RTX (SImode);
    851   rtx trunc_off = CONST2_RTX (SImode);
    852 
    853   /* y  = 1 / b			*/
    854   emit_insn (gen_recip_approx_rf (y, a, b, cond, status1));
    855   /* e  = 1 - (b * y)		*/
    856   emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
    857   /* q  = a * y                 */
    858   emit_insn (gen_mulrf3_cond (q, cond, a, y, zero, status1, trunc_off));
    859   /* q1 = q + (q * e)		*/
    860   emit_insn (gen_m2addrf4_cond (q1, cond, q, q, e, zero, status1, trunc_off));
    861   /* e1 = e * e			*/
    862   emit_insn (gen_mulrf3_cond (e1, cond, e, e, zero, status1, trunc_off));
    863   /* q2 = q1 + (e1 * q1)	*/
    864   emit_insn (gen_m2addrf4_cond (q2, cond, q1, e1, q1, zero, status1, trunc_off));
    865   /* y1 = y + (y * e)		*/
    866   emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e, zero, status1, trunc_off));
    867   /* r  = a - (b * q2)		*/
    868   emit_insn (gen_m2subrf4_cond (r, cond, a, b, q2, zero, status1, trunc_off));
    869   /* y2 = y1 + (y1 * e1)	*/
    870   emit_insn (gen_m2addrf4_cond (y2, cond, y1, y1, e1, zero, status1, trunc_off));
    871   /* q3 = q2 + (r * y2)		*/
    872   emit_insn (gen_m2addrf4_cond (operands[0], cond, q2, r, y2, y, status1, trunc_off));
    873   DONE;
    874 })
    875 
    876 (define_expand "divdi3_internal_thr"
    877   [(set (match_operand:RF 0 "fr_register_operand" "")
    878         (float:RF (div:DI (match_operand:RF 1 "fr_register_operand" "")
    879                           (match_operand:RF 2 "fr_register_operand" ""))))]
    880   "TARGET_INLINE_INT_DIV"
    881 {
    882   rtx a         = operands[1];
    883   rtx b         = operands[2];
    884   rtx y         = gen_reg_rtx (RFmode);
    885   rtx y1        = gen_reg_rtx (RFmode);
    886   rtx y2        = gen_reg_rtx (RFmode);
    887   rtx e         = gen_reg_rtx (RFmode);
    888   rtx e1        = gen_reg_rtx (RFmode);
    889   rtx q2        = gen_reg_rtx (RFmode);
    890   rtx r         = gen_reg_rtx (RFmode);
    891   rtx cond      = gen_reg_rtx (CCImode);
    892   rtx zero      = CONST0_RTX (RFmode);
    893   rtx one       = CONST1_RTX (RFmode);
    894   rtx status1   = CONST1_RTX (SImode);
    895   rtx trunc_off = CONST2_RTX (SImode);
    896 
    897   /* y  = 1 / b			*/
    898   emit_insn (gen_recip_approx_rf (y, a, b, cond, status1));
    899   /* e  = 1 - (b * y)		*/
    900   emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
    901   /* y1 = y + (y * e)		*/
    902   emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e, zero, status1, trunc_off));
    903   /* e1 = e * e			*/
    904   emit_insn (gen_mulrf3_cond (e1, cond, e, e, zero, status1, trunc_off));
    905   /* y2 = y1 + (y1 * e1)	*/
    906   emit_insn (gen_m2addrf4_cond (y2, cond, y1, y1, e1, zero, status1, trunc_off));
    907   /* q2 = y2 * a		*/
    908   emit_insn (gen_mulrf3_cond (q2, cond, y2, a, zero, status1, trunc_off));
    909   /* r  = a - (b * q2)		*/
    910   emit_insn (gen_m2subrf4_cond (r, cond, a, b, q2, zero, status1, trunc_off));
    911   /* q3 = q2 + (r * y2)		*/
    912   emit_insn (gen_m2addrf4_cond (operands[0], cond, q2, r, y2, y, status1, trunc_off));
    913   DONE;
    914 })
    915 
    916 ;; SQRT operations
    917 
    918 
    919 (define_insn "sqrt_approx_rf"
    920   [(set (match_operand:RF 0 "fr_register_operand" "=f")
    921                 (unspec:RF [(match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")]
    922 			   UNSPEC_FR_SQRT_RECIP_APPROX_RES))
    923    (set (match_operand:CCI 2 "register_operand" "=c")
    924         (unspec:CCI [(match_dup 1)] UNSPEC_FR_SQRT_RECIP_APPROX))
    925    (use (match_operand:SI 3 "const_int_operand" ""))]
    926   ""
    927   "frsqrta.s%3 %0, %2 = %F1"
    928   [(set_attr "itanium_class" "fmisc")
    929    (set_attr "predicable" "no")])
    930 
    931 (define_expand "sqrtsf2"
    932   [(set (match_operand:SF 0 "fr_register_operand" "=&f")
    933 	(sqrt:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
    934   "TARGET_INLINE_SQRT"
    935 {
    936   rtx insn;
    937   if (TARGET_INLINE_SQRT == INL_MIN_LAT)
    938     insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]);
    939   else
    940     insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
    941   emit_insn (insn);
    942   DONE;
    943 })
    944 
    945 (define_expand "sqrtsf2_internal_thr"
    946   [(set (match_operand:SF 0 "fr_register_operand" "")
    947         (sqrt:SF (match_operand:SF 1 "fr_register_operand" "")))]
    948   "TARGET_INLINE_SQRT"
    949 {
    950   rtx y         = gen_reg_rtx (RFmode);
    951   rtx b         = gen_reg_rtx (RFmode);
    952   rtx g         = gen_reg_rtx (RFmode);
    953   rtx e         = gen_reg_rtx (RFmode);
    954   rtx s         = gen_reg_rtx (RFmode);
    955   rtx f         = gen_reg_rtx (RFmode);
    956   rtx y1        = gen_reg_rtx (RFmode);
    957   rtx g1        = gen_reg_rtx (RFmode);
    958   rtx h         = gen_reg_rtx (RFmode);
    959   rtx d         = gen_reg_rtx (RFmode);
    960   rtx g2        = gen_reg_rtx (RFmode);
    961   rtx cond      = gen_reg_rtx (CCImode);
    962   rtx zero      = CONST0_RTX (RFmode);
    963   rtx one       = CONST1_RTX (RFmode);
    964   rtx c1        = ia64_dconst_0_5();
    965   rtx c2        = ia64_dconst_0_375();
    966   rtx reg_df_c1	= gen_reg_rtx (DFmode);
    967   rtx reg_df_c2	= gen_reg_rtx (DFmode);
    968   rtx reg_rf_c1 = gen_reg_rtx (RFmode);
    969   rtx reg_rf_c2 = gen_reg_rtx (RFmode);
    970   rtx status0   = CONST0_RTX (SImode);
    971   rtx status1   = CONST1_RTX (SImode);
    972   rtx trunc_sgl = CONST0_RTX (SImode);
    973   rtx trunc_off = CONST2_RTX (SImode);
    974 
    975   /* Put needed constants into registers.	 */
    976   emit_insn (gen_movdf (reg_df_c1, c1));
    977   emit_insn (gen_movdf (reg_df_c2, c2));
    978   emit_insn (gen_extenddfrf2 (reg_rf_c1, reg_df_c1));
    979   emit_insn (gen_extenddfrf2 (reg_rf_c2, reg_df_c2));
    980   /* Empty conversion to put input into RFmode.  */
    981   emit_insn (gen_extendsfrf2 (b, operands[1]));
    982   /* y = sqrt (1 / b)			*/
    983   emit_insn (gen_sqrt_approx_rf (y, b, cond, status0));
    984   /* g = b * y				*/
    985   emit_insn (gen_mulrf3_cond (g, cond, b, y, zero, status1, trunc_off));
    986   /* e = 1 - (g * y)			*/
    987   emit_insn (gen_m2subrf4_cond (e, cond, one, g, y, zero, status1, trunc_off));
    988   /* s = 0.5 + (0.375 * e)		*/
    989   emit_insn (gen_m2addrf4_cond (s, cond, reg_rf_c1, reg_rf_c2, e, zero, status1, trunc_off));
    990   /* f = y * e				*/
    991   emit_insn (gen_mulrf3_cond (f, cond, y, e, zero, status1, trunc_off));
    992   /* y1 = y + (f * s)			*/
    993   emit_insn (gen_m2addrf4_cond (y1, cond, y, f, s, zero, status1, trunc_off));
    994   /* g1 = single (b * y1)		*/
    995   emit_insn (gen_mulrf3_cond (g1, cond, b, y1, zero, status1, trunc_sgl));
    996   /* h = 0.5 * y1			*/
    997   emit_insn (gen_mulrf3_cond (h, cond, reg_rf_c1, y1, zero, status1, trunc_off));
    998   /* d = b - g1 * g1			*/
    999   emit_insn (gen_m2subrf4_cond (d, cond, b, g1, g1, zero, status1, trunc_off));
   1000   /* g2 = single(g1 + (d * h))		*/
   1001   emit_insn (gen_m2addrf4_cond (g2, cond, g1, d, h, y, status0, trunc_sgl));
   1002   /* Conversion back into SFmode.       */
   1003   emit_insn (gen_truncrfsf2 (operands[0], g2));
   1004   DONE;
   1005 })
   1006 
   1007 (define_expand "sqrtsf2_internal_lat"
   1008   [(set (match_operand:SF 0 "fr_register_operand" "")
   1009         (sqrt:SF (match_operand:SF 1 "fr_register_operand" "")))]
   1010   "TARGET_INLINE_SQRT"
   1011 {
   1012   rtx y         = gen_reg_rtx (RFmode);
   1013   rtx b         = gen_reg_rtx (RFmode);
   1014   rtx g         = gen_reg_rtx (RFmode);
   1015   rtx g1        = gen_reg_rtx (RFmode);
   1016   rtx g2        = gen_reg_rtx (RFmode);
   1017   rtx e         = gen_reg_rtx (RFmode);
   1018   rtx s         = gen_reg_rtx (RFmode);
   1019   rtx f         = gen_reg_rtx (RFmode);
   1020   rtx f1        = gen_reg_rtx (RFmode);
   1021   rtx h         = gen_reg_rtx (RFmode);
   1022   rtx h1        = gen_reg_rtx (RFmode);
   1023   rtx d         = gen_reg_rtx (RFmode);
   1024   rtx cond      = gen_reg_rtx (CCImode);
   1025   rtx zero      = CONST0_RTX (RFmode);
   1026   rtx one       = CONST1_RTX (RFmode);
   1027   rtx c1        = ia64_dconst_0_5();
   1028   rtx c2        = ia64_dconst_0_375();
   1029   rtx reg_df_c1	= gen_reg_rtx (DFmode);
   1030   rtx reg_df_c2	= gen_reg_rtx (DFmode);
   1031   rtx reg_rf_c1 = gen_reg_rtx (RFmode);
   1032   rtx reg_rf_c2 = gen_reg_rtx (RFmode);
   1033   rtx status0   = CONST0_RTX (SImode);
   1034   rtx status1   = CONST1_RTX (SImode);
   1035   rtx trunc_sgl = CONST0_RTX (SImode);
   1036   rtx trunc_off = CONST2_RTX (SImode);
   1037 
   1038   /* Put needed constants into registers.	 */
   1039   emit_insn (gen_movdf (reg_df_c1, c1));
   1040   emit_insn (gen_movdf (reg_df_c2, c2));
   1041   emit_insn (gen_extenddfrf2 (reg_rf_c1, reg_df_c1));
   1042   emit_insn (gen_extenddfrf2 (reg_rf_c2, reg_df_c2));
   1043   /* Empty conversion to put input into RFmode.  */
   1044   emit_insn (gen_extendsfrf2 (b, operands[1]));
   1045   /* y = sqrt (1 / b)			*/
   1046   emit_insn (gen_sqrt_approx_rf (y, b, cond, status0));
   1047   /* g = b * y				*/
   1048   emit_insn (gen_mulrf3_cond (g, cond, b, y, zero, status1, trunc_off));
   1049   /* e = 1 - (g * y)			*/
   1050   emit_insn (gen_m2subrf4_cond (e, cond, one, g, y, zero, status1, trunc_off));
   1051   /* h = 0.5 * y			*/
   1052   emit_insn (gen_mulrf3_cond (h, cond, reg_rf_c1, y, zero, status1, trunc_off));
   1053   /* s = 0.5 + (0.375 * e)		*/
   1054   emit_insn (gen_m2addrf4_cond (s, cond, reg_rf_c1, reg_rf_c2, e, zero, status1, trunc_off));
   1055   /* f = e * g				*/
   1056   emit_insn (gen_mulrf3_cond (f, cond, e, g, zero, status1, trunc_off));
   1057   /* g1 = single (g + (f * s))		*/
   1058   emit_insn (gen_m2addrf4_cond (g1, cond, g, f, s, zero, status1, trunc_sgl));
   1059   /* f1 = e * h				*/
   1060   emit_insn (gen_mulrf3_cond (f1, cond, e, h, zero, status1, trunc_off));
   1061   /* d = b - g1 * g1			*/
   1062   emit_insn (gen_m2subrf4_cond (d, cond, b, g1, g1, zero, status1, trunc_off));
   1063   /* h1 = h + (f1 * s)			*/
   1064   emit_insn (gen_m2addrf4_cond (h1, cond, h, f1, s, zero, status1, trunc_off));
   1065   /* g2 = single(g1 + (d * h1))		*/
   1066   emit_insn (gen_m2addrf4_cond (g2, cond, g1, d, h1, y, status0, trunc_sgl));
   1067   /* Conversion back into SFmode.       */
   1068   emit_insn (gen_truncrfsf2 (operands[0], g2));
   1069   DONE;
   1070 })
   1071 
   1072 (define_expand "sqrtdf2"
   1073   [(set (match_operand:DF 0 "fr_register_operand" "=&f")
   1074 	(sqrt:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
   1075   "TARGET_INLINE_SQRT"
   1076 {
   1077   rtx insn;
   1078 #if 0
   1079   if (TARGET_INLINE_SQRT == INL_MIN_LAT)
   1080     insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]);
   1081   else
   1082 #endif
   1083   insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
   1084   emit_insn (insn);
   1085   DONE;
   1086 })
   1087 
   1088 (define_expand "sqrtdf2_internal_thr"
   1089   [(set (match_operand:DF 0 "fr_register_operand" "")
   1090         (sqrt:DF (match_operand:DF 1 "fr_register_operand" "")))]
   1091   "TARGET_INLINE_SQRT"
   1092 {
   1093   rtx y         = gen_reg_rtx (RFmode);
   1094   rtx b         = gen_reg_rtx (RFmode);
   1095   rtx g         = gen_reg_rtx (RFmode);
   1096   rtx g1        = gen_reg_rtx (RFmode);
   1097   rtx g2        = gen_reg_rtx (RFmode);
   1098   rtx g3        = gen_reg_rtx (RFmode);
   1099   rtx g4        = gen_reg_rtx (RFmode);
   1100   rtx r         = gen_reg_rtx (RFmode);
   1101   rtx r1        = gen_reg_rtx (RFmode);
   1102   rtx h         = gen_reg_rtx (RFmode);
   1103   rtx h1        = gen_reg_rtx (RFmode);
   1104   rtx h2        = gen_reg_rtx (RFmode);
   1105   rtx d         = gen_reg_rtx (RFmode);
   1106   rtx d1        = gen_reg_rtx (RFmode);
   1107   rtx cond      = gen_reg_rtx (CCImode);
   1108   rtx zero      = CONST0_RTX (RFmode);
   1109   rtx c1        = ia64_dconst_0_5();
   1110   rtx reg_df_c1	= gen_reg_rtx (DFmode);
   1111   rtx reg_rf_c1 = gen_reg_rtx (RFmode);
   1112   rtx status0   = CONST0_RTX (SImode);
   1113   rtx status1   = CONST1_RTX (SImode);
   1114   rtx trunc_dbl = CONST1_RTX (SImode);
   1115   rtx trunc_off = CONST2_RTX (SImode);
   1116 
   1117   /* Put needed constants into registers.	 */
   1118   emit_insn (gen_movdf (reg_df_c1, c1));
   1119   emit_insn (gen_extenddfrf2 (reg_rf_c1, reg_df_c1));
   1120   /* Empty conversion to put input into RFmode.  */
   1121   emit_insn (gen_extenddfrf2 (b, operands[1]));
   1122   /* y = sqrt (1 / b)			*/
   1123   emit_insn (gen_sqrt_approx_rf (y, b, cond, status0));
   1124   /* g = b * y				*/
   1125   emit_insn (gen_mulrf3_cond (g, cond, b, y, zero, status1, trunc_off));
   1126   /* h = 0.5 * y			*/
   1127   emit_insn (gen_mulrf3_cond (h, cond, reg_rf_c1, y, zero, status1, trunc_off));
   1128   /* r = 0.5 - (g * h)			*/
   1129   emit_insn (gen_m2subrf4_cond (r, cond, reg_rf_c1, g, h, zero, status1, trunc_off));
   1130   /* g1 = g + (g * r)			*/
   1131   emit_insn (gen_m2addrf4_cond (g1, cond, g, g, r, zero, status1, trunc_off));
   1132   /* h1 = h + (h * r)			*/
   1133   emit_insn (gen_m2addrf4_cond (h1, cond, h, h, r, zero, status1, trunc_off));
   1134   /* r1 = 0.5 - (g1 * h1)		*/
   1135   emit_insn (gen_m2subrf4_cond (r1, cond, reg_rf_c1, g1, h1, zero, status1, trunc_off));
   1136   /* g2 = g1 + (g1 * r1)		*/
   1137   emit_insn (gen_m2addrf4_cond (g2, cond, g1, g1, r1, zero, status1, trunc_off));
   1138   /* h2 = h1 + (h1 * r1)		*/
   1139   emit_insn (gen_m2addrf4_cond (h2, cond, h1, h1, r1, zero, status1, trunc_off));
   1140   /* d = b - (g2 * g2)			*/
   1141   emit_insn (gen_m2subrf4_cond (d, cond, b, g2, g2, zero, status1, trunc_off));
   1142   /* g3 = g2 + (d * h2)			*/
   1143   emit_insn (gen_m2addrf4_cond (g3, cond, g2, d, h2, zero, status1, trunc_off));
   1144   /* d1 = b - (g3 * g3)			*/
   1145   emit_insn (gen_m2subrf4_cond (d1, cond, b, g3, g3, zero, status1, trunc_off));
   1146   /* g4 = g3 + (d1 * h2)		*/
   1147   emit_insn (gen_m2addrf4_cond (g4, cond, g3, d1, h2, y, status1, trunc_dbl));
   1148   /* Conversion back into SFmode.       */
   1149   emit_insn (gen_truncrfdf2 (operands[0], g4));
   1150   DONE;
   1151 })
   1152 
   1153 (define_expand "sqrtxf2"
   1154   [(set (match_operand:XF 0 "fr_register_operand" "")
   1155         (sqrt:XF (match_operand:XF 1 "fr_register_operand" "")))]
   1156   "TARGET_INLINE_SQRT"
   1157 {
   1158   rtx y         = gen_reg_rtx (RFmode);
   1159   rtx b         = gen_reg_rtx (RFmode);
   1160   rtx g         = gen_reg_rtx (RFmode);
   1161   rtx g1        = gen_reg_rtx (RFmode);
   1162   rtx g2        = gen_reg_rtx (RFmode);
   1163   rtx g3        = gen_reg_rtx (RFmode);
   1164   rtx g4        = gen_reg_rtx (RFmode);
   1165   rtx e         = gen_reg_rtx (RFmode);
   1166   rtx e1        = gen_reg_rtx (RFmode);
   1167   rtx e2        = gen_reg_rtx (RFmode);
   1168   rtx h         = gen_reg_rtx (RFmode);
   1169   rtx h1        = gen_reg_rtx (RFmode);
   1170   rtx h2        = gen_reg_rtx (RFmode);
   1171   rtx h3        = gen_reg_rtx (RFmode);
   1172   rtx d         = gen_reg_rtx (RFmode);
   1173   rtx d1        = gen_reg_rtx (RFmode);
   1174   rtx cond      = gen_reg_rtx (CCImode);
   1175   rtx zero      = CONST0_RTX (RFmode);
   1176   rtx c1        = ia64_dconst_0_5();
   1177   rtx reg_df_c1	= gen_reg_rtx (DFmode);
   1178   rtx reg_rf_c1 = gen_reg_rtx (RFmode);
   1179   rtx status0   = CONST0_RTX (SImode);
   1180   rtx status1   = CONST1_RTX (SImode);
   1181   rtx trunc_off = CONST2_RTX (SImode);
   1182 
   1183   /* Put needed constants into registers.	 */
   1184   emit_insn (gen_movdf (reg_df_c1, c1));
   1185   emit_insn (gen_extenddfrf2 (reg_rf_c1, reg_df_c1));
   1186   /* Empty conversion to put input into RFmode.  */
   1187   emit_insn (gen_extendxfrf2 (b, operands[1]));
   1188   /* y = sqrt (1 / b)			*/
   1189   emit_insn (gen_sqrt_approx_rf (y, b, cond, status0));
   1190   /* g = b * y				*/
   1191   emit_insn (gen_mulrf3_cond (g, cond, b, y, zero, status1, trunc_off));
   1192   /* h = 0.5 * y			*/
   1193   emit_insn (gen_mulrf3_cond (h, cond, reg_rf_c1, y, zero, status1, trunc_off));
   1194   /* e = 0.5 - (g * h)			*/
   1195   emit_insn (gen_m2subrf4_cond (e, cond, reg_rf_c1, g, h, zero, status1, trunc_off));
   1196   /* g1 = g + (g * e)			*/
   1197   emit_insn (gen_m2addrf4_cond (g1, cond, g, g, e, zero, status1, trunc_off));
   1198   /* h1 = h + (h * e)			*/
   1199   emit_insn (gen_m2addrf4_cond (h1, cond, h, h, e, zero, status1, trunc_off));
   1200   /* e1 = 0.5 - (g1 * h1)		*/
   1201   emit_insn (gen_m2subrf4_cond (e1, cond, reg_rf_c1, g1, h1, zero, status1, trunc_off));
   1202   /* g2 = g1 + (g1 * e1)		*/
   1203   emit_insn (gen_m2addrf4_cond (g2, cond, g1, g1, e1, zero, status1, trunc_off));
   1204   /* h2 = h1 + (h1 * e1)		*/
   1205   emit_insn (gen_m2addrf4_cond (h2, cond, h1, h1, e1, zero, status1, trunc_off));
   1206   /* d = b - (g2 * g2)			*/
   1207   emit_insn (gen_m2subrf4_cond (d, cond, b, g2, g2, zero, status1, trunc_off));
   1208   /* e2 = 0.5 - (g2 * h2)		*/
   1209   emit_insn (gen_m2subrf4_cond (e2, cond, reg_rf_c1, g2, h2, zero, status1, trunc_off));
   1210   /* g3 = g2 + (d * h2)			*/
   1211   emit_insn (gen_m2addrf4_cond (g3, cond, g2, d, h2, zero, status1, trunc_off));
   1212   /* h3 = h2 + (e2 * h2)		*/
   1213   emit_insn (gen_m2addrf4_cond (h3, cond, h2, e2, h2, zero, status1, trunc_off));
   1214   /* d1 = b - (g3 * g3)			*/
   1215   emit_insn (gen_m2subrf4_cond (d1, cond, b, g3, g3, zero, status1, trunc_off));
   1216   /* g4 = g3 + (d1 * h3)		*/
   1217   emit_insn (gen_m2addrf4_cond (g4, cond, g3, d1, h3, y, status1, trunc_off));
   1218   /* Conversion back into SFmode.       */
   1219   emit_insn (gen_truncrfxf2 (operands[0], g4));
   1220   DONE;
   1221 })
   1222