xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/spu/spu-builtins.md (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
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
5;; Software Foundation; either version 3 of the License, or (at your option)
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
14;; along with GCC; see the file COPYING3.  If not see
15;; <http://www.gnu.org/licenses/>.
16
17
18;; This includes expands for all the intrinsics.
19;; spu_expand_builtin looks at the mode of match_operand.
20
21
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
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
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
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
200;; integer multiply
201(define_insn "spu_mpy"
202  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r,r")
203        (mult:V4SI
204	  (sign_extend:V4SI
205	    (vec_select:V4HI
206	      (match_operand:V8HI 1 "spu_reg_operand" "r,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_arith_operand" "r,B")
211	      (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))))]
212  ""
213  "@
214   mpy\t%0,%1,%2
215   mpyi\t%0,%1,%2"
216  [(set_attr "type" "fp7")])
217
218(define_insn "spu_mpyu"
219  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r,r")
220        (mult:V4SI
221	  (zero_extend:V4SI
222	    (vec_select:V4HI
223	      (match_operand:V8HI 1 "spu_reg_operand" "r,r")
224	      (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))
225          (zero_extend:V4SI
226	    (vec_select:V4HI
227	      (match_operand:V8HI 2 "spu_arith_operand" "r,B")
228	      (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))))]
229  ""
230  "@
231   mpyu\t%0,%1,%2
232   mpyui\t%0,%1,%2"
233  [(set_attr "type" "fp7")])
234
235(define_insn "spu_mpya"
236  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
237        (plus:V4SI
238	  (mult:V4SI
239	    (sign_extend:V4SI
240	      (vec_select:V4HI
241		(match_operand:V8HI 1 "spu_reg_operand" "r")
242		(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))
243	    (sign_extend:V4SI
244	      (vec_select:V4HI
245		(match_operand:V8HI 2 "spu_reg_operand" "r")
246		(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))
247	(match_operand:V4SI 3 "spu_reg_operand" "r")))]
248  ""
249  "mpya\t%0,%1,%2,%3"
250  [(set_attr "type" "fp7")])
251
252(define_insn "spu_mpyh"
253  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
254        (ashift:V4SI
255	  (mult:V4SI
256	    (sign_extend:V4SI
257	      (vec_select:V4HI
258		(match_operand:V8HI 1 "spu_reg_operand" "r")
259		(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
260	    (sign_extend:V4SI
261	      (vec_select:V4HI
262		(match_operand:V8HI 2 "spu_reg_operand" "r")
263		(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))
264	  (const_vector:V4SI [(const_int 16)(const_int 16)(const_int 16)(const_int 16)])))]
265  ""
266  "mpyh\t%0,%1,%2"
267  [(set_attr "type" "fp7")])
268
269(define_insn "spu_mpys"
270  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
271        (ashiftrt:V4SI
272	  (mult:V4SI
273	    (sign_extend:V4SI
274	      (vec_select:V4HI
275		(match_operand:V8HI 1 "spu_reg_operand" "r")
276		(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))
277	    (sign_extend:V4SI
278	      (vec_select:V4HI
279		(match_operand:V8HI 2 "spu_reg_operand" "r")
280		(parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))
281	  (const_vector:V4SI [(const_int 16)(const_int 16)(const_int 16)(const_int 16)])))]
282  ""
283  "mpys\t%0,%1,%2"
284  [(set_attr "type" "fp7")])
285
286(define_insn "spu_mpyhhu"
287  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
288	(mult:V4SI
289	  (zero_extend:V4SI
290	    (vec_select:V4HI
291	      (match_operand:V8HI 1 "spu_reg_operand" "r")
292	      (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
293	  (zero_extend:V4SI
294	    (vec_select:V4HI
295	      (match_operand:V8HI 2 "spu_reg_operand" "r")
296	      (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))))]
297  ""
298  "mpyhhu\t%0,%1,%2"
299  [(set_attr "type" "fp7")])
300
301(define_insn "spu_mpyhh"
302  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
303	(mult:V4SI
304	  (sign_extend:V4SI
305	    (vec_select:V4HI
306	      (match_operand:V8HI 1 "spu_reg_operand" "r")
307	      (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
308	  (sign_extend:V4SI
309	    (vec_select:V4HI
310	      (match_operand:V8HI 2 "spu_reg_operand" "r")
311	      (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))))]
312  ""
313  "mpyhh\t%0,%1,%2"
314  [(set_attr "type" "fp7")])
315
316(define_insn "spu_mpyhhau"
317  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
318        (plus:V4SI
319	  (mult:V4SI
320	    (zero_extend:V4SI
321	      (vec_select:V4HI
322		(match_operand:V8HI 1 "spu_reg_operand" "r")
323		(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
324	    (zero_extend:V4SI
325	      (vec_select:V4HI
326		(match_operand:V8HI 2 "spu_reg_operand" "r")
327		(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))))
328	  (match_operand:V4SI 3 "spu_reg_operand" "0")))]
329  ""
330  "mpyhhau\t%0,%1,%2"
331  [(set_attr "type" "fp7")])
332
333(define_insn "spu_mpyhha"
334  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
335        (plus:V4SI
336	  (mult:V4SI
337	    (sign_extend:V4SI
338	      (vec_select:V4HI
339		(match_operand:V8HI 1 "spu_reg_operand" "r")
340		(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
341	    (sign_extend:V4SI
342	      (vec_select:V4HI
343		(match_operand:V8HI 2 "spu_reg_operand" "r")
344		(parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))))
345	  (match_operand:V4SI 3 "spu_reg_operand" "0")))]
346  ""
347  "mpyhha\t%0,%1,%2"
348  [(set_attr "type" "fp7")])
349
350;; form select mask
351(define_insn "spu_fsmb"
352  [(set (match_operand:V16QI 0 "spu_reg_operand" "=r,r")
353        (unspec:V16QI [(match_operand:SI 1 "spu_nonmem_operand" "r,MN")] UNSPEC_FSMB))]
354  ""
355  "@
356  fsmb\t%0,%1
357  fsmbi\t%0,%1"
358  [(set_attr "type" "shuf")])
359
360(define_insn "spu_fsmh"
361  [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
362        (unspec:V8HI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_FSMH))]
363  ""
364  "fsmh\t%0,%1"
365  [(set_attr "type" "shuf")])
366
367(define_insn "spu_fsm"
368  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
369        (unspec:V4SI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_FSM))]
370  ""
371  "fsm\t%0,%1"
372  [(set_attr "type" "shuf")])
373
374
375;; gather bits
376(define_insn "spu_gbb"
377  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
378        (unspec:V4SI [(match_operand:V16QI 1 "spu_reg_operand" "r")] UNSPEC_GBB))]
379  ""
380  "gbb\t%0,%1"
381  [(set_attr "type" "shuf")])
382
383(define_insn "spu_gbh"
384  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
385        (unspec:V4SI [(match_operand:V8HI 1 "spu_reg_operand" "r")] UNSPEC_GBH))]
386  ""
387  "gbh\t%0,%1"
388  [(set_attr "type" "shuf")])
389
390(define_insn "spu_gb"
391  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
392        (unspec:V4SI [(match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_GB))]
393  ""
394  "gb\t%0,%1"
395  [(set_attr "type" "shuf")])
396
397;; misc byte operations
398(define_insn "spu_avgb"
399  [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
400        (unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r")
401		       (match_operand:V16QI 2 "spu_reg_operand" "r")] UNSPEC_AVGB))]
402  ""
403  "avgb\t%0,%1,%2"
404  [(set_attr "type" "fxb")])
405
406(define_insn "spu_absdb"
407  [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
408        (unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r")
409		       (match_operand:V16QI 2 "spu_reg_operand" "r")] UNSPEC_ABSDB))]
410  ""
411  "absdb\t%0,%1,%2"
412  [(set_attr "type" "fxb")])
413
414(define_insn "spu_sumb"
415  [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
416        (unspec:V8HI [(match_operand:V16QI 1 "spu_reg_operand" "r")
417		      (match_operand:V16QI 2 "spu_reg_operand" "r")] UNSPEC_SUMB))]
418  ""
419  "sumb\t%0,%1,%2"
420  [(set_attr "type" "fxb")])
421
422;; sign extend
423(define_insn "spu_xsbh"
424  [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
425        (sign_extend:V8HI
426	  (vec_select:V8QI
427	    (match_operand:V16QI 1 "spu_reg_operand" "r")
428	    (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)
429	               (const_int 9)(const_int 11)(const_int 13)(const_int 15)]))))]
430  ""
431  "xsbh\t%0,%1")
432
433(define_insn "spu_xshw"
434  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
435        (sign_extend:V4SI
436	  (vec_select:V4HI
437	    (match_operand:V8HI 1 "spu_reg_operand" "r")
438	    (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))]
439  ""
440  "xshw\t%0,%1")
441
442(define_insn "spu_xswd"
443  [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
444        (sign_extend:V2DI
445	  (vec_select:V2SI
446	    (match_operand:V4SI 1 "spu_reg_operand" "r")
447	    (parallel [(const_int 1)(const_int 3)]))))]
448  ""
449  "xswd\t%0,%1")
450
451;; or across
452
453(define_insn "spu_orx"
454  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
455	(unspec:V4SI [(match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_ORX))]
456  ""
457  "orx\t%0,%1")
458
459
460;; compare & halt
461(define_insn "spu_heq"
462  [(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r,r")
463	             (match_operand:SI 1 "spu_nonmem_operand" "r,K")] UNSPEC_HEQ)]
464  ""
465  "@
466  heq\t%0,%1
467  heqi\t%0,%1")
468
469(define_insn "spu_hgt"
470  [(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r,r")
471	             (match_operand:SI 1 "spu_nonmem_operand" "r,K")] UNSPEC_HGT)]
472  ""
473  "@
474  hgt\t%0,%1
475  hgti\t%0,%1")
476
477(define_insn "spu_hlgt"
478  [(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r,r")
479	             (match_operand:SI 1 "spu_nonmem_operand" "r,K")] UNSPEC_HLGT)]
480  ""
481  "@
482  hlgt\t%0,%1
483  hlgti\t%0,%1")
484
485;; branches
486
487;; The description below hides the fact that bisled conditionally
488;; executes the call depending on the value in channel 0.  This was
489;; done so that the description would conform to the format of a call
490;; insn.  Otherwise (if this were not part of call insn), the link
491;; register, $lr, would not be saved/restored in the prologue/epilogue.
492
493(define_insn "spu_bisled"
494  [(parallel
495    [(call (mem:QI (match_operand:SI 0 "spu_reg_operand" "r"))
496            (const_int 0))
497     (clobber (reg:SI 0))
498     (clobber (reg:SI 130))
499     (use (match_operand:SI 1 "address_operand" ""))
500     (use (const_int 0))])]
501  ""
502  "bisled\t$lr,%0"
503  [(set_attr "type" "br")])
504
505(define_insn "spu_bisledd"
506  [(parallel
507    [(call (mem:QI (match_operand:SI 0 "spu_reg_operand" "r"))
508            (const_int 0))
509     (clobber (reg:SI 0))
510     (clobber (reg:SI 130))
511     (use (match_operand:SI 1 "address_operand" ""))
512     (use (const_int 1))])]
513  ""
514  "bisledd\t$lr,%0"
515  [(set_attr "type" "br")])
516
517(define_insn "spu_bislede"
518  [(parallel
519    [(call (mem:QI (match_operand:SI 0 "spu_reg_operand" "r"))
520            (const_int 0))
521     (clobber (reg:SI 0))
522     (clobber (reg:SI 130))
523     (use (match_operand:SI 1 "address_operand" ""))
524     (use (const_int 2))])]
525  ""
526  "bislede\t$lr,%0"
527  [(set_attr "type" "br")])
528
529;; float convert
530(define_expand "spu_csflt"
531  [(set (match_operand:V4SF 0 "spu_reg_operand")
532	(unspec:V4SF [(match_operand:V4SI 1 "spu_reg_operand")
533		      (match_operand:SI 2 "spu_nonmem_operand")] 0 ))]
534  ""
535{
536  if (GET_CODE (operands[2]) == CONST_INT
537      && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127))
538    {
539      error ("spu_convtf expects an integer literal in the range [0, 127].");
540      operands[2] = force_reg (SImode, operands[2]);
541    }
542  if (GET_CODE (operands[2]) != CONST_INT)
543    {
544      rtx exp2;
545      rtx cnv = gen_reg_rtx (V4SFmode);
546      rtx scale = gen_reg_rtx (SImode);
547      rtx op2 = force_reg (SImode, operands[2]);
548      rtx m1 = spu_gen_exp2 (V4SFmode, GEN_INT (-1));
549      emit_insn (gen_subsi3 (scale, const1_rtx, op2));
550      exp2 = spu_gen_exp2 (V4SFmode, scale);
551      emit_insn (gen_floatv4siv4sf2_mul (cnv, operands[1], m1));
552      emit_insn (gen_mulv4sf3 (operands[0], cnv, exp2));
553    }
554  else
555    {
556      rtx exp2 = spu_gen_exp2 (V4SFmode, operands[2]);
557      emit_insn (gen_floatv4siv4sf2_div (operands[0], operands[1], exp2));
558    }
559  DONE;
560})
561
562(define_expand "spu_cflts"
563  [(set (match_operand:V4SI 0 "spu_reg_operand")
564	(unspec:V4SI [(match_operand:V4SF 1 "spu_reg_operand")
565                      (match_operand:SI 2 "spu_nonmem_operand")] 0 ))]
566  ""
567{
568  rtx exp2;
569  if (GET_CODE (operands[2]) == CONST_INT
570      && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127))
571    {
572      error ("spu_convts expects an integer literal in the range [0, 127].");
573      operands[2] = force_reg (SImode, operands[2]);
574    }
575  exp2 = spu_gen_exp2 (V4SFmode, operands[2]);
576  if (GET_CODE (operands[2]) != CONST_INT)
577    {
578      rtx mul = gen_reg_rtx (V4SFmode);
579      emit_insn (gen_mulv4sf3 (mul, operands[1], exp2));
580      emit_insn (gen_fix_truncv4sfv4si2 (operands[0], mul));
581    }
582  else
583    emit_insn (gen_fix_truncv4sfv4si2_mul (operands[0], operands[1], exp2));
584  DONE;
585})
586
587(define_expand "spu_cuflt"
588  [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
589	(unspec:V4SF [(match_operand:V4SI 1 "spu_reg_operand")
590		      (match_operand:SI 2 "spu_nonmem_operand")] 0 ))]
591  ""
592{
593  if (GET_CODE (operands[2]) == CONST_INT
594      && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127))
595    {
596      error ("spu_convtf expects an integer literal in the range [0, 127].");
597      operands[2] = force_reg (SImode, operands[2]);
598    }
599  if (GET_CODE (operands[2]) != CONST_INT)
600    {
601      rtx exp2;
602      rtx cnv = gen_reg_rtx (V4SFmode);
603      rtx scale = gen_reg_rtx (SImode);
604      rtx op2 = force_reg (SImode, operands[2]);
605      rtx m1 = spu_gen_exp2 (V4SFmode, GEN_INT (-1));
606      emit_insn (gen_subsi3 (scale, const1_rtx, op2));
607      exp2 = spu_gen_exp2 (V4SFmode, scale);
608      emit_insn (gen_floatunsv4siv4sf2_mul (cnv, operands[1], m1));
609      emit_insn (gen_mulv4sf3 (operands[0], cnv, exp2));
610    }
611  else
612    {
613      rtx exp2 = spu_gen_exp2 (V4SFmode, operands[2]);
614      emit_insn (gen_floatunsv4siv4sf2_div (operands[0], operands[1], exp2));
615    }
616  DONE;
617})
618
619(define_expand "spu_cfltu"
620  [(set (match_operand:V4SI 0 "spu_reg_operand")
621	(unspec:V4SI [(match_operand:V4SF 1 "spu_reg_operand")
622		      (match_operand:SI 2 "spu_nonmem_operand")] 0 ))]
623  ""
624{
625  rtx exp2;
626  if (GET_CODE (operands[2]) == CONST_INT
627      && (INTVAL (operands[2]) < 0 || INTVAL (operands[2]) > 127))
628    {
629      error ("spu_convtu expects an integer literal in the range [0, 127].");
630      operands[2] = force_reg (SImode, operands[2]);
631    }
632  exp2 = spu_gen_exp2 (V4SFmode, operands[2]);
633  if (GET_CODE (operands[2]) != CONST_INT)
634    {
635      rtx mul = gen_reg_rtx (V4SFmode);
636      emit_insn (gen_mulv4sf3 (mul, operands[1], exp2));
637      emit_insn (gen_fixuns_truncv4sfv4si2 (operands[0], mul));
638    }
639  else
640    emit_insn (gen_fixuns_truncv4sfv4si2_mul (operands[0], operands[1], exp2));
641  DONE;
642})
643
644(define_expand "spu_frds"
645   [(set (match_operand:V4SF 0 "spu_reg_operand" "")
646         (vec_select:V4SF
647	   (vec_concat:V4SF
648	     (float_truncate:V2SF (match_operand:V2DF 1 "spu_reg_operand" ""))
649	     (match_dup:V2SF 2))
650	   (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
651  ""
652  "operands[2] = spu_const(V2SFmode, 0);")
653
654(define_insn "_frds"
655   [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
656        (vec_select:V4SF
657	  (vec_concat:V4SF
658	    (float_truncate:V2SF (match_operand:V2DF 1 "spu_reg_operand" "r"))
659	    (match_operand:V2SF 2 "vec_imm_operand" "i"))
660	  (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
661  ""
662  "frds\t%0,%1"
663  [(set_attr "type" "fpd")])
664
665(define_insn "spu_fesd"
666  [(set (match_operand:V2DF 0 "spu_reg_operand" "=r")
667        (float_extend:V2DF
668	  (vec_select:V2SF
669	    (match_operand:V4SF 1 "spu_reg_operand" "r")
670	      (parallel [(const_int 0)(const_int 2)]))))]
671  ""
672  "fesd\t%0,%1"
673  [(set_attr "type" "fpd")])
674
675;; control
676(define_insn "spu_stop"
677  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "M")] UNSPEC_STOP)]
678  ""
679  "stop\t%0"
680  [(set_attr "type" "br")])
681
682(define_insn "spu_stopd"
683  [(unspec_volatile [(match_operand:SI 0 "spu_reg_operand" "r")
684		     (match_operand:SI 1 "spu_reg_operand" "r")
685		     (match_operand:SI 2 "spu_reg_operand" "r")] UNSPEC_STOPD)]
686  ""
687  "stopd\t%0,%1,%2"
688  [(set_attr "type" "br")])
689
690;; interrupt disable/enable
691(define_expand "spu_idisable"
692  [(parallel
693    [(unspec_volatile [(const_int 0)] UNSPEC_SET_INTR)
694     (clobber (match_dup:SI 0))
695     (clobber (mem:BLK (scratch)))])]
696  ""
697  "operands[0] = gen_reg_rtx (SImode);")
698
699(define_expand "spu_ienable"
700  [(parallel
701    [(unspec_volatile [(const_int 1)] UNSPEC_SET_INTR)
702     (clobber (match_dup:SI 0))
703     (clobber (mem:BLK (scratch)))])]
704  ""
705  "operands[0] = gen_reg_rtx (SImode);")
706
707(define_insn "set_intr"
708  [(unspec_volatile [(match_operand 1 "const_int_operand" "i")] UNSPEC_SET_INTR)
709   (clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
710   (clobber (mem:BLK (scratch)))]
711  "! flag_pic"
712  "ila\t%0,.+8\;bi%I1\t%0"
713  [(set_attr "length" "8")
714   (set_attr "type" "multi0")])
715
716(define_insn "set_intr_pic"
717  [(unspec_volatile [(match_operand 1 "const_int_operand" "i")] UNSPEC_SET_INTR)
718   (clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
719   (clobber (mem:BLK (scratch)))]
720  "flag_pic"
721  "brsl\t%0,.+4\;ai\t%0,%0,8\;bi%I1\t%0"
722  [(set_attr "length" "12")
723   (set_attr "type" "multi1")])
724
725(define_insn "set_intr_cc"
726  [(cond_exec (match_operator 1 "branch_comparison_operator"
727		[(match_operand 2 "spu_reg_operand" "r")
728		 (const_int 0)])
729              (parallel [(unspec_volatile [(match_operand:SI 3 "const_int_operand" "i")] UNSPEC_SET_INTR)
730                         (clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
731			 (clobber (mem:BLK (scratch)))]))]
732  "! flag_pic"
733  "ila\t%0,.+8\;bi%b2%b1z%I3\t%2,%0"
734  [(set_attr "length" "8")
735   (set_attr "type" "multi0")])
736
737(define_insn "set_intr_cc_pic"
738  [(cond_exec (match_operator 1 "branch_comparison_operator"
739		[(match_operand 2 "spu_reg_operand" "r")
740		 (const_int 0)])
741              (parallel [(unspec_volatile [(match_operand:SI 3 "const_int_operand" "i")] UNSPEC_SET_INTR)
742                         (clobber (match_operand:SI 0 "spu_reg_operand" "=&r"))
743			 (clobber (mem:BLK (scratch)))]))]
744  "flag_pic"
745  "brsl\t%0,.+4\;ai\t%0,%0,8\;bi%b2%b1z%I3\t%2,%0"
746  [(set_attr "length" "12")
747   (set_attr "type" "multi1")])
748
749(define_insn "set_intr_return"
750  [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")] UNSPEC_SET_INTR)
751   (return)]
752  ""
753  "bi%I0\t$lr"
754  [(set_attr "type" "br")])
755
756(define_peephole2
757  [(parallel
758    [(unspec_volatile [(match_operand:SI 0 "const_int_operand")] UNSPEC_SET_INTR)
759     (clobber (match_operand:SI 1 "spu_reg_operand"))
760     (clobber (mem:BLK (scratch)))])
761   (use (reg:SI 0))
762   (return)]
763  ""
764  [(use (reg:SI 0))
765   (parallel
766    [(unspec_volatile [(match_dup:SI 0)] UNSPEC_SET_INTR)
767     (return)])]
768  "")
769
770;; special purpose registers
771(define_insn "spu_fscrrd"
772  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
773        (unspec_volatile:V4SI [(const_int 6)] UNSPEC_FSCRRD))]
774  ""
775  "fscrrd\t%0"
776  [(set_attr "type" "spr")])
777
778(define_insn "spu_fscrwr"
779  [(unspec_volatile [(match_operand:V4SI 0 "spu_reg_operand" "r")] UNSPEC_FSCRWR)]
780  ""
781  "fscrwr\t$0,%0"
782  [(set_attr "type" "spr")])
783
784(define_insn "spu_mfspr"
785  [(set (match_operand:SI 0 "spu_reg_operand" "=r")
786        (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_MFSPR))]
787  ""
788  "mfspr\t%0,$sp%1"
789  [(set_attr "type" "spr")])
790
791(define_insn "spu_mtspr"
792  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "J")
793	             (match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_MTSPR)]
794  ""
795  "mtspr\t$sp%0,%1"
796  [(set_attr "type" "spr")])
797
798;; channels
799(define_expand "spu_rdch"
800  [(set (match_operand:V4SI 0 "spu_reg_operand" "")
801        (unspec_volatile:V4SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_RDCH))]
802  ""
803  "{
804    if (spu_safe_dma (INTVAL (operands[1])))
805      {
806        emit_insn (gen_spu_rdch_clobber (operands[0], operands[1]));
807        DONE;
808      }
809   }")
810
811(define_expand "spu_rchcnt"
812  [(set (match_operand:SI 0 "spu_reg_operand" "")
813        (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_RCHCNT))]
814  ""
815  "{
816    if (spu_safe_dma (INTVAL (operands[1])))
817      {
818        emit_insn (gen_spu_rchcnt_clobber (operands[0], operands[1]));
819        DONE;
820      }
821   }")
822
823(define_expand "spu_wrch"
824   [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "")
825 	              (match_operand:V4SI 1 "spu_reg_operand" "")] UNSPEC_WRCH)]
826   ""
827  "{
828    if (spu_safe_dma (INTVAL (operands[0])))
829      {
830        emit_insn (gen_spu_wrch_clobber (operands[0], operands[1]));
831        DONE;
832      }
833   }")
834
835(define_insn "spu_rdch_noclobber"
836  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
837        (unspec_volatile:V4SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RDCH))]
838  ""
839  "rdch\t%0,$ch%1"
840  [(set_attr "type" "spr")])
841
842(define_insn "spu_rchcnt_noclobber"
843  [(set (match_operand:SI 0 "spu_reg_operand" "=r")
844        (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RCHCNT))]
845  ""
846  "rchcnt\t%0,$ch%1"
847  [(set_attr "type" "spr")])
848
849(define_insn "spu_wrch_noclobber"
850   [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "J")
851 	              (match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_WRCH)]
852   ""
853   "wrch\t$ch%0,%1"
854   [(set_attr "type" "spr")])
855
856(define_insn "spu_rdch_clobber"
857  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
858        (unspec_volatile:V4SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RDCH))
859    (clobber (mem:BLK (scratch)))]
860  ""
861  "rdch\t%0,$ch%1"
862  [(set_attr "type" "spr")])
863
864(define_insn "spu_rchcnt_clobber"
865  [(set (match_operand:SI 0 "spu_reg_operand" "=r")
866        (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "J")] UNSPEC_RCHCNT))
867    (clobber (mem:BLK (scratch)))]
868  ""
869  "rchcnt\t%0,$ch%1"
870  [(set_attr "type" "spr")])
871
872(define_insn "spu_wrch_clobber"
873   [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "J")
874 	              (match_operand:V4SI 1 "spu_reg_operand" "r")] UNSPEC_WRCH)
875    (clobber (mem:BLK (scratch)))]
876   ""
877   "wrch\t$ch%0,%1"
878   [(set_attr "type" "spr")])
879
880(define_expand "spu_splats"
881  [(set (match_operand 0 "spu_reg_operand" "")
882        (vec_duplicate (match_operand 1 "spu_nonmem_operand" "")))]
883  ""
884  {
885    spu_builtin_splats(operands);
886    DONE;
887  })
888
889(define_expand "spu_extract"
890  [(set (match_operand 0 "spu_reg_operand" "")
891	(unspec [(match_operand 1 "spu_reg_operand" "")
892		 (match_operand 2 "spu_nonmem_operand" "")] 0))]
893  ""
894  {
895    spu_builtin_extract (operands);
896    DONE;
897  })
898
899(define_expand "spu_insert"
900  [(set (match_operand 0 "spu_reg_operand" "")
901        (unspec [(match_operand 1 "spu_reg_operand" "")
902                 (match_operand 2 "spu_reg_operand" "")
903                 (match_operand:SI 3 "spu_nonmem_operand" "")] 0))]
904  ""
905  {
906    spu_builtin_insert(operands);
907    DONE;
908  })
909
910(define_expand "spu_promote"
911  [(set (match_operand 0 "spu_reg_operand" "")
912        (unspec [(match_operand 1 "spu_reg_operand" "")
913                 (match_operand:SI 2 "immediate_operand" "")] 0))]
914  ""
915  {
916    spu_builtin_promote(operands);
917    DONE;
918  })
919
920;; Currently doing nothing with this but expanding its args.
921(define_expand "spu_align_hint"
922  [(unspec [(match_operand:SI 0 "address_operand" "")
923            (match_operand:SI 1 "immediate_operand" "")
924            (match_operand:SI 2 "immediate_operand" "")] 0)]
925  ""
926  {
927     DONE;
928  })
929
930