Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/ia64/div.md @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
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 }) |