Update concepts branch to revision 131834
[official-gcc.git] / gcc / config / spu / spu.md
blob6985a6836977b24836f90583315bea064d2a2787
1 ;; Copyright (C) 2006, 2007 Free Software Foundation, Inc.
3 ;; This file is free software; you can redistribute it and/or modify it under
4 ;; the terms of the GNU General Public License as published by the Free
5 ;; Software Foundation; either version 3 of the License, or (at your option) 
6 ;; any later version.
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.
13 ;; You should have received a copy of the GNU General Public License
14 ;; along with GCC; see the file COPYING3.  If not see
15 ;; <http://www.gnu.org/licenses/>.
17 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
20 ;; Define an insn type attribute.  This is used in function unit delay
21 ;; computations.
22 ;; multi0 is a multiple insn rtl whose first insn is in pipe0
23 ;; multi1 is a multiple insn rtl whose first insn is in pipe1
24 (define_attr "type" "fx2,shuf,fx3,load,store,br,spr,lnop,nop,fxb,fp6,fp7,fpd,iprefetch,multi0,multi1,hbr,convert"
25   (const_string "fx2"))
27 ;; Length (in bytes).
28 (define_attr "length" ""
29                 (const_int 4))
31 (define_attr "tune" "cell,celledp" (const (symbol_ref "spu_tune")))
32 ;; Processor type -- this attribute must exactly match the processor_type
33 ;; enumeration in spu.h.
35 (define_attr "cpu" "spu"
36   (const (symbol_ref "spu_cpu_attr")))
38 ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
39 ;                       TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
41 (define_cpu_unit "pipe0,pipe1,fp,ls")
43 (define_insn_reservation "NOP" 1 (eq_attr "type" "nop")
44     "pipe0")
46 (define_insn_reservation "FX2" 2 (eq_attr "type" "fx2")
47     "pipe0, nothing")
49 (define_insn_reservation "FX3" 4 (eq_attr "type" "fx3,fxb")
50     "pipe0, nothing*3")
52 (define_insn_reservation "FP6" 6 (eq_attr "type" "fp6")
53     "pipe0 + fp, nothing*5")
55 (define_insn_reservation "FP7" 7 (eq_attr "type" "fp7")
56     "pipe0, fp, nothing*5")
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 
63   (and (eq_attr "tune" "cell")
64        (eq_attr "type" "fpd"))
65     "pipe0 + pipe1, fp, nothing*5")
67 ;; Tune for CELLEDP, 9 cycles, dual-issuable, fully pipelined
68 (define_insn_reservation "FPD_CELLEDP" 9
69   (and (eq_attr "tune" "celledp")
70        (eq_attr "type" "fpd"))
71   "pipe0 + fp, nothing*8")
73 (define_insn_reservation "LNOP" 1 (eq_attr "type" "lnop")
74     "pipe1")
76 (define_insn_reservation "STORE" 1 (eq_attr "type" "store")
77     "pipe1 + ls")
79 (define_insn_reservation "IPREFETCH" 1 (eq_attr "type" "iprefetch")
80     "pipe1 + ls")
82 (define_insn_reservation "SHUF" 4 (eq_attr "type" "shuf,br,spr")
83     "pipe1, nothing*3")
85 (define_insn_reservation "LOAD" 6 (eq_attr "type" "load")
86     "pipe1 + ls, nothing*5")
88 (define_insn_reservation "HBR" 18 (eq_attr "type" "hbr")
89     "pipe1, nothing*15")
91 (define_insn_reservation "MULTI0" 4 (eq_attr "type" "multi0")
92     "pipe0+pipe1, nothing*3")
94 (define_insn_reservation "MULTI1" 4 (eq_attr "type" "multi1")
95     "pipe1, nothing*3")
97 (define_insn_reservation "CONVERT" 0 (eq_attr "type" "convert")
98     "nothing")
100 ;; Force pipe0 to occur before pipe 1 in a cycle.
101 (absence_set "pipe0" "pipe1")
104 (define_constants [
105  (UNSPEC_BLOCKAGE       0)
106  (UNSPEC_IPREFETCH      1)
107  (UNSPEC_FREST          2)
108  (UNSPEC_FRSQEST        3)
109  (UNSPEC_FI             4)
110  (UNSPEC_EXTEND_CMP     5)
111  (UNSPEC_CG             6)
112  (UNSPEC_CGX            7)
113  (UNSPEC_ADDX           8)
114  (UNSPEC_BG             9)
115  (UNSPEC_BGX            10)
116  (UNSPEC_SFX            11)
117  (UNSPEC_FSM            12)
118  (UNSPEC_HBR            13)
119  (UNSPEC_LNOP           14)
120  (UNSPEC_NOP            15)
121  (UNSPEC_CONVERT        16)
122  (UNSPEC_SELB           17)
123  (UNSPEC_SHUFB          18)
124  (UNSPEC_CPAT           19)
125  (UNSPEC_SYNC           20)
126  (UNSPEC_CNTB           21)
127  (UNSPEC_SUMB           22)
128  (UNSPEC_FSMB           23)
129  (UNSPEC_FSMH           24)
130  (UNSPEC_GBB            25)
131  (UNSPEC_GBH            26)
132  (UNSPEC_GB             27)
133  (UNSPEC_AVGB           28)
134  (UNSPEC_ABSDB          29)
135  (UNSPEC_ORX            30)
136  (UNSPEC_HEQ            31)
137  (UNSPEC_HGT            32)
138  (UNSPEC_HLGT           33)
139  (UNSPEC_CSFLT          34)
140  (UNSPEC_CFLTS          35)
141  (UNSPEC_CUFLT          36)
142  (UNSPEC_CFLTU          37)
143  (UNSPEC_STOP           38)
144  (UNSPEC_STOPD          39)
145  (UNSPEC_SET_INTR       40)
146  (UNSPEC_FSCRRD         42)
147  (UNSPEC_FSCRWR         43)
148  (UNSPEC_MFSPR          44)
149  (UNSPEC_MTSPR          45)
150  (UNSPEC_RDCH           46)
151  (UNSPEC_RCHCNT         47)
152  (UNSPEC_WRCH           48)
153  (UNSPEC_SPU_REALIGN_LOAD 49)
154  (UNSPEC_SPU_MASK_FOR_LOAD 50)
155  (UNSPEC_DFTSV           51)
158 (include "predicates.md")
159 (include "constraints.md")
162 ;; Mode iterators
164 (define_mode_iterator ALL [QI V16QI
165                         HI V8HI
166                         SI V4SI
167                         DI V2DI
168                         TI
169                         SF V4SF
170                         DF V2DF])
172 ; Everything except DI and TI which are handled separately because
173 ; they need different constraints to correctly test VOIDmode constants
174 (define_mode_iterator MOV [QI V16QI
175                         HI V8HI
176                         SI V4SI
177                         V2DI
178                         SF V4SF
179                         DF V2DF])
181 (define_mode_iterator DTI  [DI TI])
183 (define_mode_iterator VINT [QI V16QI
184                          HI V8HI
185                          SI V4SI
186                          DI V2DI
187                          TI])
189 (define_mode_iterator VQHSI [QI V16QI
190                           HI V8HI
191                           SI V4SI])
193 (define_mode_iterator VHSI [HI V8HI
194                          SI V4SI])
196 (define_mode_iterator VSDF [SF V4SF
197                          DF V2DF])
199 (define_mode_iterator VSI [SI V4SI])
200 (define_mode_iterator VDI [DI V2DI])
201 (define_mode_iterator VSF [SF V4SF])
202 (define_mode_iterator VDF [DF V2DF])
204 (define_mode_iterator VCMP [V16QI
205                          V8HI
206                          V4SI
207                          V4SF
208                          V2DF])
210 (define_mode_iterator VCMPU [V16QI
211                           V8HI
212                           V4SI])
214 (define_mode_attr v      [(V8HI  "v") (V4SI  "v")
215                           (HI    "") (SI    "")])
217 (define_mode_attr bh  [(QI "b")  (V16QI "b")
218                        (HI "h")  (V8HI "h")
219                        (SI "")   (V4SI "")])
221 (define_mode_attr d   [(SF "")   (V4SF "")
222                        (DF "d")  (V2DF "d")])
223 (define_mode_attr d6  [(SF "6")  (V4SF "6")
224                        (DF "d")  (V2DF "d")])
226 (define_mode_attr f2i [(SF "si") (V4SF "v4si")
227                        (DF "di") (V2DF "v2di")])
228 (define_mode_attr F2I [(SF "SI") (V4SF "V4SI")
229                        (DF "DI") (V2DF "V2DI")])
231 (define_mode_attr DF2I [(DF "SI") (V2DF "V2DI")])
233 (define_mode_attr umask  [(HI "f")  (V8HI "f")
234                           (SI "g")  (V4SI "g")])
235 (define_mode_attr nmask  [(HI "F")  (V8HI "F")
236                           (SI "G")  (V4SI "G")])
238 ;; Used for carry and borrow instructions.
239 (define_mode_iterator CBOP  [SI DI V4SI V2DI])
241 ;; Used in vec_set and vec_extract
242 (define_mode_iterator V [V2DI V4SI V8HI V16QI V2DF V4SF])
243 (define_mode_attr inner  [(V16QI "QI")
244                           (V8HI  "HI")
245                           (V4SI  "SI")
246                           (V2DI  "DI")
247                           (V4SF  "SF")
248                           (V2DF  "DF")])
249 (define_mode_attr vmult  [(V16QI "1")
250                           (V8HI  "2")
251                           (V4SI  "4")
252                           (V2DI  "8")
253                           (V4SF  "4")
254                           (V2DF  "8")])
255 (define_mode_attr voff   [(V16QI "13")
256                           (V8HI  "14")
257                           (V4SI  "0")
258                           (V2DI  "0")
259                           (V4SF  "0")
260                           (V2DF  "0")])
263 ;; mov
265 (define_expand "mov<mode>"
266   [(set (match_operand:ALL 0 "spu_nonimm_operand" "=r,r,r,m")
267         (match_operand:ALL 1 "general_operand" "r,i,m,r"))]
268   ""
269   {
270     if (spu_expand_mov(operands, <MODE>mode))
271       DONE;
272   })
274 (define_split 
275   [(set (match_operand 0 "spu_reg_operand")
276         (match_operand 1 "immediate_operand"))]
278   ""
279   [(set (match_dup 0)
280         (high (match_dup 1)))
281    (set (match_dup 0)
282         (lo_sum (match_dup 0)
283                 (match_dup 1)))]
284   {
285     if (spu_split_immediate (operands))
286       DONE;
287     FAIL;
288   })
290 (define_insn "pic"
291   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
292         (match_operand:SI 1 "immediate_operand" "s"))
293    (use (const_int 0))]
294   "flag_pic"
295   "ila\t%0,%%pic(%1)")
297 ;; Whenever a function generates the 'pic' pattern above we need to
298 ;; load the pic_offset_table register.
299 ;; GCC doesn't deal well with labels in the middle of a block so we
300 ;; hardcode the offsets in the asm here.
301 (define_insn "load_pic_offset"
302   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
303         (unspec:SI [(const_int 0)] 0))
304    (set (match_operand:SI 1 "spu_reg_operand" "=r")
305         (unspec:SI [(const_int 0)] 0))]
306   "flag_pic"
307   "ila\t%1,.+8\;brsl\t%0,4"
308   [(set_attr "length" "8")
309    (set_attr "type" "multi0")])
312 ;; move internal
314 (define_insn "_mov<mode>"
315   [(set (match_operand:MOV 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
316         (match_operand:MOV 1 "spu_mov_operand" "r,A,f,j,m,r"))]
317   "spu_valid_move (operands)"
318   "@
319    ori\t%0,%1,0
320    il%s1\t%0,%S1
321    fsmbi\t%0,%S1
322    c%s1d\t%0,%S1($sp)
323    lq%p1\t%0,%1
324    stq%p0\t%1,%0"
325   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
327 (define_insn "low_<mode>"
328   [(set (match_operand:VSI 0 "spu_reg_operand" "=r")
329         (lo_sum:VSI (match_operand:VSI 1 "spu_reg_operand" "0")
330                     (match_operand:VSI 2 "immediate_operand" "i")))]
331   ""
332   "iohl\t%0,%2@l")
334 (define_insn "_movdi"
335   [(set (match_operand:DI 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
336         (match_operand:DI 1 "spu_mov_operand" "r,a,f,k,m,r"))]
337   "spu_valid_move (operands)"
338   "@
339    ori\t%0,%1,0
340    il%d1\t%0,%D1
341    fsmbi\t%0,%D1
342    c%d1d\t%0,%D1($sp)
343    lq%p1\t%0,%1
344    stq%p0\t%1,%0"
345   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
347 (define_insn "_movti"
348   [(set (match_operand:TI 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
349         (match_operand:TI 1 "spu_mov_operand" "r,U,f,l,m,r"))]
350   "spu_valid_move (operands)"
351   "@
352    ori\t%0,%1,0
353    il%t1\t%0,%T1
354    fsmbi\t%0,%T1
355    c%t1d\t%0,%T1($sp)
356    lq%p1\t%0,%1
357    stq%p0\t%1,%0"
358   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
360 (define_insn_and_split "load"
361   [(set (match_operand 0 "spu_reg_operand" "=r")
362         (match_operand 1 "memory_operand" "m"))
363    (clobber (match_operand:TI 2 "spu_reg_operand" "=&r"))
364    (clobber (match_operand:SI 3 "spu_reg_operand" "=&r"))]
365   "GET_MODE(operands[0]) == GET_MODE(operands[1])"
366   "#"
367   ""
368   [(set (match_dup 0)
369         (match_dup 1))]
370   { spu_split_load(operands); DONE; })
372 (define_insn_and_split "store"
373   [(set (match_operand 0 "memory_operand" "=m")
374         (match_operand 1 "spu_reg_operand" "r"))
375    (clobber (match_operand:TI 2 "spu_reg_operand" "=&r"))
376    (clobber (match_operand:TI 3 "spu_reg_operand" "=&r"))]
377   "GET_MODE(operands[0]) == GET_MODE(operands[1])"
378   "#"
379   ""
380   [(set (match_dup 0)
381         (match_dup 1))]
382   { spu_split_store(operands); DONE; })
384 ;; Operand 3 is the number of bytes. 1:b 2:h 4:w 8:d
386 (define_expand "cpat"
387   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
388         (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "r,r")
389                     (match_operand:SI 2 "spu_nonmem_operand" "r,n")
390                     (match_operand:SI 3 "immediate_operand" "i,i")] UNSPEC_CPAT))]
391   ""
392   {
393     rtx x = gen_cpat_const (operands);
394     if (x)
395       {
396         emit_move_insn (operands[0], x);
397         DONE;
398       }
399   })
401 (define_insn "_cpat"
402   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
403         (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "r,r")
404                     (match_operand:SI 2 "spu_nonmem_operand" "r,n")
405                     (match_operand:SI 3 "immediate_operand" "i,i")] UNSPEC_CPAT))]
406   ""
407   "@
408    c%M3x\t%0,%1,%2
409    c%M3d\t%0,%C2(%1)"
410   [(set_attr "type" "shuf")])
412 (define_split
413   [(set (match_operand:TI 0 "spu_reg_operand")
414         (unspec:TI [(match_operand:SI 1 "spu_nonmem_operand")
415                     (match_operand:SI 2 "immediate_operand")
416                     (match_operand:SI 3 "immediate_operand")] UNSPEC_CPAT))]
417   ""
418   [(set (match_dup:TI 0)
419         (match_dup:TI 4))]
420   {
421     operands[4] = gen_cpat_const (operands);
422     if (!operands[4])
423       FAIL;
424   })
426 ;; extend
428 (define_insn "extendqihi2"
429   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
430         (sign_extend:HI (match_operand:QI 1 "spu_reg_operand" "r")))]
431   ""
432   "xsbh\t%0,%1")
434 (define_insn "extendhisi2"
435   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
436         (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r")))]
437   ""
438   "xshw\t%0,%1")
440 (define_expand "extendsidi2"
441   [(set (match_dup:DI 2)
442         (zero_extend:DI (match_operand:SI 1 "spu_reg_operand" "")))
443    (set (match_operand:DI 0 "spu_reg_operand" "")
444         (sign_extend:DI (vec_select:SI (match_dup:V2SI 3)
445                                        (parallel [(const_int 1)]))))]
446   ""
447   {
448     operands[2] = gen_reg_rtx (DImode);
449     operands[3] = spu_gen_subreg (V2SImode, operands[2]);
450   })
452 (define_insn "xswd"
453   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
454         (sign_extend:DI
455           (vec_select:SI
456             (match_operand:V2SI 1 "spu_reg_operand" "r")
457             (parallel [(const_int 1) ]))))]
458   ""
459   "xswd\t%0,%1");
461 (define_expand "extendqiti2"
462   [(set (match_operand:TI 0 "register_operand" "")
463         (sign_extend:TI (match_operand:QI 1 "register_operand" "")))]
464   ""
465   "spu_expand_sign_extend(operands);
466    DONE;")
468 (define_expand "extendhiti2"
469   [(set (match_operand:TI 0 "register_operand" "")
470         (sign_extend:TI (match_operand:HI 1 "register_operand" "")))]
471   ""
472   "spu_expand_sign_extend(operands);
473    DONE;")
475 (define_expand "extendsiti2"
476   [(set (match_operand:TI 0 "register_operand" "")
477         (sign_extend:TI (match_operand:SI 1 "register_operand" "")))]
478   ""
479   "spu_expand_sign_extend(operands);
480    DONE;")
482 (define_expand "extendditi2"
483   [(set (match_operand:TI 0 "register_operand" "")
484         (sign_extend:TI (match_operand:DI 1 "register_operand" "")))]
485   ""
486   "spu_expand_sign_extend(operands);
487    DONE;")
490 ;; zero_extend
492 (define_insn "zero_extendqihi2"
493   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
494         (zero_extend:HI (match_operand:QI 1 "spu_reg_operand" "r")))]
495   ""
496   "andi\t%0,%1,0x00ff")
498 (define_insn "zero_extendqisi2"
499   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
500         (zero_extend:SI (match_operand:QI 1 "spu_reg_operand" "r")))]
501   ""
502   "andi\t%0,%1,0x00ff")
504 (define_expand "zero_extendhisi2"
505   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
506         (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r")))
507    (clobber (match_scratch:SI 2 "=&r"))]
508   ""
509   {
510     rtx mask = gen_reg_rtx (SImode);
511     rtx op1 = simplify_gen_subreg (SImode, operands[1], HImode, 0);
512     emit_move_insn (mask, GEN_INT (0xffff));
513     emit_insn (gen_andsi3(operands[0], op1, mask));
514     DONE;
515   })
516   
517 (define_insn "zero_extendsidi2"
518   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
519         (zero_extend:DI (match_operand:SI 1 "spu_reg_operand" "r")))]
520   ""
521   "rotqmbyi\t%0,%1,-4"
522   [(set_attr "type" "shuf")])
524 (define_insn "zero_extendsiti2"
525   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
526         (zero_extend:TI (match_operand:SI 1 "spu_reg_operand" "r")))]
527   ""
528   "rotqmbyi\t%0,%1,-12"
529   [(set_attr "type" "shuf")])
531 (define_insn "zero_extendditi2"
532   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
533         (zero_extend:TI (match_operand:DI 1 "spu_reg_operand" "r")))]
534   ""
535   "rotqmbyi\t%0,%1,-8"
536   [(set_attr "type" "shuf")])
539 ;; trunc
541 (define_insn "truncdiqi2"
542   [(set (match_operand:QI 0 "spu_reg_operand" "=r")
543         (truncate:QI (match_operand:DI 1 "spu_reg_operand" "r")))]
544   ""
545   "shlqbyi\t%0,%1,4"
546   [(set_attr "type" "shuf")])
548 (define_insn "truncdihi2"
549   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
550         (truncate:HI (match_operand:DI 1 "spu_reg_operand" "r")))]
551   ""
552   "shlqbyi\t%0,%1,4"
553   [(set_attr "type" "shuf")])
555 (define_insn "truncdisi2"
556   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
557         (truncate:SI (match_operand:DI 1 "spu_reg_operand" "r")))]
558   ""
559   "shlqbyi\t%0,%1,4"
560   [(set_attr "type" "shuf")])
562 (define_insn "trunctiqi2"
563   [(set (match_operand:QI 0 "spu_reg_operand" "=r")
564         (truncate:QI (match_operand:TI 1 "spu_reg_operand" "r")))]
565   ""
566   "shlqbyi\t%0,%1,12"
567   [(set_attr "type" "shuf")])
569 (define_insn "trunctihi2"
570   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
571         (truncate:HI (match_operand:TI 1 "spu_reg_operand" "r")))]
572   ""
573   "shlqbyi\t%0,%1,12"
574   [(set_attr "type" "shuf")])
576 (define_insn "trunctisi2"
577   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
578         (truncate:SI (match_operand:TI 1 "spu_reg_operand" "r")))]
579   ""
580   "shlqbyi\t%0,%1,12"
581   [(set_attr "type" "shuf")])
583 (define_insn "trunctidi2"
584   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
585         (truncate:DI (match_operand:TI 1 "spu_reg_operand" "r")))]
586   ""
587   "shlqbyi\t%0,%1,8"
588   [(set_attr "type" "shuf")])
591 ;; float conversions
593 (define_insn "floatsisf2"
594   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
595         (float:SF (match_operand:SI 1 "spu_reg_operand" "r")))]
596   ""
597   "csflt\t%0,%1,0"
598   [(set_attr "type" "fp7")])
600 (define_insn "floatv4siv4sf2"
601   [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
602         (float:V4SF (match_operand:V4SI 1 "spu_reg_operand" "r")))]
603   ""
604   "csflt\t%0,%1,0"
605   [(set_attr "type" "fp7")])
607 (define_insn "fix_truncsfsi2"
608   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
609         (fix:SI (match_operand:SF 1 "spu_reg_operand" "r")))]
610   ""
611   "cflts\t%0,%1,0"
612   [(set_attr "type" "fp7")])
614 (define_insn "fix_truncv4sfv4si2"
615   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
616         (fix:V4SI (match_operand:V4SF 1 "spu_reg_operand" "r")))]
617   ""
618   "cflts\t%0,%1,0"
619   [(set_attr "type" "fp7")])
621 (define_insn "floatunssisf2"
622   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
623         (unsigned_float:SF (match_operand:SI 1 "spu_reg_operand" "r")))]
624   ""
625   "cuflt\t%0,%1,0"
626   [(set_attr "type" "fp7")])
628 (define_insn "floatunsv4siv4sf2"
629   [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
630         (unsigned_float:V4SF (match_operand:V4SI 1 "spu_reg_operand" "r")))]
631   ""
632   "cuflt\t%0,%1,0"
633   [(set_attr "type" "fp7")])
635 (define_insn "fixuns_truncsfsi2"
636   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
637         (unsigned_fix:SI (match_operand:SF 1 "spu_reg_operand" "r")))]
638   ""
639   "cfltu\t%0,%1,0"
640   [(set_attr "type" "fp7")])
642 (define_insn "fixuns_truncv4sfv4si2"
643   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
644         (unsigned_fix:V4SI (match_operand:V4SF 1 "spu_reg_operand" "r")))]
645   ""
646   "cfltu\t%0,%1,0"
647   [(set_attr "type" "fp7")])
649 (define_insn "extendsfdf2"
650   [(set (match_operand:DF 0 "spu_reg_operand" "=r")
651         (float_extend:DF (match_operand:SF 1 "spu_reg_operand" "r")))]
652   ""
653   "fesd\t%0,%1"
654   [(set_attr "type" "fpd")])
656 (define_insn "truncdfsf2"
657   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
658         (float_truncate:SF (match_operand:DF 1 "spu_reg_operand" "r")))]
659   ""
660   "frds\t%0,%1"
661   [(set_attr "type" "fpd")])
663 ;; Do (double)(operands[1]+0x80000000u)-(double)0x80000000
664 (define_expand "floatsidf2"
665   [(set (match_operand:DF 0 "register_operand" "")
666         (float:DF (match_operand:SI 1 "register_operand" "")))]
667   ""
668   {
669     rtx c0 = gen_reg_rtx (SImode);
670     rtx c1 = gen_reg_rtx (DFmode);
671     rtx r0 = gen_reg_rtx (SImode);
672     rtx r1 = gen_reg_rtx (DFmode);
674     emit_move_insn (c0, GEN_INT (-0x80000000ll));
675     emit_move_insn (c1, spu_float_const ("2147483648", DFmode));
676     emit_insn (gen_xorsi3 (r0, operands[1], c0));
677     emit_insn (gen_floatunssidf2 (r1, r0));
678     emit_insn (gen_subdf3 (operands[0], r1, c1));
679     DONE;
680   })
682 (define_expand "floatunssidf2"
683   [(set (match_operand:DF 0 "register_operand"  "=r")
684         (unsigned_float:DF (match_operand:SI 1 "register_operand"   "r")))]
685   ""
686   "{
687     rtx value, insns;
688     rtx c0 = spu_const_from_ints (V16QImode, 0x02031011, 0x12138080, 
689                                              0x06071415, 0x16178080);
690     rtx r0 = gen_reg_rtx (V16QImode);
692     if (optimize_size)
693     {
694        start_sequence ();
695        value =
696          emit_library_call_value (convert_optab_libfunc (ufloat_optab,
697                                                          DFmode, SImode),
698                    NULL_RTX, LCT_NORMAL, DFmode, 1, operands[1], SImode);
699        insns = get_insns ();
700        end_sequence ();
701        emit_libcall_block (insns, operands[0], value,
702                            gen_rtx_UNSIGNED_FLOAT (DFmode, operands[1]));
703      }
704      else
705      {
706       emit_move_insn (r0, c0);
707       emit_insn (gen_floatunssidf2_internal (operands[0], operands[1], r0));
708      }
709     DONE;
710   }")
712 (define_insn_and_split "floatunssidf2_internal"
713   [(set (match_operand:DF 0 "register_operand"  "=r")
714         (unsigned_float:DF (match_operand:SI 1 "register_operand"   "r")))
715    (use (match_operand:V16QI 2 "register_operand" "r"))
716    (clobber (match_scratch:V4SI 3 "=&r"))
717    (clobber (match_scratch:V4SI 4 "=&r"))
718    (clobber (match_scratch:V4SI 5 "=&r"))
719    (clobber (match_scratch:V4SI 6 "=&r"))]
720   ""
721   "clz\t%3,%1\;il\t%6,1023+31\;shl\t%4,%1,%3\;ceqi\t%5,%3,32\;sf\t%6,%3,%6\;a\t%4,%4,%4\;andc\t%6,%6,%5\;shufb\t%6,%6,%4,%2\;shlqbii\t%0,%6,4"
722   "reload_completed"
723   [(set (match_dup:DF 0)
724         (unsigned_float:DF (match_dup:SI 1)))]
725  "{
726     rtx *ops = operands;
727     rtx op1_v4si = gen_rtx_REG(V4SImode, REGNO(ops[1]));
728     rtx op0_ti = gen_rtx_REG (TImode, REGNO (ops[0]));
729     rtx op2_ti = gen_rtx_REG (TImode, REGNO (ops[2]));
730     rtx op6_ti = gen_rtx_REG (TImode, REGNO (ops[6]));
731     emit_insn (gen_clzv4si2 (ops[3],op1_v4si));
732     emit_move_insn (ops[6], spu_const (V4SImode, 1023+31));
733     emit_insn (gen_vashlv4si3 (ops[4],op1_v4si,ops[3]));
734     emit_insn (gen_ceq_v4si (ops[5],ops[3],spu_const (V4SImode, 32)));
735     emit_insn (gen_subv4si3 (ops[6],ops[6],ops[3]));
736     emit_insn (gen_addv4si3 (ops[4],ops[4],ops[4]));
737     emit_insn (gen_andc_v4si  (ops[6],ops[6],ops[5]));
738     emit_insn (gen_shufb (ops[6],ops[6],ops[4],op2_ti));
739     emit_insn (gen_shlqbi_ti (op0_ti,op6_ti,GEN_INT(4)));
740     DONE;
741   }"
742  [(set_attr "length" "32")])
744 (define_expand "floatdidf2"
745   [(set (match_operand:DF 0 "register_operand" "")
746         (float:DF (match_operand:DI 1 "register_operand" "")))]
747   ""
748   {
749     rtx c0 = gen_reg_rtx (DImode);
750     rtx r0 = gen_reg_rtx (DImode);
751     rtx r1 = gen_reg_rtx (DFmode);
752     rtx r2 = gen_reg_rtx (DImode);
753     rtx setneg = gen_reg_rtx (DImode);
754     rtx isneg = gen_reg_rtx (SImode);
755     rtx neg = gen_reg_rtx (DImode);
756     rtx mask = gen_reg_rtx (DImode);
758     emit_move_insn (c0, GEN_INT (0x8000000000000000ull));
760     emit_insn (gen_negdi2 (neg, operands[1]));
761     emit_insn (gen_cgt_di_m1 (isneg, operands[1]));
762     emit_insn (gen_extend_compare (mask, isneg));
763     emit_insn (gen_selb (r0, neg, operands[1], mask));
764     emit_insn (gen_andc_di (setneg, c0, mask));
766     emit_insn (gen_floatunsdidf2 (r1, r0));
768     emit_insn (gen_iordi3 (r2, gen_rtx_SUBREG (DImode, r1, 0), setneg));
769     emit_move_insn (operands[0], gen_rtx_SUBREG (DFmode, r2, 0));
770     DONE;
771   })
773 (define_expand "floatunsdidf2"
774   [(set (match_operand:DF 0 "register_operand"  "=r")
775         (unsigned_float:DF (match_operand:DI 1 "register_operand"   "r")))]
776   ""
777   "{
778     rtx value, insns;
779     rtx c0 = spu_const_from_ints (V16QImode, 0x02031011, 0x12138080, 
780                                              0x06071415, 0x16178080);
781     rtx c1 = spu_const_from_ints (V4SImode, 1023+63, 1023+31, 0, 0);
782     rtx r0 = gen_reg_rtx (V16QImode);
783     rtx r1 = gen_reg_rtx (V4SImode);
785     if (optimize_size)
786     {      
787       start_sequence ();
788       value =
789          emit_library_call_value (convert_optab_libfunc (ufloat_optab,
790                                                          DFmode, DImode),
791                    NULL_RTX, LCT_NORMAL, DFmode, 1, operands[1], DImode);
792       insns = get_insns ();
793       end_sequence ();
794       emit_libcall_block (insns, operands[0], value,
795                           gen_rtx_UNSIGNED_FLOAT (DFmode, operands[1]));
796     }
797     else
798     {
799       emit_move_insn (r1, c1);
800       emit_move_insn (r0, c0);
801       emit_insn (gen_floatunsdidf2_internal (operands[0], operands[1], r0, r1));
802     }
803     DONE;
804   }")
806 (define_insn_and_split "floatunsdidf2_internal"
807   [(set (match_operand:DF 0 "register_operand"  "=r")
808         (unsigned_float:DF (match_operand:DI 1 "register_operand"   "r")))
809    (use (match_operand:V16QI 2 "register_operand" "r"))
810    (use (match_operand:V4SI 3 "register_operand" "r"))
811    (clobber (match_scratch:V4SI 4 "=&r"))
812    (clobber (match_scratch:V4SI 5 "=&r"))
813    (clobber (match_scratch:V4SI 6 "=&r"))]
814   ""
815   "clz\t%4,%1\;shl\t%5,%1,%4\;ceqi\t%6,%4,32\;sf\t%4,%4,%3\;a\t%5,%5,%5\;andc\t%4,%4,%6\;shufb\t%4,%4,%5,%2\;shlqbii\t%4,%4,4\;shlqbyi\t%5,%4,8\;dfa\t%0,%4,%5"
816   "reload_completed"
817   [(set (match_operand:DF 0 "register_operand"  "=r")
818         (unsigned_float:DF (match_operand:DI 1 "register_operand"   "r")))]
819   "{
820     rtx *ops = operands;
821     rtx op1_v4si = gen_rtx_REG (V4SImode, REGNO(ops[1]));
822     rtx op2_ti = gen_rtx_REG (TImode, REGNO(ops[2]));
823     rtx op4_ti = gen_rtx_REG (TImode, REGNO(ops[4]));
824     rtx op5_ti = gen_rtx_REG (TImode, REGNO(ops[5]));
825     rtx op4_df = gen_rtx_REG (DFmode, REGNO(ops[4]));
826     rtx op5_df = gen_rtx_REG (DFmode, REGNO(ops[5]));
827     emit_insn (gen_clzv4si2 (ops[4],op1_v4si));
828     emit_insn (gen_vashlv4si3 (ops[5],op1_v4si,ops[4]));
829     emit_insn (gen_ceq_v4si (ops[6],ops[4],spu_const (V4SImode, 32)));
830     emit_insn (gen_subv4si3 (ops[4],ops[3],ops[4]));
831     emit_insn (gen_addv4si3 (ops[5],ops[5],ops[5]));
832     emit_insn (gen_andc_v4si (ops[4],ops[4],ops[6]));
833     emit_insn (gen_shufb (ops[4],ops[4],ops[5],op2_ti));
834     emit_insn (gen_shlqbi_ti (op4_ti,op4_ti,GEN_INT(4)));
835     emit_insn (gen_shlqby_ti (op5_ti,op4_ti,GEN_INT(8)));
836     emit_insn (gen_adddf3 (ops[0],op4_df,op5_df));
837     DONE;
838   }"
839   [(set_attr "length" "40")])
842 ;; add
844 (define_expand "addv16qi3"
845   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
846         (plus:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")
847                     (match_operand:V16QI 2 "spu_reg_operand" "r")))]
848   ""
849   "{
850     rtx res_short = simplify_gen_subreg (V8HImode, operands[0], V16QImode, 0);
851     rtx lhs_short = simplify_gen_subreg (V8HImode, operands[1], V16QImode, 0);
852     rtx rhs_short = simplify_gen_subreg (V8HImode, operands[2], V16QImode, 0);
853     rtx rhs_and = gen_reg_rtx (V8HImode);
854     rtx hi_char = gen_reg_rtx (V8HImode);
855     rtx lo_char = gen_reg_rtx (V8HImode);
856     rtx mask = gen_reg_rtx (V8HImode);
858     emit_move_insn (mask, spu_const (V8HImode, 0x00ff));
859     emit_insn (gen_andv8hi3 (rhs_and, rhs_short, spu_const (V8HImode, 0xff00)));
860     emit_insn (gen_addv8hi3 (hi_char, lhs_short, rhs_and));
861     emit_insn (gen_addv8hi3 (lo_char, lhs_short, rhs_short));
862     emit_insn (gen_selb (res_short, hi_char, lo_char, mask));
863     DONE;
864    }")
866 (define_insn "add<mode>3"
867   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
868         (plus:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
869                    (match_operand:VHSI 2 "spu_arith_operand" "r,B")))]
870   ""
871   "@
872   a<bh>\t%0,%1,%2
873   a<bh>i\t%0,%1,%2")
875 (define_expand "add<mode>3"
876   [(set (match_dup:VDI 3) 
877         (unspec:VDI [(match_operand:VDI 1 "spu_reg_operand" "")
878                      (match_operand:VDI 2 "spu_reg_operand" "")] UNSPEC_CG))
879    (set (match_dup:VDI 5)
880         (unspec:VDI [(match_dup 3)
881                      (match_dup 3)
882                      (match_dup:TI 4)] UNSPEC_SHUFB))
883    (set (match_operand:VDI 0 "spu_reg_operand" "") 
884         (unspec:VDI [(match_dup 1)
885                      (match_dup 2)
886                      (match_dup 5)] UNSPEC_ADDX))]
887   ""
888   {
889     unsigned char pat[16] = {
890       0x04, 0x05, 0x06, 0x07,
891       0x80, 0x80, 0x80, 0x80,
892       0x0c, 0x0d, 0x0e, 0x0f,
893       0x80, 0x80, 0x80, 0x80
894     };
895     operands[3] = gen_reg_rtx (<MODE>mode);
896     operands[4] = gen_reg_rtx (TImode);
897     operands[5] = gen_reg_rtx (<MODE>mode);
898     emit_move_insn (operands[4], array_to_constant (TImode, pat));
899   })
901 (define_insn "cg_<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")] UNSPEC_CG))]
905   "operands"
906   "cg\t%0,%1,%2")
908 (define_insn "cgx_<mode>"
909   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
910         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
911                       (match_operand 2 "spu_reg_operand" "r")
912                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_CGX))]
913   "operands"
914   "cgx\t%0,%1,%2")
916 (define_insn "addx_<mode>"
917   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
918         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
919                       (match_operand 2 "spu_reg_operand" "r")
920                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_ADDX))]
921   "operands"
922   "addx\t%0,%1,%2")
925 ;; This is not the most efficient implementation of addti3.
926 ;; We include this here because 1) the compiler needs it to be
927 ;; defined as the word size is 128-bit and 2) sometimes gcc
928 ;; substitutes an add for a constant left-shift. 2) is unlikely
929 ;; because we also give addti3 a high cost. In case gcc does
930 ;; generate TImode add, here is the code to do it.
931 ;; operand 2 is a nonmemory because the compiler requires it.
932 (define_insn "addti3"
933   [(set (match_operand:TI 0 "spu_reg_operand" "=&r")
934         (plus:TI (match_operand:TI 1 "spu_reg_operand" "r")
935                  (match_operand:TI 2 "spu_nonmem_operand" "r")))
936    (clobber (match_scratch:TI 3 "=&r"))]
937   ""
938   "cg\t%3,%1,%2\n\\
939    shlqbyi\t%3,%3,4\n\\
940    cgx\t%3,%1,%2\n\\
941    shlqbyi\t%3,%3,4\n\\
942    cgx\t%3,%1,%2\n\\
943    shlqbyi\t%0,%3,4\n\\
944    addx\t%0,%1,%2"
945   [(set_attr "type" "multi0")
946    (set_attr "length" "28")])
948 (define_insn "add<mode>3"
949   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
950         (plus:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
951                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
952   ""
953   "fa\t%0,%1,%2"
954   [(set_attr "type" "fp6")])
956 (define_insn "add<mode>3"
957   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
958         (plus:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
959                   (match_operand:VDF 2 "spu_reg_operand" "r")))]
960   ""
961   "dfa\t%0,%1,%2"
962   [(set_attr "type" "fpd")])
965 ;; sub
967 (define_expand "subv16qi3"
968   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
969         (minus:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")
970                      (match_operand:V16QI 2 "spu_reg_operand" "r")))]
971   ""
972   "{
973     rtx res_short = simplify_gen_subreg (V8HImode, operands[0], V16QImode, 0);
974     rtx lhs_short = simplify_gen_subreg (V8HImode, operands[1], V16QImode, 0);
975     rtx rhs_short = simplify_gen_subreg (V8HImode, operands[2], V16QImode, 0);
976     rtx rhs_and = gen_reg_rtx (V8HImode);
977     rtx hi_char = gen_reg_rtx (V8HImode);
978     rtx lo_char = gen_reg_rtx (V8HImode);
979     rtx mask = gen_reg_rtx (V8HImode);
981     emit_move_insn (mask, spu_const (V8HImode, 0x00ff));
982     emit_insn (gen_andv8hi3 (rhs_and, rhs_short, spu_const (V8HImode, 0xff00)));
983     emit_insn (gen_subv8hi3 (hi_char, lhs_short, rhs_and));
984     emit_insn (gen_subv8hi3 (lo_char, lhs_short, rhs_short));
985     emit_insn (gen_selb (res_short, hi_char, lo_char, mask));
986     DONE;
987    }")
989 (define_insn "sub<mode>3"
990   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
991         (minus:VHSI (match_operand:VHSI 1 "spu_arith_operand" "r,B")
992                     (match_operand:VHSI 2 "spu_reg_operand" "r,r")))]
993   ""
994   "@
995   sf<bh>\t%0,%2,%1
996   sf<bh>i\t%0,%2,%1")
998 (define_expand "sub<mode>3"
999   [(set (match_dup:VDI 3) 
1000         (unspec:VDI [(match_operand:VDI 1 "spu_reg_operand" "")
1001                      (match_operand:VDI 2 "spu_reg_operand" "")] UNSPEC_BG))
1002    (set (match_dup:VDI 5)
1003         (unspec:VDI [(match_dup 3)
1004                      (match_dup 3)
1005                      (match_dup:TI 4)] UNSPEC_SHUFB))
1006    (set (match_operand:VDI 0 "spu_reg_operand" "") 
1007         (unspec:VDI [(match_dup 1)
1008                      (match_dup 2)
1009                      (match_dup 5)] UNSPEC_SFX))]
1010   ""
1011   {
1012     unsigned char pat[16] = {
1013       0x04, 0x05, 0x06, 0x07,
1014       0xc0, 0xc0, 0xc0, 0xc0,
1015       0x0c, 0x0d, 0x0e, 0x0f,
1016       0xc0, 0xc0, 0xc0, 0xc0
1017     };
1018     operands[3] = gen_reg_rtx (<MODE>mode);
1019     operands[4] = gen_reg_rtx (TImode);
1020     operands[5] = gen_reg_rtx (<MODE>mode);
1021     emit_move_insn (operands[4], array_to_constant (TImode, pat));
1022   })
1024 (define_insn "bg_<mode>"
1025   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1026         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1027                       (match_operand 2 "spu_reg_operand" "r")] UNSPEC_BG))]
1028   "operands"
1029   "bg\t%0,%2,%1")
1031 (define_insn "bgx_<mode>"
1032   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1033         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1034                       (match_operand 2 "spu_reg_operand" "r")
1035                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_BGX))]
1036   "operands"
1037   "bgx\t%0,%2,%1")
1039 (define_insn "sfx_<mode>"
1040   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1041         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1042                       (match_operand 2 "spu_reg_operand" "r")
1043                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_SFX))]
1044   "operands"
1045   "sfx\t%0,%2,%1")
1047 (define_insn "subti3"
1048   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
1049         (minus:TI (match_operand:TI 1 "spu_reg_operand" "r")
1050                   (match_operand:TI 2 "spu_reg_operand" "r")))
1051    (clobber (match_scratch:TI 3 "=&r"))
1052    (clobber (match_scratch:TI 4 "=&r"))
1053    (clobber (match_scratch:TI 5 "=&r"))
1054    (clobber (match_scratch:TI 6 "=&r"))]
1055   ""
1056   "il\t%6,1\n\\
1057    bg\t%3,%2,%1\n\\
1058    xor\t%3,%3,%6\n\\
1059    sf\t%4,%2,%1\n\\
1060    shlqbyi\t%5,%3,4\n\\
1061    bg\t%3,%5,%4\n\\
1062    xor\t%3,%3,%6\n\\
1063    sf\t%4,%5,%4\n\\
1064    shlqbyi\t%5,%3,4\n\\
1065    bg\t%3,%5,%4\n\\
1066    xor\t%3,%3,%6\n\\
1067    sf\t%4,%5,%4\n\\
1068    shlqbyi\t%5,%3,4\n\\
1069    sf\t%0,%5,%4"
1070   [(set_attr "type" "multi0")
1071    (set_attr "length" "56")])
1073 (define_insn "sub<mode>3"
1074   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1075         (minus:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1076                    (match_operand:VSF 2 "spu_reg_operand" "r")))]
1077   ""
1078   "fs\t%0,%1,%2"
1079   [(set_attr "type" "fp6")])
1081 (define_insn "sub<mode>3"
1082   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1083         (minus:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1084                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
1085   ""
1086   "dfs\t%0,%1,%2"
1087   [(set_attr "type" "fpd")])
1090 ;; neg
1092 (define_expand "negv16qi2"
1093   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
1094         (neg:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")))]
1095   ""
1096   "{
1097     rtx zero = gen_reg_rtx (V16QImode);
1098     emit_move_insn (zero, CONST0_RTX (V16QImode));
1099     emit_insn (gen_subv16qi3 (operands[0], zero, operands[1]));
1100     DONE;
1101    }")
1103 (define_insn "neg<mode>2"
1104   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
1105         (neg:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")))]
1106   ""
1107   "sf<bh>i\t%0,%1,0")
1109 (define_expand "negdi2"
1110   [(set (match_operand:DI 0 "spu_reg_operand" "")
1111         (neg:DI (match_operand:DI 1 "spu_reg_operand" "")))]
1112   ""
1113   {
1114     rtx zero = gen_reg_rtx(DImode);
1115     emit_move_insn(zero, GEN_INT(0));
1116     emit_insn (gen_subdi3(operands[0], zero, operands[1]));
1117     DONE;
1118   })
1120 (define_expand "negti2"
1121   [(set (match_operand:TI 0 "spu_reg_operand" "")
1122         (neg:TI (match_operand:TI 1 "spu_reg_operand" "")))]
1123   ""
1124   {
1125     rtx zero = gen_reg_rtx(TImode);
1126     emit_move_insn(zero, GEN_INT(0));
1127     emit_insn (gen_subti3(operands[0], zero, operands[1]));
1128     DONE;
1129   })
1131 (define_expand "neg<mode>2"
1132   [(parallel
1133     [(set (match_operand:VSF 0 "spu_reg_operand" "")
1134           (neg:VSF (match_operand:VSF 1 "spu_reg_operand" "")))
1135      (use (match_dup 2))])]
1136   ""
1137   "operands[2] = gen_reg_rtx (<F2I>mode);
1138    emit_move_insn (operands[2], spu_const (<F2I>mode, -0x80000000ull));")
1140 (define_expand "neg<mode>2"
1141   [(parallel
1142     [(set (match_operand:VDF 0 "spu_reg_operand" "")
1143           (neg:VDF (match_operand:VDF 1 "spu_reg_operand" "")))
1144      (use (match_dup 2))])]
1145   ""
1146   "operands[2] = gen_reg_rtx (<F2I>mode);
1147    emit_move_insn (operands[2], spu_const (<F2I>mode, -0x8000000000000000ull));")
1149 (define_insn_and_split "_neg<mode>2"
1150   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1151         (neg:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")))
1152    (use (match_operand:<F2I> 2 "spu_reg_operand" "r"))]
1153   ""
1154   "#"
1155   ""
1156   [(set (match_dup:<F2I> 3)
1157         (xor:<F2I> (match_dup:<F2I> 4)
1158                    (match_dup:<F2I> 2)))]
1159   {
1160     operands[3] = spu_gen_subreg (<F2I>mode, operands[0]);
1161     operands[4] = spu_gen_subreg (<F2I>mode, operands[1]);
1162   })
1165 ;; abs
1167 (define_expand "abs<mode>2"
1168   [(parallel
1169     [(set (match_operand:VSF 0 "spu_reg_operand" "")
1170           (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "")))
1171      (use (match_dup 2))])]
1172   ""
1173   "operands[2] = gen_reg_rtx (<F2I>mode);
1174    emit_move_insn (operands[2], spu_const (<F2I>mode, 0x7fffffffull));")
1176 (define_expand "abs<mode>2"
1177   [(parallel
1178     [(set (match_operand:VDF 0 "spu_reg_operand" "")
1179           (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "")))
1180      (use (match_dup 2))])]
1181   ""
1182   "operands[2] = gen_reg_rtx (<F2I>mode);
1183    emit_move_insn (operands[2], spu_const (<F2I>mode, 0x7fffffffffffffffull));")
1185 (define_insn_and_split "_abs<mode>2"
1186   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1187         (abs:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")))
1188    (use (match_operand:<F2I> 2 "spu_reg_operand" "r"))]
1189   ""
1190   "#"
1191   ""
1192   [(set (match_dup:<F2I> 3)
1193         (and:<F2I> (match_dup:<F2I> 4)
1194                    (match_dup:<F2I> 2)))]
1195   {
1196     operands[3] = spu_gen_subreg (<F2I>mode, operands[0]);
1197     operands[4] = spu_gen_subreg (<F2I>mode, operands[1]);
1198   })
1201 ;; mul
1203 (define_insn "mulhi3"
1204   [(set (match_operand:HI 0 "spu_reg_operand" "=r,r")
1205         (mult:HI (match_operand:HI 1 "spu_reg_operand" "r,r")
1206                  (match_operand:HI 2 "spu_arith_operand" "r,B")))]
1207   ""
1208   "@
1209   mpy\t%0,%1,%2
1210   mpyi\t%0,%1,%2"
1211   [(set_attr "type" "fp7")])
1213 (define_expand "mulv8hi3"
1214   [(set (match_operand:V8HI 0 "spu_reg_operand" "")
1215         (mult:V8HI (match_operand:V8HI 1 "spu_reg_operand" "")
1216                    (match_operand:V8HI 2 "spu_reg_operand" "")))]
1217   ""
1218   "{
1219     rtx result = simplify_gen_subreg (V4SImode, operands[0], V8HImode, 0);
1220     rtx low = gen_reg_rtx (V4SImode);
1221     rtx high = gen_reg_rtx (V4SImode);
1222     rtx shift = gen_reg_rtx (V4SImode);
1223     rtx mask = gen_reg_rtx (V4SImode);
1225     emit_move_insn (mask, spu_const (V4SImode, 0x0000ffff));
1226     emit_insn (gen_spu_mpyhh (high, operands[1], operands[2]));
1227     emit_insn (gen_spu_mpy (low, operands[1], operands[2]));
1228     emit_insn (gen_vashlv4si3 (shift, high, spu_const(V4SImode, 16)));
1229     emit_insn (gen_selb (result, shift, low, mask));
1230     DONE;
1231    }")
1233 (define_expand "mul<mode>3"
1234   [(parallel
1235     [(set (match_operand:VSI 0 "spu_reg_operand" "")
1236           (mult:VSI (match_operand:VSI 1 "spu_reg_operand" "")
1237                     (match_operand:VSI 2 "spu_reg_operand" "")))
1238      (clobber (match_dup:VSI 3))
1239      (clobber (match_dup:VSI 4))
1240      (clobber (match_dup:VSI 5))
1241      (clobber (match_dup:VSI 6))])]
1242   ""
1243   {
1244     operands[3] = gen_reg_rtx(<MODE>mode);
1245     operands[4] = gen_reg_rtx(<MODE>mode);
1246     operands[5] = gen_reg_rtx(<MODE>mode);
1247     operands[6] = gen_reg_rtx(<MODE>mode);
1248   })
1250 (define_insn_and_split "_mulsi3"
1251   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1252         (mult:SI (match_operand:SI 1 "spu_reg_operand" "r")
1253                  (match_operand:SI 2 "spu_arith_operand" "rK")))
1254    (clobber (match_operand:SI 3 "spu_reg_operand" "=&r"))
1255    (clobber (match_operand:SI 4 "spu_reg_operand" "=&r"))
1256    (clobber (match_operand:SI 5 "spu_reg_operand" "=&r"))
1257    (clobber (match_operand:SI 6 "spu_reg_operand" "=&r"))]
1258   ""
1259   "#"
1260   ""
1261   [(set (match_dup:SI 0)
1262         (mult:SI (match_dup:SI 1)
1263                  (match_dup:SI 2)))]
1264   {
1265     HOST_WIDE_INT val = 0;
1266     rtx a = operands[3];
1267     rtx b = operands[4];
1268     rtx c = operands[5];
1269     rtx d = operands[6];
1270     if (GET_CODE(operands[2]) == CONST_INT)
1271       {
1272         val = INTVAL(operands[2]);
1273         emit_move_insn(d, operands[2]);
1274         operands[2] = d;
1275       }
1276     if (val && (val & 0xffff) == 0)
1277       {
1278         emit_insn (gen_mpyh_si(operands[0], operands[2], operands[1]));
1279       }
1280     else if (val > 0 && val < 0x10000)
1281       {
1282         rtx cst = satisfies_constraint_K (GEN_INT (val)) ? GEN_INT(val) : d;
1283         emit_insn (gen_mpyh_si(a, operands[1], operands[2]));
1284         emit_insn (gen_mpyu_si(c, operands[1], cst));
1285         emit_insn (gen_addsi3(operands[0], a, c));
1286       }
1287     else
1288       {
1289         emit_insn (gen_mpyh_si(a, operands[1], operands[2]));
1290         emit_insn (gen_mpyh_si(b, operands[2], operands[1]));
1291         emit_insn (gen_mpyu_si(c, operands[1], operands[2]));
1292         emit_insn (gen_addsi3(d, a, b));
1293         emit_insn (gen_addsi3(operands[0], d, c));
1294       }
1295     DONE;
1296    })
1298 (define_insn_and_split "_mulv4si3"
1299   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
1300         (mult:V4SI (match_operand:V4SI 1 "spu_reg_operand" "r")
1301                    (match_operand:V4SI 2 "spu_reg_operand" "r")))
1302    (clobber (match_operand:V4SI 3 "spu_reg_operand" "=&r"))
1303    (clobber (match_operand:V4SI 4 "spu_reg_operand" "=&r"))
1304    (clobber (match_operand:V4SI 5 "spu_reg_operand" "=&r"))
1305    (clobber (match_operand:V4SI 6 "spu_reg_operand" "=&r"))]
1306   ""
1307   "#"
1308   ""
1309   [(set (match_dup:V4SI 0)
1310         (mult:V4SI (match_dup:V4SI 1)
1311                    (match_dup:V4SI 2)))]
1312   {
1313     rtx a = operands[3];
1314     rtx b = operands[4];
1315     rtx c = operands[5];
1316     rtx d = operands[6];
1317     rtx op1 = simplify_gen_subreg (V8HImode, operands[1], V4SImode, 0);
1318     rtx op2 = simplify_gen_subreg (V8HImode, operands[2], V4SImode, 0);
1319     emit_insn (gen_spu_mpyh(a, op1, op2));
1320     emit_insn (gen_spu_mpyh(b, op2, op1));
1321     emit_insn (gen_spu_mpyu(c, op1, op2));
1322     emit_insn (gen_addv4si3(d, a, b));
1323     emit_insn (gen_addv4si3(operands[0], d, c));
1324     DONE;
1325    })
1327 (define_insn "mulhisi3"
1328   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1329         (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1330                  (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r"))))]
1331   ""
1332   "mpy\t%0,%1,%2"
1333   [(set_attr "type" "fp7")])
1335 (define_insn "mulhisi3_imm"
1336   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1337         (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1338                  (match_operand:SI 2 "imm_K_operand" "K")))]
1339   ""
1340   "mpyi\t%0,%1,%2"
1341   [(set_attr "type" "fp7")])
1343 (define_insn "umulhisi3"
1344   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1345         (mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1346                  (zero_extend:SI (match_operand:HI 2 "spu_reg_operand" "r"))))]
1347   ""
1348   "mpyu\t%0,%1,%2"
1349   [(set_attr "type" "fp7")])
1351 (define_insn "umulhisi3_imm"
1352   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1353         (mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1354                  (and:SI (match_operand:SI 2 "imm_K_operand" "K") (const_int 65535))))]
1355   ""
1356   "mpyui\t%0,%1,%2"
1357   [(set_attr "type" "fp7")])
1359 (define_insn "mpyu_si"
1360   [(set (match_operand:SI 0 "spu_reg_operand" "=r,r")
1361         (mult:SI (and:SI (match_operand:SI 1 "spu_reg_operand" "r,r")
1362                          (const_int 65535))
1363                  (and:SI (match_operand:SI 2 "spu_arith_operand" "r,K")
1364                          (const_int 65535))))]
1365   ""
1366   "@
1367    mpyu\t%0,%1,%2
1368    mpyui\t%0,%1,%2"
1369   [(set_attr "type" "fp7")])
1371 ;; This isn't always profitable to use.  Consider r = a * b + c * d.
1372 ;; It's faster to do the multiplies in parallel then add them.  If we
1373 ;; merge a multiply and add it prevents the multiplies from happening in
1374 ;; parallel.
1375 (define_insn "mpya_si"
1376   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1377         (plus:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1378                           (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r")))
1379                  (match_operand:SI 3 "spu_reg_operand" "r")))]
1380   "0"
1381   "mpya\t%0,%1,%2,%3"
1382   [(set_attr "type" "fp7")])
1384 (define_insn "mpyh_si"
1385   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1386         (mult:SI (and:SI (match_operand:SI 1 "spu_reg_operand" "r")
1387                          (const_int -65536))
1388                  (and:SI (match_operand:SI 2 "spu_reg_operand" "r")
1389                          (const_int 65535))))]
1390   ""
1391   "mpyh\t%0,%1,%2"
1392   [(set_attr "type" "fp7")])
1394 (define_insn "mpys_si"
1395   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1396         (ashiftrt:SI
1397             (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1398                      (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r")))
1399             (const_int 16)))]
1400   ""
1401   "mpys\t%0,%1,%2"
1402   [(set_attr "type" "fp7")])
1404 (define_insn "mpyhh_si"
1405   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1406         (mult:SI (ashiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1407                               (const_int 16))
1408                  (ashiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1409                               (const_int 16))))]
1410   ""
1411   "mpyhh\t%0,%1,%2"
1412   [(set_attr "type" "fp7")])
1414 (define_insn "mpyhhu_si"
1415   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1416         (mult:SI (lshiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1417                               (const_int 16))
1418                  (lshiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1419                               (const_int 16))))]
1420   ""
1421   "mpyhhu\t%0,%1,%2"
1422   [(set_attr "type" "fp7")])
1424 (define_insn "mpyhha_si" 
1425   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1426         (plus:SI (mult:SI (ashiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1427                                        (const_int 16))
1428                           (ashiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1429                                        (const_int 16)))
1430                  (match_operand:SI 3 "spu_reg_operand" "0")))]
1431   "0"
1432   "mpyhha\t%0,%1,%2"
1433   [(set_attr "type" "fp7")])
1435 (define_insn "mul<mode>3"
1436   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1437         (mult:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")
1438                    (match_operand:VSDF 2 "spu_reg_operand" "r")))]
1439   ""
1440   "<d>fm\t%0,%1,%2"
1441   [(set_attr "type" "fp<d6>")])
1443 (define_insn "fma_<mode>"
1444   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1445         (plus:VSF (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1446                               (match_operand:VSF 2 "spu_reg_operand" "r"))
1447                    (match_operand:VSF 3 "spu_reg_operand" "r")))]
1448   ""
1449   "fma\t%0,%1,%2,%3"
1450   [(set_attr "type"     "fp6")])
1452 (define_insn "fnms_<mode>"
1453   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1454         (minus:VSF (match_operand:VSF 3 "spu_reg_operand" "r")
1455                     (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1456                                (match_operand:VSF 2 "spu_reg_operand" "r"))))]
1457   ""
1458   "fnms\t%0,%1,%2,%3"
1459   [(set_attr "type" "fp6")])
1461 (define_insn "fms_<mode>"
1462   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1463         (minus:VSF (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1464                                (match_operand:VSF 2 "spu_reg_operand" "r"))
1465                     (match_operand:VSF 3 "spu_reg_operand" "r")))]
1466   ""
1467   "fms\t%0,%1,%2,%3"
1468   [(set_attr "type" "fp6")])
1470 (define_insn "fma_<mode>"
1471   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1472         (plus:VDF (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1473                             (match_operand:VDF 2 "spu_reg_operand" "r"))
1474                   (match_operand:VDF 3 "spu_reg_operand" "0")))]
1475   ""
1476   "dfma\t%0,%1,%2"
1477   [(set_attr "type"     "fpd")])
1479 (define_insn "fnma_<mode>"
1480   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1481         (neg:VDF (plus:VDF (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1482                                      (match_operand:VDF 2 "spu_reg_operand" "r"))
1483                            (match_operand:VDF 3 "spu_reg_operand" "0"))))]
1484   ""
1485   "dfnma\t%0,%1,%2"
1486   [(set_attr "type"     "fpd")])
1488 (define_insn "fnms_<mode>"
1489   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1490         (minus:VDF (match_operand:VDF 3 "spu_reg_operand" "0")
1491                    (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1492                              (match_operand:VDF 2 "spu_reg_operand" "r"))))]
1493   ""
1494   "dfnms\t%0,%1,%2"
1495   [(set_attr "type" "fpd")])
1497 (define_insn "fms_<mode>"
1498   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1499         (minus:VDF (mult:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1500                              (match_operand:VDF 2 "spu_reg_operand" "r"))
1501                    (match_operand:VDF 3 "spu_reg_operand" "0")))]
1502   ""
1503   "dfms\t%0,%1,%2"
1504   [(set_attr "type" "fpd")])
1507 ;; mul highpart, used for divide by constant optimizations.
1509 (define_expand "smulsi3_highpart"
1510   [(set (match_operand:SI 0 "register_operand" "")
1511         (truncate:SI
1512           (ashiftrt:DI
1513             (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
1514                      (sign_extend:DI (match_operand:SI 2 "register_operand" "")))
1515             (const_int 32))))]
1516   ""
1517   {
1518     rtx t0 = gen_reg_rtx (SImode);
1519     rtx t1 = gen_reg_rtx (SImode);
1520     rtx t2 = gen_reg_rtx (SImode);
1521     rtx t3 = gen_reg_rtx (SImode);
1522     rtx t4 = gen_reg_rtx (SImode);
1523     rtx t5 = gen_reg_rtx (SImode);
1524     rtx t6 = gen_reg_rtx (SImode);
1525     rtx t7 = gen_reg_rtx (SImode);
1526     rtx t8 = gen_reg_rtx (SImode);
1527     rtx t9 = gen_reg_rtx (SImode);
1528     rtx t11 = gen_reg_rtx (SImode);
1529     rtx t12 = gen_reg_rtx (SImode);
1530     rtx t14 = gen_reg_rtx (SImode);
1531     rtx t15 = gen_reg_rtx (HImode);
1532     rtx t16 = gen_reg_rtx (HImode);
1533     rtx t17 = gen_reg_rtx (HImode);
1534     rtx t18 = gen_reg_rtx (HImode);
1535     rtx t19 = gen_reg_rtx (SImode);
1536     rtx t20 = gen_reg_rtx (SImode);
1537     rtx t21 = gen_reg_rtx (SImode);
1538     rtx op1_hi = gen_rtx_SUBREG (HImode, operands[1], 2);
1539     rtx op2_hi = gen_rtx_SUBREG (HImode, operands[2], 2);
1540     rtx t0_hi = gen_rtx_SUBREG (HImode, t0, 2);
1541     rtx t1_hi = gen_rtx_SUBREG (HImode, t1, 2);
1543     rtx insn = emit_insn (gen_lshrsi3 (t0, operands[1], GEN_INT (16)));
1544     emit_insn (gen_lshrsi3 (t1, operands[2], GEN_INT (16)));
1545     emit_insn (gen_umulhisi3 (t2, op1_hi, op2_hi));
1546     emit_insn (gen_mpyh_si (t3, operands[1], operands[2]));
1547     emit_insn (gen_mpyh_si (t4, operands[2], operands[1]));
1548     emit_insn (gen_mpyhh_si (t5, operands[1], operands[2]));
1549     emit_insn (gen_mpys_si (t6, t0_hi, op2_hi));
1550     emit_insn (gen_mpys_si (t7, t1_hi, op1_hi));
1552     /* Gen carry bits (in t9 and t11). */
1553     emit_insn (gen_addsi3 (t8, t2, t3));
1554     emit_insn (gen_cg_si (t9, t2, t3));
1555     emit_insn (gen_cg_si (t11, t8, t4));
1557     /* Gen high 32 bits in operand[0].  Correct for mpys. */
1558     emit_insn (gen_addx_si (t12, t5, t6, t9));
1559     emit_insn (gen_addx_si (t14, t12, t7, t11));
1561     /* mpys treats both operands as signed when we really want it to treat
1562        the first operand as signed and the second operand as unsigned.
1563        The code below corrects for that difference.  */
1564     emit_insn (gen_cgt_hi (t15, op1_hi, GEN_INT (-1)));
1565     emit_insn (gen_cgt_hi (t16, op2_hi, GEN_INT (-1)));
1566     emit_insn (gen_andc_hi (t17, t1_hi, t15));
1567     emit_insn (gen_andc_hi (t18, t0_hi, t16));
1568     emit_insn (gen_extendhisi2 (t19, t17));
1569     emit_insn (gen_extendhisi2 (t20, t18));
1570     emit_insn (gen_addsi3 (t21, t19, t20));
1571     emit_insn (gen_addsi3 (operands[0], t14, t21));
1572     unshare_all_rtl_in_chain (insn);
1573     DONE;
1574   })
1576 (define_expand "umulsi3_highpart"
1577   [(set (match_operand:SI 0 "register_operand" "")
1578         (truncate:SI
1579           (ashiftrt:DI
1580             (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
1581                      (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1582             (const_int 32))))]
1583   ""
1584   
1585   {
1586     rtx t0 = gen_reg_rtx (SImode);
1587     rtx t1 = gen_reg_rtx (SImode);
1588     rtx t2 = gen_reg_rtx (SImode);
1589     rtx t3 = gen_reg_rtx (SImode);
1590     rtx t4 = gen_reg_rtx (SImode);
1591     rtx t5 = gen_reg_rtx (SImode);
1592     rtx t6 = gen_reg_rtx (SImode);
1593     rtx t7 = gen_reg_rtx (SImode);
1594     rtx t8 = gen_reg_rtx (SImode);
1595     rtx t9 = gen_reg_rtx (SImode);
1596     rtx t10 = gen_reg_rtx (SImode);
1597     rtx t12 = gen_reg_rtx (SImode);
1598     rtx t13 = gen_reg_rtx (SImode);
1599     rtx t14 = gen_reg_rtx (SImode);
1600     rtx op1_hi = gen_rtx_SUBREG (HImode, operands[1], 2);
1601     rtx op2_hi = gen_rtx_SUBREG (HImode, operands[2], 2);
1602     rtx t0_hi = gen_rtx_SUBREG (HImode, t0, 2);
1604     rtx insn = emit_insn (gen_rotlsi3 (t0, operands[2], GEN_INT (16)));
1605     emit_insn (gen_umulhisi3 (t1, op1_hi, op2_hi));
1606     emit_insn (gen_umulhisi3 (t2, op1_hi, t0_hi));
1607     emit_insn (gen_mpyhhu_si (t3, operands[1], t0));
1608     emit_insn (gen_mpyhhu_si (t4, operands[1], operands[2]));
1609     emit_insn (gen_ashlsi3 (t5, t2, GEN_INT (16)));
1610     emit_insn (gen_ashlsi3 (t6, t3, GEN_INT (16)));
1611     emit_insn (gen_lshrsi3 (t7, t2, GEN_INT (16)));
1612     emit_insn (gen_lshrsi3 (t8, t3, GEN_INT (16)));
1614     /* Gen carry bits (in t10 and t12). */
1615     emit_insn (gen_addsi3 (t9, t1, t5));
1616     emit_insn (gen_cg_si (t10, t1, t5));
1617     emit_insn (gen_cg_si (t12, t9, t6));
1619     /* Gen high 32 bits in operand[0]. */
1620     emit_insn (gen_addx_si (t13, t4, t7, t10));
1621     emit_insn (gen_addx_si (t14, t13, t8, t12));
1622     emit_insn (gen_movsi (operands[0], t14));
1623     unshare_all_rtl_in_chain (insn);
1625     DONE;
1626   })
1628 ;; div
1630 ;; Not necessarily the best implementation of divide but faster then
1631 ;; the default that gcc provides because this is inlined and it uses
1632 ;; clz.
1633 (define_insn "divmodsi4"
1634       [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
1635             (div:SI (match_operand:SI 1 "spu_reg_operand" "r")
1636                     (match_operand:SI 2 "spu_reg_operand" "r")))
1637        (set (match_operand:SI 3 "spu_reg_operand" "=&r")
1638             (mod:SI (match_dup 1)
1639                     (match_dup 2)))
1640        (clobber (match_scratch:SI 4 "=&r"))
1641        (clobber (match_scratch:SI 5 "=&r"))
1642        (clobber (match_scratch:SI 6 "=&r"))
1643        (clobber (match_scratch:SI 7 "=&r"))
1644        (clobber (match_scratch:SI 8 "=&r"))
1645        (clobber (match_scratch:SI 9 "=&r"))
1646        (clobber (match_scratch:SI 10 "=&r"))
1647        (clobber (match_scratch:SI 11 "=&r"))
1648        (clobber (match_scratch:SI 12 "=&r"))
1649        (clobber (reg:SI 130))]
1650   ""
1651   "heqi %2,0\\n\\
1652         hbrr    3f,1f\\n\\
1653         sfi     %8,%1,0\\n\\
1654         sfi     %9,%2,0\\n\\
1655         cgti    %10,%1,-1\\n\\
1656         cgti    %11,%2,-1\\n\\
1657         selb    %8,%8,%1,%10\\n\\
1658         selb    %9,%9,%2,%11\\n\\
1659         clz     %4,%8\\n\\
1660         clz     %7,%9\\n\\
1661         il      %5,1\\n\\
1662         fsmbi   %0,0\\n\\
1663         sf      %7,%4,%7\\n\\
1664         shlqbyi %3,%8,0\\n\\
1665         xor     %11,%10,%11\\n\\
1666         shl     %5,%5,%7\\n\\
1667         shl     %4,%9,%7\\n\\
1668         lnop    \\n\\
1669 1:      or      %12,%0,%5\\n\\
1670         rotqmbii        %5,%5,-1\\n\\
1671         clgt    %6,%4,%3\\n\\
1672         lnop    \\n\\
1673         sf      %7,%4,%3\\n\\
1674         rotqmbii        %4,%4,-1\\n\\
1675         selb    %0,%12,%0,%6\\n\\
1676         lnop    \\n\\
1677         selb    %3,%7,%3,%6\\n\\
1678 3:      brnz    %5,1b\\n\\
1679 2:      sfi     %8,%3,0\\n\\
1680         sfi     %9,%0,0\\n\\
1681         selb    %3,%8,%3,%10\\n\\
1682         selb    %0,%0,%9,%11"
1683   [(set_attr "type" "multi0")
1684    (set_attr "length" "128")])
1686 (define_insn "udivmodsi4"
1687       [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
1688             (udiv:SI (match_operand:SI 1 "spu_reg_operand" "r")
1689                      (match_operand:SI 2 "spu_reg_operand" "r")))
1690        (set (match_operand:SI 3 "spu_reg_operand" "=&r")
1691             (umod:SI (match_dup 1)
1692                      (match_dup 2)))
1693        (clobber (match_scratch:SI 4 "=&r"))
1694        (clobber (match_scratch:SI 5 "=&r"))
1695        (clobber (match_scratch:SI 6 "=&r"))
1696        (clobber (match_scratch:SI 7 "=&r"))
1697        (clobber (match_scratch:SI 8 "=&r"))
1698        (clobber (reg:SI 130))]
1699   ""
1700   "heqi %2,0\\n\\
1701         hbrr    3f,1f\\n\\
1702         clz     %7,%2\\n\\
1703         clz     %4,%1\\n\\
1704         il      %5,1\\n\\
1705         fsmbi   %0,0\\n\\
1706         sf      %7,%4,%7\\n\\
1707         ori     %3,%1,0\\n\\
1708         shl     %5,%5,%7\\n\\
1709         shl     %4,%2,%7\\n\\
1710 1:      or      %8,%0,%5\\n\\
1711         rotqmbii        %5,%5,-1\\n\\
1712         clgt    %6,%4,%3\\n\\
1713         lnop    \\n\\
1714         sf      %7,%4,%3\\n\\
1715         rotqmbii        %4,%4,-1\\n\\
1716         selb    %0,%8,%0,%6\\n\\
1717         lnop    \\n\\
1718         selb    %3,%7,%3,%6\\n\\
1719 3:      brnz    %5,1b\\n\\
1721   [(set_attr "type" "multi0")
1722    (set_attr "length" "80")])
1724 (define_insn_and_split "div<mode>3"
1725   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1726         (div:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1727                  (match_operand:VSF 2 "spu_reg_operand" "r")))
1728    (clobber (match_scratch:VSF 3 "=&r"))
1729    (clobber (match_scratch:VSF 4 "=&r"))]
1730   ""
1731   "#"
1732   "reload_completed"
1733   [(set (match_dup:VSF 0)
1734         (div:VSF (match_dup:VSF 1)
1735                  (match_dup:VSF 2)))
1736    (clobber (match_dup:VSF 3))
1737    (clobber (match_dup:VSF 4))]
1738   {
1739     emit_insn (gen_frest_<mode>(operands[3], operands[2]));
1740     emit_insn (gen_fi_<mode>(operands[3], operands[2], operands[3]));
1741     emit_insn (gen_mul<mode>3(operands[4], operands[1], operands[3]));
1742     emit_insn (gen_fnms_<mode>(operands[0], operands[4], operands[2], operands[1]));
1743     emit_insn (gen_fma_<mode>(operands[0], operands[0], operands[3], operands[4]));
1744     DONE;
1745   })
1747 ;; Taken from STI's gcc
1748 ;; Does not correctly handle INF or NAN.
1749 (define_expand "divdf3"
1750   [(set (match_operand:DF 0 "register_operand" "=r")
1751         (div:DF (match_operand:DF 1 "register_operand" "r")
1752                 (match_operand:DF 2 "register_operand" "r")))]
1753   "flag_finite_math_only"
1754   "{    
1755     /*
1756     double
1757     divdf3 (double x, double y)
1758     {
1759         float x0;
1760         float y_f = (float) y;
1761         double x1, x2;
1763         x0 = spu_extract(spu_re(spu_promote(y_f, 0)), 0);
1764         x1 = (double)(x0 * (2.0f - y_f * x0)); 
1765         x2 = x1 * (2.0 - y * x1);
1766         return (x * x2 * (2.0 - y * x2));
1767     }
1768     */
1770     rtx dst = operands[0];
1771     rtx x   = operands[1];
1772     rtx y   = operands[2];
1773     rtx y_f = gen_reg_rtx(SFmode);
1774     rtx x0_f = gen_reg_rtx(SFmode);
1775     rtx x1_f = gen_reg_rtx(SFmode);
1776     rtx x1 = gen_reg_rtx(DFmode);
1777     rtx x2 = gen_reg_rtx(DFmode);
1778     rtx t1_f = gen_reg_rtx(SFmode);
1779     rtx t1 = gen_reg_rtx(DFmode);
1780     rtx two = gen_reg_rtx(DFmode);
1781     rtx two_f = gen_reg_rtx(SFmode);
1783     emit_insn (gen_truncdfsf2 (y_f, y));
1784     emit_insn (gen_frest_sf (x0_f, y_f));
1785     emit_insn (gen_fi_sf (x0_f, y_f, x0_f));
1786     emit_insn (gen_movsf (two_f, spu_float_const(\"2.0\",SFmode)));
1787     emit_insn (gen_fnms_sf (t1_f, y_f, x0_f, two_f));
1788     emit_insn (gen_mulsf3 (x1_f, t1_f, x0_f));
1789     emit_insn (gen_extendsfdf2 (x1, x1_f));
1790     emit_insn (gen_extendsfdf2 (two, two_f));
1791     emit_insn (gen_movdf (t1, two));
1792     emit_insn (gen_fnms_df (t1, y, x1, t1));
1793     emit_insn (gen_muldf3 (x2, x1, t1));
1794     emit_insn (gen_fnms_df (two, y, x2, two));
1795     emit_insn (gen_muldf3 (dst, x2, two));
1796     emit_insn (gen_muldf3 (dst, dst, x));
1797     DONE;
1800 ;; sqrt
1802 (define_insn_and_split "sqrtsf2"
1803   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
1804         (sqrt:SF (match_operand:SF 1 "spu_reg_operand" "r")))
1805    (clobber (match_scratch:SF 2 "=&r"))
1806    (clobber (match_scratch:SF 3 "=&r"))
1807    (clobber (match_scratch:SF 4 "=&r"))
1808    (clobber (match_scratch:SF 5 "=&r"))]
1809   ""
1810   "#"
1811   "reload_completed"
1812   [(set (match_dup:SF 0)
1813         (sqrt:SF (match_dup:SF 1)))
1814    (clobber (match_dup:SF 2))
1815    (clobber (match_dup:SF 3))
1816    (clobber (match_dup:SF 4))
1817    (clobber (match_dup:SF 5))]
1818   {
1819     emit_move_insn (operands[3],spu_float_const(\"0.5\",SFmode));
1820     emit_move_insn (operands[4],spu_float_const(\"1.00000011920928955078125\",SFmode));
1821     emit_insn (gen_frsqest_sf(operands[2],operands[1]));
1822     emit_insn (gen_fi_sf(operands[2],operands[1],operands[2]));
1823     emit_insn (gen_mulsf3(operands[5],operands[2],operands[1]));
1824     emit_insn (gen_mulsf3(operands[3],operands[5],operands[3]));
1825     emit_insn (gen_fnms_sf(operands[4],operands[2],operands[5],operands[4]));
1826     emit_insn (gen_fma_sf(operands[0],operands[4],operands[3],operands[5]));
1827     DONE;
1828   })
1830 (define_insn "frest_<mode>"
1831   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1832         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")] UNSPEC_FREST))]
1833   ""
1834   "frest\t%0,%1"
1835   [(set_attr "type" "shuf")])
1837 (define_insn "frsqest_<mode>"
1838   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1839         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")] UNSPEC_FRSQEST))]
1840   ""
1841   "frsqest\t%0,%1"
1842   [(set_attr "type" "shuf")])
1844 (define_insn "fi_<mode>"
1845   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1846         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")
1847                     (match_operand:VSF 2 "spu_reg_operand" "r")] UNSPEC_FI))]
1848   ""
1849   "fi\t%0,%1,%2"
1850   [(set_attr "type" "fp7")])
1853 ;; and
1855 (define_insn "and<mode>3"
1856   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r")
1857         (and:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r")
1858                  (match_operand:MOV 2 "spu_logical_operand" "r,C")))]
1859   ""
1860   "@
1861   and\t%0,%1,%2
1862   and%j2i\t%0,%1,%J2")
1864 (define_insn "anddi3"
1865   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
1866         (and:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
1867                 (match_operand:DI 2 "spu_logical_operand" "r,c")))]
1868   ""
1869   "@
1870   and\t%0,%1,%2
1871   and%k2i\t%0,%1,%K2")
1873 (define_insn "andti3"
1874   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
1875         (and:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
1876                 (match_operand:TI 2 "spu_logical_operand" "r,Y")))]
1877   ""
1878   "@
1879   and\t%0,%1,%2
1880   and%m2i\t%0,%1,%L2")
1882 (define_insn "andc_<mode>"
1883   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1884         (and:ALL (not:ALL (match_operand:ALL 2 "spu_reg_operand" "r"))
1885                  (match_operand:ALL 1 "spu_reg_operand" "r")))]
1886   ""
1887   "andc\t%0,%1,%2")
1889 (define_insn "nand_<mode>"
1890   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1891         (not:ALL (and:ALL (match_operand:ALL 2 "spu_reg_operand" "r")
1892                           (match_operand:ALL 1 "spu_reg_operand" "r"))))]
1893   ""
1894   "nand\t%0,%1,%2")
1897 ;; ior
1899 (define_insn "ior<mode>3"
1900   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r,r")
1901         (ior:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r,0")
1902                  (match_operand:MOV 2 "spu_ior_operand" "r,C,D")))]
1903   ""
1904   "@
1905   or\t%0,%1,%2
1906   or%j2i\t%0,%1,%J2
1907   iohl\t%0,%J2")
1909 (define_insn "iordi3"
1910   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r,r")
1911         (ior:DI (match_operand:DI 1 "spu_reg_operand" "r,r,0")
1912                 (match_operand:DI 2 "spu_ior_operand" "r,c,d")))]
1913   ""
1914   "@
1915   or\t%0,%1,%2
1916   or%k2i\t%0,%1,%K2
1917   iohl\t%0,%K2")
1919 (define_insn "iorti3"
1920   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r,r")
1921         (ior:TI (match_operand:TI 1 "spu_reg_operand" "r,r,0")
1922                 (match_operand:TI 2 "spu_ior_operand" "r,Y,Z")))]
1923   ""
1924   "@
1925   or\t%0,%1,%2
1926   or%m2i\t%0,%1,%L2
1927   iohl\t%0,%L2")
1929 (define_insn "orc_<mode>"
1930   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1931         (ior:ALL (not:ALL (match_operand:ALL 2 "spu_reg_operand" "r"))
1932                  (match_operand:ALL 1 "spu_reg_operand" "r")))]
1933   ""
1934   "orc\t%0,%1,%2")
1936 (define_insn "nor_<mode>"
1937   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1938         (not:ALL (ior:ALL (match_operand:ALL 1 "spu_reg_operand" "r")
1939                           (match_operand:ALL 2 "spu_reg_operand" "r"))))]
1940   ""
1941   "nor\t%0,%1,%2")
1943 ;; xor
1945 (define_insn "xor<mode>3"
1946   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r")
1947         (xor:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r")
1948                  (match_operand:MOV 2 "spu_logical_operand" "r,B")))]
1949   ""
1950   "@
1951   xor\t%0,%1,%2
1952   xor%j2i\t%0,%1,%J2")
1954 (define_insn "xordi3"
1955   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
1956         (xor:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
1957                 (match_operand:DI 2 "spu_logical_operand" "r,c")))]
1958   ""
1959   "@
1960   xor\t%0,%1,%2
1961   xor%k2i\t%0,%1,%K2")
1963 (define_insn "xorti3"
1964   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
1965         (xor:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
1966                 (match_operand:TI 2 "spu_logical_operand" "r,Y")))]
1967   ""
1968   "@
1969   xor\t%0,%1,%2
1970   xor%m2i\t%0,%1,%L2")
1972 (define_insn "eqv_<mode>"
1973   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1974         (not:ALL (xor:ALL (match_operand:ALL 1 "spu_reg_operand" "r")
1975                           (match_operand:ALL 2 "spu_reg_operand" "r"))))]
1976   ""
1977   "eqv\t%0,%1,%2")
1979 ;; one_cmpl
1981 (define_insn "one_cmpl<mode>2"
1982   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
1983         (not:ALL (match_operand:ALL 1 "spu_reg_operand" "r")))]
1984   ""
1985   "nor\t%0,%1,%1")
1988 ;; selb
1990 (define_expand "selb"
1991   [(set (match_operand 0 "spu_reg_operand" "")
1992         (unspec [(match_operand 1 "spu_reg_operand" "")
1993                  (match_operand 2 "spu_reg_operand" "")
1994                  (match_operand 3 "spu_reg_operand" "")] UNSPEC_SELB))]
1995   ""
1996   {
1997     rtx s = gen__selb (operands[0], operands[1], operands[2], operands[3]);
1998     PUT_MODE (SET_SRC (s), GET_MODE (operands[0]));
1999     emit_insn (s);
2000     DONE;
2001   })
2003 ;; This could be defined as a combination of logical operations, but at
2004 ;; one time it caused a crash due to recursive expansion of rtl during CSE.
2005 (define_insn "_selb"
2006   [(set (match_operand 0 "spu_reg_operand" "=r")
2007         (unspec [(match_operand 1 "spu_reg_operand" "r")
2008                  (match_operand 2 "spu_reg_operand" "r")
2009                  (match_operand 3 "spu_reg_operand" "r")] UNSPEC_SELB))]
2010   "GET_MODE(operands[0]) == GET_MODE(operands[1]) 
2011    && GET_MODE(operands[1]) == GET_MODE(operands[2])"
2012   "selb\t%0,%1,%2,%3")
2015 ;; Misc. byte/bit operations
2016 ;; clz/ctz/ffs/popcount/parity
2017 ;; cntb/sumb
2019 (define_insn "clz<mode>2"
2020   [(set (match_operand:VSI 0 "spu_reg_operand" "=r")
2021         (clz:VSI (match_operand:VSI 1 "spu_reg_operand" "r")))]
2022   ""
2023   "clz\t%0,%1")
2025 (define_expand "ctz<mode>2"
2026   [(set (match_dup 2)
2027         (neg:VSI (match_operand:VSI 1 "spu_reg_operand" "")))
2028    (set (match_dup 3) (and:VSI (match_dup 1)
2029                                (match_dup 2)))
2030    (set (match_dup 4) (clz:VSI (match_dup 3)))
2031    (set (match_operand:VSI 0 "spu_reg_operand" "")
2032         (minus:VSI (match_dup 5) (match_dup 4)))]
2033   ""
2034   {
2035      operands[2] = gen_reg_rtx (<MODE>mode);
2036      operands[3] = gen_reg_rtx (<MODE>mode);
2037      operands[4] = gen_reg_rtx (<MODE>mode);
2038      operands[5] = spu_const(<MODE>mode, 31);
2039   })
2041 (define_expand "ffs<mode>2"
2042   [(set (match_dup 2)
2043         (neg:VSI (match_operand:VSI 1 "spu_reg_operand" "")))
2044    (set (match_dup 3) (and:VSI (match_dup 1)
2045                                (match_dup 2)))
2046    (set (match_dup 4) (clz:VSI (match_dup 3)))
2047    (set (match_operand:VSI 0 "spu_reg_operand" "")
2048         (minus:VSI (match_dup 5) (match_dup 4)))]
2049   ""
2050   {
2051      operands[2] = gen_reg_rtx (<MODE>mode);
2052      operands[3] = gen_reg_rtx (<MODE>mode);
2053      operands[4] = gen_reg_rtx (<MODE>mode);
2054      operands[5] = spu_const(<MODE>mode, 32);
2055   })
2057 (define_expand "popcountsi2"
2058   [(set (match_dup 2)
2059         (unspec:SI [(match_operand:SI 1 "spu_reg_operand" "")]
2060                      UNSPEC_CNTB))
2061    (set (match_dup 3)
2062         (unspec:HI [(match_dup 2)] UNSPEC_SUMB))
2063    (set (match_operand:SI 0 "spu_reg_operand" "")
2064         (sign_extend:SI (match_dup 3)))]
2065   ""
2066   {
2067     operands[2] = gen_reg_rtx (SImode);
2068     operands[3] = gen_reg_rtx (HImode);
2069   })
2071 (define_expand "paritysi2"
2072   [(set (match_operand:SI 0 "spu_reg_operand" "")
2073         (parity:SI (match_operand:SI 1 "spu_reg_operand" "")))]
2074   ""
2075   {
2076     operands[2] = gen_reg_rtx (SImode);
2077     emit_insn (gen_popcountsi2(operands[2], operands[1]));
2078     emit_insn (gen_andsi3(operands[0], operands[2], GEN_INT (1)));
2079     DONE;
2080   })
2082 (define_insn "cntb_si"
2083   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2084         (unspec:SI [(match_operand:SI 1 "spu_reg_operand" "r")]
2085                    UNSPEC_CNTB))]
2086   ""
2087   "cntb\t%0,%1"
2088   [(set_attr "type" "fxb")])
2090 (define_insn "cntb_v16qi"
2091   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
2092         (unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r")]
2093                       UNSPEC_CNTB))]
2094   ""
2095   "cntb\t%0,%1"
2096   [(set_attr "type" "fxb")])
2098 (define_insn "sumb_si"
2099   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
2100         (unspec:HI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_SUMB))]
2101   ""
2102   "sumb\t%0,%1,%1"
2103   [(set_attr "type" "fxb")])
2106 ;; ashl, vashl
2108 (define_insn "<v>ashl<mode>3"
2109   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2110         (ashift:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2111                      (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))]
2112   ""
2113   "@
2114   shl<bh>\t%0,%1,%2
2115   shl<bh>i\t%0,%1,%<umask>2"
2116   [(set_attr "type" "fx3")])
2118 (define_insn_and_split "ashldi3"
2119   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2120         (ashift:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2121                    (match_operand:SI 2 "spu_nonmem_operand" "r,I")))
2122    (clobber (match_scratch:SI 3 "=&r,X"))]
2123   ""
2124   "#"
2125   "reload_completed"
2126   [(set (match_dup:DI 0)
2127         (ashift:DI (match_dup:DI 1)
2128                    (match_dup:SI 2)))]
2129   {
2130     rtx op0 = gen_rtx_REG (TImode, REGNO (operands[0]));
2131     rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
2132     rtx op2 = operands[2];
2133     rtx op3 = operands[3];
2135     if (GET_CODE (operands[2]) == REG)
2136       {
2137         emit_insn (gen_addsi3 (op3, op2, GEN_INT (64)));
2138         emit_insn (gen_rotlti3 (op0, op1, GEN_INT (64)));
2139         emit_insn (gen_shlqbybi_ti (op0, op0, op3));
2140         emit_insn (gen_shlqbi_ti (op0, op0, op3));
2141       }
2142     else
2143       {
2144         HOST_WIDE_INT val = INTVAL (operands[2]);
2145         emit_insn (gen_rotlti3 (op0, op1, GEN_INT (64)));
2146         emit_insn (gen_shlqby_ti (op0, op0, GEN_INT (val / 8 + 8)));
2147         if (val % 8)
2148           emit_insn (gen_shlqbi_ti (op0, op0, GEN_INT (val % 8)));
2149       }
2150     DONE;
2151   })
2153 (define_expand "ashlti3"
2154   [(parallel [(set (match_operand:TI 0 "spu_reg_operand" "")
2155                    (ashift:TI (match_operand:TI 1 "spu_reg_operand" "")
2156                               (match_operand:SI 2 "spu_nonmem_operand" "")))
2157               (clobber (match_dup:TI 3))])]
2158   ""
2159   "if (GET_CODE (operands[2]) == CONST_INT)
2160     {
2161       emit_insn (gen_ashlti3_imm(operands[0], operands[1], operands[2]));
2162       DONE;
2163     }
2164    operands[3] = gen_reg_rtx (TImode);")
2166 (define_insn_and_split "ashlti3_imm"
2167   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2168         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2169                    (match_operand:SI 2 "immediate_operand" "O,P")))]
2170   ""
2171   "@
2172    shlqbyi\t%0,%1,%h2
2173    shlqbii\t%0,%1,%e2"
2174   "!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
2175   [(set (match_dup:TI 0)
2176         (ashift:TI (match_dup:TI 1)
2177                    (match_dup:SI 3)))
2178    (set (match_dup:TI 0)
2179         (ashift:TI (match_dup:TI 0)
2180                    (match_dup:SI 4)))]
2181   {
2182     HOST_WIDE_INT val = INTVAL(operands[2]);
2183     operands[3] = GEN_INT (val&7);
2184     operands[4] = GEN_INT (val&-8);
2185   }
2186   [(set_attr "type" "shuf,shuf")])
2188 (define_insn_and_split "ashlti3_reg"
2189   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2190         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r")
2191                    (match_operand:SI 2 "spu_reg_operand" "r")))
2192    (clobber (match_operand:TI 3 "spu_reg_operand" "=&r"))]
2193   ""
2194   "#"
2195   ""
2196   [(set (match_dup:TI 3)
2197         (ashift:TI (match_dup:TI 1)
2198                    (and:SI (match_dup:SI 2)
2199                            (const_int 7))))
2200    (set (match_dup:TI 0)
2201         (ashift:TI (match_dup:TI 3)
2202                    (and:SI (match_dup:SI 2)
2203                            (const_int -8))))]
2204   "")
2206 (define_insn "shlqbybi_ti"
2207   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2208         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2209                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2210                            (const_int -8))))]
2211   ""
2212   "@
2213    shlqbybi\t%0,%1,%2
2214    shlqbyi\t%0,%1,%h2"
2215   [(set_attr "type" "shuf,shuf")])
2217 (define_insn "shlqbi_ti"
2218   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2219         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2220                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2221                            (const_int 7))))]
2222   ""
2223   "@
2224    shlqbi\t%0,%1,%2
2225    shlqbii\t%0,%1,%e2"
2226   [(set_attr "type" "shuf,shuf")])
2228 (define_insn "shlqby_ti"
2229   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2230         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2231                    (mult:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2232                             (const_int 8))))]
2233   ""
2234   "@
2235    shlqby\t%0,%1,%2
2236    shlqbyi\t%0,%1,%f2"
2237   [(set_attr "type" "shuf,shuf")])
2240 ;; lshr, vlshr
2242 (define_insn_and_split "<v>lshr<mode>3"
2243   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2244         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2245                        (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))
2246    (clobber (match_scratch:VHSI 3 "=&r,X"))]
2247   ""
2248   "@
2249    #
2250    rot<bh>mi\t%0,%1,-%<umask>2"
2251   "reload_completed && GET_CODE (operands[2]) == REG"
2252   [(set (match_dup:VHSI 3)
2253         (neg:VHSI (match_dup:VHSI 2)))
2254    (set (match_dup:VHSI 0)
2255         (lshiftrt:VHSI (match_dup:VHSI 1)
2256                        (neg:VHSI (match_dup:VHSI 3))))]
2257   ""
2258   [(set_attr "type" "*,fx3")])
2259   
2261 (define_insn "rotm_<mode>"
2262   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2263         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2264                        (neg:VHSI (match_operand:VHSI 2 "spu_nonmem_operand" "r,W"))))]
2265   ""
2266   "@
2267    rot<bh>m\t%0,%1,%2
2268    rot<bh>mi\t%0,%1,-%<nmask>2"
2269   [(set_attr "type" "fx3")])
2271 (define_expand "lshr<mode>3"
2272   [(parallel [(set (match_operand:DTI 0 "spu_reg_operand" "")
2273                    (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "")
2274                                  (match_operand:SI 2 "spu_nonmem_operand" "")))
2275               (clobber (match_dup:DTI 3))
2276               (clobber (match_dup:SI 4))
2277               (clobber (match_dup:SI 5))])]
2278   ""
2279   "if (GET_CODE (operands[2]) == CONST_INT)
2280     {
2281       emit_insn (gen_lshr<mode>3_imm(operands[0], operands[1], operands[2]));
2282       DONE;
2283     }
2284    operands[3] = gen_reg_rtx (<MODE>mode);
2285    operands[4] = gen_reg_rtx (SImode);
2286    operands[5] = gen_reg_rtx (SImode);")
2288 (define_insn_and_split "lshr<mode>3_imm"
2289   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2290         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2291                       (match_operand:SI 2 "immediate_operand" "O,P")))]
2292   ""
2293   "@
2294    rotqmbyi\t%0,%1,-%h2
2295    rotqmbii\t%0,%1,-%e2"
2296   "!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
2297   [(set (match_dup:DTI 0)
2298         (lshiftrt:DTI (match_dup:DTI 1)
2299                       (match_dup:SI 4)))
2300    (set (match_dup:DTI 0)
2301         (lshiftrt:DTI (match_dup:DTI 0)
2302                       (match_dup:SI 5)))]
2303   {
2304     HOST_WIDE_INT val = INTVAL(operands[2]);
2305     operands[4] = GEN_INT (val&7);
2306     operands[5] = GEN_INT (val&-8);
2307   }
2308   [(set_attr "type" "shuf,shuf")])
2310 (define_insn_and_split "lshr<mode>3_reg"
2311   [(set (match_operand:DTI 0 "spu_reg_operand" "=r")
2312         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r")
2313                       (match_operand:SI 2 "spu_reg_operand" "r")))
2314    (clobber (match_operand:DTI 3 "spu_reg_operand" "=&r"))
2315    (clobber (match_operand:SI 4 "spu_reg_operand" "=&r"))
2316    (clobber (match_operand:SI 5 "spu_reg_operand" "=&r"))]
2317   ""
2318   "#"
2319   ""
2320   [(set (match_dup:DTI 3)
2321         (lshiftrt:DTI (match_dup:DTI 1)
2322                      (and:SI (neg:SI (match_dup:SI 4))
2323                              (const_int 7))))
2324    (set (match_dup:DTI 0)
2325         (lshiftrt:DTI (match_dup:DTI 3)
2326                      (and:SI (neg:SI (and:SI (match_dup:SI 5)
2327                                              (const_int -8)))
2328                              (const_int -8))))]
2329   {
2330     emit_insn (gen_subsi3(operands[4], GEN_INT(0), operands[2]));
2331     emit_insn (gen_subsi3(operands[5], GEN_INT(7), operands[2]));
2332   })
2334 (define_insn "rotqmbybi_<mode>"
2335   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2336         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2337                       (and:SI (neg:SI (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2338                                               (const_int -8)))
2339                               (const_int -8))))]
2340   ""
2341   "@
2342    rotqmbybi\t%0,%1,%2
2343    rotqmbyi\t%0,%1,-%H2"
2344   [(set_attr "type" "shuf")])
2346 (define_insn "rotqmbi_<mode>"
2347   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2348         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2349                       (and:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2350                               (const_int 7))))]
2351   ""
2352   "@
2353    rotqmbi\t%0,%1,%2
2354    rotqmbii\t%0,%1,-%E2"
2355   [(set_attr "type" "shuf")])
2357 (define_insn "rotqmby_<mode>"
2358   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2359         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2360                       (mult:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2361                                (const_int 8))))]
2362   ""
2363   "@
2364    rotqmby\t%0,%1,%2
2365    rotqmbyi\t%0,%1,-%F2"
2366   [(set_attr "type" "shuf")])
2369 ;; ashr, vashr
2371 (define_insn_and_split "<v>ashr<mode>3"
2372   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2373         (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2374                        (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))
2375    (clobber (match_scratch:VHSI 3 "=&r,X"))]
2376   ""
2377   "@
2378    #
2379    rotma<bh>i\t%0,%1,-%<umask>2"
2380   "reload_completed && GET_CODE (operands[2]) == REG"
2381   [(set (match_dup:VHSI 3)
2382         (neg:VHSI (match_dup:VHSI 2)))
2383    (set (match_dup:VHSI 0)
2384         (ashiftrt:VHSI (match_dup:VHSI 1)
2385                        (neg:VHSI (match_dup:VHSI 3))))]
2386   ""
2387   [(set_attr "type" "*,fx3")])
2388   
2390 (define_insn "rotma_<mode>"
2391   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2392         (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2393                        (neg:VHSI (match_operand:VHSI 2 "spu_nonmem_operand" "r,W"))))]
2394   ""
2395   "@
2396    rotma<bh>\t%0,%1,%2
2397    rotma<bh>i\t%0,%1,-%<nmask>2"
2398   [(set_attr "type" "fx3")])
2400 (define_insn_and_split "ashrdi3"
2401   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2402         (ashiftrt:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2403                      (match_operand:SI 2 "spu_nonmem_operand" "r,I")))
2404    (clobber (match_scratch:TI 3 "=&r,&r"))
2405    (clobber (match_scratch:TI 4 "=&r,&r"))
2406    (clobber (match_scratch:SI 5 "=&r,&r"))]
2407   ""
2408   "#"
2409   "reload_completed"
2410   [(set (match_dup:DI 0)
2411         (ashiftrt:DI (match_dup:DI 1)
2412                      (match_dup:SI 2)))]
2413   {
2414     rtx op0 = gen_rtx_REG (TImode, REGNO (operands[0]));
2415     rtx op0v = gen_rtx_REG (V4SImode, REGNO (op0));
2416     rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
2417     rtx op1s = gen_rtx_REG (SImode, REGNO (op1));
2418     rtx op2 = operands[2];
2419     rtx op3 = operands[3];
2420     rtx op4 = operands[4];
2421     rtx op5 = operands[5];
2423     if (GET_CODE (op2) == CONST_INT && INTVAL (op2) >= 63)
2424       {
2425         rtx op0s = gen_rtx_REG (SImode, REGNO (op0));
2426         emit_insn (gen_ashrsi3 (op0s, op1s, GEN_INT (32)));
2427         emit_insn (gen_spu_fsm (op0v, op0s));
2428       }
2429     else if (GET_CODE (op2) == CONST_INT && INTVAL (op2) >= 32)
2430       {
2431         rtx op0d = gen_rtx_REG (V2DImode, REGNO (op0));
2432         HOST_WIDE_INT val = INTVAL (op2);
2433         emit_insn (gen_lshrti3 (op0, op1, GEN_INT (32)));
2434         emit_insn (gen_spu_xswd (op0d, op0v));
2435         if (val > 32)
2436           emit_insn (gen_vashrv4si3 (op0v, op0v, spu_const (V4SImode, val - 32)));
2437       }
2438     else
2439       {
2440         rtx op3v = gen_rtx_REG (V4SImode, REGNO (op3));
2441         unsigned char arr[16] = {
2442           0xff, 0xff, 0xff, 0xff,
2443           0xff, 0xff, 0xff, 0xff,
2444           0x00, 0x00, 0x00, 0x00,
2445           0x00, 0x00, 0x00, 0x00
2446         };
2448         emit_insn (gen_ashrsi3 (op5, op1s, GEN_INT (31)));
2449         emit_move_insn (op4, array_to_constant (TImode, arr));
2450         emit_insn (gen_spu_fsm (op3v, op5));
2452         if (GET_CODE (operands[2]) == REG)
2453           {
2454             emit_insn (gen_selb (op4, op3, op1, op4));
2455             emit_insn (gen_negsi2 (op5, op2));
2456             emit_insn (gen_rotqbybi_ti (op0, op4, op5));
2457             emit_insn (gen_rotqbi_ti (op0, op0, op5));
2458           }
2459         else
2460           {
2461             HOST_WIDE_INT val = -INTVAL (op2);
2462             emit_insn (gen_selb (op0, op3, op1, op4));
2463             if ((val - 7) / 8)
2464               emit_insn (gen_rotqby_ti (op0, op0, GEN_INT ((val - 7) / 8)));
2465             if (val % 8)
2466               emit_insn (gen_rotqbi_ti (op0, op0, GEN_INT (val % 8)));
2467           }
2468       }
2469     DONE;
2470   })
2473 (define_expand "ashrti3"
2474   [(set (match_operand:TI 0 "spu_reg_operand" "")
2475         (ashiftrt:TI (match_operand:TI 1 "spu_reg_operand" "")
2476                      (match_operand:SI 2 "spu_nonmem_operand" "")))]
2477   ""
2478   {
2479     rtx sign_shift = gen_reg_rtx (SImode);
2480     rtx sign_mask = gen_reg_rtx (TImode);
2481     rtx sign_mask_v4si = gen_rtx_SUBREG (V4SImode, sign_mask, 0);
2482     rtx op1_v4si = spu_gen_subreg (V4SImode, operands[1]);
2483     rtx t = gen_reg_rtx (TImode);
2484     emit_insn (gen_subsi3 (sign_shift, GEN_INT (128), force_reg (SImode, operands[2])));
2485     emit_insn (gen_vashrv4si3 (sign_mask_v4si, op1_v4si, spu_const (V4SImode, 31)));
2486     emit_insn (gen_fsm_ti (sign_mask, sign_mask));
2487     emit_insn (gen_ashlti3 (sign_mask, sign_mask, sign_shift));
2488     emit_insn (gen_lshrti3 (t, operands[1], operands[2]));
2489     emit_insn (gen_iorti3 (operands[0], t, sign_mask));
2490     DONE;
2491   })
2493 ;; fsm is used after rotam to replicate the sign across the whole register.
2494 (define_insn "fsm_ti"
2495   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2496         (unspec:TI [(match_operand:TI 1 "spu_reg_operand" "r")] UNSPEC_FSM))]
2497   ""
2498   "fsm\t%0,%1"
2499   [(set_attr "type" "shuf")])
2502 ;; vrotl, rotl
2504 (define_insn "<v>rotl<mode>3"
2505   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2506         (rotate:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2507                      (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))]
2508   ""
2509   "@
2510   rot<bh>\t%0,%1,%2
2511   rot<bh>i\t%0,%1,%<umask>2"
2512   [(set_attr "type" "fx3")])
2514 (define_insn "rotlti3"
2515   [(set (match_operand:TI 0 "spu_reg_operand" "=&r,r,r,r")
2516         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r,r,r")
2517                    (match_operand:SI 2 "spu_nonmem_operand" "r,O,P,I")))]
2518   ""
2519   "@
2520   rotqbybi\t%0,%1,%2\;rotqbi\t%0,%0,%2
2521   rotqbyi\t%0,%1,%h2
2522   rotqbii\t%0,%1,%e2
2523   rotqbyi\t%0,%1,%h2\;rotqbii\t%0,%0,%e2"
2524   [(set_attr "length" "8,4,4,8")
2525    (set_attr "type" "multi1,shuf,shuf,multi1")])
2527 (define_insn "rotqbybi_ti"
2528   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2529         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2530                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2531                            (const_int -8))))]
2532   ""
2533   "@
2534   rotqbybi\t%0,%1,%2
2535   rotqbyi\t%0,%1,%h2"
2536   [(set_attr "type" "shuf,shuf")])
2538 (define_insn "rotqby_ti"
2539   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2540         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2541                    (mult:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2542                             (const_int 8))))]
2543   ""
2544   "@
2545   rotqby\t%0,%1,%2
2546   rotqbyi\t%0,%1,%f2"
2547   [(set_attr "type" "shuf,shuf")])
2549 (define_insn "rotqbi_ti"
2550   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2551         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2552                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2553                            (const_int 7))))]
2554   ""
2555   "@
2556   rotqbi\t%0,%1,%2
2557   rotqbii\t%0,%1,%e2"
2558   [(set_attr "type" "shuf,shuf")])
2561 ;; struct extract/insert
2562 ;; We have to handle mem's because GCC will generate invalid SUBREG's
2563 ;; if it handles them.  We generate better code anyway.
2565 (define_expand "extv"
2566   [(set (match_operand 0 "register_operand" "")
2567         (sign_extract (match_operand 1 "register_operand" "")
2568                       (match_operand:SI 2 "const_int_operand" "")
2569                       (match_operand:SI 3 "const_int_operand" "")))]
2570   ""
2571   { spu_expand_extv(operands, 0); DONE; })
2573 (define_expand "extzv"
2574   [(set (match_operand 0 "register_operand" "")
2575         (zero_extract (match_operand 1 "register_operand" "")
2576                          (match_operand:SI 2 "const_int_operand" "")
2577                          (match_operand:SI 3 "const_int_operand" "")))]
2578   ""
2579   { spu_expand_extv(operands, 1); DONE; })
2581 (define_expand "insv"
2582   [(set (zero_extract (match_operand 0 "register_operand" "")
2583                       (match_operand:SI 1 "const_int_operand" "")
2584                       (match_operand:SI 2 "const_int_operand" ""))
2585         (match_operand 3 "nonmemory_operand" ""))]
2586   ""
2587   { spu_expand_insv(operands); DONE; })
2590 ;; String/block move insn.
2591 ;; Argument 0 is the destination
2592 ;; Argument 1 is the source
2593 ;; Argument 2 is the length
2594 ;; Argument 3 is the alignment
2596 (define_expand "movstrsi"
2597   [(parallel [(set (match_operand:BLK 0 "" "")
2598                    (match_operand:BLK 1 "" ""))
2599               (use (match_operand:SI 2 "" ""))
2600               (use (match_operand:SI 3 "" ""))])]
2601   ""
2602   "
2603   {
2604     if (spu_expand_block_move (operands))
2605       DONE;
2606     else
2607       FAIL;
2608   }")
2611 ;; jump
2613 (define_insn "indirect_jump"
2614   [(set (pc) (match_operand:SI 0 "spu_reg_operand" "r"))]
2615   ""
2616   "bi\t%0"
2617   [(set_attr "type" "br")])
2619 (define_insn "jump"
2620   [(set (pc)
2621         (label_ref (match_operand 0 "" "")))]
2622   ""
2623   "br\t%0"
2624   [(set_attr "type" "br")])
2627 ;; return
2629 ;; This will be used for leaf functions, that don't save any regs and
2630 ;; don't have locals on stack, maybe... that is for functions that
2631 ;; don't change $sp and don't need to save $lr. 
2632 (define_expand "return"
2633     [(return)]
2634   "direct_return()"
2635   "")
2637 ;; used in spu_expand_epilogue to generate return from a function and
2638 ;; explicitly set use of $lr.
2640 (define_insn "_return"
2641   [(return)]
2642   ""
2643   "bi\t$lr"
2644   [(set_attr "type" "br")])
2648 ;; ceq
2650 (define_insn "ceq_<mode>"
2651   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
2652         (eq:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
2653                  (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
2654   ""
2655   "@
2656   ceq<bh>\t%0,%1,%2
2657   ceq<bh>i\t%0,%1,%2")
2659 (define_insn_and_split "ceq_di"
2660   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2661         (eq:SI (match_operand:DI 1 "spu_reg_operand" "r")
2662                (match_operand:DI 2 "spu_reg_operand" "r")))]
2663   ""
2664   "#"
2665   "reload_completed"
2666   [(set (match_dup:SI 0)
2667         (eq:SI (match_dup:DI 1)
2668                (match_dup:DI 2)))]
2669   {
2670     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
2671     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
2672     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
2673     emit_insn (gen_ceq_v4si (op0, op1, op2));
2674     emit_insn (gen_spu_gb (op0, op0));
2675     emit_insn (gen_cgt_si (operands[0], operands[0], GEN_INT (11)));
2676     DONE;
2677   })
2680 ;; We provide the TI compares for completeness and because some parts of
2681 ;; gcc/libgcc use them, even though user code might never see it.
2682 (define_insn "ceq_ti"
2683   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2684         (eq:SI (match_operand:TI 1 "spu_reg_operand" "r")
2685                (match_operand:TI 2 "spu_reg_operand" "r")))]
2686   ""
2687   "ceq\t%0,%1,%2\;gb\t%0,%0\;ceqi\t%0,%0,15"
2688   [(set_attr "type" "multi0")
2689    (set_attr "length" "12")])
2691 (define_insn "ceq_<mode>"
2692   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
2693         (eq:<F2I> (match_operand:VSF 1 "spu_reg_operand" "r")
2694                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
2695   ""
2696   "fceq\t%0,%1,%2")
2698 (define_insn "cmeq_<mode>"
2699   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
2700         (eq:<F2I> (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "r"))
2701                   (abs:VSF (match_operand:VSF 2 "spu_reg_operand" "r"))))]
2702   ""
2703   "fcmeq\t%0,%1,%2")
2705 ;; These implementations will ignore checking of NaN or INF if
2706 ;; compiled with option -ffinite-math-only.
2707 (define_expand "ceq_df"
2708   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2709         (eq:SI (match_operand:DF 1 "spu_reg_operand" "r")
2710                (match_operand:DF 2 "const_zero_operand" "i")))]
2711   ""
2713   if (spu_arch == PROCESSOR_CELL)
2714       {
2715         rtx ra = gen_reg_rtx (V4SImode);
2716         rtx rb = gen_reg_rtx (V4SImode);
2717         rtx temp = gen_reg_rtx (TImode);
2718         rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
2719         rtx temp2 = gen_reg_rtx (V4SImode);
2720         rtx biteq = gen_reg_rtx (V4SImode);
2721         rtx ahi_inf = gen_reg_rtx (V4SImode);
2722         rtx a_nan = gen_reg_rtx (V4SImode);
2723         rtx a_abs = gen_reg_rtx (V4SImode);
2724         rtx b_abs = gen_reg_rtx (V4SImode);
2725         rtx iszero = gen_reg_rtx (V4SImode);
2726         rtx sign_mask = gen_reg_rtx (V4SImode);
2727         rtx nan_mask = gen_reg_rtx (V4SImode);
2728         rtx hihi_promote = gen_reg_rtx (TImode);
2729         rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF,
2730                                                  0x7FFFFFFF, 0xFFFFFFFF);
2732         emit_move_insn (sign_mask, pat);
2733         pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0,
2734                                              0x7FF00000, 0x0);
2735         emit_move_insn (nan_mask, pat);
2736         pat = spu_const_from_ints (TImode, 0x00010203, 0x10111213,
2737                                            0x08090A0B, 0x18191A1B);
2738         emit_move_insn (hihi_promote, pat);
2740         emit_insn (gen_spu_convert (ra, operands[1]));
2741         emit_insn (gen_spu_convert (rb, operands[2]));
2742         emit_insn (gen_ceq_v4si (biteq, ra, rb));
2743         emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, biteq),
2744                                 GEN_INT (4 * 8)));
2745         emit_insn (gen_andv4si3 (biteq, biteq, temp_v4si));
2747         emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
2748         emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
2749         if (!flag_finite_math_only)
2750           {
2751             emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
2752             emit_insn (gen_ceq_v4si (ahi_inf, a_abs, nan_mask));
2753             emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan),
2754                                    GEN_INT (4 * 8)));
2755             emit_insn (gen_andv4si3 (temp2, temp_v4si, ahi_inf));
2756             emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
2757           }
2758         emit_insn (gen_iorv4si3 (temp2, a_abs, b_abs));
2759         emit_insn (gen_ceq_v4si (iszero, temp2, CONST0_RTX (V4SImode)));
2760         emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, iszero),
2761                                 GEN_INT (4 * 8)));
2762         emit_insn (gen_andv4si3 (iszero, iszero, temp_v4si));
2763         emit_insn (gen_iorv4si3 (temp2, biteq, iszero));
2764         if (!flag_finite_math_only)
2765           {
2766             emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
2767           }
2768         emit_insn (gen_shufb (operands[0], temp2, temp2, hihi_promote));
2769         DONE;
2770       }
2773 (define_insn "ceq_<mode>_celledp"
2774   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
2775         (eq:<DF2I> (match_operand:VDF 1 "spu_reg_operand" "r")
2776                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
2777   "spu_arch == PROCESSOR_CELLEDP"
2778   "dfceq\t%0,%1,%2"
2779   [(set_attr "type" "fpd")])
2781 (define_insn "cmeq_<mode>_celledp"
2782   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
2783         (eq:<DF2I> (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "r"))
2784                    (abs:VDF (match_operand:VDF 2 "spu_reg_operand" "r"))))]
2785   "spu_arch == PROCESSOR_CELLEDP"
2786   "dfcmeq\t%0,%1,%2"
2787   [(set_attr "type" "fpd")])
2789 (define_expand "ceq_v2df"
2790   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
2791         (eq:V2DI (match_operand:V2DF 1 "spu_reg_operand" "r")
2792                  (match_operand:V2DF 2 "spu_reg_operand" "r")))]
2793   ""
2795   if (spu_arch == PROCESSOR_CELL)
2796     {
2797       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
2798       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
2799       rtx temp = gen_reg_rtx (TImode);
2800       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
2801       rtx temp2 = gen_reg_rtx (V4SImode);
2802       rtx biteq = gen_reg_rtx (V4SImode);
2803       rtx ahi_inf = gen_reg_rtx (V4SImode);
2804       rtx a_nan = gen_reg_rtx (V4SImode);
2805       rtx a_abs = gen_reg_rtx (V4SImode);
2806       rtx b_abs = gen_reg_rtx (V4SImode);
2807       rtx iszero = gen_reg_rtx (V4SImode);
2808       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF,
2809                                                0x7FFFFFFF, 0xFFFFFFFF);
2810       rtx sign_mask = gen_reg_rtx (V4SImode);
2811       rtx nan_mask = gen_reg_rtx (V4SImode);
2812       rtx hihi_promote = gen_reg_rtx (TImode);
2814       emit_move_insn (sign_mask, pat);
2815       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
2816                                              0x7FF00000, 0x0);
2817       emit_move_insn (nan_mask, pat);
2818       pat = spu_const_from_ints (TImode, 0x00010203, 0x10111213, 
2819                                            0x08090A0B, 0x18191A1B);
2820       emit_move_insn (hihi_promote, pat);
2822       emit_insn (gen_ceq_v4si (biteq, ra, rb));
2823       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, biteq), 
2824                               GEN_INT (4 * 8)));
2825       emit_insn (gen_andv4si3 (biteq, biteq, temp_v4si));
2826       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
2827       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
2828       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
2829       emit_insn (gen_ceq_v4si (ahi_inf, a_abs, nan_mask));
2830       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
2831                               GEN_INT (4 * 8)));
2832       emit_insn (gen_andv4si3 (temp2, temp_v4si, ahi_inf));
2833       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
2834       emit_insn (gen_iorv4si3 (temp2, a_abs, b_abs));
2835       emit_insn (gen_ceq_v4si (iszero, temp2, CONST0_RTX (V4SImode)));
2836       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, iszero), 
2837                               GEN_INT (4 * 8)));
2838       emit_insn (gen_andv4si3 (iszero, iszero, temp_v4si));
2839       emit_insn (gen_iorv4si3 (temp2, biteq, iszero));
2840       emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
2841       emit_insn (gen_shufb (operands[0], temp2, temp2, hihi_promote));
2842       DONE;
2843   }
2846 (define_expand "cmeq_v2df"
2847   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
2848         (eq:V2DI (abs:V2DF (match_operand:V2DF 1 "spu_reg_operand" "r"))
2849                  (abs:V2DF (match_operand:V2DF 2 "spu_reg_operand" "r"))))]
2850   ""
2852   if (spu_arch == PROCESSOR_CELL)
2853     {
2854       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
2855       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
2856       rtx temp = gen_reg_rtx (TImode);
2857       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
2858       rtx temp2 = gen_reg_rtx (V4SImode);
2859       rtx biteq = gen_reg_rtx (V4SImode);
2860       rtx ahi_inf = gen_reg_rtx (V4SImode);
2861       rtx a_nan = gen_reg_rtx (V4SImode);
2862       rtx a_abs = gen_reg_rtx (V4SImode);
2863       rtx b_abs = gen_reg_rtx (V4SImode);
2865       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
2866                                                0x7FFFFFFF, 0xFFFFFFFF);
2867       rtx sign_mask = gen_reg_rtx (V4SImode);
2868       rtx nan_mask = gen_reg_rtx (V4SImode);
2869       rtx hihi_promote = gen_reg_rtx (TImode);
2871       emit_move_insn (sign_mask, pat);
2873       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
2874                                            0x7FF00000, 0x0);
2875       emit_move_insn (nan_mask, pat);
2876       pat = spu_const_from_ints (TImode, 0x00010203, 0x10111213, 
2877                                          0x08090A0B, 0x18191A1B);
2878       emit_move_insn (hihi_promote, pat);
2880       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
2881       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
2882       emit_insn (gen_ceq_v4si (biteq, a_abs, b_abs));
2883       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, biteq), 
2884                                                     GEN_INT (4 * 8)));
2885       emit_insn (gen_andv4si3 (biteq, biteq, temp_v4si));
2886       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
2887       emit_insn (gen_ceq_v4si (ahi_inf, a_abs, nan_mask));
2888       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
2889                                                     GEN_INT (4 * 8)));
2890       emit_insn (gen_andv4si3 (temp2, temp_v4si, ahi_inf));
2891       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
2892       emit_insn (gen_andc_v4si (temp2, biteq, a_nan));
2893       emit_insn (gen_shufb (operands[0], temp2, temp2, hihi_promote));
2894       DONE;
2895   }
2899 ;; cgt
2901 (define_insn "cgt_<mode>"
2902   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
2903         (gt:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
2904                   (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
2905   ""
2906   "@
2907   cgt<bh>\t%0,%1,%2
2908   cgt<bh>i\t%0,%1,%2")
2910 (define_insn "cgt_di_m1" 
2911   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2912         (gt:SI (match_operand:DI 1 "spu_reg_operand" "r")
2913                (const_int -1)))]
2914   ""
2915   "cgti\t%0,%1,-1")
2917 (define_insn_and_split "cgt_di" 
2918   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2919         (gt:SI (match_operand:DI 1 "spu_reg_operand" "r")
2920                (match_operand:DI 2 "spu_reg_operand" "r")))
2921    (clobber (match_scratch:V4SI 3 "=&r"))
2922    (clobber (match_scratch:V4SI 4 "=&r"))
2923    (clobber (match_scratch:V4SI 5 "=&r"))]
2924   ""
2925   "#"
2926   "reload_completed"
2927   [(set (match_dup:SI 0)
2928         (gt:SI (match_dup:DI 1)
2929                (match_dup:DI 2)))]
2930   {
2931     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
2932     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
2933     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
2934     rtx op3 = operands[3];
2935     rtx op4 = operands[4];
2936     rtx op5 = operands[5];
2937     rtx op3d = gen_rtx_REG (V2DImode, REGNO (operands[3]));
2938     emit_insn (gen_clgt_v4si (op3, op1, op2));
2939     emit_insn (gen_ceq_v4si (op4, op1, op2));
2940     emit_insn (gen_cgt_v4si (op5, op1, op2));
2941     emit_insn (gen_spu_xswd (op3d, op3));
2942     emit_insn (gen_selb (op0, op5, op3, op4));
2943     DONE;
2944   })
2946 (define_insn "cgt_ti"
2947   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2948         (gt:SI (match_operand:TI 1 "spu_reg_operand" "r")
2949                (match_operand:TI 2 "spu_reg_operand" "r")))
2950    (clobber (match_scratch:V4SI 3 "=&r"))
2951    (clobber (match_scratch:V4SI 4 "=&r"))
2952    (clobber (match_scratch:V4SI 5 "=&r"))]
2953   ""
2954   "clgt\t%4,%1,%2\;\
2955 ceq\t%3,%1,%2\;\
2956 cgt\t%5,%1,%2\;\
2957 shlqbyi\t%0,%4,4\;\
2958 selb\t%0,%4,%0,%3\;\
2959 shlqbyi\t%0,%0,4\;\
2960 selb\t%0,%4,%0,%3\;\
2961 shlqbyi\t%0,%0,4\;\
2962 selb\t%0,%5,%0,%3"
2963   [(set_attr "type" "multi0")
2964    (set_attr "length" "36")])
2966 (define_insn "cgt_<mode>"
2967   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
2968         (gt:<F2I> (match_operand:VSF 1 "spu_reg_operand" "r")
2969                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
2970   ""
2971   "fcgt\t%0,%1,%2")
2973 (define_insn "cmgt_<mode>"
2974   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
2975         (gt:<F2I> (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "r"))
2976                   (abs:VSF (match_operand:VSF 2 "spu_reg_operand" "r"))))]
2977   ""
2978   "fcmgt\t%0,%1,%2")
2980 (define_expand "cgt_df"
2981   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2982         (gt:SI (match_operand:DF 1 "spu_reg_operand" "r")
2983                (match_operand:DF 2 "const_zero_operand" "i")))]
2984   ""
2986   if (spu_arch == PROCESSOR_CELL)
2987     {
2988       rtx ra = gen_reg_rtx (V4SImode);
2989       rtx rb = gen_reg_rtx (V4SImode);
2990       rtx zero = gen_reg_rtx (V4SImode);
2991       rtx temp = gen_reg_rtx (TImode);
2992       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
2993       rtx temp2 = gen_reg_rtx (V4SImode);
2994       rtx hi_inf = gen_reg_rtx (V4SImode);
2995       rtx a_nan = gen_reg_rtx (V4SImode);
2996       rtx b_nan = gen_reg_rtx (V4SImode);
2997       rtx a_abs = gen_reg_rtx (V4SImode);
2998       rtx b_abs = gen_reg_rtx (V4SImode);
2999       rtx asel = gen_reg_rtx (V4SImode);
3000       rtx bsel = gen_reg_rtx (V4SImode);
3001       rtx abor = gen_reg_rtx (V4SImode);
3002       rtx bbor = gen_reg_rtx (V4SImode);
3003       rtx gt_hi = gen_reg_rtx (V4SImode);
3004       rtx gt_lo = gen_reg_rtx (V4SImode);
3005       rtx sign_mask = gen_reg_rtx (V4SImode);
3006       rtx nan_mask = gen_reg_rtx (V4SImode);
3007       rtx hi_promote = gen_reg_rtx (TImode);
3008       rtx borrow_shuffle = gen_reg_rtx (TImode);
3010       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF,
3011                                                0x7FFFFFFF, 0xFFFFFFFF);
3012       emit_move_insn (sign_mask, pat);
3013       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0,
3014                                              0x7FF00000, 0x0);
3015       emit_move_insn (nan_mask, pat);
3016       pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203,
3017                                          0x08090A0B, 0x08090A0B);
3018       emit_move_insn (hi_promote, pat);
3019       pat = spu_const_from_ints (TImode, 0x04050607, 0xC0C0C0C0,
3020                                          0x0C0D0E0F, 0xC0C0C0C0);
3021       emit_move_insn (borrow_shuffle, pat);
3023       emit_insn (gen_spu_convert (ra, operands[1]));
3024       emit_insn (gen_spu_convert (rb, operands[2]));
3025       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3026       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3028       if (!flag_finite_math_only)
3029         {
3030           /* check if ra is NaN  */
3031           emit_insn (gen_ceq_v4si (hi_inf, a_abs, nan_mask));
3032           emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3033           emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan),
3034                                   GEN_INT (4 * 8)));
3035           emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3036           emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3037           emit_insn (gen_shufb (a_nan, a_nan, a_nan, hi_promote));
3039           /* check if rb is NaN  */
3040           emit_insn (gen_ceq_v4si (hi_inf, b_abs, nan_mask));
3041           emit_insn (gen_clgt_v4si (b_nan, b_abs, nan_mask));
3042           emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, b_nan),
3043                                   GEN_INT (4 * 8)));
3044           emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3045           emit_insn (gen_iorv4si3 (b_nan, b_nan, temp2));
3046           emit_insn (gen_shufb (b_nan, b_nan, b_nan, hi_promote));
3048           /* check if ra or rb is NaN  */
3049           emit_insn (gen_iorv4si3 (a_nan, a_nan, b_nan));
3050         }
3051       emit_move_insn (zero, CONST0_RTX (V4SImode));
3052       emit_insn (gen_vashrv4si3 (asel, ra, spu_const (V4SImode, 31)));
3053       emit_insn (gen_shufb (asel, asel, asel, hi_promote));
3054       emit_insn (gen_bg_v4si (abor, zero, a_abs));
3055       emit_insn (gen_shufb (abor, abor, abor, borrow_shuffle));
3056       emit_insn (gen_sfx_v4si (abor, zero, a_abs, abor));
3057       emit_insn (gen_selb (abor, a_abs, abor, asel));
3059       emit_insn (gen_vashrv4si3 (bsel, rb, spu_const (V4SImode, 31)));
3060       emit_insn (gen_shufb (bsel, bsel, bsel, hi_promote));
3061       emit_insn (gen_bg_v4si (bbor, zero, b_abs));
3062       emit_insn (gen_shufb (bbor, bbor, bbor, borrow_shuffle));
3063       emit_insn (gen_sfx_v4si (bbor, zero, b_abs, bbor));
3064       emit_insn (gen_selb (bbor, b_abs, bbor, bsel));
3066       emit_insn (gen_cgt_v4si (gt_hi, abor, bbor));
3067       emit_insn (gen_clgt_v4si (gt_lo, abor, bbor));
3068       emit_insn (gen_ceq_v4si (temp2, abor, bbor));
3069       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, gt_lo),
3070                                 GEN_INT (4 * 8)));
3071       emit_insn (gen_andv4si3 (temp2, temp2, temp_v4si));
3072       emit_insn (gen_iorv4si3 (temp2, gt_hi, temp2));
3073       emit_insn (gen_shufb (temp2, temp2, temp2, hi_promote));
3074       if (!flag_finite_math_only)
3075         {
3076           /* correct for NaNs  */
3077           emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3078         }
3079       emit_insn (gen_spu_convert (operands[0], temp2));
3080       DONE;
3081     }
3084 (define_insn "cgt_<mode>_celledp"
3085   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
3086         (gt:<DF2I> (match_operand:VDF 1 "spu_reg_operand" "r")
3087                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
3088   "spu_arch == PROCESSOR_CELLEDP"
3089   "dfcgt\t%0,%1,%2"
3090   [(set_attr "type" "fpd")])
3092 (define_insn "cmgt_<mode>_celledp"
3093   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
3094         (gt:<DF2I> (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "r"))
3095                    (abs:VDF (match_operand:VDF 2 "spu_reg_operand" "r"))))]
3096   "spu_arch == PROCESSOR_CELLEDP"
3097   "dfcmgt\t%0,%1,%2"
3098   [(set_attr "type" "fpd")])
3100 (define_expand "cgt_v2df"
3101   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3102         (gt:V2DI (match_operand:V2DF 1 "spu_reg_operand" "r")
3103                  (match_operand:V2DF 2 "spu_reg_operand" "r")))]
3104   ""
3106   if (spu_arch == PROCESSOR_CELL)
3107     {
3108       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3109       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
3110       rtx zero = gen_reg_rtx (V4SImode);
3111       rtx temp = gen_reg_rtx (TImode);
3112       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3113       rtx temp2 = gen_reg_rtx (V4SImode);
3114       rtx hi_inf = gen_reg_rtx (V4SImode);
3115       rtx a_nan = gen_reg_rtx (V4SImode);
3116       rtx b_nan = gen_reg_rtx (V4SImode);
3117       rtx a_abs = gen_reg_rtx (V4SImode);
3118       rtx b_abs = gen_reg_rtx (V4SImode);
3119       rtx asel = gen_reg_rtx (V4SImode);
3120       rtx bsel = gen_reg_rtx (V4SImode);
3121       rtx abor = gen_reg_rtx (V4SImode);
3122       rtx bbor = gen_reg_rtx (V4SImode);
3123       rtx gt_hi = gen_reg_rtx (V4SImode);
3124       rtx gt_lo = gen_reg_rtx (V4SImode);
3125       rtx sign_mask = gen_reg_rtx (V4SImode);
3126       rtx nan_mask = gen_reg_rtx (V4SImode);
3127       rtx hi_promote = gen_reg_rtx (TImode);
3128       rtx borrow_shuffle = gen_reg_rtx (TImode);
3129       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3130                                                0x7FFFFFFF, 0xFFFFFFFF);
3131       emit_move_insn (sign_mask, pat);
3132       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3133                                            0x7FF00000, 0x0);
3134       emit_move_insn (nan_mask, pat);
3135       pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203, 
3136                                          0x08090A0B, 0x08090A0B);
3137       emit_move_insn (hi_promote, pat);
3138       pat = spu_const_from_ints (TImode, 0x04050607, 0xC0C0C0C0, 
3139                                          0x0C0D0E0F, 0xC0C0C0C0);
3140       emit_move_insn (borrow_shuffle, pat);
3142       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3143       emit_insn (gen_ceq_v4si (hi_inf, a_abs, nan_mask));
3144       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3145       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
3146                                                     GEN_INT (4 * 8)));
3147       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3148       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3149       emit_insn (gen_shufb (a_nan, a_nan, a_nan, hi_promote));
3150       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3151       emit_insn (gen_ceq_v4si (hi_inf, b_abs, nan_mask));
3152       emit_insn (gen_clgt_v4si (b_nan, b_abs, nan_mask));
3153       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, b_nan), 
3154                                                     GEN_INT (4 * 8)));
3155       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3156       emit_insn (gen_iorv4si3 (b_nan, b_nan, temp2));
3157       emit_insn (gen_shufb (b_nan, b_nan, b_nan, hi_promote));
3158       emit_insn (gen_iorv4si3 (a_nan, a_nan, b_nan));
3159       emit_move_insn (zero, CONST0_RTX (V4SImode));
3160       emit_insn (gen_vashrv4si3 (asel, ra, spu_const (V4SImode, 31)));
3161       emit_insn (gen_shufb (asel, asel, asel, hi_promote));
3162       emit_insn (gen_bg_v4si (abor, zero, a_abs));
3163       emit_insn (gen_shufb (abor, abor, abor, borrow_shuffle));
3164       emit_insn (gen_sfx_v4si (abor, zero, a_abs, abor));
3165       emit_insn (gen_selb (abor, a_abs, abor, asel));
3166       emit_insn (gen_vashrv4si3 (bsel, rb, spu_const (V4SImode, 31)));
3167       emit_insn (gen_shufb (bsel, bsel, bsel, hi_promote));
3168       emit_insn (gen_bg_v4si (bbor, zero, b_abs));
3169       emit_insn (gen_shufb (bbor, bbor, bbor, borrow_shuffle));
3170       emit_insn (gen_sfx_v4si (bbor, zero, b_abs, bbor));
3171       emit_insn (gen_selb (bbor, b_abs, bbor, bsel));
3172       emit_insn (gen_cgt_v4si (gt_hi, abor, bbor));
3173       emit_insn (gen_clgt_v4si (gt_lo, abor, bbor));
3174       emit_insn (gen_ceq_v4si (temp2, abor, bbor));
3175       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, gt_lo), 
3176                                                     GEN_INT (4 * 8)));
3177       emit_insn (gen_andv4si3 (temp2, temp2, temp_v4si));
3178       emit_insn (gen_iorv4si3 (temp2, gt_hi, temp2));
3180       emit_insn (gen_shufb (temp2, temp2, temp2, hi_promote));
3181       emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3182       emit_move_insn (operands[0], spu_gen_subreg (V2DImode, temp2));
3183       DONE;
3184     } 
3187 (define_expand "cmgt_v2df"
3188   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3189         (gt:V2DI (abs:V2DF (match_operand:V2DF 1 "spu_reg_operand" "r"))
3190                  (abs:V2DF (match_operand:V2DF 2 "spu_reg_operand" "r"))))]
3191   ""
3193   if (spu_arch == PROCESSOR_CELL)
3194     {
3195       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3196       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
3197       rtx temp = gen_reg_rtx (TImode);
3198       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3199       rtx temp2 = gen_reg_rtx (V4SImode);
3200       rtx hi_inf = gen_reg_rtx (V4SImode);
3201       rtx a_nan = gen_reg_rtx (V4SImode);
3202       rtx b_nan = gen_reg_rtx (V4SImode);
3203       rtx a_abs = gen_reg_rtx (V4SImode);
3204       rtx b_abs = gen_reg_rtx (V4SImode);
3205       rtx gt_hi = gen_reg_rtx (V4SImode);
3206       rtx gt_lo = gen_reg_rtx (V4SImode);
3207       rtx sign_mask = gen_reg_rtx (V4SImode);
3208       rtx nan_mask = gen_reg_rtx (V4SImode);
3209       rtx hi_promote = gen_reg_rtx (TImode);
3210       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3211                                                0x7FFFFFFF, 0xFFFFFFFF);
3212       emit_move_insn (sign_mask, pat);
3213       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3214                                            0x7FF00000, 0x0);
3215       emit_move_insn (nan_mask, pat);
3216       pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203, 
3217                                          0x08090A0B, 0x08090A0B);
3218       emit_move_insn (hi_promote, pat);
3220       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3221       emit_insn (gen_ceq_v4si (hi_inf, a_abs, nan_mask));
3222       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3223       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
3224                                                     GEN_INT (4 * 8)));
3225       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3226       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3227       emit_insn (gen_shufb (a_nan, a_nan, a_nan, hi_promote));
3228       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3229       emit_insn (gen_ceq_v4si (hi_inf, b_abs, nan_mask));
3230       emit_insn (gen_clgt_v4si (b_nan, b_abs, nan_mask));
3231       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, b_nan), 
3232                                                     GEN_INT (4 * 8)));
3233       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3234       emit_insn (gen_iorv4si3 (b_nan, b_nan, temp2));
3235       emit_insn (gen_shufb (b_nan, b_nan, b_nan, hi_promote));
3236       emit_insn (gen_iorv4si3 (a_nan, a_nan, b_nan));
3238       emit_insn (gen_clgt_v4si (gt_hi, a_abs, b_abs));
3239       emit_insn (gen_clgt_v4si (gt_lo, a_abs, b_abs));
3240       emit_insn (gen_ceq_v4si (temp2, a_abs, b_abs));
3241       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, gt_lo), 
3242                                                     GEN_INT (4 * 8)));
3243       emit_insn (gen_andv4si3 (temp2, temp2, temp_v4si));
3244       emit_insn (gen_iorv4si3 (temp2, gt_hi, temp2));
3245       emit_insn (gen_shufb (temp2, temp2, temp2, hi_promote));
3246       emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3247       emit_move_insn (operands[0], spu_gen_subreg (V2DImode, temp2));
3248       DONE;
3249     }
3253 ;; clgt
3255 (define_insn "clgt_<mode>"
3256   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
3257         (gtu:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
3258                    (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
3259   ""
3260   "@
3261   clgt<bh>\t%0,%1,%2
3262   clgt<bh>i\t%0,%1,%2")
3264 (define_insn_and_split "clgt_di" 
3265   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3266         (gtu:SI (match_operand:DI 1 "spu_reg_operand" "r")
3267                 (match_operand:DI 2 "spu_reg_operand" "r")))
3268    (clobber (match_scratch:V4SI 3 "=&r"))
3269    (clobber (match_scratch:V4SI 4 "=&r"))
3270    (clobber (match_scratch:V4SI 5 "=&r"))]
3271   ""
3272   "#"
3273   "reload_completed"
3274   [(set (match_dup:SI 0)
3275         (gtu:SI (match_dup:DI 1)
3276                 (match_dup:DI 2)))]
3277   {
3278     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
3279     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
3280     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
3281     rtx op3 = operands[3];
3282     rtx op4 = operands[4];
3283     rtx op5 = operands[5];
3284     rtx op5d = gen_rtx_REG (V2DImode, REGNO (operands[5]));
3285     emit_insn (gen_clgt_v4si (op3, op1, op2));
3286     emit_insn (gen_ceq_v4si (op4, op1, op2));
3287     emit_insn (gen_spu_xswd (op5d, op3));
3288     emit_insn (gen_selb (op0, op3, op5, op4));
3289     DONE;
3290   })
3292 (define_insn "clgt_ti"
3293   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3294         (gtu:SI (match_operand:TI 1 "spu_reg_operand" "r")
3295                (match_operand:TI 2 "spu_reg_operand" "r")))
3296    (clobber (match_scratch:V4SI 3 "=&r"))
3297    (clobber (match_scratch:V4SI 4 "=&r"))]
3298   ""
3299   "ceq\t%3,%1,%2\;\
3300 clgt\t%4,%1,%2\;\
3301 shlqbyi\t%0,%4,4\;\
3302 selb\t%0,%4,%0,%3\;\
3303 shlqbyi\t%0,%0,4\;\
3304 selb\t%0,%4,%0,%3\;\
3305 shlqbyi\t%0,%0,4\;\
3306 selb\t%0,%4,%0,%3"
3307   [(set_attr "type" "multi0")
3308    (set_attr "length" "32")])
3311 ;; dftsv
3312 (define_insn "dftsv_celledp"
3313   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3314         (unspec:V2DI [(match_operand:V2DF 1 "spu_reg_operand"  "r")
3315                       (match_operand:SI   2 "const_int_operand" "i")]
3316                       UNSPEC_DFTSV))]
3317   "spu_arch == PROCESSOR_CELLEDP"
3318   "dftsv\t%0,%1,%2"
3319   [(set_attr "type" "fpd")])
3321 (define_expand "dftsv"
3322   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3323         (unspec:V2DI [(match_operand:V2DF 1 "spu_reg_operand" "r")
3324                       (match_operand:SI   2 "const_int_operand" "i")]
3325                       UNSPEC_DFTSV))]
3326   ""
3328   if (spu_arch == PROCESSOR_CELL)
3329     {
3330       rtx result = gen_reg_rtx (V4SImode);
3331       emit_move_insn (result, CONST0_RTX (V4SImode));
3333       if (INTVAL (operands[2]))
3334         {
3335           rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3336           rtx abs = gen_reg_rtx (V4SImode);
3337           rtx sign = gen_reg_rtx (V4SImode);
3338           rtx temp = gen_reg_rtx (TImode);
3339           rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3340           rtx temp2 = gen_reg_rtx (V4SImode);
3341           rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3342                                                    0x7FFFFFFF, 0xFFFFFFFF);
3343           rtx sign_mask = gen_reg_rtx (V4SImode);
3344           rtx hi_promote = gen_reg_rtx (TImode);
3345           emit_move_insn (sign_mask, pat);
3346           pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203, 
3347                                              0x08090A0B, 0x08090A0B);
3348           emit_move_insn (hi_promote, pat);
3350           emit_insn (gen_vashrv4si3 (sign, ra, spu_const (V4SImode, 31)));
3351           emit_insn (gen_shufb (sign, sign, sign, hi_promote));
3352           emit_insn (gen_andv4si3 (abs, ra, sign_mask));
3354           /* NaN  or +inf or -inf */
3355           if (INTVAL (operands[2]) & 0x70)
3356             {
3357               rtx nan_mask = gen_reg_rtx (V4SImode);
3358               rtx isinf = gen_reg_rtx (V4SImode);
3359               pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3360                                                    0x7FF00000, 0x0);
3361               emit_move_insn (nan_mask, pat);
3362               emit_insn (gen_ceq_v4si (isinf, abs, nan_mask));
3364               /* NaN  */
3365               if (INTVAL (operands[2]) & 0x40)
3366                 {
3367                   rtx isnan = gen_reg_rtx (V4SImode);
3368                   emit_insn (gen_clgt_v4si (isnan, abs, nan_mask));
3369                   emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, isnan), 
3370                                                              GEN_INT (4 * 8)));
3371                   emit_insn (gen_andv4si3 (temp2, temp_v4si, isinf));
3372                   emit_insn (gen_iorv4si3 (isnan, isnan, temp2));
3373                   emit_insn (gen_shufb (isnan, isnan, isnan, hi_promote));
3374                   emit_insn (gen_iorv4si3 (result, result, isnan));
3375                 }
3376               /* +inf or -inf  */
3377               if (INTVAL (operands[2]) & 0x30)
3378                 {
3379                   emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, isinf), 
3380                                                              GEN_INT (4 * 8)));
3381                   emit_insn (gen_andv4si3 (isinf, isinf, temp_v4si));
3382                   emit_insn (gen_shufb (isinf, isinf, isinf, hi_promote));
3384                   /* +inf  */
3385                   if (INTVAL (operands[2]) & 0x20)
3386                     {
3387                       emit_insn (gen_andc_v4si (temp2, isinf, sign));
3388                       emit_insn (gen_iorv4si3 (result, result, temp2));
3389                     }
3390                   /* -inf  */
3391                   if (INTVAL (operands[2]) & 0x10)
3392                     {
3393                       emit_insn (gen_andv4si3 (temp2, isinf, sign));
3394                       emit_insn (gen_iorv4si3 (result, result, temp2));
3395                     }
3396                 }
3397             }
3399           /* 0 or denorm  */
3400           if (INTVAL (operands[2]) & 0xF)
3401             {
3402               rtx iszero = gen_reg_rtx (V4SImode);
3403               emit_insn (gen_ceq_v4si (iszero, abs, CONST0_RTX (V4SImode)));
3404               emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, iszero), 
3405                                                           GEN_INT (4 * 8)));
3406               emit_insn (gen_andv4si3 (iszero, iszero, temp_v4si));
3408               /* denorm  */
3409               if (INTVAL (operands[2]) & 0x3)
3410                 {
3411                   rtx isdenorm = gen_reg_rtx (V4SImode);
3412                   rtx denorm_mask = gen_reg_rtx (V4SImode);
3413                   emit_move_insn (denorm_mask, spu_const (V4SImode, 0xFFFFF));
3414                   emit_insn (gen_clgt_v4si (isdenorm, abs, denorm_mask));
3415                   emit_insn (gen_nor_v4si (isdenorm, isdenorm, iszero));
3416                   emit_insn (gen_shufb (isdenorm, isdenorm, 
3417                                         isdenorm, hi_promote));
3418                   /* +denorm  */
3419                   if (INTVAL (operands[2]) & 0x2)
3420                     {
3421                       emit_insn (gen_andc_v4si (temp2, isdenorm, sign));
3422                       emit_insn (gen_iorv4si3 (result, result, temp2));
3423                     }
3424                   /* -denorm  */
3425                   if (INTVAL (operands[2]) & 0x1)
3426                     {
3427                       emit_insn (gen_andv4si3 (temp2, isdenorm, sign));
3428                       emit_insn (gen_iorv4si3 (result, result, temp2));
3429                     }
3430                 }
3432               /* 0  */
3433               if (INTVAL (operands[2]) & 0xC)
3434                 {
3435                   emit_insn (gen_shufb (iszero, iszero, iszero, hi_promote));
3436                   /* +0  */
3437                   if (INTVAL (operands[2]) & 0x8)
3438                     {
3439                       emit_insn (gen_andc_v4si (temp2, iszero, sign));
3440                       emit_insn (gen_iorv4si3 (result, result, temp2));
3441                     }
3442                   /* -0  */
3443                   if (INTVAL (operands[2]) & 0x4)
3444                     {
3445                       emit_insn (gen_andv4si3 (temp2, iszero, sign));
3446                       emit_insn (gen_iorv4si3 (result, result, temp2));
3447                     }
3448                 }
3449              }
3450           }
3451       emit_move_insn (operands[0], spu_gen_subreg (V2DImode, result));
3452       DONE;
3453     }
3457 ;; branches
3459 (define_insn ""
3460   [(set (pc)
3461         (if_then_else (match_operator 1 "branch_comparison_operator"
3462                                       [(match_operand 2
3463                                                       "spu_reg_operand" "r")
3464                                        (const_int 0)])
3465                       (label_ref (match_operand 0 "" ""))
3466                       (pc)))]
3467   ""
3468   "br%b2%b1z\t%2,%0"
3469   [(set_attr "type" "br")])
3471 (define_insn ""
3472   [(set (pc)
3473         (if_then_else (match_operator 0 "branch_comparison_operator"
3474                                       [(match_operand 1
3475                                                       "spu_reg_operand" "r")
3476                                        (const_int 0)])
3477                       (return)
3478                       (pc)))]
3479   "direct_return ()"
3480   "bi%b1%b0z\t%1,$lr"
3481   [(set_attr "type" "br")])
3483 (define_insn ""
3484   [(set (pc)
3485         (if_then_else (match_operator 1 "branch_comparison_operator"
3486                                       [(match_operand 2
3487                                                       "spu_reg_operand" "r")
3488                                        (const_int 0)])
3489                       (pc)
3490                       (label_ref (match_operand 0 "" ""))))]
3491   ""
3492   "br%b2%b1z\t%2,%0"
3493   [(set_attr "type" "br")])
3495 (define_insn ""
3496   [(set (pc)
3497         (if_then_else (match_operator 0 "branch_comparison_operator"
3498                                       [(match_operand 1
3499                                                       "spu_reg_operand" "r")
3500                                        (const_int 0)])
3501                       (pc)
3502                       (return)))]
3503   "direct_return ()"
3504   "bi%b1%b0z\t%1,$lr"
3505   [(set_attr "type" "br")])
3508 ;; Compare insns are next.  Note that the spu has two types of compares,
3509 ;; signed & unsigned, and one type of branch.
3511 ;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc
3512 ;; insns, and branches.  We store the operands of compares until we see
3513 ;; how it is used.
3515 (define_expand "cmp<mode>"
3516   [(set (cc0)
3517         (compare (match_operand:VQHSI 0 "spu_reg_operand" "")
3518                  (match_operand:VQHSI 1 "spu_nonmem_operand" "")))]
3519   ""
3520   {
3521     spu_compare_op0 = operands[0];
3522     spu_compare_op1 = operands[1];
3523     DONE;
3524   })
3526 (define_expand "cmp<mode>"
3527   [(set (cc0)
3528         (compare (match_operand:DTI 0 "spu_reg_operand" "")
3529                  (match_operand:DTI 1 "spu_reg_operand" "")))]
3530   ""
3531   {
3532     spu_compare_op0 = operands[0];
3533     spu_compare_op1 = operands[1];
3534     DONE;
3535   })
3537 (define_expand "cmp<mode>"
3538   [(set (cc0)
3539         (compare (match_operand:VSF 0 "spu_reg_operand" "")
3540                  (match_operand:VSF 1 "spu_reg_operand" "")))]
3541   ""
3542   {
3543     spu_compare_op0 = operands[0];
3544     spu_compare_op1 = operands[1];
3545     DONE;
3546   })
3548 (define_expand "cmpdf"
3549   [(set (cc0)
3550         (compare (match_operand:DF 0 "register_operand" "")
3551                  (match_operand:DF 1 "register_operand" "")))]
3552   ""
3553   "{
3554   spu_compare_op0 = operands[0];
3555   spu_compare_op1 = operands[1];
3556   DONE;
3559 ;; vector conditional compare patterns
3560 (define_expand "vcond<mode>"
3561   [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
3562         (if_then_else:VCMP
3563           (match_operator 3 "comparison_operator"
3564             [(match_operand:VCMP 4 "spu_reg_operand" "r")
3565              (match_operand:VCMP 5 "spu_reg_operand" "r")])
3566           (match_operand:VCMP 1 "spu_reg_operand" "r")
3567           (match_operand:VCMP 2 "spu_reg_operand" "r")))]
3568   ""
3569   {
3570     if (spu_emit_vector_cond_expr (operands[0], operands[1], operands[2],
3571                                    operands[3], operands[4], operands[5]))
3572     DONE;
3573     else
3574     FAIL;
3575   })
3577 (define_expand "vcondu<mode>"
3578   [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
3579         (if_then_else:VCMPU
3580           (match_operator 3 "comparison_operator"
3581             [(match_operand:VCMPU 4 "spu_reg_operand" "r")
3582              (match_operand:VCMPU 5 "spu_reg_operand" "r")])
3583           (match_operand:VCMPU 1 "spu_reg_operand" "r")
3584           (match_operand:VCMPU 2 "spu_reg_operand" "r")))]
3585   ""
3586   {
3587     if (spu_emit_vector_cond_expr (operands[0], operands[1], operands[2],
3588                                    operands[3], operands[4], operands[5]))
3589     DONE;
3590     else
3591     FAIL;
3592   })
3593         
3595 ;; branch on condition
3597 (define_expand "beq"
3598   [(use (match_operand 0 "" ""))]
3599   ""
3600   { spu_emit_branch_or_set (0, EQ, operands); DONE; })
3602 (define_expand "bne"
3603   [(use (match_operand 0 "" ""))]
3604   ""
3605   { spu_emit_branch_or_set (0, NE, operands); DONE; })
3607 (define_expand "bge"
3608   [(use (match_operand 0 "" ""))]
3609   ""
3610   { spu_emit_branch_or_set (0, GE, operands); DONE; })
3612 (define_expand "bgt"
3613   [(use (match_operand 0 "" ""))]
3614   ""
3615   { spu_emit_branch_or_set (0, GT, operands); DONE; })
3617 (define_expand "ble"
3618   [(use (match_operand 0 "" ""))]
3619   ""
3620   { spu_emit_branch_or_set (0, LE, operands); DONE; })
3622 (define_expand "blt"
3623   [(use (match_operand 0 "" ""))]
3624   ""
3625   { spu_emit_branch_or_set (0, LT, operands); DONE; })
3627 (define_expand "bgeu"
3628   [(use (match_operand 0 "" ""))]
3629   ""
3630   { spu_emit_branch_or_set (0, GEU, operands); DONE; })
3632 (define_expand "bgtu"
3633   [(use (match_operand 0 "" ""))]
3634   ""
3635   { spu_emit_branch_or_set (0, GTU, operands); DONE; })
3637 (define_expand "bleu"
3638   [(use (match_operand 0 "" ""))]
3639   ""
3640   { spu_emit_branch_or_set (0, LEU, operands); DONE; })
3642 (define_expand "bltu"
3643   [(use (match_operand 0 "" ""))]
3644   ""
3645   { spu_emit_branch_or_set (0, LTU, operands); DONE; })
3648 ;; set on condition
3650 (define_expand "seq"
3651   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
3652   ""
3653   { spu_emit_branch_or_set (1, EQ, operands); DONE; })
3655 (define_expand "sne"
3656   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
3657   ""
3658   { spu_emit_branch_or_set (1, NE, operands); DONE; })
3660 (define_expand "sgt"
3661   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
3662   ""
3663   { spu_emit_branch_or_set (1, GT, operands); DONE; })
3665 (define_expand "slt"
3666   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
3667   ""
3668   { spu_emit_branch_or_set (1, LT, operands); DONE; })
3670 (define_expand "sge"
3671   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
3672   ""
3673   { spu_emit_branch_or_set (1, GE, operands); DONE; })
3675 (define_expand "sle"
3676   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
3677   ""
3678   { spu_emit_branch_or_set (1, LE, operands); DONE; })
3680 (define_expand "sgtu"
3681   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
3682   ""
3683   { spu_emit_branch_or_set (1, GTU, operands); DONE; })
3685 (define_expand "sltu"
3686   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
3687   ""
3688   { spu_emit_branch_or_set (1, LTU, operands); DONE; })
3690 (define_expand "sgeu"
3691   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
3692   ""
3693   { spu_emit_branch_or_set (1, GEU, operands); DONE; })
3695 (define_expand "sleu"
3696   [(clobber (match_operand:SI 0 "spu_reg_operand" ""))]
3697   ""
3698   { spu_emit_branch_or_set (1, LEU, operands); DONE; })
3701 ;; conditional move
3703 ;; Define this first one so HAVE_conditional_move is defined.
3704 (define_insn "movcc_dummy"
3705   [(set (match_operand 0 "" "")
3706        (if_then_else (match_operand 1 "" "")
3707                      (match_operand 2 "" "")
3708                      (match_operand 3 "" "")))]
3709   "!operands[0]"
3710   "")
3712 (define_expand "mov<mode>cc"
3713   [(set (match_operand:ALL 0 "spu_reg_operand" "")
3714         (if_then_else:ALL (match_operand 1 "comparison_operator" "")
3715                       (match_operand:ALL 2 "spu_reg_operand" "")
3716                       (match_operand:ALL 3 "spu_reg_operand" "")))]
3717   ""
3718   {
3719     spu_emit_branch_or_set(2, GET_CODE(operands[1]), operands);
3720     DONE;
3721   })
3723 ;; This pattern is used when the result of a compare is not large
3724 ;; enough to use in a selb when expanding conditional moves.
3725 (define_expand "extend_compare"
3726   [(set (match_operand 0 "spu_reg_operand" "=r")
3727         (unspec [(match_operand 1 "spu_reg_operand" "r")] UNSPEC_EXTEND_CMP))]
3728   ""
3729   {
3730     emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3731                             gen_rtx_UNSPEC (GET_MODE (operands[0]),
3732                                             gen_rtvec (1, operands[1]),
3733                                             UNSPEC_EXTEND_CMP)));
3734     DONE;
3735   })
3737 (define_insn "extend_compare<mode>"
3738   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
3739         (unspec:ALL [(match_operand 1 "spu_reg_operand" "r")] UNSPEC_EXTEND_CMP))]
3740   "operands"
3741   "fsm\t%0,%1"
3742   [(set_attr "type" "shuf")])
3745 ;; case
3747 ;; operand 0 is index
3748 ;; operand 1 is the minimum bound
3749 ;; operand 2 is the maximum bound - minimum bound + 1
3750 ;; operand 3 is CODE_LABEL for the table;
3751 ;; operand 4 is the CODE_LABEL to go to if index out of range.
3752 (define_expand "casesi"
3753   [(match_operand:SI 0 "spu_reg_operand" "")
3754    (match_operand:SI 1 "immediate_operand" "")
3755    (match_operand:SI 2 "immediate_operand" "")
3756    (match_operand 3 "" "")
3757    (match_operand 4 "" "")]
3758   ""
3759   {
3760     rtx table = gen_reg_rtx (SImode);
3761     rtx index = gen_reg_rtx (SImode);
3762     rtx sindex = gen_reg_rtx (SImode);
3763     rtx addr = gen_reg_rtx (Pmode);
3765     emit_move_insn (table, gen_rtx_LABEL_REF (SImode, operands[3]));
3767     emit_insn (gen_subsi3(index, operands[0], force_reg(SImode, operands[1])));
3768     emit_insn (gen_ashlsi3(sindex, index, GEN_INT (2)));
3769     emit_move_insn (addr, gen_rtx_MEM (SImode,
3770                                        gen_rtx_PLUS (SImode, table, sindex)));
3771     if (flag_pic)
3772       emit_insn (gen_addsi3 (addr, addr, table));
3774     emit_cmp_and_jump_insns (index, operands[2], GTU, NULL_RTX, SImode, 1, operands[4]);
3775     emit_jump_insn (gen_tablejump (addr, operands[3]));
3776     DONE;
3777   })
3779 (define_insn "tablejump"
3780   [(set (pc) (match_operand:SI 0 "spu_reg_operand" "r"))
3781    (use (label_ref (match_operand 1 "" "")))]
3782   ""
3783   "bi\t%0"
3784   [(set_attr "type" "br")])
3787 ;; call
3789 ;; Note that operand 1 is total size of args, in bytes,
3790 ;; and what the call insn wants is the number of words.
3791 (define_expand "sibcall"
3792   [(parallel
3793     [(call (match_operand:QI 0 "call_operand" "")
3794            (match_operand:QI 1 "" ""))
3795      (use (reg:SI 0))])]
3796   ""
3797   {
3798     if (! call_operand (operands[0], QImode))
3799       XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
3800   })
3802 (define_insn "_sibcall"
3803   [(parallel
3804     [(call (match_operand:QI 0 "call_operand" "R,S")
3805            (match_operand:QI 1 "" "i,i"))
3806      (use (reg:SI 0))])]
3807   "SIBLING_CALL_P(insn)"
3808   "@
3809    bi\t%i0
3810    br\t%0"
3811    [(set_attr "type" "br,br")])
3813 (define_expand "sibcall_value"
3814   [(parallel
3815     [(set (match_operand 0 "" "")
3816           (call (match_operand:QI 1 "call_operand" "")
3817                 (match_operand:QI 2 "" "")))
3818      (use (reg:SI 0))])]
3819   ""
3820   {
3821     if (! call_operand (operands[1], QImode))
3822       XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
3823   })
3825 (define_insn "_sibcall_value"
3826   [(parallel
3827     [(set (match_operand 0 "" "")
3828           (call (match_operand:QI 1 "call_operand" "R,S")
3829                 (match_operand:QI 2 "" "i,i")))
3830      (use (reg:SI 0))])]
3831   "SIBLING_CALL_P(insn)"
3832   "@
3833    bi\t%i1
3834    br\t%1"
3835    [(set_attr "type" "br,br")])
3837 ;; Note that operand 1 is total size of args, in bytes,
3838 ;; and what the call insn wants is the number of words.
3839 (define_expand "call"
3840   [(parallel
3841     [(call (match_operand:QI 0 "call_operand" "")
3842            (match_operand:QI 1 "" ""))
3843      (clobber (reg:SI 0))
3844      (clobber (reg:SI 130))])]
3845   ""
3846   {
3847     if (! call_operand (operands[0], QImode))
3848       XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
3849   })
3851 (define_insn "_call"
3852   [(parallel
3853     [(call (match_operand:QI 0 "call_operand" "R,S,T")
3854            (match_operand:QI 1 "" "i,i,i"))
3855      (clobber (reg:SI 0))
3856      (clobber (reg:SI 130))])]
3857   ""
3858   "@
3859    bisl\t$lr,%i0
3860    brsl\t$lr,%0
3861    brasl\t$lr,%0"
3862    [(set_attr "type" "br")])
3864 (define_expand "call_value"
3865   [(parallel
3866     [(set (match_operand 0 "" "")
3867           (call (match_operand:QI 1 "call_operand" "")
3868                 (match_operand:QI 2 "" "")))
3869      (clobber (reg:SI 0))
3870      (clobber (reg:SI 130))])]
3871   ""
3872   {
3873     if (! call_operand (operands[1], QImode))
3874       XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
3875   })
3877 (define_insn "_call_value"
3878   [(parallel
3879     [(set (match_operand 0 "" "")
3880           (call (match_operand:QI 1 "call_operand" "R,S,T")
3881                 (match_operand:QI 2 "" "i,i,i")))
3882      (clobber (reg:SI 0))
3883      (clobber (reg:SI 130))])]
3884   ""
3885   "@
3886    bisl\t$lr,%i1
3887    brsl\t$lr,%1
3888    brasl\t$lr,%1"
3889    [(set_attr "type" "br")])
3891 (define_expand "untyped_call"
3892   [(parallel [(call (match_operand 0 "" "")
3893                     (const_int 0))
3894               (match_operand 1 "" "")
3895               (match_operand 2 "" "")])]
3896   ""
3897   {
3898     int i;
3899     rtx reg = gen_rtx_REG (TImode, 3);
3901     /* We need to use call_value so the return value registers don't get
3902      * clobbered. */
3903     emit_call_insn (gen_call_value (reg, operands[0], const0_rtx));
3905     for (i = 0; i < XVECLEN (operands[2], 0); i++)
3906       {
3907         rtx set = XVECEXP (operands[2], 0, i);
3908         emit_move_insn (SET_DEST (set), SET_SRC (set));
3909       }
3911     /* The optimizer does not know that the call sets the function value
3912        registers we stored in the result block.  We avoid problems by
3913        claiming that all hard registers are used and clobbered at this
3914        point.  */
3915     emit_insn (gen_blockage ());
3917     DONE;
3918   })
3921 ;; Patterns used for splitting and combining.
3924 ;; Function prologue and epilogue.
3926 (define_expand "prologue"
3927   [(const_int 1)]
3928   ""
3929   { spu_expand_prologue (); DONE; })
3931 ;; "blockage" is only emited in epilogue.  This is what it took to
3932 ;; make "basic block reordering" work with the insns sequence
3933 ;; generated by the spu_expand_epilogue (taken from mips.md)
3935 (define_insn "blockage"
3936   [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
3937   ""
3938   ""
3939   [(set_attr "type" "convert")
3940    (set_attr "length" "0")])
3942 (define_expand "epilogue"
3943   [(const_int 2)]
3944   ""
3945   { spu_expand_epilogue (false); DONE; })
3947 (define_expand "sibcall_epilogue"
3948   [(const_int 2)]
3949   ""
3950   { spu_expand_epilogue (true); DONE; })
3953 ;; stack manipulations
3955 ;; An insn to allocate new stack space for dynamic use (e.g., alloca).
3956 ;; We move the back-chain and decrement the stack pointer.
3957 (define_expand "allocate_stack"
3958   [(set (match_operand 0 "spu_reg_operand" "")
3959         (minus (reg 1) (match_operand 1 "spu_nonmem_operand" "")))
3960    (set (reg 1)
3961         (minus (reg 1) (match_dup 1)))]
3962   ""
3963   "spu_allocate_stack (operands[0], operands[1]); DONE;")
3965 ;; These patterns say how to save and restore the stack pointer.  We need not
3966 ;; save the stack pointer at function level since we are careful to preserve 
3967 ;; the backchain.  
3968 ;; 
3970 ;; At block level the stack pointer is saved and restored, so that the
3971 ;; stack space allocated within a block is deallocated when leaving
3972 ;; block scope.  By default, according to the SPU ABI, the stack
3973 ;; pointer and available stack size are saved in a register. Upon
3974 ;; restoration, the stack pointer is simply copied back, and the
3975 ;; current available stack size is calculated against the restored
3976 ;; stack pointer.
3978 ;; For nonlocal gotos, we must save the stack pointer and its
3979 ;; backchain and restore both.  Note that in the nonlocal case, the
3980 ;; save area is a memory location.
3982 (define_expand "save_stack_function"
3983   [(match_operand 0 "general_operand" "")
3984    (match_operand 1 "general_operand" "")]
3985   ""
3986   "DONE;")
3988 (define_expand "restore_stack_function"
3989   [(match_operand 0 "general_operand" "")
3990    (match_operand 1 "general_operand" "")]
3991   ""
3992   "DONE;")
3994 (define_expand "restore_stack_block"
3995   [(match_operand 0 "spu_reg_operand" "")
3996    (match_operand 1 "memory_operand" "")]
3997   ""
3998   "
3999   {
4000     spu_restore_stack_block (operands[0], operands[1]);
4001     DONE;
4002   }")
4004 (define_expand "save_stack_nonlocal"
4005   [(match_operand 0 "memory_operand" "")
4006    (match_operand 1 "spu_reg_operand" "")]
4007   ""
4008   "
4009   {
4010     rtx temp = gen_reg_rtx (Pmode);
4012     /* Copy the backchain to the first word, sp to the second.  We need to
4013        save the back chain because __builtin_apply appears to clobber it. */
4014     emit_move_insn (temp, gen_rtx_MEM (Pmode, operands[1]));
4015     emit_move_insn (adjust_address_nv (operands[0], SImode, 0), temp);
4016     emit_move_insn (adjust_address_nv (operands[0], SImode, 4), operands[1]);
4017     DONE;
4018   }")
4020 (define_expand "restore_stack_nonlocal"
4021   [(match_operand 0 "spu_reg_operand" "")
4022    (match_operand 1 "memory_operand" "")]
4023   ""
4024   "
4025   {
4026     spu_restore_stack_nonlocal(operands[0], operands[1]);
4027     DONE;
4028   }")
4031 ;; vector patterns
4033 ;; Vector initialization
4034 (define_expand "vec_init<mode>"
4035   [(match_operand:V 0 "register_operand" "")
4036    (match_operand 1 "" "")]
4037   ""
4038   {
4039     spu_expand_vector_init (operands[0], operands[1]);
4040     DONE;
4041   })
4043 (define_expand "vec_set<mode>"
4044   [(use (match_operand:SI 2 "spu_nonmem_operand" ""))
4045    (set (match_dup:TI 3)
4046         (unspec:TI [(match_dup:SI 4)
4047                     (match_dup:SI 5)
4048                     (match_dup:SI 6)] UNSPEC_CPAT))
4049    (set (match_operand:V 0 "spu_reg_operand" "")
4050         (unspec:V [(match_operand:<inner> 1 "spu_reg_operand" "")
4051                    (match_dup:V 0)
4052                    (match_dup:TI 3)] UNSPEC_SHUFB))]
4053   ""
4054   {
4055     HOST_WIDE_INT size = GET_MODE_SIZE (<inner>mode);
4056     rtx offset = GEN_INT (INTVAL (operands[2]) * size);
4057     operands[3] = gen_reg_rtx (TImode);
4058     operands[4] = stack_pointer_rtx;
4059     operands[5] = offset;
4060     operands[6] = GEN_INT (size);
4061   })
4063 (define_expand "vec_extract<mode>"
4064   [(set (match_operand:<inner> 0 "spu_reg_operand" "=r")
4065         (vec_select:<inner> (match_operand:V 1 "spu_reg_operand" "r")
4066                             (parallel [(match_operand 2 "const_int_operand" "i")])))]
4067   ""
4068   {
4069     if ((INTVAL (operands[2]) * <vmult> + <voff>) % 16 == 0)
4070       {
4071         emit_insn (gen_spu_convert (operands[0], operands[1]));
4072         DONE;
4073       }
4074   })
4076 (define_insn "_vec_extract<mode>"
4077   [(set (match_operand:<inner> 0 "spu_reg_operand" "=r")
4078         (vec_select:<inner> (match_operand:V 1 "spu_reg_operand" "r")
4079                             (parallel [(match_operand 2 "const_int_operand" "i")])))]
4080   ""
4081   "rotqbyi\t%0,%1,(%2*<vmult>+<voff>)%%16"
4082   [(set_attr "type" "shuf")])
4084 (define_insn "_vec_extractv8hi_ze"
4085   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
4086         (zero_extend:SI (vec_select:HI (match_operand:V8HI 1 "spu_reg_operand" "r")
4087                                        (parallel [(const_int 0)]))))]
4088   ""
4089   "rotqmbyi\t%0,%1,-2"
4090   [(set_attr "type" "shuf")])
4093 ;; misc
4095 (define_expand "shufb"
4096   [(set (match_operand 0 "spu_reg_operand" "")
4097         (unspec [(match_operand 1 "spu_reg_operand" "")
4098                  (match_operand 2 "spu_reg_operand" "")
4099                  (match_operand:TI 3 "spu_reg_operand" "")] UNSPEC_SHUFB))]
4100   ""
4101   {
4102     rtx s = gen__shufb (operands[0], operands[1], operands[2], operands[3]);
4103     PUT_MODE (SET_SRC (s), GET_MODE (operands[0]));
4104     emit_insn (s);
4105     DONE;
4106   })
4108 (define_insn "_shufb"
4109   [(set (match_operand 0 "spu_reg_operand" "=r")
4110         (unspec [(match_operand 1 "spu_reg_operand" "r")
4111                  (match_operand 2 "spu_reg_operand" "r")
4112                  (match_operand:TI 3 "spu_reg_operand" "r")] UNSPEC_SHUFB))]
4113   "operands"
4114   "shufb\t%0,%1,%2,%3"
4115   [(set_attr "type" "shuf")])
4117 (define_insn "nop"
4118   [(unspec_volatile [(const_int 0)] UNSPEC_NOP)]
4119   ""
4120   "nop"
4121   [(set_attr "type" "nop")])
4123 (define_insn "nopn"
4124   [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "K")] UNSPEC_NOP)]
4125   ""
4126   "nop\t%0"
4127   [(set_attr "type" "nop")])
4129 (define_insn "lnop"
4130   [(unspec_volatile [(const_int 0)] UNSPEC_LNOP)]
4131   ""
4132   "lnop"
4133   [(set_attr "type" "lnop")])
4135 (define_insn "iprefetch"
4136   [(unspec [(const_int 0)] UNSPEC_IPREFETCH)]
4137   ""
4138   "hbrp"
4139   [(set_attr "type" "iprefetch")])
4141 (define_insn "hbr"
4142   [(set (reg:SI 130)
4143         (unspec:SI [(match_operand:SI 0 "immediate_operand" "i,i,i")
4144                     (match_operand:SI 1 "nonmemory_operand" "r,s,i")] UNSPEC_HBR))
4145    (unspec [(const_int 0)] UNSPEC_HBR)]
4146   ""
4147   "@
4148    hbr\t%0,%1
4149    hbrr\t%0,%1
4150    hbra\t%0,%1"
4151   [(set_attr "type" "hbr")])
4153 (define_insn "sync"
4154   [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)
4155    (clobber (mem:BLK (scratch)))]
4156   ""
4157   "sync"
4158   [(set_attr "type" "br")])
4160 (define_insn "syncc"
4161   [(unspec_volatile [(const_int 1)] UNSPEC_SYNC)
4162    (clobber (mem:BLK (scratch)))]
4163   ""
4164   "syncc"
4165   [(set_attr "type" "br")])
4167 (define_insn "dsync"
4168   [(unspec_volatile [(const_int 2)] UNSPEC_SYNC)
4169    (clobber (mem:BLK (scratch)))]
4170   ""
4171   "dsync"
4172   [(set_attr "type" "br")])
4176  ;; Define the subtract-one-and-jump insns so loop.c
4177  ;; knows what to generate.
4178  (define_expand "doloop_end"
4179    [(use (match_operand 0 "" ""))      ; loop pseudo
4180     (use (match_operand 1 "" ""))      ; iterations; zero if unknown
4181     (use (match_operand 2 "" ""))      ; max iterations
4182     (use (match_operand 3 "" ""))      ; loop level
4183     (use (match_operand 4 "" ""))]     ; label
4184    ""
4185    "
4187    /* Currently SMS relies on the do-loop pattern to recognize loops
4188       where (1) the control part comprises of all insns defining and/or
4189       using a certain 'count' register and (2) the loop count can be
4190       adjusted by modifying this register prior to the loop.
4191 .     ??? The possible introduction of a new block to initialize the
4192       new IV can potentially effects branch optimizations.  */
4193    if (optimize > 0 && flag_modulo_sched)
4194    {
4195      rtx s0;
4196      rtx bcomp;
4197      rtx loc_ref;
4199      /* Only use this on innermost loops.  */
4200      if (INTVAL (operands[3]) > 1)
4201        FAIL;
4202      if (GET_MODE (operands[0]) != SImode)
4203        FAIL;
4205      s0 = operands [0];
4206      emit_move_insn (s0, gen_rtx_PLUS (SImode, s0, GEN_INT (-1)));
4207      bcomp = gen_rtx_NE(SImode, s0, const0_rtx);
4208      loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
4209      emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
4210                                   gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
4211                                                         loc_ref, pc_rtx)));
4213      DONE;
4214    }else
4215       FAIL;
4216  }")
4218 ;; convert between any two modes, avoiding any GCC assumptions
4219 (define_expand "spu_convert"
4220   [(set (match_operand 0 "spu_reg_operand" "")
4221         (unspec [(match_operand 1 "spu_reg_operand" "")] UNSPEC_CONVERT))]
4222   ""
4223   {
4224     rtx c = gen__spu_convert (operands[0], operands[1]);
4225     PUT_MODE (SET_SRC (c), GET_MODE (operands[0]));
4226     emit_insn (c);
4227     DONE;
4228   })
4230 (define_insn "_spu_convert"
4231   [(set (match_operand 0 "spu_reg_operand" "=r")
4232         (unspec [(match_operand 1 "spu_reg_operand" "0")] UNSPEC_CONVERT))]
4233   "operands"
4234   ""
4235   [(set_attr "type" "convert")
4236    (set_attr "length" "0")])
4238 (define_peephole2
4239   [(set (match_operand 0 "spu_reg_operand")
4240         (unspec [(match_operand 1 "spu_reg_operand")] UNSPEC_CONVERT))]
4241   ""
4242   [(use (const_int 0))]
4243   "")
4247 (include "spu-builtins.md")
4249   
4250 (define_expand "smaxv4sf3"
4251   [(set (match_operand:V4SF 0 "register_operand" "=r")
4252         (smax:V4SF (match_operand:V4SF 1 "register_operand" "r")
4253                  (match_operand:V4SF 2 "register_operand" "r")))]
4254   ""
4255   "
4257   rtx mask = gen_reg_rtx (V4SImode);
4259   emit_insn (gen_cgt_v4sf (mask, operands[1], operands[2]));
4260   emit_insn (gen_selb (operands[0], operands[2], operands[1], mask));
4261   DONE;
4262 }") 
4264 (define_expand "sminv4sf3"
4265   [(set (match_operand:V4SF 0 "register_operand" "=r")
4266         (smin:V4SF (match_operand:V4SF 1 "register_operand" "r")
4267                  (match_operand:V4SF 2 "register_operand" "r")))]
4268   ""
4269   "
4271   rtx mask = gen_reg_rtx (V4SImode);
4273   emit_insn (gen_cgt_v4sf (mask, operands[1], operands[2]));
4274   emit_insn (gen_selb (operands[0], operands[1], operands[2], mask));
4275   DONE;
4276 }") 
4278 (define_expand "smaxv2df3"
4279   [(set (match_operand:V2DF 0 "register_operand" "=r")
4280         (smax:V2DF (match_operand:V2DF 1 "register_operand" "r")
4281                  (match_operand:V2DF 2 "register_operand" "r")))]
4282   ""
4283   "
4285   rtx mask = gen_reg_rtx (V2DImode);
4286   emit_insn (gen_cgt_v2df (mask, operands[1], operands[2]));
4287   emit_insn (gen_selb (operands[0], operands[2], operands[1], 
4288                        spu_gen_subreg (V4SImode, mask)));
4289   DONE;
4292 (define_expand "sminv2df3"
4293   [(set (match_operand:V2DF 0 "register_operand" "=r")
4294         (smin:V2DF (match_operand:V2DF 1 "register_operand" "r")
4295                  (match_operand:V2DF 2 "register_operand" "r")))]
4296   ""
4297   "
4299   rtx mask = gen_reg_rtx (V2DImode);
4300   emit_insn (gen_cgt_v2df (mask, operands[1], operands[2]));
4301   emit_insn (gen_selb (operands[0], operands[1], operands[2], 
4302                        spu_gen_subreg (V4SImode, mask)));
4303   DONE;
4306 (define_expand "vec_widen_umult_hi_v8hi"
4307   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4308         (mult:V4SI
4309           (zero_extend:V4SI
4310             (vec_select:V4HI
4311               (match_operand:V8HI 1 "register_operand" "r")
4312               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))
4313           (zero_extend:V4SI
4314             (vec_select:V4HI
4315               (match_operand:V8HI 2 "register_operand" "r")
4316               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))))]
4317   ""
4318   "
4320   rtx ve = gen_reg_rtx (V4SImode);
4321   rtx vo = gen_reg_rtx (V4SImode);
4322   rtx mask = gen_reg_rtx (TImode);
4323   unsigned char arr[16] = {
4324     0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 
4325     0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17};
4326   
4327   emit_move_insn (mask, array_to_constant (TImode, arr));
4328   emit_insn (gen_spu_mpyhhu (ve, operands[1], operands[2]));
4329   emit_insn (gen_spu_mpyu (vo, operands[1], operands[2]));
4330   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4331   DONE;
4334 (define_expand "vec_widen_umult_lo_v8hi"
4335   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4336         (mult:V4SI
4337           (zero_extend:V4SI
4338             (vec_select:V4HI
4339               (match_operand:V8HI 1 "register_operand" "r")
4340               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
4341           (zero_extend:V4SI
4342             (vec_select:V4HI
4343               (match_operand:V8HI 2 "register_operand" "r")
4344               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))))]
4345   ""
4346   "
4348   rtx ve = gen_reg_rtx (V4SImode);
4349   rtx vo = gen_reg_rtx (V4SImode);
4350   rtx mask = gen_reg_rtx (TImode);
4351   unsigned char arr[16] = {
4352     0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 
4353     0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F};
4355   emit_move_insn (mask, array_to_constant (TImode, arr));
4356   emit_insn (gen_spu_mpyhhu (ve, operands[1], operands[2]));
4357   emit_insn (gen_spu_mpyu (vo, operands[1], operands[2]));
4358   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4359   DONE;
4362 (define_expand "vec_widen_smult_hi_v8hi"
4363   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4364         (mult:V4SI
4365           (sign_extend:V4SI
4366             (vec_select:V4HI
4367               (match_operand:V8HI 1 "register_operand" "r")
4368               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))
4369           (sign_extend:V4SI
4370             (vec_select:V4HI
4371               (match_operand:V8HI 2 "register_operand" "r")
4372               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))))]
4373   ""
4374   "
4376   rtx ve = gen_reg_rtx (V4SImode);
4377   rtx vo = gen_reg_rtx (V4SImode);
4378   rtx mask = gen_reg_rtx (TImode);
4379   unsigned char arr[16] = {
4380     0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 
4381     0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17};
4382   
4383   emit_move_insn (mask, array_to_constant (TImode, arr));
4384   emit_insn (gen_spu_mpyhh (ve, operands[1], operands[2]));
4385   emit_insn (gen_spu_mpy (vo, operands[1], operands[2]));
4386   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4387   DONE;
4390 (define_expand "vec_widen_smult_lo_v8hi"
4391   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4392         (mult:V4SI
4393           (sign_extend:V4SI
4394             (vec_select:V4HI
4395               (match_operand:V8HI 1 "register_operand" "r")
4396               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
4397           (sign_extend:V4SI
4398             (vec_select:V4HI
4399               (match_operand:V8HI 2 "register_operand" "r")
4400               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))))]
4401   ""
4402   "
4404   rtx ve = gen_reg_rtx (V4SImode);
4405   rtx vo = gen_reg_rtx (V4SImode);
4406   rtx mask = gen_reg_rtx (TImode);
4407   unsigned char arr[16] = {
4408     0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 
4409     0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F};
4411   emit_move_insn (mask, array_to_constant (TImode, arr));
4412   emit_insn (gen_spu_mpyhh (ve, operands[1], operands[2]));
4413   emit_insn (gen_spu_mpy (vo, operands[1], operands[2]));
4414   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4415   DONE;
4418 (define_expand "vec_realign_load_<mode>"
4419   [(set (match_operand:ALL 0 "register_operand" "=r")
4420         (unspec:ALL [(match_operand:ALL 1 "register_operand" "r")
4421                      (match_operand:ALL 2 "register_operand" "r")
4422                      (match_operand:TI 3 "register_operand" "r")] UNSPEC_SPU_REALIGN_LOAD))]
4423   ""
4424   "
4426   emit_insn (gen_shufb (operands[0], operands[1], operands[2], operands[3])); 
4427   DONE;
4430 (define_expand "spu_lvsr"
4431   [(set (match_operand:V16QI 0 "register_operand" "")
4432         (unspec:V16QI [(match_operand 1 "memory_operand" "")] UNSPEC_SPU_MASK_FOR_LOAD))]
4433   ""
4434   "
4436   rtx addr;
4437   rtx offset = gen_reg_rtx (V8HImode);
4438   rtx addr_bits = gen_reg_rtx (SImode);
4439   rtx addr_bits_vec = gen_reg_rtx (V8HImode);
4440   rtx splatqi = gen_reg_rtx (TImode);
4441   rtx result = gen_reg_rtx (V8HImode);
4442   unsigned char arr[16] = {
4443     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
4444     0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
4445   unsigned char arr2[16] = {
4446     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
4447     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
4449   emit_move_insn (offset, array_to_constant (V8HImode, arr));
4450   emit_move_insn (splatqi, array_to_constant (TImode, arr2));
4452   gcc_assert (GET_CODE (operands[1]) == MEM);
4453   addr = force_reg (Pmode, XEXP (operands[1], 0));
4454   emit_insn (gen_andsi3 (addr_bits, addr, GEN_INT (0xF))); 
4455   emit_insn (gen_shufb (addr_bits_vec, addr_bits, addr_bits, splatqi));
4457   /* offset - (addr & 0xF) 
4458      It is safe to use a single sfh, because each byte of offset is > 15 and
4459      each byte of addr is <= 15. */
4460   emit_insn (gen_subv8hi3 (result, offset, addr_bits_vec));
4462   result = simplify_gen_subreg (V16QImode, result, V8HImode, 0);
4463   emit_move_insn (operands[0], result);
4465   DONE;
4468 (define_expand "vec_unpacku_hi_v8hi"
4469   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4470         (zero_extend:V4SI 
4471           (vec_select:V4HI
4472             (match_operand:V8HI 1 "spu_reg_operand" "r")
4473             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
4474   ""
4476   rtx mask = gen_reg_rtx (TImode);
4477   unsigned char arr[16] = {
4478     0x80, 0x80, 0x00, 0x01, 0x80, 0x80, 0x02, 0x03,
4479     0x80, 0x80, 0x04, 0x05, 0x80, 0x80, 0x06, 0x07};
4481   emit_move_insn (mask, array_to_constant (TImode, arr));
4482   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4484   DONE;
4487 (define_expand "vec_unpacku_lo_v8hi"
4488   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4489          (zero_extend:V4SI
4490           (vec_select:V4HI
4491             (match_operand:V8HI 1 "spu_reg_operand" "r")
4492             (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4495   rtx mask = gen_reg_rtx (TImode);
4496   unsigned char arr[16] = {
4497     0x80, 0x80, 0x08, 0x09, 0x80, 0x80, 0x0A, 0x0B,
4498     0x80, 0x80, 0x0C, 0x0D, 0x80, 0x80, 0x0E, 0x0F};
4500   emit_move_insn (mask, array_to_constant (TImode, arr));
4501   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4502   
4503   DONE;
4506 (define_expand "vec_unpacks_hi_v8hi"
4507   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4508          (sign_extend:V4SI
4509           (vec_select:V4HI
4510             (match_operand:V8HI 1 "spu_reg_operand" "r")
4511             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
4512   ""
4514   rtx tmp1 = gen_reg_rtx (V8HImode);
4515   rtx tmp2 = gen_reg_rtx (V4SImode);
4516   rtx mask = gen_reg_rtx (TImode);
4517   unsigned char arr[16] = {
4518     0x80, 0x80, 0x00, 0x01, 0x80, 0x80, 0x02, 0x03,
4519     0x80, 0x80, 0x04, 0x05, 0x80, 0x80, 0x06, 0x07};
4521   emit_move_insn (mask, array_to_constant (TImode, arr));
4522   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4523   emit_insn (gen_spu_xshw (tmp2, tmp1)); 
4524   emit_move_insn (operands[0], tmp2);
4526   DONE;
4529 (define_expand "vec_unpacks_lo_v8hi"
4530   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4531          (sign_extend:V4SI
4532           (vec_select:V4HI
4533             (match_operand:V8HI 1 "spu_reg_operand" "r")
4534             (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4537   rtx tmp1 = gen_reg_rtx (V8HImode);
4538   rtx tmp2 = gen_reg_rtx (V4SImode);
4539   rtx mask = gen_reg_rtx (TImode);
4540   unsigned char arr[16] = {
4541     0x80, 0x80, 0x08, 0x09, 0x80, 0x80, 0x0A, 0x0B,
4542     0x80, 0x80, 0x0C, 0x0D, 0x80, 0x80, 0x0E, 0x0F};
4544   emit_move_insn (mask, array_to_constant (TImode, arr));
4545   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4546   emit_insn (gen_spu_xshw (tmp2, tmp1)); 
4547   emit_move_insn (operands[0], tmp2);
4549 DONE;
4552 (define_expand "vec_unpacku_hi_v16qi"
4553   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4554         (zero_extend:V8HI
4555           (vec_select:V8QI
4556             (match_operand:V16QI 1 "spu_reg_operand" "r")
4557             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
4558                        (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4559   ""
4561   rtx mask = gen_reg_rtx (TImode);
4562   unsigned char arr[16] = {
4563     0x80, 0x00, 0x80, 0x01, 0x80, 0x02, 0x80, 0x03,
4564     0x80, 0x04, 0x80, 0x05, 0x80, 0x06, 0x80, 0x07};
4566   emit_move_insn (mask, array_to_constant (TImode, arr));
4567   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4569   DONE;
4572 (define_expand "vec_unpacku_lo_v16qi"
4573   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4574           (zero_extend:V8HI
4575           (vec_select:V8QI
4576             (match_operand:V16QI 1 "spu_reg_operand" "r")
4577             (parallel [(const_int 8)(const_int 9)(const_int 10)(const_int 11)
4578                        (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
4581   rtx mask = gen_reg_rtx (TImode);
4582   unsigned char arr[16] = {
4583     0x80, 0x08, 0x80, 0x09, 0x80, 0x0A, 0x80, 0x0B,
4584     0x80, 0x0C, 0x80, 0x0D, 0x80, 0x0E, 0x80, 0x0F};
4586   emit_move_insn (mask, array_to_constant (TImode, arr));
4587   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4589   DONE;
4592 (define_expand "vec_unpacks_hi_v16qi"
4593   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4594          (sign_extend:V8HI
4595           (vec_select:V8QI
4596             (match_operand:V16QI 1 "spu_reg_operand" "r")
4597             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
4598                        (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4601   rtx tmp1 = gen_reg_rtx (V16QImode);
4602   rtx tmp2 = gen_reg_rtx (V8HImode);
4603   rtx mask = gen_reg_rtx (TImode);
4604   unsigned char arr[16] = {
4605     0x80, 0x00, 0x80, 0x01, 0x80, 0x02, 0x80, 0x03,
4606     0x80, 0x04, 0x80, 0x05, 0x80, 0x06, 0x80, 0x07};
4608   emit_move_insn (mask, array_to_constant (TImode, arr));
4609   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4610   emit_insn (gen_spu_xsbh (tmp2, tmp1));
4611   emit_move_insn (operands[0], tmp2);
4613   DONE;
4616 (define_expand "vec_unpacks_lo_v16qi"
4617   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4618          (sign_extend:V8HI
4619           (vec_select:V8QI
4620             (match_operand:V16QI 1 "spu_reg_operand" "r")
4621             (parallel [(const_int 8)(const_int 9)(const_int 10)(const_int 11)
4622                        (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
4625   rtx tmp1 = gen_reg_rtx (V16QImode);
4626   rtx tmp2 = gen_reg_rtx (V8HImode);
4627   rtx mask = gen_reg_rtx (TImode);
4628   unsigned char arr[16] = {
4629     0x80, 0x08, 0x80, 0x09, 0x80, 0x0A, 0x80, 0x0B,
4630     0x80, 0x0C, 0x80, 0x0D, 0x80, 0x0E, 0x80, 0x0F};
4632   emit_move_insn (mask, array_to_constant (TImode, arr));
4633   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4634   emit_insn (gen_spu_xsbh (tmp2, tmp1));
4635   emit_move_insn (operands[0], tmp2);
4637 DONE;