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