Update Copyright years for files modified in 2010.
[official-gcc.git] / gcc / config / spu / spu.md
blob79d0757ed174ddab3579d19528b5b90482664092
1 ;; Copyright (C) 2006, 2007, 2008, 2009, 2010 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_STOP           38)
140  (UNSPEC_STOPD          39)
141  (UNSPEC_SET_INTR       40)
142  (UNSPEC_FSCRRD         42)
143  (UNSPEC_FSCRWR         43)
144  (UNSPEC_MFSPR          44)
145  (UNSPEC_MTSPR          45)
146  (UNSPEC_RDCH           46)
147  (UNSPEC_RCHCNT         47)
148  (UNSPEC_WRCH           48)
149  (UNSPEC_SPU_REALIGN_LOAD 49)
150  (UNSPEC_SPU_MASK_FOR_LOAD 50)
151  (UNSPEC_DFTSV           51)
152  (UNSPEC_FLOAT_EXTEND    52)
153  (UNSPEC_FLOAT_TRUNCATE  53)
154  (UNSPEC_SP_SET         54)
155  (UNSPEC_SP_TEST        55) 
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 QHSI  [QI HI SI])
182 (define_mode_iterator QHSDI  [QI HI SI DI])
183 (define_mode_iterator DTI  [DI TI])
185 (define_mode_iterator VINT [QI V16QI
186                          HI V8HI
187                          SI V4SI
188                          DI V2DI
189                          TI])
191 (define_mode_iterator VQHSI [QI V16QI
192                           HI V8HI
193                           SI V4SI])
195 (define_mode_iterator VHSI [HI V8HI
196                          SI V4SI])
198 (define_mode_iterator VSDF [SF V4SF
199                          DF V2DF])
201 (define_mode_iterator VSI [SI V4SI])
202 (define_mode_iterator VDI [DI V2DI])
203 (define_mode_iterator VSF [SF V4SF])
204 (define_mode_iterator VDF [DF V2DF])
206 (define_mode_iterator VCMP [V16QI
207                          V8HI
208                          V4SI
209                          V4SF
210                          V2DF])
212 (define_mode_iterator VCMPU [V16QI
213                           V8HI
214                           V4SI])
216 (define_mode_attr v      [(V8HI  "v") (V4SI  "v")
217                           (HI    "") (SI    "")])
219 (define_mode_attr bh  [(QI "b")  (V16QI "b")
220                        (HI "h")  (V8HI "h")
221                        (SI "")   (V4SI "")])
223 (define_mode_attr d   [(SF "")   (V4SF "")
224                        (DF "d")  (V2DF "d")])
225 (define_mode_attr d6  [(SF "6")  (V4SF "6")
226                        (DF "d")  (V2DF "d")])
228 (define_mode_attr f2i [(SF "si") (V4SF "v4si")
229                        (DF "di") (V2DF "v2di")])
230 (define_mode_attr F2I [(SF "SI") (V4SF "V4SI")
231                        (DF "DI") (V2DF "V2DI")])
232 (define_mode_attr i2f [(SI "sf") (V4SI "v4sf")
233                        (DI "df") (V2DI "v2df")])
234 (define_mode_attr I2F [(SI "SF") (V4SI "V4SF")
235                        (DI "DF") (V2DI "V2DF")])
237 (define_mode_attr DF2I [(DF "SI") (V2DF "V2DI")])
239 (define_mode_attr umask  [(HI "f")  (V8HI "f")
240                           (SI "g")  (V4SI "g")])
241 (define_mode_attr nmask  [(HI "F")  (V8HI "F")
242                           (SI "G")  (V4SI "G")])
244 ;; Used for carry and borrow instructions.
245 (define_mode_iterator CBOP  [SI DI V4SI V2DI])
247 ;; Used in vec_set and vec_extract
248 (define_mode_iterator V [V2DI V4SI V8HI V16QI V2DF V4SF])
249 (define_mode_attr inner  [(V16QI "QI")
250                           (V8HI  "HI")
251                           (V4SI  "SI")
252                           (V2DI  "DI")
253                           (V4SF  "SF")
254                           (V2DF  "DF")])
255 (define_mode_attr vmult  [(V16QI "1")
256                           (V8HI  "2")
257                           (V4SI  "4")
258                           (V2DI  "8")
259                           (V4SF  "4")
260                           (V2DF  "8")])
261 (define_mode_attr voff   [(V16QI "13")
262                           (V8HI  "14")
263                           (V4SI  "0")
264                           (V2DI  "0")
265                           (V4SF  "0")
266                           (V2DF  "0")])
269 ;; mov
271 (define_expand "mov<mode>"
272   [(set (match_operand:ALL 0 "nonimmediate_operand" "")
273         (match_operand:ALL 1 "general_operand" ""))]
274   ""
275   {
276     if (spu_expand_mov(operands, <MODE>mode))
277       DONE;
278   })
280 (define_split 
281   [(set (match_operand 0 "spu_reg_operand")
282         (match_operand 1 "immediate_operand"))]
284   ""
285   [(set (match_dup 0)
286         (high (match_dup 1)))
287    (set (match_dup 0)
288         (lo_sum (match_dup 0)
289                 (match_dup 1)))]
290   {
291     if (spu_split_immediate (operands))
292       DONE;
293     FAIL;
294   })
296 (define_insn "pic"
297   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
298         (match_operand:SI 1 "immediate_operand" "s"))
299    (use (const_int 0))]
300   "flag_pic"
301   "ila\t%0,%%pic(%1)")
303 ;; Whenever a function generates the 'pic' pattern above we need to
304 ;; load the pic_offset_table register.
305 ;; GCC doesn't deal well with labels in the middle of a block so we
306 ;; hardcode the offsets in the asm here.
307 (define_insn "load_pic_offset"
308   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
309         (unspec:SI [(const_int 0)] 0))
310    (set (match_operand:SI 1 "spu_reg_operand" "=r")
311         (unspec:SI [(const_int 0)] 0))]
312   "flag_pic"
313   "ila\t%1,.+8\;brsl\t%0,4"
314   [(set_attr "length" "8")
315    (set_attr "type" "multi0")])
318 ;; move internal
320 (define_insn "_mov<mode>"
321   [(set (match_operand:MOV 0 "spu_dest_operand" "=r,r,r,r,r,m")
322         (match_operand:MOV 1 "spu_mov_operand" "r,A,f,j,m,r"))]
323   "register_operand(operands[0], <MODE>mode)
324    || register_operand(operands[1], <MODE>mode)"
325   "@
326    ori\t%0,%1,0
327    il%s1\t%0,%S1
328    fsmbi\t%0,%S1
329    c%s1d\t%0,%S1($sp)
330    lq%p1\t%0,%1
331    stq%p0\t%1,%0"
332   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
334 (define_insn "low_<mode>"
335   [(set (match_operand:VSI 0 "spu_reg_operand" "=r")
336         (lo_sum:VSI (match_operand:VSI 1 "spu_reg_operand" "0")
337                     (match_operand:VSI 2 "immediate_operand" "i")))]
338   ""
339   "iohl\t%0,%2@l")
341 (define_insn "_movdi"
342   [(set (match_operand:DI 0 "spu_dest_operand" "=r,r,r,r,r,m")
343         (match_operand:DI 1 "spu_mov_operand" "r,a,f,k,m,r"))]
344   "register_operand(operands[0], DImode)
345    || register_operand(operands[1], DImode)"
346   "@
347    ori\t%0,%1,0
348    il%d1\t%0,%D1
349    fsmbi\t%0,%D1
350    c%d1d\t%0,%D1($sp)
351    lq%p1\t%0,%1
352    stq%p0\t%1,%0"
353   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
355 (define_insn "_movti"
356   [(set (match_operand:TI 0 "spu_dest_operand" "=r,r,r,r,r,m")
357         (match_operand:TI 1 "spu_mov_operand" "r,U,f,l,m,r"))]
358   "register_operand(operands[0], TImode)
359    || register_operand(operands[1], TImode)"
360   "@
361    ori\t%0,%1,0
362    il%t1\t%0,%T1
363    fsmbi\t%0,%T1
364    c%t1d\t%0,%T1($sp)
365    lq%p1\t%0,%1
366    stq%p0\t%1,%0"
367   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
369 (define_split
370   [(set (match_operand 0 "spu_reg_operand")
371         (match_operand 1 "memory_operand"))]
372   "GET_MODE_SIZE (GET_MODE (operands[0])) < 16
373    && GET_MODE(operands[0]) == GET_MODE(operands[1])
374    && !reload_in_progress && !reload_completed" 
375   [(set (match_dup 0)
376         (match_dup 1))]
377   { if (spu_split_load(operands))
378       DONE;
379   })
381 (define_split
382   [(set (match_operand 0 "memory_operand")
383         (match_operand 1 "spu_reg_operand"))]
384   "GET_MODE_SIZE (GET_MODE (operands[0])) < 16
385    && GET_MODE(operands[0]) == GET_MODE(operands[1])
386    && !reload_in_progress && !reload_completed" 
387   [(set (match_dup 0)
388         (match_dup 1))]
389   { if (spu_split_store(operands))
390       DONE;
391   })
392 ;; Operand 3 is the number of bytes. 1:b 2:h 4:w 8:d
394 (define_expand "cpat"
395   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
396         (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "r,r")
397                     (match_operand:SI 2 "spu_nonmem_operand" "r,n")
398                     (match_operand:SI 3 "immediate_operand" "i,i")] UNSPEC_CPAT))]
399   ""
400   {
401     rtx x = gen_cpat_const (operands);
402     if (x)
403       {
404         emit_move_insn (operands[0], x);
405         DONE;
406       }
407   })
409 (define_insn "_cpat"
410   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
411         (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "r,r")
412                     (match_operand:SI 2 "spu_nonmem_operand" "r,n")
413                     (match_operand:SI 3 "immediate_operand" "i,i")] UNSPEC_CPAT))]
414   ""
415   "@
416    c%M3x\t%0,%1,%2
417    c%M3d\t%0,%C2(%1)"
418   [(set_attr "type" "shuf")])
420 (define_split
421   [(set (match_operand:TI 0 "spu_reg_operand")
422         (unspec:TI [(match_operand:SI 1 "spu_nonmem_operand")
423                     (match_operand:SI 2 "immediate_operand")
424                     (match_operand:SI 3 "immediate_operand")] UNSPEC_CPAT))]
425   ""
426   [(set (match_dup:TI 0)
427         (match_dup:TI 4))]
428   {
429     operands[4] = gen_cpat_const (operands);
430     if (!operands[4])
431       FAIL;
432   })
434 ;; extend
436 (define_insn "extendqihi2"
437   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
438         (sign_extend:HI (match_operand:QI 1 "spu_reg_operand" "r")))]
439   ""
440   "xsbh\t%0,%1")
442 (define_insn "extendhisi2"
443   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
444         (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r")))]
445   ""
446   "xshw\t%0,%1")
448 (define_expand "extendsidi2"
449   [(set (match_dup:DI 2)
450         (zero_extend:DI (match_operand:SI 1 "spu_reg_operand" "")))
451    (set (match_operand:DI 0 "spu_reg_operand" "")
452         (sign_extend:DI (vec_select:SI (match_dup:V2SI 3)
453                                        (parallel [(const_int 1)]))))]
454   ""
455   {
456     operands[2] = gen_reg_rtx (DImode);
457     operands[3] = spu_gen_subreg (V2SImode, operands[2]);
458   })
460 (define_insn "xswd"
461   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
462         (sign_extend:DI
463           (vec_select:SI
464             (match_operand:V2SI 1 "spu_reg_operand" "r")
465             (parallel [(const_int 1) ]))))]
466   ""
467   "xswd\t%0,%1");
469 ;; By splitting this late we don't allow much opportunity for sharing of
470 ;; constants.  That's ok because this should really be optimized away.
471 (define_insn_and_split "extend<mode>ti2"
472   [(set (match_operand:TI 0 "register_operand" "")
473         (sign_extend:TI (match_operand:QHSDI 1 "register_operand" "")))]
474   ""
475   "#"
476   ""
477   [(set (match_dup:TI 0)
478         (sign_extend:TI (match_dup:QHSDI 1)))]
479   {
480     spu_expand_sign_extend(operands);
481     DONE;
482   })
485 ;; zero_extend
487 (define_insn "zero_extendqihi2"
488   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
489         (zero_extend:HI (match_operand:QI 1 "spu_reg_operand" "r")))]
490   ""
491   "andi\t%0,%1,0x00ff")
493 (define_insn "zero_extendqisi2"
494   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
495         (zero_extend:SI (match_operand:QI 1 "spu_reg_operand" "r")))]
496   ""
497   "andi\t%0,%1,0x00ff")
499 (define_expand "zero_extendhisi2"
500   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
501         (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r")))
502    (clobber (match_scratch:SI 2 "=&r"))]
503   ""
504   {
505     rtx mask = gen_reg_rtx (SImode);
506     rtx op1 = simplify_gen_subreg (SImode, operands[1], HImode, 0);
507     emit_move_insn (mask, GEN_INT (0xffff));
508     emit_insn (gen_andsi3(operands[0], op1, mask));
509     DONE;
510   })
511   
512 (define_insn "zero_extendsidi2"
513   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
514         (zero_extend:DI (match_operand:SI 1 "spu_reg_operand" "r")))]
515   ""
516   "rotqmbyi\t%0,%1,-4"
517   [(set_attr "type" "shuf")])
519 (define_insn "zero_extendqiti2"
520   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
521         (zero_extend:TI (match_operand:QI 1 "spu_reg_operand" "r")))]
522   ""
523   "andi\t%0,%1,0x00ff\;rotqmbyi\t%0,%0,-12"
524   [(set_attr "type" "multi0")
525    (set_attr "length" "8")])
527 (define_insn "zero_extendhiti2"
528   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
529         (zero_extend:TI (match_operand:HI 1 "spu_reg_operand" "r")))]
530   ""
531   "shli\t%0,%1,16\;rotqmbyi\t%0,%0,-14"
532   [(set_attr "type" "multi1")
533    (set_attr "length" "8")])
535 (define_insn "zero_extendsiti2"
536   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
537         (zero_extend:TI (match_operand:SI 1 "spu_reg_operand" "r")))]
538   ""
539   "rotqmbyi\t%0,%1,-12"
540   [(set_attr "type" "shuf")])
542 (define_insn "zero_extendditi2"
543   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
544         (zero_extend:TI (match_operand:DI 1 "spu_reg_operand" "r")))]
545   ""
546   "rotqmbyi\t%0,%1,-8"
547   [(set_attr "type" "shuf")])
550 ;; trunc
552 (define_insn "truncdiqi2"
553   [(set (match_operand:QI 0 "spu_reg_operand" "=r")
554         (truncate:QI (match_operand:DI 1 "spu_reg_operand" "r")))]
555   ""
556   "shlqbyi\t%0,%1,4"
557   [(set_attr "type" "shuf")])
559 (define_insn "truncdihi2"
560   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
561         (truncate:HI (match_operand:DI 1 "spu_reg_operand" "r")))]
562   ""
563   "shlqbyi\t%0,%1,4"
564   [(set_attr "type" "shuf")])
566 (define_insn "truncdisi2"
567   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
568         (truncate:SI (match_operand:DI 1 "spu_reg_operand" "r")))]
569   ""
570   "shlqbyi\t%0,%1,4"
571   [(set_attr "type" "shuf")])
573 (define_insn "trunctiqi2"
574   [(set (match_operand:QI 0 "spu_reg_operand" "=r")
575         (truncate:QI (match_operand:TI 1 "spu_reg_operand" "r")))]
576   ""
577   "shlqbyi\t%0,%1,12"
578   [(set_attr "type" "shuf")])
580 (define_insn "trunctihi2"
581   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
582         (truncate:HI (match_operand:TI 1 "spu_reg_operand" "r")))]
583   ""
584   "shlqbyi\t%0,%1,12"
585   [(set_attr "type" "shuf")])
587 (define_insn "trunctisi2"
588   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
589         (truncate:SI (match_operand:TI 1 "spu_reg_operand" "r")))]
590   ""
591   "shlqbyi\t%0,%1,12"
592   [(set_attr "type" "shuf")])
594 (define_insn "trunctidi2"
595   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
596         (truncate:DI (match_operand:TI 1 "spu_reg_operand" "r")))]
597   ""
598   "shlqbyi\t%0,%1,8"
599   [(set_attr "type" "shuf")])
602 ;; float conversions
604 (define_insn "float<mode><i2f>2"
605   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
606         (float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r")))]
607   ""
608   "csflt\t%0,%1,0"
609   [(set_attr "type" "fp7")])
611 (define_insn "fix_trunc<mode><f2i>2"
612   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
613         (fix:<F2I> (match_operand:VSF 1 "spu_reg_operand" "r")))]
614   ""
615   "cflts\t%0,%1,0"
616   [(set_attr "type" "fp7")])
618 (define_insn "floatuns<mode><i2f>2"
619   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
620         (unsigned_float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r")))]
621   ""
622   "cuflt\t%0,%1,0"
623   [(set_attr "type" "fp7")])
625 (define_insn "fixuns_trunc<mode><f2i>2"
626   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
627         (unsigned_fix:<F2I> (match_operand:VSF 1 "spu_reg_operand" "r")))]
628   ""
629   "cfltu\t%0,%1,0"
630   [(set_attr "type" "fp7")])
632 (define_insn "float<mode><i2f>2_mul"
633   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
634         (mult:<I2F> (float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r"))
635                     (match_operand:<I2F> 2 "spu_inv_exp2_operand" "w")))]
636   ""
637   "csflt\t%0,%1,%w2"
638   [(set_attr "type" "fp7")])
640 (define_insn "float<mode><i2f>2_div"
641   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
642         (div:<I2F> (float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r"))
643                    (match_operand:<I2F> 2 "spu_exp2_operand" "v")))]
644   ""
645   "csflt\t%0,%1,%v2"
646   [(set_attr "type" "fp7")])
649 (define_insn "fix_trunc<mode><f2i>2_mul"
650   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
651         (fix:<F2I> (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
652                              (match_operand:VSF 2 "spu_exp2_operand" "v"))))]
653   ""
654   "cflts\t%0,%1,%v2"
655   [(set_attr "type" "fp7")])
657 (define_insn "floatuns<mode><i2f>2_mul"
658   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
659         (mult:<I2F> (unsigned_float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r"))
660                     (match_operand:<I2F> 2 "spu_inv_exp2_operand" "w")))]
661   ""
662   "cuflt\t%0,%1,%w2"
663   [(set_attr "type" "fp7")])
665 (define_insn "floatuns<mode><i2f>2_div"
666   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
667         (div:<I2F> (unsigned_float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r"))
668                    (match_operand:<I2F> 2 "spu_exp2_operand" "v")))]
669   ""
670   "cuflt\t%0,%1,%v2"
671   [(set_attr "type" "fp7")])
673 (define_insn "fixuns_trunc<mode><f2i>2_mul"
674   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
675         (unsigned_fix:<F2I> (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
676                                       (match_operand:VSF 2 "spu_exp2_operand" "v"))))]
677   ""
678   "cfltu\t%0,%1,%v2"
679   [(set_attr "type" "fp7")])
681 (define_insn "extendsfdf2"
682   [(set (match_operand:DF 0 "spu_reg_operand" "=r")
683         (unspec:DF [(match_operand:SF 1 "spu_reg_operand" "r")]
684                    UNSPEC_FLOAT_EXTEND))]
685   ""
686   "fesd\t%0,%1"
687   [(set_attr "type" "fpd")])
689 (define_insn "truncdfsf2"
690   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
691         (unspec:SF [(match_operand:DF 1 "spu_reg_operand" "r")]
692                    UNSPEC_FLOAT_TRUNCATE))]
693   ""
694   "frds\t%0,%1"
695   [(set_attr "type" "fpd")])
697 (define_expand "floatdisf2"
698   [(set (match_operand:SF 0 "register_operand" "")
699         (float:SF (match_operand:DI 1 "register_operand" "")))]
700   ""
701   {
702     rtx c0 = gen_reg_rtx (SImode);
703     rtx r0 = gen_reg_rtx (DImode);
704     rtx r1 = gen_reg_rtx (SFmode);
705     rtx r2 = gen_reg_rtx (SImode);
706     rtx setneg = gen_reg_rtx (SImode);
707     rtx isneg = gen_reg_rtx (SImode);
708     rtx neg = gen_reg_rtx (DImode);
709     rtx mask = gen_reg_rtx (DImode);
711     emit_move_insn (c0, GEN_INT (-0x80000000ll));
713     emit_insn (gen_negdi2 (neg, operands[1]));
714     emit_insn (gen_cgt_di_m1 (isneg, operands[1]));
715     emit_insn (gen_extend_compare (mask, isneg));
716     emit_insn (gen_selb (r0, neg, operands[1], mask));
717     emit_insn (gen_andc_si (setneg, c0, isneg));
719     emit_insn (gen_floatunsdisf2 (r1, r0));
721     emit_insn (gen_iorsi3 (r2, gen_rtx_SUBREG (SImode, r1, 0), setneg));
722     emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, r2, 0));
723     DONE;
724   })
726 (define_insn_and_split "floatunsdisf2"
727   [(set (match_operand:SF 0 "register_operand" "=r")
728         (unsigned_float:SF (match_operand:DI 1 "register_operand" "r")))
729    (clobber (match_scratch:SF 2 "=r"))
730    (clobber (match_scratch:SF 3 "=r"))
731    (clobber (match_scratch:SF 4 "=r"))]
732   ""
733   "#"
734   "reload_completed"
735   [(set (match_dup:SF 0)
736         (unsigned_float:SF (match_dup:DI 1)))]
737   {
738     rtx op1_v4si = gen_rtx_REG (V4SImode, REGNO (operands[1]));
739     rtx op2_v4sf = gen_rtx_REG (V4SFmode, REGNO (operands[2]));
740     rtx op2_ti = gen_rtx_REG (TImode, REGNO (operands[2]));
741     rtx op3_ti = gen_rtx_REG (TImode, REGNO (operands[3]));
743     REAL_VALUE_TYPE scale;
744     real_2expN (&scale, 32, SFmode);
746     emit_insn (gen_floatunsv4siv4sf2 (op2_v4sf, op1_v4si));
747     emit_insn (gen_shlqby_ti (op3_ti, op2_ti, GEN_INT (4)));
749     emit_move_insn (operands[4],
750                     CONST_DOUBLE_FROM_REAL_VALUE (scale, SFmode));
751     emit_insn (gen_fmasf4 (operands[0],
752                            operands[2], operands[4], operands[3]));
753     DONE;
754   })
756 (define_expand "floattisf2"
757   [(set (match_operand:SF 0 "register_operand" "")
758         (float:SF (match_operand:TI 1 "register_operand" "")))]
759   ""
760   {
761     rtx c0 = gen_reg_rtx (SImode);
762     rtx r0 = gen_reg_rtx (TImode);
763     rtx r1 = gen_reg_rtx (SFmode);
764     rtx r2 = gen_reg_rtx (SImode);
765     rtx setneg = gen_reg_rtx (SImode);
766     rtx isneg = gen_reg_rtx (SImode);
767     rtx neg = gen_reg_rtx (TImode);
768     rtx mask = gen_reg_rtx (TImode);
770     emit_move_insn (c0, GEN_INT (-0x80000000ll));
772     emit_insn (gen_negti2 (neg, operands[1]));
773     emit_insn (gen_cgt_ti_m1 (isneg, operands[1]));
774     emit_insn (gen_extend_compare (mask, isneg));
775     emit_insn (gen_selb (r0, neg, operands[1], mask));
776     emit_insn (gen_andc_si (setneg, c0, isneg));
778     emit_insn (gen_floatunstisf2 (r1, r0));
780     emit_insn (gen_iorsi3 (r2, gen_rtx_SUBREG (SImode, r1, 0), setneg));
781     emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, r2, 0));
782     DONE;
783   })
785 (define_insn_and_split "floatunstisf2"
786   [(set (match_operand:SF 0 "register_operand" "=r")
787         (unsigned_float:SF (match_operand:TI 1 "register_operand" "r")))
788    (clobber (match_scratch:SF 2 "=r"))
789    (clobber (match_scratch:SF 3 "=r"))
790    (clobber (match_scratch:SF 4 "=r"))]
791   ""
792   "#"
793   "reload_completed"
794   [(set (match_dup:SF 0)
795         (unsigned_float:SF (match_dup:TI 1)))]
796   {
797     rtx op1_v4si = gen_rtx_REG (V4SImode, REGNO (operands[1]));
798     rtx op2_v4sf = gen_rtx_REG (V4SFmode, REGNO (operands[2]));
799     rtx op2_ti = gen_rtx_REG (TImode, REGNO (operands[2]));
800     rtx op3_ti = gen_rtx_REG (TImode, REGNO (operands[3]));
802     REAL_VALUE_TYPE scale;
803     real_2expN (&scale, 32, SFmode);
805     emit_insn (gen_floatunsv4siv4sf2 (op2_v4sf, op1_v4si));
806     emit_insn (gen_shlqby_ti (op3_ti, op2_ti, GEN_INT (4)));
808     emit_move_insn (operands[4],
809                     CONST_DOUBLE_FROM_REAL_VALUE (scale, SFmode));
810     emit_insn (gen_fmasf4 (operands[2],
811                            operands[2], operands[4], operands[3]));
813     emit_insn (gen_shlqby_ti (op3_ti, op3_ti, GEN_INT (4)));
814     emit_insn (gen_fmasf4 (operands[2],
815                            operands[2], operands[4], operands[3]));
817     emit_insn (gen_shlqby_ti (op3_ti, op3_ti, GEN_INT (4)));
818     emit_insn (gen_fmasf4 (operands[0],
819                            operands[2], operands[4], operands[3]));
820     DONE;
821   })
823 ;; Do (double)(operands[1]+0x80000000u)-(double)0x80000000
824 (define_expand "floatsidf2"
825   [(set (match_operand:DF 0 "register_operand" "")
826         (float:DF (match_operand:SI 1 "register_operand" "")))]
827   ""
828   {
829     rtx c0 = gen_reg_rtx (SImode);
830     rtx c1 = gen_reg_rtx (DFmode);
831     rtx r0 = gen_reg_rtx (SImode);
832     rtx r1 = gen_reg_rtx (DFmode);
834     emit_move_insn (c0, GEN_INT (-0x80000000ll));
835     emit_move_insn (c1, spu_float_const ("2147483648", DFmode));
836     emit_insn (gen_xorsi3 (r0, operands[1], c0));
837     emit_insn (gen_floatunssidf2 (r1, r0));
838     emit_insn (gen_subdf3 (operands[0], r1, c1));
839     DONE;
840   })
842 (define_expand "floatunssidf2"
843   [(set (match_operand:DF 0 "register_operand"  "=r")
844         (unsigned_float:DF (match_operand:SI 1 "register_operand"   "r")))]
845   ""
846   "{
847     rtx value, insns;
848     rtx c0 = spu_const_from_ints (V16QImode, 0x02031011, 0x12138080, 
849                                              0x06071415, 0x16178080);
850     rtx r0 = gen_reg_rtx (V16QImode);
852     if (optimize_size)
853     {
854        start_sequence ();
855        value =
856          emit_library_call_value (convert_optab_libfunc (ufloat_optab,
857                                                          DFmode, SImode),
858                    NULL_RTX, LCT_NORMAL, DFmode, 1, operands[1], SImode);
859        insns = get_insns ();
860        end_sequence ();
861        emit_libcall_block (insns, operands[0], value,
862                            gen_rtx_UNSIGNED_FLOAT (DFmode, operands[1]));
863      }
864      else
865      {
866       emit_move_insn (r0, c0);
867       emit_insn (gen_floatunssidf2_internal (operands[0], operands[1], r0));
868      }
869     DONE;
870   }")
872 (define_insn_and_split "floatunssidf2_internal"
873   [(set (match_operand:DF 0 "register_operand"  "=r")
874         (unsigned_float:DF (match_operand:SI 1 "register_operand"   "r")))
875    (use (match_operand:V16QI 2 "register_operand" "r"))
876    (clobber (match_scratch:V4SI 3 "=&r"))
877    (clobber (match_scratch:V4SI 4 "=&r"))
878    (clobber (match_scratch:V4SI 5 "=&r"))
879    (clobber (match_scratch:V4SI 6 "=&r"))]
880   ""
881   "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"
882   "reload_completed"
883   [(set (match_dup:DF 0)
884         (unsigned_float:DF (match_dup:SI 1)))]
885  "{
886     rtx *ops = operands;
887     rtx op1_v4si = gen_rtx_REG(V4SImode, REGNO(ops[1]));
888     rtx op0_ti = gen_rtx_REG (TImode, REGNO (ops[0]));
889     rtx op2_ti = gen_rtx_REG (TImode, REGNO (ops[2]));
890     rtx op6_ti = gen_rtx_REG (TImode, REGNO (ops[6]));
891     emit_insn (gen_clzv4si2 (ops[3],op1_v4si));
892     emit_move_insn (ops[6], spu_const (V4SImode, 1023+31));
893     emit_insn (gen_vashlv4si3 (ops[4],op1_v4si,ops[3]));
894     emit_insn (gen_ceq_v4si (ops[5],ops[3],spu_const (V4SImode, 32)));
895     emit_insn (gen_subv4si3 (ops[6],ops[6],ops[3]));
896     emit_insn (gen_addv4si3 (ops[4],ops[4],ops[4]));
897     emit_insn (gen_andc_v4si  (ops[6],ops[6],ops[5]));
898     emit_insn (gen_shufb (ops[6],ops[6],ops[4],op2_ti));
899     emit_insn (gen_shlqbi_ti (op0_ti,op6_ti,GEN_INT(4)));
900     DONE;
901   }"
902  [(set_attr "length" "32")])
904 (define_expand "floatdidf2"
905   [(set (match_operand:DF 0 "register_operand" "")
906         (float:DF (match_operand:DI 1 "register_operand" "")))]
907   ""
908   {
909     rtx c0 = gen_reg_rtx (DImode);
910     rtx r0 = gen_reg_rtx (DImode);
911     rtx r1 = gen_reg_rtx (DFmode);
912     rtx r2 = gen_reg_rtx (DImode);
913     rtx setneg = gen_reg_rtx (DImode);
914     rtx isneg = gen_reg_rtx (SImode);
915     rtx neg = gen_reg_rtx (DImode);
916     rtx mask = gen_reg_rtx (DImode);
918     emit_move_insn (c0, GEN_INT (0x8000000000000000ull));
920     emit_insn (gen_negdi2 (neg, operands[1]));
921     emit_insn (gen_cgt_di_m1 (isneg, operands[1]));
922     emit_insn (gen_extend_compare (mask, isneg));
923     emit_insn (gen_selb (r0, neg, operands[1], mask));
924     emit_insn (gen_andc_di (setneg, c0, mask));
926     emit_insn (gen_floatunsdidf2 (r1, r0));
928     emit_insn (gen_iordi3 (r2, gen_rtx_SUBREG (DImode, r1, 0), setneg));
929     emit_move_insn (operands[0], gen_rtx_SUBREG (DFmode, r2, 0));
930     DONE;
931   })
933 (define_expand "floatunsdidf2"
934   [(set (match_operand:DF 0 "register_operand"  "=r")
935         (unsigned_float:DF (match_operand:DI 1 "register_operand"   "r")))]
936   ""
937   "{
938     rtx value, insns;
939     rtx c0 = spu_const_from_ints (V16QImode, 0x02031011, 0x12138080, 
940                                              0x06071415, 0x16178080);
941     rtx c1 = spu_const_from_ints (V4SImode, 1023+63, 1023+31, 0, 0);
942     rtx r0 = gen_reg_rtx (V16QImode);
943     rtx r1 = gen_reg_rtx (V4SImode);
945     if (optimize_size)
946     {      
947       start_sequence ();
948       value =
949          emit_library_call_value (convert_optab_libfunc (ufloat_optab,
950                                                          DFmode, DImode),
951                    NULL_RTX, LCT_NORMAL, DFmode, 1, operands[1], DImode);
952       insns = get_insns ();
953       end_sequence ();
954       emit_libcall_block (insns, operands[0], value,
955                           gen_rtx_UNSIGNED_FLOAT (DFmode, operands[1]));
956     }
957     else
958     {
959       emit_move_insn (r1, c1);
960       emit_move_insn (r0, c0);
961       emit_insn (gen_floatunsdidf2_internal (operands[0], operands[1], r0, r1));
962     }
963     DONE;
964   }")
966 (define_insn_and_split "floatunsdidf2_internal"
967   [(set (match_operand:DF 0 "register_operand"  "=r")
968         (unsigned_float:DF (match_operand:DI 1 "register_operand"   "r")))
969    (use (match_operand:V16QI 2 "register_operand" "r"))
970    (use (match_operand:V4SI 3 "register_operand" "r"))
971    (clobber (match_scratch:V4SI 4 "=&r"))
972    (clobber (match_scratch:V4SI 5 "=&r"))
973    (clobber (match_scratch:V4SI 6 "=&r"))]
974   ""
975   "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"
976   "reload_completed"
977   [(set (match_operand:DF 0 "register_operand"  "=r")
978         (unsigned_float:DF (match_operand:DI 1 "register_operand"   "r")))]
979   "{
980     rtx *ops = operands;
981     rtx op1_v4si = gen_rtx_REG (V4SImode, REGNO(ops[1]));
982     rtx op2_ti = gen_rtx_REG (TImode, REGNO(ops[2]));
983     rtx op4_ti = gen_rtx_REG (TImode, REGNO(ops[4]));
984     rtx op5_ti = gen_rtx_REG (TImode, REGNO(ops[5]));
985     rtx op4_df = gen_rtx_REG (DFmode, REGNO(ops[4]));
986     rtx op5_df = gen_rtx_REG (DFmode, REGNO(ops[5]));
987     emit_insn (gen_clzv4si2 (ops[4],op1_v4si));
988     emit_insn (gen_vashlv4si3 (ops[5],op1_v4si,ops[4]));
989     emit_insn (gen_ceq_v4si (ops[6],ops[4],spu_const (V4SImode, 32)));
990     emit_insn (gen_subv4si3 (ops[4],ops[3],ops[4]));
991     emit_insn (gen_addv4si3 (ops[5],ops[5],ops[5]));
992     emit_insn (gen_andc_v4si (ops[4],ops[4],ops[6]));
993     emit_insn (gen_shufb (ops[4],ops[4],ops[5],op2_ti));
994     emit_insn (gen_shlqbi_ti (op4_ti,op4_ti,GEN_INT(4)));
995     emit_insn (gen_shlqby_ti (op5_ti,op4_ti,GEN_INT(8)));
996     emit_insn (gen_adddf3 (ops[0],op4_df,op5_df));
997     DONE;
998   }"
999   [(set_attr "length" "40")])
1002 ;; add
1004 (define_expand "addv16qi3"
1005   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
1006         (plus:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")
1007                     (match_operand:V16QI 2 "spu_reg_operand" "r")))]
1008   ""
1009   "{
1010     rtx res_short = simplify_gen_subreg (V8HImode, operands[0], V16QImode, 0);
1011     rtx lhs_short = simplify_gen_subreg (V8HImode, operands[1], V16QImode, 0);
1012     rtx rhs_short = simplify_gen_subreg (V8HImode, operands[2], V16QImode, 0);
1013     rtx rhs_and = gen_reg_rtx (V8HImode);
1014     rtx hi_char = gen_reg_rtx (V8HImode);
1015     rtx lo_char = gen_reg_rtx (V8HImode);
1016     rtx mask = gen_reg_rtx (V8HImode);
1018     emit_move_insn (mask, spu_const (V8HImode, 0x00ff));
1019     emit_insn (gen_andv8hi3 (rhs_and, rhs_short, spu_const (V8HImode, 0xff00)));
1020     emit_insn (gen_addv8hi3 (hi_char, lhs_short, rhs_and));
1021     emit_insn (gen_addv8hi3 (lo_char, lhs_short, rhs_short));
1022     emit_insn (gen_selb (res_short, hi_char, lo_char, mask));
1023     DONE;
1024    }")
1026 (define_insn "add<mode>3"
1027   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
1028         (plus:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
1029                    (match_operand:VHSI 2 "spu_arith_operand" "r,B")))]
1030   ""
1031   "@
1032   a<bh>\t%0,%1,%2
1033   a<bh>i\t%0,%1,%2")
1035 (define_expand "add<mode>3"
1036   [(set (match_dup:VDI 3) 
1037         (unspec:VDI [(match_operand:VDI 1 "spu_reg_operand" "")
1038                      (match_operand:VDI 2 "spu_reg_operand" "")] UNSPEC_CG))
1039    (set (match_dup:VDI 5)
1040         (unspec:VDI [(match_dup 3)
1041                      (match_dup 3)
1042                      (match_dup:TI 4)] UNSPEC_SHUFB))
1043    (set (match_operand:VDI 0 "spu_reg_operand" "") 
1044         (unspec:VDI [(match_dup 1)
1045                      (match_dup 2)
1046                      (match_dup 5)] UNSPEC_ADDX))]
1047   ""
1048   {
1049     unsigned char pat[16] = {
1050       0x04, 0x05, 0x06, 0x07,
1051       0x80, 0x80, 0x80, 0x80,
1052       0x0c, 0x0d, 0x0e, 0x0f,
1053       0x80, 0x80, 0x80, 0x80
1054     };
1055     operands[3] = gen_reg_rtx (<MODE>mode);
1056     operands[4] = gen_reg_rtx (TImode);
1057     operands[5] = gen_reg_rtx (<MODE>mode);
1058     emit_move_insn (operands[4], array_to_constant (TImode, pat));
1059   })
1061 (define_insn "cg_<mode>"
1062   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1063         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1064                       (match_operand 2 "spu_reg_operand" "r")] UNSPEC_CG))]
1065   "operands"
1066   "cg\t%0,%1,%2")
1068 (define_insn "cgx_<mode>"
1069   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1070         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1071                       (match_operand 2 "spu_reg_operand" "r")
1072                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_CGX))]
1073   "operands"
1074   "cgx\t%0,%1,%2")
1076 (define_insn "addx_<mode>"
1077   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1078         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1079                       (match_operand 2 "spu_reg_operand" "r")
1080                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_ADDX))]
1081   "operands"
1082   "addx\t%0,%1,%2")
1085 ;; This is not the most efficient implementation of addti3.
1086 ;; We include this here because 1) the compiler needs it to be
1087 ;; defined as the word size is 128-bit and 2) sometimes gcc
1088 ;; substitutes an add for a constant left-shift. 2) is unlikely
1089 ;; because we also give addti3 a high cost. In case gcc does
1090 ;; generate TImode add, here is the code to do it.
1091 ;; operand 2 is a nonmemory because the compiler requires it.
1092 (define_insn "addti3"
1093   [(set (match_operand:TI 0 "spu_reg_operand" "=&r")
1094         (plus:TI (match_operand:TI 1 "spu_reg_operand" "r")
1095                  (match_operand:TI 2 "spu_nonmem_operand" "r")))
1096    (clobber (match_scratch:TI 3 "=&r"))]
1097   ""
1098   "cg\t%3,%1,%2\n\\
1099    shlqbyi\t%3,%3,4\n\\
1100    cgx\t%3,%1,%2\n\\
1101    shlqbyi\t%3,%3,4\n\\
1102    cgx\t%3,%1,%2\n\\
1103    shlqbyi\t%0,%3,4\n\\
1104    addx\t%0,%1,%2"
1105   [(set_attr "type" "multi0")
1106    (set_attr "length" "28")])
1108 (define_insn "add<mode>3"
1109   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1110         (plus:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1111                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
1112   ""
1113   "fa\t%0,%1,%2"
1114   [(set_attr "type" "fp6")])
1116 (define_insn "add<mode>3"
1117   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1118         (plus:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1119                   (match_operand:VDF 2 "spu_reg_operand" "r")))]
1120   ""
1121   "dfa\t%0,%1,%2"
1122   [(set_attr "type" "fpd")])
1125 ;; sub
1127 (define_expand "subv16qi3"
1128   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
1129         (minus:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")
1130                      (match_operand:V16QI 2 "spu_reg_operand" "r")))]
1131   ""
1132   "{
1133     rtx res_short = simplify_gen_subreg (V8HImode, operands[0], V16QImode, 0);
1134     rtx lhs_short = simplify_gen_subreg (V8HImode, operands[1], V16QImode, 0);
1135     rtx rhs_short = simplify_gen_subreg (V8HImode, operands[2], V16QImode, 0);
1136     rtx rhs_and = gen_reg_rtx (V8HImode);
1137     rtx hi_char = gen_reg_rtx (V8HImode);
1138     rtx lo_char = gen_reg_rtx (V8HImode);
1139     rtx mask = gen_reg_rtx (V8HImode);
1141     emit_move_insn (mask, spu_const (V8HImode, 0x00ff));
1142     emit_insn (gen_andv8hi3 (rhs_and, rhs_short, spu_const (V8HImode, 0xff00)));
1143     emit_insn (gen_subv8hi3 (hi_char, lhs_short, rhs_and));
1144     emit_insn (gen_subv8hi3 (lo_char, lhs_short, rhs_short));
1145     emit_insn (gen_selb (res_short, hi_char, lo_char, mask));
1146     DONE;
1147    }")
1149 (define_insn "sub<mode>3"
1150   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
1151         (minus:VHSI (match_operand:VHSI 1 "spu_arith_operand" "r,B")
1152                     (match_operand:VHSI 2 "spu_reg_operand" "r,r")))]
1153   ""
1154   "@
1155   sf<bh>\t%0,%2,%1
1156   sf<bh>i\t%0,%2,%1")
1158 (define_expand "sub<mode>3"
1159   [(set (match_dup:VDI 3) 
1160         (unspec:VDI [(match_operand:VDI 1 "spu_reg_operand" "")
1161                      (match_operand:VDI 2 "spu_reg_operand" "")] UNSPEC_BG))
1162    (set (match_dup:VDI 5)
1163         (unspec:VDI [(match_dup 3)
1164                      (match_dup 3)
1165                      (match_dup:TI 4)] UNSPEC_SHUFB))
1166    (set (match_operand:VDI 0 "spu_reg_operand" "") 
1167         (unspec:VDI [(match_dup 1)
1168                      (match_dup 2)
1169                      (match_dup 5)] UNSPEC_SFX))]
1170   ""
1171   {
1172     unsigned char pat[16] = {
1173       0x04, 0x05, 0x06, 0x07,
1174       0xc0, 0xc0, 0xc0, 0xc0,
1175       0x0c, 0x0d, 0x0e, 0x0f,
1176       0xc0, 0xc0, 0xc0, 0xc0
1177     };
1178     operands[3] = gen_reg_rtx (<MODE>mode);
1179     operands[4] = gen_reg_rtx (TImode);
1180     operands[5] = gen_reg_rtx (<MODE>mode);
1181     emit_move_insn (operands[4], array_to_constant (TImode, pat));
1182   })
1184 (define_insn "bg_<mode>"
1185   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1186         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1187                       (match_operand 2 "spu_reg_operand" "r")] UNSPEC_BG))]
1188   "operands"
1189   "bg\t%0,%2,%1")
1191 (define_insn "bgx_<mode>"
1192   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1193         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1194                       (match_operand 2 "spu_reg_operand" "r")
1195                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_BGX))]
1196   "operands"
1197   "bgx\t%0,%2,%1")
1199 (define_insn "sfx_<mode>"
1200   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1201         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1202                       (match_operand 2 "spu_reg_operand" "r")
1203                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_SFX))]
1204   "operands"
1205   "sfx\t%0,%2,%1")
1207 (define_insn "subti3"
1208   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
1209         (minus:TI (match_operand:TI 1 "spu_reg_operand" "r")
1210                   (match_operand:TI 2 "spu_reg_operand" "r")))
1211    (clobber (match_scratch:TI 3 "=&r"))
1212    (clobber (match_scratch:TI 4 "=&r"))
1213    (clobber (match_scratch:TI 5 "=&r"))
1214    (clobber (match_scratch:TI 6 "=&r"))]
1215   ""
1216   "il\t%6,1\n\\
1217    bg\t%3,%2,%1\n\\
1218    xor\t%3,%3,%6\n\\
1219    sf\t%4,%2,%1\n\\
1220    shlqbyi\t%5,%3,4\n\\
1221    bg\t%3,%5,%4\n\\
1222    xor\t%3,%3,%6\n\\
1223    sf\t%4,%5,%4\n\\
1224    shlqbyi\t%5,%3,4\n\\
1225    bg\t%3,%5,%4\n\\
1226    xor\t%3,%3,%6\n\\
1227    sf\t%4,%5,%4\n\\
1228    shlqbyi\t%5,%3,4\n\\
1229    sf\t%0,%5,%4"
1230   [(set_attr "type" "multi0")
1231    (set_attr "length" "56")])
1233 (define_insn "sub<mode>3"
1234   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1235         (minus:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1236                    (match_operand:VSF 2 "spu_reg_operand" "r")))]
1237   ""
1238   "fs\t%0,%1,%2"
1239   [(set_attr "type" "fp6")])
1241 (define_insn "sub<mode>3"
1242   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1243         (minus:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1244                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
1245   ""
1246   "dfs\t%0,%1,%2"
1247   [(set_attr "type" "fpd")])
1250 ;; neg
1252 (define_expand "negv16qi2"
1253   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
1254         (neg:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")))]
1255   ""
1256   "{
1257     rtx zero = gen_reg_rtx (V16QImode);
1258     emit_move_insn (zero, CONST0_RTX (V16QImode));
1259     emit_insn (gen_subv16qi3 (operands[0], zero, operands[1]));
1260     DONE;
1261    }")
1263 (define_insn "neg<mode>2"
1264   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
1265         (neg:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")))]
1266   ""
1267   "sf<bh>i\t%0,%1,0")
1269 (define_expand "negdi2"
1270   [(set (match_operand:DI 0 "spu_reg_operand" "")
1271         (neg:DI (match_operand:DI 1 "spu_reg_operand" "")))]
1272   ""
1273   {
1274     rtx zero = gen_reg_rtx(DImode);
1275     emit_move_insn(zero, GEN_INT(0));
1276     emit_insn (gen_subdi3(operands[0], zero, operands[1]));
1277     DONE;
1278   })
1280 (define_expand "negti2"
1281   [(set (match_operand:TI 0 "spu_reg_operand" "")
1282         (neg:TI (match_operand:TI 1 "spu_reg_operand" "")))]
1283   ""
1284   {
1285     rtx zero = gen_reg_rtx(TImode);
1286     emit_move_insn(zero, GEN_INT(0));
1287     emit_insn (gen_subti3(operands[0], zero, operands[1]));
1288     DONE;
1289   })
1291 (define_expand "neg<mode>2"
1292   [(parallel
1293     [(set (match_operand:VSF 0 "spu_reg_operand" "")
1294           (neg:VSF (match_operand:VSF 1 "spu_reg_operand" "")))
1295      (use (match_dup 2))])]
1296   ""
1297   "operands[2] = gen_reg_rtx (<F2I>mode);
1298    emit_move_insn (operands[2], spu_const (<F2I>mode, -0x80000000ull));")
1300 (define_expand "neg<mode>2"
1301   [(parallel
1302     [(set (match_operand:VDF 0 "spu_reg_operand" "")
1303           (neg:VDF (match_operand:VDF 1 "spu_reg_operand" "")))
1304      (use (match_dup 2))])]
1305   ""
1306   "operands[2] = gen_reg_rtx (<F2I>mode);
1307    emit_move_insn (operands[2], spu_const (<F2I>mode, -0x8000000000000000ull));")
1309 (define_insn_and_split "_neg<mode>2"
1310   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1311         (neg:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")))
1312    (use (match_operand:<F2I> 2 "spu_reg_operand" "r"))]
1313   ""
1314   "#"
1315   ""
1316   [(set (match_dup:<F2I> 3)
1317         (xor:<F2I> (match_dup:<F2I> 4)
1318                    (match_dup:<F2I> 2)))]
1319   {
1320     operands[3] = spu_gen_subreg (<F2I>mode, operands[0]);
1321     operands[4] = spu_gen_subreg (<F2I>mode, operands[1]);
1322   })
1325 ;; abs
1327 (define_expand "abs<mode>2"
1328   [(parallel
1329     [(set (match_operand:VSF 0 "spu_reg_operand" "")
1330           (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "")))
1331      (use (match_dup 2))])]
1332   ""
1333   "operands[2] = gen_reg_rtx (<F2I>mode);
1334    emit_move_insn (operands[2], spu_const (<F2I>mode, 0x7fffffffull));")
1336 (define_expand "abs<mode>2"
1337   [(parallel
1338     [(set (match_operand:VDF 0 "spu_reg_operand" "")
1339           (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "")))
1340      (use (match_dup 2))])]
1341   ""
1342   "operands[2] = gen_reg_rtx (<F2I>mode);
1343    emit_move_insn (operands[2], spu_const (<F2I>mode, 0x7fffffffffffffffull));")
1345 (define_insn_and_split "_abs<mode>2"
1346   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1347         (abs:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")))
1348    (use (match_operand:<F2I> 2 "spu_reg_operand" "r"))]
1349   ""
1350   "#"
1351   ""
1352   [(set (match_dup:<F2I> 3)
1353         (and:<F2I> (match_dup:<F2I> 4)
1354                    (match_dup:<F2I> 2)))]
1355   {
1356     operands[3] = spu_gen_subreg (<F2I>mode, operands[0]);
1357     operands[4] = spu_gen_subreg (<F2I>mode, operands[1]);
1358   })
1361 ;; mul
1363 (define_insn "mulhi3"
1364   [(set (match_operand:HI 0 "spu_reg_operand" "=r,r")
1365         (mult:HI (match_operand:HI 1 "spu_reg_operand" "r,r")
1366                  (match_operand:HI 2 "spu_arith_operand" "r,B")))]
1367   ""
1368   "@
1369   mpy\t%0,%1,%2
1370   mpyi\t%0,%1,%2"
1371   [(set_attr "type" "fp7")])
1373 (define_expand "mulv8hi3"
1374   [(set (match_operand:V8HI 0 "spu_reg_operand" "")
1375         (mult:V8HI (match_operand:V8HI 1 "spu_reg_operand" "")
1376                    (match_operand:V8HI 2 "spu_reg_operand" "")))]
1377   ""
1378   "{
1379     rtx result = simplify_gen_subreg (V4SImode, operands[0], V8HImode, 0);
1380     rtx low = gen_reg_rtx (V4SImode);
1381     rtx high = gen_reg_rtx (V4SImode);
1382     rtx shift = gen_reg_rtx (V4SImode);
1383     rtx mask = gen_reg_rtx (V4SImode);
1385     emit_move_insn (mask, spu_const (V4SImode, 0x0000ffff));
1386     emit_insn (gen_spu_mpyhh (high, operands[1], operands[2]));
1387     emit_insn (gen_spu_mpy (low, operands[1], operands[2]));
1388     emit_insn (gen_vashlv4si3 (shift, high, spu_const(V4SImode, 16)));
1389     emit_insn (gen_selb (result, shift, low, mask));
1390     DONE;
1391    }")
1393 (define_expand "mul<mode>3"
1394   [(parallel
1395     [(set (match_operand:VSI 0 "spu_reg_operand" "")
1396           (mult:VSI (match_operand:VSI 1 "spu_reg_operand" "")
1397                     (match_operand:VSI 2 "spu_reg_operand" "")))
1398      (clobber (match_dup:VSI 3))
1399      (clobber (match_dup:VSI 4))
1400      (clobber (match_dup:VSI 5))
1401      (clobber (match_dup:VSI 6))])]
1402   ""
1403   {
1404     operands[3] = gen_reg_rtx(<MODE>mode);
1405     operands[4] = gen_reg_rtx(<MODE>mode);
1406     operands[5] = gen_reg_rtx(<MODE>mode);
1407     operands[6] = gen_reg_rtx(<MODE>mode);
1408   })
1410 (define_insn_and_split "_mulsi3"
1411   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1412         (mult:SI (match_operand:SI 1 "spu_reg_operand" "r")
1413                  (match_operand:SI 2 "spu_arith_operand" "rK")))
1414    (clobber (match_operand:SI 3 "spu_reg_operand" "=&r"))
1415    (clobber (match_operand:SI 4 "spu_reg_operand" "=&r"))
1416    (clobber (match_operand:SI 5 "spu_reg_operand" "=&r"))
1417    (clobber (match_operand:SI 6 "spu_reg_operand" "=&r"))]
1418   ""
1419   "#"
1420   ""
1421   [(set (match_dup:SI 0)
1422         (mult:SI (match_dup:SI 1)
1423                  (match_dup:SI 2)))]
1424   {
1425     HOST_WIDE_INT val = 0;
1426     rtx a = operands[3];
1427     rtx b = operands[4];
1428     rtx c = operands[5];
1429     rtx d = operands[6];
1430     if (GET_CODE(operands[2]) == CONST_INT)
1431       {
1432         val = INTVAL(operands[2]);
1433         emit_move_insn(d, operands[2]);
1434         operands[2] = d;
1435       }
1436     if (val && (val & 0xffff) == 0)
1437       {
1438         emit_insn (gen_mpyh_si(operands[0], operands[2], operands[1]));
1439       }
1440     else if (val > 0 && val < 0x10000)
1441       {
1442         rtx cst = satisfies_constraint_K (GEN_INT (val)) ? GEN_INT(val) : d;
1443         emit_insn (gen_mpyh_si(a, operands[1], operands[2]));
1444         emit_insn (gen_mpyu_si(c, operands[1], cst));
1445         emit_insn (gen_addsi3(operands[0], a, c));
1446       }
1447     else
1448       {
1449         emit_insn (gen_mpyh_si(a, operands[1], operands[2]));
1450         emit_insn (gen_mpyh_si(b, operands[2], operands[1]));
1451         emit_insn (gen_mpyu_si(c, operands[1], operands[2]));
1452         emit_insn (gen_addsi3(d, a, b));
1453         emit_insn (gen_addsi3(operands[0], d, c));
1454       }
1455     DONE;
1456    })
1458 (define_insn_and_split "_mulv4si3"
1459   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
1460         (mult:V4SI (match_operand:V4SI 1 "spu_reg_operand" "r")
1461                    (match_operand:V4SI 2 "spu_reg_operand" "r")))
1462    (clobber (match_operand:V4SI 3 "spu_reg_operand" "=&r"))
1463    (clobber (match_operand:V4SI 4 "spu_reg_operand" "=&r"))
1464    (clobber (match_operand:V4SI 5 "spu_reg_operand" "=&r"))
1465    (clobber (match_operand:V4SI 6 "spu_reg_operand" "=&r"))]
1466   ""
1467   "#"
1468   ""
1469   [(set (match_dup:V4SI 0)
1470         (mult:V4SI (match_dup:V4SI 1)
1471                    (match_dup:V4SI 2)))]
1472   {
1473     rtx a = operands[3];
1474     rtx b = operands[4];
1475     rtx c = operands[5];
1476     rtx d = operands[6];
1477     rtx op1 = simplify_gen_subreg (V8HImode, operands[1], V4SImode, 0);
1478     rtx op2 = simplify_gen_subreg (V8HImode, operands[2], V4SImode, 0);
1479     emit_insn (gen_spu_mpyh(a, op1, op2));
1480     emit_insn (gen_spu_mpyh(b, op2, op1));
1481     emit_insn (gen_spu_mpyu(c, op1, op2));
1482     emit_insn (gen_addv4si3(d, a, b));
1483     emit_insn (gen_addv4si3(operands[0], d, c));
1484     DONE;
1485    })
1487 (define_insn "mulhisi3"
1488   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1489         (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1490                  (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r"))))]
1491   ""
1492   "mpy\t%0,%1,%2"
1493   [(set_attr "type" "fp7")])
1495 (define_insn "mulhisi3_imm"
1496   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1497         (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1498                  (match_operand:SI 2 "imm_K_operand" "K")))]
1499   ""
1500   "mpyi\t%0,%1,%2"
1501   [(set_attr "type" "fp7")])
1503 (define_insn "umulhisi3"
1504   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1505         (mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1506                  (zero_extend:SI (match_operand:HI 2 "spu_reg_operand" "r"))))]
1507   ""
1508   "mpyu\t%0,%1,%2"
1509   [(set_attr "type" "fp7")])
1511 (define_insn "umulhisi3_imm"
1512   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1513         (mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1514                  (and:SI (match_operand:SI 2 "imm_K_operand" "K") (const_int 65535))))]
1515   ""
1516   "mpyui\t%0,%1,%2"
1517   [(set_attr "type" "fp7")])
1519 (define_insn "mpyu_si"
1520   [(set (match_operand:SI 0 "spu_reg_operand" "=r,r")
1521         (mult:SI (and:SI (match_operand:SI 1 "spu_reg_operand" "r,r")
1522                          (const_int 65535))
1523                  (and:SI (match_operand:SI 2 "spu_arith_operand" "r,K")
1524                          (const_int 65535))))]
1525   ""
1526   "@
1527    mpyu\t%0,%1,%2
1528    mpyui\t%0,%1,%2"
1529   [(set_attr "type" "fp7")])
1531 ;; This isn't always profitable to use.  Consider r = a * b + c * d.
1532 ;; It's faster to do the multiplies in parallel then add them.  If we
1533 ;; merge a multiply and add it prevents the multiplies from happening in
1534 ;; parallel.
1535 (define_insn "mpya_si"
1536   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1537         (plus:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1538                           (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r")))
1539                  (match_operand:SI 3 "spu_reg_operand" "r")))]
1540   "0"
1541   "mpya\t%0,%1,%2,%3"
1542   [(set_attr "type" "fp7")])
1544 (define_insn "mpyh_si"
1545   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1546         (mult:SI (and:SI (match_operand:SI 1 "spu_reg_operand" "r")
1547                          (const_int -65536))
1548                  (and:SI (match_operand:SI 2 "spu_reg_operand" "r")
1549                          (const_int 65535))))]
1550   ""
1551   "mpyh\t%0,%1,%2"
1552   [(set_attr "type" "fp7")])
1554 (define_insn "mpys_si"
1555   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1556         (ashiftrt:SI
1557             (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1558                      (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r")))
1559             (const_int 16)))]
1560   ""
1561   "mpys\t%0,%1,%2"
1562   [(set_attr "type" "fp7")])
1564 (define_insn "mpyhh_si"
1565   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1566         (mult:SI (ashiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1567                               (const_int 16))
1568                  (ashiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1569                               (const_int 16))))]
1570   ""
1571   "mpyhh\t%0,%1,%2"
1572   [(set_attr "type" "fp7")])
1574 (define_insn "mpyhhu_si"
1575   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1576         (mult:SI (lshiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1577                               (const_int 16))
1578                  (lshiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1579                               (const_int 16))))]
1580   ""
1581   "mpyhhu\t%0,%1,%2"
1582   [(set_attr "type" "fp7")])
1584 (define_insn "mpyhha_si" 
1585   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1586         (plus:SI (mult:SI (ashiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1587                                        (const_int 16))
1588                           (ashiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1589                                        (const_int 16)))
1590                  (match_operand:SI 3 "spu_reg_operand" "0")))]
1591   "0"
1592   "mpyhha\t%0,%1,%2"
1593   [(set_attr "type" "fp7")])
1595 (define_insn "mul<mode>3"
1596   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1597         (mult:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")
1598                    (match_operand:VSDF 2 "spu_reg_operand" "r")))]
1599   ""
1600   "<d>fm\t%0,%1,%2"
1601   [(set_attr "type" "fp<d6>")])
1603 (define_insn "fma<mode>4"
1604   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1605         (fma:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1606                  (match_operand:VSF 2 "spu_reg_operand" "r")
1607                  (match_operand:VSF 3 "spu_reg_operand" "r")))]
1608   ""
1609   "fma\t%0,%1,%2,%3"
1610   [(set_attr "type"     "fp6")])
1612 ;; ??? The official description is (c - a*b), which is exactly (-a*b + c).
1613 ;; Note that this doesn't match the dfnms description.  Incorrect?
1614 (define_insn "fnma<mode>4"
1615   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1616         (fma:VSF
1617           (neg:VSF (match_operand:VSF 1 "spu_reg_operand" "r"))
1618           (match_operand:VSF 2 "spu_reg_operand" "r")
1619           (match_operand:VSF 3 "spu_reg_operand" "r")))]
1620   ""
1621   "fnms\t%0,%1,%2,%3"
1622   [(set_attr "type" "fp6")])
1624 (define_insn "fms<mode>4"
1625   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1626         (fma:VSF
1627           (match_operand:VSF 1 "spu_reg_operand" "r")
1628           (match_operand:VSF 2 "spu_reg_operand" "r")
1629           (neg:VSF (match_operand:VSF 3 "spu_reg_operand" "r"))))]
1630   ""
1631   "fms\t%0,%1,%2,%3"
1632   [(set_attr "type" "fp6")])
1634 (define_insn "fma<mode>4"
1635   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1636         (fma:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1637                  (match_operand:VDF 2 "spu_reg_operand" "r")
1638                  (match_operand:VDF 3 "spu_reg_operand" "0")))]
1639   ""
1640   "dfma\t%0,%1,%2"
1641   [(set_attr "type"     "fpd")])
1643 (define_insn "fms<mode>4"
1644   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1645         (fma:VDF
1646           (match_operand:VDF 1 "spu_reg_operand" "r")
1647           (match_operand:VDF 2 "spu_reg_operand" "r")
1648           (neg:VDF (match_operand:VDF 3 "spu_reg_operand" "0"))))]
1649   ""
1650   "dfms\t%0,%1,%2"
1651   [(set_attr "type" "fpd")])
1653 (define_insn "nfma<mode>4"
1654   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1655         (neg:VDF
1656           (fma:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1657                    (match_operand:VDF 2 "spu_reg_operand" "r")
1658                    (match_operand:VDF 3 "spu_reg_operand" "0"))))]
1659   ""
1660   "dfnma\t%0,%1,%2"
1661   [(set_attr "type"     "fpd")])
1663 (define_insn "nfms<mode>4"
1664   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1665         (neg:VDF
1666           (fma:VDF
1667             (match_operand:VDF 1 "spu_reg_operand" "r")
1668             (match_operand:VDF 2 "spu_reg_operand" "r")
1669             (neg:VDF (match_operand:VDF 3 "spu_reg_operand" "0")))))]
1670   ""
1671   "dfnms\t%0,%1,%2"
1672   [(set_attr "type" "fpd")])
1674 ;; If signed zeros are ignored, -(a * b - c) = -a * b + c.
1675 (define_expand "fnma<mode>4"
1676   [(set (match_operand:VDF 0 "spu_reg_operand" "")
1677         (neg:VDF
1678           (fma:VDF
1679             (match_operand:VDF 1 "spu_reg_operand" "")
1680             (match_operand:VDF 2 "spu_reg_operand" "")
1681             (neg:VDF (match_operand:VDF 3 "spu_reg_operand" "")))))]
1682   "!HONOR_SIGNED_ZEROS (<MODE>mode)"
1683   "")
1685 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
1686 (define_expand "fnms<mode>4"
1687   [(set (match_operand:VDF 0 "register_operand" "")
1688         (neg:VDF
1689           (fma:VDF
1690             (match_operand:VDF 1 "register_operand" "")
1691             (match_operand:VDF 2 "register_operand" "")
1692             (match_operand:VDF 3 "register_operand" ""))))]
1693   "!HONOR_SIGNED_ZEROS (<MODE>mode)"
1694   "")
1696 ;; mul highpart, used for divide by constant optimizations.
1698 (define_expand "smulsi3_highpart"
1699   [(set (match_operand:SI 0 "register_operand" "")
1700         (truncate:SI
1701           (ashiftrt:DI
1702             (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
1703                      (sign_extend:DI (match_operand:SI 2 "register_operand" "")))
1704             (const_int 32))))]
1705   ""
1706   {
1707     rtx t0 = gen_reg_rtx (SImode);
1708     rtx t1 = gen_reg_rtx (SImode);
1709     rtx t2 = gen_reg_rtx (SImode);
1710     rtx t3 = gen_reg_rtx (SImode);
1711     rtx t4 = gen_reg_rtx (SImode);
1712     rtx t5 = gen_reg_rtx (SImode);
1713     rtx t6 = gen_reg_rtx (SImode);
1714     rtx t7 = gen_reg_rtx (SImode);
1715     rtx t8 = gen_reg_rtx (SImode);
1716     rtx t9 = gen_reg_rtx (SImode);
1717     rtx t11 = gen_reg_rtx (SImode);
1718     rtx t12 = gen_reg_rtx (SImode);
1719     rtx t14 = gen_reg_rtx (SImode);
1720     rtx t15 = gen_reg_rtx (HImode);
1721     rtx t16 = gen_reg_rtx (HImode);
1722     rtx t17 = gen_reg_rtx (HImode);
1723     rtx t18 = gen_reg_rtx (HImode);
1724     rtx t19 = gen_reg_rtx (SImode);
1725     rtx t20 = gen_reg_rtx (SImode);
1726     rtx t21 = gen_reg_rtx (SImode);
1727     rtx op1_hi = gen_rtx_SUBREG (HImode, operands[1], 2);
1728     rtx op2_hi = gen_rtx_SUBREG (HImode, operands[2], 2);
1729     rtx t0_hi = gen_rtx_SUBREG (HImode, t0, 2);
1730     rtx t1_hi = gen_rtx_SUBREG (HImode, t1, 2);
1732     rtx insn = emit_insn (gen_lshrsi3 (t0, operands[1], GEN_INT (16)));
1733     emit_insn (gen_lshrsi3 (t1, operands[2], GEN_INT (16)));
1734     emit_insn (gen_umulhisi3 (t2, op1_hi, op2_hi));
1735     emit_insn (gen_mpyh_si (t3, operands[1], operands[2]));
1736     emit_insn (gen_mpyh_si (t4, operands[2], operands[1]));
1737     emit_insn (gen_mpyhh_si (t5, operands[1], operands[2]));
1738     emit_insn (gen_mpys_si (t6, t0_hi, op2_hi));
1739     emit_insn (gen_mpys_si (t7, t1_hi, op1_hi));
1741     /* Gen carry bits (in t9 and t11). */
1742     emit_insn (gen_addsi3 (t8, t2, t3));
1743     emit_insn (gen_cg_si (t9, t2, t3));
1744     emit_insn (gen_cg_si (t11, t8, t4));
1746     /* Gen high 32 bits in operand[0].  Correct for mpys. */
1747     emit_insn (gen_addx_si (t12, t5, t6, t9));
1748     emit_insn (gen_addx_si (t14, t12, t7, t11));
1750     /* mpys treats both operands as signed when we really want it to treat
1751        the first operand as signed and the second operand as unsigned.
1752        The code below corrects for that difference.  */
1753     emit_insn (gen_cgt_hi (t15, op1_hi, GEN_INT (-1)));
1754     emit_insn (gen_cgt_hi (t16, op2_hi, GEN_INT (-1)));
1755     emit_insn (gen_andc_hi (t17, t1_hi, t15));
1756     emit_insn (gen_andc_hi (t18, t0_hi, t16));
1757     emit_insn (gen_extendhisi2 (t19, t17));
1758     emit_insn (gen_extendhisi2 (t20, t18));
1759     emit_insn (gen_addsi3 (t21, t19, t20));
1760     emit_insn (gen_addsi3 (operands[0], t14, t21));
1761     unshare_all_rtl_in_chain (insn);
1762     DONE;
1763   })
1765 (define_expand "umulsi3_highpart"
1766   [(set (match_operand:SI 0 "register_operand" "")
1767         (truncate:SI
1768           (ashiftrt:DI
1769             (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
1770                      (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1771             (const_int 32))))]
1772   ""
1773   
1774   {
1775     rtx t0 = gen_reg_rtx (SImode);
1776     rtx t1 = gen_reg_rtx (SImode);
1777     rtx t2 = gen_reg_rtx (SImode);
1778     rtx t3 = gen_reg_rtx (SImode);
1779     rtx t4 = gen_reg_rtx (SImode);
1780     rtx t5 = gen_reg_rtx (SImode);
1781     rtx t6 = gen_reg_rtx (SImode);
1782     rtx t7 = gen_reg_rtx (SImode);
1783     rtx t8 = gen_reg_rtx (SImode);
1784     rtx t9 = gen_reg_rtx (SImode);
1785     rtx t10 = gen_reg_rtx (SImode);
1786     rtx t12 = gen_reg_rtx (SImode);
1787     rtx t13 = gen_reg_rtx (SImode);
1788     rtx t14 = gen_reg_rtx (SImode);
1789     rtx op1_hi = gen_rtx_SUBREG (HImode, operands[1], 2);
1790     rtx op2_hi = gen_rtx_SUBREG (HImode, operands[2], 2);
1791     rtx t0_hi = gen_rtx_SUBREG (HImode, t0, 2);
1793     rtx insn = emit_insn (gen_rotlsi3 (t0, operands[2], GEN_INT (16)));
1794     emit_insn (gen_umulhisi3 (t1, op1_hi, op2_hi));
1795     emit_insn (gen_umulhisi3 (t2, op1_hi, t0_hi));
1796     emit_insn (gen_mpyhhu_si (t3, operands[1], t0));
1797     emit_insn (gen_mpyhhu_si (t4, operands[1], operands[2]));
1798     emit_insn (gen_ashlsi3 (t5, t2, GEN_INT (16)));
1799     emit_insn (gen_ashlsi3 (t6, t3, GEN_INT (16)));
1800     emit_insn (gen_lshrsi3 (t7, t2, GEN_INT (16)));
1801     emit_insn (gen_lshrsi3 (t8, t3, GEN_INT (16)));
1803     /* Gen carry bits (in t10 and t12). */
1804     emit_insn (gen_addsi3 (t9, t1, t5));
1805     emit_insn (gen_cg_si (t10, t1, t5));
1806     emit_insn (gen_cg_si (t12, t9, t6));
1808     /* Gen high 32 bits in operand[0]. */
1809     emit_insn (gen_addx_si (t13, t4, t7, t10));
1810     emit_insn (gen_addx_si (t14, t13, t8, t12));
1811     emit_insn (gen_movsi (operands[0], t14));
1812     unshare_all_rtl_in_chain (insn);
1814     DONE;
1815   })
1817 ;; div
1819 ;; Not necessarily the best implementation of divide but faster then
1820 ;; the default that gcc provides because this is inlined and it uses
1821 ;; clz.
1822 (define_insn "divmodsi4"
1823       [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
1824             (div:SI (match_operand:SI 1 "spu_reg_operand" "r")
1825                     (match_operand:SI 2 "spu_reg_operand" "r")))
1826        (set (match_operand:SI 3 "spu_reg_operand" "=&r")
1827             (mod:SI (match_dup 1)
1828                     (match_dup 2)))
1829        (clobber (match_scratch:SI 4 "=&r"))
1830        (clobber (match_scratch:SI 5 "=&r"))
1831        (clobber (match_scratch:SI 6 "=&r"))
1832        (clobber (match_scratch:SI 7 "=&r"))
1833        (clobber (match_scratch:SI 8 "=&r"))
1834        (clobber (match_scratch:SI 9 "=&r"))
1835        (clobber (match_scratch:SI 10 "=&r"))
1836        (clobber (match_scratch:SI 11 "=&r"))
1837        (clobber (match_scratch:SI 12 "=&r"))
1838        (clobber (reg:SI 130))]
1839   ""
1840   "heqi %2,0\\n\\
1841         hbrr    3f,1f\\n\\
1842         sfi     %8,%1,0\\n\\
1843         sfi     %9,%2,0\\n\\
1844         cgti    %10,%1,-1\\n\\
1845         cgti    %11,%2,-1\\n\\
1846         selb    %8,%8,%1,%10\\n\\
1847         selb    %9,%9,%2,%11\\n\\
1848         clz     %4,%8\\n\\
1849         clz     %7,%9\\n\\
1850         il      %5,1\\n\\
1851         fsmbi   %0,0\\n\\
1852         sf      %7,%4,%7\\n\\
1853         shlqbyi %3,%8,0\\n\\
1854         xor     %11,%10,%11\\n\\
1855         shl     %5,%5,%7\\n\\
1856         shl     %4,%9,%7\\n\\
1857         lnop    \\n\\
1858 1:      or      %12,%0,%5\\n\\
1859         rotqmbii        %5,%5,-1\\n\\
1860         clgt    %6,%4,%3\\n\\
1861         lnop    \\n\\
1862         sf      %7,%4,%3\\n\\
1863         rotqmbii        %4,%4,-1\\n\\
1864         selb    %0,%12,%0,%6\\n\\
1865         lnop    \\n\\
1866         selb    %3,%7,%3,%6\\n\\
1867 3:      brnz    %5,1b\\n\\
1868 2:      sfi     %8,%3,0\\n\\
1869         sfi     %9,%0,0\\n\\
1870         selb    %3,%8,%3,%10\\n\\
1871         selb    %0,%0,%9,%11"
1872   [(set_attr "type" "multi0")
1873    (set_attr "length" "128")])
1875 (define_insn "udivmodsi4"
1876       [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
1877             (udiv:SI (match_operand:SI 1 "spu_reg_operand" "r")
1878                      (match_operand:SI 2 "spu_reg_operand" "r")))
1879        (set (match_operand:SI 3 "spu_reg_operand" "=&r")
1880             (umod:SI (match_dup 1)
1881                      (match_dup 2)))
1882        (clobber (match_scratch:SI 4 "=&r"))
1883        (clobber (match_scratch:SI 5 "=&r"))
1884        (clobber (match_scratch:SI 6 "=&r"))
1885        (clobber (match_scratch:SI 7 "=&r"))
1886        (clobber (match_scratch:SI 8 "=&r"))
1887        (clobber (reg:SI 130))]
1888   ""
1889   "heqi %2,0\\n\\
1890         hbrr    3f,1f\\n\\
1891         clz     %7,%2\\n\\
1892         clz     %4,%1\\n\\
1893         il      %5,1\\n\\
1894         fsmbi   %0,0\\n\\
1895         sf      %7,%4,%7\\n\\
1896         ori     %3,%1,0\\n\\
1897         shl     %5,%5,%7\\n\\
1898         shl     %4,%2,%7\\n\\
1899 1:      or      %8,%0,%5\\n\\
1900         rotqmbii        %5,%5,-1\\n\\
1901         clgt    %6,%4,%3\\n\\
1902         lnop    \\n\\
1903         sf      %7,%4,%3\\n\\
1904         rotqmbii        %4,%4,-1\\n\\
1905         selb    %0,%8,%0,%6\\n\\
1906         lnop    \\n\\
1907         selb    %3,%7,%3,%6\\n\\
1908 3:      brnz    %5,1b\\n\\
1910   [(set_attr "type" "multi0")
1911    (set_attr "length" "80")])
1913 (define_expand "div<mode>3"
1914   [(parallel
1915     [(set (match_operand:VSF 0 "spu_reg_operand" "")    
1916           (div:VSF (match_operand:VSF 1 "spu_reg_operand" "")
1917                    (match_operand:VSF 2 "spu_reg_operand" "")))
1918      (clobber (match_scratch:VSF 3 ""))
1919      (clobber (match_scratch:VSF 4 ""))
1920      (clobber (match_scratch:VSF 5 ""))])]
1921   ""
1922   "")
1924 (define_insn_and_split "*div<mode>3_fast"
1925   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1926         (div:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1927                  (match_operand:VSF 2 "spu_reg_operand" "r")))
1928    (clobber (match_scratch:VSF 3 "=&r"))
1929    (clobber (match_scratch:VSF 4 "=&r"))
1930    (clobber (scratch:VSF))]
1931   "flag_unsafe_math_optimizations"
1932   "#"
1933   "reload_completed"
1934   [(set (match_dup:VSF 0)
1935         (div:VSF (match_dup:VSF 1)
1936                  (match_dup:VSF 2)))
1937    (clobber (match_dup:VSF 3))
1938    (clobber (match_dup:VSF 4))
1939    (clobber (scratch:VSF))]
1940   {
1941     emit_insn (gen_frest_<mode>(operands[3], operands[2]));
1942     emit_insn (gen_fi_<mode>(operands[3], operands[2], operands[3]));
1943     emit_insn (gen_mul<mode>3(operands[4], operands[1], operands[3]));
1944     emit_insn (gen_fnma<mode>4(operands[0], operands[4], operands[2], operands[1]));
1945     emit_insn (gen_fma<mode>4(operands[0], operands[0], operands[3], operands[4]));
1946     DONE;
1947   })
1949 (define_insn_and_split "*div<mode>3_adjusted"
1950   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1951         (div:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1952                  (match_operand:VSF 2 "spu_reg_operand" "r")))
1953    (clobber (match_scratch:VSF 3 "=&r"))
1954    (clobber (match_scratch:VSF 4 "=&r"))
1955    (clobber (match_scratch:VSF 5 "=&r"))]
1956   "!flag_unsafe_math_optimizations"
1957   "#"
1958   "reload_completed"
1959   [(set (match_dup:VSF 0)
1960         (div:VSF (match_dup:VSF 1)
1961                  (match_dup:VSF 2)))
1962    (clobber (match_dup:VSF 3))
1963    (clobber (match_dup:VSF 4))
1964    (clobber (match_dup:VSF 5))]
1965   {
1966     emit_insn (gen_frest_<mode> (operands[3], operands[2]));
1967     emit_insn (gen_fi_<mode> (operands[3], operands[2], operands[3]));
1968     emit_insn (gen_mul<mode>3 (operands[4], operands[1], operands[3]));
1969     emit_insn (gen_fnma<mode>4 (operands[5], operands[4], operands[2], operands[1]));
1970     emit_insn (gen_fma<mode>4 (operands[3], operands[5], operands[3], operands[4]));
1972    /* Due to truncation error, the quotient result may be low by 1 ulp.
1973       Conditionally add one if the estimate is too small in magnitude.  */
1975     emit_move_insn (gen_lowpart (<F2I>mode, operands[4]),
1976                     spu_const (<F2I>mode, 0x80000000ULL));
1977     emit_move_insn (gen_lowpart (<F2I>mode, operands[5]),
1978                     spu_const (<F2I>mode, 0x3f800000ULL));
1979     emit_insn (gen_selb (operands[5], operands[5], operands[1], operands[4]));
1981     emit_insn (gen_add<f2i>3 (gen_lowpart (<F2I>mode, operands[4]),
1982                               gen_lowpart (<F2I>mode, operands[3]),
1983                               spu_const (<F2I>mode, 1)));
1984     emit_insn (gen_fnma<mode>4 (operands[0], operands[2], operands[4], operands[1]));
1985     emit_insn (gen_mul<mode>3 (operands[0], operands[0], operands[5]));
1986     emit_insn (gen_cgt_<f2i> (gen_lowpart (<F2I>mode, operands[0]),
1987                               gen_lowpart (<F2I>mode, operands[0]),
1988                               spu_const (<F2I>mode, -1)));
1989     emit_insn (gen_selb (operands[0], operands[3], operands[4], operands[0]));
1990     DONE;
1991   })
1994 ;; sqrt
1996 (define_insn_and_split "sqrtsf2"
1997   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
1998         (sqrt:SF (match_operand:SF 1 "spu_reg_operand" "r")))
1999    (clobber (match_scratch:SF 2 "=&r"))
2000    (clobber (match_scratch:SF 3 "=&r"))
2001    (clobber (match_scratch:SF 4 "=&r"))
2002    (clobber (match_scratch:SF 5 "=&r"))]
2003   ""
2004   "#"
2005   "reload_completed"
2006   [(set (match_dup:SF 0)
2007         (sqrt:SF (match_dup:SF 1)))
2008    (clobber (match_dup:SF 2))
2009    (clobber (match_dup:SF 3))
2010    (clobber (match_dup:SF 4))
2011    (clobber (match_dup:SF 5))]
2012   {
2013     emit_move_insn (operands[3],spu_float_const(\"0.5\",SFmode));
2014     emit_move_insn (operands[4],spu_float_const(\"1.00000011920928955078125\",SFmode));
2015     emit_insn (gen_frsqest_sf(operands[2],operands[1]));
2016     emit_insn (gen_fi_sf(operands[2],operands[1],operands[2]));
2017     emit_insn (gen_mulsf3(operands[5],operands[2],operands[1]));
2018     emit_insn (gen_mulsf3(operands[3],operands[5],operands[3]));
2019     emit_insn (gen_fnmasf4(operands[4],operands[2],operands[5],operands[4]));
2020     emit_insn (gen_fmasf4(operands[0],operands[4],operands[3],operands[5]));
2021     DONE;
2022   })
2024 (define_insn "frest_<mode>"
2025   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
2026         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")] UNSPEC_FREST))]
2027   ""
2028   "frest\t%0,%1"
2029   [(set_attr "type" "shuf")])
2031 (define_insn "frsqest_<mode>"
2032   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
2033         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")] UNSPEC_FRSQEST))]
2034   ""
2035   "frsqest\t%0,%1"
2036   [(set_attr "type" "shuf")])
2038 (define_insn "fi_<mode>"
2039   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
2040         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")
2041                     (match_operand:VSF 2 "spu_reg_operand" "r")] UNSPEC_FI))]
2042   ""
2043   "fi\t%0,%1,%2"
2044   [(set_attr "type" "fp7")])
2047 ;; and
2049 (define_insn "and<mode>3"
2050   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r")
2051         (and:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r")
2052                  (match_operand:MOV 2 "spu_logical_operand" "r,C")))]
2053   ""
2054   "@
2055   and\t%0,%1,%2
2056   and%j2i\t%0,%1,%J2")
2058 (define_insn "anddi3"
2059   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2060         (and:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2061                 (match_operand:DI 2 "spu_logical_operand" "r,c")))]
2062   ""
2063   "@
2064   and\t%0,%1,%2
2065   and%k2i\t%0,%1,%K2")
2067 (define_insn "andti3"
2068   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2069         (and:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2070                 (match_operand:TI 2 "spu_logical_operand" "r,Y")))]
2071   ""
2072   "@
2073   and\t%0,%1,%2
2074   and%m2i\t%0,%1,%L2")
2076 (define_insn "andc_<mode>"
2077   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2078         (and:ALL (not:ALL (match_operand:ALL 2 "spu_reg_operand" "r"))
2079                  (match_operand:ALL 1 "spu_reg_operand" "r")))]
2080   ""
2081   "andc\t%0,%1,%2")
2083 (define_insn "nand_<mode>"
2084   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2085         (not:ALL (and:ALL (match_operand:ALL 2 "spu_reg_operand" "r")
2086                           (match_operand:ALL 1 "spu_reg_operand" "r"))))]
2087   ""
2088   "nand\t%0,%1,%2")
2091 ;; ior
2093 (define_insn "ior<mode>3"
2094   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r,r")
2095         (ior:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r,0")
2096                  (match_operand:MOV 2 "spu_ior_operand" "r,C,D")))]
2097   ""
2098   "@
2099   or\t%0,%1,%2
2100   or%j2i\t%0,%1,%J2
2101   iohl\t%0,%J2")
2103 (define_insn "iordi3"
2104   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r,r")
2105         (ior:DI (match_operand:DI 1 "spu_reg_operand" "r,r,0")
2106                 (match_operand:DI 2 "spu_ior_operand" "r,c,d")))]
2107   ""
2108   "@
2109   or\t%0,%1,%2
2110   or%k2i\t%0,%1,%K2
2111   iohl\t%0,%K2")
2113 (define_insn "iorti3"
2114   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r,r")
2115         (ior:TI (match_operand:TI 1 "spu_reg_operand" "r,r,0")
2116                 (match_operand:TI 2 "spu_ior_operand" "r,Y,Z")))]
2117   ""
2118   "@
2119   or\t%0,%1,%2
2120   or%m2i\t%0,%1,%L2
2121   iohl\t%0,%L2")
2123 (define_insn "orc_<mode>"
2124   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2125         (ior:ALL (not:ALL (match_operand:ALL 2 "spu_reg_operand" "r"))
2126                  (match_operand:ALL 1 "spu_reg_operand" "r")))]
2127   ""
2128   "orc\t%0,%1,%2")
2130 (define_insn "nor_<mode>"
2131   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2132         (not:ALL (ior:ALL (match_operand:ALL 1 "spu_reg_operand" "r")
2133                           (match_operand:ALL 2 "spu_reg_operand" "r"))))]
2134   ""
2135   "nor\t%0,%1,%2")
2137 ;; xor
2139 (define_insn "xor<mode>3"
2140   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r")
2141         (xor:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r")
2142                  (match_operand:MOV 2 "spu_logical_operand" "r,B")))]
2143   ""
2144   "@
2145   xor\t%0,%1,%2
2146   xor%j2i\t%0,%1,%J2")
2148 (define_insn "xordi3"
2149   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2150         (xor:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2151                 (match_operand:DI 2 "spu_logical_operand" "r,c")))]
2152   ""
2153   "@
2154   xor\t%0,%1,%2
2155   xor%k2i\t%0,%1,%K2")
2157 (define_insn "xorti3"
2158   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2159         (xor:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2160                 (match_operand:TI 2 "spu_logical_operand" "r,Y")))]
2161   ""
2162   "@
2163   xor\t%0,%1,%2
2164   xor%m2i\t%0,%1,%L2")
2166 (define_insn "eqv_<mode>"
2167   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2168         (not:ALL (xor:ALL (match_operand:ALL 1 "spu_reg_operand" "r")
2169                           (match_operand:ALL 2 "spu_reg_operand" "r"))))]
2170   ""
2171   "eqv\t%0,%1,%2")
2173 ;; one_cmpl
2175 (define_insn "one_cmpl<mode>2"
2176   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2177         (not:ALL (match_operand:ALL 1 "spu_reg_operand" "r")))]
2178   ""
2179   "nor\t%0,%1,%1")
2182 ;; selb
2184 (define_expand "selb"
2185   [(set (match_operand 0 "spu_reg_operand" "")
2186         (unspec [(match_operand 1 "spu_reg_operand" "")
2187                  (match_operand 2 "spu_reg_operand" "")
2188                  (match_operand 3 "spu_reg_operand" "")] UNSPEC_SELB))]
2189   ""
2190   {
2191     rtx s = gen__selb (operands[0], operands[1], operands[2], operands[3]);
2192     PUT_MODE (SET_SRC (s), GET_MODE (operands[0]));
2193     emit_insn (s);
2194     DONE;
2195   })
2197 ;; This could be defined as a combination of logical operations, but at
2198 ;; one time it caused a crash due to recursive expansion of rtl during CSE.
2199 (define_insn "_selb"
2200   [(set (match_operand 0 "spu_reg_operand" "=r")
2201         (unspec [(match_operand 1 "spu_reg_operand" "r")
2202                  (match_operand 2 "spu_reg_operand" "r")
2203                  (match_operand 3 "spu_reg_operand" "r")] UNSPEC_SELB))]
2204   "GET_MODE(operands[0]) == GET_MODE(operands[1]) 
2205    && GET_MODE(operands[1]) == GET_MODE(operands[2])"
2206   "selb\t%0,%1,%2,%3")
2209 ;; Misc. byte/bit operations
2210 ;; clz/ctz/ffs/popcount/parity
2211 ;; cntb/sumb
2213 (define_insn "clz<mode>2"
2214   [(set (match_operand:VSI 0 "spu_reg_operand" "=r")
2215         (clz:VSI (match_operand:VSI 1 "spu_reg_operand" "r")))]
2216   ""
2217   "clz\t%0,%1")
2219 (define_expand "ctz<mode>2"
2220   [(set (match_dup 2)
2221         (neg:VSI (match_operand:VSI 1 "spu_reg_operand" "")))
2222    (set (match_dup 3) (and:VSI (match_dup 1)
2223                                (match_dup 2)))
2224    (set (match_dup 4) (clz:VSI (match_dup 3)))
2225    (set (match_operand:VSI 0 "spu_reg_operand" "")
2226         (minus:VSI (match_dup 5) (match_dup 4)))]
2227   ""
2228   {
2229      operands[2] = gen_reg_rtx (<MODE>mode);
2230      operands[3] = gen_reg_rtx (<MODE>mode);
2231      operands[4] = gen_reg_rtx (<MODE>mode);
2232      operands[5] = spu_const(<MODE>mode, 31);
2233   })
2235 (define_expand "ffs<mode>2"
2236   [(set (match_dup 2)
2237         (neg:VSI (match_operand:VSI 1 "spu_reg_operand" "")))
2238    (set (match_dup 3) (and:VSI (match_dup 1)
2239                                (match_dup 2)))
2240    (set (match_dup 4) (clz:VSI (match_dup 3)))
2241    (set (match_operand:VSI 0 "spu_reg_operand" "")
2242         (minus:VSI (match_dup 5) (match_dup 4)))]
2243   ""
2244   {
2245      operands[2] = gen_reg_rtx (<MODE>mode);
2246      operands[3] = gen_reg_rtx (<MODE>mode);
2247      operands[4] = gen_reg_rtx (<MODE>mode);
2248      operands[5] = spu_const(<MODE>mode, 32);
2249   })
2251 (define_expand "popcountsi2"
2252   [(set (match_dup 2)
2253         (unspec:SI [(match_operand:SI 1 "spu_reg_operand" "")]
2254                      UNSPEC_CNTB))
2255    (set (match_dup 3)
2256         (unspec:HI [(match_dup 2)] UNSPEC_SUMB))
2257    (set (match_operand:SI 0 "spu_reg_operand" "")
2258         (sign_extend:SI (match_dup 3)))]
2259   ""
2260   {
2261     operands[2] = gen_reg_rtx (SImode);
2262     operands[3] = gen_reg_rtx (HImode);
2263   })
2265 (define_expand "paritysi2"
2266   [(set (match_operand:SI 0 "spu_reg_operand" "")
2267         (parity:SI (match_operand:SI 1 "spu_reg_operand" "")))]
2268   ""
2269   {
2270     operands[2] = gen_reg_rtx (SImode);
2271     emit_insn (gen_popcountsi2(operands[2], operands[1]));
2272     emit_insn (gen_andsi3(operands[0], operands[2], GEN_INT (1)));
2273     DONE;
2274   })
2276 (define_insn "cntb_si"
2277   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2278         (unspec:SI [(match_operand:SI 1 "spu_reg_operand" "r")]
2279                    UNSPEC_CNTB))]
2280   ""
2281   "cntb\t%0,%1"
2282   [(set_attr "type" "fxb")])
2284 (define_insn "cntb_v16qi"
2285   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
2286         (unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r")]
2287                       UNSPEC_CNTB))]
2288   ""
2289   "cntb\t%0,%1"
2290   [(set_attr "type" "fxb")])
2292 (define_insn "sumb_si"
2293   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
2294         (unspec:HI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_SUMB))]
2295   ""
2296   "sumb\t%0,%1,%1"
2297   [(set_attr "type" "fxb")])
2300 ;; ashl, vashl
2302 (define_insn "<v>ashl<mode>3"
2303   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2304         (ashift:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2305                      (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))]
2306   ""
2307   "@
2308   shl<bh>\t%0,%1,%2
2309   shl<bh>i\t%0,%1,%<umask>2"
2310   [(set_attr "type" "fx3")])
2312 (define_insn_and_split "ashldi3"
2313   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2314         (ashift:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2315                    (match_operand:SI 2 "spu_nonmem_operand" "r,I")))
2316    (clobber (match_scratch:SI 3 "=&r,X"))]
2317   ""
2318   "#"
2319   "reload_completed"
2320   [(set (match_dup:DI 0)
2321         (ashift:DI (match_dup:DI 1)
2322                    (match_dup:SI 2)))]
2323   {
2324     rtx op0 = gen_rtx_REG (TImode, REGNO (operands[0]));
2325     rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
2326     rtx op2 = operands[2];
2327     rtx op3 = operands[3];
2329     if (GET_CODE (operands[2]) == REG)
2330       {
2331         emit_insn (gen_addsi3 (op3, op2, GEN_INT (64)));
2332         emit_insn (gen_rotlti3 (op0, op1, GEN_INT (64)));
2333         emit_insn (gen_shlqbybi_ti (op0, op0, op3));
2334         emit_insn (gen_shlqbi_ti (op0, op0, op3));
2335       }
2336     else
2337       {
2338         HOST_WIDE_INT val = INTVAL (operands[2]);
2339         emit_insn (gen_rotlti3 (op0, op1, GEN_INT (64)));
2340         emit_insn (gen_shlqby_ti (op0, op0, GEN_INT (val / 8 + 8)));
2341         if (val % 8)
2342           emit_insn (gen_shlqbi_ti (op0, op0, GEN_INT (val % 8)));
2343       }
2344     DONE;
2345   })
2347 (define_expand "ashlti3"
2348   [(parallel [(set (match_operand:TI 0 "spu_reg_operand" "")
2349                    (ashift:TI (match_operand:TI 1 "spu_reg_operand" "")
2350                               (match_operand:SI 2 "spu_nonmem_operand" "")))
2351               (clobber (match_dup:TI 3))])]
2352   ""
2353   "if (GET_CODE (operands[2]) == CONST_INT)
2354     {
2355       emit_insn (gen_ashlti3_imm(operands[0], operands[1], operands[2]));
2356       DONE;
2357     }
2358    operands[3] = gen_reg_rtx (TImode);")
2360 (define_insn_and_split "ashlti3_imm"
2361   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2362         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2363                    (match_operand:SI 2 "immediate_operand" "O,P")))]
2364   ""
2365   "@
2366    shlqbyi\t%0,%1,%h2
2367    shlqbii\t%0,%1,%e2"
2368   "!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
2369   [(set (match_dup:TI 0)
2370         (ashift:TI (match_dup:TI 1)
2371                    (match_dup:SI 3)))
2372    (set (match_dup:TI 0)
2373         (ashift:TI (match_dup:TI 0)
2374                    (match_dup:SI 4)))]
2375   {
2376     HOST_WIDE_INT val = INTVAL(operands[2]);
2377     operands[3] = GEN_INT (val&7);
2378     operands[4] = GEN_INT (val&-8);
2379   }
2380   [(set_attr "type" "shuf,shuf")])
2382 (define_insn_and_split "ashlti3_reg"
2383   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2384         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r")
2385                    (match_operand:SI 2 "spu_reg_operand" "r")))
2386    (clobber (match_operand:TI 3 "spu_reg_operand" "=&r"))]
2387   ""
2388   "#"
2389   ""
2390   [(set (match_dup:TI 3)
2391         (ashift:TI (match_dup:TI 1)
2392                    (and:SI (match_dup:SI 2)
2393                            (const_int 7))))
2394    (set (match_dup:TI 0)
2395         (ashift:TI (match_dup:TI 3)
2396                    (and:SI (match_dup:SI 2)
2397                            (const_int -8))))]
2398   "")
2400 (define_insn "shlqbybi_ti"
2401   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2402         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2403                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2404                            (const_int -8))))]
2405   ""
2406   "@
2407    shlqbybi\t%0,%1,%2
2408    shlqbyi\t%0,%1,%h2"
2409   [(set_attr "type" "shuf,shuf")])
2411 (define_insn "shlqbi_ti"
2412   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2413         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2414                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2415                            (const_int 7))))]
2416   ""
2417   "@
2418    shlqbi\t%0,%1,%2
2419    shlqbii\t%0,%1,%e2"
2420   [(set_attr "type" "shuf,shuf")])
2422 (define_insn "shlqby_ti"
2423   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2424         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2425                    (mult:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2426                             (const_int 8))))]
2427   ""
2428   "@
2429    shlqby\t%0,%1,%2
2430    shlqbyi\t%0,%1,%f2"
2431   [(set_attr "type" "shuf,shuf")])
2434 ;; lshr, vlshr
2436 (define_insn_and_split "<v>lshr<mode>3"
2437   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2438         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2439                        (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))
2440    (clobber (match_scratch:VHSI 3 "=&r,X"))]
2441   ""
2442   "@
2443    #
2444    rot<bh>mi\t%0,%1,-%<umask>2"
2445   "reload_completed && GET_CODE (operands[2]) == REG"
2446   [(set (match_dup:VHSI 3)
2447         (neg:VHSI (match_dup:VHSI 2)))
2448    (set (match_dup:VHSI 0)
2449         (lshiftrt:VHSI (match_dup:VHSI 1)
2450                        (neg:VHSI (match_dup:VHSI 3))))]
2451   ""
2452   [(set_attr "type" "*,fx3")])
2453   
2454 (define_insn "<v>lshr<mode>3_imm"
2455   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
2456         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")
2457                        (match_operand:VHSI 2 "immediate_operand" "W")))]
2458   ""
2459   "rot<bh>mi\t%0,%1,-%<umask>2"
2460   [(set_attr "type" "fx3")])
2462 (define_insn "rotm_<mode>"
2463   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2464         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2465                        (neg:VHSI (match_operand:VHSI 2 "spu_nonmem_operand" "r,W"))))]
2466   ""
2467   "@
2468    rot<bh>m\t%0,%1,%2
2469    rot<bh>mi\t%0,%1,-%<nmask>2"
2470   [(set_attr "type" "fx3")])
2472 (define_insn_and_split "lshr<mode>3"
2473   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r,r")
2474         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r,r")
2475                       (match_operand:SI 2 "spu_nonmem_operand" "r,O,P")))]
2476   ""
2477   "@
2478    #
2479    rotqmbyi\t%0,%1,-%h2
2480    rotqmbii\t%0,%1,-%e2"
2481   "REG_P (operands[2]) || (!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2]))"
2482   [(set (match_dup:DTI 3)
2483         (lshiftrt:DTI (match_dup:DTI 1)
2484                       (match_dup:SI 4)))
2485    (set (match_dup:DTI 0)
2486         (lshiftrt:DTI (match_dup:DTI 3)
2487                       (match_dup:SI 5)))]
2488   {
2489     operands[3] = gen_reg_rtx (<MODE>mode);
2490     if (GET_CODE (operands[2]) == CONST_INT)
2491       {
2492         HOST_WIDE_INT val = INTVAL(operands[2]);
2493         operands[4] = GEN_INT (val & 7);
2494         operands[5] = GEN_INT (val & -8);
2495       }
2496     else
2497       {
2498         rtx t0 = gen_reg_rtx (SImode);
2499         rtx t1 = gen_reg_rtx (SImode);
2500         emit_insn (gen_subsi3(t0, GEN_INT(0), operands[2]));
2501         emit_insn (gen_subsi3(t1, GEN_INT(7), operands[2]));
2502         operands[4] = gen_rtx_AND (SImode, gen_rtx_NEG (SImode, t0), GEN_INT (7));
2503         operands[5] = gen_rtx_AND (SImode, gen_rtx_NEG (SImode, gen_rtx_AND (SImode, t1, GEN_INT (-8))), GEN_INT (-8));
2504       }
2505   }
2506   [(set_attr "type" "*,shuf,shuf")])
2508 (define_expand "shrqbybi_<mode>"
2509   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2510         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2511                       (and:SI (neg:SI (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2512                                               (const_int -8)))
2513                               (const_int -8))))]
2514   ""
2515   {
2516     if (GET_CODE (operands[2]) == CONST_INT)
2517       operands[2] = GEN_INT (7 - INTVAL (operands[2]));
2518     else
2519       {
2520         rtx t0 = gen_reg_rtx (SImode);
2521         emit_insn (gen_subsi3 (t0, GEN_INT (7), operands[2]));
2522         operands[2] = t0;
2523       }
2524   })
2526 (define_insn "rotqmbybi_<mode>"
2527   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2528         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2529                       (and:SI (neg:SI (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2530                                               (const_int -8)))
2531                               (const_int -8))))]
2532   ""
2533   "@
2534    rotqmbybi\t%0,%1,%2
2535    rotqmbyi\t%0,%1,-%H2"
2536   [(set_attr "type" "shuf")])
2538 (define_insn_and_split "shrqbi_<mode>"
2539   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2540         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2541                       (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2542                               (const_int 7))))
2543    (clobber (match_scratch:SI 3 "=&r,X"))]
2544   ""
2545   "#"
2546   "reload_completed"
2547   [(set (match_dup:DTI 0)
2548         (lshiftrt:DTI (match_dup:DTI 1)
2549                       (and:SI (neg:SI (match_dup:SI 3)) (const_int 7))))]
2550   {
2551     if (GET_CODE (operands[2]) == CONST_INT)
2552       operands[3] = GEN_INT (-INTVAL (operands[2]));
2553     else
2554       emit_insn (gen_subsi3 (operands[3], GEN_INT (0), operands[2]));
2555   }
2556   [(set_attr "type" "shuf")])
2558 (define_insn "rotqmbi_<mode>"
2559   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2560         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2561                       (and:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2562                               (const_int 7))))]
2563   ""
2564   "@
2565    rotqmbi\t%0,%1,%2
2566    rotqmbii\t%0,%1,-%E2"
2567   [(set_attr "type" "shuf")])
2569 (define_expand "shrqby_<mode>"
2570   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2571         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2572                       (mult:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2573                                (const_int 8))))]
2574   ""
2575   {
2576     if (GET_CODE (operands[2]) == CONST_INT)
2577       operands[2] = GEN_INT (-INTVAL (operands[2]));
2578     else
2579       {
2580         rtx t0 = gen_reg_rtx (SImode);
2581         emit_insn (gen_subsi3 (t0, GEN_INT (0), operands[2]));
2582         operands[2] = t0;
2583       }
2584   })
2586 (define_insn "rotqmby_<mode>"
2587   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2588         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2589                       (mult:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2590                                (const_int 8))))]
2591   ""
2592   "@
2593    rotqmby\t%0,%1,%2
2594    rotqmbyi\t%0,%1,-%F2"
2595   [(set_attr "type" "shuf")])
2598 ;; ashr, vashr
2600 (define_insn_and_split "<v>ashr<mode>3"
2601   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2602         (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2603                        (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))
2604    (clobber (match_scratch:VHSI 3 "=&r,X"))]
2605   ""
2606   "@
2607    #
2608    rotma<bh>i\t%0,%1,-%<umask>2"
2609   "reload_completed && GET_CODE (operands[2]) == REG"
2610   [(set (match_dup:VHSI 3)
2611         (neg:VHSI (match_dup:VHSI 2)))
2612    (set (match_dup:VHSI 0)
2613         (ashiftrt:VHSI (match_dup:VHSI 1)
2614                        (neg:VHSI (match_dup:VHSI 3))))]
2615   ""
2616   [(set_attr "type" "*,fx3")])
2617   
2618 (define_insn "<v>ashr<mode>3_imm"
2619   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
2620         (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")
2621                        (match_operand:VHSI 2 "immediate_operand" "W")))]
2622   ""
2623   "rotma<bh>i\t%0,%1,-%<umask>2"
2624   [(set_attr "type" "fx3")])
2625   
2627 (define_insn "rotma_<mode>"
2628   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2629         (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2630                        (neg:VHSI (match_operand:VHSI 2 "spu_nonmem_operand" "r,W"))))]
2631   ""
2632   "@
2633    rotma<bh>\t%0,%1,%2
2634    rotma<bh>i\t%0,%1,-%<nmask>2"
2635   [(set_attr "type" "fx3")])
2637 (define_insn_and_split "ashrdi3"
2638   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2639         (ashiftrt:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2640                      (match_operand:SI 2 "spu_nonmem_operand" "r,I")))
2641    (clobber (match_scratch:TI 3 "=&r,&r"))
2642    (clobber (match_scratch:TI 4 "=&r,&r"))
2643    (clobber (match_scratch:SI 5 "=&r,&r"))]
2644   ""
2645   "#"
2646   "reload_completed"
2647   [(set (match_dup:DI 0)
2648         (ashiftrt:DI (match_dup:DI 1)
2649                      (match_dup:SI 2)))]
2650   {
2651     rtx op0 = gen_rtx_REG (TImode, REGNO (operands[0]));
2652     rtx op0v = gen_rtx_REG (V4SImode, REGNO (op0));
2653     rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
2654     rtx op1s = gen_rtx_REG (SImode, REGNO (op1));
2655     rtx op2 = operands[2];
2656     rtx op3 = operands[3];
2657     rtx op4 = operands[4];
2658     rtx op5 = operands[5];
2660     if (GET_CODE (op2) == CONST_INT && INTVAL (op2) >= 63)
2661       {
2662         rtx op0s = gen_rtx_REG (SImode, REGNO (op0));
2663         emit_insn (gen_ashrsi3 (op0s, op1s, GEN_INT (32)));
2664         emit_insn (gen_spu_fsm (op0v, op0s));
2665       }
2666     else if (GET_CODE (op2) == CONST_INT && INTVAL (op2) >= 32)
2667       {
2668         rtx op0d = gen_rtx_REG (V2DImode, REGNO (op0));
2669         HOST_WIDE_INT val = INTVAL (op2);
2670         emit_insn (gen_lshrti3 (op0, op1, GEN_INT (32)));
2671         emit_insn (gen_spu_xswd (op0d, op0v));
2672         if (val > 32)
2673           emit_insn (gen_vashrv4si3 (op0v, op0v, spu_const (V4SImode, val - 32)));
2674       }
2675     else
2676       {
2677         rtx op3v = gen_rtx_REG (V4SImode, REGNO (op3));
2678         unsigned char arr[16] = {
2679           0xff, 0xff, 0xff, 0xff,
2680           0xff, 0xff, 0xff, 0xff,
2681           0x00, 0x00, 0x00, 0x00,
2682           0x00, 0x00, 0x00, 0x00
2683         };
2685         emit_insn (gen_ashrsi3 (op5, op1s, GEN_INT (31)));
2686         emit_move_insn (op4, array_to_constant (TImode, arr));
2687         emit_insn (gen_spu_fsm (op3v, op5));
2689         if (GET_CODE (operands[2]) == REG)
2690           {
2691             emit_insn (gen_selb (op4, op3, op1, op4));
2692             emit_insn (gen_negsi2 (op5, op2));
2693             emit_insn (gen_rotqbybi_ti (op0, op4, op5));
2694             emit_insn (gen_rotqbi_ti (op0, op0, op5));
2695           }
2696         else
2697           {
2698             HOST_WIDE_INT val = -INTVAL (op2);
2699             emit_insn (gen_selb (op0, op3, op1, op4));
2700             if ((val - 7) / 8)
2701               emit_insn (gen_rotqby_ti (op0, op0, GEN_INT ((val - 7) / 8)));
2702             if (val % 8)
2703               emit_insn (gen_rotqbi_ti (op0, op0, GEN_INT (val % 8)));
2704           }
2705       }
2706     DONE;
2707   })
2710 (define_insn_and_split "ashrti3"
2711   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2712         (ashiftrt:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2713                      (match_operand:SI 2 "spu_nonmem_operand" "r,i")))]
2714   ""
2715   "#"
2716   ""
2717   [(set (match_dup:TI 0)
2718         (ashiftrt:TI (match_dup:TI 1)
2719                      (match_dup:SI 2)))]
2720   {
2721     rtx sign_shift = gen_reg_rtx (SImode);
2722     rtx sign_mask = gen_reg_rtx (TImode);
2723     rtx sign_mask_v4si = gen_rtx_SUBREG (V4SImode, sign_mask, 0);
2724     rtx op1_v4si = spu_gen_subreg (V4SImode, operands[1]);
2725     rtx t = gen_reg_rtx (TImode);
2726     emit_insn (gen_subsi3 (sign_shift, GEN_INT (128), force_reg (SImode, operands[2])));
2727     emit_insn (gen_vashrv4si3 (sign_mask_v4si, op1_v4si, spu_const (V4SImode, 31)));
2728     emit_insn (gen_fsm_ti (sign_mask, sign_mask));
2729     emit_insn (gen_ashlti3 (sign_mask, sign_mask, sign_shift));
2730     emit_insn (gen_lshrti3 (t, operands[1], operands[2]));
2731     emit_insn (gen_iorti3 (operands[0], t, sign_mask));
2732     DONE;
2733   })
2735 ;; fsm is used after rotam to replicate the sign across the whole register.
2736 (define_insn "fsm_ti"
2737   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2738         (unspec:TI [(match_operand:TI 1 "spu_reg_operand" "r")] UNSPEC_FSM))]
2739   ""
2740   "fsm\t%0,%1"
2741   [(set_attr "type" "shuf")])
2744 ;; vrotl, rotl
2746 (define_insn "<v>rotl<mode>3"
2747   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2748         (rotate:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2749                      (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))]
2750   ""
2751   "@
2752   rot<bh>\t%0,%1,%2
2753   rot<bh>i\t%0,%1,%<umask>2"
2754   [(set_attr "type" "fx3")])
2756 (define_insn "rotlti3"
2757   [(set (match_operand:TI 0 "spu_reg_operand" "=&r,r,r,r")
2758         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r,r,r")
2759                    (match_operand:SI 2 "spu_nonmem_operand" "r,O,P,I")))]
2760   ""
2761   "@
2762   rotqbybi\t%0,%1,%2\;rotqbi\t%0,%0,%2
2763   rotqbyi\t%0,%1,%h2
2764   rotqbii\t%0,%1,%e2
2765   rotqbyi\t%0,%1,%h2\;rotqbii\t%0,%0,%e2"
2766   [(set_attr "length" "8,4,4,8")
2767    (set_attr "type" "multi1,shuf,shuf,multi1")])
2769 (define_insn "rotqbybi_ti"
2770   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2771         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2772                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2773                            (const_int -8))))]
2774   ""
2775   "@
2776   rotqbybi\t%0,%1,%2
2777   rotqbyi\t%0,%1,%h2"
2778   [(set_attr "type" "shuf,shuf")])
2780 (define_insn "rotqby_ti"
2781   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2782         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2783                    (mult:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2784                             (const_int 8))))]
2785   ""
2786   "@
2787   rotqby\t%0,%1,%2
2788   rotqbyi\t%0,%1,%f2"
2789   [(set_attr "type" "shuf,shuf")])
2791 (define_insn "rotqbi_ti"
2792   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2793         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2794                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2795                            (const_int 7))))]
2796   ""
2797   "@
2798   rotqbi\t%0,%1,%2
2799   rotqbii\t%0,%1,%e2"
2800   [(set_attr "type" "shuf,shuf")])
2803 ;; struct extract/insert
2804 ;; We handle mem's because GCC will generate invalid SUBREG's
2805 ;; and inefficient code.
2807 (define_expand "extv"
2808   [(set (match_operand:TI 0 "register_operand" "")
2809         (sign_extract:TI (match_operand 1 "nonimmediate_operand" "")
2810                          (match_operand:SI 2 "const_int_operand" "")
2811                          (match_operand:SI 3 "const_int_operand" "")))]
2812   ""
2813   {
2814     spu_expand_extv (operands, 0);
2815     DONE;
2816   })
2818 (define_expand "extzv"
2819   [(set (match_operand:TI 0 "register_operand" "")
2820         (zero_extract:TI (match_operand 1 "nonimmediate_operand" "")
2821                          (match_operand:SI 2 "const_int_operand" "")
2822                          (match_operand:SI 3 "const_int_operand" "")))]
2823   ""
2824   {
2825     spu_expand_extv (operands, 1);
2826     DONE;
2827   })
2829 (define_expand "insv"
2830   [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2831                       (match_operand:SI 1 "const_int_operand" "")
2832                       (match_operand:SI 2 "const_int_operand" ""))
2833         (match_operand 3 "nonmemory_operand" ""))]
2834   ""
2835   { spu_expand_insv(operands); DONE; })
2837 ;; Simplify a number of patterns that get generated by extv, extzv,
2838 ;; insv, and loads.
2839 (define_insn_and_split "trunc_shr_ti<mode>"
2840   [(set (match_operand:QHSI 0 "spu_reg_operand" "=r")
2841         (truncate:QHSI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "0")
2842                                                                 (const_int 96)])))]
2843   ""
2844   "#"
2845   "reload_completed"
2846   [(const_int 0)]
2847   {
2848     spu_split_convert (operands);
2849     DONE;
2850   }
2851   [(set_attr "type" "convert")
2852    (set_attr "length" "0")])
2854 (define_insn_and_split "trunc_shr_tidi"
2855   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
2856         (truncate:DI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "0")
2857                                                               (const_int 64)])))]
2858   ""
2859   "#"
2860   "reload_completed"
2861   [(const_int 0)]
2862   {
2863     spu_split_convert (operands);
2864     DONE;
2865   }
2866   [(set_attr "type" "convert")
2867    (set_attr "length" "0")])
2869 (define_insn_and_split "shl_ext_<mode>ti"
2870   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2871         (ashift:TI (match_operator:TI 2 "extend_operator" [(match_operand:QHSI 1 "spu_reg_operand" "0")])
2872                    (const_int 96)))]
2873   ""
2874   "#"
2875   "reload_completed"
2876   [(const_int 0)]
2877   {
2878     spu_split_convert (operands);
2879     DONE;
2880   }
2881   [(set_attr "type" "convert")
2882    (set_attr "length" "0")])
2884 (define_insn_and_split "shl_ext_diti"
2885   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2886         (ashift:TI (match_operator:TI 2 "extend_operator" [(match_operand:DI 1 "spu_reg_operand" "0")])
2887                    (const_int 64)))]
2888   ""
2889   "#"
2890   "reload_completed"
2891   [(const_int 0)]
2892   {
2893     spu_split_convert (operands);
2894     DONE;
2895   }
2896   [(set_attr "type" "convert")
2897    (set_attr "length" "0")])
2899 (define_insn "sext_trunc_lshr_tiqisi"
2900   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2901         (sign_extend:SI (truncate:QI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
2902                                                                               (const_int 120)]))))]
2903   ""
2904   "rotmai\t%0,%1,-24"
2905   [(set_attr "type" "fx3")])
2907 (define_insn "zext_trunc_lshr_tiqisi"
2908   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2909         (zero_extend:SI (truncate:QI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
2910                                                                               (const_int 120)]))))]
2911   ""
2912   "rotmi\t%0,%1,-24"
2913   [(set_attr "type" "fx3")])
2915 (define_insn "sext_trunc_lshr_tihisi"
2916   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2917         (sign_extend:SI (truncate:HI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
2918                                                                               (const_int 112)]))))]
2919   ""
2920   "rotmai\t%0,%1,-16"
2921   [(set_attr "type" "fx3")])
2923 (define_insn "zext_trunc_lshr_tihisi"
2924   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2925         (zero_extend:SI (truncate:HI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
2926                                                                               (const_int 112)]))))]
2927   ""
2928   "rotmi\t%0,%1,-16"
2929   [(set_attr "type" "fx3")])
2932 ;; String/block move insn.
2933 ;; Argument 0 is the destination
2934 ;; Argument 1 is the source
2935 ;; Argument 2 is the length
2936 ;; Argument 3 is the alignment
2938 (define_expand "movstrsi"
2939   [(parallel [(set (match_operand:BLK 0 "" "")
2940                    (match_operand:BLK 1 "" ""))
2941               (use (match_operand:SI 2 "" ""))
2942               (use (match_operand:SI 3 "" ""))])]
2943   ""
2944   "
2945   {
2946     if (spu_expand_block_move (operands))
2947       DONE;
2948     else
2949       FAIL;
2950   }")
2953 ;; jump
2955 (define_insn "indirect_jump"
2956   [(set (pc) (match_operand:SI 0 "spu_reg_operand" "r"))]
2957   ""
2958   "bi\t%0"
2959   [(set_attr "type" "br")])
2961 (define_insn "jump"
2962   [(set (pc)
2963         (label_ref (match_operand 0 "" "")))]
2964   ""
2965   "br\t%0"
2966   [(set_attr "type" "br")])
2969 ;; return
2971 ;; This will be used for leaf functions, that don't save any regs and
2972 ;; don't have locals on stack, maybe... that is for functions that
2973 ;; don't change $sp and don't need to save $lr. 
2974 (define_expand "return"
2975     [(return)]
2976   "direct_return()"
2977   "")
2979 ;; used in spu_expand_epilogue to generate return from a function and
2980 ;; explicitly set use of $lr.
2982 (define_insn "_return"
2983   [(return)]
2984   ""
2985   "bi\t$lr"
2986   [(set_attr "type" "br")])
2990 ;; ceq
2992 (define_insn "ceq_<mode>"
2993   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
2994         (eq:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
2995                  (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
2996   ""
2997   "@
2998   ceq<bh>\t%0,%1,%2
2999   ceq<bh>i\t%0,%1,%2")
3001 (define_insn_and_split "ceq_di"
3002   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3003         (eq:SI (match_operand:DI 1 "spu_reg_operand" "r")
3004                (match_operand:DI 2 "spu_reg_operand" "r")))]
3005   ""
3006   "#"
3007   "reload_completed"
3008   [(set (match_dup:SI 0)
3009         (eq:SI (match_dup:DI 1)
3010                (match_dup:DI 2)))]
3011   {
3012     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
3013     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
3014     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
3015     emit_insn (gen_ceq_v4si (op0, op1, op2));
3016     emit_insn (gen_spu_gb (op0, op0));
3017     emit_insn (gen_cgt_si (operands[0], operands[0], GEN_INT (11)));
3018     DONE;
3019   })
3022 ;; We provide the TI compares for completeness and because some parts of
3023 ;; gcc/libgcc use them, even though user code might never see it.
3024 (define_insn "ceq_ti"
3025   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3026         (eq:SI (match_operand:TI 1 "spu_reg_operand" "r")
3027                (match_operand:TI 2 "spu_reg_operand" "r")))]
3028   ""
3029   "ceq\t%0,%1,%2\;gb\t%0,%0\;ceqi\t%0,%0,15"
3030   [(set_attr "type" "multi0")
3031    (set_attr "length" "12")])
3033 (define_insn "ceq_<mode>"
3034   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
3035         (eq:<F2I> (match_operand:VSF 1 "spu_reg_operand" "r")
3036                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
3037   ""
3038   "fceq\t%0,%1,%2")
3040 (define_insn "cmeq_<mode>"
3041   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
3042         (eq:<F2I> (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "r"))
3043                   (abs:VSF (match_operand:VSF 2 "spu_reg_operand" "r"))))]
3044   ""
3045   "fcmeq\t%0,%1,%2")
3047 ;; These implementations will ignore checking of NaN or INF if
3048 ;; compiled with option -ffinite-math-only.
3049 (define_expand "ceq_df"
3050   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3051         (eq:SI (match_operand:DF 1 "spu_reg_operand" "r")
3052                (match_operand:DF 2 "const_zero_operand" "i")))]
3053   ""
3055   if (spu_arch == PROCESSOR_CELL)
3056       {
3057         rtx ra = gen_reg_rtx (V4SImode);
3058         rtx rb = gen_reg_rtx (V4SImode);
3059         rtx temp = gen_reg_rtx (TImode);
3060         rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3061         rtx temp2 = gen_reg_rtx (V4SImode);
3062         rtx biteq = gen_reg_rtx (V4SImode);
3063         rtx ahi_inf = gen_reg_rtx (V4SImode);
3064         rtx a_nan = gen_reg_rtx (V4SImode);
3065         rtx a_abs = gen_reg_rtx (V4SImode);
3066         rtx b_abs = gen_reg_rtx (V4SImode);
3067         rtx iszero = gen_reg_rtx (V4SImode);
3068         rtx sign_mask = gen_reg_rtx (V4SImode);
3069         rtx nan_mask = gen_reg_rtx (V4SImode);
3070         rtx hihi_promote = gen_reg_rtx (TImode);
3071         rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF,
3072                                                  0x7FFFFFFF, 0xFFFFFFFF);
3074         emit_move_insn (sign_mask, pat);
3075         pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0,
3076                                              0x7FF00000, 0x0);
3077         emit_move_insn (nan_mask, pat);
3078         pat = spu_const_from_ints (TImode, 0x00010203, 0x10111213,
3079                                            0x08090A0B, 0x18191A1B);
3080         emit_move_insn (hihi_promote, pat);
3082         emit_insn (gen_spu_convert (ra, operands[1]));
3083         emit_insn (gen_spu_convert (rb, operands[2]));
3084         emit_insn (gen_ceq_v4si (biteq, ra, rb));
3085         emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, biteq),
3086                                 GEN_INT (4 * 8)));
3087         emit_insn (gen_andv4si3 (biteq, biteq, temp_v4si));
3089         emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3090         emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3091         if (!flag_finite_math_only)
3092           {
3093             emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3094             emit_insn (gen_ceq_v4si (ahi_inf, a_abs, nan_mask));
3095             emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan),
3096                                    GEN_INT (4 * 8)));
3097             emit_insn (gen_andv4si3 (temp2, temp_v4si, ahi_inf));
3098             emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3099           }
3100         emit_insn (gen_iorv4si3 (temp2, a_abs, b_abs));
3101         emit_insn (gen_ceq_v4si (iszero, temp2, CONST0_RTX (V4SImode)));
3102         emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, iszero),
3103                                 GEN_INT (4 * 8)));
3104         emit_insn (gen_andv4si3 (iszero, iszero, temp_v4si));
3105         emit_insn (gen_iorv4si3 (temp2, biteq, iszero));
3106         if (!flag_finite_math_only)
3107           {
3108             emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3109           }
3110         emit_insn (gen_shufb (operands[0], temp2, temp2, hihi_promote));
3111         DONE;
3112       }
3115 (define_insn "ceq_<mode>_celledp"
3116   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
3117         (eq:<DF2I> (match_operand:VDF 1 "spu_reg_operand" "r")
3118                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
3119   "spu_arch == PROCESSOR_CELLEDP"
3120   "dfceq\t%0,%1,%2"
3121   [(set_attr "type" "fpd")])
3123 (define_insn "cmeq_<mode>_celledp"
3124   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
3125         (eq:<DF2I> (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "r"))
3126                    (abs:VDF (match_operand:VDF 2 "spu_reg_operand" "r"))))]
3127   "spu_arch == PROCESSOR_CELLEDP"
3128   "dfcmeq\t%0,%1,%2"
3129   [(set_attr "type" "fpd")])
3131 (define_expand "ceq_v2df"
3132   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3133         (eq:V2DI (match_operand:V2DF 1 "spu_reg_operand" "r")
3134                  (match_operand:V2DF 2 "spu_reg_operand" "r")))]
3135   ""
3137   if (spu_arch == PROCESSOR_CELL)
3138     {
3139       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3140       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
3141       rtx temp = gen_reg_rtx (TImode);
3142       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3143       rtx temp2 = gen_reg_rtx (V4SImode);
3144       rtx biteq = gen_reg_rtx (V4SImode);
3145       rtx ahi_inf = gen_reg_rtx (V4SImode);
3146       rtx a_nan = gen_reg_rtx (V4SImode);
3147       rtx a_abs = gen_reg_rtx (V4SImode);
3148       rtx b_abs = gen_reg_rtx (V4SImode);
3149       rtx iszero = gen_reg_rtx (V4SImode);
3150       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF,
3151                                                0x7FFFFFFF, 0xFFFFFFFF);
3152       rtx sign_mask = gen_reg_rtx (V4SImode);
3153       rtx nan_mask = gen_reg_rtx (V4SImode);
3154       rtx hihi_promote = gen_reg_rtx (TImode);
3156       emit_move_insn (sign_mask, pat);
3157       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3158                                              0x7FF00000, 0x0);
3159       emit_move_insn (nan_mask, pat);
3160       pat = spu_const_from_ints (TImode, 0x00010203, 0x10111213, 
3161                                            0x08090A0B, 0x18191A1B);
3162       emit_move_insn (hihi_promote, pat);
3164       emit_insn (gen_ceq_v4si (biteq, ra, rb));
3165       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, biteq), 
3166                               GEN_INT (4 * 8)));
3167       emit_insn (gen_andv4si3 (biteq, biteq, temp_v4si));
3168       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3169       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3170       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3171       emit_insn (gen_ceq_v4si (ahi_inf, a_abs, nan_mask));
3172       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
3173                               GEN_INT (4 * 8)));
3174       emit_insn (gen_andv4si3 (temp2, temp_v4si, ahi_inf));
3175       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3176       emit_insn (gen_iorv4si3 (temp2, a_abs, b_abs));
3177       emit_insn (gen_ceq_v4si (iszero, temp2, CONST0_RTX (V4SImode)));
3178       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, iszero), 
3179                               GEN_INT (4 * 8)));
3180       emit_insn (gen_andv4si3 (iszero, iszero, temp_v4si));
3181       emit_insn (gen_iorv4si3 (temp2, biteq, iszero));
3182       emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3183       emit_insn (gen_shufb (operands[0], temp2, temp2, hihi_promote));
3184       DONE;
3185   }
3188 (define_expand "cmeq_v2df"
3189   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3190         (eq:V2DI (abs:V2DF (match_operand:V2DF 1 "spu_reg_operand" "r"))
3191                  (abs:V2DF (match_operand:V2DF 2 "spu_reg_operand" "r"))))]
3192   ""
3194   if (spu_arch == PROCESSOR_CELL)
3195     {
3196       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3197       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
3198       rtx temp = gen_reg_rtx (TImode);
3199       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3200       rtx temp2 = gen_reg_rtx (V4SImode);
3201       rtx biteq = gen_reg_rtx (V4SImode);
3202       rtx ahi_inf = gen_reg_rtx (V4SImode);
3203       rtx a_nan = gen_reg_rtx (V4SImode);
3204       rtx a_abs = gen_reg_rtx (V4SImode);
3205       rtx b_abs = gen_reg_rtx (V4SImode);
3207       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3208                                                0x7FFFFFFF, 0xFFFFFFFF);
3209       rtx sign_mask = gen_reg_rtx (V4SImode);
3210       rtx nan_mask = gen_reg_rtx (V4SImode);
3211       rtx hihi_promote = gen_reg_rtx (TImode);
3213       emit_move_insn (sign_mask, pat);
3215       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3216                                            0x7FF00000, 0x0);
3217       emit_move_insn (nan_mask, pat);
3218       pat = spu_const_from_ints (TImode, 0x00010203, 0x10111213, 
3219                                          0x08090A0B, 0x18191A1B);
3220       emit_move_insn (hihi_promote, pat);
3222       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3223       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3224       emit_insn (gen_ceq_v4si (biteq, a_abs, b_abs));
3225       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, biteq), 
3226                                                     GEN_INT (4 * 8)));
3227       emit_insn (gen_andv4si3 (biteq, biteq, temp_v4si));
3228       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3229       emit_insn (gen_ceq_v4si (ahi_inf, a_abs, nan_mask));
3230       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
3231                                                     GEN_INT (4 * 8)));
3232       emit_insn (gen_andv4si3 (temp2, temp_v4si, ahi_inf));
3233       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3234       emit_insn (gen_andc_v4si (temp2, biteq, a_nan));
3235       emit_insn (gen_shufb (operands[0], temp2, temp2, hihi_promote));
3236       DONE;
3237   }
3241 ;; cgt
3243 (define_insn "cgt_<mode>"
3244   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
3245         (gt:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
3246                   (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
3247   ""
3248   "@
3249   cgt<bh>\t%0,%1,%2
3250   cgt<bh>i\t%0,%1,%2")
3252 (define_insn "cgt_di_m1" 
3253   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3254         (gt:SI (match_operand:DI 1 "spu_reg_operand" "r")
3255                (const_int -1)))]
3256   ""
3257   "cgti\t%0,%1,-1")
3259 (define_insn_and_split "cgt_di" 
3260   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3261         (gt:SI (match_operand:DI 1 "spu_reg_operand" "r")
3262                (match_operand:DI 2 "spu_reg_operand" "r")))
3263    (clobber (match_scratch:V4SI 3 "=&r"))
3264    (clobber (match_scratch:V4SI 4 "=&r"))
3265    (clobber (match_scratch:V4SI 5 "=&r"))]
3266   ""
3267   "#"
3268   "reload_completed"
3269   [(set (match_dup:SI 0)
3270         (gt:SI (match_dup:DI 1)
3271                (match_dup:DI 2)))]
3272   {
3273     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
3274     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
3275     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
3276     rtx op3 = operands[3];
3277     rtx op4 = operands[4];
3278     rtx op5 = operands[5];
3279     rtx op3d = gen_rtx_REG (V2DImode, REGNO (operands[3]));
3280     emit_insn (gen_clgt_v4si (op3, op1, op2));
3281     emit_insn (gen_ceq_v4si (op4, op1, op2));
3282     emit_insn (gen_cgt_v4si (op5, op1, op2));
3283     emit_insn (gen_spu_xswd (op3d, op3));
3284     emit_insn (gen_selb (op0, op5, op3, op4));
3285     DONE;
3286   })
3288 (define_insn "cgt_ti_m1" 
3289   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3290         (gt:SI (match_operand:TI 1 "spu_reg_operand" "r")
3291                (const_int -1)))]
3292   ""
3293   "cgti\t%0,%1,-1")
3295 (define_insn "cgt_ti"
3296   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3297         (gt:SI (match_operand:TI 1 "spu_reg_operand" "r")
3298                (match_operand:TI 2 "spu_reg_operand" "r")))
3299    (clobber (match_scratch:V4SI 3 "=&r"))
3300    (clobber (match_scratch:V4SI 4 "=&r"))
3301    (clobber (match_scratch:V4SI 5 "=&r"))]
3302   ""
3303   "clgt\t%4,%1,%2\;\
3304 ceq\t%3,%1,%2\;\
3305 cgt\t%5,%1,%2\;\
3306 shlqbyi\t%0,%4,4\;\
3307 selb\t%0,%4,%0,%3\;\
3308 shlqbyi\t%0,%0,4\;\
3309 selb\t%0,%4,%0,%3\;\
3310 shlqbyi\t%0,%0,4\;\
3311 selb\t%0,%5,%0,%3"
3312   [(set_attr "type" "multi0")
3313    (set_attr "length" "36")])
3315 (define_insn "cgt_<mode>"
3316   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
3317         (gt:<F2I> (match_operand:VSF 1 "spu_reg_operand" "r")
3318                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
3319   ""
3320   "fcgt\t%0,%1,%2")
3322 (define_insn "cmgt_<mode>"
3323   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
3324         (gt:<F2I> (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "r"))
3325                   (abs:VSF (match_operand:VSF 2 "spu_reg_operand" "r"))))]
3326   ""
3327   "fcmgt\t%0,%1,%2")
3329 (define_expand "cgt_df"
3330   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3331         (gt:SI (match_operand:DF 1 "spu_reg_operand" "r")
3332                (match_operand:DF 2 "const_zero_operand" "i")))]
3333   ""
3335   if (spu_arch == PROCESSOR_CELL)
3336     {
3337       rtx ra = gen_reg_rtx (V4SImode);
3338       rtx rb = gen_reg_rtx (V4SImode);
3339       rtx zero = gen_reg_rtx (V4SImode);
3340       rtx temp = gen_reg_rtx (TImode);
3341       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3342       rtx temp2 = gen_reg_rtx (V4SImode);
3343       rtx hi_inf = gen_reg_rtx (V4SImode);
3344       rtx a_nan = gen_reg_rtx (V4SImode);
3345       rtx b_nan = gen_reg_rtx (V4SImode);
3346       rtx a_abs = gen_reg_rtx (V4SImode);
3347       rtx b_abs = gen_reg_rtx (V4SImode);
3348       rtx asel = gen_reg_rtx (V4SImode);
3349       rtx bsel = gen_reg_rtx (V4SImode);
3350       rtx abor = gen_reg_rtx (V4SImode);
3351       rtx bbor = gen_reg_rtx (V4SImode);
3352       rtx gt_hi = gen_reg_rtx (V4SImode);
3353       rtx gt_lo = gen_reg_rtx (V4SImode);
3354       rtx sign_mask = gen_reg_rtx (V4SImode);
3355       rtx nan_mask = gen_reg_rtx (V4SImode);
3356       rtx hi_promote = gen_reg_rtx (TImode);
3357       rtx borrow_shuffle = gen_reg_rtx (TImode);
3359       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF,
3360                                                0x7FFFFFFF, 0xFFFFFFFF);
3361       emit_move_insn (sign_mask, pat);
3362       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0,
3363                                              0x7FF00000, 0x0);
3364       emit_move_insn (nan_mask, pat);
3365       pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203,
3366                                          0x08090A0B, 0x08090A0B);
3367       emit_move_insn (hi_promote, pat);
3368       pat = spu_const_from_ints (TImode, 0x04050607, 0xC0C0C0C0,
3369                                          0x0C0D0E0F, 0xC0C0C0C0);
3370       emit_move_insn (borrow_shuffle, pat);
3372       emit_insn (gen_spu_convert (ra, operands[1]));
3373       emit_insn (gen_spu_convert (rb, operands[2]));
3374       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3375       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3377       if (!flag_finite_math_only)
3378         {
3379           /* check if ra is NaN  */
3380           emit_insn (gen_ceq_v4si (hi_inf, a_abs, nan_mask));
3381           emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3382           emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan),
3383                                   GEN_INT (4 * 8)));
3384           emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3385           emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3386           emit_insn (gen_shufb (a_nan, a_nan, a_nan, hi_promote));
3388           /* check if rb is NaN  */
3389           emit_insn (gen_ceq_v4si (hi_inf, b_abs, nan_mask));
3390           emit_insn (gen_clgt_v4si (b_nan, b_abs, nan_mask));
3391           emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, b_nan),
3392                                   GEN_INT (4 * 8)));
3393           emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3394           emit_insn (gen_iorv4si3 (b_nan, b_nan, temp2));
3395           emit_insn (gen_shufb (b_nan, b_nan, b_nan, hi_promote));
3397           /* check if ra or rb is NaN  */
3398           emit_insn (gen_iorv4si3 (a_nan, a_nan, b_nan));
3399         }
3400       emit_move_insn (zero, CONST0_RTX (V4SImode));
3401       emit_insn (gen_vashrv4si3 (asel, ra, spu_const (V4SImode, 31)));
3402       emit_insn (gen_shufb (asel, asel, asel, hi_promote));
3403       emit_insn (gen_bg_v4si (abor, zero, a_abs));
3404       emit_insn (gen_shufb (abor, abor, abor, borrow_shuffle));
3405       emit_insn (gen_sfx_v4si (abor, zero, a_abs, abor));
3406       emit_insn (gen_selb (abor, a_abs, abor, asel));
3408       emit_insn (gen_vashrv4si3 (bsel, rb, spu_const (V4SImode, 31)));
3409       emit_insn (gen_shufb (bsel, bsel, bsel, hi_promote));
3410       emit_insn (gen_bg_v4si (bbor, zero, b_abs));
3411       emit_insn (gen_shufb (bbor, bbor, bbor, borrow_shuffle));
3412       emit_insn (gen_sfx_v4si (bbor, zero, b_abs, bbor));
3413       emit_insn (gen_selb (bbor, b_abs, bbor, bsel));
3415       emit_insn (gen_cgt_v4si (gt_hi, abor, bbor));
3416       emit_insn (gen_clgt_v4si (gt_lo, abor, bbor));
3417       emit_insn (gen_ceq_v4si (temp2, abor, bbor));
3418       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, gt_lo),
3419                                 GEN_INT (4 * 8)));
3420       emit_insn (gen_andv4si3 (temp2, temp2, temp_v4si));
3421       emit_insn (gen_iorv4si3 (temp2, gt_hi, temp2));
3422       emit_insn (gen_shufb (temp2, temp2, temp2, hi_promote));
3423       if (!flag_finite_math_only)
3424         {
3425           /* correct for NaNs  */
3426           emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3427         }
3428       emit_insn (gen_spu_convert (operands[0], temp2));
3429       DONE;
3430     }
3433 (define_insn "cgt_<mode>_celledp"
3434   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
3435         (gt:<DF2I> (match_operand:VDF 1 "spu_reg_operand" "r")
3436                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
3437   "spu_arch == PROCESSOR_CELLEDP"
3438   "dfcgt\t%0,%1,%2"
3439   [(set_attr "type" "fpd")])
3441 (define_insn "cmgt_<mode>_celledp"
3442   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
3443         (gt:<DF2I> (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "r"))
3444                    (abs:VDF (match_operand:VDF 2 "spu_reg_operand" "r"))))]
3445   "spu_arch == PROCESSOR_CELLEDP"
3446   "dfcmgt\t%0,%1,%2"
3447   [(set_attr "type" "fpd")])
3449 (define_expand "cgt_v2df"
3450   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3451         (gt:V2DI (match_operand:V2DF 1 "spu_reg_operand" "r")
3452                  (match_operand:V2DF 2 "spu_reg_operand" "r")))]
3453   ""
3455   if (spu_arch == PROCESSOR_CELL)
3456     {
3457       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3458       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
3459       rtx zero = gen_reg_rtx (V4SImode);
3460       rtx temp = gen_reg_rtx (TImode);
3461       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3462       rtx temp2 = gen_reg_rtx (V4SImode);
3463       rtx hi_inf = gen_reg_rtx (V4SImode);
3464       rtx a_nan = gen_reg_rtx (V4SImode);
3465       rtx b_nan = gen_reg_rtx (V4SImode);
3466       rtx a_abs = gen_reg_rtx (V4SImode);
3467       rtx b_abs = gen_reg_rtx (V4SImode);
3468       rtx asel = gen_reg_rtx (V4SImode);
3469       rtx bsel = gen_reg_rtx (V4SImode);
3470       rtx abor = gen_reg_rtx (V4SImode);
3471       rtx bbor = gen_reg_rtx (V4SImode);
3472       rtx gt_hi = gen_reg_rtx (V4SImode);
3473       rtx gt_lo = gen_reg_rtx (V4SImode);
3474       rtx sign_mask = gen_reg_rtx (V4SImode);
3475       rtx nan_mask = gen_reg_rtx (V4SImode);
3476       rtx hi_promote = gen_reg_rtx (TImode);
3477       rtx borrow_shuffle = gen_reg_rtx (TImode);
3478       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3479                                                0x7FFFFFFF, 0xFFFFFFFF);
3480       emit_move_insn (sign_mask, pat);
3481       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3482                                            0x7FF00000, 0x0);
3483       emit_move_insn (nan_mask, pat);
3484       pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203, 
3485                                          0x08090A0B, 0x08090A0B);
3486       emit_move_insn (hi_promote, pat);
3487       pat = spu_const_from_ints (TImode, 0x04050607, 0xC0C0C0C0, 
3488                                          0x0C0D0E0F, 0xC0C0C0C0);
3489       emit_move_insn (borrow_shuffle, pat);
3491       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3492       emit_insn (gen_ceq_v4si (hi_inf, a_abs, nan_mask));
3493       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3494       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
3495                                                     GEN_INT (4 * 8)));
3496       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3497       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3498       emit_insn (gen_shufb (a_nan, a_nan, a_nan, hi_promote));
3499       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3500       emit_insn (gen_ceq_v4si (hi_inf, b_abs, nan_mask));
3501       emit_insn (gen_clgt_v4si (b_nan, b_abs, nan_mask));
3502       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, b_nan), 
3503                                                     GEN_INT (4 * 8)));
3504       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3505       emit_insn (gen_iorv4si3 (b_nan, b_nan, temp2));
3506       emit_insn (gen_shufb (b_nan, b_nan, b_nan, hi_promote));
3507       emit_insn (gen_iorv4si3 (a_nan, a_nan, b_nan));
3508       emit_move_insn (zero, CONST0_RTX (V4SImode));
3509       emit_insn (gen_vashrv4si3 (asel, ra, spu_const (V4SImode, 31)));
3510       emit_insn (gen_shufb (asel, asel, asel, hi_promote));
3511       emit_insn (gen_bg_v4si (abor, zero, a_abs));
3512       emit_insn (gen_shufb (abor, abor, abor, borrow_shuffle));
3513       emit_insn (gen_sfx_v4si (abor, zero, a_abs, abor));
3514       emit_insn (gen_selb (abor, a_abs, abor, asel));
3515       emit_insn (gen_vashrv4si3 (bsel, rb, spu_const (V4SImode, 31)));
3516       emit_insn (gen_shufb (bsel, bsel, bsel, hi_promote));
3517       emit_insn (gen_bg_v4si (bbor, zero, b_abs));
3518       emit_insn (gen_shufb (bbor, bbor, bbor, borrow_shuffle));
3519       emit_insn (gen_sfx_v4si (bbor, zero, b_abs, bbor));
3520       emit_insn (gen_selb (bbor, b_abs, bbor, bsel));
3521       emit_insn (gen_cgt_v4si (gt_hi, abor, bbor));
3522       emit_insn (gen_clgt_v4si (gt_lo, abor, bbor));
3523       emit_insn (gen_ceq_v4si (temp2, abor, bbor));
3524       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, gt_lo), 
3525                                                     GEN_INT (4 * 8)));
3526       emit_insn (gen_andv4si3 (temp2, temp2, temp_v4si));
3527       emit_insn (gen_iorv4si3 (temp2, gt_hi, temp2));
3529       emit_insn (gen_shufb (temp2, temp2, temp2, hi_promote));
3530       emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3531       emit_move_insn (operands[0], spu_gen_subreg (V2DImode, temp2));
3532       DONE;
3533     } 
3536 (define_expand "cmgt_v2df"
3537   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3538         (gt:V2DI (abs:V2DF (match_operand:V2DF 1 "spu_reg_operand" "r"))
3539                  (abs:V2DF (match_operand:V2DF 2 "spu_reg_operand" "r"))))]
3540   ""
3542   if (spu_arch == PROCESSOR_CELL)
3543     {
3544       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3545       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
3546       rtx temp = gen_reg_rtx (TImode);
3547       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3548       rtx temp2 = gen_reg_rtx (V4SImode);
3549       rtx hi_inf = gen_reg_rtx (V4SImode);
3550       rtx a_nan = gen_reg_rtx (V4SImode);
3551       rtx b_nan = gen_reg_rtx (V4SImode);
3552       rtx a_abs = gen_reg_rtx (V4SImode);
3553       rtx b_abs = gen_reg_rtx (V4SImode);
3554       rtx gt_hi = gen_reg_rtx (V4SImode);
3555       rtx gt_lo = gen_reg_rtx (V4SImode);
3556       rtx sign_mask = gen_reg_rtx (V4SImode);
3557       rtx nan_mask = gen_reg_rtx (V4SImode);
3558       rtx hi_promote = gen_reg_rtx (TImode);
3559       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3560                                                0x7FFFFFFF, 0xFFFFFFFF);
3561       emit_move_insn (sign_mask, pat);
3562       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3563                                            0x7FF00000, 0x0);
3564       emit_move_insn (nan_mask, pat);
3565       pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203, 
3566                                          0x08090A0B, 0x08090A0B);
3567       emit_move_insn (hi_promote, pat);
3569       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3570       emit_insn (gen_ceq_v4si (hi_inf, a_abs, nan_mask));
3571       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3572       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
3573                                                     GEN_INT (4 * 8)));
3574       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3575       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3576       emit_insn (gen_shufb (a_nan, a_nan, a_nan, hi_promote));
3577       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3578       emit_insn (gen_ceq_v4si (hi_inf, b_abs, nan_mask));
3579       emit_insn (gen_clgt_v4si (b_nan, b_abs, nan_mask));
3580       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, b_nan), 
3581                                                     GEN_INT (4 * 8)));
3582       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3583       emit_insn (gen_iorv4si3 (b_nan, b_nan, temp2));
3584       emit_insn (gen_shufb (b_nan, b_nan, b_nan, hi_promote));
3585       emit_insn (gen_iorv4si3 (a_nan, a_nan, b_nan));
3587       emit_insn (gen_clgt_v4si (gt_hi, a_abs, b_abs));
3588       emit_insn (gen_clgt_v4si (gt_lo, a_abs, b_abs));
3589       emit_insn (gen_ceq_v4si (temp2, a_abs, b_abs));
3590       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, gt_lo), 
3591                                                     GEN_INT (4 * 8)));
3592       emit_insn (gen_andv4si3 (temp2, temp2, temp_v4si));
3593       emit_insn (gen_iorv4si3 (temp2, gt_hi, temp2));
3594       emit_insn (gen_shufb (temp2, temp2, temp2, hi_promote));
3595       emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3596       emit_move_insn (operands[0], spu_gen_subreg (V2DImode, temp2));
3597       DONE;
3598     }
3602 ;; clgt
3604 (define_insn "clgt_<mode>"
3605   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
3606         (gtu:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
3607                    (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
3608   ""
3609   "@
3610   clgt<bh>\t%0,%1,%2
3611   clgt<bh>i\t%0,%1,%2")
3613 (define_insn_and_split "clgt_di" 
3614   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3615         (gtu:SI (match_operand:DI 1 "spu_reg_operand" "r")
3616                 (match_operand:DI 2 "spu_reg_operand" "r")))
3617    (clobber (match_scratch:V4SI 3 "=&r"))
3618    (clobber (match_scratch:V4SI 4 "=&r"))
3619    (clobber (match_scratch:V4SI 5 "=&r"))]
3620   ""
3621   "#"
3622   "reload_completed"
3623   [(set (match_dup:SI 0)
3624         (gtu:SI (match_dup:DI 1)
3625                 (match_dup:DI 2)))]
3626   {
3627     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
3628     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
3629     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
3630     rtx op3 = operands[3];
3631     rtx op4 = operands[4];
3632     rtx op5 = operands[5];
3633     rtx op5d = gen_rtx_REG (V2DImode, REGNO (operands[5]));
3634     emit_insn (gen_clgt_v4si (op3, op1, op2));
3635     emit_insn (gen_ceq_v4si (op4, op1, op2));
3636     emit_insn (gen_spu_xswd (op5d, op3));
3637     emit_insn (gen_selb (op0, op3, op5, op4));
3638     DONE;
3639   })
3641 (define_insn "clgt_ti"
3642   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3643         (gtu:SI (match_operand:TI 1 "spu_reg_operand" "r")
3644                (match_operand:TI 2 "spu_reg_operand" "r")))
3645    (clobber (match_scratch:V4SI 3 "=&r"))
3646    (clobber (match_scratch:V4SI 4 "=&r"))]
3647   ""
3648   "ceq\t%3,%1,%2\;\
3649 clgt\t%4,%1,%2\;\
3650 shlqbyi\t%0,%4,4\;\
3651 selb\t%0,%4,%0,%3\;\
3652 shlqbyi\t%0,%0,4\;\
3653 selb\t%0,%4,%0,%3\;\
3654 shlqbyi\t%0,%0,4\;\
3655 selb\t%0,%4,%0,%3"
3656   [(set_attr "type" "multi0")
3657    (set_attr "length" "32")])
3660 ;; dftsv
3661 (define_insn "dftsv_celledp"
3662   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3663         (unspec:V2DI [(match_operand:V2DF 1 "spu_reg_operand"  "r")
3664                       (match_operand:SI   2 "const_int_operand" "i")]
3665                       UNSPEC_DFTSV))]
3666   "spu_arch == PROCESSOR_CELLEDP"
3667   "dftsv\t%0,%1,%2"
3668   [(set_attr "type" "fpd")])
3670 (define_expand "dftsv"
3671   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3672         (unspec:V2DI [(match_operand:V2DF 1 "spu_reg_operand" "r")
3673                       (match_operand:SI   2 "const_int_operand" "i")]
3674                       UNSPEC_DFTSV))]
3675   ""
3677   if (spu_arch == PROCESSOR_CELL)
3678     {
3679       rtx result = gen_reg_rtx (V4SImode);
3680       emit_move_insn (result, CONST0_RTX (V4SImode));
3682       if (INTVAL (operands[2]))
3683         {
3684           rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3685           rtx abs = gen_reg_rtx (V4SImode);
3686           rtx sign = gen_reg_rtx (V4SImode);
3687           rtx temp = gen_reg_rtx (TImode);
3688           rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3689           rtx temp2 = gen_reg_rtx (V4SImode);
3690           rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3691                                                    0x7FFFFFFF, 0xFFFFFFFF);
3692           rtx sign_mask = gen_reg_rtx (V4SImode);
3693           rtx hi_promote = gen_reg_rtx (TImode);
3694           emit_move_insn (sign_mask, pat);
3695           pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203, 
3696                                              0x08090A0B, 0x08090A0B);
3697           emit_move_insn (hi_promote, pat);
3699           emit_insn (gen_vashrv4si3 (sign, ra, spu_const (V4SImode, 31)));
3700           emit_insn (gen_shufb (sign, sign, sign, hi_promote));
3701           emit_insn (gen_andv4si3 (abs, ra, sign_mask));
3703           /* NaN  or +inf or -inf */
3704           if (INTVAL (operands[2]) & 0x70)
3705             {
3706               rtx nan_mask = gen_reg_rtx (V4SImode);
3707               rtx isinf = gen_reg_rtx (V4SImode);
3708               pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3709                                                    0x7FF00000, 0x0);
3710               emit_move_insn (nan_mask, pat);
3711               emit_insn (gen_ceq_v4si (isinf, abs, nan_mask));
3713               /* NaN  */
3714               if (INTVAL (operands[2]) & 0x40)
3715                 {
3716                   rtx isnan = gen_reg_rtx (V4SImode);
3717                   emit_insn (gen_clgt_v4si (isnan, abs, nan_mask));
3718                   emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, isnan), 
3719                                                              GEN_INT (4 * 8)));
3720                   emit_insn (gen_andv4si3 (temp2, temp_v4si, isinf));
3721                   emit_insn (gen_iorv4si3 (isnan, isnan, temp2));
3722                   emit_insn (gen_shufb (isnan, isnan, isnan, hi_promote));
3723                   emit_insn (gen_iorv4si3 (result, result, isnan));
3724                 }
3725               /* +inf or -inf  */
3726               if (INTVAL (operands[2]) & 0x30)
3727                 {
3728                   emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, isinf), 
3729                                                              GEN_INT (4 * 8)));
3730                   emit_insn (gen_andv4si3 (isinf, isinf, temp_v4si));
3731                   emit_insn (gen_shufb (isinf, isinf, isinf, hi_promote));
3733                   /* +inf  */
3734                   if (INTVAL (operands[2]) & 0x20)
3735                     {
3736                       emit_insn (gen_andc_v4si (temp2, isinf, sign));
3737                       emit_insn (gen_iorv4si3 (result, result, temp2));
3738                     }
3739                   /* -inf  */
3740                   if (INTVAL (operands[2]) & 0x10)
3741                     {
3742                       emit_insn (gen_andv4si3 (temp2, isinf, sign));
3743                       emit_insn (gen_iorv4si3 (result, result, temp2));
3744                     }
3745                 }
3746             }
3748           /* 0 or denorm  */
3749           if (INTVAL (operands[2]) & 0xF)
3750             {
3751               rtx iszero = gen_reg_rtx (V4SImode);
3752               emit_insn (gen_ceq_v4si (iszero, abs, CONST0_RTX (V4SImode)));
3753               emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, iszero), 
3754                                                           GEN_INT (4 * 8)));
3755               emit_insn (gen_andv4si3 (iszero, iszero, temp_v4si));
3757               /* denorm  */
3758               if (INTVAL (operands[2]) & 0x3)
3759                 {
3760                   rtx isdenorm = gen_reg_rtx (V4SImode);
3761                   rtx denorm_mask = gen_reg_rtx (V4SImode);
3762                   emit_move_insn (denorm_mask, spu_const (V4SImode, 0xFFFFF));
3763                   emit_insn (gen_clgt_v4si (isdenorm, abs, denorm_mask));
3764                   emit_insn (gen_nor_v4si (isdenorm, isdenorm, iszero));
3765                   emit_insn (gen_shufb (isdenorm, isdenorm, 
3766                                         isdenorm, hi_promote));
3767                   /* +denorm  */
3768                   if (INTVAL (operands[2]) & 0x2)
3769                     {
3770                       emit_insn (gen_andc_v4si (temp2, isdenorm, sign));
3771                       emit_insn (gen_iorv4si3 (result, result, temp2));
3772                     }
3773                   /* -denorm  */
3774                   if (INTVAL (operands[2]) & 0x1)
3775                     {
3776                       emit_insn (gen_andv4si3 (temp2, isdenorm, sign));
3777                       emit_insn (gen_iorv4si3 (result, result, temp2));
3778                     }
3779                 }
3781               /* 0  */
3782               if (INTVAL (operands[2]) & 0xC)
3783                 {
3784                   emit_insn (gen_shufb (iszero, iszero, iszero, hi_promote));
3785                   /* +0  */
3786                   if (INTVAL (operands[2]) & 0x8)
3787                     {
3788                       emit_insn (gen_andc_v4si (temp2, iszero, sign));
3789                       emit_insn (gen_iorv4si3 (result, result, temp2));
3790                     }
3791                   /* -0  */
3792                   if (INTVAL (operands[2]) & 0x4)
3793                     {
3794                       emit_insn (gen_andv4si3 (temp2, iszero, sign));
3795                       emit_insn (gen_iorv4si3 (result, result, temp2));
3796                     }
3797                 }
3798              }
3799           }
3800       emit_move_insn (operands[0], spu_gen_subreg (V2DImode, result));
3801       DONE;
3802     }
3806 ;; branches
3808 (define_insn ""
3809   [(set (pc)
3810         (if_then_else (match_operator 1 "branch_comparison_operator"
3811                                       [(match_operand 2
3812                                                       "spu_reg_operand" "r")
3813                                        (const_int 0)])
3814                       (label_ref (match_operand 0 "" ""))
3815                       (pc)))]
3816   ""
3817   "br%b2%b1z\t%2,%0"
3818   [(set_attr "type" "br")])
3820 (define_insn ""
3821   [(set (pc)
3822         (if_then_else (match_operator 0 "branch_comparison_operator"
3823                                       [(match_operand 1
3824                                                       "spu_reg_operand" "r")
3825                                        (const_int 0)])
3826                       (return)
3827                       (pc)))]
3828   "direct_return ()"
3829   "bi%b1%b0z\t%1,$lr"
3830   [(set_attr "type" "br")])
3832 (define_insn ""
3833   [(set (pc)
3834         (if_then_else (match_operator 1 "branch_comparison_operator"
3835                                       [(match_operand 2
3836                                                       "spu_reg_operand" "r")
3837                                        (const_int 0)])
3838                       (pc)
3839                       (label_ref (match_operand 0 "" ""))))]
3840   ""
3841   "br%b2%b1z\t%2,%0"
3842   [(set_attr "type" "br")])
3844 (define_insn ""
3845   [(set (pc)
3846         (if_then_else (match_operator 0 "branch_comparison_operator"
3847                                       [(match_operand 1
3848                                                       "spu_reg_operand" "r")
3849                                        (const_int 0)])
3850                       (pc)
3851                       (return)))]
3852   "direct_return ()"
3853   "bi%b1%b0z\t%1,$lr"
3854   [(set_attr "type" "br")])
3857 ;; vector conditional compare patterns
3858 (define_expand "vcond<mode>"
3859   [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
3860         (if_then_else:VCMP
3861           (match_operator 3 "comparison_operator"
3862             [(match_operand:VCMP 4 "spu_reg_operand" "r")
3863              (match_operand:VCMP 5 "spu_reg_operand" "r")])
3864           (match_operand:VCMP 1 "spu_reg_operand" "r")
3865           (match_operand:VCMP 2 "spu_reg_operand" "r")))]
3866   ""
3867   {
3868     if (spu_emit_vector_cond_expr (operands[0], operands[1], operands[2],
3869                                    operands[3], operands[4], operands[5]))
3870     DONE;
3871     else
3872     FAIL;
3873   })
3875 (define_expand "vcondu<mode>"
3876   [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
3877         (if_then_else:VCMPU
3878           (match_operator 3 "comparison_operator"
3879             [(match_operand:VCMPU 4 "spu_reg_operand" "r")
3880              (match_operand:VCMPU 5 "spu_reg_operand" "r")])
3881           (match_operand:VCMPU 1 "spu_reg_operand" "r")
3882           (match_operand:VCMPU 2 "spu_reg_operand" "r")))]
3883   ""
3884   {
3885     if (spu_emit_vector_cond_expr (operands[0], operands[1], operands[2],
3886                                    operands[3], operands[4], operands[5]))
3887     DONE;
3888     else
3889     FAIL;
3890   })
3891         
3893 ;; branch on condition
3895 (define_expand "cbranch<mode>4"
3896   [(use (match_operator 0 "ordered_comparison_operator"
3897          [(match_operand:VQHSI 1 "spu_reg_operand" "")
3898           (match_operand:VQHSI 2 "spu_nonmem_operand" "")]))
3899    (use (match_operand 3 ""))]
3900   ""
3901   { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
3903 (define_expand "cbranch<mode>4"
3904   [(use (match_operator 0 "ordered_comparison_operator"
3905          [(match_operand:DTI 1 "spu_reg_operand" "")
3906           (match_operand:DTI 2 "spu_reg_operand" "")]))
3907    (use (match_operand 3 ""))]
3908   ""
3909   { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
3911 (define_expand "cbranch<mode>4"
3912   [(use (match_operator 0 "ordered_comparison_operator"
3913          [(match_operand:VSF 1 "spu_reg_operand" "")
3914           (match_operand:VSF 2 "spu_reg_operand" "")]))
3915    (use (match_operand 3 ""))]
3916   ""
3917   { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
3919 (define_expand "cbranchdf4"
3920   [(use (match_operator 0 "ordered_comparison_operator"
3921          [(match_operand:DF 1 "spu_reg_operand" "")
3922           (match_operand:DF 2 "spu_reg_operand" "")]))
3923    (use (match_operand 3 ""))]
3924   ""
3925   { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
3928 ;; set on condition
3930 (define_expand "cstore<mode>4"
3931   [(use (match_operator 1 "ordered_comparison_operator"
3932          [(match_operand:VQHSI 2 "spu_reg_operand" "")
3933           (match_operand:VQHSI 3 "spu_nonmem_operand" "")]))
3934    (clobber (match_operand:SI 0 "spu_reg_operand"))]
3935   ""
3936   { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
3938 (define_expand "cstore<mode>4"
3939   [(use (match_operator 1 "ordered_comparison_operator"
3940          [(match_operand:DTI 2 "spu_reg_operand" "")
3941           (match_operand:DTI 3 "spu_reg_operand" "")]))
3942    (clobber (match_operand:SI 0 "spu_reg_operand"))]
3943   ""
3944   { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
3946 (define_expand "cstore<mode>4"
3947   [(use (match_operator 1 "ordered_comparison_operator"
3948          [(match_operand:VSF 2 "spu_reg_operand" "")
3949           (match_operand:VSF 3 "spu_reg_operand" "")]))
3950    (clobber (match_operand:SI 0 "spu_reg_operand"))]
3951   ""
3952   { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
3954 (define_expand "cstoredf4"
3955   [(use (match_operator 1 "ordered_comparison_operator"
3956          [(match_operand:DF 2 "spu_reg_operand" "")
3957           (match_operand:DF 3 "spu_reg_operand" "")]))
3958    (clobber (match_operand:SI 0 "spu_reg_operand"))]
3959   ""
3960   { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
3963 ;; conditional move
3965 ;; Define this first one so HAVE_conditional_move is defined.
3966 (define_insn "movcc_dummy"
3967   [(set (match_operand 0 "" "")
3968        (if_then_else (match_operand 1 "" "")
3969                      (match_operand 2 "" "")
3970                      (match_operand 3 "" "")))]
3971   "!operands[0]"
3972   "")
3974 (define_expand "mov<mode>cc"
3975   [(set (match_operand:ALL 0 "spu_reg_operand" "")
3976         (if_then_else:ALL (match_operand 1 "ordered_comparison_operator" "")
3977                       (match_operand:ALL 2 "spu_reg_operand" "")
3978                       (match_operand:ALL 3 "spu_reg_operand" "")))]
3979   ""
3980   {
3981     spu_emit_branch_or_set(2, operands[1], operands);
3982     DONE;
3983   })
3985 ;; This pattern is used when the result of a compare is not large
3986 ;; enough to use in a selb when expanding conditional moves.
3987 (define_expand "extend_compare"
3988   [(set (match_operand 0 "spu_reg_operand" "=r")
3989         (unspec [(match_operand 1 "spu_reg_operand" "r")] UNSPEC_EXTEND_CMP))]
3990   ""
3991   {
3992     emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3993                             gen_rtx_UNSPEC (GET_MODE (operands[0]),
3994                                             gen_rtvec (1, operands[1]),
3995                                             UNSPEC_EXTEND_CMP)));
3996     DONE;
3997   })
3999 (define_insn "extend_compare<mode>"
4000   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
4001         (unspec:ALL [(match_operand 1 "spu_reg_operand" "r")] UNSPEC_EXTEND_CMP))]
4002   "operands"
4003   "fsm\t%0,%1"
4004   [(set_attr "type" "shuf")])
4007 ;; case
4009 ;; operand 0 is index
4010 ;; operand 1 is the minimum bound
4011 ;; operand 2 is the maximum bound - minimum bound + 1
4012 ;; operand 3 is CODE_LABEL for the table;
4013 ;; operand 4 is the CODE_LABEL to go to if index out of range.
4014 (define_expand "casesi"
4015   [(match_operand:SI 0 "spu_reg_operand" "")
4016    (match_operand:SI 1 "immediate_operand" "")
4017    (match_operand:SI 2 "immediate_operand" "")
4018    (match_operand 3 "" "")
4019    (match_operand 4 "" "")]
4020   ""
4021   {
4022     rtx table = gen_reg_rtx (SImode);
4023     rtx index = gen_reg_rtx (SImode);
4024     rtx sindex = gen_reg_rtx (SImode);
4025     rtx addr = gen_reg_rtx (Pmode);
4027     emit_move_insn (table, gen_rtx_LABEL_REF (SImode, operands[3]));
4029     emit_insn (gen_subsi3(index, operands[0], force_reg(SImode, operands[1])));
4030     emit_insn (gen_ashlsi3(sindex, index, GEN_INT (2)));
4031     emit_move_insn (addr, gen_rtx_MEM (SImode,
4032                                        gen_rtx_PLUS (SImode, table, sindex)));
4033     if (flag_pic)
4034       emit_insn (gen_addsi3 (addr, addr, table));
4036     emit_cmp_and_jump_insns (index, operands[2], GTU, NULL_RTX, SImode, 1, operands[4]);
4037     emit_jump_insn (gen_tablejump (addr, operands[3]));
4038     DONE;
4039   })
4041 (define_insn "tablejump"
4042   [(set (pc) (match_operand:SI 0 "spu_reg_operand" "r"))
4043    (use (label_ref (match_operand 1 "" "")))]
4044   ""
4045   "bi\t%0"
4046   [(set_attr "type" "br")])
4049 ;; call
4051 ;; Note that operand 1 is total size of args, in bytes,
4052 ;; and what the call insn wants is the number of words.
4053 (define_expand "sibcall"
4054   [(parallel
4055     [(call (match_operand:QI 0 "call_operand" "")
4056            (match_operand:QI 1 "" ""))
4057      (use (reg:SI 0))])]
4058   ""
4059   {
4060     if (! call_operand (operands[0], QImode))
4061       XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
4062   })
4064 (define_insn "_sibcall"
4065   [(parallel
4066     [(call (match_operand:QI 0 "call_operand" "R,S")
4067            (match_operand:QI 1 "" "i,i"))
4068      (use (reg:SI 0))])]
4069   "SIBLING_CALL_P(insn)"
4070   "@
4071    bi\t%i0
4072    br\t%0"
4073    [(set_attr "type" "br,br")])
4075 (define_expand "sibcall_value"
4076   [(parallel
4077     [(set (match_operand 0 "" "")
4078           (call (match_operand:QI 1 "call_operand" "")
4079                 (match_operand:QI 2 "" "")))
4080      (use (reg:SI 0))])]
4081   ""
4082   {
4083     if (! call_operand (operands[1], QImode))
4084       XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
4085   })
4087 (define_insn "_sibcall_value"
4088   [(parallel
4089     [(set (match_operand 0 "" "")
4090           (call (match_operand:QI 1 "call_operand" "R,S")
4091                 (match_operand:QI 2 "" "i,i")))
4092      (use (reg:SI 0))])]
4093   "SIBLING_CALL_P(insn)"
4094   "@
4095    bi\t%i1
4096    br\t%1"
4097    [(set_attr "type" "br,br")])
4099 ;; Note that operand 1 is total size of args, in bytes,
4100 ;; and what the call insn wants is the number of words.
4101 (define_expand "call"
4102   [(parallel
4103     [(call (match_operand:QI 0 "call_operand" "")
4104            (match_operand:QI 1 "" ""))
4105      (clobber (reg:SI 0))
4106      (clobber (reg:SI 130))])]
4107   ""
4108   {
4109     if (! call_operand (operands[0], QImode))
4110       XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
4111   })
4113 (define_insn "_call"
4114   [(parallel
4115     [(call (match_operand:QI 0 "call_operand" "R,S,T")
4116            (match_operand:QI 1 "" "i,i,i"))
4117      (clobber (reg:SI 0))
4118      (clobber (reg:SI 130))])]
4119   ""
4120   "@
4121    bisl\t$lr,%i0
4122    brsl\t$lr,%0
4123    brasl\t$lr,%0"
4124    [(set_attr "type" "br")])
4126 (define_expand "call_value"
4127   [(parallel
4128     [(set (match_operand 0 "" "")
4129           (call (match_operand:QI 1 "call_operand" "")
4130                 (match_operand:QI 2 "" "")))
4131      (clobber (reg:SI 0))
4132      (clobber (reg:SI 130))])]
4133   ""
4134   {
4135     if (! call_operand (operands[1], QImode))
4136       XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
4137   })
4139 (define_insn "_call_value"
4140   [(parallel
4141     [(set (match_operand 0 "" "")
4142           (call (match_operand:QI 1 "call_operand" "R,S,T")
4143                 (match_operand:QI 2 "" "i,i,i")))
4144      (clobber (reg:SI 0))
4145      (clobber (reg:SI 130))])]
4146   ""
4147   "@
4148    bisl\t$lr,%i1
4149    brsl\t$lr,%1
4150    brasl\t$lr,%1"
4151    [(set_attr "type" "br")])
4153 (define_expand "untyped_call"
4154   [(parallel [(call (match_operand 0 "" "")
4155                     (const_int 0))
4156               (match_operand 1 "" "")
4157               (match_operand 2 "" "")])]
4158   ""
4159   {
4160     int i;
4161     rtx reg = gen_rtx_REG (TImode, 3);
4163     /* We need to use call_value so the return value registers don't get
4164      * clobbered. */
4165     emit_call_insn (gen_call_value (reg, operands[0], const0_rtx));
4167     for (i = 0; i < XVECLEN (operands[2], 0); i++)
4168       {
4169         rtx set = XVECEXP (operands[2], 0, i);
4170         emit_move_insn (SET_DEST (set), SET_SRC (set));
4171       }
4173     /* The optimizer does not know that the call sets the function value
4174        registers we stored in the result block.  We avoid problems by
4175        claiming that all hard registers are used and clobbered at this
4176        point.  */
4177     emit_insn (gen_blockage ());
4179     DONE;
4180   })
4183 ;; Patterns used for splitting and combining.
4186 ;; Function prologue and epilogue.
4188 (define_expand "prologue"
4189   [(const_int 1)]
4190   ""
4191   { spu_expand_prologue (); DONE; })
4193 ;; "blockage" is only emited in epilogue.  This is what it took to
4194 ;; make "basic block reordering" work with the insns sequence
4195 ;; generated by the spu_expand_epilogue (taken from mips.md)
4197 (define_insn "blockage"
4198   [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
4199   ""
4200   ""
4201   [(set_attr "type" "convert")
4202    (set_attr "length" "0")])
4204 (define_expand "epilogue"
4205   [(const_int 2)]
4206   ""
4207   { spu_expand_epilogue (false); DONE; })
4209 (define_expand "sibcall_epilogue"
4210   [(const_int 2)]
4211   ""
4212   { spu_expand_epilogue (true); DONE; })
4215 ;; stack manipulations
4217 ;; An insn to allocate new stack space for dynamic use (e.g., alloca).
4218 ;; We move the back-chain and decrement the stack pointer.
4219 (define_expand "allocate_stack"
4220   [(set (match_operand 0 "spu_reg_operand" "")
4221         (minus (reg 1) (match_operand 1 "spu_nonmem_operand" "")))
4222    (set (reg 1)
4223         (minus (reg 1) (match_dup 1)))]
4224   ""
4225   "spu_allocate_stack (operands[0], operands[1]); DONE;")
4227 ;; These patterns say how to save and restore the stack pointer.  We need not
4228 ;; save the stack pointer at function level since we are careful to preserve 
4229 ;; the backchain.  
4230 ;; 
4232 ;; At block level the stack pointer is saved and restored, so that the
4233 ;; stack space allocated within a block is deallocated when leaving
4234 ;; block scope.  By default, according to the SPU ABI, the stack
4235 ;; pointer and available stack size are saved in a register. Upon
4236 ;; restoration, the stack pointer is simply copied back, and the
4237 ;; current available stack size is calculated against the restored
4238 ;; stack pointer.
4240 ;; For nonlocal gotos, we must save the stack pointer and its
4241 ;; backchain and restore both.  Note that in the nonlocal case, the
4242 ;; save area is a memory location.
4244 (define_expand "save_stack_function"
4245   [(match_operand 0 "general_operand" "")
4246    (match_operand 1 "general_operand" "")]
4247   ""
4248   "DONE;")
4250 (define_expand "restore_stack_function"
4251   [(match_operand 0 "general_operand" "")
4252    (match_operand 1 "general_operand" "")]
4253   ""
4254   "DONE;")
4256 (define_expand "restore_stack_block"
4257   [(match_operand 0 "spu_reg_operand" "")
4258    (match_operand 1 "memory_operand" "")]
4259   ""
4260   "
4261   {
4262     spu_restore_stack_block (operands[0], operands[1]);
4263     DONE;
4264   }")
4266 (define_expand "save_stack_nonlocal"
4267   [(match_operand 0 "memory_operand" "")
4268    (match_operand 1 "spu_reg_operand" "")]
4269   ""
4270   "
4271   {
4272     rtx temp = gen_reg_rtx (Pmode);
4274     /* Copy the backchain to the first word, sp to the second.  We need to
4275        save the back chain because __builtin_apply appears to clobber it. */
4276     emit_move_insn (temp, gen_rtx_MEM (Pmode, operands[1]));
4277     emit_move_insn (adjust_address_nv (operands[0], SImode, 0), temp);
4278     emit_move_insn (adjust_address_nv (operands[0], SImode, 4), operands[1]);
4279     DONE;
4280   }")
4282 (define_expand "restore_stack_nonlocal"
4283   [(match_operand 0 "spu_reg_operand" "")
4284    (match_operand 1 "memory_operand" "")]
4285   ""
4286   "
4287   {
4288     spu_restore_stack_nonlocal(operands[0], operands[1]);
4289     DONE;
4290   }")
4293 ;; vector patterns
4295 ;; Vector initialization
4296 (define_expand "vec_init<mode>"
4297   [(match_operand:V 0 "register_operand" "")
4298    (match_operand 1 "" "")]
4299   ""
4300   {
4301     spu_expand_vector_init (operands[0], operands[1]);
4302     DONE;
4303   })
4305 (define_expand "vec_set<mode>"
4306   [(use (match_operand:SI 2 "spu_nonmem_operand" ""))
4307    (set (match_dup:TI 3)
4308         (unspec:TI [(match_dup:SI 4)
4309                     (match_dup:SI 5)
4310                     (match_dup:SI 6)] UNSPEC_CPAT))
4311    (set (match_operand:V 0 "spu_reg_operand" "")
4312         (unspec:V [(match_operand:<inner> 1 "spu_reg_operand" "")
4313                    (match_dup:V 0)
4314                    (match_dup:TI 3)] UNSPEC_SHUFB))]
4315   ""
4316   {
4317     HOST_WIDE_INT size = GET_MODE_SIZE (<inner>mode);
4318     rtx offset = GEN_INT (INTVAL (operands[2]) * size);
4319     operands[3] = gen_reg_rtx (TImode);
4320     operands[4] = stack_pointer_rtx;
4321     operands[5] = offset;
4322     operands[6] = GEN_INT (size);
4323   })
4325 (define_expand "vec_extract<mode>"
4326   [(set (match_operand:<inner> 0 "spu_reg_operand" "=r")
4327         (vec_select:<inner> (match_operand:V 1 "spu_reg_operand" "r")
4328                             (parallel [(match_operand 2 "const_int_operand" "i")])))]
4329   ""
4330   {
4331     if ((INTVAL (operands[2]) * <vmult> + <voff>) % 16 == 0)
4332       {
4333         emit_insn (gen_spu_convert (operands[0], operands[1]));
4334         DONE;
4335       }
4336   })
4338 (define_insn "_vec_extract<mode>"
4339   [(set (match_operand:<inner> 0 "spu_reg_operand" "=r")
4340         (vec_select:<inner> (match_operand:V 1 "spu_reg_operand" "r")
4341                             (parallel [(match_operand 2 "const_int_operand" "i")])))]
4342   ""
4343   "rotqbyi\t%0,%1,(%2*<vmult>+<voff>)%%16"
4344   [(set_attr "type" "shuf")])
4346 (define_insn "_vec_extractv8hi_ze"
4347   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
4348         (zero_extend:SI (vec_select:HI (match_operand:V8HI 1 "spu_reg_operand" "r")
4349                                        (parallel [(const_int 0)]))))]
4350   ""
4351   "rotqmbyi\t%0,%1,-2"
4352   [(set_attr "type" "shuf")])
4355 ;; misc
4357 (define_expand "shufb"
4358   [(set (match_operand 0 "spu_reg_operand" "")
4359         (unspec [(match_operand 1 "spu_reg_operand" "")
4360                  (match_operand 2 "spu_reg_operand" "")
4361                  (match_operand:TI 3 "spu_reg_operand" "")] UNSPEC_SHUFB))]
4362   ""
4363   {
4364     rtx s = gen__shufb (operands[0], operands[1], operands[2], operands[3]);
4365     PUT_MODE (SET_SRC (s), GET_MODE (operands[0]));
4366     emit_insn (s);
4367     DONE;
4368   })
4370 (define_insn "_shufb"
4371   [(set (match_operand 0 "spu_reg_operand" "=r")
4372         (unspec [(match_operand 1 "spu_reg_operand" "r")
4373                  (match_operand 2 "spu_reg_operand" "r")
4374                  (match_operand:TI 3 "spu_reg_operand" "r")] UNSPEC_SHUFB))]
4375   "operands"
4376   "shufb\t%0,%1,%2,%3"
4377   [(set_attr "type" "shuf")])
4379 (define_insn "nop"
4380   [(unspec_volatile [(const_int 0)] UNSPEC_NOP)]
4381   ""
4382   "nop"
4383   [(set_attr "type" "nop")])
4385 (define_insn "nopn"
4386   [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "K")] UNSPEC_NOP)]
4387   ""
4388   "nop\t%0"
4389   [(set_attr "type" "nop")])
4391 (define_insn "lnop"
4392   [(unspec_volatile [(const_int 0)] UNSPEC_LNOP)]
4393   ""
4394   "lnop"
4395   [(set_attr "type" "lnop")])
4397 ;; The operand is so we know why we generated this hbrp.
4398 ;; We clobber mem to make sure it isn't moved over any
4399 ;; loads, stores or calls while scheduling.
4400 (define_insn "iprefetch"
4401   [(unspec [(match_operand:SI 0 "const_int_operand" "n")] UNSPEC_IPREFETCH)
4402    (clobber (mem:BLK (scratch)))]
4403   ""
4404   "hbrp\t# %0"
4405   [(set_attr "type" "iprefetch")])
4407 ;; A non-volatile version so it gets scheduled
4408 (define_insn "nopn_nv"
4409   [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_NOP)]
4410   ""
4411   "nop\t%0"
4412   [(set_attr "type" "nop")])
4414 (define_insn "hbr"
4415   [(set (reg:SI 130)
4416         (unspec:SI [(match_operand:SI 0 "immediate_operand" "i,i,i")
4417                     (match_operand:SI 1 "nonmemory_operand" "r,s,i")] UNSPEC_HBR))
4418    (unspec [(const_int 0)] UNSPEC_HBR)]
4419   ""
4420   "@
4421    hbr\t%0,%1
4422    hbrr\t%0,%1
4423    hbra\t%0,%1"
4424   [(set_attr "type" "hbr")])
4426 (define_insn "sync"
4427   [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)
4428    (clobber (mem:BLK (scratch)))]
4429   ""
4430   "sync"
4431   [(set_attr "type" "br")])
4433 (define_insn "syncc"
4434   [(unspec_volatile [(const_int 1)] UNSPEC_SYNC)
4435    (clobber (mem:BLK (scratch)))]
4436   ""
4437   "syncc"
4438   [(set_attr "type" "br")])
4440 (define_insn "dsync"
4441   [(unspec_volatile [(const_int 2)] UNSPEC_SYNC)
4442    (clobber (mem:BLK (scratch)))]
4443   ""
4444   "dsync"
4445   [(set_attr "type" "br")])
4449  ;; Define the subtract-one-and-jump insns so loop.c
4450  ;; knows what to generate.
4451  (define_expand "doloop_end"
4452    [(use (match_operand 0 "" ""))      ; loop pseudo
4453     (use (match_operand 1 "" ""))      ; iterations; zero if unknown
4454     (use (match_operand 2 "" ""))      ; max iterations
4455     (use (match_operand 3 "" ""))      ; loop level
4456     (use (match_operand 4 "" ""))]     ; label
4457    ""
4458    "
4460    /* Currently SMS relies on the do-loop pattern to recognize loops
4461       where (1) the control part comprises of all insns defining and/or
4462       using a certain 'count' register and (2) the loop count can be
4463       adjusted by modifying this register prior to the loop.
4464 .     ??? The possible introduction of a new block to initialize the
4465       new IV can potentially effects branch optimizations.  */
4466    if (optimize > 0 && flag_modulo_sched)
4467    {
4468      rtx s0;
4469      rtx bcomp;
4470      rtx loc_ref;
4472      /* Only use this on innermost loops.  */
4473      if (INTVAL (operands[3]) > 1)
4474        FAIL;
4475      if (GET_MODE (operands[0]) != SImode)
4476        FAIL;
4478      s0 = operands [0];
4479      emit_move_insn (s0, gen_rtx_PLUS (SImode, s0, GEN_INT (-1)));
4480      bcomp = gen_rtx_NE(SImode, s0, const0_rtx);
4481      loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
4482      emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
4483                                   gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
4484                                                         loc_ref, pc_rtx)));
4486      DONE;
4487    }else
4488       FAIL;
4489  }")
4491 ;; convert between any two modes, avoiding any GCC assumptions
4492 (define_expand "spu_convert"
4493   [(set (match_operand 0 "spu_reg_operand" "")
4494         (unspec [(match_operand 1 "spu_reg_operand" "")] UNSPEC_CONVERT))]
4495   ""
4496   {
4497     rtx c = gen__spu_convert (operands[0], operands[1]);
4498     PUT_MODE (SET_SRC (c), GET_MODE (operands[0]));
4499     emit_insn (c);
4500     DONE;
4501   })
4503 (define_insn_and_split "_spu_convert"
4504   [(set (match_operand 0 "spu_reg_operand" "=r")
4505         (unspec [(match_operand 1 "spu_reg_operand" "0")] UNSPEC_CONVERT))]
4506   ""
4507   "#"
4508   "reload_completed"
4509   [(const_int 0)]
4510   {
4511     spu_split_convert (operands);
4512     DONE;
4513   }
4514   [(set_attr "type" "convert")
4515    (set_attr "length" "0")])
4519 (include "spu-builtins.md")
4521   
4522 (define_expand "smaxv4sf3"
4523   [(set (match_operand:V4SF 0 "register_operand" "=r")
4524         (smax:V4SF (match_operand:V4SF 1 "register_operand" "r")
4525                  (match_operand:V4SF 2 "register_operand" "r")))]
4526   ""
4527   "
4529   rtx mask = gen_reg_rtx (V4SImode);
4531   emit_insn (gen_cgt_v4sf (mask, operands[1], operands[2]));
4532   emit_insn (gen_selb (operands[0], operands[2], operands[1], mask));
4533   DONE;
4534 }") 
4536 (define_expand "sminv4sf3"
4537   [(set (match_operand:V4SF 0 "register_operand" "=r")
4538         (smin:V4SF (match_operand:V4SF 1 "register_operand" "r")
4539                  (match_operand:V4SF 2 "register_operand" "r")))]
4540   ""
4541   "
4543   rtx mask = gen_reg_rtx (V4SImode);
4545   emit_insn (gen_cgt_v4sf (mask, operands[1], operands[2]));
4546   emit_insn (gen_selb (operands[0], operands[1], operands[2], mask));
4547   DONE;
4548 }") 
4550 (define_expand "smaxv2df3"
4551   [(set (match_operand:V2DF 0 "register_operand" "=r")
4552         (smax:V2DF (match_operand:V2DF 1 "register_operand" "r")
4553                  (match_operand:V2DF 2 "register_operand" "r")))]
4554   ""
4555   "
4557   rtx mask = gen_reg_rtx (V2DImode);
4558   emit_insn (gen_cgt_v2df (mask, operands[1], operands[2]));
4559   emit_insn (gen_selb (operands[0], operands[2], operands[1], 
4560                        spu_gen_subreg (V4SImode, mask)));
4561   DONE;
4564 (define_expand "sminv2df3"
4565   [(set (match_operand:V2DF 0 "register_operand" "=r")
4566         (smin:V2DF (match_operand:V2DF 1 "register_operand" "r")
4567                  (match_operand:V2DF 2 "register_operand" "r")))]
4568   ""
4569   "
4571   rtx mask = gen_reg_rtx (V2DImode);
4572   emit_insn (gen_cgt_v2df (mask, operands[1], operands[2]));
4573   emit_insn (gen_selb (operands[0], operands[1], operands[2], 
4574                        spu_gen_subreg (V4SImode, mask)));
4575   DONE;
4578 (define_expand "vec_widen_umult_hi_v8hi"
4579   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4580         (mult:V4SI
4581           (zero_extend:V4SI
4582             (vec_select:V4HI
4583               (match_operand:V8HI 1 "register_operand" "r")
4584               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))
4585           (zero_extend:V4SI
4586             (vec_select:V4HI
4587               (match_operand:V8HI 2 "register_operand" "r")
4588               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))))]
4589   ""
4590   "
4592   rtx ve = gen_reg_rtx (V4SImode);
4593   rtx vo = gen_reg_rtx (V4SImode);
4594   rtx mask = gen_reg_rtx (TImode);
4595   unsigned char arr[16] = {
4596     0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 
4597     0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17};
4598   
4599   emit_move_insn (mask, array_to_constant (TImode, arr));
4600   emit_insn (gen_spu_mpyhhu (ve, operands[1], operands[2]));
4601   emit_insn (gen_spu_mpyu (vo, operands[1], operands[2]));
4602   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4603   DONE;
4606 (define_expand "vec_widen_umult_lo_v8hi"
4607   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4608         (mult:V4SI
4609           (zero_extend:V4SI
4610             (vec_select:V4HI
4611               (match_operand:V8HI 1 "register_operand" "r")
4612               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
4613           (zero_extend:V4SI
4614             (vec_select:V4HI
4615               (match_operand:V8HI 2 "register_operand" "r")
4616               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))))]
4617   ""
4618   "
4620   rtx ve = gen_reg_rtx (V4SImode);
4621   rtx vo = gen_reg_rtx (V4SImode);
4622   rtx mask = gen_reg_rtx (TImode);
4623   unsigned char arr[16] = {
4624     0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 
4625     0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F};
4627   emit_move_insn (mask, array_to_constant (TImode, arr));
4628   emit_insn (gen_spu_mpyhhu (ve, operands[1], operands[2]));
4629   emit_insn (gen_spu_mpyu (vo, operands[1], operands[2]));
4630   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4631   DONE;
4634 (define_expand "vec_widen_smult_hi_v8hi"
4635   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4636         (mult:V4SI
4637           (sign_extend:V4SI
4638             (vec_select:V4HI
4639               (match_operand:V8HI 1 "register_operand" "r")
4640               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))
4641           (sign_extend:V4SI
4642             (vec_select:V4HI
4643               (match_operand:V8HI 2 "register_operand" "r")
4644               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))))]
4645   ""
4646   "
4648   rtx ve = gen_reg_rtx (V4SImode);
4649   rtx vo = gen_reg_rtx (V4SImode);
4650   rtx mask = gen_reg_rtx (TImode);
4651   unsigned char arr[16] = {
4652     0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 
4653     0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17};
4654   
4655   emit_move_insn (mask, array_to_constant (TImode, arr));
4656   emit_insn (gen_spu_mpyhh (ve, operands[1], operands[2]));
4657   emit_insn (gen_spu_mpy (vo, operands[1], operands[2]));
4658   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4659   DONE;
4662 (define_expand "vec_widen_smult_lo_v8hi"
4663   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4664         (mult:V4SI
4665           (sign_extend:V4SI
4666             (vec_select:V4HI
4667               (match_operand:V8HI 1 "register_operand" "r")
4668               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
4669           (sign_extend:V4SI
4670             (vec_select:V4HI
4671               (match_operand:V8HI 2 "register_operand" "r")
4672               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))))]
4673   ""
4674   "
4676   rtx ve = gen_reg_rtx (V4SImode);
4677   rtx vo = gen_reg_rtx (V4SImode);
4678   rtx mask = gen_reg_rtx (TImode);
4679   unsigned char arr[16] = {
4680     0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 
4681     0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F};
4683   emit_move_insn (mask, array_to_constant (TImode, arr));
4684   emit_insn (gen_spu_mpyhh (ve, operands[1], operands[2]));
4685   emit_insn (gen_spu_mpy (vo, operands[1], operands[2]));
4686   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4687   DONE;
4690 (define_expand "vec_realign_load_<mode>"
4691   [(set (match_operand:ALL 0 "register_operand" "=r")
4692         (unspec:ALL [(match_operand:ALL 1 "register_operand" "r")
4693                      (match_operand:ALL 2 "register_operand" "r")
4694                      (match_operand:TI 3 "register_operand" "r")] UNSPEC_SPU_REALIGN_LOAD))]
4695   ""
4696   "
4698   emit_insn (gen_shufb (operands[0], operands[1], operands[2], operands[3])); 
4699   DONE;
4702 (define_expand "spu_lvsr"
4703   [(set (match_operand:V16QI 0 "register_operand" "")
4704         (unspec:V16QI [(match_operand 1 "memory_operand" "")] UNSPEC_SPU_MASK_FOR_LOAD))]
4705   ""
4706   "
4708   rtx addr;
4709   rtx offset = gen_reg_rtx (V8HImode);
4710   rtx addr_bits = gen_reg_rtx (SImode);
4711   rtx addr_bits_vec = gen_reg_rtx (V8HImode);
4712   rtx splatqi = gen_reg_rtx (TImode);
4713   rtx result = gen_reg_rtx (V8HImode);
4714   unsigned char arr[16] = {
4715     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
4716     0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
4717   unsigned char arr2[16] = {
4718     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
4719     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
4721   emit_move_insn (offset, array_to_constant (V8HImode, arr));
4722   emit_move_insn (splatqi, array_to_constant (TImode, arr2));
4724   gcc_assert (GET_CODE (operands[1]) == MEM);
4725   addr = force_reg (Pmode, XEXP (operands[1], 0));
4726   emit_insn (gen_andsi3 (addr_bits, addr, GEN_INT (0xF))); 
4727   emit_insn (gen_shufb (addr_bits_vec, addr_bits, addr_bits, splatqi));
4729   /* offset - (addr & 0xF) 
4730      It is safe to use a single sfh, because each byte of offset is > 15 and
4731      each byte of addr is <= 15. */
4732   emit_insn (gen_subv8hi3 (result, offset, addr_bits_vec));
4734   result = simplify_gen_subreg (V16QImode, result, V8HImode, 0);
4735   emit_move_insn (operands[0], result);
4737   DONE;
4740 (define_expand "vec_unpacku_hi_v8hi"
4741   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4742         (zero_extend:V4SI 
4743           (vec_select:V4HI
4744             (match_operand:V8HI 1 "spu_reg_operand" "r")
4745             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
4746   ""
4748   rtx mask = gen_reg_rtx (TImode);
4749   unsigned char arr[16] = {
4750     0x80, 0x80, 0x00, 0x01, 0x80, 0x80, 0x02, 0x03,
4751     0x80, 0x80, 0x04, 0x05, 0x80, 0x80, 0x06, 0x07};
4753   emit_move_insn (mask, array_to_constant (TImode, arr));
4754   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4756   DONE;
4759 (define_expand "vec_unpacku_lo_v8hi"
4760   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4761          (zero_extend:V4SI
4762           (vec_select:V4HI
4763             (match_operand:V8HI 1 "spu_reg_operand" "r")
4764             (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4767   rtx mask = gen_reg_rtx (TImode);
4768   unsigned char arr[16] = {
4769     0x80, 0x80, 0x08, 0x09, 0x80, 0x80, 0x0A, 0x0B,
4770     0x80, 0x80, 0x0C, 0x0D, 0x80, 0x80, 0x0E, 0x0F};
4772   emit_move_insn (mask, array_to_constant (TImode, arr));
4773   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4774   
4775   DONE;
4778 (define_expand "vec_unpacks_hi_v8hi"
4779   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4780          (sign_extend:V4SI
4781           (vec_select:V4HI
4782             (match_operand:V8HI 1 "spu_reg_operand" "r")
4783             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
4784   ""
4786   rtx tmp1 = gen_reg_rtx (V8HImode);
4787   rtx tmp2 = gen_reg_rtx (V4SImode);
4788   rtx mask = gen_reg_rtx (TImode);
4789   unsigned char arr[16] = {
4790     0x80, 0x80, 0x00, 0x01, 0x80, 0x80, 0x02, 0x03,
4791     0x80, 0x80, 0x04, 0x05, 0x80, 0x80, 0x06, 0x07};
4793   emit_move_insn (mask, array_to_constant (TImode, arr));
4794   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4795   emit_insn (gen_spu_xshw (tmp2, tmp1)); 
4796   emit_move_insn (operands[0], tmp2);
4798   DONE;
4801 (define_expand "vec_unpacks_lo_v8hi"
4802   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4803          (sign_extend:V4SI
4804           (vec_select:V4HI
4805             (match_operand:V8HI 1 "spu_reg_operand" "r")
4806             (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4809   rtx tmp1 = gen_reg_rtx (V8HImode);
4810   rtx tmp2 = gen_reg_rtx (V4SImode);
4811   rtx mask = gen_reg_rtx (TImode);
4812   unsigned char arr[16] = {
4813     0x80, 0x80, 0x08, 0x09, 0x80, 0x80, 0x0A, 0x0B,
4814     0x80, 0x80, 0x0C, 0x0D, 0x80, 0x80, 0x0E, 0x0F};
4816   emit_move_insn (mask, array_to_constant (TImode, arr));
4817   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4818   emit_insn (gen_spu_xshw (tmp2, tmp1)); 
4819   emit_move_insn (operands[0], tmp2);
4821 DONE;
4824 (define_expand "vec_unpacku_hi_v16qi"
4825   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4826         (zero_extend:V8HI
4827           (vec_select:V8QI
4828             (match_operand:V16QI 1 "spu_reg_operand" "r")
4829             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
4830                        (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4831   ""
4833   rtx mask = gen_reg_rtx (TImode);
4834   unsigned char arr[16] = {
4835     0x80, 0x00, 0x80, 0x01, 0x80, 0x02, 0x80, 0x03,
4836     0x80, 0x04, 0x80, 0x05, 0x80, 0x06, 0x80, 0x07};
4838   emit_move_insn (mask, array_to_constant (TImode, arr));
4839   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4841   DONE;
4844 (define_expand "vec_unpacku_lo_v16qi"
4845   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4846           (zero_extend:V8HI
4847           (vec_select:V8QI
4848             (match_operand:V16QI 1 "spu_reg_operand" "r")
4849             (parallel [(const_int 8)(const_int 9)(const_int 10)(const_int 11)
4850                        (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
4853   rtx mask = gen_reg_rtx (TImode);
4854   unsigned char arr[16] = {
4855     0x80, 0x08, 0x80, 0x09, 0x80, 0x0A, 0x80, 0x0B,
4856     0x80, 0x0C, 0x80, 0x0D, 0x80, 0x0E, 0x80, 0x0F};
4858   emit_move_insn (mask, array_to_constant (TImode, arr));
4859   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4861   DONE;
4864 (define_expand "vec_unpacks_hi_v16qi"
4865   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4866          (sign_extend:V8HI
4867           (vec_select:V8QI
4868             (match_operand:V16QI 1 "spu_reg_operand" "r")
4869             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
4870                        (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4873   rtx tmp1 = gen_reg_rtx (V16QImode);
4874   rtx tmp2 = gen_reg_rtx (V8HImode);
4875   rtx mask = gen_reg_rtx (TImode);
4876   unsigned char arr[16] = {
4877     0x80, 0x00, 0x80, 0x01, 0x80, 0x02, 0x80, 0x03,
4878     0x80, 0x04, 0x80, 0x05, 0x80, 0x06, 0x80, 0x07};
4880   emit_move_insn (mask, array_to_constant (TImode, arr));
4881   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4882   emit_insn (gen_spu_xsbh (tmp2, tmp1));
4883   emit_move_insn (operands[0], tmp2);
4885   DONE;
4888 (define_expand "vec_unpacks_lo_v16qi"
4889   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4890          (sign_extend:V8HI
4891           (vec_select:V8QI
4892             (match_operand:V16QI 1 "spu_reg_operand" "r")
4893             (parallel [(const_int 8)(const_int 9)(const_int 10)(const_int 11)
4894                        (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
4897   rtx tmp1 = gen_reg_rtx (V16QImode);
4898   rtx tmp2 = gen_reg_rtx (V8HImode);
4899   rtx mask = gen_reg_rtx (TImode);
4900   unsigned char arr[16] = {
4901     0x80, 0x08, 0x80, 0x09, 0x80, 0x0A, 0x80, 0x0B,
4902     0x80, 0x0C, 0x80, 0x0D, 0x80, 0x0E, 0x80, 0x0F};
4904   emit_move_insn (mask, array_to_constant (TImode, arr));
4905   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4906   emit_insn (gen_spu_xsbh (tmp2, tmp1));
4907   emit_move_insn (operands[0], tmp2);
4909 DONE;
4913 (define_expand "vec_extract_evenv4si"
4914  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4915        (vec_concat:V4SI
4916          (vec_select:V2SI
4917            (match_operand:V4SI 1 "spu_reg_operand" "r")
4918            (parallel [(const_int 0)(const_int 2)]))
4919          (vec_select:V2SI
4920            (match_operand:V4SI 2 "spu_reg_operand" "r")
4921            (parallel [(const_int 0)(const_int 2)]))))]
4923   ""
4924   "
4926   rtx mask = gen_reg_rtx (TImode);
4927   unsigned char arr[16] = {
4928         0x00, 0x01, 0x02, 0x03,
4929         0x08, 0x09, 0x0A, 0x0B,
4930         0x10, 0x11, 0x12, 0x13,
4931         0x18, 0x19, 0x1A, 0x1B};        
4933   emit_move_insn (mask, array_to_constant (TImode, arr));
4934   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
4935   DONE;
4939 (define_expand "vec_extract_evenv4sf"
4940  [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
4941        (vec_concat:V4SF
4942          (vec_select:V2SF
4943            (match_operand:V4SF 1 "spu_reg_operand" "r")
4944            (parallel [(const_int 0)(const_int 2)]))
4945          (vec_select:V2SF
4946            (match_operand:V4SF 2 "spu_reg_operand" "r")
4947            (parallel [(const_int 0)(const_int 2)]))))]
4949   ""
4950   "
4952   rtx mask = gen_reg_rtx (TImode);
4953   unsigned char arr[16] = {
4954         0x00, 0x01, 0x02, 0x03,
4955         0x08, 0x09, 0x0A, 0x0B,
4956         0x10, 0x11, 0x12, 0x13,
4957         0x18, 0x19, 0x1A, 0x1B};
4959   emit_move_insn (mask, array_to_constant (TImode, arr));
4960   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
4961   DONE;
4964 (define_expand "vec_extract_evenv8hi"
4965  [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4966        (vec_concat:V8HI
4967          (vec_select:V4HI
4968            (match_operand:V8HI 1 "spu_reg_operand" "r")
4969            (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))
4970          (vec_select:V4HI
4971            (match_operand:V8HI 2 "spu_reg_operand" "r")
4972            (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))))]
4974   ""
4975   "
4977   rtx mask = gen_reg_rtx (TImode);
4978   unsigned char arr[16] = {
4979         0x00, 0x01, 0x04, 0x05,
4980         0x08, 0x09, 0x0C, 0x0D,
4981         0x10, 0x11, 0x14, 0x15,
4982         0x18, 0x19, 0x1C, 0x1D};
4984   emit_move_insn (mask, array_to_constant (TImode, arr));
4985   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
4986   DONE;
4989 (define_expand "vec_extract_evenv16qi"
4990  [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
4991        (vec_concat:V16QI
4992          (vec_select:V8QI
4993            (match_operand:V16QI 1 "spu_reg_operand" "r")
4994            (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)
4995                       (const_int 8)(const_int 10)(const_int 12)(const_int 14)]))
4996          (vec_select:V8QI
4997            (match_operand:V16QI 2 "spu_reg_operand" "r")
4998            (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)
4999                       (const_int 8)(const_int 10)(const_int 12)(const_int 14)]))))]
5001   ""
5002   "
5004   rtx mask = gen_reg_rtx (TImode);
5005   unsigned char arr[16] = {
5006         0x00, 0x02, 0x04, 0x06,
5007         0x08, 0x0A, 0x0C, 0x0E,
5008         0x10, 0x12, 0x14, 0x16,
5009         0x18, 0x1A, 0x1C, 0x1E};
5011   emit_move_insn (mask, array_to_constant (TImode, arr));
5012   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5013   DONE;
5016 (define_expand "vec_extract_oddv4si"
5017  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
5018        (vec_concat:V4SI
5019          (vec_select:V2SI
5020            (match_operand:V4SI 1 "spu_reg_operand" "r")
5021            (parallel [(const_int 1)(const_int 3)]))
5022          (vec_select:V2SI
5023            (match_operand:V4SI 2 "spu_reg_operand" "r")
5024            (parallel [(const_int 1)(const_int 3)]))))]
5026   ""
5027   "
5029   rtx mask = gen_reg_rtx (TImode);
5030   unsigned char arr[16] = {
5031         0x04, 0x05, 0x06, 0x07,
5032         0x0C, 0x0D, 0x0E, 0x0F,
5033         0x14, 0x15, 0x16, 0x17,
5034         0x1C, 0x1D, 0x1E, 0x1F};
5036   emit_move_insn (mask, array_to_constant (TImode, arr));
5037   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5038   DONE;
5041 (define_expand "vec_extract_oddv4sf"
5042  [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
5043        (vec_concat:V4SF
5044          (vec_select:V2SF
5045            (match_operand:V4SF 1 "spu_reg_operand" "r")
5046            (parallel [(const_int 1)(const_int 3)]))
5047          (vec_select:V2SF
5048            (match_operand:V4SF 2 "spu_reg_operand" "r")
5049            (parallel [(const_int 1)(const_int 3)]))))]
5051   ""
5052   "
5054   rtx mask = gen_reg_rtx (TImode);
5055   unsigned char arr[16] = {
5056         0x04, 0x05, 0x06, 0x07,
5057         0x0C, 0x0D, 0x0E, 0x0F,
5058         0x14, 0x15, 0x16, 0x17,
5059         0x1C, 0x1D, 0x1E, 0x1F};
5061   emit_move_insn (mask, array_to_constant (TImode, arr));
5062   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5063   DONE;
5066 (define_expand "vec_extract_oddv8hi"
5067  [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
5068        (vec_concat:V8HI
5069          (vec_select:V4HI
5070            (match_operand:V8HI 1 "spu_reg_operand" "r")
5071            (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))
5072          (vec_select:V4HI
5073            (match_operand:V8HI 2 "spu_reg_operand" "r")
5074            (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))]
5076   ""
5077   "
5079   rtx mask = gen_reg_rtx (TImode);
5080   unsigned char arr[16] = {
5081         0x02, 0x03, 0x06, 0x07,
5082         0x0A, 0x0B, 0x0E, 0x0F,
5083         0x12, 0x13, 0x16, 0x17,
5084         0x1A, 0x1B, 0x1E, 0x1F};
5086   emit_move_insn (mask, array_to_constant (TImode, arr));
5087   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5088   DONE;
5091 (define_expand "vec_extract_oddv16qi"
5092  [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
5093        (vec_concat:V16QI
5094          (vec_select:V8QI
5095            (match_operand:V16QI 1 "spu_reg_operand" "r")
5096            (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)
5097                       (const_int 9)(const_int 11)(const_int 13)(const_int 15)]))
5098          (vec_select:V8QI
5099            (match_operand:V16QI 2 "spu_reg_operand" "r")
5100            (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)
5101                       (const_int 9)(const_int 11)(const_int 13)(const_int 15)]))))]
5103   ""
5104   "
5106   rtx mask = gen_reg_rtx (TImode);
5107   unsigned char arr[16] = {
5108         0x01, 0x03, 0x05, 0x07,
5109         0x09, 0x0B, 0x0D, 0x0F,
5110         0x11, 0x13, 0x15, 0x17,
5111         0x19, 0x1B, 0x1D, 0x1F};
5113   emit_move_insn (mask, array_to_constant (TImode, arr));
5114   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5115   DONE;
5118 (define_expand "vec_interleave_highv4sf"
5119  [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
5120        (vec_select:V4SF
5121          (vec_concat:V4SF
5122            (vec_select:V2SF
5123              (match_operand:V4SF 1 "spu_reg_operand" "r")
5124              (parallel [(const_int 0)(const_int 1)]))
5125            (vec_select:V2SF
5126              (match_operand:V4SF 2 "spu_reg_operand" "r")
5127              (parallel [(const_int 0)(const_int 1)])))
5128          (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
5130   ""
5131   "
5133   rtx mask = gen_reg_rtx (TImode);
5134   unsigned char arr[16] = {
5135         0x00, 0x01, 0x02, 0x03,
5136         0x10, 0x11, 0x12, 0x13,
5137         0x04, 0x05, 0x06, 0x07,
5138         0x14, 0x15, 0x16, 0x17};
5140   emit_move_insn (mask, array_to_constant (TImode, arr));
5141   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5142   DONE;
5145 (define_expand "vec_interleave_lowv4sf"
5146  [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
5147        (vec_select:V4SF
5148          (vec_concat:V4SF
5149            (vec_select:V2SF
5150              (match_operand:V4SF 1 "spu_reg_operand" "r")
5151              (parallel [(const_int 2)(const_int 3)]))
5152            (vec_select:V2SF
5153              (match_operand:V4SF 2 "spu_reg_operand" "r")
5154              (parallel [(const_int 2)(const_int 3)])))
5155          (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
5157   ""
5158   "
5160   rtx mask = gen_reg_rtx (TImode);
5161   unsigned char arr[16] = {
5162         0x08, 0x09, 0x0A, 0x0B,
5163         0x18, 0x19, 0x1A, 0x1B,
5164         0x0C, 0x0D, 0x0E, 0x0F,
5165         0x1C, 0x1D, 0x1E, 0x1F};
5167   emit_move_insn (mask, array_to_constant (TImode, arr));
5168   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5169   DONE;
5172 (define_expand "vec_interleave_highv4si"
5173  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
5174        (vec_select:V4SI
5175          (vec_concat:V4SI
5176            (vec_select:V2SI
5177              (match_operand:V4SI 1 "spu_reg_operand" "r")
5178              (parallel [(const_int 0)(const_int 1)]))
5179            (vec_select:V2SI
5180              (match_operand:V4SI 2 "spu_reg_operand" "r")
5181              (parallel [(const_int 0)(const_int 1)])))
5182          (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
5184   ""
5185   "
5187   rtx mask = gen_reg_rtx (TImode);
5188   unsigned char arr[16] = {
5189         0x00, 0x01, 0x02, 0x03,
5190         0x10, 0x11, 0x12, 0x13,
5191         0x04, 0x05, 0x06, 0x07,
5192         0x14, 0x15, 0x16, 0x17};
5194   emit_move_insn (mask, array_to_constant (TImode, arr));
5195   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5196   DONE;
5199 (define_expand "vec_interleave_lowv4si"
5200  [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
5201        (vec_select:V4SI
5202          (vec_concat:V4SI
5203            (vec_select:V2SI
5204              (match_operand:V4SI 1 "spu_reg_operand" "r")
5205              (parallel [(const_int 2)(const_int 3)]))
5206            (vec_select:V2SI
5207              (match_operand:V4SI 2 "spu_reg_operand" "r")
5208              (parallel [(const_int 2)(const_int 3)])))
5209          (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
5211   ""
5212   "
5214   rtx mask = gen_reg_rtx (TImode);
5215   unsigned char arr[16] = {
5216         0x08, 0x09, 0x0A, 0x0B,
5217         0x18, 0x19, 0x1A, 0x1B,
5218         0x0C, 0x0D, 0x0E, 0x0F,
5219         0x1C, 0x1D, 0x1E, 0x1F};
5221   emit_move_insn (mask, array_to_constant (TImode, arr));
5222   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5223   DONE;
5226 (define_expand "vec_interleave_highv8hi"
5227  [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
5228        (vec_select:V8HI
5229          (vec_concat:V8HI
5230            (vec_select:V4HI
5231              (match_operand:V8HI 1 "spu_reg_operand" "r")
5232              (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))
5233            (vec_select:V4HI
5234              (match_operand:V8HI 2 "spu_reg_operand" "r")
5235              (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))
5236          (parallel [(const_int 0)(const_int 4)(const_int 1)(const_int 5)
5237                     (const_int 2)(const_int 6)(const_int 3)(const_int 7)])))]
5239   ""
5240   "
5242   rtx mask = gen_reg_rtx (TImode);
5243   unsigned char arr[16] = {
5244         0x00, 0x01, 0x10, 0x11,
5245         0x02, 0x03, 0x12, 0x13,
5246         0x04, 0x05, 0x14, 0x15,
5247         0x06, 0x07, 0x16, 0x17};
5249   emit_move_insn (mask, array_to_constant (TImode, arr));
5250   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5251   DONE;
5252  }")
5254 (define_expand "vec_interleave_lowv8hi"
5255  [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
5256        (vec_select:V8HI
5257          (vec_concat:V8HI
5258            (vec_select:V4HI
5259              (match_operand:V8HI 1 "spu_reg_operand" "r")
5260              (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))
5261            (vec_select:V4HI
5262              (match_operand:V8HI 2 "spu_reg_operand" "r")
5263              (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
5264          (parallel [(const_int 0)(const_int 4)(const_int 1)(const_int 5)
5265                     (const_int 2)(const_int 6)(const_int 3)(const_int 7)])))]
5267   ""
5268   "
5270   rtx mask = gen_reg_rtx (TImode);
5271   unsigned char arr[16] = {
5272         0x08, 0x09, 0x18, 0x19,
5273         0x0A, 0x0B, 0x1A, 0x1B,
5274         0x0C, 0x0D, 0x1C, 0x1D,
5275         0x0E, 0x0F, 0x1E, 0x1F};
5277   emit_move_insn (mask, array_to_constant (TImode, arr));
5278   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5279   DONE;
5282 (define_expand "vec_interleave_highv16qi"
5283  [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
5284        (vec_select:V16QI
5285          (vec_concat:V16QI
5286            (vec_select:V8QI
5287              (match_operand:V16QI 1 "spu_reg_operand" "r")
5288              (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
5289                         (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))
5290            (vec_select:V8QI
5291              (match_operand:V16QI 2 "spu_reg_operand" "r")
5292              (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
5293                         (const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
5294          (parallel [(const_int 0)(const_int 8)(const_int 1)(const_int 9)
5295                     (const_int 2)(const_int 10)(const_int 3)(const_int 11)
5296                     (const_int 4)(const_int 12)(const_int 5)(const_int 13)
5297                     (const_int 6)(const_int 14)(const_int 7)(const_int 15)])))]
5299   ""
5300   "
5302   rtx mask = gen_reg_rtx (TImode);
5303   unsigned char arr[16] = {
5304         0x00, 0x10, 0x01, 0x11,
5305         0x02, 0x12, 0x03, 0x13,
5306         0x04, 0x14, 0x05, 0x15,
5307         0x06, 0x16, 0x07, 0x17};
5309   emit_move_insn (mask, array_to_constant (TImode, arr));
5310   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5311   DONE;
5314 (define_expand "vec_interleave_lowv16qi"
5315  [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
5316        (vec_select:V16QI
5317          (vec_concat:V16QI
5318            (vec_select:V8QI
5319              (match_operand:V16QI 1 "spu_reg_operand" "r")
5320              (parallel [(const_int 8)(const_int 9)(const_int 10)(const_int 11)
5321                         (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))
5322            (vec_select:V8QI
5323              (match_operand:V16QI 2 "spu_reg_operand" "r")
5324              (parallel [(const_int 8)(const_int 9)(const_int 10)(const_int 11)
5325                         (const_int 12)(const_int 13)(const_int 14)(const_int 15)])))
5326          (parallel [(const_int 0)(const_int 8)(const_int 1)(const_int 9)
5327                     (const_int 2)(const_int 10)(const_int 3)(const_int 11)
5328                     (const_int 4)(const_int 12)(const_int 5)(const_int 13)
5329                     (const_int 6)(const_int 14)(const_int 7)(const_int 15)])))]
5331   ""
5332   "
5334   rtx mask = gen_reg_rtx (TImode);
5335   unsigned char arr[16] = {
5336          0x08, 0x18, 0x09, 0x19,
5337          0x0A, 0x1A, 0x0B, 0x1B,
5338          0x0C, 0x1C, 0x0D, 0x1D,
5339          0x0E, 0x1E, 0x0F, 0x1F};
5341   emit_move_insn (mask, array_to_constant (TImode, arr));
5342   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5343   DONE;
5346 (define_expand "vec_pack_trunc_v8hi"
5347   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
5348         (vec_concat:V16QI
5349           (truncate:V8QI (match_operand:V8HI 1 "spu_reg_operand" "r"))
5350           (truncate:V8QI (match_operand:V8HI 2 "spu_reg_operand" "r"))))]
5351   ""
5352   "
5354   rtx mask = gen_reg_rtx (TImode);
5355   unsigned char arr[16] = {
5356     0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
5357     0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F};
5359   emit_move_insn (mask, array_to_constant (TImode, arr));
5360   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5362   DONE;
5365 (define_expand "vec_pack_trunc_v4si"
5366   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
5367         (vec_concat:V8HI
5368           (truncate:V4HI (match_operand:V4SI 1 "spu_reg_operand" "r"))
5369           (truncate:V4HI (match_operand:V4SI 2 "spu_reg_operand" "r"))))]
5370   ""
5371   "
5373   rtx mask = gen_reg_rtx (TImode);
5374   unsigned char arr[16] = {
5375     0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
5376     0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F};
5378   emit_move_insn (mask, array_to_constant (TImode, arr));
5379   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5381   DONE;
5384 (define_insn "stack_protect_set"
5385   [(set (match_operand:SI 0 "memory_operand" "=m")
5386         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
5387    (set (match_scratch:SI 2 "=&r") (const_int 0))]
5388   ""
5389   "lq%p1\t%2,%1\;stq%p0\t%2,%0\;xor\t%2,%2,%2"
5390   [(set_attr "length" "12")
5391    (set_attr "type" "multi1")]
5394 (define_expand "stack_protect_test"
5395   [(match_operand 0 "memory_operand" "")
5396    (match_operand 1 "memory_operand" "")
5397    (match_operand 2 "" "")]
5398   ""
5400   rtx compare_result;
5401   rtx bcomp, loc_ref;
5403   compare_result = gen_reg_rtx (SImode);
5405   emit_insn (gen_stack_protect_test_si (compare_result,
5406                                         operands[0],
5407                                         operands[1]));
5409   bcomp = gen_rtx_NE (SImode, compare_result, const0_rtx);
5411   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[2]);
5413   emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
5414                                    gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5415                                                          loc_ref, pc_rtx)));
5417   DONE;
5420 (define_insn "stack_protect_test_si"
5421   [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
5422         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
5423                     (match_operand:SI 2 "memory_operand" "m")]
5424                    UNSPEC_SP_TEST))
5425    (set (match_scratch:SI 3 "=&r") (const_int 0))]
5426   ""
5427   "lq%p1\t%0,%1\;lq%p2\t%3,%2\;ceq\t%0,%0,%3\;xor\t%3,%3,%3"
5428   [(set_attr "length" "16")
5429    (set_attr "type" "multi1")]