OSDN Git Service

2007-02-21 Trevor Smigiel <trevor_smigiel@playstation.sony.com>
[pf3gnuchains/gcc-fork.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 behavior of the double precision is that both pipes stall
59 ;; for 6 cycles and 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_SET_INTR       40)
138  (UNSPEC_FSCRRD         42)
139  (UNSPEC_FSCRWR         43)
140  (UNSPEC_MFSPR          44)
141  (UNSPEC_MTSPR          45)
142  (UNSPEC_RDCH           46)
143  (UNSPEC_RCHCNT         47)
144  (UNSPEC_WRCH           48)
145  (UNSPEC_SPU_REALIGN_LOAD 49)
146  (UNSPEC_SPU_MASK_FOR_LOAD 50)
147 ])
148
149 (include "predicates.md")
150 (include "constraints.md")
151
152 \f
153 ;; Mode macros
154
155 (define_mode_macro ALL [QI V16QI
156                         HI V8HI
157                         SI V4SI
158                         DI V2DI
159                         TI
160                         SF V4SF
161                         DF V2DF])
162
163 ; Everything except DI and TI which are handled separately because
164 ; they need different constraints to correctly test VOIDmode constants
165 (define_mode_macro MOV [QI V16QI
166                         HI V8HI
167                         SI V4SI
168                         V2DI
169                         SF V4SF
170                         DF V2DF])
171
172 (define_mode_macro DTI  [DI TI])
173
174 (define_mode_macro VINT [QI V16QI
175                          HI V8HI
176                          SI V4SI
177                          DI V2DI
178                          TI])
179
180 (define_mode_macro VQHSI [QI V16QI
181                           HI V8HI
182                           SI V4SI])
183
184 (define_mode_macro VHSI [HI V8HI
185                          SI V4SI])
186
187 (define_mode_macro VSDF [SF V4SF
188                          DF V2DF])
189
190 (define_mode_macro VSI [SI V4SI])
191 (define_mode_macro VDI [DI V2DI])
192 (define_mode_macro VSF [SF V4SF])
193 (define_mode_macro VDF [DF V2DF])
194
195 (define_mode_attr bh  [(QI "b")  (V16QI "b")
196                        (HI "h")  (V8HI "h")
197                        (SI "")   (V4SI "")])
198
199 (define_mode_attr d   [(SF "")   (V4SF "")
200                        (DF "d")  (V2DF "d")])
201 (define_mode_attr d6  [(SF "6")  (V4SF "6")
202                        (DF "d")  (V2DF "d")])
203 (define_mode_attr f2i [(SF "SI") (V4SF "V4SI")
204                        (DF "DI") (V2DF "V2DI")])
205
206 (define_mode_attr umask  [(HI "f")  (V8HI "f")
207                           (SI "g")  (V4SI "g")])
208 (define_mode_attr nmask  [(HI "F")  (V8HI "F")
209                           (SI "G")  (V4SI "G")])
210
211 ;; Used for carry and borrow instructions.
212 (define_mode_macro CBOP  [SI DI V4SI V2DI])
213
214 ;; Used in vec_set and vec_extract
215 (define_mode_macro V [V2DI V4SI V8HI V16QI V2DF V4SF])
216 (define_mode_attr inner  [(V16QI "QI")
217                           (V8HI  "HI")
218                           (V4SI  "SI")
219                           (V2DI  "DI")
220                           (V4SF  "SF")
221                           (V2DF  "DF")])
222 (define_mode_attr vmult  [(V16QI "1")
223                           (V8HI  "2")
224                           (V4SI  "4")
225                           (V2DI  "8")
226                           (V4SF  "4")
227                           (V2DF  "8")])
228 (define_mode_attr voff   [(V16QI "13")
229                           (V8HI  "14")
230                           (V4SI  "0")
231                           (V2DI  "0")
232                           (V4SF  "0")
233                           (V2DF  "0")])
234
235 \f
236 ;; mov
237
238 (define_expand "mov<mode>"
239   [(set (match_operand:ALL 0 "spu_nonimm_operand" "=r,r,r,m")
240         (match_operand:ALL 1 "general_operand" "r,i,m,r"))]
241   ""
242   {
243     if (spu_expand_mov(operands, <MODE>mode))
244       DONE;
245   })
246
247 (define_split 
248   [(set (match_operand 0 "spu_reg_operand")
249         (match_operand 1 "immediate_operand"))]
250
251   ""
252   [(set (match_dup 0)
253         (high (match_dup 1)))
254    (set (match_dup 0)
255         (lo_sum (match_dup 0)
256                 (match_dup 1)))]
257   {
258     if (spu_split_immediate (operands))
259       DONE;
260     FAIL;
261   })
262
263 (define_insn "pic"
264   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
265         (match_operand:SI 1 "immediate_operand" "s"))
266    (use (const_int 0))]
267   "flag_pic"
268   "ila\t%0,%%pic(%1)")
269
270 ;; Whenever a function generates the 'pic' pattern above we need to
271 ;; load the pic_offset_table register.
272 ;; GCC doesn't deal well with labels in the middle of a block so we
273 ;; hardcode the offsets in the asm here.
274 (define_insn "load_pic_offset"
275   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
276         (unspec:SI [(const_int 0)] 0))
277    (set (match_operand:SI 1 "spu_reg_operand" "=r")
278         (unspec:SI [(const_int 0)] 0))]
279   "flag_pic"
280   "ila\t%1,.+8\;brsl\t%0,4"
281   [(set_attr "length" "8")
282    (set_attr "type" "multi0")])
283
284 \f
285 ;; move internal
286
287 (define_insn "_mov<mode>"
288   [(set (match_operand:MOV 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
289         (match_operand:MOV 1 "spu_mov_operand" "r,A,f,j,m,r"))]
290   "spu_valid_move (operands)"
291   "@
292    ori\t%0,%1,0
293    il%s1\t%0,%S1
294    fsmbi\t%0,%S1
295    c%s1d\t%0,%S1($sp)
296    lq%p1\t%0,%1
297    stq%p0\t%1,%0"
298   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
299
300 (define_insn "low_<mode>"
301   [(set (match_operand:VSI 0 "spu_reg_operand" "=r")
302         (lo_sum:VSI (match_operand:VSI 1 "spu_reg_operand" "0")
303                     (match_operand:VSI 2 "immediate_operand" "i")))]
304   ""
305   "iohl\t%0,%2@l")
306
307 (define_insn "_movdi"
308   [(set (match_operand:DI 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
309         (match_operand:DI 1 "spu_mov_operand" "r,a,f,k,m,r"))]
310   "spu_valid_move (operands)"
311   "@
312    ori\t%0,%1,0
313    il%d1\t%0,%D1
314    fsmbi\t%0,%D1
315    c%d1d\t%0,%D1($sp)
316    lq%p1\t%0,%1
317    stq%p0\t%1,%0"
318   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
319
320 (define_insn "_movti"
321   [(set (match_operand:TI 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
322         (match_operand:TI 1 "spu_mov_operand" "r,U,f,l,m,r"))]
323   "spu_valid_move (operands)"
324   "@
325    ori\t%0,%1,0
326    il%t1\t%0,%T1
327    fsmbi\t%0,%T1
328    c%t1d\t%0,%T1($sp)
329    lq%p1\t%0,%1
330    stq%p0\t%1,%0"
331   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
332
333 (define_insn_and_split "load"
334   [(set (match_operand 0 "spu_reg_operand" "=r")
335         (match_operand 1 "memory_operand" "m"))
336    (clobber (match_operand:TI 2 "spu_reg_operand" "=&r"))
337    (clobber (match_operand:SI 3 "spu_reg_operand" "=&r"))]
338   "GET_MODE(operands[0]) == GET_MODE(operands[1])"
339   "#"
340   ""
341   [(set (match_dup 0)
342         (match_dup 1))]
343   { spu_split_load(operands); DONE; })
344
345 (define_insn_and_split "store"
346   [(set (match_operand 0 "memory_operand" "=m")
347         (match_operand 1 "spu_reg_operand" "r"))
348    (clobber (match_operand:TI 2 "spu_reg_operand" "=&r"))
349    (clobber (match_operand:TI 3 "spu_reg_operand" "=&r"))]
350   "GET_MODE(operands[0]) == GET_MODE(operands[1])"
351   "#"
352   ""
353   [(set (match_dup 0)
354         (match_dup 1))]
355   { spu_split_store(operands); DONE; })
356
357 ;; Operand 3 is the number of bytes. 1:b 2:h 4:w 8:d
358
359 (define_expand "cpat"
360   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
361         (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "r,r")
362                     (match_operand:SI 2 "spu_nonmem_operand" "r,n")
363                     (match_operand:SI 3 "immediate_operand" "i,i")] UNSPEC_CPAT))]
364   ""
365   {
366     rtx x = gen_cpat_const (operands);
367     if (x)
368       {
369         emit_move_insn (operands[0], x);
370         DONE;
371       }
372   })
373
374 (define_insn "_cpat"
375   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
376         (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "r,r")
377                     (match_operand:SI 2 "spu_nonmem_operand" "r,n")
378                     (match_operand:SI 3 "immediate_operand" "i,i")] UNSPEC_CPAT))]
379   ""
380   "@
381    c%M3x\t%0,%1,%2
382    c%M3d\t%0,%C2(%1)"
383   [(set_attr "type" "shuf")])
384
385 (define_split
386   [(set (match_operand:TI 0 "spu_reg_operand")
387         (unspec:TI [(match_operand:SI 1 "spu_nonmem_operand")
388                     (match_operand:SI 2 "immediate_operand")
389                     (match_operand:SI 3 "immediate_operand")] UNSPEC_CPAT))]
390   ""
391   [(set (match_dup:TI 0)
392         (match_dup:TI 4))]
393   {
394     operands[4] = gen_cpat_const (operands);
395     if (!operands[4])
396       FAIL;
397   })
398 \f
399 ;; extend
400
401 (define_insn "extendqihi2"
402   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
403         (sign_extend:HI (match_operand:QI 1 "spu_reg_operand" "r")))]
404   ""
405   "xsbh\t%0,%1")
406
407 (define_insn "extendhisi2"
408   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
409         (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r")))]
410   ""
411   "xshw\t%0,%1")
412
413 (define_expand "extendsidi2"
414   [(set (match_dup:DI 2)
415         (zero_extend:DI (match_operand:SI 1 "spu_reg_operand" "")))
416    (set (match_operand:DI 0 "spu_reg_operand" "")
417         (sign_extend:DI (vec_select:SI (match_dup:V2SI 3)
418                                        (parallel [(const_int 1)]))))]
419   ""
420   {
421     operands[2] = gen_reg_rtx (DImode);
422     operands[3] = spu_gen_subreg (V2SImode, operands[2]);
423   })
424
425 (define_insn "xswd"
426   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
427         (sign_extend:DI
428           (vec_select:SI
429             (match_operand:V2SI 1 "spu_reg_operand" "r")
430             (parallel [(const_int 1) ]))))]
431   ""
432   "xswd\t%0,%1");
433
434 (define_expand "extendqiti2"
435   [(set (match_operand:TI 0 "register_operand" "")
436         (sign_extend:TI (match_operand:QI 1 "register_operand" "")))]
437   ""
438   "spu_expand_sign_extend(operands);
439    DONE;")
440
441 (define_expand "extendhiti2"
442   [(set (match_operand:TI 0 "register_operand" "")
443         (sign_extend:TI (match_operand:HI 1 "register_operand" "")))]
444   ""
445   "spu_expand_sign_extend(operands);
446    DONE;")
447
448 (define_expand "extendsiti2"
449   [(set (match_operand:TI 0 "register_operand" "")
450         (sign_extend:TI (match_operand:SI 1 "register_operand" "")))]
451   ""
452   "spu_expand_sign_extend(operands);
453    DONE;")
454
455 (define_expand "extendditi2"
456   [(set (match_operand:TI 0 "register_operand" "")
457         (sign_extend:TI (match_operand:DI 1 "register_operand" "")))]
458   ""
459   "spu_expand_sign_extend(operands);
460    DONE;")
461
462 \f
463 ;; zero_extend
464
465 (define_insn "zero_extendqihi2"
466   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
467         (zero_extend:HI (match_operand:QI 1 "spu_reg_operand" "r")))]
468   ""
469   "andi\t%0,%1,0x00ff")
470
471 (define_insn "zero_extendqisi2"
472   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
473         (zero_extend:SI (match_operand:QI 1 "spu_reg_operand" "r")))]
474   ""
475   "andi\t%0,%1,0x00ff")
476
477 (define_expand "zero_extendhisi2"
478   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
479         (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r")))
480    (clobber (match_scratch:SI 2 "=&r"))]
481   ""
482   {
483     rtx mask = gen_reg_rtx (SImode);
484     rtx op1 = simplify_gen_subreg (SImode, operands[1], HImode, 0);
485     emit_move_insn (mask, GEN_INT (0xffff));
486     emit_insn (gen_andsi3(operands[0], op1, mask));
487     DONE;
488   })
489   
490 (define_insn "zero_extendsidi2"
491   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
492         (zero_extend:DI (match_operand:SI 1 "spu_reg_operand" "r")))]
493   ""
494   "rotqmbyi\t%0,%1,-4"
495   [(set_attr "type" "shuf")])
496
497 (define_insn "zero_extendsiti2"
498   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
499         (zero_extend:TI (match_operand:SI 1 "spu_reg_operand" "r")))]
500   ""
501   "rotqmbyi\t%0,%1,-12"
502   [(set_attr "type" "shuf")])
503
504 (define_insn "zero_extendditi2"
505   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
506         (zero_extend:TI (match_operand:DI 1 "spu_reg_operand" "r")))]
507   ""
508   "rotqmbyi\t%0,%1,-8"
509   [(set_attr "type" "shuf")])
510
511 \f
512 ;; trunc
513
514 (define_insn "truncdiqi2"
515   [(set (match_operand:QI 0 "spu_reg_operand" "=r")
516         (truncate:QI (match_operand:DI 1 "spu_reg_operand" "r")))]
517   ""
518   "shlqbyi\t%0,%1,4"
519   [(set_attr "type" "shuf")])
520
521 (define_insn "truncdihi2"
522   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
523         (truncate:HI (match_operand:DI 1 "spu_reg_operand" "r")))]
524   ""
525   "shlqbyi\t%0,%1,4"
526   [(set_attr "type" "shuf")])
527
528 (define_insn "truncdisi2"
529   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
530         (truncate:SI (match_operand:DI 1 "spu_reg_operand" "r")))]
531   ""
532   "shlqbyi\t%0,%1,4"
533   [(set_attr "type" "shuf")])
534
535 (define_insn "trunctiqi2"
536   [(set (match_operand:QI 0 "spu_reg_operand" "=r")
537         (truncate:QI (match_operand:TI 1 "spu_reg_operand" "r")))]
538   ""
539   "shlqbyi\t%0,%1,12"
540   [(set_attr "type" "shuf")])
541
542 (define_insn "trunctihi2"
543   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
544         (truncate:HI (match_operand:TI 1 "spu_reg_operand" "r")))]
545   ""
546   "shlqbyi\t%0,%1,12"
547   [(set_attr "type" "shuf")])
548
549 (define_insn "trunctisi2"
550   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
551         (truncate:SI (match_operand:TI 1 "spu_reg_operand" "r")))]
552   ""
553   "shlqbyi\t%0,%1,12"
554   [(set_attr "type" "shuf")])
555
556 (define_insn "trunctidi2"
557   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
558         (truncate:DI (match_operand:TI 1 "spu_reg_operand" "r")))]
559   ""
560   "shlqbyi\t%0,%1,8"
561   [(set_attr "type" "shuf")])
562
563 \f
564 ;; float conversions
565
566 (define_insn "floatsisf2"
567   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
568         (float:SF (match_operand:SI 1 "spu_reg_operand" "r")))]
569   ""
570   "csflt\t%0,%1,0"
571   [(set_attr "type" "fp7")])
572
573 (define_insn "floatv4siv4sf2"
574   [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
575         (float:V4SF (match_operand:V4SI 1 "spu_reg_operand" "r")))]
576   ""
577   "csflt\t%0,%1,0"
578   [(set_attr "type" "fp7")])
579
580 (define_insn "fix_truncsfsi2"
581   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
582         (fix:SI (match_operand:SF 1 "spu_reg_operand" "r")))]
583   ""
584   "cflts\t%0,%1,0"
585   [(set_attr "type" "fp7")])
586
587 (define_insn "fix_truncv4sfv4si2"
588   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
589         (fix:V4SI (match_operand:V4SF 1 "spu_reg_operand" "r")))]
590   ""
591   "cflts\t%0,%1,0"
592   [(set_attr "type" "fp7")])
593
594 (define_insn "floatunssisf2"
595   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
596         (unsigned_float:SF (match_operand:SI 1 "spu_reg_operand" "r")))]
597   ""
598   "cuflt\t%0,%1,0"
599   [(set_attr "type" "fp7")])
600
601 (define_insn "floatunsv4siv4sf2"
602   [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
603         (unsigned_float:V4SF (match_operand:V4SI 1 "spu_reg_operand" "r")))]
604   ""
605   "cuflt\t%0,%1,0"
606   [(set_attr "type" "fp7")])
607
608 (define_insn "fixuns_truncsfsi2"
609   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
610         (unsigned_fix:SI (match_operand:SF 1 "spu_reg_operand" "r")))]
611   ""
612   "cfltu\t%0,%1,0"
613   [(set_attr "type" "fp7")])
614
615 (define_insn "fixuns_truncv4sfv4si2"
616   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
617         (unsigned_fix:V4SI (match_operand:V4SF 1 "spu_reg_operand" "r")))]
618   ""
619   "cfltu\t%0,%1,0"
620   [(set_attr "type" "fp7")])
621
622 (define_insn "extendsfdf2"
623   [(set (match_operand:DF 0 "spu_reg_operand" "=r")
624         (float_extend:DF (match_operand:SF 1 "spu_reg_operand" "r")))]
625   ""
626   "fesd\t%0,%1"
627   [(set_attr "type" "fpd")])
628
629 (define_insn "truncdfsf2"
630   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
631         (float_truncate:SF (match_operand:DF 1 "spu_reg_operand" "r")))]
632   ""
633   "frds\t%0,%1"
634   [(set_attr "type" "fpd")])
635
636 ;; Do (double)(operands[1]+0x80000000u)-(double)0x80000000
637 (define_expand "floatsidf2"
638   [(set (match_operand:DF 0 "register_operand" "")
639         (float:DF (match_operand:SI 1 "register_operand" "")))]
640   ""
641   {
642     rtx value, insns;
643     rtx c0 = gen_reg_rtx (SImode);
644     rtx c1 = gen_reg_rtx (DFmode);
645     rtx r0 = gen_reg_rtx (SImode);
646     rtx r1 = gen_reg_rtx (DFmode);
647
648     emit_move_insn (c0, GEN_INT (-0x80000000ll));
649     emit_move_insn (c1, spu_float_const ("2147483648", DFmode));
650
651     emit_insn (gen_xorsi3 (r0, operands[1], c0));
652
653     start_sequence ();
654     value =
655       emit_library_call_value (ufloat_optab->handlers[DFmode][SImode].libfunc,
656                                NULL_RTX, LCT_NORMAL, DFmode, 1, r0, SImode);
657     insns = get_insns ();
658     end_sequence ();
659     emit_libcall_block (insns, r1, value,
660                         gen_rtx_UNSIGNED_FLOAT (DFmode, r0));
661
662     emit_insn (gen_subdf3 (operands[0], r1, c1));
663     DONE;
664   })
665
666 (define_expand "floatdidf2"
667   [(set (match_operand:DF 0 "register_operand" "")
668         (float:DF (match_operand:DI 1 "register_operand" "")))]
669   ""
670   {
671     rtx value, insns;
672     rtx c0 = gen_reg_rtx (DImode);
673     rtx r0 = gen_reg_rtx (DImode);
674     rtx r1 = gen_reg_rtx (DFmode);
675     rtx r2 = gen_reg_rtx (DImode);
676     rtx setneg = gen_reg_rtx (DImode);
677     rtx isneg = gen_reg_rtx (SImode);
678     rtx neg = gen_reg_rtx (DImode);
679     rtx mask = gen_reg_rtx (DImode);
680
681     emit_move_insn (c0, GEN_INT (0x8000000000000000ull));
682
683     emit_insn (gen_negdi2 (neg, operands[1]));
684     emit_insn (gen_cgt_di_m1 (isneg, operands[1]));
685     emit_insn (gen_extend_compare (mask, isneg));
686     emit_insn (gen_selb (r0, neg, operands[1], mask));
687     emit_insn (gen_andc_di (setneg, c0, mask));
688
689
690     start_sequence ();
691     value =
692       emit_library_call_value (ufloat_optab->handlers[DFmode][DImode].libfunc,
693                                NULL_RTX, LCT_NORMAL, DFmode, 1, r0, DImode);
694     insns = get_insns ();
695     end_sequence ();
696     emit_libcall_block (insns, r1, value,
697                         gen_rtx_UNSIGNED_FLOAT (DFmode, r0));
698
699     emit_insn (gen_iordi3 (r2, gen_rtx_SUBREG (DImode, r1, 0), setneg));
700     emit_move_insn (operands[0], gen_rtx_SUBREG (DFmode, r2, 0));
701     DONE;
702   })
703 \f
704 ;; add
705
706 (define_expand "addv16qi3"
707   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
708         (plus:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")
709                     (match_operand:V16QI 2 "spu_reg_operand" "r")))]
710   ""
711   "{
712     rtx res_short = simplify_gen_subreg (V8HImode, operands[0], V16QImode, 0);
713     rtx lhs_short = simplify_gen_subreg (V8HImode, operands[1], V16QImode, 0);
714     rtx rhs_short = simplify_gen_subreg (V8HImode, operands[2], V16QImode, 0);
715     rtx rhs_and = gen_reg_rtx (V8HImode);
716     rtx hi_char = gen_reg_rtx (V8HImode);
717     rtx lo_char = gen_reg_rtx (V8HImode);
718     rtx mask = gen_reg_rtx (V8HImode);
719
720     emit_move_insn (mask, spu_const (V8HImode, 0x00ff));
721     emit_insn (gen_andv8hi3 (rhs_and, rhs_short, spu_const (V8HImode, 0xff00)));
722     emit_insn (gen_addv8hi3 (hi_char, lhs_short, rhs_and));
723     emit_insn (gen_addv8hi3 (lo_char, lhs_short, rhs_short));
724     emit_insn (gen_selb (res_short, hi_char, lo_char, mask));
725     DONE;
726    }")
727
728 (define_insn "add<mode>3"
729   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
730         (plus:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
731                    (match_operand:VHSI 2 "spu_arith_operand" "r,B")))]
732   ""
733   "@
734   a<bh>\t%0,%1,%2
735   a<bh>i\t%0,%1,%2")
736
737 (define_expand "add<mode>3"
738   [(set (match_dup:VDI 3) 
739         (unspec:VDI [(match_operand:VDI 1 "spu_reg_operand" "")
740                      (match_operand:VDI 2 "spu_reg_operand" "")] UNSPEC_CG))
741    (set (match_dup:VDI 5)
742         (unspec:VDI [(match_dup 3)
743                      (match_dup 3)
744                      (match_dup:TI 4)] UNSPEC_SHUFB))
745    (set (match_operand:VDI 0 "spu_reg_operand" "") 
746         (unspec:VDI [(match_dup 1)
747                      (match_dup 2)
748                      (match_dup 5)] UNSPEC_ADDX))]
749   ""
750   {
751     unsigned char pat[16] = {
752       0x04, 0x05, 0x06, 0x07,
753       0x80, 0x80, 0x80, 0x80,
754       0x0c, 0x0d, 0x0e, 0x0f,
755       0x80, 0x80, 0x80, 0x80
756     };
757     operands[3] = gen_reg_rtx (<MODE>mode);
758     operands[4] = gen_reg_rtx (TImode);
759     operands[5] = gen_reg_rtx (<MODE>mode);
760     emit_move_insn (operands[4], array_to_constant (TImode, pat));
761   })
762
763 (define_insn "cg_<mode>"
764   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
765         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
766                       (match_operand 2 "spu_reg_operand" "r")] UNSPEC_CG))]
767   "operands"
768   "cg\t%0,%1,%2")
769
770 (define_insn "cgx_<mode>"
771   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
772         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
773                       (match_operand 2 "spu_reg_operand" "r")
774                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_CGX))]
775   "operands"
776   "cgx\t%0,%1,%2")
777
778 (define_insn "addx_<mode>"
779   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
780         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
781                       (match_operand 2 "spu_reg_operand" "r")
782                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_ADDX))]
783   "operands"
784   "addx\t%0,%1,%2")
785
786
787 ;; This is not the most efficient implementation of addti3.
788 ;; We include this here because 1) the compiler needs it to be
789 ;; defined as the word size is 128-bit and 2) sometimes gcc
790 ;; substitutes an add for a constant left-shift. 2) is unlikely
791 ;; because we also give addti3 a high cost. In case gcc does
792 ;; generate TImode add, here is the code to do it.
793 ;; operand 2 is a nonmemory because the compiler requires it.
794 (define_insn "addti3"
795   [(set (match_operand:TI 0 "spu_reg_operand" "=&r")
796         (plus:TI (match_operand:TI 1 "spu_reg_operand" "r")
797                  (match_operand:TI 2 "spu_nonmem_operand" "r")))
798    (clobber (match_scratch:TI 3 "=&r"))]
799   ""
800   "cg\t%3,%1,%2\n\\
801    shlqbyi\t%3,%3,4\n\\
802    cgx\t%3,%1,%2\n\\
803    shlqbyi\t%3,%3,4\n\\
804    cgx\t%3,%1,%2\n\\
805    shlqbyi\t%0,%3,4\n\\
806    addx\t%0,%1,%2"
807   [(set_attr "type" "multi0")
808    (set_attr "length" "28")])
809
810 (define_insn "add<mode>3"
811   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
812         (plus:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
813                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
814   ""
815   "fa\t%0,%1,%2"
816   [(set_attr "type" "fp6")])
817
818 (define_insn "add<mode>3"
819   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
820         (plus:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
821                   (match_operand:VDF 2 "spu_reg_operand" "r")))]
822   ""
823   "dfa\t%0,%1,%2"
824   [(set_attr "type" "fpd")])
825
826 \f
827 ;; sub
828
829 (define_expand "subv16qi3"
830   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
831         (minus:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")
832                      (match_operand:V16QI 2 "spu_reg_operand" "r")))]
833   ""
834   "{
835     rtx res_short = simplify_gen_subreg (V8HImode, operands[0], V16QImode, 0);
836     rtx lhs_short = simplify_gen_subreg (V8HImode, operands[1], V16QImode, 0);
837     rtx rhs_short = simplify_gen_subreg (V8HImode, operands[2], V16QImode, 0);
838     rtx rhs_and = gen_reg_rtx (V8HImode);
839     rtx hi_char = gen_reg_rtx (V8HImode);
840     rtx lo_char = gen_reg_rtx (V8HImode);
841     rtx mask = gen_reg_rtx (V8HImode);
842
843     emit_move_insn (mask, spu_const (V8HImode, 0x00ff));
844     emit_insn (gen_andv8hi3 (rhs_and, rhs_short, spu_const (V8HImode, 0xff00)));
845     emit_insn (gen_subv8hi3 (hi_char, lhs_short, rhs_and));
846     emit_insn (gen_subv8hi3 (lo_char, lhs_short, rhs_short));
847     emit_insn (gen_selb (res_short, hi_char, lo_char, mask));
848     DONE;
849    }")
850
851 (define_insn "sub<mode>3"
852   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
853         (minus:VHSI (match_operand:VHSI 1 "spu_arith_operand" "r,B")
854                     (match_operand:VHSI 2 "spu_reg_operand" "r,r")))]
855   ""
856   "@
857   sf<bh>\t%0,%2,%1
858   sf<bh>i\t%0,%2,%1")
859
860 (define_expand "sub<mode>3"
861   [(set (match_dup:VDI 3) 
862         (unspec:VDI [(match_operand:VDI 1 "spu_reg_operand" "")
863                      (match_operand:VDI 2 "spu_reg_operand" "")] UNSPEC_BG))
864    (set (match_dup:VDI 5)
865         (unspec:VDI [(match_dup 3)
866                      (match_dup 3)
867                      (match_dup:TI 4)] UNSPEC_SHUFB))
868    (set (match_operand:VDI 0 "spu_reg_operand" "") 
869         (unspec:VDI [(match_dup 1)
870                      (match_dup 2)
871                      (match_dup 5)] UNSPEC_SFX))]
872   ""
873   {
874     unsigned char pat[16] = {
875       0x04, 0x05, 0x06, 0x07,
876       0xc0, 0xc0, 0xc0, 0xc0,
877       0x0c, 0x0d, 0x0e, 0x0f,
878       0xc0, 0xc0, 0xc0, 0xc0
879     };
880     operands[3] = gen_reg_rtx (<MODE>mode);
881     operands[4] = gen_reg_rtx (TImode);
882     operands[5] = gen_reg_rtx (<MODE>mode);
883     emit_move_insn (operands[4], array_to_constant (TImode, pat));
884   })
885
886 (define_insn "bg_<mode>"
887   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
888         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
889                       (match_operand 2 "spu_reg_operand" "r")] UNSPEC_BG))]
890   "operands"
891   "bg\t%0,%2,%1")
892
893 (define_insn "bgx_<mode>"
894   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
895         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
896                       (match_operand 2 "spu_reg_operand" "r")
897                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_BGX))]
898   "operands"
899   "bgx\t%0,%2,%1")
900
901 (define_insn "sfx_<mode>"
902   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
903         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
904                       (match_operand 2 "spu_reg_operand" "r")
905                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_SFX))]
906   "operands"
907   "sfx\t%0,%2,%1")
908
909 (define_insn "subti3"
910   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
911         (minus:TI (match_operand:TI 1 "spu_reg_operand" "r")
912                   (match_operand:TI 2 "spu_reg_operand" "r")))
913    (clobber (match_scratch:TI 3 "=&r"))
914    (clobber (match_scratch:TI 4 "=&r"))
915    (clobber (match_scratch:TI 5 "=&r"))]
916   ""
917   "bg\t%3,%1,%2\n\\
918    sf\t%4,%2,%1\n\\
919    shlqbyi\t%5,%3,4\n\\
920    bg\t%3,%4,%5\n\\
921    sf\t%4,%5,%4\n\\
922    shlqbyi\t%5,%3,4\n\\
923    bg\t%3,%4,%5\n\\
924    shlqbyi\t%0,%3,4\n\\
925    sfx\t%0,%5,%4"
926   [(set_attr "type" "multi0")
927    (set_attr "length" "36")])
928
929 (define_insn "sub<mode>3"
930   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
931         (minus:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
932                    (match_operand:VSF 2 "spu_reg_operand" "r")))]
933   ""
934   "fs\t%0,%1,%2"
935   [(set_attr "type" "fp6")])
936
937 (define_insn "sub<mode>3"
938   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
939         (minus:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
940                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
941   ""
942   "dfs\t%0,%1,%2"
943   [(set_attr "type" "fpd")])
944
945 \f
946 ;; neg
947
948 (define_expand "negv16qi2"
949   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
950         (neg:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")))]
951   ""
952   "{
953     rtx zero = gen_reg_rtx (V16QImode);
954     emit_move_insn (zero, CONST0_RTX (V16QImode));
955     emit_insn (gen_subv16qi3 (operands[0], zero, operands[1]));
956     DONE;
957    }")
958
959 (define_insn "neg<mode>2"
960   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
961         (neg:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")))]
962   ""
963   "sf<bh>i\t%0,%1,0")
964
965 (define_expand "negdi2"
966   [(set (match_operand:DI 0 "spu_reg_operand" "")
967         (neg:DI (match_operand:DI 1 "spu_reg_operand" "")))]
968   ""
969   {
970     rtx zero = gen_reg_rtx(DImode);
971     emit_move_insn(zero, GEN_INT(0));
972     emit_insn(gen_subdi3(operands[0], zero, operands[1]));
973     DONE;
974   })
975
976 (define_expand "negti2"
977   [(set (match_operand:TI 0 "spu_reg_operand" "")
978         (neg:TI (match_operand:TI 1 "spu_reg_operand" "")))]
979   ""
980   {
981     rtx zero = gen_reg_rtx(TImode);
982     emit_move_insn(zero, GEN_INT(0));
983     emit_insn(gen_subti3(operands[0], zero, operands[1]));
984     DONE;
985   })
986
987 (define_expand "neg<mode>2"
988   [(parallel
989     [(set (match_operand:VSF 0 "spu_reg_operand" "")
990           (neg:VSF (match_operand:VSF 1 "spu_reg_operand" "")))
991      (use (match_dup 2))])]
992   ""
993   "operands[2] = gen_reg_rtx (<f2i>mode);
994    emit_move_insn (operands[2], spu_const (<f2i>mode, -0x80000000ull));")
995
996 (define_expand "neg<mode>2"
997   [(parallel
998     [(set (match_operand:VDF 0 "spu_reg_operand" "")
999           (neg:VDF (match_operand:VDF 1 "spu_reg_operand" "")))
1000      (use (match_dup 2))])]
1001   ""
1002   "operands[2] = gen_reg_rtx (<f2i>mode);
1003    emit_move_insn (operands[2], spu_const (<f2i>mode, -0x8000000000000000ull));")
1004
1005 (define_insn_and_split "_neg<mode>2"
1006   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1007         (neg:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")))
1008    (use (match_operand:<f2i> 2 "spu_reg_operand" "r"))]
1009   ""
1010   "#"
1011   ""
1012   [(set (match_dup:<f2i> 3)
1013         (xor:<f2i> (match_dup:<f2i> 4)
1014                    (match_dup:<f2i> 2)))]
1015   {
1016     operands[3] = spu_gen_subreg (<f2i>mode, operands[0]);
1017     operands[4] = spu_gen_subreg (<f2i>mode, operands[1]);
1018   })
1019
1020 \f
1021 ;; abs
1022
1023 (define_expand "abs<mode>2"
1024   [(parallel
1025     [(set (match_operand:VSF 0 "spu_reg_operand" "")
1026           (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "")))
1027      (use (match_dup 2))])]
1028   ""
1029   "operands[2] = gen_reg_rtx (<f2i>mode);
1030    emit_move_insn (operands[2], spu_const (<f2i>mode, 0x7fffffffull));")
1031
1032 (define_expand "abs<mode>2"
1033   [(parallel
1034     [(set (match_operand:VDF 0 "spu_reg_operand" "")
1035           (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "")))
1036      (use (match_dup 2))])]
1037   ""
1038   "operands[2] = gen_reg_rtx (<f2i>mode);
1039    emit_move_insn (operands[2], spu_const (<f2i>mode, 0x7fffffffffffffffull));")
1040
1041 (define_insn_and_split "_abs<mode>2"
1042   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1043         (abs:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")))
1044    (use (match_operand:<f2i> 2 "spu_reg_operand" "r"))]
1045   ""
1046   "#"
1047   ""
1048   [(set (match_dup:<f2i> 3)
1049         (and:<f2i> (match_dup:<f2i> 4)
1050                    (match_dup:<f2i> 2)))]
1051   {
1052     operands[3] = spu_gen_subreg (<f2i>mode, operands[0]);
1053     operands[4] = spu_gen_subreg (<f2i>mode, operands[1]);
1054   })
1055
1056 \f
1057 ;; mul
1058
1059 (define_insn "mulhi3"
1060   [(set (match_operand:HI 0 "spu_reg_operand" "=r,r")
1061         (mult:HI (match_operand:HI 1 "spu_reg_operand" "r,r")
1062                  (match_operand:HI 2 "spu_arith_operand" "r,B")))]
1063   ""
1064   "@
1065   mpy\t%0,%1,%2
1066   mpyi\t%0,%1,%2"
1067   [(set_attr "type" "fp7")])
1068
1069 (define_expand "mulv8hi3"
1070   [(set (match_operand:V8HI 0 "spu_reg_operand" "")
1071         (mult:V8HI (match_operand:V8HI 1 "spu_reg_operand" "")
1072                    (match_operand:V8HI 2 "spu_reg_operand" "")))]
1073   ""
1074   "{
1075     rtx result = simplify_gen_subreg (V4SImode, operands[0], V8HImode, 0);
1076     rtx low = gen_reg_rtx (V4SImode);
1077     rtx high = gen_reg_rtx (V4SImode);
1078     rtx shift = gen_reg_rtx (V4SImode);
1079     rtx mask = gen_reg_rtx (V4SImode);
1080
1081     emit_move_insn (mask, spu_const (V4SImode, 0x0000ffff));
1082     emit_insn (gen_spu_mpyhh (high, operands[1], operands[2]));
1083     emit_insn (gen_spu_mpy (low, operands[1], operands[2]));
1084     emit_insn (gen_ashlv4si3 (shift, high, spu_const(V4SImode, 16)));
1085     emit_insn (gen_selb (result, shift, low, mask));
1086     DONE;
1087    }")
1088
1089 (define_expand "mul<mode>3"
1090   [(parallel
1091     [(set (match_operand:VSI 0 "spu_reg_operand" "")
1092           (mult:VSI (match_operand:VSI 1 "spu_reg_operand" "")
1093                     (match_operand:VSI 2 "spu_reg_operand" "")))
1094      (clobber (match_dup:VSI 3))
1095      (clobber (match_dup:VSI 4))
1096      (clobber (match_dup:VSI 5))
1097      (clobber (match_dup:VSI 6))])]
1098   ""
1099   {
1100     operands[3] = gen_reg_rtx(<MODE>mode);
1101     operands[4] = gen_reg_rtx(<MODE>mode);
1102     operands[5] = gen_reg_rtx(<MODE>mode);
1103     operands[6] = gen_reg_rtx(<MODE>mode);
1104   })
1105
1106 (define_insn_and_split "_mulsi3"
1107   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1108         (mult:SI (match_operand:SI 1 "spu_reg_operand" "r")
1109                  (match_operand:SI 2 "spu_arith_operand" "rK")))
1110    (clobber (match_operand:SI 3 "spu_reg_operand" "=&r"))
1111    (clobber (match_operand:SI 4 "spu_reg_operand" "=&r"))
1112    (clobber (match_operand:SI 5 "spu_reg_operand" "=&r"))
1113    (clobber (match_operand:SI 6 "spu_reg_operand" "=&r"))]
1114   ""
1115   "#"
1116   ""
1117   [(set (match_dup:SI 0)
1118         (mult:SI (match_dup:SI 1)
1119                  (match_dup:SI 2)))]
1120   {
1121     HOST_WIDE_INT val = 0;
1122     rtx a = operands[3];
1123     rtx b = operands[4];
1124     rtx c = operands[5];
1125     rtx d = operands[6];
1126     if (GET_CODE(operands[2]) == CONST_INT)
1127       {
1128         val = INTVAL(operands[2]);
1129         emit_move_insn(d, operands[2]);
1130         operands[2] = d;
1131       }
1132     if (val && (val & 0xffff) == 0)
1133       {
1134         emit_insn(gen_mpyh_si(operands[0], operands[2], operands[1]));
1135       }
1136     else if (val > 0 && val < 0x10000)
1137       {
1138         rtx cst = satisfies_constraint_K (GEN_INT (val)) ? GEN_INT(val) : d;
1139         emit_insn(gen_mpyh_si(a, operands[1], operands[2]));
1140         emit_insn(gen_mpyu_si(c, operands[1], cst));
1141         emit_insn(gen_addsi3(operands[0], a, c));
1142       }
1143     else
1144       {
1145         emit_insn(gen_mpyh_si(a, operands[1], operands[2]));
1146         emit_insn(gen_mpyh_si(b, operands[2], operands[1]));
1147         emit_insn(gen_mpyu_si(c, operands[1], operands[2]));
1148         emit_insn(gen_addsi3(d, a, b));
1149         emit_insn(gen_addsi3(operands[0], d, c));
1150       }
1151     DONE;
1152    })
1153
1154 (define_insn_and_split "_mulv4si3"
1155   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
1156         (mult:V4SI (match_operand:V4SI 1 "spu_reg_operand" "r")
1157                    (match_operand:V4SI 2 "spu_reg_operand" "r")))
1158    (clobber (match_operand:V4SI 3 "spu_reg_operand" "=&r"))
1159    (clobber (match_operand:V4SI 4 "spu_reg_operand" "=&r"))
1160    (clobber (match_operand:V4SI 5 "spu_reg_operand" "=&r"))
1161    (clobber (match_operand:V4SI 6 "spu_reg_operand" "=&r"))]
1162   ""
1163   "#"
1164   ""
1165   [(set (match_dup:V4SI 0)
1166         (mult:V4SI (match_dup:V4SI 1)
1167                    (match_dup:V4SI 2)))]
1168   {
1169     rtx a = operands[3];
1170     rtx b = operands[4];
1171     rtx c = operands[5];
1172     rtx d = operands[6];
1173     rtx op1 = simplify_gen_subreg (V8HImode, operands[1], V4SImode, 0);
1174     rtx op2 = simplify_gen_subreg (V8HImode, operands[2], V4SImode, 0);
1175     emit_insn(gen_spu_mpyh(a, op1, op2));
1176     emit_insn(gen_spu_mpyh(b, op2, op1));
1177     emit_insn(gen_spu_mpyu(c, op1, op2));
1178     emit_insn(gen_addv4si3(d, a, b));
1179     emit_insn(gen_addv4si3(operands[0], d, c));
1180     DONE;
1181    })
1182
1183 (define_insn "mulhisi3"
1184   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1185         (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1186                  (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r"))))]
1187   ""
1188   "mpy\t%0,%1,%2"
1189   [(set_attr "type" "fp7")])
1190
1191 (define_insn "mulhisi3_imm"
1192   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1193         (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1194                  (match_operand:SI 2 "imm_K_operand" "K")))]
1195   ""
1196   "mpyi\t%0,%1,%2"
1197   [(set_attr "type" "fp7")])
1198
1199 (define_insn "umulhisi3"
1200   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1201         (mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1202                  (zero_extend:SI (match_operand:HI 2 "spu_reg_operand" "r"))))]
1203   ""
1204   "mpyu\t%0,%1,%2"
1205   [(set_attr "type" "fp7")])
1206
1207 (define_insn "umulhisi3_imm"
1208   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1209         (mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1210                  (and:SI (match_operand:SI 2 "imm_K_operand" "K") (const_int 65535))))]
1211   ""
1212   "mpyui\t%0,%1,%2"
1213   [(set_attr "type" "fp7")])
1214
1215 (define_insn "mpyu_si"
1216   [(set (match_operand:SI 0 "spu_reg_operand" "=r,r")
1217         (mult:SI (and:SI (match_operand:SI 1 "spu_reg_operand" "r,r")
1218                          (const_int 65535))
1219                  (and:SI (match_operand:SI 2 "spu_arith_operand" "r,K")
1220                          (const_int 65535))))]
1221   ""
1222   "@
1223    mpyu\t%0,%1,%2
1224    mpyui\t%0,%1,%2"
1225   [(set_attr "type" "fp7")])
1226
1227 ;; This isn't always profitable to use.  Consider r = a * b + c * d.
1228 ;; It's faster to do the multiplies in parallel then add them.  If we
1229 ;; merge a multiply and add it prevents the multiplies from happening in
1230 ;; parallel.
1231 (define_insn "mpya_si"
1232   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1233         (plus:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1234                           (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r")))
1235                  (match_operand:SI 3 "spu_reg_operand" "r")))]
1236   "0"
1237   "mpya\t%0,%1,%2,%3"
1238   [(set_attr "type" "fp7")])
1239
1240 (define_insn "mpyh_si"
1241   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1242         (mult:SI (and:SI (match_operand:SI 1 "spu_reg_operand" "r")
1243                          (const_int -65536))
1244                  (and:SI (match_operand:SI 2 "spu_reg_operand" "r")
1245                          (const_int 65535))))]
1246   ""
1247   "mpyh\t%0,%1,%2"
1248   [(set_attr "type" "fp7")])
1249
1250 (define_insn "mpys_si"
1251   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1252         (ashiftrt:SI
1253             (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1254                      (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r")))
1255             (const_int 16)))]
1256   ""
1257   "mpys\t%0,%1,%2"
1258   [(set_attr "type" "fp7")])
1259
1260 (define_insn "mpyhh_si"
1261   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1262         (mult:SI (ashiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1263                               (const_int 16))
1264                  (ashiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1265                               (const_int 16))))]
1266   ""
1267   "mpyhh\t%0,%1,%2"
1268   [(set_attr "type" "fp7")])
1269
1270 (define_insn "mpyhhu_si"
1271   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1272         (mult:SI (lshiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1273                               (const_int 16))
1274                  (lshiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1275                               (const_int 16))))]
1276   ""
1277   "mpyhhu\t%0,%1,%2"
1278   [(set_attr "type" "fp7")])
1279
1280 (define_insn "mpyhha_si" 
1281   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1282         (plus:SI (mult:SI (ashiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1283                                        (const_int 16))
1284                           (ashiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1285                                        (const_int 16)))
1286                  (match_operand:SI 3 "spu_reg_operand" "0")))]
1287   "0"
1288   "mpyhha\t%0,%1,%2"
1289   [(set_attr "type" "fp7")])
1290
1291 (define_insn "mul<mode>3"
1292   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1293         (mult:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")
1294                    (match_operand:VSDF 2 "spu_reg_operand" "r")))]
1295   ""
1296   "<d>fm\t%0,%1,%2"
1297   [(set_attr "type" "fp<d6>")])
1298
1299 (define_insn "fma_<mode>"
1300   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1301         (plus:VSF (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1302                               (match_operand:VSF 2 "spu_reg_operand" "r"))
1303                    (match_operand:VSF 3 "spu_reg_operand" "r")))]
1304   ""
1305   "fma\t%0,%1,%2,%3"
1306   [(set_attr "type"     "fp6")])
1307
1308 (define_insn "fnms_<mode>"
1309   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1310         (minus:VSF (match_operand:VSF 3 "spu_reg_operand" "r")
1311                     (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1312                                (match_operand:VSF 2 "spu_reg_operand" "r"))))]
1313   ""
1314   "fnms\t%0,%1,%2,%3"
1315   [(set_attr "type" "fp6")])
1316
1317 (define_insn "fms_<mode>"
1318   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1319         (minus:VSF (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1320                                (match_operand:VSF 2 "spu_reg_operand" "r"))
1321                     (match_operand:VSF 3 "spu_reg_operand" "r")))]
1322   ""
1323   "fms\t%0,%1,%2,%3"
1324   [(set_attr "type" "fp6")])
1325
1326 (define_insn "fma_<mode>"
1327   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1328         (plus:VDF (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1329                             (match_operand:VDF 2 "spu_reg_operand" "r"))
1330                   (match_operand:VDF 3 "spu_reg_operand" "0")))]
1331   ""
1332   "dfma\t%0,%1,%2"
1333   [(set_attr "type"     "fpd")])
1334
1335 (define_insn "fnma_<mode>"
1336   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1337         (neg:VDF (plus:VDF (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1338                                      (match_operand:VDF 2 "spu_reg_operand" "r"))
1339                            (match_operand:VDF 3 "spu_reg_operand" "0"))))]
1340   ""
1341   "dfnma\t%0,%1,%2"
1342   [(set_attr "type"     "fpd")])
1343
1344 (define_insn "fnms_<mode>"
1345   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1346         (minus:VDF (match_operand:VDF 3 "spu_reg_operand" "0")
1347                    (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1348                              (match_operand:VDF 2 "spu_reg_operand" "r"))))]
1349   ""
1350   "dfnms\t%0,%1,%2"
1351   [(set_attr "type" "fpd")])
1352
1353 (define_insn "fms_<mode>"
1354   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1355         (minus:VDF (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1356                              (match_operand:VDF 2 "spu_reg_operand" "r"))
1357                    (match_operand:VDF 3 "spu_reg_operand" "0")))]
1358   ""
1359   "dfms\t%0,%1,%2"
1360   [(set_attr "type" "fpd")])
1361
1362 \f
1363 ;; mul highpart, used for divide by constant optimizations.
1364
1365 (define_expand "smulsi3_highpart"
1366   [(set (match_operand:SI 0 "register_operand" "")
1367         (truncate:SI
1368           (ashiftrt:DI
1369             (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
1370                      (sign_extend:DI (match_operand:SI 2 "register_operand" "")))
1371             (const_int 32))))]
1372   ""
1373   {
1374     rtx t0 = gen_reg_rtx (SImode);
1375     rtx t1 = gen_reg_rtx (SImode);
1376     rtx t2 = gen_reg_rtx (SImode);
1377     rtx t3 = gen_reg_rtx (SImode);
1378     rtx t4 = gen_reg_rtx (SImode);
1379     rtx t5 = gen_reg_rtx (SImode);
1380     rtx t6 = gen_reg_rtx (SImode);
1381     rtx t7 = gen_reg_rtx (SImode);
1382     rtx t8 = gen_reg_rtx (SImode);
1383     rtx t9 = gen_reg_rtx (SImode);
1384     rtx t11 = gen_reg_rtx (SImode);
1385     rtx t12 = gen_reg_rtx (SImode);
1386     rtx t14 = gen_reg_rtx (SImode);
1387     rtx t15 = gen_reg_rtx (HImode);
1388     rtx t16 = gen_reg_rtx (HImode);
1389     rtx t17 = gen_reg_rtx (HImode);
1390     rtx t18 = gen_reg_rtx (HImode);
1391     rtx t19 = gen_reg_rtx (SImode);
1392     rtx t20 = gen_reg_rtx (SImode);
1393     rtx t21 = gen_reg_rtx (SImode);
1394     rtx op1_hi = gen_rtx_SUBREG (HImode, operands[1], 2);
1395     rtx op2_hi = gen_rtx_SUBREG (HImode, operands[2], 2);
1396     rtx t0_hi = gen_rtx_SUBREG (HImode, t0, 2);
1397     rtx t1_hi = gen_rtx_SUBREG (HImode, t1, 2);
1398
1399     emit_insn (gen_lshrsi3 (t0, operands[1], GEN_INT (16)));
1400     emit_insn (gen_lshrsi3 (t1, operands[2], GEN_INT (16)));
1401     emit_insn (gen_umulhisi3 (t2, op1_hi, op2_hi));
1402     emit_insn (gen_mpyh_si (t3, operands[1], operands[2]));
1403     emit_insn (gen_mpyh_si (t4, operands[2], operands[1]));
1404     emit_insn (gen_mpyhh_si (t5, operands[1], operands[2]));
1405     emit_insn (gen_mpys_si (t6, t0_hi, op2_hi));
1406     emit_insn (gen_mpys_si (t7, t1_hi, op1_hi));
1407
1408     /* Gen carry bits (in t9 and t11). */
1409     emit_insn (gen_addsi3 (t8, t2, t3));
1410     emit_insn (gen_cg_si (t9, t2, t3));
1411     emit_insn (gen_cg_si (t11, t8, t4));
1412
1413     /* Gen high 32 bits in operand[0].  Correct for mpys. */
1414     emit_insn (gen_addx_si (t12, t5, t6, t9));
1415     emit_insn (gen_addx_si (t14, t12, t7, t11));
1416
1417     /* mpys treats both operands as signed when we really want it to treat
1418        the first operand as signed and the second operand as unsigned.
1419        The code below corrects for that difference.  */
1420     emit_insn (gen_cgt_hi (t15, op1_hi, GEN_INT (-1)));
1421     emit_insn (gen_cgt_hi (t16, op2_hi, GEN_INT (-1)));
1422     emit_insn (gen_andc_hi (t17, t1_hi, t15));
1423     emit_insn (gen_andc_hi (t18, t0_hi, t16));
1424     emit_insn (gen_extendhisi2 (t19, t17));
1425     emit_insn (gen_extendhisi2 (t20, t18));
1426     emit_insn (gen_addsi3 (t21, t19, t20));
1427     emit_insn (gen_addsi3 (operands[0], t14, t21));
1428     DONE;
1429   })
1430
1431 (define_expand "umulsi3_highpart"
1432   [(set (match_operand:SI 0 "register_operand" "")
1433         (truncate:SI
1434           (ashiftrt:DI
1435             (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
1436                      (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1437             (const_int 32))))]
1438   ""
1439   
1440   {
1441     rtx t0 = gen_reg_rtx (SImode);
1442     rtx t1 = gen_reg_rtx (SImode);
1443     rtx t2 = gen_reg_rtx (SImode);
1444     rtx t3 = gen_reg_rtx (SImode);
1445     rtx t4 = gen_reg_rtx (SImode);
1446     rtx t5 = gen_reg_rtx (SImode);
1447     rtx t6 = gen_reg_rtx (SImode);
1448     rtx t7 = gen_reg_rtx (SImode);
1449     rtx t8 = gen_reg_rtx (SImode);
1450     rtx t9 = gen_reg_rtx (SImode);
1451     rtx t10 = gen_reg_rtx (SImode);
1452     rtx t12 = gen_reg_rtx (SImode);
1453     rtx t13 = gen_reg_rtx (SImode);
1454     rtx t14 = gen_reg_rtx (SImode);
1455     rtx op1_hi = gen_rtx_SUBREG (HImode, operands[1], 2);
1456     rtx op2_hi = gen_rtx_SUBREG (HImode, operands[2], 2);
1457     rtx t0_hi = gen_rtx_SUBREG (HImode, t0, 2);
1458
1459     emit_insn (gen_rotlsi3 (t0, operands[2], GEN_INT (16)));
1460     emit_insn (gen_umulhisi3 (t1, op1_hi, op2_hi));
1461     emit_insn (gen_umulhisi3 (t2, op1_hi, t0_hi));
1462     emit_insn (gen_mpyhhu_si (t3, operands[1], t0));
1463     emit_insn (gen_mpyhhu_si (t4, operands[1], operands[2]));
1464     emit_insn (gen_ashlsi3 (t5, t2, GEN_INT (16)));
1465     emit_insn (gen_ashlsi3 (t6, t3, GEN_INT (16)));
1466     emit_insn (gen_lshrsi3 (t7, t2, GEN_INT (16)));
1467     emit_insn (gen_lshrsi3 (t8, t3, GEN_INT (16)));
1468
1469     /* Gen carry bits (in t10 and t12). */
1470     emit_insn (gen_addsi3 (t9, t1, t5));
1471     emit_insn (gen_cg_si (t10, t1, t5));
1472     emit_insn (gen_cg_si (t12, t9, t6));
1473
1474     /* Gen high 32 bits in operand[0]. */
1475     emit_insn (gen_addx_si (t13, t4, t7, t10));
1476     emit_insn (gen_addx_si (t14, t13, t8, t12));
1477     emit_insn (gen_movsi (operands[0], t14));
1478
1479     DONE;
1480   })
1481 \f
1482 ;; div
1483
1484 ;; Not necessarily the best implementation of divide but faster then
1485 ;; the default that gcc provides because this is inlined and it uses
1486 ;; clz.
1487 (define_insn "divmodsi4"
1488       [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
1489             (div:SI (match_operand:SI 1 "spu_reg_operand" "r")
1490                     (match_operand:SI 2 "spu_reg_operand" "r")))
1491        (set (match_operand:SI 3 "spu_reg_operand" "=&r")
1492             (mod:SI (match_dup 1)
1493                     (match_dup 2)))
1494        (clobber (match_scratch:SI 4 "=&r"))
1495        (clobber (match_scratch:SI 5 "=&r"))
1496        (clobber (match_scratch:SI 6 "=&r"))
1497        (clobber (match_scratch:SI 7 "=&r"))
1498        (clobber (match_scratch:SI 8 "=&r"))
1499        (clobber (match_scratch:SI 9 "=&r"))
1500        (clobber (match_scratch:SI 10 "=&r"))
1501        (clobber (match_scratch:SI 11 "=&r"))
1502        (clobber (match_scratch:SI 12 "=&r"))
1503        (clobber (reg:SI 130))]
1504   ""
1505   "heqi %2,0\\n\\
1506         hbrr    3f,1f\\n\\
1507         sfi     %8,%1,0\\n\\
1508         sfi     %9,%2,0\\n\\
1509         cgti    %10,%1,-1\\n\\
1510         cgti    %11,%2,-1\\n\\
1511         selb    %8,%8,%1,%10\\n\\
1512         selb    %9,%9,%2,%11\\n\\
1513         clz     %4,%8\\n\\
1514         clz     %7,%9\\n\\
1515         il      %5,1\\n\\
1516         fsmbi   %0,0\\n\\
1517         sf      %7,%4,%7\\n\\
1518         shlqbyi %3,%8,0\\n\\
1519         xor     %11,%10,%11\\n\\
1520         shl     %5,%5,%7\\n\\
1521         shl     %4,%9,%7\\n\\
1522         lnop    \\n\\
1523 1:      or      %12,%0,%5\\n\\
1524         rotqmbii        %5,%5,-1\\n\\
1525         clgt    %6,%4,%3\\n\\
1526         lnop    \\n\\
1527         sf      %7,%4,%3\\n\\
1528         rotqmbii        %4,%4,-1\\n\\
1529         selb    %0,%12,%0,%6\\n\\
1530         lnop    \\n\\
1531         selb    %3,%7,%3,%6\\n\\
1532 3:      brnz    %5,1b\\n\\
1533 2:      sfi     %8,%3,0\\n\\
1534         sfi     %9,%0,0\\n\\
1535         selb    %3,%8,%3,%10\\n\\
1536         selb    %0,%0,%9,%11"
1537   [(set_attr "type" "multi0")
1538    (set_attr "length" "128")])
1539
1540 (define_insn "udivmodsi4"
1541       [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
1542             (udiv:SI (match_operand:SI 1 "spu_reg_operand" "r")
1543                      (match_operand:SI 2 "spu_reg_operand" "r")))
1544        (set (match_operand:SI 3 "spu_reg_operand" "=&r")
1545             (umod:SI (match_dup 1)
1546                      (match_dup 2)))
1547        (clobber (match_scratch:SI 4 "=&r"))
1548        (clobber (match_scratch:SI 5 "=&r"))
1549        (clobber (match_scratch:SI 6 "=&r"))
1550        (clobber (match_scratch:SI 7 "=&r"))
1551        (clobber (match_scratch:SI 8 "=&r"))
1552        (clobber (reg:SI 130))]
1553   ""
1554   "heqi %2,0\\n\\
1555         hbrr    3f,1f\\n\\
1556         clz     %7,%2\\n\\
1557         clz     %4,%1\\n\\
1558         il      %5,1\\n\\
1559         fsmbi   %0,0\\n\\
1560         sf      %7,%4,%7\\n\\
1561         ori     %3,%1,0\\n\\
1562         shl     %5,%5,%7\\n\\
1563         shl     %4,%2,%7\\n\\
1564 1:      or      %8,%0,%5\\n\\
1565         rotqmbii        %5,%5,-1\\n\\
1566         clgt    %6,%4,%3\\n\\
1567         lnop    \\n\\
1568         sf      %7,%4,%3\\n\\
1569         rotqmbii        %4,%4,-1\\n\\
1570         selb    %0,%8,%0,%6\\n\\
1571         lnop    \\n\\
1572         selb    %3,%7,%3,%6\\n\\
1573 3:      brnz    %5,1b\\n\\
1574 2:"
1575   [(set_attr "type" "multi0")
1576    (set_attr "length" "80")])
1577
1578 (define_insn_and_split "div<mode>3"
1579   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1580         (div:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1581                  (match_operand:VSF 2 "spu_reg_operand" "r")))
1582    (clobber (match_scratch:VSF 3 "=&r"))
1583    (clobber (match_scratch:VSF 4 "=&r"))]
1584   ""
1585   "#"
1586   "reload_completed"
1587   [(set (match_dup:VSF 0)
1588         (div:VSF (match_dup:VSF 1)
1589                  (match_dup:VSF 2)))
1590    (clobber (match_dup:VSF 3))
1591    (clobber (match_dup:VSF 4))]
1592   {
1593     emit_insn(gen_frest_<mode>(operands[3], operands[2]));
1594     emit_insn(gen_fi_<mode>(operands[3], operands[2], operands[3]));
1595     emit_insn(gen_mul<mode>3(operands[4], operands[1], operands[3]));
1596     emit_insn(gen_fnms_<mode>(operands[0], operands[4], operands[2], operands[1]));
1597     emit_insn(gen_fma_<mode>(operands[0], operands[0], operands[3], operands[4]));
1598     DONE;
1599   })
1600
1601 \f
1602 ;; sqrt
1603
1604 (define_insn_and_split "sqrtsf2"
1605   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
1606         (sqrt:SF (match_operand:SF 1 "spu_reg_operand" "r")))
1607    (clobber (match_scratch:SF 2 "=&r"))
1608    (clobber (match_scratch:SF 3 "=&r"))
1609    (clobber (match_scratch:SF 4 "=&r"))
1610    (clobber (match_scratch:SF 5 "=&r"))]
1611   ""
1612   "#"
1613   "reload_completed"
1614   [(set (match_dup:SF 0)
1615         (sqrt:SF (match_dup:SF 1)))
1616    (clobber (match_dup:SF 2))
1617    (clobber (match_dup:SF 3))
1618    (clobber (match_dup:SF 4))
1619    (clobber (match_dup:SF 5))]
1620   {
1621     emit_move_insn (operands[3],spu_float_const(\"0.5\",SFmode));
1622     emit_move_insn (operands[4],spu_float_const(\"1.00000011920928955078125\",SFmode));
1623     emit_insn(gen_frsqest_sf(operands[2],operands[1]));
1624     emit_insn(gen_fi_sf(operands[2],operands[1],operands[2]));
1625     emit_insn(gen_mulsf3(operands[5],operands[2],operands[1]));
1626     emit_insn(gen_mulsf3(operands[3],operands[5],operands[3]));
1627     emit_insn(gen_fnms_sf(operands[4],operands[2],operands[5],operands[4]));
1628     emit_insn(gen_fma_sf(operands[0],operands[4],operands[3],operands[5]));
1629     DONE;
1630   })
1631
1632 (define_insn "frest_<mode>"
1633   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1634         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")] UNSPEC_FREST))]
1635   ""
1636   "frest\t%0,%1"
1637   [(set_attr "type" "shuf")])
1638
1639 (define_insn "frsqest_<mode>"
1640   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1641         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")] UNSPEC_FRSQEST))]
1642   ""
1643   "frsqest\t%0,%1"
1644   [(set_attr "type" "shuf")])
1645
1646 (define_insn "fi_<mode>"
1647   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1648         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")
1649                     (match_operand:VSF 2 "spu_reg_operand" "r")] UNSPEC_FI))]
1650   ""
1651   "fi\t%0,%1,%2"
1652   [(set_attr "type" "fp7")])
1653
1654 \f
1655 ;; and
1656
1657 (define_insn "and<mode>3"
1658   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r")
1659         (and:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r")
1660                  (match_operand:MOV 2 "spu_logical_operand" "r,C")))]
1661   ""
1662   "@
1663   and\t%0,%1,%2
1664   and%j2i\t%0,%1,%J2")
1665
1666 (define_insn "anddi3"
1667   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
1668         (and:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
1669                 (match_operand:DI 2 "spu_logical_operand" "r,c")))]
1670   ""
1671   "@
1672   and\t%0,%1,%2
1673   and%k2i\t%0,%1,%K2")
1674
1675 (define_insn "andti3"
1676   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
1677         (and:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
1678                 (match_operand:TI 2 "spu_logical_operand" "r,Y")))]
1679   ""
1680   "@
1681   and\t%0,%1,%2
1682   and%m2i\t%0,%1,%L2")
1683
1684 (define_insn "andc_<mode>"
1685   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1686         (and:ALL (not:ALL (match_operand:ALL 2 "spu_reg_operand" "r"))
1687                  (match_operand:ALL 1 "spu_reg_operand" "r")))]
1688   ""
1689   "andc\t%0,%1,%2")
1690
1691 (define_insn "nand_<mode>"
1692   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1693         (not:ALL (and:ALL (match_operand:ALL 2 "spu_reg_operand" "r")
1694                           (match_operand:ALL 1 "spu_reg_operand" "r"))))]
1695   ""
1696   "nand\t%0,%1,%2")
1697
1698 \f
1699 ;; ior
1700
1701 (define_insn "ior<mode>3"
1702   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r,r")
1703         (ior:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r,0")
1704                  (match_operand:MOV 2 "spu_ior_operand" "r,C,D")))]
1705   ""
1706   "@
1707   or\t%0,%1,%2
1708   or%j2i\t%0,%1,%J2
1709   iohl\t%0,%J2")
1710
1711 (define_insn "iordi3"
1712   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r,r")
1713         (ior:DI (match_operand:DI 1 "spu_reg_operand" "r,r,0")
1714                 (match_operand:DI 2 "spu_ior_operand" "r,c,d")))]
1715   ""
1716   "@
1717   or\t%0,%1,%2
1718   or%k2i\t%0,%1,%K2
1719   iohl\t%0,%K2")
1720
1721 (define_insn "iorti3"
1722   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r,r")
1723         (ior:TI (match_operand:TI 1 "spu_reg_operand" "r,r,0")
1724                 (match_operand:TI 2 "spu_ior_operand" "r,Y,Z")))]
1725   ""
1726   "@
1727   or\t%0,%1,%2
1728   or%m2i\t%0,%1,%L2
1729   iohl\t%0,%L2")
1730
1731 (define_insn "orc_<mode>"
1732   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1733         (ior:ALL (not:ALL (match_operand:ALL 2 "spu_reg_operand" "r"))
1734                  (match_operand:ALL 1 "spu_reg_operand" "r")))]
1735   ""
1736   "orc\t%0,%1,%2")
1737
1738 (define_insn "nor_<mode>"
1739   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1740         (not:ALL (ior:ALL (match_operand:ALL 1 "spu_reg_operand" "r")
1741                           (match_operand:ALL 2 "spu_reg_operand" "r"))))]
1742   ""
1743   "nor\t%0,%1,%2")
1744 \f
1745 ;; xor
1746
1747 (define_insn "xor<mode>3"
1748   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r")
1749         (xor:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r")
1750                  (match_operand:MOV 2 "spu_logical_operand" "r,B")))]
1751   ""
1752   "@
1753   xor\t%0,%1,%2
1754   xor%j2i\t%0,%1,%J2")
1755
1756 (define_insn "xordi3"
1757   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
1758         (xor:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
1759                 (match_operand:DI 2 "spu_logical_operand" "r,c")))]
1760   ""
1761   "@
1762   xor\t%0,%1,%2
1763   xor%k2i\t%0,%1,%K2")
1764
1765 (define_insn "xorti3"
1766   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
1767         (xor:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
1768                 (match_operand:TI 2 "spu_logical_operand" "r,Y")))]
1769   ""
1770   "@
1771   xor\t%0,%1,%2
1772   xor%m2i\t%0,%1,%L2")
1773
1774 (define_insn "eqv_<mode>"
1775   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1776         (not:ALL (xor:ALL (match_operand:ALL 1 "spu_reg_operand" "r")
1777                           (match_operand:ALL 2 "spu_reg_operand" "r"))))]
1778   ""
1779   "eqv\t%0,%1,%2")
1780 \f
1781 ;; one_cmpl
1782
1783 (define_insn "one_cmpl<mode>2"
1784   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1785         (not:ALL (match_operand:ALL 1 "spu_reg_operand" "r")))]
1786   ""
1787   "nor\t%0,%1,%1")
1788
1789 \f
1790 ;; selb
1791
1792 (define_expand "selb"
1793   [(set (match_operand 0 "spu_reg_operand" "")
1794         (unspec [(match_operand 1 "spu_reg_operand" "")
1795                  (match_operand 2 "spu_reg_operand" "")
1796                  (match_operand 3 "spu_reg_operand" "")] UNSPEC_SELB))]
1797   ""
1798   {
1799     rtx s = gen__selb (operands[0], operands[1], operands[2], operands[3]);
1800     PUT_MODE (SET_SRC (s), GET_MODE (operands[0]));
1801     emit_insn (s);
1802     DONE;
1803   })
1804
1805 ;; This could be defined as a combination of logical operations, but at
1806 ;; one time it caused a crash due to recursive expansion of rtl during CSE.
1807 (define_insn "_selb"
1808   [(set (match_operand 0 "spu_reg_operand" "=r")
1809         (unspec [(match_operand 1 "spu_reg_operand" "r")
1810                  (match_operand 2 "spu_reg_operand" "r")
1811                  (match_operand 3 "spu_reg_operand" "r")] UNSPEC_SELB))]
1812   "GET_MODE(operands[0]) == GET_MODE(operands[1]) 
1813    && GET_MODE(operands[1]) == GET_MODE(operands[2])"
1814   "selb\t%0,%1,%2,%3")
1815
1816 \f
1817 ;; Misc. byte/bit operations
1818 ;; clz/ctz/ffs/popcount/parity
1819 ;; cntb/sumb
1820
1821 (define_insn "clz<mode>2"
1822   [(set (match_operand:VSI 0 "spu_reg_operand" "=r")
1823         (clz:VSI (match_operand:VSI 1 "spu_reg_operand" "r")))]
1824   ""
1825   "clz\t%0,%1")
1826
1827 (define_expand "ctz<mode>2"
1828   [(set (match_dup 2)
1829         (neg:VSI (match_operand:VSI 1 "spu_reg_operand" "")))
1830    (set (match_dup 3) (and:VSI (match_dup 1)
1831                                (match_dup 2)))
1832    (set (match_dup 4) (clz:VSI (match_dup 3)))
1833    (set (match_operand:VSI 0 "spu_reg_operand" "")
1834         (minus:VSI (match_dup 5) (match_dup 4)))]
1835   ""
1836   {
1837      operands[2] = gen_reg_rtx (<MODE>mode);
1838      operands[3] = gen_reg_rtx (<MODE>mode);
1839      operands[4] = gen_reg_rtx (<MODE>mode);
1840      operands[5] = spu_const(<MODE>mode, 31);
1841   })
1842
1843 (define_expand "ffs<mode>2"
1844   [(set (match_dup 2)
1845         (neg:VSI (match_operand:VSI 1 "spu_reg_operand" "")))
1846    (set (match_dup 3) (and:VSI (match_dup 1)
1847                                (match_dup 2)))
1848    (set (match_dup 4) (clz:VSI (match_dup 3)))
1849    (set (match_operand:VSI 0 "spu_reg_operand" "")
1850         (minus:VSI (match_dup 5) (match_dup 4)))]
1851   ""
1852   {
1853      operands[2] = gen_reg_rtx (<MODE>mode);
1854      operands[3] = gen_reg_rtx (<MODE>mode);
1855      operands[4] = gen_reg_rtx (<MODE>mode);
1856      operands[5] = spu_const(<MODE>mode, 32);
1857   })
1858
1859 (define_expand "popcountsi2"
1860   [(set (match_dup 2)
1861         (unspec:SI [(match_operand:SI 1 "spu_reg_operand" "")]
1862                      UNSPEC_CNTB))
1863    (set (match_dup 3)
1864         (unspec:HI [(match_dup 2)] UNSPEC_SUMB))
1865    (set (match_operand:SI 0 "spu_reg_operand" "")
1866         (sign_extend:SI (match_dup 3)))]
1867   ""
1868   {
1869     operands[2] = gen_reg_rtx (SImode);
1870     operands[3] = gen_reg_rtx (HImode);
1871   })
1872
1873 (define_expand "paritysi2"
1874   [(set (match_operand:SI 0 "spu_reg_operand" "")
1875         (parity:SI (match_operand:SI 1 "spu_reg_operand" "")))]
1876   ""
1877   {
1878     operands[2] = gen_reg_rtx (SImode);
1879     emit_insn (gen_popcountsi2(operands[2], operands[1]));
1880     emit_insn (gen_andsi3(operands[0], operands[2], GEN_INT (1)));
1881     DONE;
1882   })
1883
1884 (define_insn "cntb_si"
1885   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1886         (unspec:SI [(match_operand:SI 1 "spu_reg_operand" "r")]
1887                    UNSPEC_CNTB))]
1888   ""
1889   "cntb\t%0,%1"
1890   [(set_attr "type" "fxb")])
1891
1892 (define_insn "cntb_v16qi"
1893   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
1894         (unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r")]
1895                       UNSPEC_CNTB))]
1896   ""
1897   "cntb\t%0,%1"
1898   [(set_attr "type" "fxb")])
1899
1900 (define_insn "sumb_si"
1901   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
1902         (unspec:HI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_SUMB))]
1903   ""
1904   "sumb\t%0,%1,%1"
1905   [(set_attr "type" "fxb")])
1906
1907 \f
1908 ;; ashl
1909
1910 (define_insn "ashl<mode>3"
1911   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
1912         (ashift:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
1913                      (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))]
1914   ""
1915   "@
1916   shl<bh>\t%0,%1,%2
1917   shl<bh>i\t%0,%1,%<umask>2"
1918   [(set_attr "type" "fx3")])
1919
1920 (define_insn_and_split "ashldi3"
1921   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
1922         (ashift:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
1923                    (match_operand:SI 2 "spu_nonmem_operand" "r,I")))
1924    (clobber (match_scratch:SI 3 "=&r,X"))]
1925   ""
1926   "#"
1927   "reload_completed"
1928   [(set (match_dup:DI 0)
1929         (ashift:DI (match_dup:DI 1)
1930                    (match_dup:SI 2)))]
1931   {
1932     rtx op0 = gen_rtx_REG (TImode, REGNO (operands[0]));
1933     rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
1934     rtx op2 = operands[2];
1935     rtx op3 = operands[3];
1936
1937     if (GET_CODE (operands[2]) == REG)
1938       {
1939         emit_insn (gen_addsi3 (op3, op2, GEN_INT (64)));
1940         emit_insn (gen_rotlti3 (op0, op1, GEN_INT (64)));
1941         emit_insn (gen_shlqbybi_ti (op0, op0, op3));
1942         emit_insn (gen_shlqbi_ti (op0, op0, op3));
1943       }
1944     else
1945       {
1946         HOST_WIDE_INT val = INTVAL (operands[2]);
1947         emit_insn (gen_rotlti3 (op0, op1, GEN_INT (64)));
1948         emit_insn (gen_shlqby_ti (op0, op0, GEN_INT (val / 8 + 8)));
1949         if (val % 8)
1950           emit_insn (gen_shlqbi_ti (op0, op0, GEN_INT (val % 8)));
1951       }
1952     DONE;
1953   })
1954
1955 (define_expand "ashlti3"
1956   [(parallel [(set (match_operand:TI 0 "spu_reg_operand" "")
1957                    (ashift:TI (match_operand:TI 1 "spu_reg_operand" "")
1958                               (match_operand:SI 2 "spu_nonmem_operand" "")))
1959               (clobber (match_dup:TI 3))])]
1960   ""
1961   "if (GET_CODE (operands[2]) == CONST_INT)
1962     {
1963       emit_insn(gen_ashlti3_imm(operands[0], operands[1], operands[2]));
1964       DONE;
1965     }
1966    operands[3] = gen_reg_rtx (TImode);")
1967
1968 (define_insn_and_split "ashlti3_imm"
1969   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
1970         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
1971                    (match_operand:SI 2 "immediate_operand" "O,P")))]
1972   ""
1973   "@
1974    shlqbyi\t%0,%1,%h2
1975    shlqbii\t%0,%1,%e2"
1976   "!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
1977   [(set (match_dup:TI 0)
1978         (ashift:TI (match_dup:TI 1)
1979                    (match_dup:SI 3)))
1980    (set (match_dup:TI 0)
1981         (ashift:TI (match_dup:TI 0)
1982                    (match_dup:SI 4)))]
1983   {
1984     HOST_WIDE_INT val = INTVAL(operands[2]);
1985     operands[3] = GEN_INT (val&7);
1986     operands[4] = GEN_INT (val&-8);
1987   }
1988   [(set_attr "type" "shuf,shuf")])
1989
1990 (define_insn_and_split "ashlti3_reg"
1991   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
1992         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r")
1993                    (match_operand:SI 2 "spu_reg_operand" "r")))
1994    (clobber (match_operand:TI 3 "spu_reg_operand" "=&r"))]
1995   ""
1996   "#"
1997   ""
1998   [(set (match_dup:TI 3)
1999         (ashift:TI (match_dup:TI 1)
2000                    (and:SI (match_dup:SI 2)
2001                            (const_int 7))))
2002    (set (match_dup:TI 0)
2003         (ashift:TI (match_dup:TI 3)
2004                    (and:SI (match_dup:SI 2)
2005                            (const_int -8))))]
2006   "")
2007
2008 (define_insn "shlqbybi_ti"
2009   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2010         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2011                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2012                            (const_int -8))))]
2013   ""
2014   "@
2015    shlqbybi\t%0,%1,%2
2016    shlqbyi\t%0,%1,%h2"
2017   [(set_attr "type" "shuf,shuf")])
2018
2019 (define_insn "shlqbi_ti"
2020   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2021         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2022                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2023                            (const_int 7))))]
2024   ""
2025   "@
2026    shlqbi\t%0,%1,%2
2027    shlqbii\t%0,%1,%e2"
2028   [(set_attr "type" "shuf,shuf")])
2029
2030 (define_insn "shlqby_ti"
2031   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2032         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2033                    (mult:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2034                             (const_int 8))))]
2035   ""
2036   "@
2037    shlqby\t%0,%1,%2
2038    shlqbyi\t%0,%1,%f2"
2039   [(set_attr "type" "shuf,shuf")])
2040
2041 \f
2042 ;; lshr
2043
2044 (define_insn_and_split "lshr<mode>3"
2045   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2046         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2047                        (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))
2048    (clobber (match_scratch:VHSI 3 "=&r,X"))]
2049   ""
2050   "@
2051    #
2052    rot<bh>mi\t%0,%1,-%<umask>2"
2053   "reload_completed && GET_CODE (operands[2]) == REG"
2054   [(set (match_dup:VHSI 3)
2055         (neg:VHSI (match_dup:VHSI 2)))
2056    (set (match_dup:VHSI 0)
2057         (lshiftrt:VHSI (match_dup:VHSI 1)
2058                        (neg:VHSI (match_dup:VHSI 3))))]
2059   ""
2060   [(set_attr "type" "*,fx3")])
2061   
2062
2063 (define_insn "rotm_<mode>"
2064   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2065         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2066                        (neg:VHSI (match_operand:VHSI 2 "spu_nonmem_operand" "r,W"))))]
2067   ""
2068   "@
2069    rot<bh>m\t%0,%1,%2
2070    rot<bh>mi\t%0,%1,-%<nmask>2"
2071   [(set_attr "type" "fx3")])
2072  
2073 (define_expand "lshr<mode>3"
2074   [(parallel [(set (match_operand:DTI 0 "spu_reg_operand" "")
2075                    (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "")
2076                                  (match_operand:SI 2 "spu_nonmem_operand" "")))
2077               (clobber (match_dup:DTI 3))
2078               (clobber (match_dup:SI 4))
2079               (clobber (match_dup:SI 5))])]
2080   ""
2081   "if (GET_CODE (operands[2]) == CONST_INT)
2082     {
2083       emit_insn(gen_lshr<mode>3_imm(operands[0], operands[1], operands[2]));
2084       DONE;
2085     }
2086    operands[3] = gen_reg_rtx (<MODE>mode);
2087    operands[4] = gen_reg_rtx (SImode);
2088    operands[5] = gen_reg_rtx (SImode);")
2089
2090 (define_insn_and_split "lshr<mode>3_imm"
2091   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2092         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2093                       (match_operand:SI 2 "immediate_operand" "O,P")))]
2094   ""
2095   "@
2096    rotqmbyi\t%0,%1,-%h2
2097    rotqmbii\t%0,%1,-%e2"
2098   "!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
2099   [(set (match_dup:DTI 0)
2100         (lshiftrt:DTI (match_dup:DTI 1)
2101                       (match_dup:SI 4)))
2102    (set (match_dup:DTI 0)
2103         (lshiftrt:DTI (match_dup:DTI 0)
2104                       (match_dup:SI 5)))]
2105   {
2106     HOST_WIDE_INT val = INTVAL(operands[2]);
2107     operands[4] = GEN_INT (val&7);
2108     operands[5] = GEN_INT (val&-8);
2109   }
2110   [(set_attr "type" "shuf,shuf")])
2111
2112 (define_insn_and_split "lshr<mode>3_reg"
2113   [(set (match_operand:DTI 0 "spu_reg_operand" "=r")
2114         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r")
2115                       (match_operand:SI 2 "spu_reg_operand" "r")))
2116    (clobber (match_operand:DTI 3 "spu_reg_operand" "=&r"))
2117    (clobber (match_operand:SI 4 "spu_reg_operand" "=&r"))
2118    (clobber (match_operand:SI 5 "spu_reg_operand" "=&r"))]
2119   ""
2120   "#"
2121   ""
2122   [(set (match_dup:DTI 3)
2123         (lshiftrt:DTI (match_dup:DTI 1)
2124                      (and:SI (neg:SI (match_dup:SI 4))
2125                              (const_int 7))))
2126    (set (match_dup:DTI 0)
2127         (lshiftrt:DTI (match_dup:DTI 3)
2128                      (and:SI (neg:SI (and:SI (match_dup:SI 5)
2129                                              (const_int -8)))
2130                              (const_int -8))))]
2131   {
2132     emit_insn(gen_subsi3(operands[4], GEN_INT(0), operands[2]));
2133     emit_insn(gen_subsi3(operands[5], GEN_INT(7), operands[2]));
2134   })
2135
2136 (define_insn "rotqmbybi_<mode>"
2137   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2138         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2139                       (and:SI (neg:SI (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2140                                               (const_int -8)))
2141                               (const_int -8))))]
2142   ""
2143   "@
2144    rotqmbybi\t%0,%1,%2
2145    rotqmbyi\t%0,%1,-%H2"
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,-%E2"
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,-%F2"
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_nonmem_operand" "r,W")))
2177    (clobber (match_scratch:VHSI 3 "=&r,X"))]
2178   ""
2179   "@
2180    #
2181    rotma<bh>i\t%0,%1,-%<umask>2"
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_nonmem_operand" "r,W"))))]
2196   ""
2197   "@
2198    rotma<bh>\t%0,%1,%2
2199    rotma<bh>i\t%0,%1,-%<nmask>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_nonmem_operand" "r,W")))]
2310   ""
2311   "@
2312   rot<bh>\t%0,%1,%2
2313   rot<bh>i\t%0,%1,%<umask>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,%h2
2324   rotqbii\t%0,%1,%e2
2325   rotqbyi\t%0,%1,%h2\;rotqbii\t%0,%0,%e2"
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,%h2"
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,%f2"
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,%e2"
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 "type" "convert")
3094    (set_attr "length" "0")])
3095
3096 (define_expand "epilogue"
3097   [(const_int 2)]
3098   ""
3099   { spu_expand_epilogue (false); DONE; })
3100
3101 (define_expand "sibcall_epilogue"
3102   [(const_int 2)]
3103   ""
3104   { spu_expand_epilogue (true); DONE; })
3105
3106 \f
3107 ;; stack manipulations
3108
3109 ;; An insn to allocate new stack space for dynamic use (e.g., alloca).
3110 ;; We move the back-chain and decrement the stack pointer.
3111 (define_expand "allocate_stack"
3112   [(set (match_operand 0 "spu_reg_operand" "")
3113         (minus (reg 1) (match_operand 1 "spu_nonmem_operand" "")))
3114    (set (reg 1)
3115         (minus (reg 1) (match_dup 1)))]
3116   ""
3117   "spu_allocate_stack (operands[0], operands[1]); DONE;")
3118
3119 ;; These patterns say how to save and restore the stack pointer.  We need not
3120 ;; save the stack pointer at function level since we are careful to preserve 
3121 ;; the backchain.  
3122 ;; 
3123
3124 ;; At block level the stack pointer is saved and restored, so that the
3125 ;; stack space allocated within a block is deallocated when leaving
3126 ;; block scope.  By default, according to the SPU ABI, the stack
3127 ;; pointer and available stack size are saved in a register. Upon
3128 ;; restoration, the stack pointer is simply copied back, and the
3129 ;; current available stack size is calculated against the restored
3130 ;; stack pointer.
3131 ;;
3132 ;; For nonlocal gotos, we must save the stack pointer and its
3133 ;; backchain and restore both.  Note that in the nonlocal case, the
3134 ;; save area is a memory location.
3135
3136 (define_expand "save_stack_function"
3137   [(match_operand 0 "general_operand" "")
3138    (match_operand 1 "general_operand" "")]
3139   ""
3140   "DONE;")
3141
3142 (define_expand "restore_stack_function"
3143   [(match_operand 0 "general_operand" "")
3144    (match_operand 1 "general_operand" "")]
3145   ""
3146   "DONE;")
3147
3148 (define_expand "restore_stack_block"
3149   [(match_operand 0 "spu_reg_operand" "")
3150    (match_operand 1 "memory_operand" "")]
3151   ""
3152   "
3153   {
3154     spu_restore_stack_block (operands[0], operands[1]);
3155     DONE;
3156   }")
3157
3158 (define_expand "save_stack_nonlocal"
3159   [(match_operand 0 "memory_operand" "")
3160    (match_operand 1 "spu_reg_operand" "")]
3161   ""
3162   "
3163   {
3164     rtx temp = gen_reg_rtx (Pmode);
3165
3166     /* Copy the backchain to the first word, sp to the second.  We need to
3167        save the back chain because __builtin_apply appears to clobber it. */
3168     emit_move_insn (temp, gen_rtx_MEM (Pmode, operands[1]));
3169     emit_move_insn (adjust_address_nv (operands[0], SImode, 0), temp);
3170     emit_move_insn (adjust_address_nv (operands[0], SImode, 4), operands[1]);
3171     DONE;
3172   }")
3173
3174 (define_expand "restore_stack_nonlocal"
3175   [(match_operand 0 "spu_reg_operand" "")
3176    (match_operand 1 "memory_operand" "")]
3177   ""
3178   "
3179   {
3180     spu_restore_stack_nonlocal(operands[0], operands[1]);
3181     DONE;
3182   }")
3183
3184 \f
3185 ;; vector patterns
3186
3187 ;; Vector initialization
3188 (define_expand "vec_init<mode>"
3189   [(match_operand:V 0 "register_operand" "")
3190    (match_operand 1 "" "")]
3191   ""
3192   {
3193     spu_expand_vector_init (operands[0], operands[1]);
3194     DONE;
3195   })
3196
3197 (define_expand "vec_set<mode>"
3198   [(use (match_operand:SI 2 "spu_nonmem_operand" ""))
3199    (set (match_dup:TI 3)
3200         (unspec:TI [(match_dup:SI 4)
3201                     (match_dup:SI 5)
3202                     (match_dup:SI 6)] UNSPEC_CPAT))
3203    (set (match_operand:V 0 "spu_reg_operand" "")
3204         (unspec:V [(match_operand:<inner> 1 "spu_reg_operand" "")
3205                    (match_dup:V 0)
3206                    (match_dup:TI 3)] UNSPEC_SHUFB))]
3207   ""
3208   {
3209     HOST_WIDE_INT size = GET_MODE_SIZE (<inner>mode);
3210     rtx offset = GEN_INT (INTVAL (operands[2]) * size);
3211     operands[3] = gen_reg_rtx (TImode);
3212     operands[4] = stack_pointer_rtx;
3213     operands[5] = offset;
3214     operands[6] = GEN_INT (size);
3215   })
3216
3217 (define_expand "vec_extract<mode>"
3218   [(set (match_operand:<inner> 0 "spu_reg_operand" "=r")
3219         (vec_select:<inner> (match_operand:V 1 "spu_reg_operand" "r")
3220                             (parallel [(match_operand 2 "const_int_operand" "i")])))]
3221   ""
3222   {
3223     if ((INTVAL (operands[2]) * <vmult> + <voff>) % 16 == 0)
3224       {
3225         emit_insn (gen_spu_convert (operands[0], operands[1]));
3226         DONE;
3227       }
3228   })
3229
3230 (define_insn "_vec_extract<mode>"
3231   [(set (match_operand:<inner> 0 "spu_reg_operand" "=r")
3232         (vec_select:<inner> (match_operand:V 1 "spu_reg_operand" "r")
3233                             (parallel [(match_operand 2 "const_int_operand" "i")])))]
3234   ""
3235   "rotqbyi\t%0,%1,(%2*<vmult>+<voff>)%%16"
3236   [(set_attr "type" "shuf")])
3237
3238 (define_insn "_vec_extractv8hi_ze"
3239   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3240         (zero_extend:SI (vec_select:HI (match_operand:V8HI 1 "spu_reg_operand" "r")
3241                                        (parallel [(const_int 0)]))))]
3242   ""
3243   "rotqmbyi\t%0,%1,-2"
3244   [(set_attr "type" "shuf")])
3245
3246 \f
3247 ;; misc
3248
3249 (define_expand "shufb"
3250   [(set (match_operand 0 "spu_reg_operand" "")
3251         (unspec [(match_operand 1 "spu_reg_operand" "")
3252                  (match_operand 2 "spu_reg_operand" "")
3253                  (match_operand:TI 3 "spu_reg_operand" "")] UNSPEC_SHUFB))]
3254   ""
3255   {
3256     rtx s = gen__shufb (operands[0], operands[1], operands[2], operands[3]);
3257     PUT_MODE (SET_SRC (s), GET_MODE (operands[0]));
3258     emit_insn (s);
3259     DONE;
3260   })
3261
3262 (define_insn "_shufb"
3263   [(set (match_operand 0 "spu_reg_operand" "=r")
3264         (unspec [(match_operand 1 "spu_reg_operand" "r")
3265                  (match_operand 2 "spu_reg_operand" "r")
3266                  (match_operand:TI 3 "spu_reg_operand" "r")] UNSPEC_SHUFB))]
3267   "operands"
3268   "shufb\t%0,%1,%2,%3"
3269   [(set_attr "type" "shuf")])
3270
3271 (define_insn "nop"
3272   [(unspec_volatile [(const_int 0)] UNSPEC_NOP)]
3273   ""
3274   "nop"
3275   [(set_attr "type" "nop")])
3276
3277 (define_insn "nopn"
3278   [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "K")] UNSPEC_NOP)]
3279   ""
3280   "nop\t%0"
3281   [(set_attr "type" "nop")])
3282
3283 (define_insn "lnop"
3284   [(unspec_volatile [(const_int 0)] UNSPEC_LNOP)]
3285   ""
3286   "lnop"
3287   [(set_attr "type" "lnop")])
3288
3289 (define_insn "iprefetch"
3290   [(unspec [(const_int 0)] UNSPEC_IPREFETCH)]
3291   ""
3292   "hbrp"
3293   [(set_attr "type" "iprefetch")])
3294
3295 (define_insn "hbr"
3296   [(set (reg:SI 130)
3297         (unspec:SI [(match_operand:SI 0 "immediate_operand" "i,i,i")
3298                     (match_operand:SI 1 "nonmemory_operand" "r,s,i")] UNSPEC_HBR))
3299    (unspec [(const_int 0)] UNSPEC_HBR)]
3300   ""
3301   "@
3302    hbr\t%0,%1
3303    hbrr\t%0,%1
3304    hbra\t%0,%1"
3305   [(set_attr "type" "hbr")])
3306
3307 (define_insn "sync"
3308   [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)
3309    (clobber (mem:BLK (scratch)))]
3310   ""
3311   "sync"
3312   [(set_attr "type" "br")])
3313
3314 (define_insn "syncc"
3315   [(unspec_volatile [(const_int 1)] UNSPEC_SYNC)
3316    (clobber (mem:BLK (scratch)))]
3317   ""
3318   "syncc"
3319   [(set_attr "type" "br")])
3320
3321 (define_insn "dsync"
3322   [(unspec_volatile [(const_int 2)] UNSPEC_SYNC)
3323    (clobber (mem:BLK (scratch)))]
3324   ""
3325   "dsync"
3326   [(set_attr "type" "br")])
3327
3328 \f
3329 ;; convert between any two modes, avoiding any GCC assumptions
3330 (define_expand "spu_convert"
3331   [(set (match_operand 0 "spu_reg_operand" "")
3332         (unspec [(match_operand 1 "spu_reg_operand" "")] UNSPEC_CONVERT))]
3333   ""
3334   {
3335     rtx c = gen__spu_convert (operands[0], operands[1]);
3336     PUT_MODE (SET_SRC (c), GET_MODE (operands[0]));
3337     emit_insn (c);
3338     DONE;
3339   })
3340
3341 (define_insn "_spu_convert"
3342   [(set (match_operand 0 "spu_reg_operand" "=r")
3343         (unspec [(match_operand 1 "spu_reg_operand" "0")] UNSPEC_CONVERT))]
3344   "operands"
3345   ""
3346   [(set_attr "type" "convert")
3347    (set_attr "length" "0")])
3348
3349 (define_peephole2
3350   [(set (match_operand 0 "spu_reg_operand")
3351         (unspec [(match_operand 1 "spu_reg_operand")] UNSPEC_CONVERT))]
3352   ""
3353   [(use (const_int 0))]
3354   "")
3355
3356 \f
3357 ;;
3358 (include "spu-builtins.md")
3359
3360   
3361 (define_expand "smaxv4sf3"
3362   [(set (match_operand:V4SF 0 "register_operand" "=r")
3363         (smax:V4SF (match_operand:V4SF 1 "register_operand" "r")
3364                  (match_operand:V4SF 2 "register_operand" "r")))]
3365   ""
3366   "
3367 {
3368   rtx mask = gen_reg_rtx (V4SImode);
3369
3370   emit_insn (gen_cgt_v4sf (mask, operands[1], operands[2]));
3371   emit_insn (gen_selb (operands[0], operands[2], operands[1], mask));
3372   DONE;
3373 }") 
3374
3375 (define_expand "sminv4sf3"
3376   [(set (match_operand:V4SF 0 "register_operand" "=r")
3377         (smax:V4SF (match_operand:V4SF 1 "register_operand" "r")
3378                  (match_operand:V4SF 2 "register_operand" "r")))]
3379   ""
3380   "
3381 {
3382   rtx mask = gen_reg_rtx (V4SImode);
3383
3384   emit_insn (gen_cgt_v4sf (mask, operands[1], operands[2]));
3385   emit_insn (gen_selb (operands[0], operands[1], operands[2], mask));
3386   DONE;
3387 }") 
3388
3389 (define_expand "vec_widen_umult_hi_v8hi"
3390   [(set (match_operand:V4SI 0 "register_operand"   "=r")
3391         (mult:V4SI
3392           (zero_extend:V4SI
3393             (vec_select:V4HI
3394               (match_operand:V8HI 1 "register_operand" "r")
3395               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))
3396           (zero_extend:V4SI
3397             (vec_select:V4HI
3398               (match_operand:V8HI 2 "register_operand" "r")
3399               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))))]
3400   ""
3401   "
3402 {
3403   rtx ve = gen_reg_rtx (V4SImode);
3404   rtx vo = gen_reg_rtx (V4SImode);
3405   rtx mask = gen_reg_rtx (TImode);
3406   unsigned char arr[16] = {
3407     0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 
3408     0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17};
3409   
3410   emit_move_insn (mask, array_to_constant (TImode, arr));
3411   emit_insn (gen_spu_mpyhhu (ve, operands[1], operands[2]));
3412   emit_insn (gen_spu_mpyu (vo, operands[1], operands[2]));
3413   emit_insn (gen_shufb (operands[0], ve, vo, mask));
3414   DONE;
3415 }")
3416
3417 (define_expand "vec_widen_umult_lo_v8hi"
3418   [(set (match_operand:V4SI 0 "register_operand"   "=r")
3419         (mult:V4SI
3420           (zero_extend:V4SI
3421             (vec_select:V4HI
3422               (match_operand:V8HI 1 "register_operand" "r")
3423               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
3424           (zero_extend:V4SI
3425             (vec_select:V4HI
3426               (match_operand:V8HI 2 "register_operand" "r")
3427               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))))]
3428   ""
3429   "
3430 {
3431   rtx ve = gen_reg_rtx (V4SImode);
3432   rtx vo = gen_reg_rtx (V4SImode);
3433   rtx mask = gen_reg_rtx (TImode);
3434   unsigned char arr[16] = {
3435     0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 
3436     0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F};
3437
3438   emit_move_insn (mask, array_to_constant (TImode, arr));
3439   emit_insn (gen_spu_mpyhhu (ve, operands[1], operands[2]));
3440   emit_insn (gen_spu_mpyu (vo, operands[1], operands[2]));
3441   emit_insn (gen_shufb (operands[0], ve, vo, mask));
3442   DONE;
3443 }")
3444
3445 (define_expand "vec_widen_smult_hi_v8hi"
3446   [(set (match_operand:V4SI 0 "register_operand"   "=r")
3447         (mult:V4SI
3448           (sign_extend:V4SI
3449             (vec_select:V4HI
3450               (match_operand:V8HI 1 "register_operand" "r")
3451               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))
3452           (sign_extend:V4SI
3453             (vec_select:V4HI
3454               (match_operand:V8HI 2 "register_operand" "r")
3455               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))))]
3456   ""
3457   "
3458 {
3459   rtx ve = gen_reg_rtx (V4SImode);
3460   rtx vo = gen_reg_rtx (V4SImode);
3461   rtx mask = gen_reg_rtx (TImode);
3462   unsigned char arr[16] = {
3463     0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 
3464     0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17};
3465   
3466   emit_move_insn (mask, array_to_constant (TImode, arr));
3467   emit_insn (gen_spu_mpyhh (ve, operands[1], operands[2]));
3468   emit_insn (gen_spu_mpy (vo, operands[1], operands[2]));
3469   emit_insn (gen_shufb (operands[0], ve, vo, mask));
3470   DONE;
3471 }")
3472
3473 (define_expand "vec_widen_smult_lo_v8hi"
3474   [(set (match_operand:V4SI 0 "register_operand"   "=r")
3475         (mult:V4SI
3476           (sign_extend:V4SI
3477             (vec_select:V4HI
3478               (match_operand:V8HI 1 "register_operand" "r")
3479               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
3480           (sign_extend:V4SI
3481             (vec_select:V4HI
3482               (match_operand:V8HI 2 "register_operand" "r")
3483               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))))]
3484   ""
3485   "
3486 {
3487   rtx ve = gen_reg_rtx (V4SImode);
3488   rtx vo = gen_reg_rtx (V4SImode);
3489   rtx mask = gen_reg_rtx (TImode);
3490   unsigned char arr[16] = {
3491     0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 
3492     0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F};
3493
3494   emit_move_insn (mask, array_to_constant (TImode, arr));
3495   emit_insn (gen_spu_mpyhh (ve, operands[1], operands[2]));
3496   emit_insn (gen_spu_mpy (vo, operands[1], operands[2]));
3497   emit_insn (gen_shufb (operands[0], ve, vo, mask));
3498  &nb