1;; Copyright (C) 2006-2019 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(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
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
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"
523  [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
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})
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
626(define_expand "spu_idisable"
627  [(parallel
628    [(unspec_volatile [(const_int 0)] UNSPEC_SET_INTR)
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
636    [(unspec_volatile [(const_int 1)] UNSPEC_SET_INTR)
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"
643  [(unspec_volatile [(match_operand 1 "const_int_operand" "i")] UNSPEC_SET_INTR)
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"
652  [(unspec_volatile [(match_operand 1 "const_int_operand" "i")] UNSPEC_SET_INTR)
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
660(define_insn "set_intr_cc"
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)))]))]
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"
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)))]))]
679  "flag_pic"
680  "brsl\t%0,.+4\;ai\t%0,%0,8\;bi%b2%b1z%I3\t%2,%0"
681  [(set_attr "length" "12")
682   (set_attr "type" "multi1")])
683
684(define_insn "set_intr_return"
685  [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")] UNSPEC_SET_INTR)
686   (return)]
687  ""
688  "bi%I0\t$lr"
689  [(set_attr "type" "br")])
690
691(define_peephole2
692  [(parallel
693    [(unspec_volatile [(match_operand:SI 0 "const_int_operand")] UNSPEC_SET_INTR)
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
701    [(unspec_volatile [(match_dup:SI 0)] UNSPEC_SET_INTR)
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
865