]>
Commit | Line | Data |
---|---|---|
f1717362 | 1 | ;; Copyright (C) 2006-2016 Free Software Foundation, Inc. |
644459d0 | 2 | |
3 | ;; This file is free software; you can redistribute it and/or modify it under | |
4 | ;; the terms of the GNU General Public License as published by the Free | |
038d1e19 | 5 | ;; Software Foundation; either version 3 of the License, or (at your option) |
644459d0 | 6 | ;; any later version. |
7 | ||
8 | ;; This file is distributed in the hope that it will be useful, but WITHOUT | |
9 | ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
10 | ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
11 | ;; for more details. | |
12 | ||
13 | ;; You should have received a copy of the GNU General Public License | |
038d1e19 | 14 | ;; along with GCC; see the file COPYING3. If not see |
15 | ;; <http://www.gnu.org/licenses/>. | |
644459d0 | 16 | |
17 | ||
18 | ;; This includes expands for all the intrinsics. | |
19 | ;; spu_expand_builtin looks at the mode of match_operand. | |
20 | ||
21 | \f | |
22 | ;; load/store | |
23 | ||
24 | (define_expand "spu_lqd" | |
25 | [(set (match_operand:TI 0 "spu_reg_operand" "") | |
26 | (mem:TI (and:SI (plus:SI (match_operand:SI 1 "spu_reg_operand" "") | |
27 | (match_operand:SI 2 "spu_nonmem_operand" "")) | |
28 | (const_int -16))))] | |
29 | "" | |
30 | { | |
31 | if (GET_CODE (operands[2]) == CONST_INT | |
32 | && (INTVAL (operands[2]) & 15) != 0) | |
33 | operands[2] = GEN_INT (INTVAL (operands[2]) & -16); | |
34 | if (GET_CODE (operands[2]) != CONST_INT) | |
35 | { | |
36 | rtx op2 = operands[2]; | |
37 | operands[2] = force_reg (Pmode, operands[2]); | |
38 | if (!ALIGNED_SYMBOL_REF_P (op2)) | |
39 | emit_insn (gen_andsi3 (operands[2], operands[2], GEN_INT (-16))); | |
40 | } | |
41 | }) | |
42 | ||
43 | (define_expand "spu_lqx" | |
44 | [(set (match_operand:TI 0 "spu_reg_operand" "") | |
45 | (mem:TI (and:SI (plus:SI (match_operand:SI 1 "spu_reg_operand" "") | |
46 | (match_operand:SI 2 "spu_reg_operand" "")) | |
47 | (const_int -16))))] | |
48 | "" | |
49 | "") | |
50 | ||
51 | (define_expand "spu_lqa" | |
52 | [(set (match_operand:TI 0 "spu_reg_operand" "") | |
53 | (mem:TI (and:SI (match_operand:SI 1 "immediate_operand" "") | |
54 | (const_int -16))))] | |
55 | "" | |
56 | { | |
57 | if (GET_CODE (operands[1]) == CONST_INT | |
58 | && (INTVAL (operands[1]) & 15) != 0) | |
59 | operands[1] = GEN_INT (INTVAL (operands[1]) & -16); | |
60 | }) | |
61 | ||
62 | (define_expand "spu_lqr" | |
63 | [(set (match_operand:TI 0 "spu_reg_operand" "") | |
64 | (mem:TI (and:SI (match_operand:SI 1 "address_operand" "") | |
65 | (const_int -16))))] | |
66 | "" | |
67 | "") | |
68 | ||
69 | (define_expand "spu_stqd" | |
70 | [(set (mem:TI (and:SI (plus:SI (match_operand:SI 1 "spu_reg_operand" "") | |
71 | (match_operand:SI 2 "spu_nonmem_operand" "")) | |
72 | (const_int -16))) | |
73 | (match_operand:TI 0 "spu_reg_operand" "r,r"))] | |
74 | "" | |
75 | { | |
76 | if (GET_CODE (operands[2]) == CONST_INT | |
77 | && (INTVAL (operands[2]) & 15) != 0) | |
78 | operands[2] = GEN_INT (INTVAL (operands[2]) & -16); | |
79 | if (GET_CODE (operands[2]) != CONST_INT) | |
80 | { | |
81 | rtx op2 = operands[2]; | |
82 | operands[2] = force_reg (Pmode, operands[2]); | |
83 | if (!ALIGNED_SYMBOL_REF_P (op2)) | |
84 | emit_insn (gen_andsi3 (operands[2], operands[2], GEN_INT (-16))); | |
85 | } | |
86 | }) | |
87 | ||
88 | (define_expand "spu_stqx" | |
89 | [(set (mem:TI (and:SI (plus:SI (match_operand:SI 1 "spu_reg_operand" "") | |
90 | (match_operand:SI 2 "spu_reg_operand" "")) | |
91 | (const_int -16))) | |
92 | (match_operand:TI 0 "spu_reg_operand" "r"))] | |
93 | "" | |
94 | "") | |
95 | ||
96 | (define_expand "spu_stqa" | |
97 | [(set (mem:TI (and:SI (match_operand:SI 1 "immediate_operand" "") | |
98 | (const_int -16))) | |
99 | (match_operand:TI 0 "spu_reg_operand" "r"))] | |
100 | "" | |
101 | { | |
102 | if (GET_CODE (operands[1]) == CONST_INT | |
103 | && (INTVAL (operands[1]) & 15) != 0) | |
104 | operands[1] = GEN_INT (INTVAL (operands[1]) & -16); | |
105 | }) | |
106 | ||
107 | (define_expand "spu_stqr" | |
108 | [(set (mem:TI (and:SI (match_operand:SI 1 "address_operand" "") | |
109 | (const_int -16))) | |
110 | (match_operand:TI 0 "spu_reg_operand" ""))] | |
111 | "" | |
112 | "") | |
113 | ||
114 | \f | |
115 | ;; generate control word | |
116 | ||
117 | (define_expand "spu_cbx" | |
118 | [(set (match_operand:TI 0 "spu_reg_operand" "") | |
119 | (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "") | |
120 | (match_operand:SI 2 "spu_nonmem_operand" "") | |
121 | (const_int 1)] UNSPEC_CPAT))] | |
122 | "" | |
123 | "") | |
124 | ||
125 | (define_expand "spu_chx" | |
126 | [(set (match_operand:TI 0 "spu_reg_operand" "") | |
127 | (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "") | |
128 | (match_operand:SI 2 "spu_nonmem_operand" "") | |
129 | (const_int 2)] UNSPEC_CPAT))] | |
130 | "" | |
131 | "") | |
132 | ||
133 | (define_expand "spu_cwx" | |
134 | [(set (match_operand:TI 0 "spu_reg_operand" "") | |
135 | (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "") | |
136 | (match_operand:SI 2 "spu_nonmem_operand" "") | |
137 | (const_int 4)] UNSPEC_CPAT))] | |
138 | "" | |
139 | "") | |
140 | ||
141 | (define_expand "spu_cdx" | |
142 | [(set (match_operand:TI 0 "spu_reg_operand" "") | |
143 | (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "") | |
144 | (match_operand:SI 2 "spu_nonmem_operand" "") | |
145 | (const_int 8)] UNSPEC_CPAT))] | |
146 | "" | |
147 | "") | |
148 | ||
149 | ||
150 | \f | |
151 | ;; Constant formation | |
152 | ||
153 | (define_expand "spu_ilhu" | |
154 | [(set (match_operand:V4SI 0 "spu_reg_operand" "") | |
155 | (const_vector:V4SI [(match_operand:SI 1 "immediate_operand" "")]))] | |
156 | "" | |
157 | "{ emit_insn(gen_movv4si(operands[0], spu_const(V4SImode, (INTVAL(operands[1]) << 16)))); | |
158 | DONE; | |
159 | }") | |
160 | ||
161 | \f | |
162 | ;; integer subtract | |
163 | (define_expand "spu_sfh" | |
164 | [(set (match_operand:V8HI 0 "spu_reg_operand" "") | |
165 | (minus:V8HI (match_operand:V8HI 2 "spu_nonmem_operand" "") | |
166 | (match_operand:V8HI 1 "spu_reg_operand" "")))] | |
167 | "" | |
168 | "") | |
169 | ||
170 | (define_expand "spu_sf" | |
171 | [(set (match_operand:V4SI 0 "spu_reg_operand" "") | |
172 | (minus:V4SI (match_operand:V4SI 2 "spu_nonmem_operand" "") | |
173 | (match_operand:V4SI 1 "spu_reg_operand" "")))] | |
174 | "" | |
175 | "") | |
176 | ||
177 | (define_expand "spu_sfx" | |
178 | [(set (match_operand:V4SI 0 "spu_reg_operand" "") | |
179 | (unspec:V4SI [(match_operand:V4SI 2 "spu_reg_operand" "") | |
180 | (match_operand:V4SI 1 "spu_reg_operand" "") | |
181 | (match_operand:V4SI 3 "spu_reg_operand" "")] UNSPEC_SFX))] | |
182 | "" | |
183 | "") | |
184 | ||
185 | (define_expand "spu_bg" | |
186 | [(set (match_operand:V4SI 0 "spu_reg_operand" "") | |
187 | (unspec:V4SI [(match_operand:V4SI 2 "spu_reg_operand" "") | |
188 | (match_operand:V4SI 1 "spu_reg_operand" "")] UNSPEC_BG))] | |
189 | "" | |
190 | "") | |
191 | ||
192 | (define_expand "spu_bgx" | |
193 | [(set (match_operand:V4SI 0 "spu_reg_operand" "") | |
194 | (unspec:V4SI [(match_operand:V4SI 2 "spu_reg_operand" "") | |
195 | (match_operand:V4SI 1 "spu_reg_operand" "") | |
196 | (match_operand:V4SI 3 "spu_reg_operand" "")] UNSPEC_BGX))] | |
197 | "" | |
198 | "") | |
199 | ||
644459d0 | 200 | (define_insn "spu_mpya" |
201 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
202 | (plus:V4SI | |
203 | (mult:V4SI | |
204 | (sign_extend:V4SI | |
205 | (vec_select:V4HI | |
206 | (match_operand:V8HI 1 "spu_reg_operand" "r") | |
207 | (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))) | |
208 | (sign_extend:V4SI | |
209 | (vec_select:V4HI | |
210 | (match_operand:V8HI 2 "spu_reg_operand" "r") | |
211 | (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))) | |
212 | (match_operand:V4SI 3 "spu_reg_operand" "r")))] | |
213 | "" | |
214 | "mpya\t%0,%1,%2,%3" | |
215 | [(set_attr "type" "fp7")]) | |
216 | ||
217 | (define_insn "spu_mpyh" | |
218 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
219 | (ashift:V4SI | |
220 | (mult:V4SI | |
221 | (sign_extend:V4SI | |
222 | (vec_select:V4HI | |
223 | (match_operand:V8HI 1 "spu_reg_operand" "r") | |
224 | (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))) | |
225 | (sign_extend:V4SI | |
226 | (vec_select:V4HI | |
227 | (match_operand:V8HI 2 "spu_reg_operand" "r") | |
228 | (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))) | |
229 | (const_vector:V4SI [(const_int 16)(const_int 16)(const_int 16)(const_int 16)])))] | |
230 | "" | |
231 | "mpyh\t%0,%1,%2" | |
232 | [(set_attr "type" "fp7")]) | |
233 | ||
234 | (define_insn "spu_mpys" | |
235 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
236 | (ashiftrt:V4SI | |
237 | (mult:V4SI | |
238 | (sign_extend:V4SI | |
239 | (vec_select:V4HI | |
240 | (match_operand:V8HI 1 "spu_reg_operand" "r") | |
241 | (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))) | |
242 | (sign_extend:V4SI | |
243 | (vec_select:V4HI | |
244 | (match_operand:V8HI 2 "spu_reg_operand" "r") | |
245 | (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))) | |
246 | (const_vector:V4SI [(const_int 16)(const_int 16)(const_int 16)(const_int 16)])))] | |
247 | "" | |
248 | "mpys\t%0,%1,%2" | |
249 | [(set_attr "type" "fp7")]) | |
250 | ||
644459d0 | 251 | (define_insn "spu_mpyhhau" |
252 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
253 | (plus:V4SI | |
254 | (mult:V4SI | |
255 | (zero_extend:V4SI | |
256 | (vec_select:V4HI | |
257 | (match_operand:V8HI 1 "spu_reg_operand" "r") | |
258 | (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))) | |
259 | (zero_extend:V4SI | |
260 | (vec_select:V4HI | |
261 | (match_operand:V8HI 2 "spu_reg_operand" "r") | |
262 | (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))) | |
263 | (match_operand:V4SI 3 "spu_reg_operand" "0")))] | |
264 | "" | |
265 | "mpyhhau\t%0,%1,%2" | |
266 | [(set_attr "type" "fp7")]) | |
267 | ||
268 | (define_insn "spu_mpyhha" | |
269 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
270 | (plus:V4SI | |
271 | (mult:V4SI | |
272 | (sign_extend:V4SI | |
273 | (vec_select:V4HI | |
274 | (match_operand:V8HI 1 "spu_reg_operand" "r") | |
275 | (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))) | |
276 | (sign_extend:V4SI | |
277 | (vec_select:V4HI | |
278 | (match_operand:V8HI 2 "spu_reg_operand" "r") | |
279 | (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))) | |
280 | (match_operand:V4SI 3 "spu_reg_operand" "0")))] | |
281 | "" | |
282 | "mpyhha\t%0,%1,%2" | |
283 | [(set_attr "type" "fp7")]) | |
284 | ||
285 | ;; form select mask | |
286 | (define_insn "spu_fsmb" | |
287 | [(set (match_operand:V16QI 0 "spu_reg_operand" "=r,r") | |
288 | (unspec:V16QI [(match_operand:SI 1 "spu_nonmem_operand" "r,MN")] UNSPEC_FSMB))] | |
289 | "" | |
290 | "@ | |
291 | fsmb\t%0,%1 | |
292 | fsmbi\t%0,%1" | |
293 | [(set_attr "type" "shuf")]) | |
294 | ||
295 | (define_insn "spu_fsmh" | |
296 | [(set (match_operand:V8HI 0 "spu_reg_operand" "=r") | |
297 | (unspec:V8HI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_FSMH))] | |
298 | "" | |
299 | "fsmh\t%0,%1" | |
300 | [(set_attr "type" "shuf")]) | |
301 | ||
302 | (define_insn "spu_fsm" | |
303 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
304 | (unspec:V4SI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_FSM))] | |
305 | "" | |
306 | "fsm\t%0,%1" | |
307 | [(set_attr "type" "shuf")]) | |
308 | ||
309 | ||
310 | ;; gather bits | |
311 | (define_insn "spu_gbb" | |
312 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
313 | (unspec:V4SI [(match_operand:V16QI 1 "spu_reg_operand" "r")] UNSPEC_GBB))] | |
314 | "" | |
315 | "gbb\t%0,%1" | |
316 | [(set_attr "type" "shuf")]) | |
317 | ||
318 | (define_insn "spu_gbh" | |
319 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
320 | (unspec:V4SI [(match_operand:V8HI 1 "spu_reg_operand" "r")] UNSPEC_GBH))] | |
321 | "" | |
322 | "gbh\t%0,%1" | |
323 | [(set_attr "type" "shuf")]) | |
324 | ||
325 | (define_insn "spu_gb" | |
326 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
327 | (unspec:V4SI [(match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_GB))] | |
328 | "" | |
329 | "gb\t%0,%1" | |
330 | [(set_attr "type" "shuf")]) | |
331 | ||
332 | ;; misc byte operations | |
333 | (define_insn "spu_avgb" | |
334 | [(set (match_operand:V16QI 0 "spu_reg_operand" "=r") | |
335 | (unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r") | |
336 | (match_operand:V16QI 2 "spu_reg_operand" "r")] UNSPEC_AVGB))] | |
337 | "" | |
338 | "avgb\t%0,%1,%2" | |
339 | [(set_attr "type" "fxb")]) | |
340 | ||
341 | (define_insn "spu_absdb" | |
342 | [(set (match_operand:V16QI 0 "spu_reg_operand" "=r") | |
343 | (unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r") | |
344 | (match_operand:V16QI 2 "spu_reg_operand" "r")] UNSPEC_ABSDB))] | |
345 | "" | |
346 | "absdb\t%0,%1,%2" | |
347 | [(set_attr "type" "fxb")]) | |
348 | ||
349 | (define_insn "spu_sumb" | |
350 | [(set (match_operand:V8HI 0 "spu_reg_operand" "=r") | |
351 | (unspec:V8HI [(match_operand:V16QI 1 "spu_reg_operand" "r") | |
352 | (match_operand:V16QI 2 "spu_reg_operand" "r")] UNSPEC_SUMB))] | |
353 | "" | |
354 | "sumb\t%0,%1,%2" | |
355 | [(set_attr "type" "fxb")]) | |
356 | ||
357 | ;; sign extend | |
358 | (define_insn "spu_xsbh" | |
359 | [(set (match_operand:V8HI 0 "spu_reg_operand" "=r") | |
360 | (sign_extend:V8HI | |
361 | (vec_select:V8QI | |
362 | (match_operand:V16QI 1 "spu_reg_operand" "r") | |
363 | (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7) | |
364 | (const_int 9)(const_int 11)(const_int 13)(const_int 15)]))))] | |
365 | "" | |
366 | "xsbh\t%0,%1") | |
367 | ||
368 | (define_insn "spu_xshw" | |
369 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
370 | (sign_extend:V4SI | |
371 | (vec_select:V4HI | |
372 | (match_operand:V8HI 1 "spu_reg_operand" "r") | |
373 | (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))] | |
374 | "" | |
375 | "xshw\t%0,%1") | |
376 | ||
377 | (define_insn "spu_xswd" | |
378 | [(set (match_operand:V2DI 0 "spu_reg_operand" "=r") | |
379 | (sign_extend:V2DI | |
380 | (vec_select:V2SI | |
381 | (match_operand:V4SI 1 "spu_reg_operand" "r") | |
382 | (parallel [(const_int 1)(const_int 3)]))))] | |
383 | "" | |
384 | "xswd\t%0,%1") | |
385 | ||
386 | ;; or across | |
387 | ||
388 | (define_insn "spu_orx" | |
389 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
390 | (unspec:V4SI [(match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_ORX))] | |
391 | "" | |
392 | "orx\t%0,%1") | |
393 | ||
394 | ||
395 | ;; compare & halt | |
396 | (define_insn "spu_heq" | |
397 | [(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r,r") | |
398 | (match_operand:SI 1 "spu_nonmem_operand" "r,K")] UNSPEC_HEQ)] | |
399 | "" | |
400 | "@ | |
401 | heq\t%0,%1 | |
402 | heqi\t%0,%1") | |
403 | ||
404 | (define_insn "spu_hgt" | |
405 | [(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r,r") | |
406 | (match_operand:SI 1 "spu_nonmem_operand" "r,K")] UNSPEC_HGT)] | |
407 | "" | |
408 | "@ | |
409 | hgt\t%0,%1 | |
410 | hgti\t%0,%1") | |
411 | ||
412 | (define_insn "spu_hlgt" | |
413 | [(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r,r") | |
414 | (match_operand:SI 1 "spu_nonmem_operand" "r,K")] UNSPEC_HLGT)] | |
415 | "" | |
416 | "@ | |
417 | hlgt\t%0,%1 | |
418 | hlgti\t%0,%1") | |
419 | ||
420 | ;; branches | |
421 | ||
422 | ;; The description below hides the fact that bisled conditionally | |
423 | ;; executes the call depending on the value in channel 0. This was | |
424 | ;; done so that the description would conform to the format of a call | |
425 | ;; insn. Otherwise (if this were not part of call insn), the link | |
426 | ;; register, $lr, would not be saved/restored in the prologue/epilogue. | |
427 | ||
428 | (define_insn "spu_bisled" | |
429 | [(parallel | |
430 | [(call (mem:QI (match_operand:SI 0 "spu_reg_operand" "r")) | |
431 | (const_int 0)) | |
432 | (clobber (reg:SI 0)) | |
433 | (clobber (reg:SI 130)) | |
434 | (use (match_operand:SI 1 "address_operand" "")) | |
435 | (use (const_int 0))])] | |
436 | "" | |
437 | "bisled\t$lr,%0" | |
438 | [(set_attr "type" "br")]) | |
439 | ||
440 | (define_insn "spu_bisledd" | |
441 | [(parallel | |
442 | [(call (mem:QI (match_operand:SI 0 "spu_reg_operand" "r")) | |
443 | (const_int 0)) | |
444 | (clobber (reg:SI 0)) | |
445 | (clobber (reg:SI 130)) | |
446 | (use (match_operand:SI 1 "address_operand" "")) | |
447 | (use (const_int 1))])] | |
448 | "" | |
449 | "bisledd\t$lr,%0" | |
450 | [(set_attr "type" "br")]) | |
451 | ||
452 | (define_insn "spu_bislede" | |
453 | [(parallel | |
454 | [(call (mem:QI (match_operand:SI 0 "spu_reg_operand" "r")) | |
455 | (const_int 0)) | |
456 | (clobber (reg:SI 0)) | |
457 | (clobber (reg:SI 130)) | |
458 | (use (match_operand:SI 1 "address_operand" "")) | |
459 | (use (const_int 2))])] | |
460 | "" | |
461 | "bislede\t$lr,%0" | |
462 | [(set_attr "type" "br")]) | |
463 | ||
464 | ;; float convert | |
56c7bfc2 | 465 | (define_expand "spu_csflt" |
466 | [(set (match_operand:V4SF 0 "spu_reg_operand") | |
467 | (unspec:V4SF [(match_operand:V4SI 1 "spu_reg_operand") | |
468 | (match_operand:SI 2 "spu_nonmem_operand")] 0 ))] | |
469 | "" | |
470 | { | |
471 | if (GET_CODE (operands[2]) == CONST_INT | |
472 | && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127)) | |
473 | { | |
474 | error ("spu_convtf expects an integer literal in the range [0, 127]."); | |
475 | operands[2] = force_reg (SImode, operands[2]); | |
476 | } | |
477 | if (GET_CODE (operands[2]) != CONST_INT) | |
478 | { | |
479 | rtx exp2; | |
480 | rtx cnv = gen_reg_rtx (V4SFmode); | |
481 | rtx scale = gen_reg_rtx (SImode); | |
482 | rtx op2 = force_reg (SImode, operands[2]); | |
483 | rtx m1 = spu_gen_exp2 (V4SFmode, GEN_INT (-1)); | |
484 | emit_insn (gen_subsi3 (scale, const1_rtx, op2)); | |
485 | exp2 = spu_gen_exp2 (V4SFmode, scale); | |
486 | emit_insn (gen_floatv4siv4sf2_mul (cnv, operands[1], m1)); | |
487 | emit_insn (gen_mulv4sf3 (operands[0], cnv, exp2)); | |
488 | } | |
489 | else | |
490 | { | |
491 | rtx exp2 = spu_gen_exp2 (V4SFmode, operands[2]); | |
492 | emit_insn (gen_floatv4siv4sf2_div (operands[0], operands[1], exp2)); | |
493 | } | |
494 | DONE; | |
495 | }) | |
496 | ||
497 | (define_expand "spu_cflts" | |
498 | [(set (match_operand:V4SI 0 "spu_reg_operand") | |
499 | (unspec:V4SI [(match_operand:V4SF 1 "spu_reg_operand") | |
500 | (match_operand:SI 2 "spu_nonmem_operand")] 0 ))] | |
501 | "" | |
502 | { | |
503 | rtx exp2; | |
504 | if (GET_CODE (operands[2]) == CONST_INT | |
505 | && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127)) | |
506 | { | |
507 | error ("spu_convts expects an integer literal in the range [0, 127]."); | |
508 | operands[2] = force_reg (SImode, operands[2]); | |
509 | } | |
510 | exp2 = spu_gen_exp2 (V4SFmode, operands[2]); | |
511 | if (GET_CODE (operands[2]) != CONST_INT) | |
512 | { | |
513 | rtx mul = gen_reg_rtx (V4SFmode); | |
514 | emit_insn (gen_mulv4sf3 (mul, operands[1], exp2)); | |
515 | emit_insn (gen_fix_truncv4sfv4si2 (operands[0], mul)); | |
516 | } | |
517 | else | |
518 | emit_insn (gen_fix_truncv4sfv4si2_mul (operands[0], operands[1], exp2)); | |
519 | DONE; | |
520 | }) | |
521 | ||
522 | (define_expand "spu_cuflt" | |
644459d0 | 523 | [(set (match_operand:V4SF 0 "spu_reg_operand" "=r") |
56c7bfc2 | 524 | (unspec:V4SF [(match_operand:V4SI 1 "spu_reg_operand") |
525 | (match_operand:SI 2 "spu_nonmem_operand")] 0 ))] | |
526 | "" | |
527 | { | |
528 | if (GET_CODE (operands[2]) == CONST_INT | |
529 | && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127)) | |
530 | { | |
531 | error ("spu_convtf expects an integer literal in the range [0, 127]."); | |
532 | operands[2] = force_reg (SImode, operands[2]); | |
533 | } | |
534 | if (GET_CODE (operands[2]) != CONST_INT) | |
535 | { | |
536 | rtx exp2; | |
537 | rtx cnv = gen_reg_rtx (V4SFmode); | |
538 | rtx scale = gen_reg_rtx (SImode); | |
539 | rtx op2 = force_reg (SImode, operands[2]); | |
540 | rtx m1 = spu_gen_exp2 (V4SFmode, GEN_INT (-1)); | |
541 | emit_insn (gen_subsi3 (scale, const1_rtx, op2)); | |
542 | exp2 = spu_gen_exp2 (V4SFmode, scale); | |
543 | emit_insn (gen_floatunsv4siv4sf2_mul (cnv, operands[1], m1)); | |
544 | emit_insn (gen_mulv4sf3 (operands[0], cnv, exp2)); | |
545 | } | |
546 | else | |
547 | { | |
548 | rtx exp2 = spu_gen_exp2 (V4SFmode, operands[2]); | |
549 | emit_insn (gen_floatunsv4siv4sf2_div (operands[0], operands[1], exp2)); | |
550 | } | |
551 | DONE; | |
552 | }) | |
553 | ||
554 | (define_expand "spu_cfltu" | |
555 | [(set (match_operand:V4SI 0 "spu_reg_operand") | |
556 | (unspec:V4SI [(match_operand:V4SF 1 "spu_reg_operand") | |
557 | (match_operand:SI 2 "spu_nonmem_operand")] 0 ))] | |
558 | "" | |
559 | { | |
560 | rtx exp2; | |
561 | if (GET_CODE (operands[2]) == CONST_INT | |
562 | && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127)) | |
563 | { | |
564 | error ("spu_convtu expects an integer literal in the range [0, 127]."); | |
565 | operands[2] = force_reg (SImode, operands[2]); | |
566 | } | |
567 | exp2 = spu_gen_exp2 (V4SFmode, operands[2]); | |
568 | if (GET_CODE (operands[2]) != CONST_INT) | |
569 | { | |
570 | rtx mul = gen_reg_rtx (V4SFmode); | |
571 | emit_insn (gen_mulv4sf3 (mul, operands[1], exp2)); | |
572 | emit_insn (gen_fixuns_truncv4sfv4si2 (operands[0], mul)); | |
573 | } | |
574 | else | |
575 | emit_insn (gen_fixuns_truncv4sfv4si2_mul (operands[0], operands[1], exp2)); | |
576 | DONE; | |
577 | }) | |
644459d0 | 578 | |
579 | (define_expand "spu_frds" | |
580 | [(set (match_operand:V4SF 0 "spu_reg_operand" "") | |
581 | (vec_select:V4SF | |
582 | (vec_concat:V4SF | |
583 | (float_truncate:V2SF (match_operand:V2DF 1 "spu_reg_operand" "")) | |
584 | (match_dup:V2SF 2)) | |
585 | (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))] | |
586 | "" | |
587 | "operands[2] = spu_const(V2SFmode, 0);") | |
588 | ||
589 | (define_insn "_frds" | |
590 | [(set (match_operand:V4SF 0 "spu_reg_operand" "=r") | |
591 | (vec_select:V4SF | |
592 | (vec_concat:V4SF | |
593 | (float_truncate:V2SF (match_operand:V2DF 1 "spu_reg_operand" "r")) | |
594 | (match_operand:V2SF 2 "vec_imm_operand" "i")) | |
595 | (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))] | |
596 | "" | |
597 | "frds\t%0,%1" | |
598 | [(set_attr "type" "fpd")]) | |
599 | ||
600 | (define_insn "spu_fesd" | |
601 | [(set (match_operand:V2DF 0 "spu_reg_operand" "=r") | |
602 | (float_extend:V2DF | |
603 | (vec_select:V2SF | |
604 | (match_operand:V4SF 1 "spu_reg_operand" "r") | |
605 | (parallel [(const_int 0)(const_int 2)]))))] | |
606 | "" | |
607 | "fesd\t%0,%1" | |
608 | [(set_attr "type" "fpd")]) | |
609 | ||
610 | ;; control | |
611 | (define_insn "spu_stop" | |
612 | [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "M")] UNSPEC_STOP)] | |
613 | "" | |
614 | "stop\t%0" | |
615 | [(set_attr "type" "br")]) | |
616 | ||
617 | (define_insn "spu_stopd" | |
618 | [(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r") | |
619 | (match_operand:SI 1 "spu_reg_operand" "r") | |
620 | (match_operand:SI 2 "spu_reg_operand" "r")] UNSPEC_STOPD)] | |
621 | "" | |
622 | "stopd\t%0,%1,%2" | |
623 | [(set_attr "type" "br")]) | |
624 | ||
625 | ;; interrupt disable/enable | |
644459d0 | 626 | (define_expand "spu_idisable" |
627 | [(parallel | |
5df189be | 628 | [(unspec_volatile [(const_int 0)] UNSPEC_SET_INTR) |
644459d0 | 629 | (clobber (match_dup:SI 0)) |
630 | (clobber (mem:BLK (scratch)))])] | |
631 | "" | |
632 | "operands[0] = gen_reg_rtx (SImode);") | |
633 | ||
634 | (define_expand "spu_ienable" | |
635 | [(parallel | |
5df189be | 636 | [(unspec_volatile [(const_int 1)] UNSPEC_SET_INTR) |
644459d0 | 637 | (clobber (match_dup:SI 0)) |
638 | (clobber (mem:BLK (scratch)))])] | |
639 | "" | |
640 | "operands[0] = gen_reg_rtx (SImode);") | |
641 | ||
642 | (define_insn "set_intr" | |
5df189be | 643 | [(unspec_volatile [(match_operand 1 "const_int_operand" "i")] UNSPEC_SET_INTR) |
644459d0 | 644 | (clobber (match_operand:SI 0 "spu_reg_operand" "=&r")) |
645 | (clobber (mem:BLK (scratch)))] | |
646 | "! flag_pic" | |
647 | "ila\t%0,.+8\;bi%I1\t%0" | |
648 | [(set_attr "length" "8") | |
649 | (set_attr "type" "multi0")]) | |
650 | ||
651 | (define_insn "set_intr_pic" | |
5df189be | 652 | [(unspec_volatile [(match_operand 1 "const_int_operand" "i")] UNSPEC_SET_INTR) |
644459d0 | 653 | (clobber (match_operand:SI 0 "spu_reg_operand" "=&r")) |
654 | (clobber (mem:BLK (scratch)))] | |
655 | "flag_pic" | |
656 | "brsl\t%0,.+4\;ai\t%0,%0,8\;bi%I1\t%0" | |
657 | [(set_attr "length" "12") | |
658 | (set_attr "type" "multi1")]) | |
659 | ||
644459d0 | 660 | (define_insn "set_intr_cc" |
5df189be | 661 | [(cond_exec (match_operator 1 "branch_comparison_operator" |
662 | [(match_operand 2 "spu_reg_operand" "r") | |
663 | (const_int 0)]) | |
664 | (parallel [(unspec_volatile [(match_operand:SI 3 "const_int_operand" "i")] UNSPEC_SET_INTR) | |
665 | (clobber (match_operand:SI 0 "spu_reg_operand" "=&r")) | |
666 | (clobber (mem:BLK (scratch)))]))] | |
644459d0 | 667 | "! flag_pic" |
668 | "ila\t%0,.+8\;bi%b2%b1z%I3\t%2,%0" | |
669 | [(set_attr "length" "8") | |
670 | (set_attr "type" "multi0")]) | |
671 | ||
672 | (define_insn "set_intr_cc_pic" | |
5df189be | 673 | [(cond_exec (match_operator 1 "branch_comparison_operator" |
674 | [(match_operand 2 "spu_reg_operand" "r") | |
675 | (const_int 0)]) | |
676 | (parallel [(unspec_volatile [(match_operand:SI 3 "const_int_operand" "i")] UNSPEC_SET_INTR) | |
677 | (clobber (match_operand:SI 0 "spu_reg_operand" "=&r")) | |
678 | (clobber (mem:BLK (scratch)))]))] | |
644459d0 | 679 | "flag_pic" |
5df189be | 680 | "brsl\t%0,.+4\;ai\t%0,%0,8\;bi%b2%b1z%I3\t%2,%0" |
644459d0 | 681 | [(set_attr "length" "12") |
682 | (set_attr "type" "multi1")]) | |
683 | ||
684 | (define_insn "set_intr_return" | |
5df189be | 685 | [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")] UNSPEC_SET_INTR) |
644459d0 | 686 | (return)] |
687 | "" | |
688 | "bi%I0\t$lr" | |
689 | [(set_attr "type" "br")]) | |
690 | ||
691 | (define_peephole2 | |
692 | [(parallel | |
5df189be | 693 | [(unspec_volatile [(match_operand:SI 0 "const_int_operand")] UNSPEC_SET_INTR) |
644459d0 | 694 | (clobber (match_operand:SI 1 "spu_reg_operand")) |
695 | (clobber (mem:BLK (scratch)))]) | |
696 | (use (reg:SI 0)) | |
697 | (return)] | |
698 | "" | |
699 | [(use (reg:SI 0)) | |
700 | (parallel | |
5df189be | 701 | [(unspec_volatile [(match_dup:SI 0)] UNSPEC_SET_INTR) |
644459d0 | 702 | (return)])] |
703 | "") | |
704 | ||
705 | ;; special purpose registers | |
706 | (define_insn "spu_fscrrd" | |
707 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
708 | (unspec_volatile:V4SI [(const_int 6)] UNSPEC_FSCRRD))] | |
709 | "" | |
710 | "fscrrd\t%0" | |
711 | [(set_attr "type" "spr")]) | |
712 | ||
713 | (define_insn "spu_fscrwr" | |
714 | [(unspec_volatile [(match_operand:V4SI 0 "spu_reg_operand" "r")] UNSPEC_FSCRWR)] | |
715 | "" | |
716 | "fscrwr\t$0,%0" | |
717 | [(set_attr "type" "spr")]) | |
718 | ||
719 | (define_insn "spu_mfspr" | |
720 | [(set (match_operand:SI 0 "spu_reg_operand" "=r") | |
721 | (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_MFSPR))] | |
722 | "" | |
723 | "mfspr\t%0,$sp%1" | |
724 | [(set_attr "type" "spr")]) | |
725 | ||
726 | (define_insn "spu_mtspr" | |
727 | [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "J") | |
728 | (match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_MTSPR)] | |
729 | "" | |
730 | "mtspr\t$sp%0,%1" | |
731 | [(set_attr "type" "spr")]) | |
732 | ||
733 | ;; channels | |
734 | (define_expand "spu_rdch" | |
735 | [(set (match_operand:V4SI 0 "spu_reg_operand" "") | |
736 | (unspec_volatile:V4SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_RDCH))] | |
737 | "" | |
738 | "{ | |
739 | if (spu_safe_dma (INTVAL (operands[1]))) | |
740 | { | |
741 | emit_insn (gen_spu_rdch_clobber (operands[0], operands[1])); | |
742 | DONE; | |
743 | } | |
744 | }") | |
745 | ||
746 | (define_expand "spu_rchcnt" | |
747 | [(set (match_operand:SI 0 "spu_reg_operand" "") | |
748 | (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_RCHCNT))] | |
749 | "" | |
750 | "{ | |
751 | if (spu_safe_dma (INTVAL (operands[1]))) | |
752 | { | |
753 | emit_insn (gen_spu_rchcnt_clobber (operands[0], operands[1])); | |
754 | DONE; | |
755 | } | |
756 | }") | |
757 | ||
758 | (define_expand "spu_wrch" | |
759 | [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "") | |
760 | (match_operand:V4SI 1 "spu_reg_operand" "")] UNSPEC_WRCH)] | |
761 | "" | |
762 | "{ | |
763 | if (spu_safe_dma (INTVAL (operands[0]))) | |
764 | { | |
765 | emit_insn (gen_spu_wrch_clobber (operands[0], operands[1])); | |
766 | DONE; | |
767 | } | |
768 | }") | |
769 | ||
770 | (define_insn "spu_rdch_noclobber" | |
771 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
772 | (unspec_volatile:V4SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RDCH))] | |
773 | "" | |
774 | "rdch\t%0,$ch%1" | |
775 | [(set_attr "type" "spr")]) | |
776 | ||
777 | (define_insn "spu_rchcnt_noclobber" | |
778 | [(set (match_operand:SI 0 "spu_reg_operand" "=r") | |
779 | (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RCHCNT))] | |
780 | "" | |
781 | "rchcnt\t%0,$ch%1" | |
782 | [(set_attr "type" "spr")]) | |
783 | ||
784 | (define_insn "spu_wrch_noclobber" | |
785 | [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "J") | |
786 | (match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_WRCH)] | |
787 | "" | |
788 | "wrch\t$ch%0,%1" | |
789 | [(set_attr "type" "spr")]) | |
790 | ||
791 | (define_insn "spu_rdch_clobber" | |
792 | [(set (match_operand:V4SI 0 "spu_reg_operand" "=r") | |
793 | (unspec_volatile:V4SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RDCH)) | |
794 | (clobber (mem:BLK (scratch)))] | |
795 | "" | |
796 | "rdch\t%0,$ch%1" | |
797 | [(set_attr "type" "spr")]) | |
798 | ||
799 | (define_insn "spu_rchcnt_clobber" | |
800 | [(set (match_operand:SI 0 "spu_reg_operand" "=r") | |
801 | (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RCHCNT)) | |
802 | (clobber (mem:BLK (scratch)))] | |
803 | "" | |
804 | "rchcnt\t%0,$ch%1" | |
805 | [(set_attr "type" "spr")]) | |
806 | ||
807 | (define_insn "spu_wrch_clobber" | |
808 | [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "J") | |
809 | (match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_WRCH) | |
810 | (clobber (mem:BLK (scratch)))] | |
811 | "" | |
812 | "wrch\t$ch%0,%1" | |
813 | [(set_attr "type" "spr")]) | |
814 | ||
815 | (define_expand "spu_splats" | |
816 | [(set (match_operand 0 "spu_reg_operand" "") | |
817 | (vec_duplicate (match_operand 1 "spu_nonmem_operand" "")))] | |
818 | "" | |
819 | { | |
820 | spu_builtin_splats(operands); | |
821 | DONE; | |
822 | }) | |
823 | ||
824 | (define_expand "spu_extract" | |
825 | [(set (match_operand 0 "spu_reg_operand" "") | |
826 | (unspec [(match_operand 1 "spu_reg_operand" "") | |
827 | (match_operand 2 "spu_nonmem_operand" "")] 0))] | |
828 | "" | |
829 | { | |
830 | spu_builtin_extract (operands); | |
831 | DONE; | |
832 | }) | |
833 | ||
834 | (define_expand "spu_insert" | |
835 | [(set (match_operand 0 "spu_reg_operand" "") | |
836 | (unspec [(match_operand 1 "spu_reg_operand" "") | |
837 | (match_operand 2 "spu_reg_operand" "") | |
838 | (match_operand:SI 3 "spu_nonmem_operand" "")] 0))] | |
839 | "" | |
840 | { | |
841 | spu_builtin_insert(operands); | |
842 | DONE; | |
843 | }) | |
844 | ||
845 | (define_expand "spu_promote" | |
846 | [(set (match_operand 0 "spu_reg_operand" "") | |
847 | (unspec [(match_operand 1 "spu_reg_operand" "") | |
848 | (match_operand:SI 2 "immediate_operand" "")] 0))] | |
849 | "" | |
850 | { | |
851 | spu_builtin_promote(operands); | |
852 | DONE; | |
853 | }) | |
854 | ||
855 | ;; Currently doing nothing with this but expanding its args. | |
856 | (define_expand "spu_align_hint" | |
857 | [(unspec [(match_operand:SI 0 "address_operand" "") | |
858 | (match_operand:SI 1 "immediate_operand" "") | |
859 | (match_operand:SI 2 "immediate_operand" "")] 0)] | |
860 | "" | |
861 | { | |
862 | DONE; | |
863 | }) | |
864 |