Fix compilation failure with C++98 compilers
[official-gcc.git] / gcc / config / spu / spu.md
blobcdc8a6820f2532af9dedf3f80c7cd8474d339455
1 ;; Copyright (C) 2006-2018 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_c_enum "unspec" [
105   UNSPEC_IPREFETCH
106   UNSPEC_FREST
107   UNSPEC_FRSQEST
108   UNSPEC_FI
109   UNSPEC_EXTEND_CMP
110   UNSPEC_CG
111   UNSPEC_CGX
112   UNSPEC_ADDX
113   UNSPEC_BG
114   UNSPEC_BGX
115   UNSPEC_SFX
116   UNSPEC_FSM
117   UNSPEC_HBR
118   UNSPEC_NOP
119   UNSPEC_CONVERT
120   UNSPEC_SELB
121   UNSPEC_SHUFB
122   UNSPEC_CPAT
123   UNSPEC_CNTB
124   UNSPEC_SUMB
125   UNSPEC_FSMB
126   UNSPEC_FSMH
127   UNSPEC_GBB
128   UNSPEC_GBH
129   UNSPEC_GB
130   UNSPEC_AVGB
131   UNSPEC_ABSDB
132   UNSPEC_ORX
133   UNSPEC_HEQ
134   UNSPEC_HGT
135   UNSPEC_HLGT
136   UNSPEC_STOP
137   UNSPEC_STOPD
138   UNSPEC_SET_INTR
139   UNSPEC_FSCRRD
140   UNSPEC_FSCRWR
141   UNSPEC_MFSPR
142   UNSPEC_MTSPR
143   UNSPEC_RDCH
144   UNSPEC_RCHCNT
145   UNSPEC_WRCH
146   UNSPEC_SPU_REALIGN_LOAD
147   UNSPEC_SPU_MASK_FOR_LOAD
148   UNSPEC_DFTSV
149   UNSPEC_FLOAT_EXTEND
150   UNSPEC_FLOAT_TRUNCATE
151   UNSPEC_SP_SET
152   UNSPEC_SP_TEST
155 (define_c_enum "unspecv" [
156   UNSPECV_BLOCKAGE
157   UNSPECV_LNOP
158   UNSPECV_NOP
159   UNSPECV_SYNC
162 (include "predicates.md")
163 (include "constraints.md")
166 ;; Mode iterators
168 (define_mode_iterator ALL [QI V16QI
169                         HI V8HI
170                         SI V4SI
171                         DI V2DI
172                         TI
173                         SF V4SF
174                         DF V2DF])
176 ; Everything except DI and TI which are handled separately because
177 ; they need different constraints to correctly test VOIDmode constants
178 (define_mode_iterator MOV [QI V16QI
179                         HI V8HI
180                         SI V4SI
181                         V2DI
182                         SF V4SF
183                         DF V2DF])
185 (define_mode_iterator QHSI  [QI HI SI])
186 (define_mode_iterator QHSDI  [QI HI SI DI])
187 (define_mode_iterator DTI  [DI TI])
189 (define_mode_iterator VINT [QI V16QI
190                          HI V8HI
191                          SI V4SI
192                          DI V2DI
193                          TI])
195 (define_mode_iterator VQHSI [QI V16QI
196                           HI V8HI
197                           SI V4SI])
199 (define_mode_iterator VHSI [HI V8HI
200                          SI V4SI])
202 (define_mode_iterator VSDF [SF V4SF
203                          DF V2DF])
205 (define_mode_iterator VSI [SI V4SI])
206 (define_mode_iterator VDI [DI V2DI])
207 (define_mode_iterator VSF [SF V4SF])
208 (define_mode_iterator VDF [DF V2DF])
210 (define_mode_iterator VCMP [V16QI
211                          V8HI
212                          V4SI
213                          V4SF
214                          V2DF])
216 (define_mode_iterator VCMPU [V16QI
217                           V8HI
218                           V4SI])
220 (define_mode_attr v      [(V8HI  "v") (V4SI  "v")
221                           (HI    "") (SI    "")])
223 (define_mode_attr bh  [(QI "b")  (V16QI "b")
224                        (HI "h")  (V8HI "h")
225                        (SI "")   (V4SI "")])
227 (define_mode_attr d   [(SF "")   (V4SF "")
228                        (DF "d")  (V2DF "d")])
229 (define_mode_attr d6  [(SF "6")  (V4SF "6")
230                        (DF "d")  (V2DF "d")])
232 (define_mode_attr f2i [(SF "si") (V4SF "v4si")
233                        (DF "di") (V2DF "v2di")])
234 (define_mode_attr F2I [(SF "SI") (V4SF "V4SI")
235                        (DF "DI") (V2DF "V2DI")])
236 (define_mode_attr i2f [(SI "sf") (V4SI "v4sf")
237                        (DI "df") (V2DI "v2df")])
238 (define_mode_attr I2F [(SI "SF") (V4SI "V4SF")
239                        (DI "DF") (V2DI "V2DF")])
241 (define_mode_attr DF2I [(DF "SI") (V2DF "V2DI")])
243 (define_mode_attr umask  [(HI "f")  (V8HI "f")
244                           (SI "g")  (V4SI "g")])
245 (define_mode_attr nmask  [(HI "F")  (V8HI "F")
246                           (SI "G")  (V4SI "G")])
248 ;; Used for carry and borrow instructions.
249 (define_mode_iterator CBOP  [SI DI V4SI V2DI])
251 ;; Used in vec_set and vec_extract
252 (define_mode_iterator V [V2DI V4SI V8HI V16QI V2DF V4SF])
253 (define_mode_attr inner  [(V16QI "QI")
254                           (V8HI  "HI")
255                           (V4SI  "SI")
256                           (V2DI  "DI")
257                           (V4SF  "SF")
258                           (V2DF  "DF")])
259 ;; Like above, but in lower case
260 (define_mode_attr inner_l [(V16QI "qi")
261                            (V8HI  "hi")
262                            (V4SI  "si")
263                            (V2DI  "di")
264                            (V4SF  "sf")
265                            (V2DF  "df")])
266 (define_mode_attr vmult  [(V16QI "1")
267                           (V8HI  "2")
268                           (V4SI  "4")
269                           (V2DI  "8")
270                           (V4SF  "4")
271                           (V2DF  "8")])
272 (define_mode_attr voff   [(V16QI "13")
273                           (V8HI  "14")
274                           (V4SI  "0")
275                           (V2DI  "0")
276                           (V4SF  "0")
277                           (V2DF  "0")])
280 ;; mov
282 (define_expand "mov<mode>"
283   [(set (match_operand:ALL 0 "nonimmediate_operand" "")
284         (match_operand:ALL 1 "general_operand" ""))]
285   ""
286   {
287     if (spu_expand_mov(operands, <MODE>mode))
288       DONE;
289   })
291 (define_split 
292   [(set (match_operand 0 "spu_reg_operand")
293         (match_operand 1 "immediate_operand"))]
295   ""
296   [(set (match_dup 0)
297         (high (match_dup 1)))
298    (set (match_dup 0)
299         (lo_sum (match_dup 0)
300                 (match_dup 1)))]
301   {
302     if (spu_split_immediate (operands))
303       DONE;
304     FAIL;
305   })
307 (define_insn "pic"
308   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
309         (match_operand:SI 1 "immediate_operand" "s"))
310    (use (const_int 0))]
311   "flag_pic"
312   "ila\t%0,%%pic(%1)")
314 ;; Whenever a function generates the 'pic' pattern above we need to
315 ;; load the pic_offset_table register.
316 ;; GCC doesn't deal well with labels in the middle of a block so we
317 ;; hardcode the offsets in the asm here.
318 (define_insn "load_pic_offset"
319   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
320         (unspec:SI [(const_int 0)] 0))
321    (set (match_operand:SI 1 "spu_reg_operand" "=r")
322         (unspec:SI [(const_int 0)] 0))]
323   "flag_pic"
324   "ila\t%1,.+8\;brsl\t%0,4"
325   [(set_attr "length" "8")
326    (set_attr "type" "multi0")])
329 ;; move internal
331 (define_insn "_mov<mode>"
332   [(set (match_operand:MOV 0 "spu_dest_operand" "=r,r,r,r,r,m")
333         (match_operand:MOV 1 "spu_mov_operand" "r,A,f,j,m,r"))]
334   "register_operand(operands[0], <MODE>mode)
335    || register_operand(operands[1], <MODE>mode)"
336   "@
337    ori\t%0,%1,0
338    il%s1\t%0,%S1
339    fsmbi\t%0,%S1
340    c%s1d\t%0,%S1($sp)
341    lq%p1\t%0,%1
342    stq%p0\t%1,%0"
343   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
345 (define_insn "low_<mode>"
346   [(set (match_operand:VSI 0 "spu_reg_operand" "=r")
347         (lo_sum:VSI (match_operand:VSI 1 "spu_reg_operand" "0")
348                     (match_operand:VSI 2 "immediate_operand" "i")))]
349   ""
350   "iohl\t%0,%2@l")
352 (define_insn "_movdi"
353   [(set (match_operand:DI 0 "spu_dest_operand" "=r,r,r,r,r,m")
354         (match_operand:DI 1 "spu_mov_operand" "r,a,f,k,m,r"))]
355   "register_operand(operands[0], DImode)
356    || register_operand(operands[1], DImode)"
357   "@
358    ori\t%0,%1,0
359    il%d1\t%0,%D1
360    fsmbi\t%0,%D1
361    c%d1d\t%0,%D1($sp)
362    lq%p1\t%0,%1
363    stq%p0\t%1,%0"
364   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
366 (define_insn "_movti"
367   [(set (match_operand:TI 0 "spu_dest_operand" "=r,r,r,r,r,m")
368         (match_operand:TI 1 "spu_mov_operand" "r,U,f,l,m,r"))]
369   "register_operand(operands[0], TImode)
370    || register_operand(operands[1], TImode)"
371   "@
372    ori\t%0,%1,0
373    il%t1\t%0,%T1
374    fsmbi\t%0,%T1
375    c%t1d\t%0,%T1($sp)
376    lq%p1\t%0,%1
377    stq%p0\t%1,%0"
378   [(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
380 (define_split
381   [(set (match_operand 0 "spu_reg_operand")
382         (match_operand 1 "memory_operand"))]
383   "GET_MODE_SIZE (GET_MODE (operands[0])) < 16
384    && GET_MODE(operands[0]) == GET_MODE(operands[1])
385    && !reload_in_progress && !reload_completed" 
386   [(set (match_dup 0)
387         (match_dup 1))]
388   { if (spu_split_load(operands))
389       DONE;
390   })
392 (define_split
393   [(set (match_operand 0 "memory_operand")
394         (match_operand 1 "spu_reg_operand"))]
395   "GET_MODE_SIZE (GET_MODE (operands[0])) < 16
396    && GET_MODE(operands[0]) == GET_MODE(operands[1])
397    && !reload_in_progress && !reload_completed" 
398   [(set (match_dup 0)
399         (match_dup 1))]
400   { if (spu_split_store(operands))
401       DONE;
402   })
403 ;; Operand 3 is the number of bytes. 1:b 2:h 4:w 8:d
405 (define_expand "cpat"
406   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
407         (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "r,r")
408                     (match_operand:SI 2 "spu_nonmem_operand" "r,n")
409                     (match_operand:SI 3 "immediate_operand" "i,i")] UNSPEC_CPAT))]
410   ""
411   {
412     rtx x = gen_cpat_const (operands);
413     if (x)
414       {
415         emit_move_insn (operands[0], x);
416         DONE;
417       }
418   })
420 (define_insn "_cpat"
421   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
422         (unspec:TI [(match_operand:SI 1 "spu_reg_operand" "r,r")
423                     (match_operand:SI 2 "spu_nonmem_operand" "r,n")
424                     (match_operand:SI 3 "immediate_operand" "i,i")] UNSPEC_CPAT))]
425   ""
426   "@
427    c%M3x\t%0,%1,%2
428    c%M3d\t%0,%C2(%1)"
429   [(set_attr "type" "shuf")])
431 (define_split
432   [(set (match_operand:TI 0 "spu_reg_operand")
433         (unspec:TI [(match_operand:SI 1 "spu_nonmem_operand")
434                     (match_operand:SI 2 "immediate_operand")
435                     (match_operand:SI 3 "immediate_operand")] UNSPEC_CPAT))]
436   ""
437   [(set (match_dup:TI 0)
438         (match_dup:TI 4))]
439   {
440     operands[4] = gen_cpat_const (operands);
441     if (!operands[4])
442       FAIL;
443   })
445 ;; extend
447 (define_insn "extendqihi2"
448   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
449         (sign_extend:HI (match_operand:QI 1 "spu_reg_operand" "r")))]
450   ""
451   "xsbh\t%0,%1")
453 (define_insn "extendhisi2"
454   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
455         (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r")))]
456   ""
457   "xshw\t%0,%1")
459 (define_expand "extendsidi2"
460   [(set (match_dup:DI 2)
461         (zero_extend:DI (match_operand:SI 1 "spu_reg_operand" "")))
462    (set (match_operand:DI 0 "spu_reg_operand" "")
463         (sign_extend:DI (vec_select:SI (match_dup:V2SI 3)
464                                        (parallel [(const_int 1)]))))]
465   ""
466   {
467     operands[2] = gen_reg_rtx (DImode);
468     operands[3] = spu_gen_subreg (V2SImode, operands[2]);
469   })
471 (define_insn "xswd"
472   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
473         (sign_extend:DI
474           (vec_select:SI
475             (match_operand:V2SI 1 "spu_reg_operand" "r")
476             (parallel [(const_int 1) ]))))]
477   ""
478   "xswd\t%0,%1");
480 ;; By splitting this late we don't allow much opportunity for sharing of
481 ;; constants.  That's ok because this should really be optimized away.
482 (define_insn_and_split "extend<mode>ti2"
483   [(set (match_operand:TI 0 "register_operand" "")
484         (sign_extend:TI (match_operand:QHSDI 1 "register_operand" "")))]
485   ""
486   "#"
487   ""
488   [(set (match_dup:TI 0)
489         (sign_extend:TI (match_dup:QHSDI 1)))]
490   {
491     spu_expand_sign_extend(operands);
492     DONE;
493   })
496 ;; zero_extend
498 (define_insn "zero_extendqihi2"
499   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
500         (zero_extend:HI (match_operand:QI 1 "spu_reg_operand" "r")))]
501   ""
502   "andi\t%0,%1,0x00ff")
504 (define_insn "zero_extendqisi2"
505   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
506         (zero_extend:SI (match_operand:QI 1 "spu_reg_operand" "r")))]
507   ""
508   "andi\t%0,%1,0x00ff")
510 (define_expand "zero_extendhisi2"
511   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
512         (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r")))
513    (clobber (match_scratch:SI 2 "=&r"))]
514   ""
515   {
516     rtx mask = gen_reg_rtx (SImode);
517     rtx op1 = simplify_gen_subreg (SImode, operands[1], HImode, 0);
518     emit_move_insn (mask, GEN_INT (0xffff));
519     emit_insn (gen_andsi3(operands[0], op1, mask));
520     DONE;
521   })
522   
523 (define_insn "zero_extendsidi2"
524   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
525         (zero_extend:DI (match_operand:SI 1 "spu_reg_operand" "r")))]
526   ""
527   "rotqmbyi\t%0,%1,-4"
528   [(set_attr "type" "shuf")])
530 (define_insn "zero_extendqiti2"
531   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
532         (zero_extend:TI (match_operand:QI 1 "spu_reg_operand" "r")))]
533   ""
534   "andi\t%0,%1,0x00ff\;rotqmbyi\t%0,%0,-12"
535   [(set_attr "type" "multi0")
536    (set_attr "length" "8")])
538 (define_insn "zero_extendhiti2"
539   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
540         (zero_extend:TI (match_operand:HI 1 "spu_reg_operand" "r")))]
541   ""
542   "shli\t%0,%1,16\;rotqmbyi\t%0,%0,-14"
543   [(set_attr "type" "multi1")
544    (set_attr "length" "8")])
546 (define_insn "zero_extendsiti2"
547   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
548         (zero_extend:TI (match_operand:SI 1 "spu_reg_operand" "r")))]
549   ""
550   "rotqmbyi\t%0,%1,-12"
551   [(set_attr "type" "shuf")])
553 (define_insn "zero_extendditi2"
554   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
555         (zero_extend:TI (match_operand:DI 1 "spu_reg_operand" "r")))]
556   ""
557   "rotqmbyi\t%0,%1,-8"
558   [(set_attr "type" "shuf")])
561 ;; trunc
563 (define_insn "truncdiqi2"
564   [(set (match_operand:QI 0 "spu_reg_operand" "=r")
565         (truncate:QI (match_operand:DI 1 "spu_reg_operand" "r")))]
566   ""
567   "shlqbyi\t%0,%1,4"
568   [(set_attr "type" "shuf")])
570 (define_insn "truncdihi2"
571   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
572         (truncate:HI (match_operand:DI 1 "spu_reg_operand" "r")))]
573   ""
574   "shlqbyi\t%0,%1,4"
575   [(set_attr "type" "shuf")])
577 (define_insn "truncdisi2"
578   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
579         (truncate:SI (match_operand:DI 1 "spu_reg_operand" "r")))]
580   ""
581   "shlqbyi\t%0,%1,4"
582   [(set_attr "type" "shuf")])
584 (define_insn "trunctiqi2"
585   [(set (match_operand:QI 0 "spu_reg_operand" "=r")
586         (truncate:QI (match_operand:TI 1 "spu_reg_operand" "r")))]
587   ""
588   "shlqbyi\t%0,%1,12"
589   [(set_attr "type" "shuf")])
591 (define_insn "trunctihi2"
592   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
593         (truncate:HI (match_operand:TI 1 "spu_reg_operand" "r")))]
594   ""
595   "shlqbyi\t%0,%1,12"
596   [(set_attr "type" "shuf")])
598 (define_insn "trunctisi2"
599   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
600         (truncate:SI (match_operand:TI 1 "spu_reg_operand" "r")))]
601   ""
602   "shlqbyi\t%0,%1,12"
603   [(set_attr "type" "shuf")])
605 (define_insn "trunctidi2"
606   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
607         (truncate:DI (match_operand:TI 1 "spu_reg_operand" "r")))]
608   ""
609   "shlqbyi\t%0,%1,8"
610   [(set_attr "type" "shuf")])
613 ;; float conversions
615 (define_insn "float<mode><i2f>2"
616   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
617         (float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r")))]
618   ""
619   "csflt\t%0,%1,0"
620   [(set_attr "type" "fp7")])
622 (define_insn "fix_trunc<mode><f2i>2"
623   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
624         (fix:<F2I> (match_operand:VSF 1 "spu_reg_operand" "r")))]
625   ""
626   "cflts\t%0,%1,0"
627   [(set_attr "type" "fp7")])
629 (define_insn "floatuns<mode><i2f>2"
630   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
631         (unsigned_float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r")))]
632   ""
633   "cuflt\t%0,%1,0"
634   [(set_attr "type" "fp7")])
636 (define_insn "fixuns_trunc<mode><f2i>2"
637   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
638         (unsigned_fix:<F2I> (match_operand:VSF 1 "spu_reg_operand" "r")))]
639   ""
640   "cfltu\t%0,%1,0"
641   [(set_attr "type" "fp7")])
643 (define_insn "float<mode><i2f>2_mul"
644   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
645         (mult:<I2F> (float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r"))
646                     (match_operand:<I2F> 2 "spu_inv_exp2_operand" "w")))]
647   ""
648   "csflt\t%0,%1,%w2"
649   [(set_attr "type" "fp7")])
651 (define_insn "float<mode><i2f>2_div"
652   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
653         (div:<I2F> (float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r"))
654                    (match_operand:<I2F> 2 "spu_exp2_operand" "v")))]
655   ""
656   "csflt\t%0,%1,%v2"
657   [(set_attr "type" "fp7")])
660 (define_insn "fix_trunc<mode><f2i>2_mul"
661   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
662         (fix:<F2I> (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
663                              (match_operand:VSF 2 "spu_exp2_operand" "v"))))]
664   ""
665   "cflts\t%0,%1,%v2"
666   [(set_attr "type" "fp7")])
668 (define_insn "floatuns<mode><i2f>2_mul"
669   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
670         (mult:<I2F> (unsigned_float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r"))
671                     (match_operand:<I2F> 2 "spu_inv_exp2_operand" "w")))]
672   ""
673   "cuflt\t%0,%1,%w2"
674   [(set_attr "type" "fp7")])
676 (define_insn "floatuns<mode><i2f>2_div"
677   [(set (match_operand:<I2F> 0 "spu_reg_operand" "=r")
678         (div:<I2F> (unsigned_float:<I2F> (match_operand:VSI 1 "spu_reg_operand" "r"))
679                    (match_operand:<I2F> 2 "spu_exp2_operand" "v")))]
680   ""
681   "cuflt\t%0,%1,%v2"
682   [(set_attr "type" "fp7")])
684 (define_insn "fixuns_trunc<mode><f2i>2_mul"
685   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
686         (unsigned_fix:<F2I> (mult:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
687                                       (match_operand:VSF 2 "spu_exp2_operand" "v"))))]
688   ""
689   "cfltu\t%0,%1,%v2"
690   [(set_attr "type" "fp7")])
692 (define_insn "extendsfdf2"
693   [(set (match_operand:DF 0 "spu_reg_operand" "=r")
694         (unspec:DF [(match_operand:SF 1 "spu_reg_operand" "r")]
695                    UNSPEC_FLOAT_EXTEND))]
696   ""
697   "fesd\t%0,%1"
698   [(set_attr "type" "fpd")])
700 (define_insn "truncdfsf2"
701   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
702         (unspec:SF [(match_operand:DF 1 "spu_reg_operand" "r")]
703                    UNSPEC_FLOAT_TRUNCATE))]
704   ""
705   "frds\t%0,%1"
706   [(set_attr "type" "fpd")])
708 (define_expand "floatdisf2"
709   [(set (match_operand:SF 0 "register_operand" "")
710         (float:SF (match_operand:DI 1 "register_operand" "")))]
711   ""
712   {
713     rtx c0 = gen_reg_rtx (SImode);
714     rtx r0 = gen_reg_rtx (DImode);
715     rtx r1 = gen_reg_rtx (SFmode);
716     rtx r2 = gen_reg_rtx (SImode);
717     rtx setneg = gen_reg_rtx (SImode);
718     rtx isneg = gen_reg_rtx (SImode);
719     rtx neg = gen_reg_rtx (DImode);
720     rtx mask = gen_reg_rtx (DImode);
722     emit_move_insn (c0, GEN_INT (-0x80000000ll));
724     emit_insn (gen_negdi2 (neg, operands[1]));
725     emit_insn (gen_cgt_di_m1 (isneg, operands[1]));
726     emit_insn (gen_extend_compare (mask, isneg));
727     emit_insn (gen_selb (r0, neg, operands[1], mask));
728     emit_insn (gen_andc_si (setneg, c0, isneg));
730     emit_insn (gen_floatunsdisf2 (r1, r0));
732     emit_insn (gen_iorsi3 (r2, gen_rtx_SUBREG (SImode, r1, 0), setneg));
733     emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, r2, 0));
734     DONE;
735   })
737 (define_insn_and_split "floatunsdisf2"
738   [(set (match_operand:SF 0 "register_operand" "=r")
739         (unsigned_float:SF (match_operand:DI 1 "register_operand" "r")))
740    (clobber (match_scratch:SF 2 "=r"))
741    (clobber (match_scratch:SF 3 "=r"))
742    (clobber (match_scratch:SF 4 "=r"))]
743   ""
744   "#"
745   "reload_completed"
746   [(set (match_dup:SF 0)
747         (unsigned_float:SF (match_dup:DI 1)))]
748   {
749     rtx op1_v4si = gen_rtx_REG (V4SImode, REGNO (operands[1]));
750     rtx op2_v4sf = gen_rtx_REG (V4SFmode, REGNO (operands[2]));
751     rtx op2_ti = gen_rtx_REG (TImode, REGNO (operands[2]));
752     rtx op3_ti = gen_rtx_REG (TImode, REGNO (operands[3]));
754     REAL_VALUE_TYPE scale;
755     real_2expN (&scale, 32, SFmode);
757     emit_insn (gen_floatunsv4siv4sf2 (op2_v4sf, op1_v4si));
758     emit_insn (gen_shlqby_ti (op3_ti, op2_ti, GEN_INT (4)));
760     emit_move_insn (operands[4],
761                     const_double_from_real_value (scale, SFmode));
762     emit_insn (gen_fmasf4 (operands[0],
763                            operands[2], operands[4], operands[3]));
764     DONE;
765   })
767 (define_expand "floattisf2"
768   [(set (match_operand:SF 0 "register_operand" "")
769         (float:SF (match_operand:TI 1 "register_operand" "")))]
770   ""
771   {
772     rtx c0 = gen_reg_rtx (SImode);
773     rtx r0 = gen_reg_rtx (TImode);
774     rtx r1 = gen_reg_rtx (SFmode);
775     rtx r2 = gen_reg_rtx (SImode);
776     rtx setneg = gen_reg_rtx (SImode);
777     rtx isneg = gen_reg_rtx (SImode);
778     rtx neg = gen_reg_rtx (TImode);
779     rtx mask = gen_reg_rtx (TImode);
781     emit_move_insn (c0, GEN_INT (-0x80000000ll));
783     emit_insn (gen_negti2 (neg, operands[1]));
784     emit_insn (gen_cgt_ti_m1 (isneg, operands[1]));
785     emit_insn (gen_extend_compare (mask, isneg));
786     emit_insn (gen_selb (r0, neg, operands[1], mask));
787     emit_insn (gen_andc_si (setneg, c0, isneg));
789     emit_insn (gen_floatunstisf2 (r1, r0));
791     emit_insn (gen_iorsi3 (r2, gen_rtx_SUBREG (SImode, r1, 0), setneg));
792     emit_move_insn (operands[0], gen_rtx_SUBREG (SFmode, r2, 0));
793     DONE;
794   })
796 (define_insn_and_split "floatunstisf2"
797   [(set (match_operand:SF 0 "register_operand" "=r")
798         (unsigned_float:SF (match_operand:TI 1 "register_operand" "r")))
799    (clobber (match_scratch:SF 2 "=r"))
800    (clobber (match_scratch:SF 3 "=r"))
801    (clobber (match_scratch:SF 4 "=r"))]
802   ""
803   "#"
804   "reload_completed"
805   [(set (match_dup:SF 0)
806         (unsigned_float:SF (match_dup:TI 1)))]
807   {
808     rtx op1_v4si = gen_rtx_REG (V4SImode, REGNO (operands[1]));
809     rtx op2_v4sf = gen_rtx_REG (V4SFmode, REGNO (operands[2]));
810     rtx op2_ti = gen_rtx_REG (TImode, REGNO (operands[2]));
811     rtx op3_ti = gen_rtx_REG (TImode, REGNO (operands[3]));
813     REAL_VALUE_TYPE scale;
814     real_2expN (&scale, 32, SFmode);
816     emit_insn (gen_floatunsv4siv4sf2 (op2_v4sf, op1_v4si));
817     emit_insn (gen_shlqby_ti (op3_ti, op2_ti, GEN_INT (4)));
819     emit_move_insn (operands[4],
820                     const_double_from_real_value (scale, SFmode));
821     emit_insn (gen_fmasf4 (operands[2],
822                            operands[2], operands[4], operands[3]));
824     emit_insn (gen_shlqby_ti (op3_ti, op3_ti, GEN_INT (4)));
825     emit_insn (gen_fmasf4 (operands[2],
826                            operands[2], operands[4], operands[3]));
828     emit_insn (gen_shlqby_ti (op3_ti, op3_ti, GEN_INT (4)));
829     emit_insn (gen_fmasf4 (operands[0],
830                            operands[2], operands[4], operands[3]));
831     DONE;
832   })
834 ;; Do (double)(operands[1]+0x80000000u)-(double)0x80000000
835 (define_expand "floatsidf2"
836   [(set (match_operand:DF 0 "register_operand" "")
837         (float:DF (match_operand:SI 1 "register_operand" "")))]
838   ""
839   {
840     rtx c0 = gen_reg_rtx (SImode);
841     rtx c1 = gen_reg_rtx (DFmode);
842     rtx r0 = gen_reg_rtx (SImode);
843     rtx r1 = gen_reg_rtx (DFmode);
845     emit_move_insn (c0, GEN_INT (-0x80000000ll));
846     emit_move_insn (c1, spu_float_const ("2147483648", DFmode));
847     emit_insn (gen_xorsi3 (r0, operands[1], c0));
848     emit_insn (gen_floatunssidf2 (r1, r0));
849     emit_insn (gen_subdf3 (operands[0], r1, c1));
850     DONE;
851   })
853 (define_expand "floatunssidf2"
854   [(set (match_operand:DF 0 "register_operand"  "=r")
855         (unsigned_float:DF (match_operand:SI 1 "register_operand"   "r")))]
856   ""
857   "{
858     rtx value;
859     rtx c0 = spu_const_from_ints (V16QImode, 0x02031011, 0x12138080, 
860                                              0x06071415, 0x16178080);
861     rtx r0 = gen_reg_rtx (V16QImode);
863     if (optimize_size)
864     {
865        start_sequence ();
866        value =
867          emit_library_call_value (convert_optab_libfunc (ufloat_optab,
868                                                          DFmode, SImode),
869                                   NULL_RTX, LCT_NORMAL, DFmode,
870                                   operands[1], SImode);
871        rtx_insn *insns = get_insns ();
872        end_sequence ();
873        emit_libcall_block (insns, operands[0], value,
874                            gen_rtx_UNSIGNED_FLOAT (DFmode, operands[1]));
875      }
876      else
877      {
878       emit_move_insn (r0, c0);
879       emit_insn (gen_floatunssidf2_internal (operands[0], operands[1], r0));
880      }
881     DONE;
882   }")
884 (define_insn_and_split "floatunssidf2_internal"
885   [(set (match_operand:DF 0 "register_operand"  "=r")
886         (unsigned_float:DF (match_operand:SI 1 "register_operand"   "r")))
887    (use (match_operand:V16QI 2 "register_operand" "r"))
888    (clobber (match_scratch:V4SI 3 "=&r"))
889    (clobber (match_scratch:V4SI 4 "=&r"))
890    (clobber (match_scratch:V4SI 5 "=&r"))
891    (clobber (match_scratch:V4SI 6 "=&r"))]
892   ""
893   "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"
894   "reload_completed"
895   [(set (match_dup:DF 0)
896         (unsigned_float:DF (match_dup:SI 1)))]
897  "{
898     rtx *ops = operands;
899     rtx op1_v4si = gen_rtx_REG(V4SImode, REGNO(ops[1]));
900     rtx op0_ti = gen_rtx_REG (TImode, REGNO (ops[0]));
901     rtx op2_ti = gen_rtx_REG (TImode, REGNO (ops[2]));
902     rtx op6_ti = gen_rtx_REG (TImode, REGNO (ops[6]));
903     emit_insn (gen_clzv4si2 (ops[3],op1_v4si));
904     emit_move_insn (ops[6], spu_const (V4SImode, 1023+31));
905     emit_insn (gen_vashlv4si3 (ops[4],op1_v4si,ops[3]));
906     emit_insn (gen_ceq_v4si (ops[5],ops[3],spu_const (V4SImode, 32)));
907     emit_insn (gen_subv4si3 (ops[6],ops[6],ops[3]));
908     emit_insn (gen_addv4si3 (ops[4],ops[4],ops[4]));
909     emit_insn (gen_andc_v4si  (ops[6],ops[6],ops[5]));
910     emit_insn (gen_shufb (ops[6],ops[6],ops[4],op2_ti));
911     emit_insn (gen_shlqbi_ti (op0_ti,op6_ti,GEN_INT(4)));
912     DONE;
913   }"
914  [(set_attr "length" "32")])
916 (define_expand "floatdidf2"
917   [(set (match_operand:DF 0 "register_operand" "")
918         (float:DF (match_operand:DI 1 "register_operand" "")))]
919   ""
920   {
921     rtx c0 = gen_reg_rtx (DImode);
922     rtx r0 = gen_reg_rtx (DImode);
923     rtx r1 = gen_reg_rtx (DFmode);
924     rtx r2 = gen_reg_rtx (DImode);
925     rtx setneg = gen_reg_rtx (DImode);
926     rtx isneg = gen_reg_rtx (SImode);
927     rtx neg = gen_reg_rtx (DImode);
928     rtx mask = gen_reg_rtx (DImode);
930     emit_move_insn (c0, GEN_INT (0x8000000000000000ull));
932     emit_insn (gen_negdi2 (neg, operands[1]));
933     emit_insn (gen_cgt_di_m1 (isneg, operands[1]));
934     emit_insn (gen_extend_compare (mask, isneg));
935     emit_insn (gen_selb (r0, neg, operands[1], mask));
936     emit_insn (gen_andc_di (setneg, c0, mask));
938     emit_insn (gen_floatunsdidf2 (r1, r0));
940     emit_insn (gen_iordi3 (r2, gen_rtx_SUBREG (DImode, r1, 0), setneg));
941     emit_move_insn (operands[0], gen_rtx_SUBREG (DFmode, r2, 0));
942     DONE;
943   })
945 (define_expand "floatunsdidf2"
946   [(set (match_operand:DF 0 "register_operand"  "=r")
947         (unsigned_float:DF (match_operand:DI 1 "register_operand"   "r")))]
948   ""
949   "{
950     rtx value;
951     rtx c0 = spu_const_from_ints (V16QImode, 0x02031011, 0x12138080, 
952                                              0x06071415, 0x16178080);
953     rtx c1 = spu_const_from_ints (V4SImode, 1023+63, 1023+31, 0, 0);
954     rtx r0 = gen_reg_rtx (V16QImode);
955     rtx r1 = gen_reg_rtx (V4SImode);
957     if (optimize_size)
958     {      
959       start_sequence ();
960       value =
961          emit_library_call_value (convert_optab_libfunc (ufloat_optab,
962                                                          DFmode, DImode),
963                                   NULL_RTX, LCT_NORMAL, DFmode,
964                                   operands[1], DImode);
965       rtx_insn *insns = get_insns ();
966       end_sequence ();
967       emit_libcall_block (insns, operands[0], value,
968                           gen_rtx_UNSIGNED_FLOAT (DFmode, operands[1]));
969     }
970     else
971     {
972       emit_move_insn (r1, c1);
973       emit_move_insn (r0, c0);
974       emit_insn (gen_floatunsdidf2_internal (operands[0], operands[1], r0, r1));
975     }
976     DONE;
977   }")
979 (define_insn_and_split "floatunsdidf2_internal"
980   [(set (match_operand:DF 0 "register_operand"  "=r")
981         (unsigned_float:DF (match_operand:DI 1 "register_operand"   "r")))
982    (use (match_operand:V16QI 2 "register_operand" "r"))
983    (use (match_operand:V4SI 3 "register_operand" "r"))
984    (clobber (match_scratch:V4SI 4 "=&r"))
985    (clobber (match_scratch:V4SI 5 "=&r"))
986    (clobber (match_scratch:V4SI 6 "=&r"))]
987   ""
988   "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"
989   "reload_completed"
990   [(set (match_operand:DF 0 "register_operand"  "=r")
991         (unsigned_float:DF (match_operand:DI 1 "register_operand"   "r")))]
992   "{
993     rtx *ops = operands;
994     rtx op1_v4si = gen_rtx_REG (V4SImode, REGNO(ops[1]));
995     rtx op2_ti = gen_rtx_REG (TImode, REGNO(ops[2]));
996     rtx op4_ti = gen_rtx_REG (TImode, REGNO(ops[4]));
997     rtx op5_ti = gen_rtx_REG (TImode, REGNO(ops[5]));
998     rtx op4_df = gen_rtx_REG (DFmode, REGNO(ops[4]));
999     rtx op5_df = gen_rtx_REG (DFmode, REGNO(ops[5]));
1000     emit_insn (gen_clzv4si2 (ops[4],op1_v4si));
1001     emit_insn (gen_vashlv4si3 (ops[5],op1_v4si,ops[4]));
1002     emit_insn (gen_ceq_v4si (ops[6],ops[4],spu_const (V4SImode, 32)));
1003     emit_insn (gen_subv4si3 (ops[4],ops[3],ops[4]));
1004     emit_insn (gen_addv4si3 (ops[5],ops[5],ops[5]));
1005     emit_insn (gen_andc_v4si (ops[4],ops[4],ops[6]));
1006     emit_insn (gen_shufb (ops[4],ops[4],ops[5],op2_ti));
1007     emit_insn (gen_shlqbi_ti (op4_ti,op4_ti,GEN_INT(4)));
1008     emit_insn (gen_shlqby_ti (op5_ti,op4_ti,GEN_INT(8)));
1009     emit_insn (gen_adddf3 (ops[0],op4_df,op5_df));
1010     DONE;
1011   }"
1012   [(set_attr "length" "40")])
1015 ;; add
1017 (define_expand "addv16qi3"
1018   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
1019         (plus:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")
1020                     (match_operand:V16QI 2 "spu_reg_operand" "r")))]
1021   ""
1022   "{
1023     rtx res_short = simplify_gen_subreg (V8HImode, operands[0], V16QImode, 0);
1024     rtx lhs_short = simplify_gen_subreg (V8HImode, operands[1], V16QImode, 0);
1025     rtx rhs_short = simplify_gen_subreg (V8HImode, operands[2], V16QImode, 0);
1026     rtx rhs_and = gen_reg_rtx (V8HImode);
1027     rtx hi_char = gen_reg_rtx (V8HImode);
1028     rtx lo_char = gen_reg_rtx (V8HImode);
1029     rtx mask = gen_reg_rtx (V8HImode);
1031     emit_move_insn (mask, spu_const (V8HImode, 0x00ff));
1032     emit_insn (gen_andv8hi3 (rhs_and, rhs_short, spu_const (V8HImode, 0xff00)));
1033     emit_insn (gen_addv8hi3 (hi_char, lhs_short, rhs_and));
1034     emit_insn (gen_addv8hi3 (lo_char, lhs_short, rhs_short));
1035     emit_insn (gen_selb (res_short, hi_char, lo_char, mask));
1036     DONE;
1037    }")
1039 (define_insn "add<mode>3"
1040   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
1041         (plus:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
1042                    (match_operand:VHSI 2 "spu_arith_operand" "r,B")))]
1043   ""
1044   "@
1045   a<bh>\t%0,%1,%2
1046   a<bh>i\t%0,%1,%2")
1048 (define_expand "add<mode>3"
1049   [(set (match_dup:VDI 3) 
1050         (unspec:VDI [(match_operand:VDI 1 "spu_reg_operand" "")
1051                      (match_operand:VDI 2 "spu_reg_operand" "")] UNSPEC_CG))
1052    (set (match_dup:VDI 5)
1053         (unspec:VDI [(match_dup 3)
1054                      (match_dup 3)
1055                      (match_dup:TI 4)] UNSPEC_SHUFB))
1056    (set (match_operand:VDI 0 "spu_reg_operand" "") 
1057         (unspec:VDI [(match_dup 1)
1058                      (match_dup 2)
1059                      (match_dup 5)] UNSPEC_ADDX))]
1060   ""
1061   {
1062     unsigned char pat[16] = {
1063       0x04, 0x05, 0x06, 0x07,
1064       0x80, 0x80, 0x80, 0x80,
1065       0x0c, 0x0d, 0x0e, 0x0f,
1066       0x80, 0x80, 0x80, 0x80
1067     };
1068     operands[3] = gen_reg_rtx (<MODE>mode);
1069     operands[4] = gen_reg_rtx (TImode);
1070     operands[5] = gen_reg_rtx (<MODE>mode);
1071     emit_move_insn (operands[4], array_to_constant (TImode, pat));
1072   })
1074 (define_insn "cg_<mode>"
1075   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1076         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1077                       (match_operand 2 "spu_reg_operand" "r")] UNSPEC_CG))]
1078   "operands != NULL"
1079   "cg\t%0,%1,%2")
1081 (define_insn "cgx_<mode>"
1082   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1083         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1084                       (match_operand 2 "spu_reg_operand" "r")
1085                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_CGX))]
1086   "operands != NULL"
1087   "cgx\t%0,%1,%2")
1089 (define_insn "addx_<mode>"
1090   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1091         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1092                       (match_operand 2 "spu_reg_operand" "r")
1093                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_ADDX))]
1094   "operands != NULL"
1095   "addx\t%0,%1,%2")
1098 ;; This is not the most efficient implementation of addti3.
1099 ;; We include this here because 1) the compiler needs it to be
1100 ;; defined as the word size is 128-bit and 2) sometimes gcc
1101 ;; substitutes an add for a constant left-shift. 2) is unlikely
1102 ;; because we also give addti3 a high cost. In case gcc does
1103 ;; generate TImode add, here is the code to do it.
1104 ;; operand 2 is a nonmemory because the compiler requires it.
1105 (define_insn "addti3"
1106   [(set (match_operand:TI 0 "spu_reg_operand" "=&r")
1107         (plus:TI (match_operand:TI 1 "spu_reg_operand" "r")
1108                  (match_operand:TI 2 "spu_nonmem_operand" "r")))
1109    (clobber (match_scratch:TI 3 "=&r"))]
1110   ""
1111   "cg\t%3,%1,%2\n\\
1112    shlqbyi\t%3,%3,4\n\\
1113    cgx\t%3,%1,%2\n\\
1114    shlqbyi\t%3,%3,4\n\\
1115    cgx\t%3,%1,%2\n\\
1116    shlqbyi\t%0,%3,4\n\\
1117    addx\t%0,%1,%2"
1118   [(set_attr "type" "multi0")
1119    (set_attr "length" "28")])
1121 (define_insn "add<mode>3"
1122   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1123         (plus:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1124                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
1125   ""
1126   "fa\t%0,%1,%2"
1127   [(set_attr "type" "fp6")])
1129 (define_insn "add<mode>3"
1130   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1131         (plus:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1132                   (match_operand:VDF 2 "spu_reg_operand" "r")))]
1133   ""
1134   "dfa\t%0,%1,%2"
1135   [(set_attr "type" "fpd")])
1138 ;; sub
1140 (define_expand "subv16qi3"
1141   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
1142         (minus:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")
1143                      (match_operand:V16QI 2 "spu_reg_operand" "r")))]
1144   ""
1145   "{
1146     rtx res_short = simplify_gen_subreg (V8HImode, operands[0], V16QImode, 0);
1147     rtx lhs_short = simplify_gen_subreg (V8HImode, operands[1], V16QImode, 0);
1148     rtx rhs_short = simplify_gen_subreg (V8HImode, operands[2], V16QImode, 0);
1149     rtx rhs_and = gen_reg_rtx (V8HImode);
1150     rtx hi_char = gen_reg_rtx (V8HImode);
1151     rtx lo_char = gen_reg_rtx (V8HImode);
1152     rtx mask = gen_reg_rtx (V8HImode);
1154     emit_move_insn (mask, spu_const (V8HImode, 0x00ff));
1155     emit_insn (gen_andv8hi3 (rhs_and, rhs_short, spu_const (V8HImode, 0xff00)));
1156     emit_insn (gen_subv8hi3 (hi_char, lhs_short, rhs_and));
1157     emit_insn (gen_subv8hi3 (lo_char, lhs_short, rhs_short));
1158     emit_insn (gen_selb (res_short, hi_char, lo_char, mask));
1159     DONE;
1160    }")
1162 (define_insn "sub<mode>3"
1163   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
1164         (minus:VHSI (match_operand:VHSI 1 "spu_arith_operand" "r,B")
1165                     (match_operand:VHSI 2 "spu_reg_operand" "r,r")))]
1166   ""
1167   "@
1168   sf<bh>\t%0,%2,%1
1169   sf<bh>i\t%0,%2,%1")
1171 (define_expand "sub<mode>3"
1172   [(set (match_dup:VDI 3) 
1173         (unspec:VDI [(match_operand:VDI 1 "spu_reg_operand" "")
1174                      (match_operand:VDI 2 "spu_reg_operand" "")] UNSPEC_BG))
1175    (set (match_dup:VDI 5)
1176         (unspec:VDI [(match_dup 3)
1177                      (match_dup 3)
1178                      (match_dup:TI 4)] UNSPEC_SHUFB))
1179    (set (match_operand:VDI 0 "spu_reg_operand" "") 
1180         (unspec:VDI [(match_dup 1)
1181                      (match_dup 2)
1182                      (match_dup 5)] UNSPEC_SFX))]
1183   ""
1184   {
1185     unsigned char pat[16] = {
1186       0x04, 0x05, 0x06, 0x07,
1187       0xc0, 0xc0, 0xc0, 0xc0,
1188       0x0c, 0x0d, 0x0e, 0x0f,
1189       0xc0, 0xc0, 0xc0, 0xc0
1190     };
1191     operands[3] = gen_reg_rtx (<MODE>mode);
1192     operands[4] = gen_reg_rtx (TImode);
1193     operands[5] = gen_reg_rtx (<MODE>mode);
1194     emit_move_insn (operands[4], array_to_constant (TImode, pat));
1195   })
1197 (define_insn "bg_<mode>"
1198   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1199         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1200                       (match_operand 2 "spu_reg_operand" "r")] UNSPEC_BG))]
1201   "operands != NULL"
1202   "bg\t%0,%2,%1")
1204 (define_insn "bgx_<mode>"
1205   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1206         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1207                       (match_operand 2 "spu_reg_operand" "r")
1208                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_BGX))]
1209   "operands != NULL"
1210   "bgx\t%0,%2,%1")
1212 (define_insn "sfx_<mode>"
1213   [(set (match_operand:CBOP 0 "spu_reg_operand" "=r")
1214         (unspec:CBOP [(match_operand 1 "spu_reg_operand" "r")
1215                       (match_operand 2 "spu_reg_operand" "r")
1216                       (match_operand 3 "spu_reg_operand" "0")] UNSPEC_SFX))]
1217   "operands != NULL"
1218   "sfx\t%0,%2,%1")
1220 (define_insn "subti3"
1221   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
1222         (minus:TI (match_operand:TI 1 "spu_reg_operand" "r")
1223                   (match_operand:TI 2 "spu_reg_operand" "r")))
1224    (clobber (match_scratch:TI 3 "=&r"))
1225    (clobber (match_scratch:TI 4 "=&r"))
1226    (clobber (match_scratch:TI 5 "=&r"))
1227    (clobber (match_scratch:TI 6 "=&r"))]
1228   ""
1229   "il\t%6,1\n\\
1230    bg\t%3,%2,%1\n\\
1231    xor\t%3,%3,%6\n\\
1232    sf\t%4,%2,%1\n\\
1233    shlqbyi\t%5,%3,4\n\\
1234    bg\t%3,%5,%4\n\\
1235    xor\t%3,%3,%6\n\\
1236    sf\t%4,%5,%4\n\\
1237    shlqbyi\t%5,%3,4\n\\
1238    bg\t%3,%5,%4\n\\
1239    xor\t%3,%3,%6\n\\
1240    sf\t%4,%5,%4\n\\
1241    shlqbyi\t%5,%3,4\n\\
1242    sf\t%0,%5,%4"
1243   [(set_attr "type" "multi0")
1244    (set_attr "length" "56")])
1246 (define_insn "sub<mode>3"
1247   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1248         (minus:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1249                    (match_operand:VSF 2 "spu_reg_operand" "r")))]
1250   ""
1251   "fs\t%0,%1,%2"
1252   [(set_attr "type" "fp6")])
1254 (define_insn "sub<mode>3"
1255   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1256         (minus:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1257                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
1258   ""
1259   "dfs\t%0,%1,%2"
1260   [(set_attr "type" "fpd")])
1263 ;; neg
1265 (define_expand "negv16qi2"
1266   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
1267         (neg:V16QI (match_operand:V16QI 1 "spu_reg_operand" "r")))]
1268   ""
1269   "{
1270     rtx zero = gen_reg_rtx (V16QImode);
1271     emit_move_insn (zero, CONST0_RTX (V16QImode));
1272     emit_insn (gen_subv16qi3 (operands[0], zero, operands[1]));
1273     DONE;
1274    }")
1276 (define_insn "neg<mode>2"
1277   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
1278         (neg:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")))]
1279   ""
1280   "sf<bh>i\t%0,%1,0")
1282 (define_expand "negdi2"
1283   [(set (match_operand:DI 0 "spu_reg_operand" "")
1284         (neg:DI (match_operand:DI 1 "spu_reg_operand" "")))]
1285   ""
1286   {
1287     rtx zero = gen_reg_rtx(DImode);
1288     emit_move_insn(zero, GEN_INT(0));
1289     emit_insn (gen_subdi3(operands[0], zero, operands[1]));
1290     DONE;
1291   })
1293 (define_expand "negti2"
1294   [(set (match_operand:TI 0 "spu_reg_operand" "")
1295         (neg:TI (match_operand:TI 1 "spu_reg_operand" "")))]
1296   ""
1297   {
1298     rtx zero = gen_reg_rtx(TImode);
1299     emit_move_insn(zero, GEN_INT(0));
1300     emit_insn (gen_subti3(operands[0], zero, operands[1]));
1301     DONE;
1302   })
1304 (define_expand "neg<mode>2"
1305   [(parallel
1306     [(set (match_operand:VSF 0 "spu_reg_operand" "")
1307           (neg:VSF (match_operand:VSF 1 "spu_reg_operand" "")))
1308      (use (match_dup 2))])]
1309   ""
1310   "operands[2] = gen_reg_rtx (<F2I>mode);
1311    emit_move_insn (operands[2], spu_const (<F2I>mode, -0x80000000ull));")
1313 (define_expand "neg<mode>2"
1314   [(parallel
1315     [(set (match_operand:VDF 0 "spu_reg_operand" "")
1316           (neg:VDF (match_operand:VDF 1 "spu_reg_operand" "")))
1317      (use (match_dup 2))])]
1318   ""
1319   "operands[2] = gen_reg_rtx (<F2I>mode);
1320    emit_move_insn (operands[2], spu_const (<F2I>mode, -0x8000000000000000ull));")
1322 (define_insn_and_split "_neg<mode>2"
1323   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1324         (neg:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")))
1325    (use (match_operand:<F2I> 2 "spu_reg_operand" "r"))]
1326   ""
1327   "#"
1328   ""
1329   [(set (match_dup:<F2I> 3)
1330         (xor:<F2I> (match_dup:<F2I> 4)
1331                    (match_dup:<F2I> 2)))]
1332   {
1333     operands[3] = spu_gen_subreg (<F2I>mode, operands[0]);
1334     operands[4] = spu_gen_subreg (<F2I>mode, operands[1]);
1335   })
1338 ;; abs
1340 (define_expand "abs<mode>2"
1341   [(parallel
1342     [(set (match_operand:VSF 0 "spu_reg_operand" "")
1343           (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "")))
1344      (use (match_dup 2))])]
1345   ""
1346   "operands[2] = gen_reg_rtx (<F2I>mode);
1347    emit_move_insn (operands[2], spu_const (<F2I>mode, 0x7fffffffull));")
1349 (define_expand "abs<mode>2"
1350   [(parallel
1351     [(set (match_operand:VDF 0 "spu_reg_operand" "")
1352           (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "")))
1353      (use (match_dup 2))])]
1354   ""
1355   "operands[2] = gen_reg_rtx (<F2I>mode);
1356    emit_move_insn (operands[2], spu_const (<F2I>mode, 0x7fffffffffffffffull));")
1358 (define_insn_and_split "_abs<mode>2"
1359   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1360         (abs:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")))
1361    (use (match_operand:<F2I> 2 "spu_reg_operand" "r"))]
1362   ""
1363   "#"
1364   ""
1365   [(set (match_dup:<F2I> 3)
1366         (and:<F2I> (match_dup:<F2I> 4)
1367                    (match_dup:<F2I> 2)))]
1368   {
1369     operands[3] = spu_gen_subreg (<F2I>mode, operands[0]);
1370     operands[4] = spu_gen_subreg (<F2I>mode, operands[1]);
1371   })
1374 ;; mul
1376 (define_insn "mulhi3"
1377   [(set (match_operand:HI 0 "spu_reg_operand" "=r,r")
1378         (mult:HI (match_operand:HI 1 "spu_reg_operand" "r,r")
1379                  (match_operand:HI 2 "spu_arith_operand" "r,B")))]
1380   ""
1381   "@
1382   mpy\t%0,%1,%2
1383   mpyi\t%0,%1,%2"
1384   [(set_attr "type" "fp7")])
1386 (define_expand "mulv8hi3"
1387   [(set (match_operand:V8HI 0 "spu_reg_operand" "")
1388         (mult:V8HI (match_operand:V8HI 1 "spu_reg_operand" "")
1389                    (match_operand:V8HI 2 "spu_reg_operand" "")))]
1390   ""
1391   "{
1392     rtx result = simplify_gen_subreg (V4SImode, operands[0], V8HImode, 0);
1393     rtx low = gen_reg_rtx (V4SImode);
1394     rtx high = gen_reg_rtx (V4SImode);
1395     rtx shift = gen_reg_rtx (V4SImode);
1396     rtx mask = gen_reg_rtx (V4SImode);
1398     emit_move_insn (mask, spu_const (V4SImode, 0x0000ffff));
1399     emit_insn (gen_vec_widen_smult_even_v8hi (high, operands[1], operands[2]));
1400     emit_insn (gen_vec_widen_smult_odd_v8hi (low, operands[1], operands[2]));
1401     emit_insn (gen_vashlv4si3 (shift, high, spu_const(V4SImode, 16)));
1402     emit_insn (gen_selb (result, shift, low, mask));
1403     DONE;
1404    }")
1406 (define_expand "mul<mode>3"
1407   [(parallel
1408     [(set (match_operand:VSI 0 "spu_reg_operand" "")
1409           (mult:VSI (match_operand:VSI 1 "spu_reg_operand" "")
1410                     (match_operand:VSI 2 "spu_reg_operand" "")))
1411      (clobber (match_dup:VSI 3))
1412      (clobber (match_dup:VSI 4))
1413      (clobber (match_dup:VSI 5))
1414      (clobber (match_dup:VSI 6))])]
1415   ""
1416   {
1417     operands[3] = gen_reg_rtx(<MODE>mode);
1418     operands[4] = gen_reg_rtx(<MODE>mode);
1419     operands[5] = gen_reg_rtx(<MODE>mode);
1420     operands[6] = gen_reg_rtx(<MODE>mode);
1421   })
1423 (define_insn_and_split "_mulsi3"
1424   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1425         (mult:SI (match_operand:SI 1 "spu_reg_operand" "r")
1426                  (match_operand:SI 2 "spu_arith_operand" "rK")))
1427    (clobber (match_operand:SI 3 "spu_reg_operand" "=&r"))
1428    (clobber (match_operand:SI 4 "spu_reg_operand" "=&r"))
1429    (clobber (match_operand:SI 5 "spu_reg_operand" "=&r"))
1430    (clobber (match_operand:SI 6 "spu_reg_operand" "=&r"))]
1431   ""
1432   "#"
1433   ""
1434   [(set (match_dup:SI 0)
1435         (mult:SI (match_dup:SI 1)
1436                  (match_dup:SI 2)))]
1437   {
1438     HOST_WIDE_INT val = 0;
1439     rtx a = operands[3];
1440     rtx b = operands[4];
1441     rtx c = operands[5];
1442     rtx d = operands[6];
1443     if (GET_CODE(operands[2]) == CONST_INT)
1444       {
1445         val = INTVAL(operands[2]);
1446         emit_move_insn(d, operands[2]);
1447         operands[2] = d;
1448       }
1449     if (val && (val & 0xffff) == 0)
1450       {
1451         emit_insn (gen_mpyh_si(operands[0], operands[2], operands[1]));
1452       }
1453     else if (val > 0 && val < 0x10000)
1454       {
1455         rtx cst = satisfies_constraint_K (GEN_INT (val)) ? GEN_INT(val) : d;
1456         emit_insn (gen_mpyh_si(a, operands[1], operands[2]));
1457         emit_insn (gen_mpyu_si(c, operands[1], cst));
1458         emit_insn (gen_addsi3(operands[0], a, c));
1459       }
1460     else
1461       {
1462         emit_insn (gen_mpyh_si(a, operands[1], operands[2]));
1463         emit_insn (gen_mpyh_si(b, operands[2], operands[1]));
1464         emit_insn (gen_mpyu_si(c, operands[1], operands[2]));
1465         emit_insn (gen_addsi3(d, a, b));
1466         emit_insn (gen_addsi3(operands[0], d, c));
1467       }
1468     DONE;
1469    })
1471 (define_insn_and_split "_mulv4si3"
1472   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
1473         (mult:V4SI (match_operand:V4SI 1 "spu_reg_operand" "r")
1474                    (match_operand:V4SI 2 "spu_reg_operand" "r")))
1475    (clobber (match_operand:V4SI 3 "spu_reg_operand" "=&r"))
1476    (clobber (match_operand:V4SI 4 "spu_reg_operand" "=&r"))
1477    (clobber (match_operand:V4SI 5 "spu_reg_operand" "=&r"))
1478    (clobber (match_operand:V4SI 6 "spu_reg_operand" "=&r"))]
1479   ""
1480   "#"
1481   ""
1482   [(set (match_dup:V4SI 0)
1483         (mult:V4SI (match_dup:V4SI 1)
1484                    (match_dup:V4SI 2)))]
1485   {
1486     rtx a = operands[3];
1487     rtx b = operands[4];
1488     rtx c = operands[5];
1489     rtx d = operands[6];
1490     rtx op1 = simplify_gen_subreg (V8HImode, operands[1], V4SImode, 0);
1491     rtx op2 = simplify_gen_subreg (V8HImode, operands[2], V4SImode, 0);
1492     emit_insn (gen_spu_mpyh(a, op1, op2));
1493     emit_insn (gen_spu_mpyh(b, op2, op1));
1494     emit_insn (gen_vec_widen_umult_odd_v8hi (c, op1, op2));
1495     emit_insn (gen_addv4si3(d, a, b));
1496     emit_insn (gen_addv4si3(operands[0], d, c));
1497     DONE;
1498    })
1500 (define_insn "mulhisi3"
1501   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1502         (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1503                  (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r"))))]
1504   ""
1505   "mpy\t%0,%1,%2"
1506   [(set_attr "type" "fp7")])
1508 (define_insn "mulhisi3_imm"
1509   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1510         (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1511                  (match_operand:SI 2 "imm_K_operand" "K")))]
1512   ""
1513   "mpyi\t%0,%1,%2"
1514   [(set_attr "type" "fp7")])
1516 (define_insn "umulhisi3"
1517   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1518         (mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1519                  (zero_extend:SI (match_operand:HI 2 "spu_reg_operand" "r"))))]
1520   ""
1521   "mpyu\t%0,%1,%2"
1522   [(set_attr "type" "fp7")])
1524 (define_insn "umulhisi3_imm"
1525   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1526         (mult:SI (zero_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1527                  (and:SI (match_operand:SI 2 "imm_K_operand" "K") (const_int 65535))))]
1528   ""
1529   "mpyui\t%0,%1,%2"
1530   [(set_attr "type" "fp7")])
1532 (define_insn "mpyu_si"
1533   [(set (match_operand:SI 0 "spu_reg_operand" "=r,r")
1534         (mult:SI (and:SI (match_operand:SI 1 "spu_reg_operand" "r,r")
1535                          (const_int 65535))
1536                  (and:SI (match_operand:SI 2 "spu_arith_operand" "r,K")
1537                          (const_int 65535))))]
1538   ""
1539   "@
1540    mpyu\t%0,%1,%2
1541    mpyui\t%0,%1,%2"
1542   [(set_attr "type" "fp7")])
1544 ;; This isn't always profitable to use.  Consider r = a * b + c * d.
1545 ;; It's faster to do the multiplies in parallel then add them.  If we
1546 ;; merge a multiply and add it prevents the multiplies from happening in
1547 ;; parallel.
1548 (define_insn "mpya_si"
1549   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1550         (plus:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1551                           (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r")))
1552                  (match_operand:SI 3 "spu_reg_operand" "r")))]
1553   "0"
1554   "mpya\t%0,%1,%2,%3"
1555   [(set_attr "type" "fp7")])
1557 (define_insn "mpyh_si"
1558   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1559         (mult:SI (and:SI (match_operand:SI 1 "spu_reg_operand" "r")
1560                          (const_int -65536))
1561                  (and:SI (match_operand:SI 2 "spu_reg_operand" "r")
1562                          (const_int 65535))))]
1563   ""
1564   "mpyh\t%0,%1,%2"
1565   [(set_attr "type" "fp7")])
1567 (define_insn "mpys_si"
1568   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1569         (ashiftrt:SI
1570             (mult:SI (sign_extend:SI (match_operand:HI 1 "spu_reg_operand" "r"))
1571                      (sign_extend:SI (match_operand:HI 2 "spu_reg_operand" "r")))
1572             (const_int 16)))]
1573   ""
1574   "mpys\t%0,%1,%2"
1575   [(set_attr "type" "fp7")])
1577 (define_insn "mpyhh_si"
1578   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1579         (mult:SI (ashiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1580                               (const_int 16))
1581                  (ashiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1582                               (const_int 16))))]
1583   ""
1584   "mpyhh\t%0,%1,%2"
1585   [(set_attr "type" "fp7")])
1587 (define_insn "mpyhhu_si"
1588   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1589         (mult:SI (lshiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1590                               (const_int 16))
1591                  (lshiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1592                               (const_int 16))))]
1593   ""
1594   "mpyhhu\t%0,%1,%2"
1595   [(set_attr "type" "fp7")])
1597 (define_insn "mpyhha_si" 
1598   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
1599         (plus:SI (mult:SI (ashiftrt:SI (match_operand:SI 1 "spu_reg_operand" "r")
1600                                        (const_int 16))
1601                           (ashiftrt:SI (match_operand:SI 2 "spu_reg_operand" "r")
1602                                        (const_int 16)))
1603                  (match_operand:SI 3 "spu_reg_operand" "0")))]
1604   "0"
1605   "mpyhha\t%0,%1,%2"
1606   [(set_attr "type" "fp7")])
1608 (define_insn "mul<mode>3"
1609   [(set (match_operand:VSDF 0 "spu_reg_operand" "=r")
1610         (mult:VSDF (match_operand:VSDF 1 "spu_reg_operand" "r")
1611                    (match_operand:VSDF 2 "spu_reg_operand" "r")))]
1612   ""
1613   "<d>fm\t%0,%1,%2"
1614   [(set_attr "type" "fp<d6>")])
1616 (define_insn "fma<mode>4"
1617   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1618         (fma:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1619                  (match_operand:VSF 2 "spu_reg_operand" "r")
1620                  (match_operand:VSF 3 "spu_reg_operand" "r")))]
1621   ""
1622   "fma\t%0,%1,%2,%3"
1623   [(set_attr "type"     "fp6")])
1625 ;; ??? The official description is (c - a*b), which is exactly (-a*b + c).
1626 ;; Note that this doesn't match the dfnms description.  Incorrect?
1627 (define_insn "fnma<mode>4"
1628   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1629         (fma:VSF
1630           (neg:VSF (match_operand:VSF 1 "spu_reg_operand" "r"))
1631           (match_operand:VSF 2 "spu_reg_operand" "r")
1632           (match_operand:VSF 3 "spu_reg_operand" "r")))]
1633   ""
1634   "fnms\t%0,%1,%2,%3"
1635   [(set_attr "type" "fp6")])
1637 (define_insn "fms<mode>4"
1638   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1639         (fma:VSF
1640           (match_operand:VSF 1 "spu_reg_operand" "r")
1641           (match_operand:VSF 2 "spu_reg_operand" "r")
1642           (neg:VSF (match_operand:VSF 3 "spu_reg_operand" "r"))))]
1643   ""
1644   "fms\t%0,%1,%2,%3"
1645   [(set_attr "type" "fp6")])
1647 (define_insn "fma<mode>4"
1648   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1649         (fma:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1650                  (match_operand:VDF 2 "spu_reg_operand" "r")
1651                  (match_operand:VDF 3 "spu_reg_operand" "0")))]
1652   ""
1653   "dfma\t%0,%1,%2"
1654   [(set_attr "type"     "fpd")])
1656 (define_insn "fms<mode>4"
1657   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1658         (fma:VDF
1659           (match_operand:VDF 1 "spu_reg_operand" "r")
1660           (match_operand:VDF 2 "spu_reg_operand" "r")
1661           (neg:VDF (match_operand:VDF 3 "spu_reg_operand" "0"))))]
1662   ""
1663   "dfms\t%0,%1,%2"
1664   [(set_attr "type" "fpd")])
1666 (define_insn "nfma<mode>4"
1667   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1668         (neg:VDF
1669           (fma:VDF (match_operand:VDF 1 "spu_reg_operand" "r")
1670                    (match_operand:VDF 2 "spu_reg_operand" "r")
1671                    (match_operand:VDF 3 "spu_reg_operand" "0"))))]
1672   ""
1673   "dfnma\t%0,%1,%2"
1674   [(set_attr "type"     "fpd")])
1676 (define_insn "nfms<mode>4"
1677   [(set (match_operand:VDF 0 "spu_reg_operand" "=r")
1678         (neg:VDF
1679           (fma:VDF
1680             (match_operand:VDF 1 "spu_reg_operand" "r")
1681             (match_operand:VDF 2 "spu_reg_operand" "r")
1682             (neg:VDF (match_operand:VDF 3 "spu_reg_operand" "0")))))]
1683   ""
1684   "dfnms\t%0,%1,%2"
1685   [(set_attr "type" "fpd")])
1687 ;; If signed zeros are ignored, -(a * b - c) = -a * b + c.
1688 (define_expand "fnma<mode>4"
1689   [(set (match_operand:VDF 0 "spu_reg_operand" "")
1690         (neg:VDF
1691           (fma:VDF
1692             (match_operand:VDF 1 "spu_reg_operand" "")
1693             (match_operand:VDF 2 "spu_reg_operand" "")
1694             (neg:VDF (match_operand:VDF 3 "spu_reg_operand" "")))))]
1695   "!HONOR_SIGNED_ZEROS (<MODE>mode)"
1696   "")
1698 ;; If signed zeros are ignored, -(a * b + c) = -a * b - c.
1699 (define_expand "fnms<mode>4"
1700   [(set (match_operand:VDF 0 "register_operand" "")
1701         (neg:VDF
1702           (fma:VDF
1703             (match_operand:VDF 1 "register_operand" "")
1704             (match_operand:VDF 2 "register_operand" "")
1705             (match_operand:VDF 3 "register_operand" ""))))]
1706   "!HONOR_SIGNED_ZEROS (<MODE>mode)"
1707   "")
1709 ;; mul highpart, used for divide by constant optimizations.
1711 (define_expand "smulsi3_highpart"
1712   [(set (match_operand:SI 0 "register_operand" "")
1713         (truncate:SI
1714           (ashiftrt:DI
1715             (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
1716                      (sign_extend:DI (match_operand:SI 2 "register_operand" "")))
1717             (const_int 32))))]
1718   ""
1719   {
1720     rtx t0 = gen_reg_rtx (SImode);
1721     rtx t1 = gen_reg_rtx (SImode);
1722     rtx t2 = gen_reg_rtx (SImode);
1723     rtx t3 = gen_reg_rtx (SImode);
1724     rtx t4 = gen_reg_rtx (SImode);
1725     rtx t5 = gen_reg_rtx (SImode);
1726     rtx t6 = gen_reg_rtx (SImode);
1727     rtx t7 = gen_reg_rtx (SImode);
1728     rtx t8 = gen_reg_rtx (SImode);
1729     rtx t9 = gen_reg_rtx (SImode);
1730     rtx t11 = gen_reg_rtx (SImode);
1731     rtx t12 = gen_reg_rtx (SImode);
1732     rtx t14 = gen_reg_rtx (SImode);
1733     rtx t15 = gen_reg_rtx (HImode);
1734     rtx t16 = gen_reg_rtx (HImode);
1735     rtx t17 = gen_reg_rtx (HImode);
1736     rtx t18 = gen_reg_rtx (HImode);
1737     rtx t19 = gen_reg_rtx (SImode);
1738     rtx t20 = gen_reg_rtx (SImode);
1739     rtx t21 = gen_reg_rtx (SImode);
1740     rtx op1_hi = gen_rtx_SUBREG (HImode, operands[1], 2);
1741     rtx op2_hi = gen_rtx_SUBREG (HImode, operands[2], 2);
1742     rtx t0_hi = gen_rtx_SUBREG (HImode, t0, 2);
1743     rtx t1_hi = gen_rtx_SUBREG (HImode, t1, 2);
1745     rtx_insn *insn = emit_insn (gen_lshrsi3 (t0, operands[1], GEN_INT (16)));
1746     emit_insn (gen_lshrsi3 (t1, operands[2], GEN_INT (16)));
1747     emit_insn (gen_umulhisi3 (t2, op1_hi, op2_hi));
1748     emit_insn (gen_mpyh_si (t3, operands[1], operands[2]));
1749     emit_insn (gen_mpyh_si (t4, operands[2], operands[1]));
1750     emit_insn (gen_mpyhh_si (t5, operands[1], operands[2]));
1751     emit_insn (gen_mpys_si (t6, t0_hi, op2_hi));
1752     emit_insn (gen_mpys_si (t7, t1_hi, op1_hi));
1754     /* Gen carry bits (in t9 and t11). */
1755     emit_insn (gen_addsi3 (t8, t2, t3));
1756     emit_insn (gen_cg_si (t9, t2, t3));
1757     emit_insn (gen_cg_si (t11, t8, t4));
1759     /* Gen high 32 bits in operand[0].  Correct for mpys. */
1760     emit_insn (gen_addx_si (t12, t5, t6, t9));
1761     emit_insn (gen_addx_si (t14, t12, t7, t11));
1763     /* mpys treats both operands as signed when we really want it to treat
1764        the first operand as signed and the second operand as unsigned.
1765        The code below corrects for that difference.  */
1766     emit_insn (gen_cgt_hi (t15, op1_hi, GEN_INT (-1)));
1767     emit_insn (gen_cgt_hi (t16, op2_hi, GEN_INT (-1)));
1768     emit_insn (gen_andc_hi (t17, t1_hi, t15));
1769     emit_insn (gen_andc_hi (t18, t0_hi, t16));
1770     emit_insn (gen_extendhisi2 (t19, t17));
1771     emit_insn (gen_extendhisi2 (t20, t18));
1772     emit_insn (gen_addsi3 (t21, t19, t20));
1773     emit_insn (gen_addsi3 (operands[0], t14, t21));
1774     unshare_all_rtl_in_chain (insn);
1775     DONE;
1776   })
1778 (define_expand "umulsi3_highpart"
1779   [(set (match_operand:SI 0 "register_operand" "")
1780         (truncate:SI
1781           (ashiftrt:DI
1782             (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
1783                      (zero_extend:DI (match_operand:SI 2 "register_operand" "")))
1784             (const_int 32))))]
1785   ""
1786   
1787   {
1788     rtx t0 = gen_reg_rtx (SImode);
1789     rtx t1 = gen_reg_rtx (SImode);
1790     rtx t2 = gen_reg_rtx (SImode);
1791     rtx t3 = gen_reg_rtx (SImode);
1792     rtx t4 = gen_reg_rtx (SImode);
1793     rtx t5 = gen_reg_rtx (SImode);
1794     rtx t6 = gen_reg_rtx (SImode);
1795     rtx t7 = gen_reg_rtx (SImode);
1796     rtx t8 = gen_reg_rtx (SImode);
1797     rtx t9 = gen_reg_rtx (SImode);
1798     rtx t10 = gen_reg_rtx (SImode);
1799     rtx t12 = gen_reg_rtx (SImode);
1800     rtx t13 = gen_reg_rtx (SImode);
1801     rtx t14 = gen_reg_rtx (SImode);
1802     rtx op1_hi = gen_rtx_SUBREG (HImode, operands[1], 2);
1803     rtx op2_hi = gen_rtx_SUBREG (HImode, operands[2], 2);
1804     rtx t0_hi = gen_rtx_SUBREG (HImode, t0, 2);
1806     rtx_insn *insn = emit_insn (gen_rotlsi3 (t0, operands[2], GEN_INT (16)));
1807     emit_insn (gen_umulhisi3 (t1, op1_hi, op2_hi));
1808     emit_insn (gen_umulhisi3 (t2, op1_hi, t0_hi));
1809     emit_insn (gen_mpyhhu_si (t3, operands[1], t0));
1810     emit_insn (gen_mpyhhu_si (t4, operands[1], operands[2]));
1811     emit_insn (gen_ashlsi3 (t5, t2, GEN_INT (16)));
1812     emit_insn (gen_ashlsi3 (t6, t3, GEN_INT (16)));
1813     emit_insn (gen_lshrsi3 (t7, t2, GEN_INT (16)));
1814     emit_insn (gen_lshrsi3 (t8, t3, GEN_INT (16)));
1816     /* Gen carry bits (in t10 and t12). */
1817     emit_insn (gen_addsi3 (t9, t1, t5));
1818     emit_insn (gen_cg_si (t10, t1, t5));
1819     emit_insn (gen_cg_si (t12, t9, t6));
1821     /* Gen high 32 bits in operand[0]. */
1822     emit_insn (gen_addx_si (t13, t4, t7, t10));
1823     emit_insn (gen_addx_si (t14, t13, t8, t12));
1824     emit_insn (gen_movsi (operands[0], t14));
1825     unshare_all_rtl_in_chain (insn);
1827     DONE;
1828   })
1830 ;; div
1832 ;; Not necessarily the best implementation of divide but faster then
1833 ;; the default that gcc provides because this is inlined and it uses
1834 ;; clz.
1835 (define_insn "divmodsi4"
1836       [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
1837             (div:SI (match_operand:SI 1 "spu_reg_operand" "r")
1838                     (match_operand:SI 2 "spu_reg_operand" "r")))
1839        (set (match_operand:SI 3 "spu_reg_operand" "=&r")
1840             (mod:SI (match_dup 1)
1841                     (match_dup 2)))
1842        (clobber (match_scratch:SI 4 "=&r"))
1843        (clobber (match_scratch:SI 5 "=&r"))
1844        (clobber (match_scratch:SI 6 "=&r"))
1845        (clobber (match_scratch:SI 7 "=&r"))
1846        (clobber (match_scratch:SI 8 "=&r"))
1847        (clobber (match_scratch:SI 9 "=&r"))
1848        (clobber (match_scratch:SI 10 "=&r"))
1849        (clobber (match_scratch:SI 11 "=&r"))
1850        (clobber (match_scratch:SI 12 "=&r"))
1851        (clobber (reg:SI 130))]
1852   ""
1853   "heqi %2,0\\n\\
1854         hbrr    3f,1f\\n\\
1855         sfi     %8,%1,0\\n\\
1856         sfi     %9,%2,0\\n\\
1857         cgti    %10,%1,-1\\n\\
1858         cgti    %11,%2,-1\\n\\
1859         selb    %8,%8,%1,%10\\n\\
1860         selb    %9,%9,%2,%11\\n\\
1861         clz     %4,%8\\n\\
1862         clz     %7,%9\\n\\
1863         il      %5,1\\n\\
1864         fsmbi   %0,0\\n\\
1865         sf      %7,%4,%7\\n\\
1866         shlqbyi %3,%8,0\\n\\
1867         xor     %11,%10,%11\\n\\
1868         shl     %5,%5,%7\\n\\
1869         shl     %4,%9,%7\\n\\
1870         lnop    \\n\\
1871 1:      or      %12,%0,%5\\n\\
1872         rotqmbii        %5,%5,-1\\n\\
1873         clgt    %6,%4,%3\\n\\
1874         lnop    \\n\\
1875         sf      %7,%4,%3\\n\\
1876         rotqmbii        %4,%4,-1\\n\\
1877         selb    %0,%12,%0,%6\\n\\
1878         lnop    \\n\\
1879         selb    %3,%7,%3,%6\\n\\
1880 3:      brnz    %5,1b\\n\\
1881 2:      sfi     %8,%3,0\\n\\
1882         sfi     %9,%0,0\\n\\
1883         selb    %3,%8,%3,%10\\n\\
1884         selb    %0,%0,%9,%11"
1885   [(set_attr "type" "multi0")
1886    (set_attr "length" "128")])
1888 (define_insn "udivmodsi4"
1889       [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
1890             (udiv:SI (match_operand:SI 1 "spu_reg_operand" "r")
1891                      (match_operand:SI 2 "spu_reg_operand" "r")))
1892        (set (match_operand:SI 3 "spu_reg_operand" "=&r")
1893             (umod:SI (match_dup 1)
1894                      (match_dup 2)))
1895        (clobber (match_scratch:SI 4 "=&r"))
1896        (clobber (match_scratch:SI 5 "=&r"))
1897        (clobber (match_scratch:SI 6 "=&r"))
1898        (clobber (match_scratch:SI 7 "=&r"))
1899        (clobber (match_scratch:SI 8 "=&r"))
1900        (clobber (reg:SI 130))]
1901   ""
1902   "heqi %2,0\\n\\
1903         hbrr    3f,1f\\n\\
1904         clz     %7,%2\\n\\
1905         clz     %4,%1\\n\\
1906         il      %5,1\\n\\
1907         fsmbi   %0,0\\n\\
1908         sf      %7,%4,%7\\n\\
1909         ori     %3,%1,0\\n\\
1910         shl     %5,%5,%7\\n\\
1911         shl     %4,%2,%7\\n\\
1912 1:      or      %8,%0,%5\\n\\
1913         rotqmbii        %5,%5,-1\\n\\
1914         clgt    %6,%4,%3\\n\\
1915         lnop    \\n\\
1916         sf      %7,%4,%3\\n\\
1917         rotqmbii        %4,%4,-1\\n\\
1918         selb    %0,%8,%0,%6\\n\\
1919         lnop    \\n\\
1920         selb    %3,%7,%3,%6\\n\\
1921 3:      brnz    %5,1b\\n\\
1923   [(set_attr "type" "multi0")
1924    (set_attr "length" "80")])
1926 (define_expand "div<mode>3"
1927   [(parallel
1928     [(set (match_operand:VSF 0 "spu_reg_operand" "")    
1929           (div:VSF (match_operand:VSF 1 "spu_reg_operand" "")
1930                    (match_operand:VSF 2 "spu_reg_operand" "")))
1931      (clobber (match_scratch:VSF 3 ""))
1932      (clobber (match_scratch:VSF 4 ""))
1933      (clobber (match_scratch:VSF 5 ""))])]
1934   ""
1935   "")
1937 (define_insn_and_split "*div<mode>3_fast"
1938   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1939         (div:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1940                  (match_operand:VSF 2 "spu_reg_operand" "r")))
1941    (clobber (match_scratch:VSF 3 "=&r"))
1942    (clobber (match_scratch:VSF 4 "=&r"))
1943    (clobber (scratch:VSF))]
1944   "flag_unsafe_math_optimizations"
1945   "#"
1946   "reload_completed"
1947   [(set (match_dup:VSF 0)
1948         (div:VSF (match_dup:VSF 1)
1949                  (match_dup:VSF 2)))
1950    (clobber (match_dup:VSF 3))
1951    (clobber (match_dup:VSF 4))
1952    (clobber (scratch:VSF))]
1953   {
1954     emit_insn (gen_frest_<mode>(operands[3], operands[2]));
1955     emit_insn (gen_fi_<mode>(operands[3], operands[2], operands[3]));
1956     emit_insn (gen_mul<mode>3(operands[4], operands[1], operands[3]));
1957     emit_insn (gen_fnma<mode>4(operands[0], operands[4], operands[2], operands[1]));
1958     emit_insn (gen_fma<mode>4(operands[0], operands[0], operands[3], operands[4]));
1959     DONE;
1960   })
1962 (define_insn_and_split "*div<mode>3_adjusted"
1963   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
1964         (div:VSF (match_operand:VSF 1 "spu_reg_operand" "r")
1965                  (match_operand:VSF 2 "spu_reg_operand" "r")))
1966    (clobber (match_scratch:VSF 3 "=&r"))
1967    (clobber (match_scratch:VSF 4 "=&r"))
1968    (clobber (match_scratch:VSF 5 "=&r"))]
1969   "!flag_unsafe_math_optimizations"
1970   "#"
1971   "reload_completed"
1972   [(set (match_dup:VSF 0)
1973         (div:VSF (match_dup:VSF 1)
1974                  (match_dup:VSF 2)))
1975    (clobber (match_dup:VSF 3))
1976    (clobber (match_dup:VSF 4))
1977    (clobber (match_dup:VSF 5))]
1978   {
1979     emit_insn (gen_frest_<mode> (operands[3], operands[2]));
1980     emit_insn (gen_fi_<mode> (operands[3], operands[2], operands[3]));
1981     emit_insn (gen_mul<mode>3 (operands[4], operands[1], operands[3]));
1982     emit_insn (gen_fnma<mode>4 (operands[5], operands[4], operands[2], operands[1]));
1983     emit_insn (gen_fma<mode>4 (operands[3], operands[5], operands[3], operands[4]));
1985    /* Due to truncation error, the quotient result may be low by 1 ulp.
1986       Conditionally add one if the estimate is too small in magnitude.  */
1988     emit_move_insn (gen_lowpart (<F2I>mode, operands[4]),
1989                     spu_const (<F2I>mode, 0x80000000ULL));
1990     emit_move_insn (gen_lowpart (<F2I>mode, operands[5]),
1991                     spu_const (<F2I>mode, 0x3f800000ULL));
1992     emit_insn (gen_selb (operands[5], operands[5], operands[1], operands[4]));
1994     emit_insn (gen_add<f2i>3 (gen_lowpart (<F2I>mode, operands[4]),
1995                               gen_lowpart (<F2I>mode, operands[3]),
1996                               spu_const (<F2I>mode, 1)));
1997     emit_insn (gen_fnma<mode>4 (operands[0], operands[2], operands[4], operands[1]));
1998     emit_insn (gen_mul<mode>3 (operands[0], operands[0], operands[5]));
1999     emit_insn (gen_cgt_<f2i> (gen_lowpart (<F2I>mode, operands[0]),
2000                               gen_lowpart (<F2I>mode, operands[0]),
2001                               spu_const (<F2I>mode, -1)));
2002     emit_insn (gen_selb (operands[0], operands[3], operands[4], operands[0]));
2003     DONE;
2004   })
2007 ;; sqrt
2009 (define_insn_and_split "sqrtsf2"
2010   [(set (match_operand:SF 0 "spu_reg_operand" "=r")
2011         (sqrt:SF (match_operand:SF 1 "spu_reg_operand" "r")))
2012    (clobber (match_scratch:SF 2 "=&r"))
2013    (clobber (match_scratch:SF 3 "=&r"))
2014    (clobber (match_scratch:SF 4 "=&r"))
2015    (clobber (match_scratch:SF 5 "=&r"))]
2016   ""
2017   "#"
2018   "reload_completed"
2019   [(set (match_dup:SF 0)
2020         (sqrt:SF (match_dup:SF 1)))
2021    (clobber (match_dup:SF 2))
2022    (clobber (match_dup:SF 3))
2023    (clobber (match_dup:SF 4))
2024    (clobber (match_dup:SF 5))]
2025   {
2026     emit_move_insn (operands[3],spu_float_const(\"0.5\",SFmode));
2027     emit_move_insn (operands[4],spu_float_const(\"1.00000011920928955078125\",SFmode));
2028     emit_insn (gen_frsqest_sf(operands[2],operands[1]));
2029     emit_insn (gen_fi_sf(operands[2],operands[1],operands[2]));
2030     emit_insn (gen_mulsf3(operands[5],operands[2],operands[1]));
2031     emit_insn (gen_mulsf3(operands[3],operands[5],operands[3]));
2032     emit_insn (gen_fnmasf4(operands[4],operands[2],operands[5],operands[4]));
2033     emit_insn (gen_fmasf4(operands[0],operands[4],operands[3],operands[5]));
2034     DONE;
2035   })
2037 (define_insn "frest_<mode>"
2038   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
2039         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")] UNSPEC_FREST))]
2040   ""
2041   "frest\t%0,%1"
2042   [(set_attr "type" "shuf")])
2044 (define_insn "frsqest_<mode>"
2045   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
2046         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")] UNSPEC_FRSQEST))]
2047   ""
2048   "frsqest\t%0,%1"
2049   [(set_attr "type" "shuf")])
2051 (define_insn "fi_<mode>"
2052   [(set (match_operand:VSF 0 "spu_reg_operand" "=r")
2053         (unspec:VSF [(match_operand:VSF 1 "spu_reg_operand" "r")
2054                     (match_operand:VSF 2 "spu_reg_operand" "r")] UNSPEC_FI))]
2055   ""
2056   "fi\t%0,%1,%2"
2057   [(set_attr "type" "fp7")])
2060 ;; and
2062 (define_insn "and<mode>3"
2063   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r")
2064         (and:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r")
2065                  (match_operand:MOV 2 "spu_logical_operand" "r,C")))]
2066   ""
2067   "@
2068   and\t%0,%1,%2
2069   and%j2i\t%0,%1,%J2")
2071 (define_insn "anddi3"
2072   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2073         (and:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2074                 (match_operand:DI 2 "spu_logical_operand" "r,c")))]
2075   ""
2076   "@
2077   and\t%0,%1,%2
2078   and%k2i\t%0,%1,%K2")
2080 (define_insn "andti3"
2081   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2082         (and:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2083                 (match_operand:TI 2 "spu_logical_operand" "r,Y")))]
2084   ""
2085   "@
2086   and\t%0,%1,%2
2087   and%m2i\t%0,%1,%L2")
2089 (define_insn "andc_<mode>"
2090   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2091         (and:ALL (not:ALL (match_operand:ALL 2 "spu_reg_operand" "r"))
2092                  (match_operand:ALL 1 "spu_reg_operand" "r")))]
2093   ""
2094   "andc\t%0,%1,%2")
2096 (define_insn "nand_<mode>"
2097   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2098         (not:ALL (and:ALL (match_operand:ALL 2 "spu_reg_operand" "r")
2099                           (match_operand:ALL 1 "spu_reg_operand" "r"))))]
2100   ""
2101   "nand\t%0,%1,%2")
2104 ;; ior
2106 (define_insn "ior<mode>3"
2107   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r,r")
2108         (ior:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r,0")
2109                  (match_operand:MOV 2 "spu_ior_operand" "r,C,D")))]
2110   ""
2111   "@
2112   or\t%0,%1,%2
2113   or%j2i\t%0,%1,%J2
2114   iohl\t%0,%J2")
2116 (define_insn "iordi3"
2117   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r,r")
2118         (ior:DI (match_operand:DI 1 "spu_reg_operand" "r,r,0")
2119                 (match_operand:DI 2 "spu_ior_operand" "r,c,d")))]
2120   ""
2121   "@
2122   or\t%0,%1,%2
2123   or%k2i\t%0,%1,%K2
2124   iohl\t%0,%K2")
2126 (define_insn "iorti3"
2127   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r,r")
2128         (ior:TI (match_operand:TI 1 "spu_reg_operand" "r,r,0")
2129                 (match_operand:TI 2 "spu_ior_operand" "r,Y,Z")))]
2130   ""
2131   "@
2132   or\t%0,%1,%2
2133   or%m2i\t%0,%1,%L2
2134   iohl\t%0,%L2")
2136 (define_insn "orc_<mode>"
2137   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2138         (ior:ALL (not:ALL (match_operand:ALL 2 "spu_reg_operand" "r"))
2139                  (match_operand:ALL 1 "spu_reg_operand" "r")))]
2140   ""
2141   "orc\t%0,%1,%2")
2143 (define_insn "nor_<mode>"
2144   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2145         (not:ALL (ior:ALL (match_operand:ALL 1 "spu_reg_operand" "r")
2146                           (match_operand:ALL 2 "spu_reg_operand" "r"))))]
2147   ""
2148   "nor\t%0,%1,%2")
2150 ;; xor
2152 (define_insn "xor<mode>3"
2153   [(set (match_operand:MOV 0 "spu_reg_operand" "=r,r")
2154         (xor:MOV (match_operand:MOV 1 "spu_reg_operand" "r,r")
2155                  (match_operand:MOV 2 "spu_logical_operand" "r,B")))]
2156   ""
2157   "@
2158   xor\t%0,%1,%2
2159   xor%j2i\t%0,%1,%J2")
2161 (define_insn "xordi3"
2162   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2163         (xor:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2164                 (match_operand:DI 2 "spu_logical_operand" "r,c")))]
2165   ""
2166   "@
2167   xor\t%0,%1,%2
2168   xor%k2i\t%0,%1,%K2")
2170 (define_insn "xorti3"
2171   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2172         (xor:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2173                 (match_operand:TI 2 "spu_logical_operand" "r,Y")))]
2174   ""
2175   "@
2176   xor\t%0,%1,%2
2177   xor%m2i\t%0,%1,%L2")
2179 (define_insn "eqv_<mode>"
2180   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2181         (not:ALL (xor:ALL (match_operand:ALL 1 "spu_reg_operand" "r")
2182                           (match_operand:ALL 2 "spu_reg_operand" "r"))))]
2183   ""
2184   "eqv\t%0,%1,%2")
2186 ;; one_cmpl
2188 (define_insn "one_cmpl<mode>2"
2189   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
2190         (not:ALL (match_operand:ALL 1 "spu_reg_operand" "r")))]
2191   ""
2192   "nor\t%0,%1,%1")
2195 ;; selb
2197 (define_expand "selb"
2198   [(set (match_operand 0 "spu_reg_operand" "")
2199         (unspec [(match_operand 1 "spu_reg_operand" "")
2200                  (match_operand 2 "spu_reg_operand" "")
2201                  (match_operand 3 "spu_reg_operand" "")] UNSPEC_SELB))]
2202   ""
2203   {
2204     rtx s = gen__selb (operands[0], operands[1], operands[2], operands[3]);
2205     PUT_MODE (SET_SRC (s), GET_MODE (operands[0]));
2206     emit_insn (s);
2207     DONE;
2208   })
2210 ;; This could be defined as a combination of logical operations, but at
2211 ;; one time it caused a crash due to recursive expansion of rtl during CSE.
2212 (define_insn "_selb"
2213   [(set (match_operand 0 "spu_reg_operand" "=r")
2214         (unspec [(match_operand 1 "spu_reg_operand" "r")
2215                  (match_operand 2 "spu_reg_operand" "r")
2216                  (match_operand 3 "spu_reg_operand" "r")] UNSPEC_SELB))]
2217   "GET_MODE(operands[0]) == GET_MODE(operands[1]) 
2218    && GET_MODE(operands[1]) == GET_MODE(operands[2])"
2219   "selb\t%0,%1,%2,%3")
2222 ;; Misc. byte/bit operations
2223 ;; clz/ctz/ffs/popcount/parity
2224 ;; cntb/sumb
2226 (define_insn "clz<mode>2"
2227   [(set (match_operand:VSI 0 "spu_reg_operand" "=r")
2228         (clz:VSI (match_operand:VSI 1 "spu_reg_operand" "r")))]
2229   ""
2230   "clz\t%0,%1")
2232 (define_expand "ctz<mode>2"
2233   [(set (match_dup 2)
2234         (neg:VSI (match_operand:VSI 1 "spu_reg_operand" "")))
2235    (set (match_dup 3) (and:VSI (match_dup 1)
2236                                (match_dup 2)))
2237    (set (match_dup 4) (clz:VSI (match_dup 3)))
2238    (set (match_operand:VSI 0 "spu_reg_operand" "")
2239         (minus:VSI (match_dup 5) (match_dup 4)))]
2240   ""
2241   {
2242      operands[2] = gen_reg_rtx (<MODE>mode);
2243      operands[3] = gen_reg_rtx (<MODE>mode);
2244      operands[4] = gen_reg_rtx (<MODE>mode);
2245      operands[5] = spu_const(<MODE>mode, 31);
2246   })
2248 (define_expand "clrsb<mode>2"
2249   [(set (match_dup 2)
2250         (gt:VSI (match_operand:VSI 1 "spu_reg_operand" "") (match_dup 5)))
2251    (set (match_dup 3) (not:VSI (xor:VSI (match_dup 1) (match_dup 2))))
2252    (set (match_dup 4) (clz:VSI (match_dup 3)))
2253    (set (match_operand:VSI 0 "spu_reg_operand")
2254         (plus:VSI (match_dup 4) (match_dup 5)))]
2255   ""
2256   {
2257      operands[2] = gen_reg_rtx (<MODE>mode);
2258      operands[3] = gen_reg_rtx (<MODE>mode);
2259      operands[4] = gen_reg_rtx (<MODE>mode);
2260      operands[5] = spu_const(<MODE>mode, -1);
2261   })
2263 (define_expand "ffs<mode>2"
2264   [(set (match_dup 2)
2265         (neg:VSI (match_operand:VSI 1 "spu_reg_operand" "")))
2266    (set (match_dup 3) (and:VSI (match_dup 1)
2267                                (match_dup 2)))
2268    (set (match_dup 4) (clz:VSI (match_dup 3)))
2269    (set (match_operand:VSI 0 "spu_reg_operand" "")
2270         (minus:VSI (match_dup 5) (match_dup 4)))]
2271   ""
2272   {
2273      operands[2] = gen_reg_rtx (<MODE>mode);
2274      operands[3] = gen_reg_rtx (<MODE>mode);
2275      operands[4] = gen_reg_rtx (<MODE>mode);
2276      operands[5] = spu_const(<MODE>mode, 32);
2277   })
2279 (define_expand "popcountsi2"
2280   [(set (match_dup 2)
2281         (unspec:SI [(match_operand:SI 1 "spu_reg_operand" "")]
2282                      UNSPEC_CNTB))
2283    (set (match_dup 3)
2284         (unspec:HI [(match_dup 2)] UNSPEC_SUMB))
2285    (set (match_operand:SI 0 "spu_reg_operand" "")
2286         (sign_extend:SI (match_dup 3)))]
2287   ""
2288   {
2289     operands[2] = gen_reg_rtx (SImode);
2290     operands[3] = gen_reg_rtx (HImode);
2291   })
2293 (define_expand "paritysi2"
2294   [(set (match_operand:SI 0 "spu_reg_operand" "")
2295         (parity:SI (match_operand:SI 1 "spu_reg_operand" "")))]
2296   ""
2297   {
2298     operands[2] = gen_reg_rtx (SImode);
2299     emit_insn (gen_popcountsi2(operands[2], operands[1]));
2300     emit_insn (gen_andsi3(operands[0], operands[2], GEN_INT (1)));
2301     DONE;
2302   })
2304 (define_insn "cntb_si"
2305   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2306         (unspec:SI [(match_operand:SI 1 "spu_reg_operand" "r")]
2307                    UNSPEC_CNTB))]
2308   ""
2309   "cntb\t%0,%1"
2310   [(set_attr "type" "fxb")])
2312 (define_insn "cntb_v16qi"
2313   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
2314         (unspec:V16QI [(match_operand:V16QI 1 "spu_reg_operand" "r")]
2315                       UNSPEC_CNTB))]
2316   ""
2317   "cntb\t%0,%1"
2318   [(set_attr "type" "fxb")])
2320 (define_insn "sumb_si"
2321   [(set (match_operand:HI 0 "spu_reg_operand" "=r")
2322         (unspec:HI [(match_operand:SI 1 "spu_reg_operand" "r")] UNSPEC_SUMB))]
2323   ""
2324   "sumb\t%0,%1,%1"
2325   [(set_attr "type" "fxb")])
2328 ;; ashl, vashl
2330 (define_insn "<v>ashl<mode>3"
2331   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2332         (ashift:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2333                      (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))]
2334   ""
2335   "@
2336   shl<bh>\t%0,%1,%2
2337   shl<bh>i\t%0,%1,%<umask>2"
2338   [(set_attr "type" "fx3")])
2340 (define_insn_and_split "ashldi3"
2341   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2342         (ashift:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2343                    (match_operand:SI 2 "spu_nonmem_operand" "r,I")))
2344    (clobber (match_scratch:SI 3 "=&r,X"))]
2345   ""
2346   "#"
2347   "reload_completed"
2348   [(set (match_dup:DI 0)
2349         (ashift:DI (match_dup:DI 1)
2350                    (match_dup:SI 2)))]
2351   {
2352     rtx op0 = gen_rtx_REG (TImode, REGNO (operands[0]));
2353     rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
2354     rtx op2 = operands[2];
2355     rtx op3 = operands[3];
2357     if (GET_CODE (operands[2]) == REG)
2358       {
2359         emit_insn (gen_addsi3 (op3, op2, GEN_INT (64)));
2360         emit_insn (gen_rotlti3 (op0, op1, GEN_INT (64)));
2361         emit_insn (gen_shlqbybi_ti (op0, op0, op3));
2362         emit_insn (gen_shlqbi_ti (op0, op0, op3));
2363       }
2364     else
2365       {
2366         HOST_WIDE_INT val = INTVAL (operands[2]);
2367         emit_insn (gen_rotlti3 (op0, op1, GEN_INT (64)));
2368         emit_insn (gen_shlqby_ti (op0, op0, GEN_INT (val / 8 + 8)));
2369         if (val % 8)
2370           emit_insn (gen_shlqbi_ti (op0, op0, GEN_INT (val % 8)));
2371       }
2372     DONE;
2373   })
2375 (define_expand "ashlti3"
2376   [(parallel [(set (match_operand:TI 0 "spu_reg_operand" "")
2377                    (ashift:TI (match_operand:TI 1 "spu_reg_operand" "")
2378                               (match_operand:SI 2 "spu_nonmem_operand" "")))
2379               (clobber (match_dup:TI 3))])]
2380   ""
2381   "if (GET_CODE (operands[2]) == CONST_INT)
2382     {
2383       emit_insn (gen_ashlti3_imm(operands[0], operands[1], operands[2]));
2384       DONE;
2385     }
2386    operands[3] = gen_reg_rtx (TImode);")
2388 (define_insn_and_split "ashlti3_imm"
2389   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2390         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2391                    (match_operand:SI 2 "immediate_operand" "O,P")))]
2392   ""
2393   "@
2394    shlqbyi\t%0,%1,%h2
2395    shlqbii\t%0,%1,%e2"
2396   "!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
2397   [(set (match_dup:TI 0)
2398         (ashift:TI (match_dup:TI 1)
2399                    (match_dup:SI 3)))
2400    (set (match_dup:TI 0)
2401         (ashift:TI (match_dup:TI 0)
2402                    (match_dup:SI 4)))]
2403   {
2404     HOST_WIDE_INT val = INTVAL(operands[2]);
2405     operands[3] = GEN_INT (val&7);
2406     operands[4] = GEN_INT (val&-8);
2407   }
2408   [(set_attr "type" "shuf,shuf")])
2410 (define_insn_and_split "ashlti3_reg"
2411   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2412         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r")
2413                    (match_operand:SI 2 "spu_reg_operand" "r")))
2414    (clobber (match_operand:TI 3 "spu_reg_operand" "=&r"))]
2415   ""
2416   "#"
2417   ""
2418   [(set (match_dup:TI 3)
2419         (ashift:TI (match_dup:TI 1)
2420                    (and:SI (match_dup:SI 2)
2421                            (const_int 7))))
2422    (set (match_dup:TI 0)
2423         (ashift:TI (match_dup:TI 3)
2424                    (and:SI (match_dup:SI 2)
2425                            (const_int -8))))]
2426   "")
2428 (define_insn "shlqbybi_ti"
2429   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2430         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2431                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2432                            (const_int -8))))]
2433   ""
2434   "@
2435    shlqbybi\t%0,%1,%2
2436    shlqbyi\t%0,%1,%h2"
2437   [(set_attr "type" "shuf,shuf")])
2439 (define_insn "shlqbi_ti"
2440   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2441         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2442                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2443                            (const_int 7))))]
2444   ""
2445   "@
2446    shlqbi\t%0,%1,%2
2447    shlqbii\t%0,%1,%e2"
2448   [(set_attr "type" "shuf,shuf")])
2450 (define_insn "shlqby_ti"
2451   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2452         (ashift:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2453                    (mult:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2454                             (const_int 8))))]
2455   ""
2456   "@
2457    shlqby\t%0,%1,%2
2458    shlqbyi\t%0,%1,%f2"
2459   [(set_attr "type" "shuf,shuf")])
2462 ;; lshr, vlshr
2464 (define_insn_and_split "<v>lshr<mode>3"
2465   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2466         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2467                        (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))
2468    (clobber (match_scratch:VHSI 3 "=&r,X"))]
2469   ""
2470   "@
2471    #
2472    rot<bh>mi\t%0,%1,-%<umask>2"
2473   "reload_completed && GET_CODE (operands[2]) == REG"
2474   [(set (match_dup:VHSI 3)
2475         (neg:VHSI (match_dup:VHSI 2)))
2476    (set (match_dup:VHSI 0)
2477         (lshiftrt:VHSI (match_dup:VHSI 1)
2478                        (neg:VHSI (match_dup:VHSI 3))))]
2479   ""
2480   [(set_attr "type" "*,fx3")])
2481   
2482 (define_insn "<v>lshr<mode>3_imm"
2483   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
2484         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")
2485                        (match_operand:VHSI 2 "immediate_operand" "W")))]
2486   ""
2487   "rot<bh>mi\t%0,%1,-%<umask>2"
2488   [(set_attr "type" "fx3")])
2490 (define_insn "rotm_<mode>"
2491   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2492         (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2493                        (neg:VHSI (match_operand:VHSI 2 "spu_nonmem_operand" "r,W"))))]
2494   ""
2495   "@
2496    rot<bh>m\t%0,%1,%2
2497    rot<bh>mi\t%0,%1,-%<nmask>2"
2498   [(set_attr "type" "fx3")])
2500 (define_insn_and_split "lshr<mode>3"
2501   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r,r")
2502         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r,r")
2503                       (match_operand:SI 2 "spu_nonmem_operand" "r,O,P")))]
2504   ""
2505   "@
2506    #
2507    rotqmbyi\t%0,%1,-%h2
2508    rotqmbii\t%0,%1,-%e2"
2509   "REG_P (operands[2]) || (!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2]))"
2510   [(set (match_dup:DTI 3)
2511         (lshiftrt:DTI (match_dup:DTI 1)
2512                       (match_dup:SI 4)))
2513    (set (match_dup:DTI 0)
2514         (lshiftrt:DTI (match_dup:DTI 3)
2515                       (match_dup:SI 5)))]
2516   {
2517     operands[3] = gen_reg_rtx (<MODE>mode);
2518     if (GET_CODE (operands[2]) == CONST_INT)
2519       {
2520         HOST_WIDE_INT val = INTVAL(operands[2]);
2521         operands[4] = GEN_INT (val & 7);
2522         operands[5] = GEN_INT (val & -8);
2523       }
2524     else
2525       {
2526         rtx t0 = gen_reg_rtx (SImode);
2527         rtx t1 = gen_reg_rtx (SImode);
2528         emit_insn (gen_subsi3(t0, GEN_INT(0), operands[2]));
2529         emit_insn (gen_subsi3(t1, GEN_INT(7), operands[2]));
2530         operands[4] = gen_rtx_AND (SImode, gen_rtx_NEG (SImode, t0), GEN_INT (7));
2531         operands[5] = gen_rtx_AND (SImode, gen_rtx_NEG (SImode, gen_rtx_AND (SImode, t1, GEN_INT (-8))), GEN_INT (-8));
2532       }
2533   }
2534   [(set_attr "type" "*,shuf,shuf")])
2536 (define_expand "shrqbybi_<mode>"
2537   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2538         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2539                       (and:SI (neg:SI (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2540                                               (const_int -8)))
2541                               (const_int -8))))]
2542   ""
2543   {
2544     if (GET_CODE (operands[2]) == CONST_INT)
2545       operands[2] = GEN_INT (7 - INTVAL (operands[2]));
2546     else
2547       {
2548         rtx t0 = gen_reg_rtx (SImode);
2549         emit_insn (gen_subsi3 (t0, GEN_INT (7), operands[2]));
2550         operands[2] = t0;
2551       }
2552   })
2554 (define_insn "rotqmbybi_<mode>"
2555   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2556         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2557                       (and:SI (neg:SI (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2558                                               (const_int -8)))
2559                               (const_int -8))))]
2560   ""
2561   "@
2562    rotqmbybi\t%0,%1,%2
2563    rotqmbyi\t%0,%1,-%H2"
2564   [(set_attr "type" "shuf")])
2566 (define_insn_and_split "shrqbi_<mode>"
2567   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2568         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2569                       (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2570                               (const_int 7))))
2571    (clobber (match_scratch:SI 3 "=&r,X"))]
2572   ""
2573   "#"
2574   "reload_completed"
2575   [(set (match_dup:DTI 0)
2576         (lshiftrt:DTI (match_dup:DTI 1)
2577                       (and:SI (neg:SI (match_dup:SI 3)) (const_int 7))))]
2578   {
2579     if (GET_CODE (operands[2]) == CONST_INT)
2580       operands[3] = GEN_INT (-INTVAL (operands[2]));
2581     else
2582       emit_insn (gen_subsi3 (operands[3], GEN_INT (0), operands[2]));
2583   }
2584   [(set_attr "type" "shuf")])
2586 (define_insn "rotqmbi_<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                       (and:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2590                               (const_int 7))))]
2591   ""
2592   "@
2593    rotqmbi\t%0,%1,%2
2594    rotqmbii\t%0,%1,-%E2"
2595   [(set_attr "type" "shuf")])
2597 (define_expand "shrqby_<mode>"
2598   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2599         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2600                       (mult:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2601                                (const_int 8))))]
2602   ""
2603   {
2604     if (GET_CODE (operands[2]) == CONST_INT)
2605       operands[2] = GEN_INT (-INTVAL (operands[2]));
2606     else
2607       {
2608         rtx t0 = gen_reg_rtx (SImode);
2609         emit_insn (gen_subsi3 (t0, GEN_INT (0), operands[2]));
2610         operands[2] = t0;
2611       }
2612   })
2614 (define_insn "rotqmby_<mode>"
2615   [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
2616         (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
2617                       (mult:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
2618                                (const_int 8))))]
2619   ""
2620   "@
2621    rotqmby\t%0,%1,%2
2622    rotqmbyi\t%0,%1,-%F2"
2623   [(set_attr "type" "shuf")])
2626 ;; ashr, vashr
2628 (define_insn_and_split "<v>ashr<mode>3"
2629   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2630         (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2631                        (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))
2632    (clobber (match_scratch:VHSI 3 "=&r,X"))]
2633   ""
2634   "@
2635    #
2636    rotma<bh>i\t%0,%1,-%<umask>2"
2637   "reload_completed && GET_CODE (operands[2]) == REG"
2638   [(set (match_dup:VHSI 3)
2639         (neg:VHSI (match_dup:VHSI 2)))
2640    (set (match_dup:VHSI 0)
2641         (ashiftrt:VHSI (match_dup:VHSI 1)
2642                        (neg:VHSI (match_dup:VHSI 3))))]
2643   ""
2644   [(set_attr "type" "*,fx3")])
2645   
2646 (define_insn "<v>ashr<mode>3_imm"
2647   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
2648         (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")
2649                        (match_operand:VHSI 2 "immediate_operand" "W")))]
2650   ""
2651   "rotma<bh>i\t%0,%1,-%<umask>2"
2652   [(set_attr "type" "fx3")])
2653   
2655 (define_insn "rotma_<mode>"
2656   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2657         (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2658                        (neg:VHSI (match_operand:VHSI 2 "spu_nonmem_operand" "r,W"))))]
2659   ""
2660   "@
2661    rotma<bh>\t%0,%1,%2
2662    rotma<bh>i\t%0,%1,-%<nmask>2"
2663   [(set_attr "type" "fx3")])
2665 (define_insn_and_split "ashrdi3"
2666   [(set (match_operand:DI 0 "spu_reg_operand" "=r,r")
2667         (ashiftrt:DI (match_operand:DI 1 "spu_reg_operand" "r,r")
2668                      (match_operand:SI 2 "spu_nonmem_operand" "r,I")))
2669    (clobber (match_scratch:TI 3 "=&r,&r"))
2670    (clobber (match_scratch:TI 4 "=&r,&r"))
2671    (clobber (match_scratch:SI 5 "=&r,&r"))]
2672   ""
2673   "#"
2674   "reload_completed"
2675   [(set (match_dup:DI 0)
2676         (ashiftrt:DI (match_dup:DI 1)
2677                      (match_dup:SI 2)))]
2678   {
2679     rtx op0 = gen_rtx_REG (TImode, REGNO (operands[0]));
2680     rtx op0v = gen_rtx_REG (V4SImode, REGNO (op0));
2681     rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
2682     rtx op1s = gen_rtx_REG (SImode, REGNO (op1));
2683     rtx op2 = operands[2];
2684     rtx op3 = operands[3];
2685     rtx op4 = operands[4];
2686     rtx op5 = operands[5];
2688     if (GET_CODE (op2) == CONST_INT && INTVAL (op2) >= 63)
2689       {
2690         rtx op0s = gen_rtx_REG (SImode, REGNO (op0));
2691         emit_insn (gen_ashrsi3 (op0s, op1s, GEN_INT (32)));
2692         emit_insn (gen_spu_fsm (op0v, op0s));
2693       }
2694     else if (GET_CODE (op2) == CONST_INT && INTVAL (op2) >= 32)
2695       {
2696         rtx op0d = gen_rtx_REG (V2DImode, REGNO (op0));
2697         HOST_WIDE_INT val = INTVAL (op2);
2698         emit_insn (gen_lshrti3 (op0, op1, GEN_INT (32)));
2699         emit_insn (gen_spu_xswd (op0d, op0v));
2700         if (val > 32)
2701           emit_insn (gen_vashrv4si3 (op0v, op0v, spu_const (V4SImode, val - 32)));
2702       }
2703     else
2704       {
2705         rtx op3v = gen_rtx_REG (V4SImode, REGNO (op3));
2706         unsigned char arr[16] = {
2707           0xff, 0xff, 0xff, 0xff,
2708           0xff, 0xff, 0xff, 0xff,
2709           0x00, 0x00, 0x00, 0x00,
2710           0x00, 0x00, 0x00, 0x00
2711         };
2713         emit_insn (gen_ashrsi3 (op5, op1s, GEN_INT (31)));
2714         emit_move_insn (op4, array_to_constant (TImode, arr));
2715         emit_insn (gen_spu_fsm (op3v, op5));
2717         if (GET_CODE (operands[2]) == REG)
2718           {
2719             emit_insn (gen_selb (op4, op3, op1, op4));
2720             emit_insn (gen_negsi2 (op5, op2));
2721             emit_insn (gen_rotqbybi_ti (op0, op4, op5));
2722             emit_insn (gen_rotqbi_ti (op0, op0, op5));
2723           }
2724         else
2725           {
2726             HOST_WIDE_INT val = -INTVAL (op2);
2727             emit_insn (gen_selb (op0, op3, op1, op4));
2728             if ((val - 7) / 8)
2729               emit_insn (gen_rotqby_ti (op0, op0, GEN_INT ((val - 7) / 8)));
2730             if (val % 8)
2731               emit_insn (gen_rotqbi_ti (op0, op0, GEN_INT (val % 8)));
2732           }
2733       }
2734     DONE;
2735   })
2738 (define_insn_and_split "ashrti3"
2739   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2740         (ashiftrt:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2741                      (match_operand:SI 2 "spu_nonmem_operand" "r,i")))]
2742   ""
2743   "#"
2744   ""
2745   [(set (match_dup:TI 0)
2746         (ashiftrt:TI (match_dup:TI 1)
2747                      (match_dup:SI 2)))]
2748   {
2749     rtx sign_shift = gen_reg_rtx (SImode);
2750     rtx sign_mask = gen_reg_rtx (TImode);
2751     rtx sign_mask_v4si = gen_rtx_SUBREG (V4SImode, sign_mask, 0);
2752     rtx op1_v4si = spu_gen_subreg (V4SImode, operands[1]);
2753     rtx t = gen_reg_rtx (TImode);
2754     emit_insn (gen_subsi3 (sign_shift, GEN_INT (128), force_reg (SImode, operands[2])));
2755     emit_insn (gen_vashrv4si3 (sign_mask_v4si, op1_v4si, spu_const (V4SImode, 31)));
2756     emit_insn (gen_fsm_ti (sign_mask, sign_mask));
2757     emit_insn (gen_ashlti3 (sign_mask, sign_mask, sign_shift));
2758     emit_insn (gen_lshrti3 (t, operands[1], operands[2]));
2759     emit_insn (gen_iorti3 (operands[0], t, sign_mask));
2760     DONE;
2761   })
2763 ;; fsm is used after rotam to replicate the sign across the whole register.
2764 (define_insn "fsm_ti"
2765   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2766         (unspec:TI [(match_operand:TI 1 "spu_reg_operand" "r")] UNSPEC_FSM))]
2767   ""
2768   "fsm\t%0,%1"
2769   [(set_attr "type" "shuf")])
2772 ;; vrotl, rotl
2774 (define_insn "<v>rotl<mode>3"
2775   [(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
2776         (rotate:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r,r")
2777                      (match_operand:VHSI 2 "spu_nonmem_operand" "r,W")))]
2778   ""
2779   "@
2780   rot<bh>\t%0,%1,%2
2781   rot<bh>i\t%0,%1,%<umask>2"
2782   [(set_attr "type" "fx3")])
2784 (define_insn "rotlti3"
2785   [(set (match_operand:TI 0 "spu_reg_operand" "=&r,r,r,r")
2786         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r,r,r")
2787                    (match_operand:SI 2 "spu_nonmem_operand" "r,O,P,I")))]
2788   ""
2789   "@
2790   rotqbybi\t%0,%1,%2\;rotqbi\t%0,%0,%2
2791   rotqbyi\t%0,%1,%h2
2792   rotqbii\t%0,%1,%e2
2793   rotqbyi\t%0,%1,%h2\;rotqbii\t%0,%0,%e2"
2794   [(set_attr "length" "8,4,4,8")
2795    (set_attr "type" "multi1,shuf,shuf,multi1")])
2797 (define_insn "rotqbybi_ti"
2798   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2799         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2800                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2801                            (const_int -8))))]
2802   ""
2803   "@
2804   rotqbybi\t%0,%1,%2
2805   rotqbyi\t%0,%1,%h2"
2806   [(set_attr "type" "shuf,shuf")])
2808 (define_insn "rotqby_ti"
2809   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2810         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2811                    (mult:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2812                             (const_int 8))))]
2813   ""
2814   "@
2815   rotqby\t%0,%1,%2
2816   rotqbyi\t%0,%1,%f2"
2817   [(set_attr "type" "shuf,shuf")])
2819 (define_insn "rotqbi_ti"
2820   [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
2821         (rotate:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
2822                    (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
2823                            (const_int 7))))]
2824   ""
2825   "@
2826   rotqbi\t%0,%1,%2
2827   rotqbii\t%0,%1,%e2"
2828   [(set_attr "type" "shuf,shuf")])
2831 ;; struct extract/insert
2832 ;; We handle mem's because GCC will generate invalid SUBREG's
2833 ;; and inefficient code.
2835 (define_expand "extv"
2836   [(set (match_operand:TI 0 "register_operand" "")
2837         (sign_extract:TI (match_operand 1 "nonimmediate_operand" "")
2838                          (match_operand:SI 2 "const_int_operand" "")
2839                          (match_operand:SI 3 "const_int_operand" "")))]
2840   ""
2841   {
2842     spu_expand_extv (operands, 0);
2843     DONE;
2844   })
2846 (define_expand "extzv"
2847   [(set (match_operand:TI 0 "register_operand" "")
2848         (zero_extract:TI (match_operand 1 "nonimmediate_operand" "")
2849                          (match_operand:SI 2 "const_int_operand" "")
2850                          (match_operand:SI 3 "const_int_operand" "")))]
2851   ""
2852   {
2853     spu_expand_extv (operands, 1);
2854     DONE;
2855   })
2857 (define_expand "insv"
2858   [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2859                       (match_operand:SI 1 "const_int_operand" "")
2860                       (match_operand:SI 2 "const_int_operand" ""))
2861         (match_operand 3 "nonmemory_operand" ""))]
2862   ""
2863   {
2864     if (INTVAL (operands[1]) + INTVAL (operands[2])
2865         > GET_MODE_BITSIZE (GET_MODE (operands[0])))
2866       FAIL;
2867     spu_expand_insv(operands);
2868     DONE;
2869   })
2871 ;; Simplify a number of patterns that get generated by extv, extzv,
2872 ;; insv, and loads.
2873 (define_insn_and_split "trunc_shr_ti<mode>"
2874   [(set (match_operand:QHSI 0 "spu_reg_operand" "=r")
2875         (truncate:QHSI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "0")
2876                                                                 (const_int 96)])))]
2877   ""
2878   "#"
2879   "reload_completed"
2880   [(const_int 0)]
2881   {
2882     spu_split_convert (operands);
2883     DONE;
2884   }
2885   [(set_attr "type" "convert")
2886    (set_attr "length" "0")])
2888 (define_insn_and_split "trunc_shr_tidi"
2889   [(set (match_operand:DI 0 "spu_reg_operand" "=r")
2890         (truncate:DI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "0")
2891                                                               (const_int 64)])))]
2892   ""
2893   "#"
2894   "reload_completed"
2895   [(const_int 0)]
2896   {
2897     spu_split_convert (operands);
2898     DONE;
2899   }
2900   [(set_attr "type" "convert")
2901    (set_attr "length" "0")])
2903 (define_insn_and_split "shl_ext_<mode>ti"
2904   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2905         (ashift:TI (match_operator:TI 2 "extend_operator" [(match_operand:QHSI 1 "spu_reg_operand" "0")])
2906                    (const_int 96)))]
2907   ""
2908   "#"
2909   "reload_completed"
2910   [(const_int 0)]
2911   {
2912     spu_split_convert (operands);
2913     DONE;
2914   }
2915   [(set_attr "type" "convert")
2916    (set_attr "length" "0")])
2918 (define_insn_and_split "shl_ext_diti"
2919   [(set (match_operand:TI 0 "spu_reg_operand" "=r")
2920         (ashift:TI (match_operator:TI 2 "extend_operator" [(match_operand:DI 1 "spu_reg_operand" "0")])
2921                    (const_int 64)))]
2922   ""
2923   "#"
2924   "reload_completed"
2925   [(const_int 0)]
2926   {
2927     spu_split_convert (operands);
2928     DONE;
2929   }
2930   [(set_attr "type" "convert")
2931    (set_attr "length" "0")])
2933 (define_insn "sext_trunc_lshr_tiqisi"
2934   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2935         (sign_extend:SI (truncate:QI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
2936                                                                               (const_int 120)]))))]
2937   ""
2938   "rotmai\t%0,%1,-24"
2939   [(set_attr "type" "fx3")])
2941 (define_insn "zext_trunc_lshr_tiqisi"
2942   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2943         (zero_extend:SI (truncate:QI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
2944                                                                               (const_int 120)]))))]
2945   ""
2946   "rotmi\t%0,%1,-24"
2947   [(set_attr "type" "fx3")])
2949 (define_insn "sext_trunc_lshr_tihisi"
2950   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2951         (sign_extend:SI (truncate:HI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
2952                                                                               (const_int 112)]))))]
2953   ""
2954   "rotmai\t%0,%1,-16"
2955   [(set_attr "type" "fx3")])
2957 (define_insn "zext_trunc_lshr_tihisi"
2958   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
2959         (zero_extend:SI (truncate:HI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
2960                                                                               (const_int 112)]))))]
2961   ""
2962   "rotmi\t%0,%1,-16"
2963   [(set_attr "type" "fx3")])
2966 ;; String/block move insn.
2967 ;; Argument 0 is the destination
2968 ;; Argument 1 is the source
2969 ;; Argument 2 is the length
2970 ;; Argument 3 is the alignment
2972 (define_expand "movstrsi"
2973   [(parallel [(set (match_operand:BLK 0 "" "")
2974                    (match_operand:BLK 1 "" ""))
2975               (use (match_operand:SI 2 "" ""))
2976               (use (match_operand:SI 3 "" ""))])]
2977   ""
2978   "
2979   {
2980     if (spu_expand_block_move (operands))
2981       DONE;
2982     else
2983       FAIL;
2984   }")
2987 ;; jump
2989 (define_insn "indirect_jump"
2990   [(set (pc) (match_operand:SI 0 "spu_reg_operand" "r"))]
2991   ""
2992   "bi\t%0"
2993   [(set_attr "type" "br")])
2995 (define_insn "jump"
2996   [(set (pc)
2997         (label_ref (match_operand 0 "" "")))]
2998   ""
2999   "br\t%0"
3000   [(set_attr "type" "br")])
3003 ;; return
3005 ;; This will be used for leaf functions, that don't save any regs and
3006 ;; don't have locals on stack, maybe... that is for functions that
3007 ;; don't change $sp and don't need to save $lr. 
3008 (define_expand "return"
3009     [(return)]
3010   "direct_return()"
3011   "")
3013 ;; used in spu_expand_epilogue to generate return from a function and
3014 ;; explicitly set use of $lr.
3016 (define_insn "_return"
3017   [(return)]
3018   ""
3019   "bi\t$lr"
3020   [(set_attr "type" "br")])
3024 ;; ceq
3026 (define_insn "ceq_<mode>"
3027   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
3028         (eq:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
3029                  (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
3030   ""
3031   "@
3032   ceq<bh>\t%0,%1,%2
3033   ceq<bh>i\t%0,%1,%2")
3035 (define_insn_and_split "ceq_di"
3036   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3037         (eq:SI (match_operand:DI 1 "spu_reg_operand" "r")
3038                (match_operand:DI 2 "spu_reg_operand" "r")))]
3039   ""
3040   "#"
3041   "reload_completed"
3042   [(set (match_dup:SI 0)
3043         (eq:SI (match_dup:DI 1)
3044                (match_dup:DI 2)))]
3045   {
3046     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
3047     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
3048     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
3049     emit_insn (gen_ceq_v4si (op0, op1, op2));
3050     emit_insn (gen_spu_gb (op0, op0));
3051     emit_insn (gen_cgt_si (operands[0], operands[0], GEN_INT (11)));
3052     DONE;
3053   })
3056 ;; We provide the TI compares for completeness and because some parts of
3057 ;; gcc/libgcc use them, even though user code might never see it.
3058 (define_insn "ceq_ti"
3059   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3060         (eq:SI (match_operand:TI 1 "spu_reg_operand" "r")
3061                (match_operand:TI 2 "spu_reg_operand" "r")))]
3062   ""
3063   "ceq\t%0,%1,%2\;gb\t%0,%0\;ceqi\t%0,%0,15"
3064   [(set_attr "type" "multi0")
3065    (set_attr "length" "12")])
3067 (define_insn "ceq_<mode>"
3068   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
3069         (eq:<F2I> (match_operand:VSF 1 "spu_reg_operand" "r")
3070                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
3071   ""
3072   "fceq\t%0,%1,%2")
3074 (define_insn "cmeq_<mode>"
3075   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
3076         (eq:<F2I> (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "r"))
3077                   (abs:VSF (match_operand:VSF 2 "spu_reg_operand" "r"))))]
3078   ""
3079   "fcmeq\t%0,%1,%2")
3081 ;; These implementations will ignore checking of NaN or INF if
3082 ;; compiled with option -ffinite-math-only.
3083 (define_expand "ceq_df"
3084   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3085         (eq:SI (match_operand:DF 1 "spu_reg_operand" "r")
3086                (match_operand:DF 2 "const_zero_operand" "i")))]
3087   ""
3089   if (spu_arch == PROCESSOR_CELL)
3090       {
3091         rtx ra = gen_reg_rtx (V4SImode);
3092         rtx rb = gen_reg_rtx (V4SImode);
3093         rtx temp = gen_reg_rtx (TImode);
3094         rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3095         rtx temp2 = gen_reg_rtx (V4SImode);
3096         rtx biteq = gen_reg_rtx (V4SImode);
3097         rtx ahi_inf = gen_reg_rtx (V4SImode);
3098         rtx a_nan = gen_reg_rtx (V4SImode);
3099         rtx a_abs = gen_reg_rtx (V4SImode);
3100         rtx b_abs = gen_reg_rtx (V4SImode);
3101         rtx iszero = gen_reg_rtx (V4SImode);
3102         rtx sign_mask = gen_reg_rtx (V4SImode);
3103         rtx nan_mask = gen_reg_rtx (V4SImode);
3104         rtx hihi_promote = gen_reg_rtx (TImode);
3105         rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF,
3106                                                  0x7FFFFFFF, 0xFFFFFFFF);
3108         emit_move_insn (sign_mask, pat);
3109         pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0,
3110                                              0x7FF00000, 0x0);
3111         emit_move_insn (nan_mask, pat);
3112         pat = spu_const_from_ints (TImode, 0x00010203, 0x10111213,
3113                                            0x08090A0B, 0x18191A1B);
3114         emit_move_insn (hihi_promote, pat);
3116         emit_insn (gen_spu_convert (ra, operands[1]));
3117         emit_insn (gen_spu_convert (rb, operands[2]));
3118         emit_insn (gen_ceq_v4si (biteq, ra, rb));
3119         emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, biteq),
3120                                 GEN_INT (4 * 8)));
3121         emit_insn (gen_andv4si3 (biteq, biteq, temp_v4si));
3123         emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3124         emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3125         if (!flag_finite_math_only)
3126           {
3127             emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3128             emit_insn (gen_ceq_v4si (ahi_inf, a_abs, nan_mask));
3129             emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan),
3130                                    GEN_INT (4 * 8)));
3131             emit_insn (gen_andv4si3 (temp2, temp_v4si, ahi_inf));
3132             emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3133           }
3134         emit_insn (gen_iorv4si3 (temp2, a_abs, b_abs));
3135         emit_insn (gen_ceq_v4si (iszero, temp2, CONST0_RTX (V4SImode)));
3136         emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, iszero),
3137                                 GEN_INT (4 * 8)));
3138         emit_insn (gen_andv4si3 (iszero, iszero, temp_v4si));
3139         emit_insn (gen_iorv4si3 (temp2, biteq, iszero));
3140         if (!flag_finite_math_only)
3141           {
3142             emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3143           }
3144         emit_insn (gen_shufb (operands[0], temp2, temp2, hihi_promote));
3145         DONE;
3146       }
3149 (define_insn "ceq_<mode>_celledp"
3150   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
3151         (eq:<DF2I> (match_operand:VDF 1 "spu_reg_operand" "r")
3152                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
3153   "spu_arch == PROCESSOR_CELLEDP"
3154   "dfceq\t%0,%1,%2"
3155   [(set_attr "type" "fpd")])
3157 (define_insn "cmeq_<mode>_celledp"
3158   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
3159         (eq:<DF2I> (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "r"))
3160                    (abs:VDF (match_operand:VDF 2 "spu_reg_operand" "r"))))]
3161   "spu_arch == PROCESSOR_CELLEDP"
3162   "dfcmeq\t%0,%1,%2"
3163   [(set_attr "type" "fpd")])
3165 (define_expand "ceq_v2df"
3166   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3167         (eq:V2DI (match_operand:V2DF 1 "spu_reg_operand" "r")
3168                  (match_operand:V2DF 2 "spu_reg_operand" "r")))]
3169   ""
3171   if (spu_arch == PROCESSOR_CELL)
3172     {
3173       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3174       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
3175       rtx temp = gen_reg_rtx (TImode);
3176       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3177       rtx temp2 = gen_reg_rtx (V4SImode);
3178       rtx biteq = gen_reg_rtx (V4SImode);
3179       rtx ahi_inf = gen_reg_rtx (V4SImode);
3180       rtx a_nan = gen_reg_rtx (V4SImode);
3181       rtx a_abs = gen_reg_rtx (V4SImode);
3182       rtx b_abs = gen_reg_rtx (V4SImode);
3183       rtx iszero = gen_reg_rtx (V4SImode);
3184       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF,
3185                                                0x7FFFFFFF, 0xFFFFFFFF);
3186       rtx sign_mask = gen_reg_rtx (V4SImode);
3187       rtx nan_mask = gen_reg_rtx (V4SImode);
3188       rtx hihi_promote = gen_reg_rtx (TImode);
3190       emit_move_insn (sign_mask, pat);
3191       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3192                                              0x7FF00000, 0x0);
3193       emit_move_insn (nan_mask, pat);
3194       pat = spu_const_from_ints (TImode, 0x00010203, 0x10111213, 
3195                                            0x08090A0B, 0x18191A1B);
3196       emit_move_insn (hihi_promote, pat);
3198       emit_insn (gen_ceq_v4si (biteq, ra, rb));
3199       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, biteq), 
3200                               GEN_INT (4 * 8)));
3201       emit_insn (gen_andv4si3 (biteq, biteq, temp_v4si));
3202       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3203       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3204       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3205       emit_insn (gen_ceq_v4si (ahi_inf, a_abs, nan_mask));
3206       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
3207                               GEN_INT (4 * 8)));
3208       emit_insn (gen_andv4si3 (temp2, temp_v4si, ahi_inf));
3209       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3210       emit_insn (gen_iorv4si3 (temp2, a_abs, b_abs));
3211       emit_insn (gen_ceq_v4si (iszero, temp2, CONST0_RTX (V4SImode)));
3212       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, iszero), 
3213                               GEN_INT (4 * 8)));
3214       emit_insn (gen_andv4si3 (iszero, iszero, temp_v4si));
3215       emit_insn (gen_iorv4si3 (temp2, biteq, iszero));
3216       emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3217       emit_insn (gen_shufb (operands[0], temp2, temp2, hihi_promote));
3218       DONE;
3219   }
3222 (define_expand "cmeq_v2df"
3223   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3224         (eq:V2DI (abs:V2DF (match_operand:V2DF 1 "spu_reg_operand" "r"))
3225                  (abs:V2DF (match_operand:V2DF 2 "spu_reg_operand" "r"))))]
3226   ""
3228   if (spu_arch == PROCESSOR_CELL)
3229     {
3230       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3231       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
3232       rtx temp = gen_reg_rtx (TImode);
3233       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3234       rtx temp2 = gen_reg_rtx (V4SImode);
3235       rtx biteq = gen_reg_rtx (V4SImode);
3236       rtx ahi_inf = gen_reg_rtx (V4SImode);
3237       rtx a_nan = gen_reg_rtx (V4SImode);
3238       rtx a_abs = gen_reg_rtx (V4SImode);
3239       rtx b_abs = gen_reg_rtx (V4SImode);
3241       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3242                                                0x7FFFFFFF, 0xFFFFFFFF);
3243       rtx sign_mask = gen_reg_rtx (V4SImode);
3244       rtx nan_mask = gen_reg_rtx (V4SImode);
3245       rtx hihi_promote = gen_reg_rtx (TImode);
3247       emit_move_insn (sign_mask, pat);
3249       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3250                                            0x7FF00000, 0x0);
3251       emit_move_insn (nan_mask, pat);
3252       pat = spu_const_from_ints (TImode, 0x00010203, 0x10111213, 
3253                                          0x08090A0B, 0x18191A1B);
3254       emit_move_insn (hihi_promote, pat);
3256       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3257       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3258       emit_insn (gen_ceq_v4si (biteq, a_abs, b_abs));
3259       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, biteq), 
3260                                                     GEN_INT (4 * 8)));
3261       emit_insn (gen_andv4si3 (biteq, biteq, temp_v4si));
3262       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3263       emit_insn (gen_ceq_v4si (ahi_inf, a_abs, nan_mask));
3264       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
3265                                                     GEN_INT (4 * 8)));
3266       emit_insn (gen_andv4si3 (temp2, temp_v4si, ahi_inf));
3267       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3268       emit_insn (gen_andc_v4si (temp2, biteq, a_nan));
3269       emit_insn (gen_shufb (operands[0], temp2, temp2, hihi_promote));
3270       DONE;
3271   }
3275 ;; cgt
3277 (define_insn "cgt_<mode>"
3278   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
3279         (gt:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
3280                   (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
3281   ""
3282   "@
3283   cgt<bh>\t%0,%1,%2
3284   cgt<bh>i\t%0,%1,%2")
3286 (define_insn "cgt_di_m1" 
3287   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3288         (gt:SI (match_operand:DI 1 "spu_reg_operand" "r")
3289                (const_int -1)))]
3290   ""
3291   "cgti\t%0,%1,-1")
3293 (define_insn_and_split "cgt_di" 
3294   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3295         (gt:SI (match_operand:DI 1 "spu_reg_operand" "r")
3296                (match_operand:DI 2 "spu_reg_operand" "r")))
3297    (clobber (match_scratch:V4SI 3 "=&r"))
3298    (clobber (match_scratch:V4SI 4 "=&r"))
3299    (clobber (match_scratch:V4SI 5 "=&r"))]
3300   ""
3301   "#"
3302   "reload_completed"
3303   [(set (match_dup:SI 0)
3304         (gt:SI (match_dup:DI 1)
3305                (match_dup:DI 2)))]
3306   {
3307     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
3308     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
3309     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
3310     rtx op3 = operands[3];
3311     rtx op4 = operands[4];
3312     rtx op5 = operands[5];
3313     rtx op3d = gen_rtx_REG (V2DImode, REGNO (operands[3]));
3314     emit_insn (gen_clgt_v4si (op3, op1, op2));
3315     emit_insn (gen_ceq_v4si (op4, op1, op2));
3316     emit_insn (gen_cgt_v4si (op5, op1, op2));
3317     emit_insn (gen_spu_xswd (op3d, op3));
3318     emit_insn (gen_selb (op0, op5, op3, op4));
3319     DONE;
3320   })
3322 (define_insn "cgt_ti_m1" 
3323   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3324         (gt:SI (match_operand:TI 1 "spu_reg_operand" "r")
3325                (const_int -1)))]
3326   ""
3327   "cgti\t%0,%1,-1")
3329 (define_insn "cgt_ti"
3330   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3331         (gt:SI (match_operand:TI 1 "spu_reg_operand" "r")
3332                (match_operand:TI 2 "spu_reg_operand" "r")))
3333    (clobber (match_scratch:V4SI 3 "=&r"))
3334    (clobber (match_scratch:V4SI 4 "=&r"))
3335    (clobber (match_scratch:V4SI 5 "=&r"))]
3336   ""
3337   "clgt\t%4,%1,%2\;\
3338 ceq\t%3,%1,%2\;\
3339 cgt\t%5,%1,%2\;\
3340 shlqbyi\t%0,%4,4\;\
3341 selb\t%0,%4,%0,%3\;\
3342 shlqbyi\t%0,%0,4\;\
3343 selb\t%0,%4,%0,%3\;\
3344 shlqbyi\t%0,%0,4\;\
3345 selb\t%0,%5,%0,%3"
3346   [(set_attr "type" "multi0")
3347    (set_attr "length" "36")])
3349 (define_insn "cgt_<mode>"
3350   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
3351         (gt:<F2I> (match_operand:VSF 1 "spu_reg_operand" "r")
3352                   (match_operand:VSF 2 "spu_reg_operand" "r")))]
3353   ""
3354   "fcgt\t%0,%1,%2")
3356 (define_insn "cmgt_<mode>"
3357   [(set (match_operand:<F2I> 0 "spu_reg_operand" "=r")
3358         (gt:<F2I> (abs:VSF (match_operand:VSF 1 "spu_reg_operand" "r"))
3359                   (abs:VSF (match_operand:VSF 2 "spu_reg_operand" "r"))))]
3360   ""
3361   "fcmgt\t%0,%1,%2")
3363 (define_expand "cgt_df"
3364   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3365         (gt:SI (match_operand:DF 1 "spu_reg_operand" "r")
3366                (match_operand:DF 2 "const_zero_operand" "i")))]
3367   ""
3369   if (spu_arch == PROCESSOR_CELL)
3370     {
3371       rtx ra = gen_reg_rtx (V4SImode);
3372       rtx rb = gen_reg_rtx (V4SImode);
3373       rtx zero = gen_reg_rtx (V4SImode);
3374       rtx temp = gen_reg_rtx (TImode);
3375       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3376       rtx temp2 = gen_reg_rtx (V4SImode);
3377       rtx hi_inf = gen_reg_rtx (V4SImode);
3378       rtx a_nan = gen_reg_rtx (V4SImode);
3379       rtx b_nan = gen_reg_rtx (V4SImode);
3380       rtx a_abs = gen_reg_rtx (V4SImode);
3381       rtx b_abs = gen_reg_rtx (V4SImode);
3382       rtx asel = gen_reg_rtx (V4SImode);
3383       rtx bsel = gen_reg_rtx (V4SImode);
3384       rtx abor = gen_reg_rtx (V4SImode);
3385       rtx bbor = gen_reg_rtx (V4SImode);
3386       rtx gt_hi = gen_reg_rtx (V4SImode);
3387       rtx gt_lo = gen_reg_rtx (V4SImode);
3388       rtx sign_mask = gen_reg_rtx (V4SImode);
3389       rtx nan_mask = gen_reg_rtx (V4SImode);
3390       rtx hi_promote = gen_reg_rtx (TImode);
3391       rtx borrow_shuffle = gen_reg_rtx (TImode);
3393       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF,
3394                                                0x7FFFFFFF, 0xFFFFFFFF);
3395       emit_move_insn (sign_mask, pat);
3396       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0,
3397                                              0x7FF00000, 0x0);
3398       emit_move_insn (nan_mask, pat);
3399       pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203,
3400                                          0x08090A0B, 0x08090A0B);
3401       emit_move_insn (hi_promote, pat);
3402       pat = spu_const_from_ints (TImode, 0x04050607, 0xC0C0C0C0,
3403                                          0x0C0D0E0F, 0xC0C0C0C0);
3404       emit_move_insn (borrow_shuffle, pat);
3406       emit_insn (gen_spu_convert (ra, operands[1]));
3407       emit_insn (gen_spu_convert (rb, operands[2]));
3408       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3409       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3411       if (!flag_finite_math_only)
3412         {
3413           /* check if ra is NaN  */
3414           emit_insn (gen_ceq_v4si (hi_inf, a_abs, nan_mask));
3415           emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3416           emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan),
3417                                   GEN_INT (4 * 8)));
3418           emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3419           emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3420           emit_insn (gen_shufb (a_nan, a_nan, a_nan, hi_promote));
3422           /* check if rb is NaN  */
3423           emit_insn (gen_ceq_v4si (hi_inf, b_abs, nan_mask));
3424           emit_insn (gen_clgt_v4si (b_nan, b_abs, nan_mask));
3425           emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, b_nan),
3426                                   GEN_INT (4 * 8)));
3427           emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3428           emit_insn (gen_iorv4si3 (b_nan, b_nan, temp2));
3429           emit_insn (gen_shufb (b_nan, b_nan, b_nan, hi_promote));
3431           /* check if ra or rb is NaN  */
3432           emit_insn (gen_iorv4si3 (a_nan, a_nan, b_nan));
3433         }
3434       emit_move_insn (zero, CONST0_RTX (V4SImode));
3435       emit_insn (gen_vashrv4si3 (asel, ra, spu_const (V4SImode, 31)));
3436       emit_insn (gen_shufb (asel, asel, asel, hi_promote));
3437       emit_insn (gen_bg_v4si (abor, zero, a_abs));
3438       emit_insn (gen_shufb (abor, abor, abor, borrow_shuffle));
3439       emit_insn (gen_sfx_v4si (abor, zero, a_abs, abor));
3440       emit_insn (gen_selb (abor, a_abs, abor, asel));
3442       emit_insn (gen_vashrv4si3 (bsel, rb, spu_const (V4SImode, 31)));
3443       emit_insn (gen_shufb (bsel, bsel, bsel, hi_promote));
3444       emit_insn (gen_bg_v4si (bbor, zero, b_abs));
3445       emit_insn (gen_shufb (bbor, bbor, bbor, borrow_shuffle));
3446       emit_insn (gen_sfx_v4si (bbor, zero, b_abs, bbor));
3447       emit_insn (gen_selb (bbor, b_abs, bbor, bsel));
3449       emit_insn (gen_cgt_v4si (gt_hi, abor, bbor));
3450       emit_insn (gen_clgt_v4si (gt_lo, abor, bbor));
3451       emit_insn (gen_ceq_v4si (temp2, abor, bbor));
3452       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, gt_lo),
3453                                 GEN_INT (4 * 8)));
3454       emit_insn (gen_andv4si3 (temp2, temp2, temp_v4si));
3455       emit_insn (gen_iorv4si3 (temp2, gt_hi, temp2));
3456       emit_insn (gen_shufb (temp2, temp2, temp2, hi_promote));
3457       if (!flag_finite_math_only)
3458         {
3459           /* correct for NaNs  */
3460           emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3461         }
3462       emit_insn (gen_spu_convert (operands[0], temp2));
3463       DONE;
3464     }
3467 (define_insn "cgt_<mode>_celledp"
3468   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
3469         (gt:<DF2I> (match_operand:VDF 1 "spu_reg_operand" "r")
3470                    (match_operand:VDF 2 "spu_reg_operand" "r")))]
3471   "spu_arch == PROCESSOR_CELLEDP"
3472   "dfcgt\t%0,%1,%2"
3473   [(set_attr "type" "fpd")])
3475 (define_insn "cmgt_<mode>_celledp"
3476   [(set (match_operand:<DF2I> 0 "spu_reg_operand" "=r")
3477         (gt:<DF2I> (abs:VDF (match_operand:VDF 1 "spu_reg_operand" "r"))
3478                    (abs:VDF (match_operand:VDF 2 "spu_reg_operand" "r"))))]
3479   "spu_arch == PROCESSOR_CELLEDP"
3480   "dfcmgt\t%0,%1,%2"
3481   [(set_attr "type" "fpd")])
3483 (define_expand "cgt_v2df"
3484   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3485         (gt:V2DI (match_operand:V2DF 1 "spu_reg_operand" "r")
3486                  (match_operand:V2DF 2 "spu_reg_operand" "r")))]
3487   ""
3489   if (spu_arch == PROCESSOR_CELL)
3490     {
3491       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3492       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
3493       rtx zero = gen_reg_rtx (V4SImode);
3494       rtx temp = gen_reg_rtx (TImode);
3495       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3496       rtx temp2 = gen_reg_rtx (V4SImode);
3497       rtx hi_inf = gen_reg_rtx (V4SImode);
3498       rtx a_nan = gen_reg_rtx (V4SImode);
3499       rtx b_nan = gen_reg_rtx (V4SImode);
3500       rtx a_abs = gen_reg_rtx (V4SImode);
3501       rtx b_abs = gen_reg_rtx (V4SImode);
3502       rtx asel = gen_reg_rtx (V4SImode);
3503       rtx bsel = gen_reg_rtx (V4SImode);
3504       rtx abor = gen_reg_rtx (V4SImode);
3505       rtx bbor = gen_reg_rtx (V4SImode);
3506       rtx gt_hi = gen_reg_rtx (V4SImode);
3507       rtx gt_lo = gen_reg_rtx (V4SImode);
3508       rtx sign_mask = gen_reg_rtx (V4SImode);
3509       rtx nan_mask = gen_reg_rtx (V4SImode);
3510       rtx hi_promote = gen_reg_rtx (TImode);
3511       rtx borrow_shuffle = gen_reg_rtx (TImode);
3512       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3513                                                0x7FFFFFFF, 0xFFFFFFFF);
3514       emit_move_insn (sign_mask, pat);
3515       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3516                                            0x7FF00000, 0x0);
3517       emit_move_insn (nan_mask, pat);
3518       pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203, 
3519                                          0x08090A0B, 0x08090A0B);
3520       emit_move_insn (hi_promote, pat);
3521       pat = spu_const_from_ints (TImode, 0x04050607, 0xC0C0C0C0, 
3522                                          0x0C0D0E0F, 0xC0C0C0C0);
3523       emit_move_insn (borrow_shuffle, pat);
3525       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3526       emit_insn (gen_ceq_v4si (hi_inf, a_abs, nan_mask));
3527       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3528       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
3529                                                     GEN_INT (4 * 8)));
3530       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3531       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3532       emit_insn (gen_shufb (a_nan, a_nan, a_nan, hi_promote));
3533       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3534       emit_insn (gen_ceq_v4si (hi_inf, b_abs, nan_mask));
3535       emit_insn (gen_clgt_v4si (b_nan, b_abs, nan_mask));
3536       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, b_nan), 
3537                                                     GEN_INT (4 * 8)));
3538       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3539       emit_insn (gen_iorv4si3 (b_nan, b_nan, temp2));
3540       emit_insn (gen_shufb (b_nan, b_nan, b_nan, hi_promote));
3541       emit_insn (gen_iorv4si3 (a_nan, a_nan, b_nan));
3542       emit_move_insn (zero, CONST0_RTX (V4SImode));
3543       emit_insn (gen_vashrv4si3 (asel, ra, spu_const (V4SImode, 31)));
3544       emit_insn (gen_shufb (asel, asel, asel, hi_promote));
3545       emit_insn (gen_bg_v4si (abor, zero, a_abs));
3546       emit_insn (gen_shufb (abor, abor, abor, borrow_shuffle));
3547       emit_insn (gen_sfx_v4si (abor, zero, a_abs, abor));
3548       emit_insn (gen_selb (abor, a_abs, abor, asel));
3549       emit_insn (gen_vashrv4si3 (bsel, rb, spu_const (V4SImode, 31)));
3550       emit_insn (gen_shufb (bsel, bsel, bsel, hi_promote));
3551       emit_insn (gen_bg_v4si (bbor, zero, b_abs));
3552       emit_insn (gen_shufb (bbor, bbor, bbor, borrow_shuffle));
3553       emit_insn (gen_sfx_v4si (bbor, zero, b_abs, bbor));
3554       emit_insn (gen_selb (bbor, b_abs, bbor, bsel));
3555       emit_insn (gen_cgt_v4si (gt_hi, abor, bbor));
3556       emit_insn (gen_clgt_v4si (gt_lo, abor, bbor));
3557       emit_insn (gen_ceq_v4si (temp2, abor, bbor));
3558       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, gt_lo), 
3559                                                     GEN_INT (4 * 8)));
3560       emit_insn (gen_andv4si3 (temp2, temp2, temp_v4si));
3561       emit_insn (gen_iorv4si3 (temp2, gt_hi, temp2));
3563       emit_insn (gen_shufb (temp2, temp2, temp2, hi_promote));
3564       emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3565       emit_move_insn (operands[0], spu_gen_subreg (V2DImode, temp2));
3566       DONE;
3567     } 
3570 (define_expand "cmgt_v2df"
3571   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3572         (gt:V2DI (abs:V2DF (match_operand:V2DF 1 "spu_reg_operand" "r"))
3573                  (abs:V2DF (match_operand:V2DF 2 "spu_reg_operand" "r"))))]
3574   ""
3576   if (spu_arch == PROCESSOR_CELL)
3577     {
3578       rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3579       rtx rb = spu_gen_subreg (V4SImode, operands[2]);
3580       rtx temp = gen_reg_rtx (TImode);
3581       rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3582       rtx temp2 = gen_reg_rtx (V4SImode);
3583       rtx hi_inf = gen_reg_rtx (V4SImode);
3584       rtx a_nan = gen_reg_rtx (V4SImode);
3585       rtx b_nan = gen_reg_rtx (V4SImode);
3586       rtx a_abs = gen_reg_rtx (V4SImode);
3587       rtx b_abs = gen_reg_rtx (V4SImode);
3588       rtx gt_hi = gen_reg_rtx (V4SImode);
3589       rtx gt_lo = gen_reg_rtx (V4SImode);
3590       rtx sign_mask = gen_reg_rtx (V4SImode);
3591       rtx nan_mask = gen_reg_rtx (V4SImode);
3592       rtx hi_promote = gen_reg_rtx (TImode);
3593       rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3594                                                0x7FFFFFFF, 0xFFFFFFFF);
3595       emit_move_insn (sign_mask, pat);
3596       pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3597                                            0x7FF00000, 0x0);
3598       emit_move_insn (nan_mask, pat);
3599       pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203, 
3600                                          0x08090A0B, 0x08090A0B);
3601       emit_move_insn (hi_promote, pat);
3603       emit_insn (gen_andv4si3 (a_abs, ra, sign_mask));
3604       emit_insn (gen_ceq_v4si (hi_inf, a_abs, nan_mask));
3605       emit_insn (gen_clgt_v4si (a_nan, a_abs, nan_mask));
3606       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, a_nan), 
3607                                                     GEN_INT (4 * 8)));
3608       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3609       emit_insn (gen_iorv4si3 (a_nan, a_nan, temp2));
3610       emit_insn (gen_shufb (a_nan, a_nan, a_nan, hi_promote));
3611       emit_insn (gen_andv4si3 (b_abs, rb, sign_mask));
3612       emit_insn (gen_ceq_v4si (hi_inf, b_abs, nan_mask));
3613       emit_insn (gen_clgt_v4si (b_nan, b_abs, nan_mask));
3614       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, b_nan), 
3615                                                     GEN_INT (4 * 8)));
3616       emit_insn (gen_andv4si3 (temp2, temp_v4si, hi_inf));
3617       emit_insn (gen_iorv4si3 (b_nan, b_nan, temp2));
3618       emit_insn (gen_shufb (b_nan, b_nan, b_nan, hi_promote));
3619       emit_insn (gen_iorv4si3 (a_nan, a_nan, b_nan));
3621       emit_insn (gen_clgt_v4si (gt_hi, a_abs, b_abs));
3622       emit_insn (gen_clgt_v4si (gt_lo, a_abs, b_abs));
3623       emit_insn (gen_ceq_v4si (temp2, a_abs, b_abs));
3624       emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, gt_lo), 
3625                                                     GEN_INT (4 * 8)));
3626       emit_insn (gen_andv4si3 (temp2, temp2, temp_v4si));
3627       emit_insn (gen_iorv4si3 (temp2, gt_hi, temp2));
3628       emit_insn (gen_shufb (temp2, temp2, temp2, hi_promote));
3629       emit_insn (gen_andc_v4si (temp2, temp2, a_nan));
3630       emit_move_insn (operands[0], spu_gen_subreg (V2DImode, temp2));
3631       DONE;
3632     }
3636 ;; clgt
3638 (define_insn "clgt_<mode>"
3639   [(set (match_operand:VQHSI 0 "spu_reg_operand" "=r,r")
3640         (gtu:VQHSI (match_operand:VQHSI 1 "spu_reg_operand" "r,r")
3641                    (match_operand:VQHSI 2 "spu_arith_operand" "r,B")))]
3642   ""
3643   "@
3644   clgt<bh>\t%0,%1,%2
3645   clgt<bh>i\t%0,%1,%2")
3647 (define_insn_and_split "clgt_di" 
3648   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3649         (gtu:SI (match_operand:DI 1 "spu_reg_operand" "r")
3650                 (match_operand:DI 2 "spu_reg_operand" "r")))
3651    (clobber (match_scratch:V4SI 3 "=&r"))
3652    (clobber (match_scratch:V4SI 4 "=&r"))
3653    (clobber (match_scratch:V4SI 5 "=&r"))]
3654   ""
3655   "#"
3656   "reload_completed"
3657   [(set (match_dup:SI 0)
3658         (gtu:SI (match_dup:DI 1)
3659                 (match_dup:DI 2)))]
3660   {
3661     rtx op0 = gen_rtx_REG (V4SImode, REGNO (operands[0]));
3662     rtx op1 = gen_rtx_REG (V4SImode, REGNO (operands[1]));
3663     rtx op2 = gen_rtx_REG (V4SImode, REGNO (operands[2]));
3664     rtx op3 = operands[3];
3665     rtx op4 = operands[4];
3666     rtx op5 = operands[5];
3667     rtx op5d = gen_rtx_REG (V2DImode, REGNO (operands[5]));
3668     emit_insn (gen_clgt_v4si (op3, op1, op2));
3669     emit_insn (gen_ceq_v4si (op4, op1, op2));
3670     emit_insn (gen_spu_xswd (op5d, op3));
3671     emit_insn (gen_selb (op0, op3, op5, op4));
3672     DONE;
3673   })
3675 (define_insn "clgt_ti"
3676   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
3677         (gtu:SI (match_operand:TI 1 "spu_reg_operand" "r")
3678                (match_operand:TI 2 "spu_reg_operand" "r")))
3679    (clobber (match_scratch:V4SI 3 "=&r"))
3680    (clobber (match_scratch:V4SI 4 "=&r"))]
3681   ""
3682   "ceq\t%3,%1,%2\;\
3683 clgt\t%4,%1,%2\;\
3684 shlqbyi\t%0,%4,4\;\
3685 selb\t%0,%4,%0,%3\;\
3686 shlqbyi\t%0,%0,4\;\
3687 selb\t%0,%4,%0,%3\;\
3688 shlqbyi\t%0,%0,4\;\
3689 selb\t%0,%4,%0,%3"
3690   [(set_attr "type" "multi0")
3691    (set_attr "length" "32")])
3694 ;; dftsv
3695 (define_insn "dftsv_celledp"
3696   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3697         (unspec:V2DI [(match_operand:V2DF 1 "spu_reg_operand"  "r")
3698                       (match_operand:SI   2 "const_int_operand" "i")]
3699                       UNSPEC_DFTSV))]
3700   "spu_arch == PROCESSOR_CELLEDP"
3701   "dftsv\t%0,%1,%2"
3702   [(set_attr "type" "fpd")])
3704 (define_expand "dftsv"
3705   [(set (match_operand:V2DI 0 "spu_reg_operand" "=r")
3706         (unspec:V2DI [(match_operand:V2DF 1 "spu_reg_operand" "r")
3707                       (match_operand:SI   2 "const_int_operand" "i")]
3708                       UNSPEC_DFTSV))]
3709   ""
3711   if (spu_arch == PROCESSOR_CELL)
3712     {
3713       rtx result = gen_reg_rtx (V4SImode);
3714       emit_move_insn (result, CONST0_RTX (V4SImode));
3716       if (INTVAL (operands[2]))
3717         {
3718           rtx ra = spu_gen_subreg (V4SImode, operands[1]);
3719           rtx abs = gen_reg_rtx (V4SImode);
3720           rtx sign = gen_reg_rtx (V4SImode);
3721           rtx temp = gen_reg_rtx (TImode);
3722           rtx temp_v4si = spu_gen_subreg (V4SImode, temp);
3723           rtx temp2 = gen_reg_rtx (V4SImode);
3724           rtx pat = spu_const_from_ints (V4SImode, 0x7FFFFFFF, 0xFFFFFFFF, 
3725                                                    0x7FFFFFFF, 0xFFFFFFFF);
3726           rtx sign_mask = gen_reg_rtx (V4SImode);
3727           rtx hi_promote = gen_reg_rtx (TImode);
3728           emit_move_insn (sign_mask, pat);
3729           pat = spu_const_from_ints (TImode, 0x00010203, 0x00010203, 
3730                                              0x08090A0B, 0x08090A0B);
3731           emit_move_insn (hi_promote, pat);
3733           emit_insn (gen_vashrv4si3 (sign, ra, spu_const (V4SImode, 31)));
3734           emit_insn (gen_shufb (sign, sign, sign, hi_promote));
3735           emit_insn (gen_andv4si3 (abs, ra, sign_mask));
3737           /* NaN  or +inf or -inf */
3738           if (INTVAL (operands[2]) & 0x70)
3739             {
3740               rtx nan_mask = gen_reg_rtx (V4SImode);
3741               rtx isinf = gen_reg_rtx (V4SImode);
3742               pat = spu_const_from_ints (V4SImode, 0x7FF00000, 0x0, 
3743                                                    0x7FF00000, 0x0);
3744               emit_move_insn (nan_mask, pat);
3745               emit_insn (gen_ceq_v4si (isinf, abs, nan_mask));
3747               /* NaN  */
3748               if (INTVAL (operands[2]) & 0x40)
3749                 {
3750                   rtx isnan = gen_reg_rtx (V4SImode);
3751                   emit_insn (gen_clgt_v4si (isnan, abs, nan_mask));
3752                   emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, isnan), 
3753                                                              GEN_INT (4 * 8)));
3754                   emit_insn (gen_andv4si3 (temp2, temp_v4si, isinf));
3755                   emit_insn (gen_iorv4si3 (isnan, isnan, temp2));
3756                   emit_insn (gen_shufb (isnan, isnan, isnan, hi_promote));
3757                   emit_insn (gen_iorv4si3 (result, result, isnan));
3758                 }
3759               /* +inf or -inf  */
3760               if (INTVAL (operands[2]) & 0x30)
3761                 {
3762                   emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, isinf), 
3763                                                              GEN_INT (4 * 8)));
3764                   emit_insn (gen_andv4si3 (isinf, isinf, temp_v4si));
3765                   emit_insn (gen_shufb (isinf, isinf, isinf, hi_promote));
3767                   /* +inf  */
3768                   if (INTVAL (operands[2]) & 0x20)
3769                     {
3770                       emit_insn (gen_andc_v4si (temp2, isinf, sign));
3771                       emit_insn (gen_iorv4si3 (result, result, temp2));
3772                     }
3773                   /* -inf  */
3774                   if (INTVAL (operands[2]) & 0x10)
3775                     {
3776                       emit_insn (gen_andv4si3 (temp2, isinf, sign));
3777                       emit_insn (gen_iorv4si3 (result, result, temp2));
3778                     }
3779                 }
3780             }
3782           /* 0 or denorm  */
3783           if (INTVAL (operands[2]) & 0xF)
3784             {
3785               rtx iszero = gen_reg_rtx (V4SImode);
3786               emit_insn (gen_ceq_v4si (iszero, abs, CONST0_RTX (V4SImode)));
3787               emit_insn (gen_rotlti3 (temp, spu_gen_subreg (TImode, iszero), 
3788                                                           GEN_INT (4 * 8)));
3789               emit_insn (gen_andv4si3 (iszero, iszero, temp_v4si));
3791               /* denorm  */
3792               if (INTVAL (operands[2]) & 0x3)
3793                 {
3794                   rtx isdenorm = gen_reg_rtx (V4SImode);
3795                   rtx denorm_mask = gen_reg_rtx (V4SImode);
3796                   emit_move_insn (denorm_mask, spu_const (V4SImode, 0xFFFFF));
3797                   emit_insn (gen_clgt_v4si (isdenorm, abs, denorm_mask));
3798                   emit_insn (gen_nor_v4si (isdenorm, isdenorm, iszero));
3799                   emit_insn (gen_shufb (isdenorm, isdenorm, 
3800                                         isdenorm, hi_promote));
3801                   /* +denorm  */
3802                   if (INTVAL (operands[2]) & 0x2)
3803                     {
3804                       emit_insn (gen_andc_v4si (temp2, isdenorm, sign));
3805                       emit_insn (gen_iorv4si3 (result, result, temp2));
3806                     }
3807                   /* -denorm  */
3808                   if (INTVAL (operands[2]) & 0x1)
3809                     {
3810                       emit_insn (gen_andv4si3 (temp2, isdenorm, sign));
3811                       emit_insn (gen_iorv4si3 (result, result, temp2));
3812                     }
3813                 }
3815               /* 0  */
3816               if (INTVAL (operands[2]) & 0xC)
3817                 {
3818                   emit_insn (gen_shufb (iszero, iszero, iszero, hi_promote));
3819                   /* +0  */
3820                   if (INTVAL (operands[2]) & 0x8)
3821                     {
3822                       emit_insn (gen_andc_v4si (temp2, iszero, sign));
3823                       emit_insn (gen_iorv4si3 (result, result, temp2));
3824                     }
3825                   /* -0  */
3826                   if (INTVAL (operands[2]) & 0x4)
3827                     {
3828                       emit_insn (gen_andv4si3 (temp2, iszero, sign));
3829                       emit_insn (gen_iorv4si3 (result, result, temp2));
3830                     }
3831                 }
3832              }
3833           }
3834       emit_move_insn (operands[0], spu_gen_subreg (V2DImode, result));
3835       DONE;
3836     }
3840 ;; branches
3842 (define_insn ""
3843   [(set (pc)
3844         (if_then_else (match_operator 1 "branch_comparison_operator"
3845                                       [(match_operand 2
3846                                                       "spu_reg_operand" "r")
3847                                        (const_int 0)])
3848                       (label_ref (match_operand 0 "" ""))
3849                       (pc)))]
3850   ""
3851   "br%b2%b1z\t%2,%0"
3852   [(set_attr "type" "br")])
3854 (define_insn ""
3855   [(set (pc)
3856         (if_then_else (match_operator 0 "branch_comparison_operator"
3857                                       [(match_operand 1
3858                                                       "spu_reg_operand" "r")
3859                                        (const_int 0)])
3860                       (return)
3861                       (pc)))]
3862   "direct_return ()"
3863   "bi%b1%b0z\t%1,$lr"
3864   [(set_attr "type" "br")])
3866 (define_insn ""
3867   [(set (pc)
3868         (if_then_else (match_operator 1 "branch_comparison_operator"
3869                                       [(match_operand 2
3870                                                       "spu_reg_operand" "r")
3871                                        (const_int 0)])
3872                       (pc)
3873                       (label_ref (match_operand 0 "" ""))))]
3874   ""
3875   "br%b2%b1z\t%2,%0"
3876   [(set_attr "type" "br")])
3878 (define_insn ""
3879   [(set (pc)
3880         (if_then_else (match_operator 0 "branch_comparison_operator"
3881                                       [(match_operand 1
3882                                                       "spu_reg_operand" "r")
3883                                        (const_int 0)])
3884                       (pc)
3885                       (return)))]
3886   "direct_return ()"
3887   "bi%b1%b0z\t%1,$lr"
3888   [(set_attr "type" "br")])
3891 ;; vector conditional compare patterns
3892 (define_expand "vcond<mode><mode>"
3893   [(set (match_operand:VCMP 0 "spu_reg_operand" "=r")
3894         (if_then_else:VCMP
3895           (match_operator 3 "comparison_operator"
3896             [(match_operand:VCMP 4 "spu_reg_operand" "r")
3897              (match_operand:VCMP 5 "spu_reg_operand" "r")])
3898           (match_operand:VCMP 1 "spu_reg_operand" "r")
3899           (match_operand:VCMP 2 "spu_reg_operand" "r")))]
3900   ""
3901   {
3902     if (spu_emit_vector_cond_expr (operands[0], operands[1], operands[2],
3903                                    operands[3], operands[4], operands[5]))
3904     DONE;
3905     else
3906     FAIL;
3907   })
3909 (define_expand "vcondu<mode><mode>"
3910   [(set (match_operand:VCMPU 0 "spu_reg_operand" "=r")
3911         (if_then_else:VCMPU
3912           (match_operator 3 "comparison_operator"
3913             [(match_operand:VCMPU 4 "spu_reg_operand" "r")
3914              (match_operand:VCMPU 5 "spu_reg_operand" "r")])
3915           (match_operand:VCMPU 1 "spu_reg_operand" "r")
3916           (match_operand:VCMPU 2 "spu_reg_operand" "r")))]
3917   ""
3918   {
3919     if (spu_emit_vector_cond_expr (operands[0], operands[1], operands[2],
3920                                    operands[3], operands[4], operands[5]))
3921     DONE;
3922     else
3923     FAIL;
3924   })
3925         
3927 ;; branch on condition
3929 (define_expand "cbranch<mode>4"
3930   [(use (match_operator 0 "ordered_comparison_operator"
3931          [(match_operand:VQHSI 1 "spu_reg_operand" "")
3932           (match_operand:VQHSI 2 "spu_nonmem_operand" "")]))
3933    (use (match_operand 3 ""))]
3934   ""
3935   { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
3937 (define_expand "cbranch<mode>4"
3938   [(use (match_operator 0 "ordered_comparison_operator"
3939          [(match_operand:DTI 1 "spu_reg_operand" "")
3940           (match_operand:DTI 2 "spu_reg_operand" "")]))
3941    (use (match_operand 3 ""))]
3942   ""
3943   { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
3945 (define_expand "cbranch<mode>4"
3946   [(use (match_operator 0 "ordered_comparison_operator"
3947          [(match_operand:VSF 1 "spu_reg_operand" "")
3948           (match_operand:VSF 2 "spu_reg_operand" "")]))
3949    (use (match_operand 3 ""))]
3950   ""
3951   { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
3953 (define_expand "cbranchdf4"
3954   [(use (match_operator 0 "ordered_comparison_operator"
3955          [(match_operand:DF 1 "spu_reg_operand" "")
3956           (match_operand:DF 2 "spu_reg_operand" "")]))
3957    (use (match_operand 3 ""))]
3958   ""
3959   { spu_emit_branch_or_set (0, operands[0], operands); DONE; })
3962 ;; set on condition
3964 (define_expand "cstore<mode>4"
3965   [(use (match_operator 1 "ordered_comparison_operator"
3966          [(match_operand:VQHSI 2 "spu_reg_operand" "")
3967           (match_operand:VQHSI 3 "spu_nonmem_operand" "")]))
3968    (clobber (match_operand:SI 0 "spu_reg_operand"))]
3969   ""
3970   { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
3972 (define_expand "cstore<mode>4"
3973   [(use (match_operator 1 "ordered_comparison_operator"
3974          [(match_operand:DTI 2 "spu_reg_operand" "")
3975           (match_operand:DTI 3 "spu_reg_operand" "")]))
3976    (clobber (match_operand:SI 0 "spu_reg_operand"))]
3977   ""
3978   { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
3980 (define_expand "cstore<mode>4"
3981   [(use (match_operator 1 "ordered_comparison_operator"
3982          [(match_operand:VSF 2 "spu_reg_operand" "")
3983           (match_operand:VSF 3 "spu_reg_operand" "")]))
3984    (clobber (match_operand:SI 0 "spu_reg_operand"))]
3985   ""
3986   { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
3988 (define_expand "cstoredf4"
3989   [(use (match_operator 1 "ordered_comparison_operator"
3990          [(match_operand:DF 2 "spu_reg_operand" "")
3991           (match_operand:DF 3 "spu_reg_operand" "")]))
3992    (clobber (match_operand:SI 0 "spu_reg_operand"))]
3993   ""
3994   { spu_emit_branch_or_set (1, operands[1], operands); DONE; })
3997 ;; conditional move
3999 ;; Define this first one so HAVE_conditional_move is defined.
4000 (define_insn "movcc_dummy"
4001   [(set (match_operand 0 "" "")
4002        (if_then_else (match_operand 1 "" "")
4003                      (match_operand 2 "" "")
4004                      (match_operand 3 "" "")))]
4005   "!operands[0]"
4006   "")
4008 (define_expand "mov<mode>cc"
4009   [(set (match_operand:ALL 0 "spu_reg_operand" "")
4010         (if_then_else:ALL (match_operand 1 "ordered_comparison_operator" "")
4011                       (match_operand:ALL 2 "spu_reg_operand" "")
4012                       (match_operand:ALL 3 "spu_reg_operand" "")))]
4013   ""
4014   {
4015     spu_emit_branch_or_set(2, operands[1], operands);
4016     DONE;
4017   })
4019 ;; This pattern is used when the result of a compare is not large
4020 ;; enough to use in a selb when expanding conditional moves.
4021 (define_expand "extend_compare"
4022   [(set (match_operand 0 "spu_reg_operand" "=r")
4023         (unspec [(match_operand 1 "spu_reg_operand" "r")] UNSPEC_EXTEND_CMP))]
4024   ""
4025   {
4026     emit_insn (gen_rtx_SET (operands[0],
4027                             gen_rtx_UNSPEC (GET_MODE (operands[0]),
4028                                             gen_rtvec (1, operands[1]),
4029                                             UNSPEC_EXTEND_CMP)));
4030     DONE;
4031   })
4033 (define_insn "extend_compare<mode>"
4034   [(set (match_operand:ALL 0 "spu_reg_operand" "=r")
4035         (unspec:ALL [(match_operand 1 "spu_reg_operand" "r")] UNSPEC_EXTEND_CMP))]
4036   "operands != NULL"
4037   "fsm\t%0,%1"
4038   [(set_attr "type" "shuf")])
4041 ;; case
4043 ;; operand 0 is index
4044 ;; operand 1 is the minimum bound
4045 ;; operand 2 is the maximum bound - minimum bound + 1
4046 ;; operand 3 is CODE_LABEL for the table;
4047 ;; operand 4 is the CODE_LABEL to go to if index out of range.
4048 (define_expand "casesi"
4049   [(match_operand:SI 0 "spu_reg_operand" "")
4050    (match_operand:SI 1 "immediate_operand" "")
4051    (match_operand:SI 2 "immediate_operand" "")
4052    (match_operand 3 "" "")
4053    (match_operand 4 "" "")]
4054   ""
4055   {
4056     rtx table = gen_reg_rtx (SImode);
4057     rtx index = gen_reg_rtx (SImode);
4058     rtx sindex = gen_reg_rtx (SImode);
4059     rtx addr = gen_reg_rtx (Pmode);
4061     emit_move_insn (table, gen_rtx_LABEL_REF (SImode, operands[3]));
4063     emit_insn (gen_subsi3(index, operands[0], force_reg(SImode, operands[1])));
4064     emit_insn (gen_ashlsi3(sindex, index, GEN_INT (2)));
4065     emit_move_insn (addr, gen_rtx_MEM (SImode,
4066                                        gen_rtx_PLUS (SImode, table, sindex)));
4067     if (flag_pic)
4068       emit_insn (gen_addsi3 (addr, addr, table));
4070     emit_cmp_and_jump_insns (index, operands[2], GTU, NULL_RTX, SImode, 1, operands[4]);
4071     emit_jump_insn (gen_tablejump (addr, operands[3]));
4072     DONE;
4073   })
4075 (define_insn "tablejump"
4076   [(set (pc) (match_operand:SI 0 "spu_reg_operand" "r"))
4077    (use (label_ref (match_operand 1 "" "")))]
4078   ""
4079   "bi\t%0"
4080   [(set_attr "type" "br")])
4083 ;; call
4085 ;; Note that operand 1 is total size of args, in bytes,
4086 ;; and what the call insn wants is the number of words.
4087 (define_expand "sibcall"
4088   [(parallel
4089     [(call (match_operand:QI 0 "call_operand" "")
4090            (match_operand:QI 1 "" ""))
4091      (use (reg:SI 0))])]
4092   ""
4093   {
4094     if (! call_operand (operands[0], QImode))
4095       XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
4096   })
4098 (define_insn "_sibcall"
4099   [(parallel
4100     [(call (match_operand:QI 0 "call_operand" "R,S")
4101            (match_operand:QI 1 "" "i,i"))
4102      (use (reg:SI 0))])]
4103   "SIBLING_CALL_P(insn)"
4104   "@
4105    bi\t%i0
4106    br\t%0"
4107    [(set_attr "type" "br,br")])
4109 (define_expand "sibcall_value"
4110   [(parallel
4111     [(set (match_operand 0 "" "")
4112           (call (match_operand:QI 1 "call_operand" "")
4113                 (match_operand:QI 2 "" "")))
4114      (use (reg:SI 0))])]
4115   ""
4116   {
4117     if (! call_operand (operands[1], QImode))
4118       XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
4119   })
4121 (define_insn "_sibcall_value"
4122   [(parallel
4123     [(set (match_operand 0 "" "")
4124           (call (match_operand:QI 1 "call_operand" "R,S")
4125                 (match_operand:QI 2 "" "i,i")))
4126      (use (reg:SI 0))])]
4127   "SIBLING_CALL_P(insn)"
4128   "@
4129    bi\t%i1
4130    br\t%1"
4131    [(set_attr "type" "br,br")])
4133 ;; Note that operand 1 is total size of args, in bytes,
4134 ;; and what the call insn wants is the number of words.
4135 (define_expand "call"
4136   [(parallel
4137     [(call (match_operand:QI 0 "call_operand" "")
4138            (match_operand:QI 1 "" ""))
4139      (clobber (reg:SI 0))
4140      (clobber (reg:SI 130))])]
4141   ""
4142   {
4143     if (! call_operand (operands[0], QImode))
4144       XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
4145   })
4147 (define_insn "_call"
4148   [(parallel
4149     [(call (match_operand:QI 0 "call_operand" "R,S,T")
4150            (match_operand:QI 1 "" "i,i,i"))
4151      (clobber (reg:SI 0))
4152      (clobber (reg:SI 130))])]
4153   ""
4154   "@
4155    bisl\t$lr,%i0
4156    brsl\t$lr,%0
4157    brasl\t$lr,%0"
4158    [(set_attr "type" "br")])
4160 (define_expand "call_value"
4161   [(parallel
4162     [(set (match_operand 0 "" "")
4163           (call (match_operand:QI 1 "call_operand" "")
4164                 (match_operand:QI 2 "" "")))
4165      (clobber (reg:SI 0))
4166      (clobber (reg:SI 130))])]
4167   ""
4168   {
4169     if (! call_operand (operands[1], QImode))
4170       XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
4171   })
4173 (define_insn "_call_value"
4174   [(parallel
4175     [(set (match_operand 0 "" "")
4176           (call (match_operand:QI 1 "call_operand" "R,S,T")
4177                 (match_operand:QI 2 "" "i,i,i")))
4178      (clobber (reg:SI 0))
4179      (clobber (reg:SI 130))])]
4180   ""
4181   "@
4182    bisl\t$lr,%i1
4183    brsl\t$lr,%1
4184    brasl\t$lr,%1"
4185    [(set_attr "type" "br")])
4187 (define_expand "untyped_call"
4188   [(parallel [(call (match_operand 0 "" "")
4189                     (const_int 0))
4190               (match_operand 1 "" "")
4191               (match_operand 2 "" "")])]
4192   ""
4193   {
4194     int i;
4195     rtx reg = gen_rtx_REG (TImode, 3);
4197     /* We need to use call_value so the return value registers don't get
4198      * clobbered. */
4199     emit_call_insn (gen_call_value (reg, operands[0], const0_rtx));
4201     for (i = 0; i < XVECLEN (operands[2], 0); i++)
4202       {
4203         rtx set = XVECEXP (operands[2], 0, i);
4204         emit_move_insn (SET_DEST (set), SET_SRC (set));
4205       }
4207     /* The optimizer does not know that the call sets the function value
4208        registers we stored in the result block.  We avoid problems by
4209        claiming that all hard registers are used and clobbered at this
4210        point.  */
4211     emit_insn (gen_blockage ());
4213     DONE;
4214   })
4217 ;; Patterns used for splitting and combining.
4220 ;; Function prologue and epilogue.
4222 (define_expand "prologue"
4223   [(const_int 1)]
4224   ""
4225   { spu_expand_prologue (); DONE; })
4227 ;; "blockage" is only emitted in epilogue.  This is what it took to
4228 ;; make "basic block reordering" work with the insns sequence
4229 ;; generated by the spu_expand_epilogue (taken from mips.md)
4231 (define_insn "blockage"
4232   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
4233   ""
4234   ""
4235   [(set_attr "type" "convert")
4236    (set_attr "length" "0")])
4238 (define_expand "epilogue"
4239   [(const_int 2)]
4240   ""
4241   { spu_expand_epilogue (false); DONE; })
4243 (define_expand "sibcall_epilogue"
4244   [(const_int 2)]
4245   ""
4246   { spu_expand_epilogue (true); DONE; })
4249 ;; stack manipulations
4251 ;; An insn to allocate new stack space for dynamic use (e.g., alloca).
4252 ;; We move the back-chain and decrement the stack pointer.
4253 (define_expand "allocate_stack"
4254   [(set (match_operand 0 "spu_reg_operand" "")
4255         (minus (reg 1) (match_operand 1 "spu_nonmem_operand" "")))
4256    (set (reg 1)
4257         (minus (reg 1) (match_dup 1)))]
4258   ""
4259   "spu_allocate_stack (operands[0], operands[1]); DONE;")
4261 ;; These patterns say how to save and restore the stack pointer.  We need not
4262 ;; save the stack pointer at function level since we are careful to preserve 
4263 ;; the backchain.  
4264 ;; 
4266 ;; At block level the stack pointer is saved and restored, so that the
4267 ;; stack space allocated within a block is deallocated when leaving
4268 ;; block scope.  By default, according to the SPU ABI, the stack
4269 ;; pointer and available stack size are saved in a register. Upon
4270 ;; restoration, the stack pointer is simply copied back, and the
4271 ;; current available stack size is calculated against the restored
4272 ;; stack pointer.
4274 ;; For nonlocal gotos, we must save the stack pointer and its
4275 ;; backchain and restore both.  Note that in the nonlocal case, the
4276 ;; save area is a memory location.
4278 (define_expand "save_stack_function"
4279   [(match_operand 0 "general_operand" "")
4280    (match_operand 1 "general_operand" "")]
4281   ""
4282   "DONE;")
4284 (define_expand "restore_stack_function"
4285   [(match_operand 0 "general_operand" "")
4286    (match_operand 1 "general_operand" "")]
4287   ""
4288   "DONE;")
4290 (define_expand "restore_stack_block"
4291   [(match_operand 0 "spu_reg_operand" "")
4292    (match_operand 1 "memory_operand" "")]
4293   ""
4294   "
4295   {
4296     spu_restore_stack_block (operands[0], operands[1]);
4297     DONE;
4298   }")
4300 (define_expand "save_stack_nonlocal"
4301   [(match_operand 0 "memory_operand" "")
4302    (match_operand 1 "spu_reg_operand" "")]
4303   ""
4304   "
4305   {
4306     rtx temp = gen_reg_rtx (Pmode);
4308     /* Copy the backchain to the first word, sp to the second.  We need to
4309        save the back chain because __builtin_apply appears to clobber it. */
4310     emit_move_insn (temp, gen_rtx_MEM (Pmode, operands[1]));
4311     emit_move_insn (adjust_address_nv (operands[0], SImode, 0), temp);
4312     emit_move_insn (adjust_address_nv (operands[0], SImode, 4), operands[1]);
4313     DONE;
4314   }")
4316 (define_expand "restore_stack_nonlocal"
4317   [(match_operand 0 "spu_reg_operand" "")
4318    (match_operand 1 "memory_operand" "")]
4319   ""
4320   "
4321   {
4322     spu_restore_stack_nonlocal(operands[0], operands[1]);
4323     DONE;
4324   }")
4327 ;; vector patterns
4329 ;; Vector initialization
4330 (define_expand "vec_init<mode><inner_l>"
4331   [(match_operand:V 0 "register_operand" "")
4332    (match_operand 1 "" "")]
4333   ""
4334   {
4335     spu_expand_vector_init (operands[0], operands[1]);
4336     DONE;
4337   })
4339 (define_expand "vec_set<mode>"
4340   [(use (match_operand:SI 2 "spu_nonmem_operand" ""))
4341    (set (match_dup:TI 3)
4342         (unspec:TI [(match_dup:SI 4)
4343                     (match_dup:SI 5)
4344                     (match_dup:SI 6)] UNSPEC_CPAT))
4345    (set (match_operand:V 0 "spu_reg_operand" "")
4346         (unspec:V [(match_operand:<inner> 1 "spu_reg_operand" "")
4347                    (match_dup:V 0)
4348                    (match_dup:TI 3)] UNSPEC_SHUFB))]
4349   ""
4350   {
4351     HOST_WIDE_INT size = GET_MODE_SIZE (<inner>mode);
4352     rtx offset = GEN_INT (INTVAL (operands[2]) * size);
4353     operands[3] = gen_reg_rtx (TImode);
4354     operands[4] = stack_pointer_rtx;
4355     operands[5] = offset;
4356     operands[6] = GEN_INT (size);
4357   })
4359 (define_expand "vec_extract<mode><inner_l>"
4360   [(set (match_operand:<inner> 0 "spu_reg_operand" "=r")
4361         (vec_select:<inner> (match_operand:V 1 "spu_reg_operand" "r")
4362                             (parallel [(match_operand 2 "const_int_operand" "i")])))]
4363   ""
4364   {
4365     if ((INTVAL (operands[2]) * <vmult> + <voff>) % 16 == 0)
4366       {
4367         emit_insn (gen_spu_convert (operands[0], operands[1]));
4368         DONE;
4369       }
4370   })
4372 (define_insn "_vec_extract<mode>"
4373   [(set (match_operand:<inner> 0 "spu_reg_operand" "=r")
4374         (vec_select:<inner> (match_operand:V 1 "spu_reg_operand" "r")
4375                             (parallel [(match_operand 2 "const_int_operand" "i")])))]
4376   ""
4377   "rotqbyi\t%0,%1,(%2*<vmult>+<voff>)%%16"
4378   [(set_attr "type" "shuf")])
4380 (define_insn "_vec_extractv8hi_ze"
4381   [(set (match_operand:SI 0 "spu_reg_operand" "=r")
4382         (zero_extend:SI (vec_select:HI (match_operand:V8HI 1 "spu_reg_operand" "r")
4383                                        (parallel [(const_int 0)]))))]
4384   ""
4385   "rotqmbyi\t%0,%1,-2"
4386   [(set_attr "type" "shuf")])
4389 ;; misc
4391 (define_expand "shufb"
4392   [(set (match_operand 0 "spu_reg_operand" "")
4393         (unspec [(match_operand 1 "spu_reg_operand" "")
4394                  (match_operand 2 "spu_reg_operand" "")
4395                  (match_operand:TI 3 "spu_reg_operand" "")] UNSPEC_SHUFB))]
4396   ""
4397   {
4398     rtx s = gen__shufb (operands[0], operands[1], operands[2], operands[3]);
4399     PUT_MODE (SET_SRC (s), GET_MODE (operands[0]));
4400     emit_insn (s);
4401     DONE;
4402   })
4404 (define_insn "_shufb"
4405   [(set (match_operand 0 "spu_reg_operand" "=r")
4406         (unspec [(match_operand 1 "spu_reg_operand" "r")
4407                  (match_operand 2 "spu_reg_operand" "r")
4408                  (match_operand:TI 3 "spu_reg_operand" "r")] UNSPEC_SHUFB))]
4409   "operands != NULL"
4410   "shufb\t%0,%1,%2,%3"
4411   [(set_attr "type" "shuf")])
4413 ; The semantics of vec_permv16qi are nearly identical to those of the SPU
4414 ; shufb instruction, except that we need to reduce the selector modulo 32.
4415 (define_expand "vec_permv16qi"
4416   [(set (match_dup 4) (and:V16QI (match_operand:V16QI 3 "spu_reg_operand" "")
4417                                  (match_dup 6)))
4418    (set (match_operand:V16QI 0 "spu_reg_operand" "")
4419         (unspec:V16QI
4420           [(match_operand:V16QI 1 "spu_reg_operand" "")
4421            (match_operand:V16QI 2 "spu_reg_operand" "")
4422            (match_dup 5)]
4423           UNSPEC_SHUFB))]
4424   ""
4425   {
4426     operands[4] = gen_reg_rtx (V16QImode);
4427     operands[5] = gen_lowpart (TImode, operands[4]);
4428     operands[6] = spu_const (V16QImode, 31);
4429   })
4431 (define_insn "nop"
4432   [(unspec_volatile [(const_int 0)] UNSPECV_NOP)]
4433   ""
4434   "nop"
4435   [(set_attr "type" "nop")])
4437 (define_insn "nopn"
4438   [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "K")] UNSPECV_NOP)]
4439   ""
4440   "nop\t%0"
4441   [(set_attr "type" "nop")])
4443 (define_insn "lnop"
4444   [(unspec_volatile [(const_int 0)] UNSPECV_LNOP)]
4445   ""
4446   "lnop"
4447   [(set_attr "type" "lnop")])
4449 ;; The operand is so we know why we generated this hbrp.
4450 ;; We clobber mem to make sure it isn't moved over any
4451 ;; loads, stores or calls while scheduling.
4452 (define_insn "iprefetch"
4453   [(unspec [(match_operand:SI 0 "const_int_operand" "n")] UNSPEC_IPREFETCH)
4454    (clobber (mem:BLK (scratch)))]
4455   ""
4456   "hbrp\t# %0"
4457   [(set_attr "type" "iprefetch")])
4459 ;; A non-volatile version so it gets scheduled
4460 (define_insn "nopn_nv"
4461   [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_NOP)]
4462   ""
4463   "nop\t%0"
4464   [(set_attr "type" "nop")])
4466 (define_insn "hbr"
4467   [(set (reg:SI 130)
4468         (unspec:SI [(match_operand:SI 0 "immediate_operand" "i,i,i")
4469                     (match_operand:SI 1 "nonmemory_operand" "r,s,i")] UNSPEC_HBR))
4470    (unspec [(const_int 0)] UNSPEC_HBR)]
4471   ""
4472   "@
4473    hbr\t%0,%1
4474    hbrr\t%0,%1
4475    hbra\t%0,%1"
4476   [(set_attr "type" "hbr")])
4478 (define_insn "sync"
4479   [(unspec_volatile [(const_int 0)] UNSPECV_SYNC)
4480    (clobber (mem:BLK (scratch)))]
4481   ""
4482   "sync"
4483   [(set_attr "type" "br")])
4485 (define_insn "syncc"
4486   [(unspec_volatile [(const_int 1)] UNSPECV_SYNC)
4487    (clobber (mem:BLK (scratch)))]
4488   ""
4489   "syncc"
4490   [(set_attr "type" "br")])
4492 (define_insn "dsync"
4493   [(unspec_volatile [(const_int 2)] UNSPECV_SYNC)
4494    (clobber (mem:BLK (scratch)))]
4495   ""
4496   "dsync"
4497   [(set_attr "type" "br")])
4501  ;; Define the subtract-one-and-jump insns so loop.c
4502  ;; knows what to generate.
4503  (define_expand "doloop_end"
4504    [(use (match_operand 0 "" ""))      ; loop pseudo
4505     (use (match_operand 1 "" ""))]     ; label
4506    ""
4507    "
4509    /* Currently SMS relies on the do-loop pattern to recognize loops
4510       where (1) the control part comprises of all insns defining and/or
4511       using a certain 'count' register and (2) the loop count can be
4512       adjusted by modifying this register prior to the loop.
4513 .     ??? The possible introduction of a new block to initialize the
4514       new IV can potentially effects branch optimizations.  */
4515    if (optimize > 0 && flag_modulo_sched)
4516    {
4517      rtx s0;
4518      rtx bcomp;
4519      rtx loc_ref;
4521      if (GET_MODE (operands[0]) != SImode)
4522        FAIL;
4524      s0 = operands [0];
4525      emit_move_insn (s0, gen_rtx_PLUS (SImode, s0, GEN_INT (-1)));
4526      bcomp = gen_rtx_NE(SImode, s0, const0_rtx);
4527      loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
4528      emit_jump_insn (gen_rtx_SET (pc_rtx,
4529                                   gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
4530                                                         loc_ref, pc_rtx)));
4532      DONE;
4533    }else
4534       FAIL;
4535  }")
4537 ;; convert between any two modes, avoiding any GCC assumptions
4538 (define_expand "spu_convert"
4539   [(set (match_operand 0 "spu_reg_operand" "")
4540         (unspec [(match_operand 1 "spu_reg_operand" "")] UNSPEC_CONVERT))]
4541   ""
4542   {
4543     rtx c = gen__spu_convert (operands[0], operands[1]);
4544     PUT_MODE (SET_SRC (c), GET_MODE (operands[0]));
4545     emit_insn (c);
4546     DONE;
4547   })
4549 (define_insn_and_split "_spu_convert"
4550   [(set (match_operand 0 "spu_reg_operand" "=r")
4551         (unspec [(match_operand 1 "spu_reg_operand" "0")] UNSPEC_CONVERT))]
4552   ""
4553   "#"
4554   "reload_completed"
4555   [(const_int 0)]
4556   {
4557     spu_split_convert (operands);
4558     DONE;
4559   }
4560   [(set_attr "type" "convert")
4561    (set_attr "length" "0")])
4565 (include "spu-builtins.md")
4567   
4568 (define_expand "smaxv4sf3"
4569   [(set (match_operand:V4SF 0 "register_operand" "=r")
4570         (smax:V4SF (match_operand:V4SF 1 "register_operand" "r")
4571                  (match_operand:V4SF 2 "register_operand" "r")))]
4572   ""
4573   "
4575   rtx mask = gen_reg_rtx (V4SImode);
4577   emit_insn (gen_cgt_v4sf (mask, operands[1], operands[2]));
4578   emit_insn (gen_selb (operands[0], operands[2], operands[1], mask));
4579   DONE;
4580 }") 
4582 (define_expand "sminv4sf3"
4583   [(set (match_operand:V4SF 0 "register_operand" "=r")
4584         (smin:V4SF (match_operand:V4SF 1 "register_operand" "r")
4585                  (match_operand:V4SF 2 "register_operand" "r")))]
4586   ""
4587   "
4589   rtx mask = gen_reg_rtx (V4SImode);
4591   emit_insn (gen_cgt_v4sf (mask, operands[1], operands[2]));
4592   emit_insn (gen_selb (operands[0], operands[1], operands[2], mask));
4593   DONE;
4594 }") 
4596 (define_expand "smaxv2df3"
4597   [(set (match_operand:V2DF 0 "register_operand" "=r")
4598         (smax:V2DF (match_operand:V2DF 1 "register_operand" "r")
4599                  (match_operand:V2DF 2 "register_operand" "r")))]
4600   ""
4601   "
4603   rtx mask = gen_reg_rtx (V2DImode);
4604   emit_insn (gen_cgt_v2df (mask, operands[1], operands[2]));
4605   emit_insn (gen_selb (operands[0], operands[2], operands[1], 
4606                        spu_gen_subreg (V4SImode, mask)));
4607   DONE;
4610 (define_expand "sminv2df3"
4611   [(set (match_operand:V2DF 0 "register_operand" "=r")
4612         (smin:V2DF (match_operand:V2DF 1 "register_operand" "r")
4613                  (match_operand:V2DF 2 "register_operand" "r")))]
4614   ""
4615   "
4617   rtx mask = gen_reg_rtx (V2DImode);
4618   emit_insn (gen_cgt_v2df (mask, operands[1], operands[2]));
4619   emit_insn (gen_selb (operands[0], operands[1], operands[2], 
4620                        spu_gen_subreg (V4SImode, mask)));
4621   DONE;
4624 (define_insn "vec_widen_smult_odd_v8hi"
4625   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r,r")
4626         (mult:V4SI
4627           (sign_extend:V4SI
4628             (vec_select:V4HI
4629               (match_operand:V8HI 1 "spu_reg_operand" "r,r")
4630               (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))
4631           (sign_extend:V4SI
4632             (vec_select:V4HI
4633               (match_operand:V8HI 2 "spu_arith_operand" "r,B")
4634               (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))))]
4635   ""
4636   "@
4637    mpy\t%0,%1,%2
4638    mpyi\t%0,%1,%2"
4639   [(set_attr "type" "fp7")])
4641 (define_insn "vec_widen_umult_odd_v8hi"
4642   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r,r")
4643         (mult:V4SI
4644           (zero_extend:V4SI
4645             (vec_select:V4HI
4646               (match_operand:V8HI 1 "spu_reg_operand" "r,r")
4647               (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))
4648           (zero_extend:V4SI
4649             (vec_select:V4HI
4650               (match_operand:V8HI 2 "spu_arith_operand" "r,B")
4651               (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)])))))]
4652   ""
4653   "@
4654    mpyu\t%0,%1,%2
4655    mpyui\t%0,%1,%2"
4656   [(set_attr "type" "fp7")])
4658 (define_insn "vec_widen_smult_even_v8hi"
4659   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4660         (mult:V4SI
4661           (sign_extend:V4SI
4662             (vec_select:V4HI
4663               (match_operand:V8HI 1 "spu_reg_operand" "r")
4664               (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
4665           (sign_extend:V4SI
4666             (vec_select:V4HI
4667               (match_operand:V8HI 2 "spu_reg_operand" "r")
4668               (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))))]
4669   ""
4670   "mpyhh\t%0,%1,%2"
4671   [(set_attr "type" "fp7")])
4673 (define_insn "vec_widen_umult_even_v8hi"
4674   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4675         (mult:V4SI
4676           (zero_extend:V4SI
4677             (vec_select:V4HI
4678               (match_operand:V8HI 1 "spu_reg_operand" "r")
4679               (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))
4680           (zero_extend:V4SI
4681             (vec_select:V4HI
4682               (match_operand:V8HI 2 "spu_reg_operand" "r")
4683               (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)])))))]
4684   ""
4685   "mpyhhu\t%0,%1,%2"
4686   [(set_attr "type" "fp7")])
4688 (define_expand "vec_widen_umult_hi_v8hi"
4689   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4690         (mult:V4SI
4691           (zero_extend:V4SI
4692             (vec_select:V4HI
4693               (match_operand:V8HI 1 "register_operand" "r")
4694               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))
4695           (zero_extend:V4SI
4696             (vec_select:V4HI
4697               (match_operand:V8HI 2 "register_operand" "r")
4698               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))))]
4699   ""
4700   "
4702   rtx ve = gen_reg_rtx (V4SImode);
4703   rtx vo = gen_reg_rtx (V4SImode);
4704   rtx mask = gen_reg_rtx (TImode);
4705   unsigned char arr[16] = {
4706     0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 
4707     0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17};
4708   
4709   emit_move_insn (mask, array_to_constant (TImode, arr));
4710   emit_insn (gen_vec_widen_umult_even_v8hi (ve, operands[1], operands[2]));
4711   emit_insn (gen_vec_widen_umult_odd_v8hi (vo, operands[1], operands[2]));
4712   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4713   DONE;
4716 (define_expand "vec_widen_umult_lo_v8hi"
4717   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4718         (mult:V4SI
4719           (zero_extend:V4SI
4720             (vec_select:V4HI
4721               (match_operand:V8HI 1 "register_operand" "r")
4722               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
4723           (zero_extend:V4SI
4724             (vec_select:V4HI
4725               (match_operand:V8HI 2 "register_operand" "r")
4726               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))))]
4727   ""
4728   "
4730   rtx ve = gen_reg_rtx (V4SImode);
4731   rtx vo = gen_reg_rtx (V4SImode);
4732   rtx mask = gen_reg_rtx (TImode);
4733   unsigned char arr[16] = {
4734     0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 
4735     0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F};
4737   emit_move_insn (mask, array_to_constant (TImode, arr));
4738   emit_insn (gen_vec_widen_umult_even_v8hi (ve, operands[1], operands[2]));
4739   emit_insn (gen_vec_widen_umult_odd_v8hi (vo, operands[1], operands[2]));
4740   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4741   DONE;
4744 (define_expand "vec_widen_smult_hi_v8hi"
4745   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4746         (mult:V4SI
4747           (sign_extend:V4SI
4748             (vec_select:V4HI
4749               (match_operand:V8HI 1 "register_operand" "r")
4750               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))
4751           (sign_extend:V4SI
4752             (vec_select:V4HI
4753               (match_operand:V8HI 2 "register_operand" "r")
4754               (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))))]
4755   ""
4756   "
4758   rtx ve = gen_reg_rtx (V4SImode);
4759   rtx vo = gen_reg_rtx (V4SImode);
4760   rtx mask = gen_reg_rtx (TImode);
4761   unsigned char arr[16] = {
4762     0x00, 0x01, 0x02, 0x03, 0x10, 0x11, 0x12, 0x13, 
4763     0x04, 0x05, 0x06, 0x07, 0x14, 0x15, 0x16, 0x17};
4764   
4765   emit_move_insn (mask, array_to_constant (TImode, arr));
4766   emit_insn (gen_vec_widen_smult_even_v8hi (ve, operands[1], operands[2]));
4767   emit_insn (gen_vec_widen_smult_odd_v8hi (vo, operands[1], operands[2]));
4768   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4769   DONE;
4772 (define_expand "vec_widen_smult_lo_v8hi"
4773   [(set (match_operand:V4SI 0 "register_operand"   "=r")
4774         (mult:V4SI
4775           (sign_extend:V4SI
4776             (vec_select:V4HI
4777               (match_operand:V8HI 1 "register_operand" "r")
4778               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
4779           (sign_extend:V4SI
4780             (vec_select:V4HI
4781               (match_operand:V8HI 2 "register_operand" "r")
4782               (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))))]
4783   ""
4784   "
4786   rtx ve = gen_reg_rtx (V4SImode);
4787   rtx vo = gen_reg_rtx (V4SImode);
4788   rtx mask = gen_reg_rtx (TImode);
4789   unsigned char arr[16] = {
4790     0x08, 0x09, 0x0A, 0x0B, 0x18, 0x19, 0x1A, 0x1B, 
4791     0x0C, 0x0D, 0x0E, 0x0F, 0x1C, 0x1D, 0x1E, 0x1F};
4793   emit_move_insn (mask, array_to_constant (TImode, arr));
4794   emit_insn (gen_vec_widen_smult_even_v8hi (ve, operands[1], operands[2]));
4795   emit_insn (gen_vec_widen_smult_odd_v8hi (vo, operands[1], operands[2]));
4796   emit_insn (gen_shufb (operands[0], ve, vo, mask));
4797   DONE;
4800 (define_expand "vec_realign_load_<mode>"
4801   [(set (match_operand:ALL 0 "register_operand" "=r")
4802         (unspec:ALL [(match_operand:ALL 1 "register_operand" "r")
4803                      (match_operand:ALL 2 "register_operand" "r")
4804                      (match_operand:TI 3 "register_operand" "r")] UNSPEC_SPU_REALIGN_LOAD))]
4805   ""
4806   "
4808   emit_insn (gen_shufb (operands[0], operands[1], operands[2], operands[3])); 
4809   DONE;
4812 (define_expand "spu_lvsr"
4813   [(set (match_operand:V16QI 0 "register_operand" "")
4814         (unspec:V16QI [(match_operand 1 "memory_operand" "")] UNSPEC_SPU_MASK_FOR_LOAD))]
4815   ""
4816   "
4818   rtx addr;
4819   rtx offset = gen_reg_rtx (V8HImode);
4820   rtx addr_bits = gen_reg_rtx (SImode);
4821   rtx addr_bits_vec = gen_reg_rtx (V8HImode);
4822   rtx splatqi = gen_reg_rtx (TImode);
4823   rtx result = gen_reg_rtx (V8HImode);
4824   unsigned char arr[16] = {
4825     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
4826     0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
4827   unsigned char arr2[16] = {
4828     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
4829     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
4831   emit_move_insn (offset, array_to_constant (V8HImode, arr));
4832   emit_move_insn (splatqi, array_to_constant (TImode, arr2));
4834   gcc_assert (GET_CODE (operands[1]) == MEM);
4835   addr = force_reg (Pmode, XEXP (operands[1], 0));
4836   emit_insn (gen_andsi3 (addr_bits, addr, GEN_INT (0xF))); 
4837   emit_insn (gen_shufb (addr_bits_vec, addr_bits, addr_bits, splatqi));
4839   /* offset - (addr & 0xF) 
4840      It is safe to use a single sfh, because each byte of offset is > 15 and
4841      each byte of addr is <= 15. */
4842   emit_insn (gen_subv8hi3 (result, offset, addr_bits_vec));
4844   result = simplify_gen_subreg (V16QImode, result, V8HImode, 0);
4845   emit_move_insn (operands[0], result);
4847   DONE;
4850 (define_expand "vec_unpacku_hi_v8hi"
4851   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4852         (zero_extend:V4SI 
4853           (vec_select:V4HI
4854             (match_operand:V8HI 1 "spu_reg_operand" "r")
4855             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
4856   ""
4858   rtx mask = gen_reg_rtx (TImode);
4859   unsigned char arr[16] = {
4860     0x80, 0x80, 0x00, 0x01, 0x80, 0x80, 0x02, 0x03,
4861     0x80, 0x80, 0x04, 0x05, 0x80, 0x80, 0x06, 0x07};
4863   emit_move_insn (mask, array_to_constant (TImode, arr));
4864   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4866   DONE;
4869 (define_expand "vec_unpacku_lo_v8hi"
4870   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4871          (zero_extend:V4SI
4872           (vec_select:V4HI
4873             (match_operand:V8HI 1 "spu_reg_operand" "r")
4874             (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4877   rtx mask = gen_reg_rtx (TImode);
4878   unsigned char arr[16] = {
4879     0x80, 0x80, 0x08, 0x09, 0x80, 0x80, 0x0A, 0x0B,
4880     0x80, 0x80, 0x0C, 0x0D, 0x80, 0x80, 0x0E, 0x0F};
4882   emit_move_insn (mask, array_to_constant (TImode, arr));
4883   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4884   
4885   DONE;
4888 (define_expand "vec_unpacks_hi_v8hi"
4889   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4890          (sign_extend:V4SI
4891           (vec_select:V4HI
4892             (match_operand:V8HI 1 "spu_reg_operand" "r")
4893             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))))]
4894   ""
4896   rtx tmp1 = gen_reg_rtx (V8HImode);
4897   rtx tmp2 = gen_reg_rtx (V4SImode);
4898   rtx mask = gen_reg_rtx (TImode);
4899   unsigned char arr[16] = {
4900     0x80, 0x80, 0x00, 0x01, 0x80, 0x80, 0x02, 0x03,
4901     0x80, 0x80, 0x04, 0x05, 0x80, 0x80, 0x06, 0x07};
4903   emit_move_insn (mask, array_to_constant (TImode, arr));
4904   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4905   emit_insn (gen_spu_xshw (tmp2, tmp1)); 
4906   emit_move_insn (operands[0], tmp2);
4908   DONE;
4911 (define_expand "vec_unpacks_lo_v8hi"
4912   [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
4913          (sign_extend:V4SI
4914           (vec_select:V4HI
4915             (match_operand:V8HI 1 "spu_reg_operand" "r")
4916             (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4919   rtx tmp1 = gen_reg_rtx (V8HImode);
4920   rtx tmp2 = gen_reg_rtx (V4SImode);
4921   rtx mask = gen_reg_rtx (TImode);
4922   unsigned char arr[16] = {
4923     0x80, 0x80, 0x08, 0x09, 0x80, 0x80, 0x0A, 0x0B,
4924     0x80, 0x80, 0x0C, 0x0D, 0x80, 0x80, 0x0E, 0x0F};
4926   emit_move_insn (mask, array_to_constant (TImode, arr));
4927   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4928   emit_insn (gen_spu_xshw (tmp2, tmp1)); 
4929   emit_move_insn (operands[0], tmp2);
4931 DONE;
4934 (define_expand "vec_unpacku_hi_v16qi"
4935   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4936         (zero_extend:V8HI
4937           (vec_select:V8QI
4938             (match_operand:V16QI 1 "spu_reg_operand" "r")
4939             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
4940                        (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4941   ""
4943   rtx mask = gen_reg_rtx (TImode);
4944   unsigned char arr[16] = {
4945     0x80, 0x00, 0x80, 0x01, 0x80, 0x02, 0x80, 0x03,
4946     0x80, 0x04, 0x80, 0x05, 0x80, 0x06, 0x80, 0x07};
4948   emit_move_insn (mask, array_to_constant (TImode, arr));
4949   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4951   DONE;
4954 (define_expand "vec_unpacku_lo_v16qi"
4955   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4956           (zero_extend:V8HI
4957           (vec_select:V8QI
4958             (match_operand:V16QI 1 "spu_reg_operand" "r")
4959             (parallel [(const_int 8)(const_int 9)(const_int 10)(const_int 11)
4960                        (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
4963   rtx mask = gen_reg_rtx (TImode);
4964   unsigned char arr[16] = {
4965     0x80, 0x08, 0x80, 0x09, 0x80, 0x0A, 0x80, 0x0B,
4966     0x80, 0x0C, 0x80, 0x0D, 0x80, 0x0E, 0x80, 0x0F};
4968   emit_move_insn (mask, array_to_constant (TImode, arr));
4969   emit_insn (gen_shufb (operands[0], operands[1], operands[1], mask));
4971   DONE;
4974 (define_expand "vec_unpacks_hi_v16qi"
4975   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
4976          (sign_extend:V8HI
4977           (vec_select:V8QI
4978             (match_operand:V16QI 1 "spu_reg_operand" "r")
4979             (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)
4980                        (const_int 4)(const_int 5)(const_int 6)(const_int 7)]))))]
4983   rtx tmp1 = gen_reg_rtx (V16QImode);
4984   rtx tmp2 = gen_reg_rtx (V8HImode);
4985   rtx mask = gen_reg_rtx (TImode);
4986   unsigned char arr[16] = {
4987     0x80, 0x00, 0x80, 0x01, 0x80, 0x02, 0x80, 0x03,
4988     0x80, 0x04, 0x80, 0x05, 0x80, 0x06, 0x80, 0x07};
4990   emit_move_insn (mask, array_to_constant (TImode, arr));
4991   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
4992   emit_insn (gen_spu_xsbh (tmp2, tmp1));
4993   emit_move_insn (operands[0], tmp2);
4995   DONE;
4998 (define_expand "vec_unpacks_lo_v16qi"
4999   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
5000          (sign_extend:V8HI
5001           (vec_select:V8QI
5002             (match_operand:V16QI 1 "spu_reg_operand" "r")
5003             (parallel [(const_int 8)(const_int 9)(const_int 10)(const_int 11)
5004                        (const_int 12)(const_int 13)(const_int 14)(const_int 15)]))))]
5007   rtx tmp1 = gen_reg_rtx (V16QImode);
5008   rtx tmp2 = gen_reg_rtx (V8HImode);
5009   rtx mask = gen_reg_rtx (TImode);
5010   unsigned char arr[16] = {
5011     0x80, 0x08, 0x80, 0x09, 0x80, 0x0A, 0x80, 0x0B,
5012     0x80, 0x0C, 0x80, 0x0D, 0x80, 0x0E, 0x80, 0x0F};
5014   emit_move_insn (mask, array_to_constant (TImode, arr));
5015   emit_insn (gen_shufb (tmp1, operands[1], operands[1], mask));
5016   emit_insn (gen_spu_xsbh (tmp2, tmp1));
5017   emit_move_insn (operands[0], tmp2);
5019 DONE;
5023 (define_expand "vec_pack_trunc_v8hi"
5024   [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
5025         (vec_concat:V16QI
5026           (truncate:V8QI (match_operand:V8HI 1 "spu_reg_operand" "r"))
5027           (truncate:V8QI (match_operand:V8HI 2 "spu_reg_operand" "r"))))]
5028   ""
5029   "
5031   rtx mask = gen_reg_rtx (TImode);
5032   unsigned char arr[16] = {
5033     0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F,
5034     0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F};
5036   emit_move_insn (mask, array_to_constant (TImode, arr));
5037   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5039   DONE;
5042 (define_expand "vec_pack_trunc_v4si"
5043   [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
5044         (vec_concat:V8HI
5045           (truncate:V4HI (match_operand:V4SI 1 "spu_reg_operand" "r"))
5046           (truncate:V4HI (match_operand:V4SI 2 "spu_reg_operand" "r"))))]
5047   ""
5048   "
5050   rtx mask = gen_reg_rtx (TImode);
5051   unsigned char arr[16] = {
5052     0x02, 0x03, 0x06, 0x07, 0x0A, 0x0B, 0x0E, 0x0F,
5053     0x12, 0x13, 0x16, 0x17, 0x1A, 0x1B, 0x1E, 0x1F};
5055   emit_move_insn (mask, array_to_constant (TImode, arr));
5056   emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
5058   DONE;
5061 (define_insn "stack_protect_set"
5062   [(set (match_operand:SI 0 "memory_operand" "=m")
5063         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
5064    (set (match_scratch:SI 2 "=&r") (const_int 0))]
5065   ""
5066   "lq%p1\t%2,%1\;stq%p0\t%2,%0\;xor\t%2,%2,%2"
5067   [(set_attr "length" "12")
5068    (set_attr "type" "multi1")]
5071 (define_expand "stack_protect_test"
5072   [(match_operand 0 "memory_operand" "")
5073    (match_operand 1 "memory_operand" "")
5074    (match_operand 2 "" "")]
5075   ""
5077   rtx compare_result;
5078   rtx bcomp, loc_ref;
5080   compare_result = gen_reg_rtx (SImode);
5082   emit_insn (gen_stack_protect_test_si (compare_result,
5083                                         operands[0],
5084                                         operands[1]));
5086   bcomp = gen_rtx_NE (SImode, compare_result, const0_rtx);
5088   loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[2]);
5090   emit_jump_insn (gen_rtx_SET (pc_rtx,
5091                                gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
5092                                                      loc_ref, pc_rtx)));
5094   DONE;
5097 (define_insn "stack_protect_test_si"
5098   [(set (match_operand:SI 0 "spu_reg_operand" "=&r")
5099         (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
5100                     (match_operand:SI 2 "memory_operand" "m")]
5101                    UNSPEC_SP_TEST))
5102    (set (match_scratch:SI 3 "=&r") (const_int 0))]
5103   ""
5104   "lq%p1\t%0,%1\;lq%p2\t%3,%2\;ceq\t%0,%0,%3\;xor\t%3,%3,%3"
5105   [(set_attr "length" "16")
5106    (set_attr "type" "multi1")]
5109 ; Atomic operations
5111 ; SPU execution is always single-threaded, so there is no need for real
5112 ; atomic operations.  We provide the atomic primitives anyway so that
5113 ; code expecting the builtins to be present (like libgfortran) will work.
5115 ;; Types that we should provide atomic instructions for.
5116 (define_mode_iterator AINT [QI HI SI DI TI])
5118 (define_code_iterator ATOMIC [plus minus ior xor and mult])
5119 (define_code_attr atomic_name
5120   [(plus "add") (minus "sub")
5121    (ior "or") (xor "xor") (and "and") (mult "nand")])
5122 (define_code_attr atomic_pred
5123   [(plus "spu_arith_operand") (minus "spu_reg_operand")
5124    (ior "spu_logical_operand") (xor "spu_logical_operand")
5125    (and "spu_logical_operand") (mult "spu_logical_operand")])
5127 (define_expand "atomic_load<mode>"
5128   [(set (match_operand:AINT 0 "spu_reg_operand" "")             ;; output
5129         (match_operand:AINT 1 "memory_operand" ""))             ;; memory
5130    (use (match_operand:SI 2 "const_int_operand" ""))]           ;; model
5131   ""
5133   if (MEM_ADDR_SPACE (operands[1]))
5134     FAIL;
5136   emit_move_insn (operands[0], operands[1]);
5137   DONE;
5140 (define_expand "atomic_store<mode>"
5141   [(set (match_operand:AINT 0 "memory_operand" "")              ;; memory
5142         (match_operand:AINT 1 "spu_reg_operand" ""))            ;; input
5143    (use (match_operand:SI 2 "const_int_operand" ""))]           ;; model
5144   ""
5146   if (MEM_ADDR_SPACE (operands[0]))
5147     FAIL;
5149   emit_move_insn (operands[0], operands[1]);
5150   DONE;
5153 (define_expand "atomic_compare_and_swap<mode>"
5154   [(match_operand:SI 0 "spu_reg_operand" "")            ;; bool out
5155    (match_operand:AINT 1 "spu_reg_operand" "")          ;; val out
5156    (match_operand:AINT 2 "memory_operand" "")           ;; memory
5157    (match_operand:AINT 3 "spu_nonmem_operand" "")       ;; expected
5158    (match_operand:AINT 4 "spu_nonmem_operand" "")       ;; desired
5159    (match_operand:SI 5 "const_int_operand" "")          ;; is_weak
5160    (match_operand:SI 6 "const_int_operand" "")          ;; model succ
5161    (match_operand:SI 7 "const_int_operand" "")]         ;; model fail
5162   ""
5164   rtx boolval, retval, label;
5166   if (MEM_ADDR_SPACE (operands[2]))
5167     FAIL;
5169   boolval = gen_reg_rtx (SImode);
5170   retval = gen_reg_rtx (<MODE>mode);
5171   label = gen_label_rtx ();
5173   emit_move_insn (retval, operands[2]);
5174   emit_move_insn (boolval, const0_rtx);
5176   emit_cmp_and_jump_insns (retval, operands[3], NE, NULL_RTX,
5177                            <MODE>mode, 1, label);
5179   emit_move_insn (operands[2], operands[4]);
5180   emit_move_insn (boolval, const1_rtx);
5182   emit_label (label);
5184   emit_move_insn (operands[0], boolval);
5185   emit_move_insn (operands[1], retval);
5186   DONE;
5189 (define_expand "atomic_exchange<mode>"
5190   [(match_operand:AINT 0 "spu_reg_operand" "")          ;; output
5191    (match_operand:AINT 1 "memory_operand" "")           ;; memory
5192    (match_operand:AINT 2 "spu_nonmem_operand" "")       ;; input
5193    (match_operand:SI 3 "const_int_operand" "")]         ;; model
5194   ""
5196   rtx retval;
5198   if (MEM_ADDR_SPACE (operands[1]))
5199     FAIL;
5201   retval = gen_reg_rtx (<MODE>mode);
5203   emit_move_insn (retval, operands[1]);
5204   emit_move_insn (operands[1], operands[2]);
5205   emit_move_insn (operands[0], retval);
5206   DONE;
5209 (define_expand "atomic_<atomic_name><mode>"
5210   [(ATOMIC:AINT
5211      (match_operand:AINT 0 "memory_operand" "")         ;; memory
5212      (match_operand:AINT 1 "<atomic_pred>" ""))         ;; operand
5213    (match_operand:SI 2 "const_int_operand" "")]         ;; model
5214   ""
5216   if (MEM_ADDR_SPACE (operands[0]))
5217     FAIL;
5219   spu_expand_atomic_op (<CODE>, operands[0], operands[1],
5220                         NULL_RTX, NULL_RTX);
5221   DONE;
5224 (define_expand "atomic_fetch_<atomic_name><mode>"
5225   [(match_operand:AINT 0 "spu_reg_operand" "")          ;; output
5226    (ATOMIC:AINT
5227      (match_operand:AINT 1 "memory_operand" "")         ;; memory
5228      (match_operand:AINT 2 "<atomic_pred>" ""))         ;; operand
5229    (match_operand:SI 3 "const_int_operand" "")]         ;; model
5230   ""
5232   if (MEM_ADDR_SPACE (operands[1]))
5233     FAIL;
5235   spu_expand_atomic_op (<CODE>, operands[1], operands[2],
5236                         operands[0], NULL_RTX);
5237   DONE;
5240 (define_expand "atomic_<atomic_name>_fetch<mode>"
5241   [(match_operand:AINT 0 "spu_reg_operand" "")          ;; output
5242    (ATOMIC:AINT
5243      (match_operand:AINT 1 "memory_operand" "")         ;; memory
5244      (match_operand:AINT 2 "<atomic_pred>" ""))         ;; operand
5245    (match_operand:SI 3 "const_int_operand" "")]         ;; model
5246   ""
5248   if (MEM_ADDR_SPACE (operands[1]))
5249     FAIL;
5251   spu_expand_atomic_op (<CODE>, operands[1], operands[2],
5252                         NULL_RTX, operands[0]);
5253   DONE;