OSDN Git Service

9cb0dc7f40091c2ff4dcf360c70ea6d660ede34f
[pf3gnuchains/gcc-fork.git] / gcc / config / spu / spu.md
1 ;; Copyright (C) 2006 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 2 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 this file; see the file COPYING.  If not, write to the Free
15 ;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
16 ;; 02110-1301, USA.
17
18 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
19
20 \f
21 ;; Define an insn type attribute.  This is used in function unit delay
22 ;; computations.
23 ;; multi0 is a multiple insn rtl whose first insn is in pipe0
24 ;; multi1 is a multiple insn rtl whose first insn is in pipe1
25 (define_attr "type" "fx2,shuf,fx3,load,store,br,spr,lnop,nop,fxb,fp6,fp7,fpd,iprefetch,multi0,multi1,hbr,convert"
26   (const_string "fx2"))
27
28 ;; Length (in bytes).
29 (define_attr "length" ""
30                 (const_int 4))
31
32 ;; Processor type -- this attribute must exactly match the processor_type
33 ;; enumeration in spu.h.
34
35 (define_attr "cpu" "spu"
36   (const (symbol_ref "spu_cpu_attr")))
37
38 ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
39 ;                       TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
40
41 (define_cpu_unit "pipe0,pipe1,fp,ls")
42
43 (define_insn_reservation "NOP" 1 (eq_attr "type" "nop")
44     "pipe0")
45
46 (define_insn_reservation "FX2" 2 (eq_attr "type" "fx2")
47     "pipe0, nothing")
48
49 (define_insn_reservation "FX3" 4 (eq_attr "type" "fx3,fxb")
50     "pipe0, nothing*3")
51
52 (define_insn_reservation "FP6" 6 (eq_attr "type" "fp6")
53     "pipe0 + fp, nothing*5")
54
55 (define_insn_reservation "FP7" 7 (eq_attr "type" "fp7")
56     "pipe0, fp, nothing*5")
57
58 ;; The behaviour of the double precision is that both pipes stall
59 ;; for 6 cycles and the the rest of the operation pipelines for
60 ;; 7 cycles.  The simplest way to model this is to simply ignore
61 ;; the 6 cyle stall.
62 (define_insn_reservation "FPD" 7 (eq_attr "type" "fpd")
63     "pipe0 + pipe1, fp, nothing*5")
64
65 (define_insn_reservation "LNOP" 1 (eq_attr "type" "lnop")
66     "pipe1")
67
68 (define_insn_reservation "STORE" 1 (eq_attr "type" "store")
69     "pipe1 + ls")
70
71 (define_insn_reservation "IPREFETCH" 1 (eq_attr "type" "iprefetch")
72     "pipe1 + ls")
73
74 (define_insn_reservation "SHUF" 4 (eq_attr "type" "shuf,br,spr")
75     "pipe1, nothing*3")
76
77 (define_insn_reservation "LOAD" 6 (eq_attr "type" "load")
78     "pipe1 + ls, nothing*5")
79
80 (define_insn_reservation "HBR" 18 (eq_attr "type" "hbr")
81     "pipe1, nothing*15")
82
83 (define_insn_reservation "MULTI0" 4 (eq_attr "type" "multi0")
84     "pipe0+pipe1, nothing*3")
85
86 (define_insn_reservation "MULTI1" 4 (eq_attr "type" "multi1")
87     "pipe1, nothing*3")
88
89 (define_insn_reservation "CONVERT" 0 (eq_attr "type" "convert")
90     "nothing")
91
92 ;; Force pipe0 to occur before pipe 1 in a cycle.
93 (absence_set "pipe0" "pipe1")
94
95 \f
96 (define_constants [
97  (UNSPEC_BLOCKAGE       0)
98  (UNSPEC_IPREFETCH      1)
99  (UNSPEC_FREST          2)
100  (UNSPEC_FRSQEST        3)
101  (UNSPEC_FI             4)
102  (UNSPEC_EXTEND_CMP     5)
103  (UNSPEC_CG             6)
104  (UNSPEC_CGX            7)
105  (UNSPEC_ADDX           8)
106  (UNSPEC_BG             9)
107  (UNSPEC_BGX            10)
108  (UNSPEC_SFX            11)
109  (UNSPEC_FSM            12)
110  (UNSPEC_HBR            13)
111  (UNSPEC_LNOP           14)
112  (UNSPEC_NOP            15)
113  (UNSPEC_CONVERT        16)
114  (UNSPEC_SELB           17)
115  (UNSPEC_SHUFB          18)
116  (UNSPEC_CPAT           19)
117  (UNSPEC_SYNC           20)
118  (UNSPEC_CNTB           21)
119  (UNSPEC_SUMB           22)
120  (UNSPEC_FSMB           23)
121  (UNSPEC_FSMH           24)
122  (UNSPEC_GBB            25)
123  (UNSPEC_GBH            26)
124  (UNSPEC_GB             27)
125  (UNSPEC_AVGB           28)
126  (UNSPEC_ABSDB          29)
127  (UNSPEC_ORX            30)
128  (UNSPEC_HEQ            31)
129  (UNSPEC_HGT            32)
130  (UNSPEC_HLGT           33)
131  (UNSPEC_CSFLT          34)
132  (UNSPEC_CFLTS          35)
133  (UNSPEC_CUFLT          36)
134  (UNSPEC_CFLTU          37)
135  (UNSPEC_STOP           38)
136  (UNSPEC_STOPD          39)
137  (UNSPEC_IDISABLE       40)
138  (UNSPEC_IENABLE        41)
139  (UNSPEC_FSCRRD         42)
140  (UNSPEC_FSCRWR         43)
141  (UNSPEC_MFSPR          44)
142  (UNSPEC_MTSPR          45)
143  (UNSPEC_RDCH           46)
144  (UNSPEC_RCHCNT         47)
145  (UNSPEC_WRCH           48)])
146
147 (include "predicates.md")
148 (include "constraints.md")
149
150 \f
151 ;; Mode macros
152
153 (define_mode_macro ALL [QI V16QI
154                         HI V8HI
155                         SI V4SI
156                         DI V2DI
157                         TI
158                         SF V4SF
159                         DF V2DF])
160
161 ; Everything except DI and TI which are handled separately because
162 ; they need different constraints to correctly test VOIDmode constants
163 (define_mode_macro MOV [QI V16QI
164                         HI V8HI
165                         SI V4SI
166                         V2DI
167                         SF V4SF
168                         DF V2DF])
169
170 (define_mode_macro DTI  [DI TI])
171
172 (define_mode_macro VINT [QI V16QI
173                          HI V8HI
174                          SI V4SI
175                          DI V2DI
176                          TI])
177
178 (define_mode_macro VQHSI [QI V16QI
179                           HI V8HI
180                           SI V4SI])
181
182 (define_mode_macro VHSI [HI V8HI
183                          SI V4SI])
184
185 (define_mode_macro VSDF [SF V4SF
186                          DF V2DF])
187
188 (define_mode_macro VSI [SI V4SI])
189 (define_mode_macro VDI [DI V2DI])
190 (define_mode_macro VSF [SF V4SF])
191 (define_mode_macro VDF [DF V2DF])
192
193 (define_mode_attr bh  [(QI "b")  (V16QI "b")
194                        (HI "h")  (V8HI "h")
195                        (SI "")   (V4SI "")])
196
197 (define_mode_attr d   [(SF "")   (V4SF "")
198                        (DF "d")  (V2DF "d")])
199 (define_mode_attr d6  [(SF "6")  (V4SF "6")
200                        (DF "d")  (V2DF "d")])
201 (define_mode_attr f2i [(SF "SI") (V4SF "V4SI")
202                        (DF "DI") (V2DF "V2DI")])
203
204 ;; Used for carry and borrow instructions.
205 (define_mode_macro CBOP  [SI DI V4SI V2DI])
206
207 ;; Used in vec_set and vec_extract
208 (define_mode_macro V [V2DI V4SI V8HI V16QI V2DF V4SF])
209 (define_mode_attr inner  [(V16QI "QI")
210                           (V8HI  "HI")
211                           (V4SI  "SI")
212                           (V2DI  "DI")
213                           (V4SF  "SF")
214                           (V2DF  "DF")])
215 (define_mode_attr vmult  [(V16QI "1")
216                           (V8HI  "2")
217                           (V4SI  "4")
218                           (V2DI  "8")
219                           (V4SF  "4")
220                           (V2DF  "8")])
221 (define_mode_attr voff   [(V16QI "13")
222                           (V8HI  "14")
223                           (V4SI  "0")
224                           (V2DI  "0")
225                           (V4SF  "0")
226                           (V2DF  "0")])
227
228 \f
229 ;; mov
230
231 (define_expand "mov<mode>"
232   [(set (match_operand:ALL 0 "spu_nonimm_operand" "=r,r,r,m")
233         (match_operand:ALL 1 "general_operand" "r,i,m,r"))]
234   ""
235   {
236     if (spu_expand_mov(operands, <MODE>mode))
237       DONE;
238   })
239
240 (define_split 
241   [(set (match_operand 0 "spu_reg_operand")
242         (match_operand 1 "immediate_operand"))]
243
244   ""
245   [(set (match_dup 0)
246         (high (match_dup 1)))
247    (set (match_dup 0)
248         (lo_sum (match_dup 0)
249                 (match_dup 1)))]
250   {
251     if (spu_split_immediate (operands))
252       DONE;
253     FAIL;
254   })
255
256 (define_insn "pic"
257   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
258         (match_operand:SI 1 "immediate_operand" "s"))
259    (use (const_int 0))]
260   "flag_pic"
261   "ila\t%0,%%pic(%1)")
262
263 ;; Whenever a function generates the 'pic' pattern above we need to
264 ;; load the pic_offset_table register.
265 ;; GCC doesn't deal well with labels in the middle of a block so we
266 ;; hardcode the offsets in the asm here.
267 (define_insn "load_pic_offset"
268   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
269         (unspec:SI [(const_int 0)] 0))
270    (set (match_operand:SI 1 "spu_reg_operand" "=r")
271         (unspec:SI [(const_int 0)] 0))]
272   "flag_pic"
273   "ila\t%1,.+8\;brsl\t%0,4"
274   [(set_attr "length" "8")
275    (set_attr "type" "multi0")])
276
277 \f
278 ;; move internal
279
280 (define_insn "_mov<mode>"
281   [(set (match_operand:MOV 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
282         (match_operand:MOV 1 "spu_mov_operand" "r,A,f,j,m,r"))]
283   "spu_valid_move (operands)"
284   "@
285    ori\t%0,%1,0
286    il%s1\t%0,%S1
287    fsmbi\t%0,%S1
288    c%s1d\t%0,%S1($sp)
289    lq%p1\t%0,%1
290    stq%p0\t%1,%0"
291   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
292
293 (define_insn "high"
294   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
295         (high:SI (match_operand:SI 1 "immediate_operand" "i")))]
296   ""
297   "ilhu\t%0,%1@h")
298
299 (define_insn "low"
300   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
301         (lo_sum:SI (match_operand:SI 1 "spu_reg_operand" "0")
302                    (match_operand:SI 2 "immediate_operand" "i")))]
303   ""
304   "iohl\t%0,%2@l")
305
306 (define_insn "_movdi"
307   [(set (match_operand:DI 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
308         (match_operand:DI 1 "spu_mov_operand" "r,a,f,k,m,r"))]
309   "spu_valid_move (operands)"
310   "@
311    ori\t%0,%1,0
312    il%d1\t%0,%D1
313    fsmbi\t%0,%D1
314    c%d1d\t%0,%D1($sp)
315    lq%p1\t%0,%1
316    stq%p0\t%1,%0"
317   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
318
319 (define_insn "_movti"
320   [(set (match_operand:TI 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
321         (match_operand:TI 1 "spu_mov_operand" "r,U,f,l,m,r"))]
322   "spu_valid_move (operands)"
323   "@
324    ori\t%0,%1,0
325    il%t1\t%0,%T1
326    fsmbi\t%0,%T1
327    c%t1d\t%0,%T1($sp)
328    lq%p1\t%0,%1
329    stq%p0\t%1,%0"
330   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
331
332 (define_insn_and_split "load"
333   [(set (match_operand 0 "spu_reg_operand" "=r")
334         (match_operand 1 "memory_operand" "m"))
335    (clobber (match_operand:TI 2 "spu_reg_operand" "=&r"))
336    (clobber (match_operand:SI 3 "spu_reg_operand" "=&r"))]
337   "GET_MODE(operands[0]) == GET_MODE(operands[1])"
338   "#"
339   ""
340   [(set (match_dup 0)
341         (match_dup 1))]
342   { spu_split_load(operands); DONE; })
343
344 (define_insn_and_split "store"
345   [(set (match_operand 0 "memory_operand" "=m")
346         (match_operand 1 "spu_reg_operand" "r"))
347    (clobber (match_operand:TI 2 "spu_reg_operand" "=&r"))
348    (clobber (match_operand:TI 3 "spu_reg_operand" "=&r"))]
349   "GET_MODE(operands[0]) == GET_MODE(operands[1])"
350   "#"
351   ""
352   [(set (match_dup 0)
353         (match_dup 1))]
354   { spu_split_store(operands); DONE; })
355
356 ;; Operand 3 is the number of bytes. 1:b 2:h 4:w 8:d
357
358 (define_expand "cpat"
359   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
360         (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "r,r")
361                     (match_operand:SI 2 "spu_nonmem_operand" "r,n")
362                     (match_operand:SI 3 "immediate_operand" "i,i")] UNSPEC_CPAT))]
363   ""
364   {
365     rtx x = gen_cpat_const (operands);
366     if (x)
367       {
368         emit_move_insn (operands[0], x);
369         DONE;
370       }
371   })
372
373 (define_insn "_cpat"
374   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
375         (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "r,r")
376                     (match_operand:SI 2 "spu_nonmem_operand" "r,n")
377                     (match_operand:SI 3 "immediate_operand" "i,i")] UNSPEC_CPAT))]
378   ""
379   "@
380    c%M3x\t%0,%1,%2
381    c%M3d\t%0,%C2(%1)"
382   [(set_attr "type" "shuf")])
383
384 (define_split
385   [(set (match_operand:TI 0 "spu_reg_operand")
386         (unspec:TI [(match_operand:SI 1 "spu_nonmem_operand")
387                     (match_operand:SI 2 "immediate_operand")
388                     (match_operand:SI 3 "immediate_operand")] UNSPEC_CPAT))]
389   ""
390   [(set (match_dup:TI 0)
391         (match_dup:TI 4))]
392   {
393     operands[4] = gen_cpat_const (operands);
394     if (!operands[4])
395       FAIL;
396   })
397 \f
398 ;; extend
399
400 (define_insn "extendqihi2"
401   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
402         (sign_extend:HI (match_operand:QI 1 "spu_reg_operand" "r")))]
403   ""
404   "xsbh\t%0,%1")
405
406 (define_insn "extendhisi2"
407   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
408         (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r")))]
409   ""
410   "xshw\t%0,%1")
411
412 (define_expand "extendsidi2"
413   [(set (match_dup:DI 2)
414         (zero_extend:DI (match_operand:SI 1 "spu_reg_operand" "")))
415    (set (match_operand:DI 0 "spu_reg_operand" "")
416         (sign_extend:DI (vec_select:SI (match_dup:V2SI 3)
417                                        (parallel [(const_int 1)]))))]
418   ""
419   {
420     operands[2] = gen_reg_rtx (DImode);
421     operands[3] = spu_gen_subreg (V2SImode, operands[2]);
422   })
423
424 (define_insn "xswd"
425   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
426         (sign_extend:DI
427           (vec_select:SI
428             (match_operand:V2SI 1 "spu_reg_operand" "r")
429             (parallel [(const_int 1) ]))))]
430   ""
431   "xswd\t%0,%1");
432
433 (define_expand "extendqiti2"
434   [(set (match_operand:TI 0 "register_operand" "")
435         (sign_extend:TI (match_operand:QI 1 "register_operand" "")))]
436   ""
437   "spu_expand_sign_extend(operands);
438    DONE;")
439
440 (define_expand "extendhiti2"
441   [(set (match_operand:TI 0 "register_operand" "")
442         (sign_extend:TI (match_operand:HI 1 "register_operand" "")))]
443   ""
444   "spu_expand_sign_extend(operands);
445    DONE;")
446
447 (define_expand "extendsiti2"
448   [(set (match_operand:TI 0 "register_operand" "")
449         (sign_extend:TI (match_operand:SI 1 "register_operand" "")))]
450   ""
451   "spu_expand_sign_extend(operands);
452    DONE;")
453
454 (define_expand "extendditi2"
455   [(set (match_operand:TI 0 "register_operand" "")
456         (sign_extend:TI (match_operand:DI 1 "register_operand" "")))]
457   ""
458   "spu_expand_sign_extend(operands);
459    DONE;")
460
461 \f
462 ;; zero_extend
463
464 (define_insn "zero_extendqihi2"
465   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
466         (zero_extend:HI (match_operand:QI 1 "spu_reg_operand" "r")))]
467   ""
468   "andi\t%0,%1,0x00ff")
469
470 (define_insn "zero_extendqisi2"
471   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
472         (zero_extend:SI (match_operand:QI 1 "spu_reg_operand" "r")))]
473   ""
474   "andi\t%0,%1,0x00ff")
475
476 (define_expand "zero_extendhisi2"
477   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
478         (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r")))
479    (clobber (match_scratch:SI 2 "=&r"))]
480   ""
481   {
482     rtx mask = gen_reg_rtx (SImode);
483     rtx op1 = simplify_gen_subreg (SImode, operands[1], HImode, 0);
484     emit_move_insn (mask, GEN_INT (0xffff));
485     emit_insn (gen_andsi3(operands[0], op1, mask));
486     DONE;
487   })
488   
489 (define_insn "zero_extendsidi2"
490   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
491         (zero_extend:DI (match_operand:SI 1 "spu_reg_operand" "r")))]
492   ""
493   "rotqmbyi\t%0,%1,-4"
494   [(set_attr "type" "shuf")])
495
496 (define_insn "zero_extendsiti2"
497   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
498         (zero_extend:TI (match_operand:SI 1 "spu_reg_operand" "r")))]
499   ""
500   "rotqmbyi\t%0,%1,-12"
501   [(set_attr "type" "shuf")])
502
503 (define_insn "zero_extendditi2"
504   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
505         (zero_extend:TI (match_operand:DI 1 "spu_reg_operand" "r")))]
506   ""
507   "rotqmbyi\t%0,%1,-8"
508   [(set_attr "type" "shuf")])
509
510 \f
511 ;; trunc
512
513 (define_insn "truncdiqi2"
514   [(set (match_operand:QI 0 "spu_reg_operand" "=r")
515         (truncate:QI (match_operand:DI 1 "spu_reg_operand" "r")))]
516   ""
517   "shlqbyi\t%0,%1,4"
518   [(set_attr "type" "shuf")])
519
520 (define_insn "truncdihi2"
521   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
522         (truncate:HI (match_operand:DI 1 "spu_reg_operand" "r")))]
523   ""
524   "shlqbyi\t%0,%1,4"
525   [(set_attr "type" "shuf")])
526
527 (define_insn "truncdisi2"
528   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
529         (truncate:SI (match_operand:DI 1 "spu_reg_operand" "r")))]
530   ""
531   "shlqbyi\t%0,%1,4"
532   [(set_attr "type" "shuf")])
533
534 (define_insn "trunctiqi2"
535   [(set (match_operand:QI 0 "spu_reg_operand" "=r")
536         (truncate:QI (match_operand:TI 1 "spu_reg_operand" "r")))]
537   ""
538   "shlqbyi\t%0,%1,12"
539   [(set_attr "type" "shuf")])
540
541 (define_insn "trunctihi2"
542   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
543         (truncate:HI (match_operand:TI 1 "spu_reg_operand" "r")))]
544   ""
545   "shlqbyi\t%0,%1,12"
546   [(set_attr "type" "shuf")])
547
548 (define_insn "trunctisi2"
549   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
550         (truncate:SI (match_operand:TI 1 "spu_reg_operand" "r")))]
551   ""
552   "shlqbyi\t%0,%1,12"
553   [(set_attr "type" "shuf")])
554
555 (define_insn "trunctidi2"
556   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
557         (truncate:DI (match_operand:TI 1 "spu_reg_operand" "r")))]
558   ""
559   "shlqbyi\t%0,%1,8"
560   [(set_attr "type" "shuf")])
561
562 \f
563 ;; float conversions
564
565 (define_insn "floatsisf2"
566   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
567         (float:SF (match_operand:SI 1 "spu_reg_operand" "r")))]
568   ""
569   "csflt\t%0,%1,0"
570   [(set_attr "type" "fp7")])
571
572 (define_insn "floatv4siv4sf2"
573   [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
574         (float:V4SF (match_operand:V4SI 1 "spu_reg_operand" "r")))]
575   ""
576   "csflt\t%0,%1,0"
577   [(set_attr "type" "fp7")])
578
579 (define_insn "fix_truncsfsi2"
580   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
581         (fix:SI (match_operand:SF 1 "spu_reg_operand" "r")))]
582   ""
583   "cflts\t%0,%1,0"
584   [(set_attr "type" "fp7")])
585
586 (define_insn "fix_truncv4sfv4si2"
587   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
588         (fix:V4SI (match_operand:V4SF 1 "spu_reg_operand" "r")))]
589   ""
590   "cflts\t%0,%1,0"
591   [(set_attr "type" "fp7")])
592
593 (define_insn "floatunssisf2"
594   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
595         (unsigned_float:SF (match_operand:SI 1 "spu_reg_operand" "r")))]
596   ""
597   "cuflt\t%0,%1,0"
598   [(set_attr "type" "fp7")])
599
600 (define_insn "floatunsv4siv4sf2"
601   [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
602         (unsigned_float:V4SF (match_operand:V4SI 1 "spu_reg_operand" "r")))]
603   ""
604   "cuflt\t%0,%1,0"
605   [(set_attr "type" "fp7")])
606
607 (define_insn "fixuns_truncsfsi2"
608   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
609         (unsigned_fix:SI (match_operand:SF 1 "spu_reg_operand" "r")))]
610   ""
611   "cfltu\t%0,%1,0"
612   [(set_attr "type" "fp7")])
613
614 (define_insn "fixuns_truncv4sfv4si2"
615   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
616         (unsigned_fix:V4SI (match_operand:V4SF 1 "spu_reg_operand" "r")))]
617   ""
618   "cfltu\t%0,%1,0"
619   [(set_attr "type" "fp7")])
620
621 (define_insn "extendsfdf2"
622   [(set (match_operand:DF 0 "spu_reg_operand" "=r")
623         (float_extend:DF (match_operand:SF 1 "spu_reg_operand" "r")))]
624   ""
625   "fesd\t%0,%1"
626   [(set_attr "type" "fpd")])
627
628 (define_insn "truncdfsf2"
629   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
630         (float_truncate:SF (match_operand:DF 1 "spu_reg_operand" "r")))]
631   ""
632   "frds\t%0,%1"
633   [(set_attr "type" "fpd")])
634
635 ;; Do (double)(operands[1]+0x80000000u)-(double)0x80000000
636 (define_expand "floatsidf2"
637   [(set (match_operand:DF 0 "register_operand" "")
638         (float:DF (match_operand:SI 1 "register_operand" "")))]
639   ""
640   {
641     rtx value, insns;
642     rtx c0 = gen_reg_rtx (SImode);
643     rtx c1 = gen_reg_rtx (DFmode);
644     rtx r0 = gen_reg_rtx (SImode);
645     rtx r1 = gen_reg_rtx (DFmode);
646
647     emit_move_insn (c0, GEN_INT (-0x80000000ll));
648     emit_move_insn (c1, spu_float_const ("2147483648", DFmode));
649
650     emit_insn (gen_xorsi3 (r0, operands[1], c0));
651
652     start_sequence ();
653     value =
654       emit_library_call_value (ufloat_optab->handlers[DFmode][SImode].libfunc,
655                                NULL_RTX, LCT_NORMAL, DFmode, 1, r0, SImode);
656     insns = get_insns ();
657     end_sequence ();
658     emit_libcall_block (insns, r1, value,
659                         gen_rtx_UNSIGNED_FLOAT (DFmode, r0));
660
661     emit_insn (gen_subdf3 (operands[0], r1, c1));
662     DONE;
663   })
664
665 (define_expand "floatdidf2"
666   [(set (match_operand:DF 0 "register_operand" "")
667         (float:DF (match_operand:DI 1 "register_operand" "")))]
668   ""
669   {
670     rtx value, insns;
671     rtx c0 = gen_reg_rtx (DImode);
672     rtx r0 = gen_reg_rtx (DImode);
673     rtx r1 = gen_reg_rtx (DFmode);
674     rtx r2 = gen_reg_rtx (DImode);
675     rtx setneg = gen_reg_rtx (DImode);
676     rtx isneg = gen_reg_rtx (SImode);
677     rtx neg = gen_reg_rtx (DImode);
678     rtx mask = gen_reg_rtx (DImode);
679
680     emit_move_insn (c0, GEN_INT (0x8000000000000000ull));
681
682     emit_insn (gen_negdi2 (neg, operands[1]));
683     emit_insn (gen_cgt_di_m1 (isneg, operands[1]));
684     emit_insn (gen_extend_compare (mask, isneg));
685     emit_insn (gen_selb (r0, neg, operands[1], mask));
686     emit_insn (gen_andc_di (setneg, c0, mask));
687
688
689     start_sequence ();
690     value =
691       emit_library_call_value (ufloat_optab->handlers[DFmode][DImode].libfunc,
692                                NULL_RTX, LCT_NORMAL, DFmode, 1, r0, DImode);
693     insns = get_insns ();
694     end_sequence ();
695     emit_libcall_block (insns, r1, value,
696                         gen_rtx_UNSIGNED_FLOAT (DFmode, r0));
697
698     emit_insn (gen_iordi3 (r2, gen_rtx_SUBREG (DImode, r1, 0), setneg));
699     emit_move_insn (operands[0], gen_rtx_SUBREG (DFmode, r2, 0));
700     DONE;
701   })
702 \f
703 ;; add
704
705 (define_expand "addv16qi3"
706   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
707         (plus:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")
708                     (match_operand:V16QI 2 "spu_reg_operand" "r")))]
709   ""
710   "{
711     rtx res_short = simplify_gen_subreg (V8HImode, operands[0], V16QImode, 0);
712     rtx lhs_short = simplify_gen_subreg (V8HImode, operands[1], V16QImode, 0);
713     rtx rhs_short = simplify_gen_subreg (V8HImode, operands[2], V16QImode, 0);
714     rtx rhs_and = gen_reg_rtx (V8HImode);
715     rtx hi_char = gen_reg_rtx (V8HImode);
716     rtx lo_char = gen_reg_rtx (V8HImode);
717     rtx mask = gen_reg_rtx (V8HImode);
718
719     emit_move_insn (mask, spu_const (V8HImode, 0x00ff));
720     emit_insn (gen_andv8hi3 (rhs_and, rhs_short, spu_const (V8HImode, 0xff00)));
721     emit_insn (gen_addv8hi3 (hi_char, lhs_short, rhs_and));
722     emit_insn (gen_addv8hi3 (lo_char, lhs_short, rhs_short));
723     emit_insn (gen_selb (res_short, hi_char, lo_char, mask));
724     DONE;
725    }")
726
727 (define_insn "add<mode>3"
728   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
729         (plus:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
730                    (match_operand:VHSI 2 "spu_arith_operand" "r,B")))]
731   ""
732   "@
733   a<bh>\t%0,%1,%2
734   a<bh>i\t%0,%1,%2")
735
736 (define_expand "add<mode>3"
737   [(set (match_dup:VDI 3) 
738         (unspec:VDI [(match_operand:VDI 1 "spu_reg_operand" "")
739                      (match_operand:VDI 2 "spu_reg_operand" "")] UNSPEC_CG))
740    (set (match_dup:VDI 5)
741         (unspec:VDI [(match_dup 3)
742                      (match_dup 3)
743                      (match_dup:TI 4)] UNSPEC_SHUFB))
744    (set (match_operand:VDI 0 "spu_reg_operand" "") 
745         (unspec:VDI [(match_dup 1)
746                      (match_dup 2)
747                      (match_dup 5)] UNSPEC_ADDX))]
748   ""
749   {
750     unsigned char pat[16] = {
751       0x04, 0x05, 0x06, 0x07,
752       0x80, 0x80, 0x80, 0x80,
753       0x0c, 0x0d, 0x0e, 0x0f,
754       0x80, 0x80, 0x80, 0x80
755     };
756     operands[3] = gen_reg_rtx (<MODE>mode);
757     operands[4] = gen_reg_rtx (TImode);
758     operands[5] = gen_reg_rtx (<MODE>mode);
759     emit_move_insn (operands[4], array_to_constant (TImode, pat));
760   })
761
762 (define_insn "cg_<mode>"
763   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
764         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
765                       (match_operand 2 "spu_reg_operand" "r")] UNSPEC_CG))]
766   "operands"
767   "cg\t%0,%1,%2")
768
769 (define_insn "cgx_<mode>"
770   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
771         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
772                       (match_operand 2 "spu_reg_operand" "r")
773                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_CGX))]
774   "operands"
775   "cgx\t%0,%1,%2")
776
777 (define_insn "addx_<mode>"
778   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
779         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
780                       (match_operand 2 "spu_reg_operand" "r")
781                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_ADDX))]
782   "operands"
783   "addx\t%0,%1,%2")
784
785
786 ;; This is not the most efficient implementation of addti3.
787 ;; We include this here because 1) the compiler needs it to be
788 ;; defined as the word size is 128-bit and 2) sometimes gcc
789 ;; substitutes an add for a constant left-shift. 2) is unlikely
790 ;; because we also give addti3 a high cost. In case gcc does
791 ;; generate TImode add, here is the code to do it.
792 ;; operand 2 is a nonmemory because the compiler requires it.
793 (define_insn "addti3"
794   [(set (match_operand:TI 0 "spu_reg_operand" "=&r")
795         (plus:TI (match_operand:TI 1 "spu_reg_operand" "r")
796                  (match_operand:TI 2 "spu_nonmem_operand" "r")))
797    (clobber (match_scratch:TI 3 "=&r"))]
798   ""
799   "cg\t%3,%1,%2\n\\
800    shlqbyi\t%3,%3,4\n\\
801    cgx\t%3,%1,%2\n\\
802    shlqbyi\t%3,%3,4\n\\
803    cgx\t%3,%1,%2\n\\
804    shlqbyi\t%0,%3,4\n\\
805    addx\t%0,%1,%2"
806   [(set_attr "type" "multi0")
807    (set_attr "length" "28")])
808
809 (define_insn "add<mode>3"
810   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
811         (plus:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
812                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
813   ""
814   "fa\t%0,%1,%2"
815   [(set_attr "type" "fp6")])
816
817 (define_insn "add<mode>3"
818   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
819         (plus:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
820                   (match_operand:VDF 2 "spu_reg_operand" "r")))]
821   ""
822   "dfa\t%0,%1,%2"
823   [(set_attr "type" "fpd")])
824
825 \f
826 ;; sub
827
828 (define_expand "subv16qi3"
829   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
830         (minus:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")
831                      (match_operand:V16QI 2 "spu_reg_operand" "r")))]
832   ""
833   "{
834     rtx res_short = simplify_gen_subreg (V8HImode, operands[0], V16QImode, 0);
835     rtx lhs_short = simplify_gen_subreg (V8HImode, operands[1], V16QImode, 0);
836     rtx rhs_short = simplify_gen_subreg (V8HImode, operands[2], V16QImode, 0);
837     rtx rhs_and = gen_reg_rtx (V8HImode);
838     rtx hi_char = gen_reg_rtx (V8HImode);
839     rtx lo_char = gen_reg_rtx (V8HImode);
840     rtx mask = gen_reg_rtx (V8HImode);
841
842     emit_move_insn (mask, spu_const (V8HImode, 0x00ff));
843     emit_insn (gen_andv8hi3 (rhs_and, rhs_short, spu_const (V8HImode, 0xff00)));
844     emit_insn (gen_subv8hi3 (hi_char, lhs_short, rhs_and));
845     emit_insn (gen_subv8hi3 (lo_char, lhs_short, rhs_short));
846     emit_insn (gen_selb (res_short, hi_char, lo_char, mask));
847     DONE;
848    }")
849
850 (define_insn "sub<mode>3"
851   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
852         (minus:VHSI (match_operand:VHSI 1 "spu_arith_operand" "r,B")
853                     (match_operand:VHSI 2 "spu_reg_operand" "r,r")))]
854   ""
855   "@
856   sf<bh>\t%0,%2,%1
857   sf<bh>i\t%0,%2,%1")
858
859 (define_expand "sub<mode>3"
860   [(set (match_dup:VDI 3) 
861         (unspec:VDI [(match_operand:VDI 1 "spu_reg_operand" "")
862                      (match_operand:VDI 2 "spu_reg_operand" "")] UNSPEC_BG))
863    (set (match_dup:VDI 5)
864         (unspec:VDI [(match_dup 3)
865                      (match_dup 3)
866                      (match_dup:TI 4)] UNSPEC_SHUFB))
867    (set (match_operand:VDI 0 "spu_reg_operand" "") 
868         (unspec:VDI [(match_dup 1)
869                      (match_dup 2)
870                      (match_dup 5)] UNSPEC_SFX))]
871   ""
872   {
873     unsigned char pat[16] = {
874       0x04, 0x05, 0x06, 0x07,
875       0xc0, 0xc0, 0xc0, 0xc0,
876       0x0c, 0x0d, 0x0e, 0x0f,
877       0xc0, 0xc0, 0xc0, 0xc0
878     };
879     operands[3] = gen_reg_rtx (<MODE>mode);
880     operands[4] = gen_reg_rtx (TImode);
881     operands[5] = gen_reg_rtx (<MODE>mode);
882     emit_move_insn (operands[4], array_to_constant (TImode, pat));
883   })
884
885 (define_insn "bg_<mode>"
886   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
887         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
888                       (match_operand 2 "spu_reg_operand" "r")] UNSPEC_BG))]
889   "operands"
890   "bg\t%0,%2,%1")
891
892 (define_insn "bgx_<mode>"
893   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
894         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
895                       (match_operand 2 "spu_reg_operand" "r")
896                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_BGX))]
897   "operands"
898   "bgx\t%0,%2,%1")
899
900 (define_insn "sfx_<mode>"
901   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
902         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
903                       (match_operand 2 "spu_reg_operand" "r")
904                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_SFX))]
905   "operands"
906   "sfx\t%0,%2,%1")
907
908 (define_insn "subti3"
909   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
910         (minus:TI (match_operand:TI 1 "spu_reg_operand" "r")
911                   (match_operand:TI 2 "spu_reg_operand" "r")))
912    (clobber (match_scratch:TI 3 "=&r"))
913    (clobber (match_scratch:TI 4 "=&r"))
914    (clobber (match_scratch:TI 5 "=&r"))]
915   ""
916   "bg\t%3,%1,%2\n\\
917    sf\t%4,%2,%1\n\\
918    shlqbyi\t%5,%3,4\n\\
919    bg\t%3,%4,%5\n\\
920    sf\t%4,%5,%4\n\\
921    shlqbyi\t%5,%3,4\n\\
922    bg\t%3,%4,%5\n\\
923    shlqbyi\t%0,%3,4\n\\
924    sfx\t%0,%5,%4"
925   [(set_attr "type" "multi0")
926    (set_attr "length" "36")])
927
928 (define_insn "sub<mode>3"
929   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
930         (minus:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
931                    (match_operand:VSF 2 "spu_reg_operand" "r")))]
932   ""
933   "fs\t%0,%1,%2"
934   [(set_attr "type" "fp6")])
935
936 (define_insn "sub<mode>3"
937   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
938         (minus:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
939                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
940   ""
941   "dfs\t%0,%1,%2"
942   [(set_attr "type" "fpd")])
943
944 \f
945 ;; neg
946
947 (define_expand "negv16qi2"
948   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
949         (neg:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")))]
950   ""
951   "{
952     rtx zero = gen_reg_rtx (V16QImode);
953     emit_move_insn (zero, CONST0_RTX (V16QImode));
954     emit_insn (gen_subv16qi3 (operands[0], zero, operands[1]));
955     DONE;
956    }")
957
958 (define_insn "neg<mode>2"
959   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
960         (neg:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")))]
961   ""
962   "sf<bh>i\t%0,%1,0")
963
964 (define_expand "negdi2"
965   [(set (match_operand:DI 0 "spu_reg_operand" "")
966         (neg:DI (match_operand:DI 1 "spu_reg_operand" "")))]
967   ""
968   {
969     rtx zero = gen_reg_rtx(DImode);
970     emit_move_insn(zero, GEN_INT(0));
971     emit_insn(gen_subdi3(operands[0], zero, operands[1]));
972     DONE;
973   })
974
975 (define_expand "negti2"
976   [(set (match_operand:TI 0 "spu_reg_operand" "")
977         (neg:TI (match_operand:TI 1 "spu_reg_operand" "")))]
978   ""
979   {
980     rtx zero = gen_reg_rtx(TImode);
981     emit_move_insn(zero, GEN_INT(0));
982     emit_insn(gen_subti3(operands[0], zero, operands[1]));
983     DONE;
984   })
985
986 (define_expand "neg<mode>2"
987   [(parallel
988     [(set (match_operand:VSF 0 "spu_reg_operand" "")
989           (neg:VSF (match_operand:VSF 1 "spu_reg_operand" "")))
990      (use (match_dup 2))])]
991   ""
992   "operands[2] = gen_reg_rtx (<f2i>mode);
993    emit_move_insn (operands[2], spu_const (<f2i>mode, -0x80000000ull));")
994
995 (define_expand "neg<mode>2"
996   [(parallel
997     [(set (match_operand:VDF 0 "spu_reg_operand" "")
998           (neg:VDF (match_operand:VDF 1 "spu_reg_operand" "")))
999      (use (match_dup 2))])]
1000   ""
1001   "operands[2] = gen_reg_rtx (<f2i>mode);
1002    emit_move_insn (operands[2], spu_const (<f2i>mode, -0x8000000000000000ull));")
1003
1004 (define_insn_and_split "_neg<mode>2"
1005   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1006         (neg:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")))
1007    (use (match_operand:<f2i> 2 "spu_reg_operand" "r"))]
1008   ""
1009   "#"
1010   ""
1011   [(set (match_dup:<f2i> 3)
1012         (xor:<f2i> (match_dup:<f2i> 4)
1013                    (match_dup:<f2i> 2)))]
1014   {
1015     operands[3] = spu_gen_subreg (<f2i>mode, operands[0]);
1016     operands[4] = spu_gen_subreg (<f2i>mode, operands[1]);
1017   })
1018
1019 \f
1020 ;; abs
1021
1022 (define_expand "abs<mode>2"
1023   [(parallel
1024     [(set (match_operand:VSF 0 "spu_reg_operand" "")
1025           (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "")))
1026      (use (match_dup 2))])]
1027   ""
1028   "operands[2] = gen_reg_rtx (<f2i>mode);
1029    emit_move_insn (operands[2], spu_const (<f2i>mode, 0x7fffffffull));")
1030
1031 (define_expand "abs<mode>2"
1032   [(parallel
1033     [(set (match_operand:VDF 0 "spu_reg_operand" "")
1034           (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "")))
1035      (use (match_dup 2))])]
1036   ""
1037   "operands[2] = gen_reg_rtx (<f2i>mode);
1038    emit_move_insn (operands[2], spu_const (<f2i>mode, 0x7fffffffffffffffull));")
1039
1040 (define_insn_and_split "_abs<mode>2"
1041   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1042         (abs:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")))
1043    (use (match_operand:<f2i> 2 "spu_reg_operand" "r"))]
1044   ""
1045   "#"
1046   ""
1047   [(set (match_dup:<f2i> 3)
1048         (and:<f2i> (match_dup:<f2i> 4)
1049                    (match_dup:<f2i> 2)))]
1050   {
1051     operands[3] = spu_gen_subreg (<f2i>mode, operands[0]);
1052     operands[4] = spu_gen_subreg (<f2i>mode, operands[1]);
1053   })
1054
1055 \f
1056 ;; mul
1057
1058 (define_insn "mulhi3"
1059   [(set (match_operand:HI 0 "spu_reg_operand" "=r,r")
1060         (mult:HI (match_operand:HI 1 "spu_reg_operand" "r,r")
1061                  (match_operand:HI 2 "spu_arith_operand" "r,B")))]
1062   ""
1063   "@
1064   mpy\t%0,%1,%2
1065   mpyi\t%0,%1,%2"
1066   [(set_attr "type" "fp7")])
1067
1068 (define_expand "mulv8hi3"
1069   [(set (match_operand:V8HI 0 "spu_reg_operand" "")
1070         (mult:V8HI (match_operand:V8HI 1 "spu_reg_operand" "")
1071                    (match_operand:V8HI 2 "spu_reg_operand" "")))]
1072   ""
1073   "{
1074     rtx result = simplify_gen_subreg (V4SImode, operands[0], V8HImode, 0);
1075     rtx low = gen_reg_rtx (V4SImode);
1076     rtx high = gen_reg_rtx (V4SImode);
1077     rtx shift = gen_reg_rtx (V4SImode);
1078     rtx mask = gen_reg_rtx (V4SImode);
1079
1080     emit_move_insn (mask, spu_const (V4SImode, 0x0000ffff));
1081     emit_insn (gen_spu_mpyhh (high, operands[1], operands[2]));
1082     emit_insn (gen_spu_mpy (low, operands[1], operands[2]));
1083     emit_insn (gen_ashlv4si3 (shift, high, spu_const(V4SImode, 16)));
1084     emit_insn (gen_selb (result, shift, low, mask));
1085     DONE;
1086    }")
1087
1088 (define_expand "mul<mode>3"
1089   [(parallel
1090     [(set (match_operand:VSI 0 "spu_reg_operand" "")
1091           (mult:VSI (match_operand:VSI 1 "spu_reg_operand" "")
1092                     (match_operand:VSI 2 "spu_reg_operand" "")))
1093      (clobber (match_dup:VSI 3))
1094      (clobber (match_dup:VSI 4))
1095      (clobber (match_dup:VSI 5))
1096      (clobber (match_dup:VSI 6))])]
1097   ""
1098   {
1099     operands[3] = gen_reg_rtx(<MODE>mode);
1100     operands[4] = gen_reg_rtx(<MODE>mode);
1101     operands[5] = gen_reg_rtx(<MODE>mode);
1102     operands[6] = gen_reg_rtx(<MODE>mode);
1103   })
1104
1105 (define_insn_and_split "_mulsi3"
1106   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1107         (mult:SI (match_operand:SI 1 "spu_reg_operand" "r")
1108                  (match_operand:SI 2 "spu_arith_operand" "rK")))
1109    (clobber (match_operand:SI 3 "spu_reg_operand" "=&r"))
1110    (clobber (match_operand:SI 4 "spu_reg_operand" "=&r"))
1111    (clobber (match_operand:SI 5 "spu_reg_operand" "=&r"))
1112    (clobber (match_operand:SI 6 "spu_reg_operand" "=&r"))]
1113   ""
1114   "#"
1115   ""
1116   [(set (match_dup:SI 0)
1117         (mult:SI (match_dup:SI 1)
1118                  (match_dup:SI 2)))]
1119   {
1120     HOST_WIDE_INT val = 0;
1121     rtx a = operands[3];
1122     rtx b = operands[4];
1123     rtx c = operands[5];
1124     rtx d = operands[6];
1125     if (GET_CODE(operands[2]) == CONST_INT)
1126       {
1127         val = INTVAL(operands[2]);
1128         emit_move_insn(d, operands[2]);
1129         operands[2] = d;
1130       }
1131     if (val && (val & 0xffff) == 0)
1132       {
1133         emit_insn(gen_mpyh_si(operands[0], operands[2], operands[1]));
1134       }
1135     else if (val > 0 && val < 0x10000)
1136       {
1137         rtx cst = satisfies_constraint_K (GEN_INT (val)) ? GEN_INT(val) : d;
1138         emit_insn(gen_mpyh_si(a, operands[1], operands[2]));
1139         emit_insn(gen_mpyu_si(c, operands[1], cst));
1140         emit_insn(gen_addsi3(operands[0], a, c));
1141       }
1142     else
1143       {
1144         emit_insn(gen_mpyh_si(a, operands[1], operands[2]));
1145         emit_insn(gen_mpyh_si(b, operands[2], operands[1]));
1146         emit_insn(gen_mpyu_si(c, operands[1], operands[2]));
1147         emit_insn(gen_addsi3(d, a, b));
1148         emit_insn(gen_addsi3(operands[0], d, c));
1149       }
1150     DONE;
1151    })
1152
1153 (define_insn_and_split "_mulv4si3"
1154   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
1155         (mult:V4SI (match_operand:V4SI 1 "spu_reg_operand" "r")
1156                    (match_operand:V4SI 2 "spu_reg_operand" "r")))
1157    (clobber (match_operand:V4SI 3 "spu_reg_operand" "=&r"))
1158    (clobber (match_operand:V4SI 4 "spu_reg_operand" "=&r"))
1159    (clobber (match_operand:V4SI 5 "spu_reg_operand" "=&r"))
1160    (clobber (match_operand:V4SI 6 "spu_reg_operand" "=&r"))]
1161   ""
1162   "#"
1163   ""
1164   [(set (match_dup:V4SI 0)
1165         (mult:V4SI (match_dup:V4SI 1)
1166                    (match_dup:V4SI 2)))]
1167   {
1168     rtx a = operands[3];
1169     rtx b = operands[4];
1170     rtx c = operands[5];
1171     rtx d = operands[6];
1172     rtx op1 = simplify_gen_subreg (V8HImode, operands[1], V4SImode, 0);
1173     rtx op2 = simplify_gen_subreg (V8HImode, operands[2], V4SImode, 0);
1174     emit_insn(gen_spu_mpyh(a, op1, op2));
1175     emit_insn(gen_spu_mpyh(b, op2, op1));
1176     emit_insn(gen_spu_mpyu(c, op1, op2));
1177     emit_insn(gen_addv4si3(d, a, b));
1178     emit_insn(gen_addv4si3(operands[0], d, c));
1179     DONE;
1180    })
1181
1182 (define_insn "mulhisi3"
1183   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1184         (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1185                  (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r"))))]
1186   ""
1187   "mpy\t%0,%1,%2"
1188   [(set_attr "type" "fp7")])
1189
1190 (define_insn "mulhisi3_imm"
1191   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1192         (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1193                  (match_operand:SI 2 "immediate_operand" "K")))]
1194   ""
1195   "mpyi\t%0,%1,%2"
1196   [(set_attr "type" "fp7")])
1197
1198 (define_insn "umulhisi3"
1199   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1200         (mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1201                  (zero_extend:SI (match_operand:HI 2 "spu_reg_operand" "r"))))]
1202   ""
1203   "mpyu\t%0,%1,%2"
1204   [(set_attr "type" "fp7")])
1205
1206 (define_insn "umulhisi3_imm"
1207   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1208         (mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1209                  (and:SI (match_operand:SI 2 "immediate_operand" "K") (const_int 65535))))]
1210   ""
1211   "mpyui\t%0,%1,%2"
1212   [(set_attr "type" "fp7")])
1213
1214 (define_insn "mpyu_si"
1215   [(set (match_operand:SI 0 "spu_reg_operand" "=r,r")
1216         (mult:SI (and:SI (match_operand:SI 1 "spu_reg_operand" "r,r")
1217                          (const_int 65535))
1218                  (and:SI (match_operand:SI 2 "spu_arith_operand" "r,K")
1219                          (const_int 65535))))]
1220   ""
1221   "@
1222    mpyu\t%0,%1,%2
1223    mpyui\t%0,%1,%2"
1224   [(set_attr "type" "fp7")])
1225
1226 ;; This isn't always profitable to use.  Consider r = a * b + c * d.
1227 ;; It's faster to do the multiplies in parallel then add them.  If we
1228 ;; merge a multiply and add it prevents the multiplies from happening in
1229 ;; parallel.
1230 (define_insn "mpya_si"
1231   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1232         (plus:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1233                           (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r")))
1234                  (match_operand:SI 3 "spu_reg_operand" "r")))]
1235   "0"
1236   "mpya\t%0,%1,%2,%3"
1237   [(set_attr "type" "fp7")])
1238
1239 (define_insn "mpyh_si"
1240   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1241         (mult:SI (and:SI (match_operand:SI 1 "spu_reg_operand" "r")
1242                          (const_int -65536))
1243                  (and:SI (match_operand:SI 2 "spu_reg_operand" "r")
1244                          (const_int 65535))))]
1245   ""
1246   "mpyh\t%0,%1,%2"
1247   [(set_attr "type" "fp7")])
1248
1249 (define_insn "mpys_si"
1250   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1251         (ashiftrt:SI
1252             (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1253                      (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r")))
1254             (const_int 16)))]
1255   ""
1256   "mpys\t%0,%1,%2"
1257   [(set_attr "type" "fp7")])
1258
1259 (define_insn "mpyhh_si"
1260   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1261         (mult:SI (ashiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1262                               (const_int 16))
1263                  (ashiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1264                               (const_int 16))))]
1265   ""
1266   "mpyhh\t%0,%1,%2"
1267   [(set_attr "type" "fp7")])
1268
1269 (define_insn "mpyhhu_si"
1270   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1271         (mult:SI (lshiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1272                               (const_int 16))
1273                  (lshiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1274                               (const_int 16))))]
1275   ""
1276   "mpyhhu\t%0,%1,%2"
1277   [(set_attr "type" "fp7")])
1278
1279 (define_insn "mpyhha_si" 
1280   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1281         (plus:SI (mult:SI (ashiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1282                                        (const_int 16))
1283                           (ashiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1284                                        (const_int 16)))
1285                  (match_operand:SI 3 "spu_reg_operand" "0")))]
1286   "0"
1287   "mpyhha\t%0,%1,%2"
1288   [(set_attr "type" "fp7")])
1289
1290 (define_insn "mul<mode>3"
1291   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1292         (mult:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")
1293                    (match_operand:VSDF 2 "spu_reg_operand" "r")))]
1294   ""
1295   "<d>fm\t%0,%1,%2"
1296   [(set_attr "type" "fp<d6>")])
1297
1298 (define_insn "fma_<mode>"
1299   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1300         (plus:VSF (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1301                               (match_operand:VSF 2 "spu_reg_operand" "r"))
1302                    (match_operand:VSF 3 "spu_reg_operand" "r")))]
1303   ""
1304   "fma\t%0,%1,%2,%3"
1305   [(set_attr "type"     "fp6")])
1306
1307 (define_insn "fnms_<mode>"
1308   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1309         (minus:VSF (match_operand:VSF 3 "spu_reg_operand" "r")
1310                     (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1311                                (match_operand:VSF 2 "spu_reg_operand" "r"))))]
1312   ""
1313   "fnms\t%0,%1,%2,%3"
1314   [(set_attr "type" "fp6")])
1315
1316 (define_insn "fms_<mode>"
1317   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1318         (minus:VSF (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1319                                (match_operand:VSF 2 "spu_reg_operand" "r"))
1320                     (match_operand:VSF 3 "spu_reg_operand" "r")))]
1321   ""
1322   "fms\t%0,%1,%2,%3"
1323   [(set_attr "type" "fp6")])
1324
1325 (define_insn "fma_<mode>"
1326   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1327         (plus:VDF (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1328                             (match_operand:VDF 2 "spu_reg_operand" "r"))
1329                   (match_operand:VDF 3 "spu_reg_operand" "0")))]
1330   ""
1331   "dfma\t%0,%1,%2"
1332   [(set_attr "type"     "fpd")])
1333
1334 (define_insn "fnma_<mode>"
1335   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1336         (neg:VDF (plus:VDF (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1337                                      (match_operand:VDF 2 "spu_reg_operand" "r"))
1338                            (match_operand:VDF 3 "spu_reg_operand" "0"))))]
1339   ""
1340   "dfnma\t%0,%1,%2"
1341   [(set_attr "type"     "fpd")])
1342
1343 (define_insn "fnms_<mode>"
1344   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1345         (minus:VDF (match_operand:VDF 3 "spu_reg_operand" "0")
1346                    (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1347                              (match_operand:VDF 2 "spu_reg_operand" "r"))))]
1348   ""
1349   "dfnms\t%0,%1,%2"
1350   [(set_attr "type" "fpd")])
1351
1352 (define_insn "fms_<mode>"
1353   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1354         (minus:VDF (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1355                              (match_operand:VDF 2 "spu_reg_operand" "r"))
1356                    (match_operand:VDF 3 "spu_reg_operand" "0")))]
1357   ""
1358   "dfms\t%0,%1,%2"
1359   [(set_attr "type" "fpd")])
1360
1361 \f
1362 ;; mul highpart, used for divide by constant optimizations.
1363
1364 (define_expand "smulsi3_highpart"
1365   [(set (match_operand:SI 0 "register_operand" "")
1366         (truncate:SI
1367           (ashiftrt:DI
1368             (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
1369                      (sign_extend:DI (match_operand:SI 2 "register_operand" "")))
1370             (const_int 32))))]
1371   ""
1372   {
1373     rtx t0 = gen_reg_rtx (SImode);
1374     rtx t1 = gen_reg_rtx (SImode);
1375     rtx t2 = gen_reg_rtx (SImode);
1376     rtx t3 = gen_reg_rtx (SImode);
1377     rtx t4 = gen_reg_rtx (SImode);
1378     rtx t5 = gen_reg_rtx (SImode);
1379     rtx t6 = gen_reg_rtx (SImode);
1380     rtx t7 = gen_reg_rtx (SImode);
1381     rtx t8 = gen_reg_rtx (SImode);
1382     rtx t9 = gen_reg_rtx (SImode);
1383     rtx t11 = gen_reg_rtx (SImode);
1384     rtx t12 = gen_reg_rtx (SImode);
1385     rtx t14 = gen_reg_rtx (SImode);
1386     rtx t15 = gen_reg_rtx (HImode);
1387     rtx t16 = gen_reg_rtx (HImode);
1388     rtx t17 = gen_reg_rtx (HImode);
1389     rtx t18 = gen_reg_rtx (HImode);
1390     rtx t19 = gen_reg_rtx (SImode);
1391     rtx t20 = gen_reg_rtx (SImode);
1392     rtx t21 = gen_reg_rtx (SImode);
1393     rtx op1_hi = gen_rtx_SUBREG (HImode, operands[1], 2);
1394     rtx op2_hi = gen_rtx_SUBREG (HImode, operands[2], 2);
1395     rtx t0_hi = gen_rtx_SUBREG (HImode, t0, 2);
1396     rtx t1_hi = gen_rtx_SUBREG (HImode, t1, 2);
1397
1398     emit_insn (gen_lshrsi3 (t0, operands[1], GEN_INT (16)));
1399     emit_insn (gen_lshrsi3 (t1, operands[2], GEN_INT (16)));
1400     emit_insn (gen_umulhisi3 (t2, op1_hi, op2_hi));
1401     emit_insn (gen_mpyh_si (t3, operands[1], operands[2]));
1402     emit_insn (gen_mpyh_si (t4, operands[2], operands[1]));
1403     emit_insn (gen_mpyhh_si (t5, operands[1], operands[2]));
1404     emit_insn (gen_mpys_si (t6, t0_hi, op2_hi));
1405     emit_insn (gen_mpys_si (t7, t1_hi, op1_hi));
1406
1407     /* Gen carry bits (in t9 and t11). */
1408     emit_insn (gen_addsi3 (t8, t2, t3));
1409     emit_insn (gen_cg_si (t9, t2, t3));
1410     emit_insn (gen_cg_si (t11, t8, t4));
1411
1412     /* Gen high 32 bits in operand[0].  Correct for mpys. */
1413     emit_insn (gen_addx_si (t12, t5, t6, t9));
1414     emit_insn (gen_addx_si (t14, t12, t7, t11));
1415
1416     /* mpys treats both operands as signed when we really want it to treat
1417        the first operand as signed and the second operand as unsigned.
1418        The code below corrects for that difference.  */
1419     emit_insn (gen_cgt_hi (t15, op1_hi, GEN_INT (-1)));
1420     emit_insn (gen_cgt_hi (t16, op2_hi, GEN_INT (-1)));
1421     emit_insn (gen_andc_hi (t17, t1_hi, t15));
1422     emit_insn (gen_andc_hi (t18, t0_hi, t16));
1423     emit_insn (gen_extendhisi2 (t19, t17));
1424     emit_insn (gen_extendhisi2 (t20, t18));
1425     emit_insn (gen_addsi3 (t21, t19, t20));
1426     emit_insn (gen_addsi3 (operands[0], t14, t21));
1427     DONE;
1428   })
1429
1430 (define_expand "umulsi3_highpart"
1431   [(set (match_operand:SI 0 "register_operand" "")
1432         (truncate:SI
1433           (ashiftrt:DI
1434             (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
1435                      (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1436             (const_int 32))))]
1437   ""
1438   
1439   {
1440     rtx t0 = gen_reg_rtx (SImode);
1441     rtx t1 = gen_reg_rtx (SImode);
1442     rtx t2 = gen_reg_rtx (SImode);
1443     rtx t3 = gen_reg_rtx (SImode);
1444     rtx t4 = gen_reg_rtx (SImode);
1445     rtx t5 = gen_reg_rtx (SImode);
1446     rtx t6 = gen_reg_rtx (SImode);
1447     rtx t7 = gen_reg_rtx (SImode);
1448     rtx t8 = gen_reg_rtx (SImode);
1449     rtx t9 = gen_reg_rtx (SImode);
1450     rtx t10 = gen_reg_rtx (SImode);
1451     rtx t12 = gen_reg_rtx (SImode);
1452     rtx t13 = gen_reg_rtx (SImode);
1453     rtx t14 = gen_reg_rtx (SImode);
1454     rtx op1_hi = gen_rtx_SUBREG (HImode, operands[1], 2);
1455     rtx op2_hi = gen_rtx_SUBREG (HImode, operands[2], 2);
1456     rtx t0_hi = gen_rtx_SUBREG (HImode, t0, 2);
1457
1458     emit_insn (gen_rotlsi3 (t0, operands[2], GEN_INT (16)));
1459     emit_insn (gen_umulhisi3 (t1, op1_hi, op2_hi));
1460     emit_insn (gen_umulhisi3 (t2, op1_hi, t0_hi));
1461     emit_insn (gen_mpyhhu_si (t3, operands[1], t0));
1462     emit_insn (gen_mpyhhu_si (t4, operands[1], operands[2]));
1463     emit_insn (gen_ashlsi3 (t5, t2, GEN_INT (16)));
1464     emit_insn (gen_ashlsi3 (t6, t3, GEN_INT (16)));
1465     emit_insn (gen_lshrsi3 (t7, t2, GEN_INT (16)));
1466     emit_insn (gen_lshrsi3 (t8, t3, GEN_INT (16)));
1467
1468     /* Gen carry bits (in t10 and t12). */
1469     emit_insn (gen_addsi3 (t9, t1, t5));
1470     emit_insn (gen_cg_si (t10, t1, t5));
1471     emit_insn (gen_cg_si (t12, t9, t6));
1472
1473     /* Gen high 32 bits in operand[0]. */
1474     emit_insn (gen_addx_si (t13, t4, t7, t10));
1475     emit_insn (gen_addx_si (t14, t13, t8, t12));
1476     emit_insn (gen_movsi (operands[0], t14));
1477
1478     DONE;
1479   })
1480 \f
1481 ;; div
1482
1483 ;; Not necessarily the best implementation of divide but faster then
1484 ;; the default that gcc provides because this is inlined and it uses
1485 ;; clz.
1486 (define_insn "divmodsi4"
1487       [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
1488             (div:SI (match_operand:SI 1 "spu_reg_operand" "r")
1489                     (match_operand:SI 2 "spu_reg_operand" "r")))
1490        (set (match_operand:SI 3 "spu_reg_operand" "=&r")
1491             (mod:SI (match_dup 1)
1492                     (match_dup 2)))
1493        (clobber (match_scratch:SI 4 "=&r"))
1494        (clobber (match_scratch:SI 5 "=&r"))
1495        (clobber (match_scratch:SI 6 "=&r"))
1496        (clobber (match_scratch:SI 7 "=&r"))
1497        (clobber (match_scratch:SI 8 "=&r"))
1498        (clobber (match_scratch:SI 9 "=&r"))
1499        (clobber (match_scratch:SI 10 "=&r"))
1500        (clobber (match_scratch:SI 11 "=&r"))
1501        (clobber (match_scratch:SI 12 "=&r"))
1502        (clobber (reg:SI 130))]
1503   ""
1504   "heqi %2,0\\n\\
1505         hbrr    3f,1f\\n\\
1506         sfi     %8,%1,0\\n\\
1507         sfi     %9,%2,0\\n\\
1508         cgti    %10,%1,-1\\n\\
1509         cgti    %11,%2,-1\\n\\
1510         selb    %8,%8,%1,%10\\n\\
1511         selb    %9,%9,%2,%11\\n\\
1512         clz     %4,%8\\n\\
1513         clz     %7,%9\\n\\
1514         il      %5,1\\n\\
1515         fsmbi   %0,0\\n\\
1516         sf      %7,%4,%7\\n\\
1517         shlqbyi %3,%8,0\\n\\
1518         xor     %11,%10,%11\\n\\
1519         shl     %5,%5,%7\\n\\
1520         shl     %4,%9,%7\\n\\
1521         lnop    \\n\\
1522 1:      or      %12,%0,%5\\n\\
1523         rotqmbii        %5,%5,-1\\n\\
1524         clgt    %6,%4,%3\\n\\
1525         lnop    \\n\\
1526         sf      %7,%4,%3\\n\\
1527         rotqmbii        %4,%4,-1\\n\\
1528         selb    %0,%12,%0,%6\\n\\
1529         lnop    \\n\\
1530         selb    %3,%7,%3,%6\\n\\
1531 3:      brnz    %5,1b\\n\\
1532 2:      sfi     %8,%3,0\\n\\
1533         sfi     %9,%0,0\\n\\
1534         selb    %3,%8,%3,%10\\n\\
1535         selb    %0,%0,%9,%11"
1536   [(set_attr "type" "multi0")
1537    (set_attr "length" "128")])
1538
1539 (define_insn "udivmodsi4"
1540       [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
1541             (udiv:SI (match_operand:SI 1 "spu_reg_operand" "r")
1542                      (match_operand:SI 2 "spu_reg_operand" "r")))
1543        (set (match_operand:SI 3 "spu_reg_operand" "=&r")
1544             (umod:SI (match_dup 1)
1545                      (match_dup 2)))
1546        (clobber (match_scratch:SI 4 "=&r"))
1547        (clobber (match_scratch:SI 5 "=&r"))
1548        (clobber (match_scratch:SI 6 "=&r"))
1549        (clobber (match_scratch:SI 7 "=&r"))
1550        (clobber (match_scratch:SI 8 "=&r"))
1551        (clobber (reg:SI 130))]
1552   ""
1553   "heqi %2,0\\n\\
1554         hbrr    3f,1f\\n\\
1555         clz     %7,%2\\n\\
1556         clz     %4,%1\\n\\
1557         il      %5,1\\n\\
1558         fsmbi   %0,0\\n\\
1559         sf      %7,%4,%7\\n\\
1560         ori     %3,%1,0\\n\\
1561         shl     %5,%5,%7\\n\\
1562         shl     %4,%2,%7\\n\\
1563 1:      or      %8,%0,%5\\n\\
1564         rotqmbii        %5,%5,-1\\n\\
1565         clgt    %6,%4,%3\\n\\
1566         lnop    \\n\\
1567         sf      %7,%4,%3\\n\\
1568         rotqmbii        %4,%4,-1\\n\\
1569         selb    %0,%8,%0,%6\\n\\
1570         lnop    \\n\\
1571         selb    %3,%7,%3,%6\\n\\
1572 3:      brnz    %5,1b\\n\\
1573 2:"
1574   [(set_attr "type" "multi0")
1575    (set_attr "length" "80")])
1576
1577 (define_insn_and_split "div<mode>3"
1578   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1579         (div:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1580                  (match_operand:VSF 2 "spu_reg_operand" "r")))
1581    (clobber (match_scratch:VSF 3 "=&r"))
1582    (clobber (match_scratch:VSF 4 "=&r"))]
1583   ""
1584   "#"
1585   "reload_completed"
1586   [(set (match_dup:VSF 0)
1587         (div:VSF (match_dup:VSF 1)
1588                  (match_dup:VSF 2)))
1589    (clobber (match_dup:VSF 3))
1590    (clobber (match_dup:VSF 4))]
1591   {
1592     emit_insn(gen_frest_<mode>(operands[3], operands[2]));
1593     emit_insn(gen_fi_<mode>(operands[3], operands[2], operands[3]));
1594     emit_insn(gen_mul<mode>3(operands[4], operands[1], operands[3]));
1595     emit_insn(gen_fnms_<mode>(operands[0], operands[4], operands[2], operands[1]));
1596     emit_insn(gen_fma_<mode>(operands[0], operands[0], operands[3], operands[4]));
1597     DONE;
1598   })
1599
1600 \f
1601 ;; sqrt
1602
1603 (define_insn_and_split "sqrtsf2"
1604   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
1605         (sqrt:SF (match_operand:SF 1 "spu_reg_operand" "r")))
1606    (clobber (match_scratch:SF 2 "=&r"))
1607    (clobber (match_scratch:SF 3 "=&r"))
1608    (clobber (match_scratch:SF 4 "=&r"))
1609    (clobber (match_scratch:SF 5 "=&r"))]
1610   ""
1611   "#"
1612   "reload_completed"
1613   [(set (match_dup:SF 0)
1614         (sqrt:SF (match_dup:SF 1)))
1615    (clobber (match_dup:SF 2))
1616    (clobber (match_dup:SF 3))
1617    (clobber (match_dup:SF 4))
1618    (clobber (match_dup:SF 5))]
1619   {
1620     emit_move_insn (operands[3],spu_float_const(\"0.5\",SFmode));
1621     emit_move_insn (operands[4],spu_float_const(\"1.00000011920928955078125\",SFmode));
1622     emit_insn(gen_frsqest_sf(operands[2],operands[1]));
1623     emit_insn(gen_fi_sf(operands[2],operands[1],operands[2]));
1624     emit_insn(gen_mulsf3(operands[5],operands[2],operands[1]));
1625     emit_insn(gen_mulsf3(operands[3],operands[5],operands[3]));
1626     emit_insn(gen_fnms_sf(operands[4],operands[2],operands[5],operands[4]));
1627     emit_insn(gen_fma_sf(operands[0],operands[4],operands[3],operands[5]));
1628     DONE;
1629   })
1630
1631 (define_insn "frest_<mode>"
1632   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1633         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")] UNSPEC_FREST))]
1634   ""
1635   "frest\t%0,%1"
1636   [(set_attr "type" "shuf")])
1637
1638 (define_insn "frsqest_<mode>"
1639   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1640         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")] UNSPEC_FRSQEST))]
1641   ""
1642   "frsqest\t%0,%1"
1643   [(set_attr "type" "shuf")])
1644
1645 (define_insn "fi_<mode>"
1646   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1647         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")
1648                     (match_operand:VSF 2 "spu_reg_operand" "r")] UNSPEC_FI))]
1649   ""
1650   "fi\t%0,%1,%2"
1651   [(set_attr "type" "fp7")])
1652
1653 \f
1654 ;; and
1655
1656 (define_insn "and<mode>3"
1657   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r")
1658         (and:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r")
1659                  (match_operand:MOV 2 "spu_logical_operand" "r,C")))]
1660   ""
1661   "@
1662   and\t%0,%1,%2
1663   and%j2i\t%0,%1,%J2")
1664
1665 (define_insn "anddi3"
1666   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
1667         (and:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
1668                 (match_operand:DI 2 "spu_logical_operand" "r,c")))]
1669   ""
1670   "@
1671   and\t%0,%1,%2
1672   and%k2i\t%0,%1,%K2")
1673
1674 (define_insn "andti3"
1675   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
1676         (and:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
1677                 (match_operand:TI 2 "spu_logical_operand" "r,Y")))]
1678   ""
1679   "@
1680   and\t%0,%1,%2
1681   and%m2i\t%0,%1,%L2")
1682
1683 (define_insn "andc_<mode>"
1684   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1685         (and:ALL (not:ALL (match_operand:ALL 2 "spu_reg_operand" "r"))
1686                  (match_operand:ALL 1 "spu_reg_operand" "r")))]
1687   ""
1688   "andc\t%0,%1,%2")
1689
1690 (define_insn "nand_<mode>"
1691   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1692         (not:ALL (and:ALL (match_operand:ALL 2 "spu_reg_operand" "r")
1693                           (match_operand:ALL 1 "spu_reg_operand" "r"))))]
1694   ""
1695   "nand\t%0,%1,%2")
1696
1697 \f
1698 ;; ior
1699
1700 (define_insn "ior<mode>3"
1701   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r,r")
1702         (ior:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r,0")
1703                  (match_operand:MOV 2 "spu_ior_operand" "r,C,D")))]
1704   ""
1705   "@
1706   or\t%0,%1,%2
1707   or%j2i\t%0,%1,%J2
1708   iohl\t%0,%J2")
1709
1710 (define_insn "iordi3"
1711   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r,r")
1712         (ior:DI (match_operand:DI 1 "spu_reg_operand" "r,r,0")
1713                 (match_operand:DI 2 "spu_ior_operand" "r,c,d")))]
1714   ""
1715   "@
1716   or\t%0,%1,%2
1717   or%k2i\t%0,%1,%K2
1718   iohl\t%0,%K2")
1719
1720 (define_insn "iorti3"
1721   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r,r")
1722         (ior:TI (match_operand:TI 1 "spu_reg_operand" "r,r,0")
1723                 (match_operand:TI 2 "spu_ior_operand" "r,Y,Z")))]
1724   ""
1725   "@
1726   or\t%0,%1,%2
1727   or%m2i\t%0,%1,%L2
1728   iohl\t%0,%L2")
1729
1730 (define_insn "orc_<mode>"
1731   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1732         (ior:ALL (not:ALL (match_operand:ALL 2 "spu_reg_operand" "r"))
1733                  (match_operand:ALL 1 "spu_reg_operand" "r")))]
1734   ""
1735   "orc\t%0,%1,%2")
1736
1737 (define_insn "nor_<mode>"
1738   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1739         (not:ALL (ior:ALL (match_operand:ALL 1 "spu_reg_operand" "r")
1740                           (match_operand:ALL 2 "spu_reg_operand" "r"))))]
1741   ""
1742   "nor\t%0,%1,%2")
1743 \f
1744 ;; xor
1745
1746 (define_insn "xor<mode>3"
1747   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r")
1748         (xor:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r")
1749                  (match_operand:MOV 2 "spu_logical_operand" "r,B")))]
1750   ""
1751   "@
1752   xor\t%0,%1,%2
1753   xor%j2i\t%0,%1,%S2")
1754
1755 (define_insn "xordi3"
1756   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
1757         (xor:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
1758                 (match_operand:DI 2 "spu_logical_operand" "r,c")))]
1759   ""
1760   "@
1761   xor\t%0,%1,%2
1762   xor%k2i\t%0,%1,%K2")
1763
1764 (define_insn "xorti3"
1765   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
1766         (xor:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
1767                 (match_operand:TI 2 "spu_logical_operand" "r,Y")))]
1768   ""
1769   "@
1770   xor\t%0,%1,%2
1771   xor%m2i\t%0,%1,%L2")
1772
1773 (define_insn "eqv_<mode>"
1774   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1775         (not:ALL (xor:ALL (match_operand:ALL 1 "spu_reg_operand" "r")
1776                           (match_operand:ALL 2 "spu_reg_operand" "r"))))]
1777   ""
1778   "eqv\t%0,%1,%2")
1779 \f
1780 ;; one_cmpl
1781
1782 (define_insn "one_cmpl<mode>2"
1783   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1784         (not:ALL (match_operand:ALL 1 "spu_reg_operand" "r")))]
1785   ""
1786   "nor\t%0,%1,%1")
1787
1788 \f
1789 ;; selb
1790
1791 (define_expand "selb"
1792   [(set (match_operand 0 "spu_reg_operand" "")
1793         (unspec [(match_operand 1 "spu_reg_operand" "")
1794                  (match_operand 2 "spu_reg_operand" "")
1795                  (match_operand 3 "spu_reg_operand" "")] UNSPEC_SELB))]
1796   ""
1797   {
1798     rtx s = gen__selb (operands[0], operands[1], operands[2], operands[3]);
1799     PUT_MODE (SET_SRC (s), GET_MODE (operands[0]));
1800     emit_insn (s);
1801     DONE;
1802   })
1803
1804 ;; This could be defined as a combination of logical operations, but at
1805 ;; one time it caused a crash due to recursive expansion of rtl during CSE.
1806 (define_insn "_selb"
1807   [(set (match_operand 0 "spu_reg_operand" "=r")
1808         (unspec [(match_operand 1 "spu_reg_operand" "r")
1809                  (match_operand 2 "spu_reg_operand" "r")
1810                  (match_operand 3 "spu_reg_operand" "r")] UNSPEC_SELB))]
1811   "GET_MODE(operands[0]) == GET_MODE(operands[1]) 
1812    && GET_MODE(operands[1]) == GET_MODE(operands[2])"
1813   "selb\t%0,%1,%2,%3")
1814
1815 \f
1816 ;; Misc. byte/bit operations
1817 ;; clz/ctz/ffs/popcount/parity
1818 ;; cntb/sumb
1819
1820 (define_insn "clz<mode>2"
1821   [(set (match_operand:VSI 0 "spu_reg_operand" "=r")
1822         (clz:VSI (match_operand:VSI 1 "spu_reg_operand" "r")))]
1823   ""
1824   "clz\t%0,%1")
1825
1826 (define_expand "ctz<mode>2"
1827   [(set (match_dup 2)
1828         (neg:VSI (match_operand:VSI 1 "spu_reg_operand" "")))
1829    (set (match_dup 3) (and:VSI (match_dup 1)
1830                                (match_dup 2)))
1831    (set (match_dup 4) (clz:VSI (match_dup 3)))
1832    (set (match_operand:VSI 0 "spu_reg_operand" "")
1833         (minus:VSI (match_dup 5) (match_dup 4)))]
1834   ""
1835   {
1836      operands[2] = gen_reg_rtx (<MODE>mode);
1837      operands[3] = gen_reg_rtx (<MODE>mode);
1838      operands[4] = gen_reg_rtx (<MODE>mode);
1839      operands[5] = spu_const(<MODE>mode, 31);
1840   })
1841
1842 (define_expand "ffs<mode>2"
1843   [(set (match_dup 2)
1844         (neg:VSI (match_operand:VSI 1 "spu_reg_operand" "")))
1845    (set (match_dup 3) (and:VSI (match_dup 1)
1846                                (match_dup 2)))
1847    (set (match_dup 4) (clz:VSI (match_dup 3)))
1848    (set (match_operand:VSI 0 "spu_reg_operand" "")
1849         (minus:VSI (match_dup 5) (match_dup 4)))]
1850   ""
1851   {
1852      operands[2] = gen_reg_rtx (<MODE>mode);
1853      operands[3] = gen_reg_rtx (<MODE>mode);
1854      operands[4] = gen_reg_rtx (<MODE>mode);
1855      operands[5] = spu_const(<MODE>mode, 32);
1856   })
1857
1858 (define_expand "popcountsi2"
1859   [(set (match_dup 2)
1860         (unspec:SI [(match_operand:SI 1 "spu_reg_operand" "")]
1861                      UNSPEC_CNTB))
1862    (set (match_dup 3)
1863         (unspec:HI [(match_dup 2)] UNSPEC_SUMB))
1864    (set (match_operand:SI 0 "spu_reg_operand" "")
1865         (sign_extend:SI (match_dup 3)))]
1866   ""
1867   {
1868     operands[2] = gen_reg_rtx (SImode);
1869     operands[3] = gen_reg_rtx (HImode);
1870   })
1871
1872 (define_expand "paritysi2"
1873   [(set (match_operand:SI 0 "spu_reg_operand" "")
1874         (parity:SI (match_operand:SI 1 "spu_reg_operand" "")))]
1875   ""
1876   {
1877     operands[2] = gen_reg_rtx (SImode);
1878     emit_insn (gen_popcountsi2(operands[2], operands[1]));
1879     emit_insn (gen_andsi3(operands[0], operands[2], GEN_INT (1)));
1880     DONE;
1881   })
1882
1883 (define_insn "cntb_si"
1884   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1885         (unspec:SI [(match_operand:SI 1 "spu_reg_operand" "r")]
1886                    UNSPEC_CNTB))]
1887   ""
1888   "cntb\t%0,%1"
1889   [(set_attr "type" "fxb")])
1890
1891 (define_insn "cntb_v16qi"
1892   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
1893         (unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r")]
1894                       UNSPEC_CNTB))]
1895   ""
1896   "cntb\t%0,%1"
1897   [(set_attr "type" "fxb")])
1898
1899 (define_insn "sumb_si"
1900   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
1901         (unspec:HI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_SUMB))]
1902   ""
1903   "sumb\t%0,%1,%1"
1904   [(set_attr "type" "fxb")])
1905
1906 \f
1907 ;; ashl
1908
1909 (define_insn "ashl<mode>3"
1910   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
1911         (ashift:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
1912                      (match_operand:VHSI 2 "spu_shift_operand" "r,W")))]
1913   ""
1914   "@
1915   shl<bh>\t%0,%1,%2
1916   shl<bh>i\t%0,%1,%2"
1917   [(set_attr "type" "fx3")])
1918
1919 (define_insn_and_split "ashldi3"
1920   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
1921         (ashift:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
1922                    (match_operand:SI 2 "spu_shift_operand" "r,I")))
1923    (clobber (match_scratch:SI 3 "=&r,X"))]
1924   ""
1925   "#"
1926   "reload_completed"
1927   [(set (match_dup:DI 0)
1928         (ashift:DI (match_dup:DI 1)
1929                    (match_dup:SI 2)))]
1930   {
1931     rtx op0 = gen_rtx_REG (TImode, REGNO (operands[0]));
1932     rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
1933     rtx op2 = operands[2];
1934     rtx op3 = operands[3];
1935
1936     if (GET_CODE (operands[2]) == REG)
1937       {
1938         emit_insn (gen_addsi3 (op3, op2, GEN_INT (64)));
1939         emit_insn (gen_rotlti3 (op0, op1, GEN_INT (64)));
1940         emit_insn (gen_shlqbybi_ti (op0, op0, op3));
1941         emit_insn (gen_shlqbi_ti (op0, op0, op3));
1942       }
1943     else
1944       {
1945         HOST_WIDE_INT val = INTVAL (operands[2]);
1946         emit_insn (gen_rotlti3 (op0, op1, GEN_INT (64)));
1947         emit_insn (gen_shlqby_ti (op0, op0, GEN_INT (val / 8 + 8)));
1948         if (val % 8)
1949           emit_insn (gen_shlqbi_ti (op0, op0, GEN_INT (val % 8)));
1950       }
1951     DONE;
1952   })
1953
1954 (define_expand "ashlti3"
1955   [(parallel [(set (match_operand:TI 0 "spu_reg_operand" "")
1956                    (ashift:TI (match_operand:TI 1 "spu_reg_operand" "")
1957                               (match_operand:SI 2 "spu_nonmem_operand" "")))
1958               (clobber (match_dup:TI 3))])]
1959   ""
1960   "if (GET_CODE (operands[2]) == CONST_INT)
1961     {
1962       emit_insn(gen_ashlti3_imm(operands[0], operands[1], operands[2]));
1963       DONE;
1964     }
1965    operands[3] = gen_reg_rtx (TImode);")
1966
1967 (define_insn_and_split "ashlti3_imm"
1968   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
1969         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
1970                    (match_operand:SI 2 "immediate_operand" "O,P")))]
1971   ""
1972   "@
1973    shlqbyi\t%0,%1,%2/8
1974    shlqbii\t%0,%1,%2"
1975   "!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
1976   [(set (match_dup:TI 0)
1977         (ashift:TI (match_dup:TI 1)
1978                    (match_dup:SI 3)))
1979    (set (match_dup:TI 0)
1980         (ashift:TI (match_dup:TI 0)
1981                    (match_dup:SI 4)))]
1982   {
1983     HOST_WIDE_INT val = INTVAL(operands[2]);
1984     operands[3] = GEN_INT (val&7);
1985     operands[4] = GEN_INT (val&0x78);
1986   }
1987   [(set_attr "type" "shuf,shuf")])
1988
1989 (define_insn_and_split "ashlti3_reg"
1990   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
1991         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r")
1992                    (match_operand:SI 2 "spu_reg_operand" "r")))
1993    (clobber (match_operand:TI 3 "spu_reg_operand" "=&r"))]
1994   ""
1995   "#"
1996   ""
1997   [(set (match_dup:TI 3)
1998         (ashift:TI (match_dup:TI 1)
1999                    (and:SI (match_dup:SI 2)
2000                            (const_int 7))))
2001    (set (match_dup:TI 0)
2002         (ashift:TI (match_dup:TI 3)
2003                    (and:SI (match_dup:SI 2)
2004                            (const_int -8))))]
2005   "")
2006
2007 (define_insn "shlqbybi_ti"
2008   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2009         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2010                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2011                            (const_int -8))))]
2012   ""
2013   "@
2014    shlqbybi\t%0,%1,%2
2015    shlqbyi\t%0,%1,%2/8"
2016   [(set_attr "type" "shuf,shuf")])
2017
2018 (define_insn "shlqbi_ti"
2019   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2020         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2021                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2022                            (const_int 7))))]
2023   ""
2024   "@
2025    shlqbi\t%0,%1,%2
2026    shlqbii\t%0,%1,%2"
2027   [(set_attr "type" "shuf,shuf")])
2028
2029 (define_insn "shlqby_ti"
2030   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2031         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2032                    (mult:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2033                             (const_int 8))))]
2034   ""
2035   "@
2036    shlqby\t%0,%1,%2
2037    shlqbyi\t%0,%1,%2"
2038   [(set_attr "type" "shuf,shuf")])
2039
2040 \f
2041 ;; lshr
2042
2043 (define_insn_and_split "lshr<mode>3"
2044   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2045         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2046                        (match_operand:VHSI 2 "spu_shift_operand" "r,W")))
2047    (clobber (match_scratch:VHSI 3 "=&r,X"))]
2048   ""
2049   "@
2050    #
2051    rot<bh>mi\t%0,%1,%N2"
2052   "reload_completed && GET_CODE (operands[2]) == REG"
2053   [(set (match_dup:VHSI 3)
2054         (neg:VHSI (match_dup:VHSI 2)))
2055    (set (match_dup:VHSI 0)
2056         (lshiftrt:VHSI (match_dup:VHSI 1)
2057                        (neg:VHSI (match_dup:VHSI 3))))]
2058   ""
2059   [(set_attr "type" "*,fx3")])
2060   
2061
2062 (define_insn "rotm_<mode>"
2063   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2064         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2065                        (neg:VHSI (match_operand:VHSI 2 "spu_shift_operand" "r,W"))))]
2066   ""
2067   "@
2068    rot<bh>m\t%0,%1,%2
2069    rot<bh>mi\t%0,%1,%2"
2070   [(set_attr "type" "fx3")])
2071  
2072 (define_expand "lshr<mode>3"
2073   [(parallel [(set (match_operand:DTI 0 "spu_reg_operand" "")
2074                    (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "")
2075                                  (match_operand:SI 2 "spu_nonmem_operand" "")))
2076               (clobber (match_dup:DTI 3))
2077               (clobber (match_dup:SI 4))
2078               (clobber (match_dup:SI 5))])]
2079   ""
2080   "if (GET_CODE (operands[2]) == CONST_INT)
2081     {
2082       emit_insn(gen_lshr<mode>3_imm(operands[0], operands[1], operands[2]));
2083       DONE;
2084     }
2085    operands[3] = gen_reg_rtx (<MODE>mode);
2086    operands[4] = gen_reg_rtx (SImode);
2087    operands[5] = gen_reg_rtx (SImode);")
2088
2089 (define_insn_and_split "lshr<mode>3_imm"
2090   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2091         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2092                       (match_operand:SI 2 "immediate_operand" "O,P")))]
2093   ""
2094   "@
2095    rotqmbyi\t%0,%1,%N2/8
2096    rotqmbii\t%0,%1,%N2"
2097   "!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
2098   [(set (match_dup:DTI 0)
2099         (lshiftrt:DTI (match_dup:DTI 1)
2100                       (match_dup:SI 4)))
2101    (set (match_dup:DTI 0)
2102         (lshiftrt:DTI (match_dup:DTI 0)
2103                       (match_dup:SI 5)))]
2104   {
2105     HOST_WIDE_INT val = INTVAL(operands[2]);
2106     operands[4] = GEN_INT (val&7);
2107     operands[5] = GEN_INT (val&0x78);
2108   }
2109   [(set_attr "type" "shuf,shuf")])
2110
2111 (define_insn_and_split "lshr<mode>3_reg"
2112   [(set (match_operand:DTI 0 "spu_reg_operand" "=r")
2113         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r")
2114                       (match_operand:SI 2 "spu_reg_operand" "r")))
2115    (clobber (match_operand:DTI 3 "spu_reg_operand" "=&r"))
2116    (clobber (match_operand:SI 4 "spu_reg_operand" "=&r"))
2117    (clobber (match_operand:SI 5 "spu_reg_operand" "=&r"))]
2118   ""
2119   "#"
2120   ""
2121   [(set (match_dup:DTI 3)
2122         (lshiftrt:DTI (match_dup:DTI 1)
2123                      (and:SI (neg:SI (match_dup:SI 4))
2124                              (const_int 7))))
2125    (set (match_dup:DTI 0)
2126         (lshiftrt:DTI (match_dup:DTI 3)
2127                      (and:SI (neg:SI (match_dup:SI 5))
2128                              (const_int -8))))]
2129   {
2130     emit_insn(gen_subsi3(operands[4], GEN_INT(0), operands[2]));
2131     emit_insn(gen_subsi3(operands[5], GEN_INT(7), operands[2]));
2132   })
2133
2134 (define_insn "rotqmbybi_<mode>"
2135   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2136         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2137                       (and:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2138                               (const_int -8))))]
2139   ""
2140   "@
2141    rotqmbybi\t%0,%1,%2
2142    rotqmbyi\t%0,%1,%2/8"
2143   [(set_attr "type" "shuf")])
2144
2145 (define_insn "rotqmbi_<mode>"
2146   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2147         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2148                       (and:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2149                               (const_int 7))))]
2150   ""
2151   "@
2152    rotqmbi\t%0,%1,%2
2153    rotqmbii\t%0,%1,%2"
2154   [(set_attr "type" "shuf")])
2155
2156 (define_insn "rotqmby_<mode>"
2157   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2158         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2159                       (mult:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2160                                (const_int 8))))]
2161   ""
2162   "@
2163    rotqmby\t%0,%1,%2
2164    rotqmbyi\t%0,%1,%2"
2165   [(set_attr "type" "shuf")])
2166
2167 \f
2168 ;; ashr
2169
2170 (define_insn_and_split "ashr<mode>3"
2171   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2172         (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2173                        (match_operand:VHSI 2 "spu_shift_operand" "r,W")))
2174    (clobber (match_scratch:VHSI 3 "=&r,X"))]
2175   ""
2176   "@
2177    #
2178    rotma<bh>i\t%0,%1,%N2"
2179   "reload_completed && GET_CODE (operands[2]) == REG"
2180   [(set (match_dup:VHSI 3)
2181         (neg:VHSI (match_dup:VHSI 2)))
2182    (set (match_dup:VHSI 0)
2183         (ashiftrt:VHSI (match_dup:VHSI 1)
2184                        (neg:VHSI (match_dup:VHSI 3))))]
2185   ""
2186   [(set_attr "type" "*,fx3")])
2187   
2188
2189 (define_insn "rotma_<mode>"
2190   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2191         (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2192                        (neg:VHSI (match_operand:VHSI 2 "spu_shift_operand" "r,W"))))]
2193   ""
2194   "@
2195    rotma<bh>\t%0,%1,%2
2196    rotma<bh>i\t%0,%1,%2"
2197   [(set_attr "type" "fx3")])
2198  
2199 (define_insn_and_split "ashrdi3"
2200   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2201         (ashiftrt:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2202                      (match_operand:SI 2 "spu_nonmem_operand" "r,I")))
2203    (clobber (match_scratch:TI 3 "=&r,&r"))
2204    (clobber (match_scratch:TI 4 "=&r,&r"))
2205    (clobber (match_scratch:SI 5 "=&r,&r"))]
2206   ""
2207   "#"
2208   "reload_completed"
2209   [(set (match_dup:DI 0)
2210         (ashiftrt:DI (match_dup:DI 1)
2211                      (match_dup:SI 2)))]
2212   {
2213     rtx op0 = gen_rtx_REG (TImode, REGNO (operands[0]));
2214     rtx op0v = gen_rtx_REG (V4SImode, REGNO (op0));
2215     rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
2216     rtx op1s = gen_rtx_REG (SImode, REGNO (op1));
2217     rtx op2 = operands[2];
2218     rtx op3 = operands[3];
2219     rtx op4 = operands[4];
2220     rtx op5 = operands[5];
2221
2222     if (GET_CODE (op2) == CONST_INT && INTVAL (op2) >= 63)
2223       {
2224         rtx op0s = gen_rtx_REG (SImode, REGNO (op0));
2225         emit_insn (gen_ashrsi3 (op0s, op1s, GEN_INT (32)));
2226         emit_insn (gen_spu_fsm (op0v, op0s));
2227       }
2228     else if (GET_CODE (op2) == CONST_INT && INTVAL (op2) >= 32)
2229       {
2230         rtx op0d = gen_rtx_REG (V2DImode, REGNO (op0));
2231         HOST_WIDE_INT val = INTVAL (op2);
2232         emit_insn (gen_lshrti3 (op0, op1, GEN_INT (32)));
2233         emit_insn (gen_spu_xswd (op0d, op0v));
2234         if (val > 32)
2235           emit_insn (gen_ashrv4si3 (op0v, op0v, spu_const (V4SImode, val - 32)));
2236       }
2237     else
2238       {
2239         rtx op3v = gen_rtx_REG (V4SImode, REGNO (op3));
2240         unsigned char arr[16] = {
2241           0xff, 0xff, 0xff, 0xff,
2242           0xff, 0xff, 0xff, 0xff,
2243           0x00, 0x00, 0x00, 0x00,
2244           0x00, 0x00, 0x00, 0x00
2245         };
2246
2247         emit_insn (gen_ashrsi3 (op5, op1s, GEN_INT (31)));
2248         emit_move_insn (op4, array_to_constant (TImode, arr));
2249         emit_insn (gen_spu_fsm (op3v, op5));
2250
2251         if (GET_CODE (operands[2]) == REG)
2252           {
2253             emit_insn (gen_selb (op4, op3, op1, op4));
2254             emit_insn (gen_negsi2 (op5, op2));
2255             emit_insn (gen_rotqbybi_ti (op0, op4, op5));
2256             emit_insn (gen_rotqbi_ti (op0, op0, op5));
2257           }
2258         else
2259           {
2260             HOST_WIDE_INT val = -INTVAL (op2);
2261             emit_insn (gen_selb (op0, op3, op1, op4));
2262             if ((val - 7) / 8)
2263               emit_insn (gen_rotqby_ti (op0, op0, GEN_INT ((val - 7) / 8)));
2264             if (val % 8)
2265               emit_insn (gen_rotqbi_ti (op0, op0, GEN_INT (val % 8)));
2266           }
2267       }
2268     DONE;
2269   })
2270
2271
2272 (define_expand "ashrti3"
2273   [(set (match_operand:TI 0 "spu_reg_operand" "")
2274         (ashiftrt:TI (match_operand:TI 1 "spu_reg_operand" "")
2275                      (match_operand:SI 2 "spu_nonmem_operand" "")))]
2276   ""
2277   {
2278     rtx sign_shift = gen_reg_rtx (SImode);
2279     rtx sign_mask = gen_reg_rtx (TImode);
2280     rtx sign_mask_v4si = gen_rtx_SUBREG (V4SImode, sign_mask, 0);
2281     rtx op1_v4si = spu_gen_subreg (V4SImode, operands[1]);
2282     rtx t = gen_reg_rtx (TImode);
2283     emit_insn (gen_subsi3 (sign_shift, GEN_INT (128), force_reg (SImode, operands[2])));
2284     emit_insn (gen_ashrv4si3 (sign_mask_v4si, op1_v4si, spu_const (V4SImode, 31)));
2285     emit_insn (gen_fsm_ti (sign_mask, sign_mask));
2286     emit_insn (gen_ashlti3 (sign_mask, sign_mask, sign_shift));
2287     emit_insn (gen_lshrti3 (t, operands[1], operands[2]));
2288     emit_insn (gen_iorti3 (operands[0], t, sign_mask));
2289     DONE;
2290   })
2291
2292 ;; fsm is used after rotam to replicate the sign across the whole register.
2293 (define_insn "fsm_ti"
2294   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2295         (unspec:TI [(match_operand:TI 1 "spu_reg_operand" "r")] UNSPEC_FSM))]
2296   ""
2297   "fsm\t%0,%1"
2298   [(set_attr "type" "shuf")])
2299
2300 \f
2301 ;; rotl
2302
2303 (define_insn "rotl<mode>3"
2304   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2305         (rotate:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2306                      (match_operand:VHSI 2 "spu_shift_operand" "r,W")))]
2307   ""
2308   "@
2309   rot<bh>\t%0,%1,%2
2310   rot<bh>i\t%0,%1,%2"
2311   [(set_attr "type" "fx3")])
2312
2313 (define_insn "rotlti3"
2314   [(set (match_operand:TI 0 "spu_reg_operand" "=&r,r,r,r")
2315         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r,r,r")
2316                    (match_operand:SI 2 "spu_nonmem_operand" "r,O,P,I")))]
2317   ""
2318   "@
2319   rotqbybi\t%0,%1,%2\;rotqbi\t%0,%0,%2
2320   rotqbyi\t%0,%1,%2/8
2321   rotqbii\t%0,%1,%2
2322   rotqbyi\t%0,%1,%2/8\;rotqbii\t%0,%0,%2%%8"
2323   [(set_attr "length" "8,4,4,8")
2324    (set_attr "type" "multi1,shuf,shuf,multi1")])
2325
2326 (define_insn "rotqbybi_ti"
2327   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2328         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2329                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2330                            (const_int -8))))]
2331   ""
2332   "@
2333   rotqbybi\t%0,%1,%2
2334   rotqbyi\t%0,%1,%2/8"
2335   [(set_attr "type" "shuf,shuf")])
2336
2337 (define_insn "rotqby_ti"
2338   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2339         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2340                    (mult:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2341                             (const_int 8))))]
2342   ""
2343   "@
2344   rotqby\t%0,%1,%2
2345   rotqbyi\t%0,%1,%2"
2346   [(set_attr "type" "shuf,shuf")])
2347
2348 (define_insn "rotqbi_ti"
2349   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2350         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2351                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2352                            (const_int 7))))]
2353   ""
2354   "@
2355   rotqbi\t%0,%1,%2
2356   rotqbii\t%0,%1,%2%%8"
2357   [(set_attr "type" "shuf,shuf")])
2358
2359 \f
2360 ;; struct extract/insert
2361 ;; We have to handle mem's because GCC will generate invalid SUBREG's
2362 ;; if it handles them.  We generate better code anyway.
2363
2364 (define_expand "extv"
2365   [(set (match_operand 0 "register_operand" "")
2366         (sign_extract (match_operand 1 "register_operand" "")
2367                       (match_operand:SI 2 "const_int_operand" "")
2368                       (match_operand:SI 3 "const_int_operand" "")))]
2369   ""
2370   { spu_expand_extv(operands, 0); DONE; })
2371
2372 (define_expand "extzv"
2373   [(set (match_operand 0 "register_operand" "")
2374         (zero_extract (match_operand 1 "register_operand" "")
2375                          (match_operand:SI 2 "const_int_operand" "")
2376                          (match_operand:SI 3 "const_int_operand" "")))]
2377   ""
2378   { spu_expand_extv(operands, 1); DONE; })
2379
2380 (define_expand "insv"
2381   [(set (zero_extract (match_operand 0 "register_operand" "")
2382                       (match_operand:SI 1 "const_int_operand" "")
2383                       (match_operand:SI 2 "const_int_operand" ""))
2384         (match_operand 3 "nonmemory_operand" ""))]
2385   ""
2386   { spu_expand_insv(operands); DONE; })
2387
2388 \f
2389 ;; String/block move insn.
2390 ;; Argument 0 is the destination
2391 ;; Argument 1 is the source
2392 ;; Argument 2 is the length
2393 ;; Argument 3 is the alignment
2394
2395 (define_expand "movstrsi"
2396   [(parallel [(set (match_operand:BLK 0 "" "")
2397                    (match_operand:BLK 1 "" ""))
2398               (use (match_operand:SI 2 "" ""))
2399               (use (match_operand:SI 3 "" ""))])]
2400   ""
2401   "
2402   {
2403     if (spu_expand_block_move (operands))
2404       DONE;
2405     else
2406       FAIL;
2407   }")
2408
2409 \f
2410 ;; jump
2411
2412 (define_insn "indirect_jump"
2413   [(set (pc) (match_operand:SI 0 "spu_reg_operand" "r"))]
2414   ""
2415   "bi\t%0"
2416   [(set_attr "type" "br")])
2417
2418 (define_insn "jump"
2419   [(set (pc)
2420         (label_ref (match_operand 0 "" "")))]
2421   ""
2422   "br\t%0"
2423   [(set_attr "type" "br")])
2424
2425 \f
2426 ;; return
2427
2428 ;; This will be used for leaf functions, that don't save any regs and
2429 ;; don't have locals on stack, maybe... that is for functions that
2430 ;; don't change $sp and don't need to save $lr. 
2431 (define_expand "return"
2432     [(return)]
2433   "direct_return()"
2434   "")
2435
2436 ;; used in spu_expand_epilogue to generate return from a function and
2437 ;; explicitly set use of $lr.
2438
2439 (define_insn "_return"
2440   [(return)]
2441   ""
2442   "bi\t$lr"
2443   [(set_attr "type" "br")])
2444
2445
2446 \f
2447 ;; ceq
2448
2449 (define_insn "ceq_<mode>"
2450   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
2451         (eq:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
2452                  (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
2453   ""
2454   "@
2455   ceq<bh>\t%0,%1,%2
2456   ceq<bh>i\t%0,%1,%2")
2457
2458 (define_insn_and_split "ceq_di"
2459   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2460         (eq:SI (match_operand:DI 1 "spu_reg_operand" "r")
2461                (match_operand:DI 2 "spu_reg_operand" "r")))]
2462   ""
2463   "#"
2464   "reload_completed"
2465   [(set (match_dup:SI 0)
2466         (eq:SI (match_dup:DI 1)
2467                (match_dup:DI 2)))]
2468   {
2469     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
2470     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
2471     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
2472     emit_insn (gen_ceq_v4si (op0, op1, op2));
2473     emit_insn (gen_spu_gb (op0, op0));
2474     emit_insn (gen_cgt_si (operands[0], operands[0], GEN_INT (11)));
2475     DONE;
2476   })
2477
2478
2479 ;; We provide the TI compares for completeness and because some parts of
2480 ;; gcc/libgcc use them, even though user code might never see it.
2481 (define_insn "ceq_ti"
2482   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2483         (eq:SI (match_operand:TI 1 "spu_reg_operand" "r")
2484                (match_operand:TI 2 "spu_reg_operand" "r")))]
2485   ""
2486   "ceq\t%0,%1,%2\;gb\t%0,%0\;ceqi\t%0,%0,15"
2487   [(set_attr "type" "multi0")
2488    (set_attr "length" "12")])
2489
2490 (define_insn "ceq_<mode>"
2491   [(set (match_operand:<f2i> 0 "spu_reg_operand" "=r")
2492         (eq:<f2i> (match_operand:VSF 1 "spu_reg_operand" "r")
2493                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
2494   ""
2495   "fceq\t%0,%1,%2")
2496
2497 (define_insn "cmeq_<mode>"
2498   [(set (match_operand:<f2i> 0 "spu_reg_operand" "=r")
2499         (eq:<f2i> (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "r"))
2500                   (abs:VSF (match_operand:VSF 2 "spu_reg_operand" "r"))))]
2501   ""
2502   "fcmeq\t%0,%1,%2")
2503
2504 (define_insn "ceq_vec"
2505   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2506         (eq:SI (match_operand 1 "spu_reg_operand" "r")
2507                (match_operand 2 "spu_reg_operand" "r")))]
2508   "VECTOR_MODE_P(GET_MODE(operands[1]))
2509    && GET_MODE(operands[1]) == GET_MODE(operands[2])"
2510   "ceq\t%0,%1,%2\;gb\t%0,%0\;ceqi\t%0,%0,15"
2511   [(set_attr "length" "12")])
2512
2513 \f
2514 ;; cgt
2515
2516 (define_insn "cgt_<mode>"
2517   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
2518         (gt:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
2519                   (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
2520   ""
2521   "@
2522   cgt<bh>\t%0,%1,%2
2523   cgt<bh>i\t%0,%1,%2")
2524
2525 (define_insn "cgt_di_m1" 
2526   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2527         (gt:SI (match_operand:DI 1 "spu_reg_operand" "r")
2528                (const_int -1)))]
2529   ""
2530   "cgti\t%0,%1,-1")
2531
2532 (define_insn_and_split "cgt_di" 
2533   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2534         (gt:SI (match_operand:DI 1 "spu_reg_operand" "r")
2535                (match_operand:DI 2 "spu_reg_operand" "r")))
2536    (clobber (match_scratch:V4SI 3 "=&r"))
2537    (clobber (match_scratch:V4SI 4 "=&r"))
2538    (clobber (match_scratch:V4SI 5 "=&r"))]
2539   ""
2540   "#"
2541   "reload_completed"
2542   [(set (match_dup:SI 0)
2543         (gt:SI (match_dup:DI 1)
2544                (match_dup:DI 2)))]
2545   {
2546     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
2547     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
2548     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
2549     rtx op3 = operands[3];
2550     rtx op4 = operands[4];
2551     rtx op5 = operands[5];
2552     rtx op3d = gen_rtx_REG (V2DImode, REGNO (operands[3]));
2553     emit_insn (gen_clgt_v4si (op3, op1, op2));
2554     emit_insn (gen_ceq_v4si (op4, op1, op2));
2555     emit_insn (gen_cgt_v4si (op5, op1, op2));
2556     emit_insn (gen_spu_xswd (op3d, op3));
2557     emit_insn (gen_selb (op0, op5, op3, op4));
2558     DONE;
2559   })
2560
2561 (define_insn "cgt_ti"
2562   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2563         (gt:SI (match_operand:TI 1 "spu_reg_operand" "r")
2564                (match_operand:TI 2 "spu_reg_operand" "r")))
2565    (clobber (match_scratch:V4SI 3 "=&r"))
2566    (clobber (match_scratch:V4SI 4 "=&r"))
2567    (clobber (match_scratch:V4SI 5 "=&r"))]
2568   ""
2569   "clgt\t%4,%1,%2\;\
2570 ceq\t%3,%1,%2\;\
2571 cgt\t%5,%1,%2\;\
2572 shlqbyi\t%0,%4,4\;\
2573 selb\t%0,%4,%0,%3\;\
2574 shlqbyi\t%0,%0,4\;\
2575 selb\t%0,%4,%0,%3\;\
2576 shlqbyi\t%0,%0,4\;\
2577 selb\t%0,%5,%0,%3"
2578   [(set_attr "type" "multi0")
2579    (set_attr "length" "36")])
2580
2581 (define_insn "cgt_<mode>"
2582   [(set (match_operand:<f2i> 0 "spu_reg_operand" "=r")
2583         (gt:<f2i> (match_operand:VSF 1 "spu_reg_operand" "r")
2584                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
2585   ""
2586   "fcgt\t%0,%1,%2")
2587
2588 (define_insn "cmgt_<mode>"
2589   [(set (match_operand:<f2i> 0 "spu_reg_operand" "=r")
2590         (gt:<f2i> (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "r"))
2591                   (abs:VSF (match_operand:VSF 2 "spu_reg_operand" "r"))))]
2592   ""
2593   "fcmgt\t%0,%1,%2")
2594
2595 \f
2596 ;; clgt
2597
2598 (define_insn "clgt_<mode>"
2599   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
2600         (gtu:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
2601                    (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
2602   ""
2603   "@
2604   clgt<bh>\t%0,%1,%2
2605   clgt<bh>i\t%0,%1,%2")
2606
2607 (define_insn_and_split "clgt_di" 
2608   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2609         (gtu:SI (match_operand:DI 1 "spu_reg_operand" "r")
2610                 (match_operand:DI 2 "spu_reg_operand" "r")))
2611    (clobber (match_scratch:V4SI 3 "=&r"))
2612    (clobber (match_scratch:V4SI 4 "=&r"))
2613    (clobber (match_scratch:V4SI 5 "=&r"))]
2614   ""
2615   "#"
2616   "reload_completed"
2617   [(set (match_dup:SI 0)
2618         (gtu:SI (match_dup:DI 1)
2619                 (match_dup:DI 2)))]
2620   {
2621     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
2622     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
2623     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
2624     rtx op3 = operands[3];
2625     rtx op4 = operands[4];
2626     rtx op5 = operands[5];
2627     rtx op5d = gen_rtx_REG (V2DImode, REGNO (operands[5]));
2628     emit_insn (gen_clgt_v4si (op3, op1, op2));
2629     emit_insn (gen_ceq_v4si (op4, op1, op2));
2630     emit_insn (gen_spu_xswd (op5d, op3));
2631     emit_insn (gen_selb (op0, op3, op5, op4));
2632     DONE;
2633   })
2634
2635 (define_insn "clgt_ti"
2636   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2637         (gtu:SI (match_operand:TI 1 "spu_reg_operand" "r")
2638                (match_operand:TI 2 "spu_reg_operand" "r")))
2639    (clobber (match_scratch:V4SI 3 "=&r"))
2640    (clobber (match_scratch:V4SI 4 "=&r"))]
2641   ""
2642   "ceq\t%3,%1,%2\;\
2643 clgt\t%4,%1,%2\;\
2644 shlqbyi\t%0,%4,4\;\
2645 selb\t%0,%4,%0,%3\;\
2646 shlqbyi\t%0,%0,4\;\
2647 selb\t%0,%4,%0,%3\;\
2648 shlqbyi\t%0,%0,4\;\
2649 selb\t%0,%4,%0,%3"
2650   [(set_attr "type" "multi0")
2651    (set_attr "length" "32")])
2652
2653 \f
2654 ;; branches
2655
2656 (define_insn ""
2657   [(set (pc)
2658         (if_then_else (match_operator 1 "branch_comparison_operator"
2659                                       [(match_operand 2
2660                                                       "spu_reg_operand" "r")
2661                                        (const_int 0)])
2662                       (label_ref (match_operand 0 "" ""))
2663                       (pc)))]
2664   ""
2665   "br%b2%b1z\t%2,%0"
2666   [(set_attr "type" "br")])
2667
2668 (define_insn ""
2669   [(set (pc)
2670         (if_then_else (match_operator 0 "branch_comparison_operator"
2671                                       [(match_operand 1
2672                                                       "spu_reg_operand" "r")
2673                                        (const_int 0)])
2674                       (return)
2675                       (pc)))]
2676   "direct_return ()"
2677   "bi%b1%b0z\t%1,$lr"
2678   [(set_attr "type" "br")])
2679
2680 (define_insn ""
2681   [(set (pc)
2682         (if_then_else (match_operator 1 "branch_comparison_operator"
2683                                       [(match_operand 2
2684                                                       "spu_reg_operand" "r")
2685                                        (const_int 0)])
2686                       (pc)
2687                       (label_ref (match_operand 0 "" ""))))]
2688   ""
2689   "br%b2%b1z\t%2,%0"
2690   [(set_attr "type" "br")])
2691
2692 (define_insn ""
2693   [(set (pc)
2694         (if_then_else (match_operator 0 "branch_comparison_operator"
2695                                       [(match_operand 1
2696                                                       "spu_reg_operand" "r")
2697                                        (const_int 0)])
2698                       (pc)
2699                       (return)))]
2700   "direct_return ()"
2701   "bi%b1%b0z\t%1,$lr"
2702   [(set_attr "type" "br")])
2703
2704 \f
2705 ;; Compare insns are next.  Note that the spu has two types of compares,
2706 ;; signed & unsigned, and one type of branch.
2707 ;;
2708 ;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc
2709 ;; insns, and branches.  We store the operands of compares until we see
2710 ;; how it is used.
2711
2712 (define_expand "cmp<mode>"
2713   [(set (cc0)
2714         (compare (match_operand:VQHSI 0 "spu_reg_operand" "")
2715                  (match_operand:VQHSI 1 "spu_nonmem_operand" "")))]
2716   ""
2717   {
2718     spu_compare_op0 = operands[0];
2719     spu_compare_op1 = operands[1];
2720     DONE;
2721   })
2722
2723 (define_expand "cmp<mode>"
2724   [(set (cc0)
2725         (compare (match_operand:DTI 0 "spu_reg_operand" "")
2726                  (match_operand:DTI 1 "spu_reg_operand" "")))]
2727   ""
2728   {
2729     spu_compare_op0 = operands[0];
2730     spu_compare_op1 = operands[1];
2731     DONE;
2732   })
2733
2734 (define_expand "cmp<mode>"
2735   [(set (cc0)
2736         (compare (match_operand:VSF 0 "spu_reg_operand" "")
2737                  (match_operand:VSF 1 "spu_reg_operand" "")))]
2738   ""
2739   {
2740     spu_compare_op0 = operands[0];
2741     spu_compare_op1 = operands[1];
2742     DONE;
2743   })
2744
2745 \f
2746 ;; branch on condition
2747
2748 (define_expand "beq"
2749   [(use (match_operand 0 "" ""))]
2750   ""
2751   { spu_emit_branch_or_set (0, EQ, operands); DONE; })
2752
2753 (define_expand "bne"
2754   [(use (match_operand 0 "" ""))]
2755   ""
2756   { spu_emit_branch_or_set (0, NE, operands); DONE; })
2757
2758 (define_expand "bge"
2759   [(use (match_operand 0 "" ""))]
2760   ""
2761   { spu_emit_branch_or_set (0, GE, operands); DONE; })
2762
2763 (define_expand "bgt"
2764   [(use (match_operand 0 "" ""))]
2765   ""
2766   { spu_emit_branch_or_set (0, GT, operands); DONE; })
2767
2768 (define_expand "ble"
2769   [(use (match_operand 0 "" ""))]
2770   ""
2771   { spu_emit_branch_or_set (0, LE, operands); DONE; })
2772
2773 (define_expand "blt"
2774   [(use (match_operand 0 "" ""))]
2775   ""
2776   { spu_emit_branch_or_set (0, LT, operands); DONE; })
2777
2778 (define_expand "bgeu"
2779   [(use (match_operand 0 "" ""))]
2780   ""
2781   { spu_emit_branch_or_set (0, GEU, operands); DONE; })
2782
2783 (define_expand "bgtu"
2784   [(use (match_operand 0 "" ""))]
2785   ""
2786   { spu_emit_branch_or_set (0, GTU, operands); DONE; })
2787
2788 (define_expand "bleu"
2789   [(use (match_operand 0 "" ""))]
2790   ""
2791   { spu_emit_branch_or_set (0, LEU, operands); DONE; })
2792
2793 (define_expand "bltu"
2794   [(use (match_operand 0 "" ""))]
2795   ""
2796   { spu_emit_branch_or_set (0, LTU, operands); DONE; })
2797
2798 \f
2799 ;; set on condition
2800
2801 (define_expand "seq"
2802   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
2803   ""
2804   { spu_emit_branch_or_set (1, EQ, operands); DONE; })
2805
2806 (define_expand "sne"
2807   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
2808   ""
2809   { spu_emit_branch_or_set (1, NE, operands); DONE; })
2810
2811 (define_expand "sgt"
2812   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
2813   ""
2814   { spu_emit_branch_or_set (1, GT, operands); DONE; })
2815
2816 (define_expand "slt"
2817   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
2818   ""
2819   { spu_emit_branch_or_set (1, LT, operands); DONE; })
2820
2821 (define_expand "sge"
2822   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
2823   ""
2824   { spu_emit_branch_or_set (1, GE, operands); DONE; })
2825
2826 (define_expand "sle"
2827   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
2828   ""
2829   { spu_emit_branch_or_set (1, LE, operands); DONE; })
2830
2831 (define_expand "sgtu"
2832   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
2833   ""
2834   { spu_emit_branch_or_set (1, GTU, operands); DONE; })
2835
2836 (define_expand "sltu"
2837   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
2838   ""
2839   { spu_emit_branch_or_set (1, LTU, operands); DONE; })
2840
2841 (define_expand "sgeu"
2842   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
2843   ""
2844   { spu_emit_branch_or_set (1, GEU, operands); DONE; })
2845
2846 (define_expand "sleu"
2847   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
2848   ""
2849   { spu_emit_branch_or_set (1, LEU, operands); DONE; })
2850
2851 \f
2852 ;; conditional move
2853
2854 ;; Define this first one so HAVE_conditional_move is defined.
2855 (define_insn "movcc_dummy"
2856   [(set (match_operand 0 "" "")
2857        (if_then_else (match_operand 1 "" "")
2858                      (match_operand 2 "" "")
2859                      (match_operand 3 "" "")))]
2860   "!operands[0]"
2861   "")
2862
2863 (define_expand "mov<mode>cc"
2864   [(set (match_operand:ALL 0 "spu_reg_operand" "")
2865         (if_then_else:ALL (match_operand 1 "comparison_operator" "")
2866                       (match_operand:ALL 2 "spu_reg_operand" "")
2867                       (match_operand:ALL 3 "spu_reg_operand" "")))]
2868   ""
2869   {
2870     spu_emit_branch_or_set(2, GET_CODE(operands[1]), operands);
2871     DONE;
2872   })
2873
2874 ;; This pattern is used when the result of a compare is not large
2875 ;; enough to use in a selb when expanding conditional moves.
2876 (define_expand "extend_compare"
2877   [(set (match_operand 0 "spu_reg_operand" "=r")
2878         (unspec [(match_operand 1 "spu_reg_operand" "r")] UNSPEC_EXTEND_CMP))]
2879   ""
2880   {
2881     emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2882                             gen_rtx_UNSPEC (GET_MODE (operands[0]),
2883                                             gen_rtvec (1, operands[1]),
2884                                             UNSPEC_EXTEND_CMP)));
2885     DONE;
2886   })
2887
2888 (define_insn "extend_compare<mode>"
2889   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2890         (unspec:ALL [(match_operand 1 "spu_reg_operand" "r")] UNSPEC_EXTEND_CMP))]
2891   "operands"
2892   "fsm\t%0,%1"
2893   [(set_attr "type" "shuf")])
2894
2895 \f
2896 ;; case
2897
2898 ;; operand 0 is index
2899 ;; operand 1 is the minimum bound
2900 ;; operand 2 is the maximum bound - minimum bound + 1
2901 ;; operand 3 is CODE_LABEL for the table;
2902 ;; operand 4 is the CODE_LABEL to go to if index out of range.
2903 (define_expand "casesi"
2904   [(match_operand:SI 0 "spu_reg_operand" "")
2905    (match_operand:SI 1 "immediate_operand" "")
2906    (match_operand:SI 2 "immediate_operand" "")
2907    (match_operand 3 "" "")
2908    (match_operand 4 "" "")]
2909   ""
2910   {
2911     rtx table = gen_reg_rtx (SImode);
2912     rtx index = gen_reg_rtx (SImode);
2913     rtx sindex = gen_reg_rtx (SImode);
2914     rtx addr = gen_reg_rtx (Pmode);
2915
2916     emit_move_insn (table, gen_rtx_LABEL_REF (SImode, operands[3]));
2917
2918     emit_insn (gen_subsi3(index, operands[0], force_reg(SImode, operands[1])));
2919     emit_insn (gen_ashlsi3(sindex, index, GEN_INT (2)));
2920     emit_move_insn (addr, gen_rtx_MEM (SImode,
2921                                        gen_rtx_PLUS (SImode, table, sindex)));
2922     if (flag_pic)
2923       emit_insn (gen_addsi3 (addr, addr, table));
2924
2925     emit_cmp_and_jump_insns (index, operands[2], GTU, NULL_RTX, SImode, 1, operands[4]);
2926     emit_jump_insn (gen_tablejump (addr, operands[3]));
2927     DONE;
2928   })
2929
2930 (define_insn "tablejump"
2931   [(set (pc) (match_operand:SI 0 "spu_reg_operand" "r"))
2932    (use (label_ref (match_operand 1 "" "")))]
2933   ""
2934   "bi\t%0"
2935   [(set_attr "type" "br")])
2936
2937 \f
2938 ;; call
2939
2940 ;; Note that operand 1 is total size of args, in bytes,
2941 ;; and what the call insn wants is the number of words.
2942 (define_expand "sibcall"
2943   [(parallel
2944     [(call (match_operand:QI 0 "call_operand" "")
2945            (match_operand:QI 1 "" ""))
2946      (use (reg:SI 0))])]
2947   ""
2948   {
2949     if (! call_operand (operands[0], QImode))
2950       XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
2951   })
2952
2953 (define_insn "_sibcall"
2954   [(parallel
2955     [(call (match_operand:QI 0 "call_operand" "R,S")
2956            (match_operand:QI 1 "" "i,i"))
2957      (use (reg:SI 0))])]
2958   "SIBLING_CALL_P(insn)"
2959   "@
2960    bi\t%i0
2961    br\t%0"
2962    [(set_attr "type" "br,br")])
2963
2964 (define_expand "sibcall_value"
2965   [(parallel
2966     [(set (match_operand 0 "" "")
2967           (call (match_operand:QI 1 "call_operand" "")
2968                 (match_operand:QI 2 "" "")))
2969      (use (reg:SI 0))])]
2970   ""
2971   {
2972     if (! call_operand (operands[1], QImode))
2973       XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
2974   })
2975
2976 (define_insn "_sibcall_value"
2977   [(parallel
2978     [(set (match_operand 0 "" "")
2979           (call (match_operand:QI 1 "call_operand" "R,S")
2980                 (match_operand:QI 2 "" "i,i")))
2981      (use (reg:SI 0))])]
2982   "SIBLING_CALL_P(insn)"
2983   "@
2984    bi\t%i1
2985    br\t%1"
2986    [(set_attr "type" "br,br")])
2987
2988 ;; Note that operand 1 is total size of args, in bytes,
2989 ;; and what the call insn wants is the number of words.
2990 (define_expand "call"
2991   [(parallel
2992     [(call (match_operand:QI 0 "call_operand" "")
2993            (match_operand:QI 1 "" ""))
2994      (clobber (reg:SI 0))
2995      (clobber (reg:SI 130))])]
2996   ""
2997   {
2998     if (! call_operand (operands[0], QImode))
2999       XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
3000   })
3001
3002 (define_insn "_call"
3003   [(parallel
3004     [(call (match_operand:QI 0 "call_operand" "R,S,T")
3005            (match_operand:QI 1 "" "i,i,i"))
3006      (clobber (reg:SI 0))
3007      (clobber (reg:SI 130))])]
3008   ""
3009   "@
3010    bisl\t$lr,%i0
3011    brsl\t$lr,%0
3012    brasl\t$lr,%0"
3013    [(set_attr "type" "br")])
3014
3015 (define_expand "call_value"
3016   [(parallel
3017     [(set (match_operand 0 "" "")
3018           (call (match_operand:QI 1 "call_operand" "")
3019                 (match_operand:QI 2 "" "")))
3020      (clobber (reg:SI 0))
3021      (clobber (reg:SI 130))])]
3022   ""
3023   {
3024     if (! call_operand (operands[1], QImode))
3025       XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
3026   })
3027
3028 (define_insn "_call_value"
3029   [(parallel
3030     [(set (match_operand 0 "" "")
3031           (call (match_operand:QI 1 "call_operand" "R,S,T")
3032                 (match_operand:QI 2 "" "i,i,i")))
3033      (clobber (reg:SI 0))
3034      (clobber (reg:SI 130))])]
3035   ""
3036   "@
3037    bisl\t$lr,%i1
3038    brsl\t$lr,%1
3039    brasl\t$lr,%1"
3040    [(set_attr "type" "br")])
3041
3042 (define_expand "untyped_call"
3043   [(parallel [(call (match_operand 0 "" "")
3044                     (const_int 0))
3045               (match_operand 1 "" "")
3046               (match_operand 2 "" "")])]
3047   ""
3048   {
3049     int i;
3050     rtx reg = gen_rtx_REG (TImode, 3);
3051
3052     /* We need to use call_value so the return value registers don't get
3053      * clobbered. */
3054     emit_call_insn (gen_call_value (reg, operands[0], const0_rtx));
3055
3056     for (i = 0; i < XVECLEN (operands[2], 0); i++)
3057       {
3058         rtx set = XVECEXP (operands[2], 0, i);
3059         emit_move_insn (SET_DEST (set), SET_SRC (set));
3060       }
3061
3062     /* The optimizer does not know that the call sets the function value
3063        registers we stored in the result block.  We avoid problems by
3064        claiming that all hard registers are used and clobbered at this
3065        point.  */
3066     emit_insn (gen_blockage ());
3067
3068     DONE;
3069   })
3070
3071 \f
3072 ;; Patterns used for splitting and combining.
3073
3074 \f
3075 ;; Function prologue and epilogue.
3076
3077 (define_expand "prologue"
3078   [(const_int 1)]
3079   ""
3080   { spu_expand_prologue (); DONE; })
3081
3082 ;; "blockage" is only emited in epilogue.  This is what it took to
3083 ;; make "basic block reordering" work with the insns sequence
3084 ;; generated by the spu_expand_epilogue (taken from mips.md)
3085
3086 (define_insn "blockage"
3087   [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
3088   ""
3089   ""
3090   [(set_attr "length" "0")])
3091
3092 (define_expand "epilogue"
3093   [(const_int 2)]
3094   ""
3095   { spu_expand_epilogue (false); DONE; })
3096
3097 (define_expand "sibcall_epilogue"
3098   [(const_int 2)]
3099   ""
3100   { spu_expand_epilogue (true); DONE; })
3101
3102 \f
3103 ;; stack manipulations
3104
3105 ;; An insn to allocate new stack space for dynamic use (e.g., alloca).
3106 ;; We move the back-chain and decrement the stack pointer.
3107 (define_expand "allocate_stack"
3108   [(set (match_operand 0 "spu_reg_operand" "")
3109         (minus (reg 1) (match_operand 1 "spu_nonmem_operand" "")))
3110    (set (reg 1)
3111         (minus (reg 1) (match_dup 1)))]
3112   ""
3113   "spu_allocate_stack (operands[0], operands[1]); DONE;")
3114
3115 ;; These patterns say how to save and restore the stack pointer.  We need not
3116 ;; save the stack pointer at function or block level since we are careful to
3117 ;; preserve the backchain.  Doing nothing at block level means the stack space
3118 ;; is allocated until the end of the function.  This is currently safe to do
3119 ;; because gcc uses the frame pointer for the whole function, so the worst that
3120 ;; happens is wasted stack space.  That could be bad if a VLA is declared in a
3121 ;; loop, because new space will be allocated every iteration, but users can
3122 ;; work around that case.  Ideally we could detect when we are in a loop and
3123 ;; generate the more complicated code in that case.
3124 ;;
3125 ;; For nonlocal gotos, we must save both the stack pointer and its
3126 ;; backchain and restore both.  Note that in the nonlocal case, the
3127 ;; save area is a memory location.
3128
3129 (define_expand "save_stack_function"
3130   [(match_operand 0 "general_operand" "")
3131    (match_operand 1 "general_operand" "")]
3132   ""
3133   "DONE;")
3134
3135 (define_expand "restore_stack_function"
3136   [(match_operand 0 "general_operand" "")
3137    (match_operand 1 "general_operand" "")]
3138   ""
3139   "DONE;")
3140
3141 (define_expand "save_stack_block"
3142   [(match_operand 0 "general_operand" "")
3143    (match_operand 1 "general_operand" "")]
3144   ""
3145   "DONE; ")
3146
3147 (define_expand "restore_stack_block"
3148   [(use (match_operand 0 "spu_reg_operand" ""))
3149    (set (match_dup 2) (match_dup 3))
3150    (set (match_dup 0) (match_operand 1 "spu_reg_operand" ""))
3151    (set (match_dup 3) (match_dup 2))]
3152   ""
3153   "DONE;")
3154
3155 (define_expand "save_stack_nonlocal"
3156   [(match_operand 0 "memory_operand" "")
3157    (match_operand 1 "spu_reg_operand" "")]
3158   ""
3159   "
3160   {
3161     rtx temp = gen_reg_rtx (Pmode);
3162
3163     /* Copy the backchain to the first word, sp to the second.  We need to
3164        save the back chain because __builtin_apply appears to clobber it. */
3165     emit_move_insn (temp, gen_rtx_MEM (Pmode, operands[1]));
3166     emit_move_insn (adjust_address_nv (operands[0], SImode, 0), temp);
3167     emit_move_insn (adjust_address_nv (operands[0], SImode, 4), operands[1]);
3168     DONE;
3169   }")
3170
3171 (define_expand "restore_stack_nonlocal"
3172   [(match_operand 0 "spu_reg_operand" "")
3173    (match_operand 1 "memory_operand" "")]
3174   ""
3175   "
3176   {
3177     spu_restore_stack_nonlocal(operands[0], operands[1]);
3178     DONE;
3179   }")
3180
3181 \f
3182 ;; vector patterns
3183
3184 ;; Vector initialization
3185 (define_expand "vec_init<mode>"
3186   [(match_operand:V 0 "register_operand" "")
3187    (match_operand 1 "" "")]
3188   ""
3189   {
3190     spu_expand_vector_init (operands[0], operands[1]);
3191     DONE;
3192   })
3193
3194 (define_expand "vec_set<mode>"
3195   [(use (match_operand:SI 2 "spu_nonmem_operand" ""))
3196    (set (match_dup:TI 3)
3197         (unspec:TI [(match_dup:SI 4)
3198                     (match_dup:SI 5)
3199                     (match_dup:SI 6)] UNSPEC_CPAT))
3200    (set (match_operand:V 0 "spu_reg_operand" "")
3201         (unspec:V [(match_operand:<inner> 1 "spu_reg_operand" "")
3202                    (match_dup:V 0)
3203                    (match_dup:TI 3)] UNSPEC_SHUFB))]
3204   ""
3205   {
3206     HOST_WIDE_INT size = GET_MODE_SIZE (<inner>mode);
3207     rtx offset = GEN_INT (INTVAL (operands[2]) * size);
3208     operands[3] = gen_reg_rtx (TImode);
3209     operands[4] = stack_pointer_rtx;
3210     operands[5] = offset;
3211     operands[6] = GEN_INT (size);
3212   })
3213
3214 (define_expand "vec_extract<mode>"
3215   [(set (match_operand:<inner> 0 "spu_reg_operand" "=r")
3216         (vec_select:<inner> (match_operand:V 1 "spu_reg_operand" "r")
3217                             (parallel [(match_operand 2 "const_int_operand" "i")])))]
3218   ""
3219   {
3220     if ((INTVAL (operands[2]) * <vmult> + <voff>) % 16 == 0)
3221       {
3222         emit_insn (gen_spu_convert (operands[0], operands[1]));
3223         DONE;
3224       }
3225   })
3226
3227 (define_insn "_vec_extract<mode>"
3228   [(set (match_operand:<inner> 0 "spu_reg_operand" "=r")
3229         (vec_select:<inner> (match_operand:V 1 "spu_reg_operand" "r")
3230                             (parallel [(match_operand 2 "const_int_operand" "i")])))]
3231   ""
3232   "rotqbyi\t%0,%1,(%2*<vmult>+<voff>)%%16"
3233   [(set_attr "type" "shuf")])
3234
3235 \f
3236 ;; misc
3237
3238 (define_expand "shufb"
3239   [(set (match_operand 0 "spu_reg_operand" "")
3240         (unspec [(match_operand 1 "spu_reg_operand" "")
3241                  (match_operand 2 "spu_reg_operand" "")
3242                  (match_operand:TI 3 "spu_reg_operand" "")] UNSPEC_SHUFB))]
3243   ""
3244   {
3245     rtx s = gen__shufb (operands[0], operands[1], operands[2], operands[3]);
3246     PUT_MODE (SET_SRC (s), GET_MODE (operands[0]));
3247     emit_insn (s);
3248     DONE;
3249   })
3250
3251 (define_insn "_shufb"
3252   [(set (match_operand 0 "spu_reg_operand" "=r")
3253         (unspec [(match_operand 1 "spu_reg_operand" "r")
3254                  (match_operand 2 "spu_reg_operand" "r")
3255                  (match_operand:TI 3 "spu_reg_operand" "r")] UNSPEC_SHUFB))]
3256   "operands"
3257   "shufb\t%0,%1,%2,%3"
3258   [(set_attr "type" "shuf")])
3259
3260 (define_insn "nop"
3261   [(unspec_volatile [(const_int 0)] UNSPEC_NOP)]
3262   ""
3263   "nop"
3264   [(set_attr "type" "nop")])
3265
3266 (define_insn "nopn"
3267   [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "K")] UNSPEC_NOP)]
3268   ""
3269   "nop\t%0"
3270   [(set_attr "type" "nop")])
3271
3272 (define_insn "lnop"
3273   [(unspec_volatile [(const_int 0)] UNSPEC_LNOP)]
3274   ""
3275   "lnop"
3276   [(set_attr "type" "lnop")])
3277
3278 (define_insn "iprefetch"
3279   [(unspec [(const_int 0)] UNSPEC_IPREFETCH)]
3280   ""
3281   "hbrp"
3282   [(set_attr "type" "iprefetch")])
3283
3284 (define_insn "hbr"
3285   [(set (reg:SI 130)
3286         (unspec:SI [(match_operand:SI 0 "immediate_operand" "s,s,s")
3287                     (match_operand:SI 1 "nonmemory_operand" "r,s,i")] UNSPEC_HBR))
3288    (unspec [(const_int 0)] UNSPEC_HBR)]
3289   ""
3290   "@
3291    hbr\t%0,%1
3292    hbrr\t%0,%1
3293    hbra\t%0,%1"
3294   [(set_attr "type" "hbr")])
3295
3296 (define_insn "sync"
3297   [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)
3298    (clobber (mem:BLK (scratch)))]
3299   ""
3300   "sync"
3301   [(set_attr "type" "br")])
3302
3303 (define_insn "syncc"
3304   [(unspec_volatile [(const_int 1)] UNSPEC_SYNC)
3305    (clobber (mem:BLK (scratch)))]
3306   ""
3307   "syncc"
3308   [(set_attr "type" "br")])
3309
3310 (define_insn "dsync"
3311   [(unspec_volatile [(const_int 2)] UNSPEC_SYNC)
3312    (clobber (mem:BLK (scratch)))]
3313   ""
3314   "dsync"
3315   [(set_attr "type" "br")])
3316
3317 \f
3318 ;; convert between any two modes, avoiding any GCC assumptions
3319 (define_expand "spu_convert"
3320   [(set (match_operand 0 "spu_reg_operand" "")
3321         (unspec [(match_operand 1 "spu_reg_operand" "")] UNSPEC_CONVERT))]
3322   ""
3323   {
3324     rtx c = gen__spu_convert (operands[0], operands[1]);
3325     PUT_MODE (SET_SRC (c), GET_MODE (operands[0]));
3326     emit_insn (c);
3327     DONE;
3328   })
3329
3330 (define_insn "_spu_convert"
3331   [(set (match_operand 0 "spu_reg_operand" "=r")
3332         (unspec [(match_operand 1 "spu_reg_operand" "0")] UNSPEC_CONVERT))]
3333   "operands"
3334   ""
3335   [(set_attr "type" "convert")
3336    (set_attr "length" "0")])
3337
3338 (define_peephole2
3339   [(set (match_operand 0 "spu_reg_operand")
3340         (unspec [(match_operand 1 "spu_reg_operand")] UNSPEC_CONVERT))]
3341   ""
3342   [(use (const_int 0))]
3343   "")
3344
3345 \f
3346 ;;
3347 (include "spu-builtins.md")
3348
3349   
3350 (define_expand "smaxv4sf3"
3351   [(set (match_operand:V4SF 0 "register_operand" "=r")
3352         (smax:V4SF (match_operand:V4SF 1 "register_operand" "r")
3353                  (match_operand:V4SF 2 "register_operand" "r")))]
3354   ""
3355   "
3356 {
3357   rtx mask = gen_reg_rtx (V4SImode);
3358
3359   emit_insn (gen_cgt_v4sf (mask, operands[1], operands[2]));
3360   emit_insn (gen_selb (operands[0], operands[2], operands[1], mask));
3361   DONE;
3362 }") 
3363
3364 (define_expand "sminv4sf3"
3365   [(set (match_operand:V4SF 0 "register_operand" "=r")
3366         (smax:V4SF (match_operand:V4SF 1 "register_operand" "r")
3367                  (match_operand:V4SF 2 "register_operand" "r")))]
3368   ""
3369   "
3370 {
3371   rtx mask = gen_reg_rtx (V4SImode);
3372
3373   emit_insn (gen_cgt_v4sf (mask, operands[1], operands[2]));
3374   emit_insn (gen_selb (operands[0], operands[1], operands[2], mask));
3375   DONE;
3376 }")