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