OSDN Git Service

* config/alpha/alpha.c (alpha_preferred_reload_class,
[pf3gnuchains/gcc-fork.git] / gcc / config / ia64 / div.md
1
2 ;; For the internal conditional math routines:
3
4 ;; operand 0 is always the result
5 ;; operand 1 is always the predicate
6 ;; operand 2, 3, and sometimes 4 are the input values.
7 ;; operand 4 or 5 is the floating point status register to use.
8 ;; operand 5 or 6 is the rounding to do. (0 = single, 1 = double, 2 = none)
9 ;;
10 ;; addrf3_cond   - F0 = F2 + F3
11 ;; subrf3_cond   - F0 = F2 - F3
12 ;; mulrf3_cond   - F0 = F2 * F3
13 ;; nmulrf3_cond  - F0 = - (F2 * F3)
14 ;; m1addrf4_cond - F0 = (F2 * F3) + F4
15 ;; m1subrf4_cond - F0 = (F2 * F3) - F4
16 ;; m2addrf4_cond - F0 = F2 + (F3 * F4)
17 ;; m2subrf4_cond - F0 = F2 - (F3 * F4)
18
19 ;; Basic plus/minus/mult operations
20
21 (define_insn "addrf3_cond"
22   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
23         (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
24                                 (const_int 0))
25           (plus:RF
26             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
27             (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG"))
28           (match_operand:RF 4 "fr_reg_or_0_operand" "0,H")))
29    (use (match_operand:SI 5 "const_int_operand" ""))
30    (use (match_operand:SI 6 "const_int_operand" ""))]
31   ""
32   "(%1) fadd%R6.s%5 %0 = %F2, %F3"
33   [(set_attr "itanium_class" "fmac")
34    (set_attr "predicable" "no")])
35
36 (define_insn "subrf3_cond"
37   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
38         (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
39                                 (const_int 0))
40           (minus:RF
41             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
42             (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG"))
43           (match_operand:RF 4 "fr_reg_or_0_operand" "0,H")))
44    (use (match_operand:SI 5 "const_int_operand" ""))
45    (use (match_operand:SI 6 "const_int_operand" ""))]
46   ""
47   "(%1) fsub%R6.s%5 %0 = %F2, %F3"
48   [(set_attr "itanium_class" "fmac")
49    (set_attr "predicable" "no")])
50
51 (define_insn "mulrf3_cond"
52   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
53         (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
54                                 (const_int 0))
55           (mult:RF
56             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
57             (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG"))
58           (match_operand:RF 4 "fr_reg_or_0_operand" "0,H")))
59    (use (match_operand:SI 5 "const_int_operand" ""))
60    (use (match_operand:SI 6 "const_int_operand" ""))]
61   ""
62   "(%1) fmpy%R6.s%5 %0 = %F2, %F3"
63   [(set_attr "itanium_class" "fmac")
64    (set_attr "predicable" "no")])
65
66 ;; neg-mult operation
67
68 (define_insn "nmulrf3_cond"
69   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
70         (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
71                                 (const_int 0))
72           (neg:RF (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) fnmpy%R6.s%5 %0 = %F2, %F3"
80   [(set_attr "itanium_class" "fmac")
81    (set_attr "predicable" "no")])
82
83 ;; add-mult/sub-mult operations (mult as op1)
84
85 (define_insn "m1addrf4_cond"
86   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
87         (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
88                                 (const_int 0))
89           (plus:RF
90             (mult:RF
91               (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
92               (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG"))
93             (match_operand:RF 4 "fr_reg_or_fp01_operand" "fG,fG"))
94           (match_operand:RF 5 "fr_reg_or_0_operand" "0,H")))
95    (use (match_operand:SI 6 "const_int_operand" ""))
96    (use (match_operand:SI 7 "const_int_operand" ""))]
97   ""
98   "(%1) fma%R7.s%6 %0 = %F2, %F3, %F4"
99   [(set_attr "itanium_class" "fmac")
100    (set_attr "predicable" "no")])
101
102 (define_insn "m1subrf4_cond"
103   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
104         (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
105                                 (const_int 0))
106           (minus: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) fms%R7.s%6 %0 = %F2, %F3, %F4"
116   [(set_attr "itanium_class" "fmac")
117    (set_attr "predicable" "no")])
118
119 ;; add-mult/sub-mult operations (mult as op2)
120
121 (define_insn "m2addrf4_cond"
122   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
123         (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
124                                 (const_int 0))
125           (plus:RF
126             (match_operand:RF 2 "fr_reg_or_fp01_operand" "fG,fG")
127             (mult:RF
128               (match_operand:RF 3 "fr_reg_or_fp01_operand" "fG,fG")
129               (match_operand:RF 4 "fr_reg_or_fp01_operand" "fG,fG")))
130           (match_operand:RF 5 "fr_reg_or_0_operand" "0,H")))
131    (use (match_operand:SI 6 "const_int_operand" ""))
132    (use (match_operand:SI 7 "const_int_operand" ""))]
133   ""
134   "(%1) fma%R7.s%6 %0 = %F3, %F4, %F2"
135   [(set_attr "itanium_class" "fmac")
136    (set_attr "predicable" "no")])
137
138 (define_insn "m2subrf4_cond"
139   [(set (match_operand:RF 0 "fr_register_operand" "=f,f")
140         (if_then_else:RF (ne:RF (match_operand:BI 1 "register_operand"  "c,c")
141                                 (const_int 0))
142           (minus: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) fnma%R7.s%6 %0 = %F3, %F4, %F2"
152   [(set_attr "itanium_class" "fmac")
153    (set_attr "predicable" "no")])
154
155 ;; Conversions to/from RF and SF/DF/XF
156 ;; These conversions should not generate any code but make it possible
157 ;; for all the instructions used to implement floating point division
158 ;; to be written for RFmode only and to not have to handle multiple
159 ;; modes or to have to handle a register in more than one mode.
160
161 (define_mode_iterator SDX_F [SF DF XF])
162
163 (define_insn "extend<mode>rf2"
164   [(set (match_operand:RF 0 "fr_register_operand" "=f")
165         (float_extend:RF (match_operand:SDX_F 1 "fr_register_operand" "f")))]
166   ""
167   "#"
168   [(set_attr "itanium_class" "fmisc")
169    (set_attr "predicable" "yes")])
170
171 (define_split
172   [(set (match_operand:RF 0 "fr_register_operand" "")
173         (float_extend:RF (match_operand:SDX_F 1 "fr_register_operand" "")))]
174    "reload_completed"
175    [(set (match_dup 0) (match_dup 2))]
176 {
177    operands[2] = gen_rtx_REG (RFmode, REGNO (operands[1]));
178 })
179
180
181 (define_insn "truncrf<mode>2"
182   [(set (match_operand:SDX_F 0 "fr_register_operand" "=f")
183         (float_truncate:SDX_F (match_operand:RF 1 "fr_register_operand" "f")))]
184   ""
185   "#"
186   [(set_attr "itanium_class" "fmisc")
187    (set_attr "predicable" "yes")])
188
189 (define_split
190   [(set (match_operand:SDX_F 0 "fr_register_operand" "")
191         (float_truncate:SDX_F (match_operand:RF 1 "fr_register_operand" "")))]
192    "reload_completed"
193    [(set (match_dup 0) (match_dup 2))]
194 {
195    operands[2] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
196 })
197
198 ;; Reciprocal approximation
199
200 (define_insn "recip_approx_rf"
201   [(set (match_operand:RF 0 "fr_register_operand" "=f")
202         (unspec:RF [(match_operand:RF 1 "fr_register_operand" "f")
203                     (match_operand:RF 2 "fr_register_operand" "f")]
204                    UNSPEC_FR_RECIP_APPROX_RES))
205    (set (match_operand:BI 3 "register_operand" "=c")
206         (unspec:BI [(match_dup 1) (match_dup 2)] UNSPEC_FR_RECIP_APPROX))
207    (use (match_operand:SI 4 "const_int_operand" ""))]
208   ""
209   "frcpa.s%4 %0, %3 = %1, %2"
210   [(set_attr "itanium_class" "fmisc")
211    (set_attr "predicable" "no")])
212
213 ;; Single precision floating point division (maximum throughput algorithm).
214
215 (define_expand "divsf3_internal_thr"
216   [(set (match_operand:SF 0 "fr_register_operand" "")
217         (div:SF (match_operand:SF 1 "fr_register_operand" "")
218                 (match_operand:SF 2 "fr_register_operand" "")))]
219   "TARGET_INLINE_FLOAT_DIV"
220 {
221   rtx y     = gen_reg_rtx (RFmode);
222   rtx a     = gen_reg_rtx (RFmode);
223   rtx b     = gen_reg_rtx (RFmode);
224   rtx e     = gen_reg_rtx (RFmode);
225   rtx y1    = gen_reg_rtx (RFmode);
226   rtx y2    = gen_reg_rtx (RFmode);
227   rtx q     = gen_reg_rtx (RFmode);
228   rtx r     = gen_reg_rtx (RFmode);
229   rtx q_res = gen_reg_rtx (RFmode);
230   rtx cond  = gen_reg_rtx (BImode);
231   rtx zero    = CONST0_RTX (RFmode);
232   rtx one     = CONST1_RTX (RFmode);
233   rtx status0 = CONST0_RTX (SImode);
234   rtx status1 = CONST1_RTX (SImode);
235   rtx trunc_sgl = CONST0_RTX (SImode);
236   rtx trunc_off    = CONST2_RTX (SImode);
237
238   /* Empty conversions to put inputs into RFmode.  */
239   emit_insn (gen_extendsfrf2 (a, operands[1]));
240   emit_insn (gen_extendsfrf2 (b, operands[2]));
241   /* y = 1 / b                          */
242   emit_insn (gen_recip_approx_rf (y, a, b, cond, status0));
243   /* e = 1 - (b * y)                    */
244   emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
245   /* y1 = y + (y * e)                   */
246   emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e, zero, status1, trunc_off));
247   /* y2 = y + (y1 * e)                  */
248   emit_insn (gen_m2addrf4_cond (y2, cond, y, y1, e, zero, status1, trunc_off));
249   /* q = single(a * y2)                 */
250   emit_insn (gen_mulrf3_cond (q, cond, a, y2, zero, status1, trunc_sgl));
251   /* r = a - (q * b)                    */
252   emit_insn (gen_m2subrf4_cond (r, cond, a, q, b, zero, status1, trunc_off));
253   /* Q = single (q + (r * y2))          */
254   emit_insn (gen_m2addrf4_cond (q_res, cond, q, r, y2, y, status0, trunc_sgl));
255   /* Conversion back into SFmode.       */
256   emit_insn (gen_truncrfsf2 (operands[0], q_res));
257   DONE;
258 })
259
260
261 ;; Double precision floating point division (maximum throughput algorithm).
262
263 (define_expand "divdf3_internal_thr"
264   [(set (match_operand:DF 0 "fr_register_operand" "")
265         (div:DF (match_operand:DF 1 "fr_register_operand" "")
266                 (match_operand:DF 2 "fr_register_operand" "")))]
267   "TARGET_INLINE_FLOAT_DIV"
268 {
269   rtx q_res = gen_reg_rtx (RFmode);
270   rtx a     = gen_reg_rtx (RFmode);
271   rtx b     = gen_reg_rtx (RFmode);
272   rtx y     = gen_reg_rtx (RFmode);
273   rtx e     = gen_reg_rtx (RFmode);
274   rtx y1    = gen_reg_rtx (RFmode);
275   rtx e1    = gen_reg_rtx (RFmode);
276   rtx y2    = gen_reg_rtx (RFmode);
277   rtx e2    = gen_reg_rtx (RFmode);
278   rtx y3    = gen_reg_rtx (RFmode);
279   rtx q     = gen_reg_rtx (RFmode);
280   rtx r     = gen_reg_rtx (RFmode);
281   rtx cond  = gen_reg_rtx (BImode);
282   rtx zero    = CONST0_RTX (RFmode);
283   rtx one     = CONST1_RTX (RFmode);
284   rtx status0 = CONST0_RTX (SImode);
285   rtx status1 = CONST1_RTX (SImode);
286   rtx trunc_dbl = CONST1_RTX (SImode);
287   rtx trunc_off = CONST2_RTX (SImode);
288   /* Empty conversions to put inputs into RFmode */
289   emit_insn (gen_extenddfrf2 (a, operands[1]));
290   emit_insn (gen_extenddfrf2 (b, operands[2]));
291   /* y  = 1 / b                 */
292   emit_insn (gen_recip_approx_rf (y, a, b, cond, status0));
293   /* e  = 1 - (b * y)           */
294   emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
295   /* y1 = y + (y * e)           */
296   emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e, zero, status1, trunc_off));
297   /* e1 = e * e                 */
298   emit_insn (gen_mulrf3_cond (e1, cond, e, e, zero, status1, trunc_off));
299   /* y2 = y1 + (y1 * e1)        */
300   emit_insn (gen_m2addrf4_cond (y2, cond, y1, y1, e1, zero, status1, trunc_off));
301   /* e2 = e1 * e1               */
302   emit_insn (gen_mulrf3_cond (e2, cond, e1, e1, zero, status1, trunc_off));
303   /* y3 = y2 + (y2 * e2)        */
304   emit_insn (gen_m2addrf4_cond (y3, cond, y2, y2, e2, zero, status1, trunc_off));
305   /* q  = double (a * y3)       */
306   emit_insn (gen_mulrf3_cond (q, cond, a, y3, zero, status1, trunc_dbl));
307   /* r  = a - (b * q)           */
308   emit_insn (gen_m2subrf4_cond (r, cond, a, b, q, zero, status1, trunc_off));
309   /* Q  = double (q + (r * y3)) */
310   emit_insn (gen_m2addrf4_cond (q_res, cond, q, r, y3, y, status0, trunc_dbl));
311   /* Conversion back into DFmode */
312   emit_insn (gen_truncrfdf2 (operands[0], q_res));
313   DONE;
314 })