1;; GCC machine description for MMX and 3dNOW! instructions
2;; Copyright (C) 2005
3;; Free Software Foundation, Inc.
4;;
5;; This file is part of GCC.
6;;
7;; GCC is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 2, or (at your option)
10;; any later version.
11;;
12;; GCC is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15;; GNU General Public License for more details.
16;;
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING.  If not, write to
19;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20;; Boston, MA 02110-1301, USA.
21
22;; The MMX and 3dNOW! patterns are in the same file because they use
23;; the same register file, and 3dNOW! adds a number of extensions to
24;; the base integer MMX isa.
25
26;; Note!  Except for the basic move instructions, *all* of these 
27;; patterns are outside the normal optabs namespace.  This is because
28;; use of these registers requires the insertion of emms or femms
29;; instructions to return to normal fpu mode.  The compiler doesn't
30;; know how to do that itself, which means it's up to the user.  Which
31;; means that we should never use any of these patterns except at the
32;; direction of the user via a builtin.
33
34;; 8 byte integral modes handled by MMX (and by extension, SSE)
35(define_mode_macro MMXMODEI [V8QI V4HI V2SI])
36
37;; All 8-byte vector modes handled by MMX
38(define_mode_macro MMXMODE [V8QI V4HI V2SI V2SF])
39
40;; Mix-n-match
41(define_mode_macro MMXMODE12 [V8QI V4HI])
42(define_mode_macro MMXMODE24 [V4HI V2SI])
43
44;; Mapping from integer vector mode to mnemonic suffix
45(define_mode_attr mmxvecsize [(V8QI "b") (V4HI "w") (V2SI "d") (DI "q")])
46
47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
48;;
49;; Move patterns
50;;
51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
52
53;; All of these patterns are enabled for MMX as well as 3dNOW.
54;; This is essential for maintaining stable calling conventions.
55
56(define_expand "mov<mode>"
57  [(set (match_operand:MMXMODEI 0 "nonimmediate_operand" "")
58	(match_operand:MMXMODEI 1 "nonimmediate_operand" ""))]
59  "TARGET_MMX"
60{
61  ix86_expand_vector_move (<MODE>mode, operands);
62  DONE;
63})
64
65(define_insn "*mov<mode>_internal_rex64"
66  [(set (match_operand:MMXMODEI 0 "nonimmediate_operand"
67				"=rm,r,*y,*y ,m ,*y,Y ,x,x ,m,r,x")
68	(match_operand:MMXMODEI 1 "vector_move_operand"
69				"Cr ,m,C ,*ym,*y,Y ,*y,C,xm,x,x,r"))]
70  "TARGET_64BIT && TARGET_MMX
71   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
72  "@
73    movq\t{%1, %0|%0, %1}
74    movq\t{%1, %0|%0, %1}
75    pxor\t%0, %0
76    movq\t{%1, %0|%0, %1}
77    movq\t{%1, %0|%0, %1}
78    movdq2q\t{%1, %0|%0, %1}
79    movq2dq\t{%1, %0|%0, %1}
80    pxor\t%0, %0
81    movq\t{%1, %0|%0, %1}
82    movq\t{%1, %0|%0, %1}
83    movd\t{%1, %0|%0, %1}
84    movd\t{%1, %0|%0, %1}"
85  [(set_attr "type" "imov,imov,mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov,ssemov,ssemov")
86   (set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*")
87   (set_attr "mode" "DI")])
88
89(define_insn "*mov<mode>_internal"
90  [(set (match_operand:MMXMODEI 0 "nonimmediate_operand"
91			"=*y,*y ,m ,*y,*Y,*Y,*Y ,m ,*x,*x,*x,m ,?r ,?m")
92	(match_operand:MMXMODEI 1 "vector_move_operand"
93			"C  ,*ym,*y,*Y,*y,C ,*Ym,*Y,C ,*x,m ,*x,irm,r"))]
94  "TARGET_MMX
95   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
96  "@
97    pxor\t%0, %0
98    movq\t{%1, %0|%0, %1}
99    movq\t{%1, %0|%0, %1}
100    movdq2q\t{%1, %0|%0, %1}
101    movq2dq\t{%1, %0|%0, %1}
102    pxor\t%0, %0
103    movq\t{%1, %0|%0, %1}
104    movq\t{%1, %0|%0, %1}
105    xorps\t%0, %0
106    movaps\t{%1, %0|%0, %1}
107    movlps\t{%1, %0|%0, %1}
108    movlps\t{%1, %0|%0, %1}
109    #
110    #"
111  [(set_attr "type" "mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov,ssemov,ssemov,ssemov,ssemov,*,*")
112   (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*,*,*,*")
113   (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
114
115(define_expand "movv2sf"
116  [(set (match_operand:V2SF 0 "nonimmediate_operand" "")
117	(match_operand:V2SF 1 "nonimmediate_operand" ""))]
118  "TARGET_MMX"
119{
120  ix86_expand_vector_move (V2SFmode, operands);
121  DONE;
122})
123
124(define_insn "*movv2sf_internal_rex64"
125  [(set (match_operand:V2SF 0 "nonimmediate_operand"
126				"=rm,r,*y ,*y ,m ,*y,Y ,x,x,x,m,r,x")
127        (match_operand:V2SF 1 "vector_move_operand"
128				"Cr ,m ,C ,*ym,*y,Y ,*y,C,x,m,x,x,r"))]
129  "TARGET_64BIT && TARGET_MMX
130   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
131  "@
132    movq\t{%1, %0|%0, %1}
133    movq\t{%1, %0|%0, %1}
134    pxor\t%0, %0
135    movq\t{%1, %0|%0, %1}
136    movq\t{%1, %0|%0, %1}
137    movdq2q\t{%1, %0|%0, %1}
138    movq2dq\t{%1, %0|%0, %1}
139    xorps\t%0, %0
140    movaps\t{%1, %0|%0, %1}
141    movlps\t{%1, %0|%0, %1}
142    movlps\t{%1, %0|%0, %1}
143    movd\t{%1, %0|%0, %1}
144    movd\t{%1, %0|%0, %1}"
145  [(set_attr "type" "imov,imov,mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov,ssemov,ssemov,ssemov")
146   (set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*,*")
147   (set_attr "mode" "DI,DI,DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
148
149(define_insn "*movv2sf_internal"
150  [(set (match_operand:V2SF 0 "nonimmediate_operand"
151					"=*y,*y ,m,*y,*Y,*x,*x,*x,m ,?r ,?m")
152        (match_operand:V2SF 1 "vector_move_operand"
153					"C ,*ym,*y,*Y,*y,C ,*x,m ,*x,irm,r"))]
154  "TARGET_MMX
155   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
156  "@
157    pxor\t%0, %0
158    movq\t{%1, %0|%0, %1}
159    movq\t{%1, %0|%0, %1}
160    movdq2q\t{%1, %0|%0, %1}
161    movq2dq\t{%1, %0|%0, %1}
162    xorps\t%0, %0
163    movaps\t{%1, %0|%0, %1}
164    movlps\t{%1, %0|%0, %1}
165    movlps\t{%1, %0|%0, %1}
166    #
167    #"
168  [(set_attr "type" "mmxmov,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,ssemov,ssemov,ssemov,*,*")
169   (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*")
170   (set_attr "mode" "DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
171
172;; %%% This multiword shite has got to go.
173(define_split
174  [(set (match_operand:MMXMODE 0 "nonimmediate_operand" "")
175        (match_operand:MMXMODE 1 "general_operand" ""))]
176  "!TARGET_64BIT && reload_completed
177   && (!MMX_REG_P (operands[0]) && !SSE_REG_P (operands[0]))
178   && (!MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
179  [(const_int 0)]
180  "ix86_split_long_move (operands); DONE;")
181
182(define_expand "push<mode>1"
183  [(match_operand:MMXMODE 0 "register_operand" "")]
184  "TARGET_MMX"
185{
186  ix86_expand_push (<MODE>mode, operands[0]);
187  DONE;
188})
189
190(define_expand "movmisalign<mode>"
191  [(set (match_operand:MMXMODE 0 "nonimmediate_operand" "")
192	(match_operand:MMXMODE 1 "nonimmediate_operand" ""))]
193  "TARGET_MMX"
194{
195  ix86_expand_vector_move (<MODE>mode, operands);
196  DONE;
197})
198
199(define_insn "sse_movntdi"
200  [(set (match_operand:DI 0 "memory_operand" "=m")
201	(unspec:DI [(match_operand:DI 1 "register_operand" "y")]
202		   UNSPEC_MOVNT))]
203  "TARGET_SSE || TARGET_3DNOW_A"
204  "movntq\t{%1, %0|%0, %1}"
205  [(set_attr "type" "mmxmov")
206   (set_attr "mode" "DI")])
207
208;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
209;;
210;; Parallel single-precision floating point arithmetic
211;;
212;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
213
214(define_insn "mmx_addv2sf3"
215  [(set (match_operand:V2SF 0 "register_operand" "=y")
216	(plus:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
217		   (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
218  "TARGET_3DNOW && ix86_binary_operator_ok (PLUS, V2SFmode, operands)"
219  "pfadd\\t{%2, %0|%0, %2}"
220  [(set_attr "type" "mmxadd")
221   (set_attr "mode" "V2SF")])
222
223(define_insn "mmx_subv2sf3"
224  [(set (match_operand:V2SF 0 "register_operand" "=y,y")
225        (minus:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "0,ym")
226		    (match_operand:V2SF 2 "nonimmediate_operand" "ym,0")))]
227  "TARGET_3DNOW && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
228  "@
229   pfsub\\t{%2, %0|%0, %2}
230   pfsubr\\t{%2, %0|%0, %2}"
231  [(set_attr "type" "mmxadd")
232   (set_attr "mode" "V2SF")])
233
234(define_expand "mmx_subrv2sf3"
235  [(set (match_operand:V2SF 0 "register_operand" "")
236        (minus:V2SF (match_operand:V2SF 2 "nonimmediate_operand" "")
237		    (match_operand:V2SF 1 "nonimmediate_operand" "")))]
238  "TARGET_3DNOW && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
239  "")
240
241(define_insn "mmx_mulv2sf3"
242  [(set (match_operand:V2SF 0 "register_operand" "=y")
243	(mult:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
244		   (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
245  "TARGET_3DNOW && ix86_binary_operator_ok (MULT, V2SFmode, operands)"
246  "pfmul\\t{%2, %0|%0, %2}"
247  [(set_attr "type" "mmxmul")
248   (set_attr "mode" "V2SF")])
249
250(define_insn "mmx_smaxv2sf3"
251  [(set (match_operand:V2SF 0 "register_operand" "=y")
252        (smax:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
253                   (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
254  "TARGET_3DNOW && ix86_binary_operator_ok (SMAX, V2SFmode, operands)"
255  "pfmax\\t{%2, %0|%0, %2}"
256  [(set_attr "type" "mmxadd")
257   (set_attr "mode" "V2SF")])
258
259(define_insn "mmx_sminv2sf3"
260  [(set (match_operand:V2SF 0 "register_operand" "=y")
261        (smin:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
262                   (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
263  "TARGET_3DNOW && ix86_binary_operator_ok (SMIN, V2SFmode, operands)"
264  "pfmin\\t{%2, %0|%0, %2}"
265  [(set_attr "type" "mmxadd")
266   (set_attr "mode" "V2SF")])
267
268(define_insn "mmx_rcpv2sf2"
269  [(set (match_operand:V2SF 0 "register_operand" "=y")
270        (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")]
271		     UNSPEC_PFRCP))]
272  "TARGET_3DNOW"
273  "pfrcp\\t{%1, %0|%0, %1}"
274  [(set_attr "type" "mmx")
275   (set_attr "mode" "V2SF")])
276
277(define_insn "mmx_rcpit1v2sf3"
278  [(set (match_operand:V2SF 0 "register_operand" "=y")
279	(unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
280		      (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
281		     UNSPEC_PFRCPIT1))]
282  "TARGET_3DNOW"
283  "pfrcpit1\\t{%2, %0|%0, %2}"
284  [(set_attr "type" "mmx")
285   (set_attr "mode" "V2SF")])
286
287(define_insn "mmx_rcpit2v2sf3"
288  [(set (match_operand:V2SF 0 "register_operand" "=y")
289	(unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
290		      (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
291		     UNSPEC_PFRCPIT2))]
292  "TARGET_3DNOW"
293  "pfrcpit2\\t{%2, %0|%0, %2}"
294  [(set_attr "type" "mmx")
295   (set_attr "mode" "V2SF")])
296
297(define_insn "mmx_rsqrtv2sf2"
298  [(set (match_operand:V2SF 0 "register_operand" "=y")
299	(unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")]
300		     UNSPEC_PFRSQRT))]
301  "TARGET_3DNOW"
302  "pfrsqrt\\t{%1, %0|%0, %1}"
303  [(set_attr "type" "mmx")
304   (set_attr "mode" "V2SF")])
305		
306(define_insn "mmx_rsqit1v2sf3"
307  [(set (match_operand:V2SF 0 "register_operand" "=y")
308	(unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
309		      (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
310		     UNSPEC_PFRSQIT1))]
311  "TARGET_3DNOW"
312  "pfrsqit1\\t{%2, %0|%0, %2}"
313  [(set_attr "type" "mmx")
314   (set_attr "mode" "V2SF")])
315
316(define_insn "mmx_haddv2sf3"
317  [(set (match_operand:V2SF 0 "register_operand" "=y")
318	(vec_concat:V2SF
319	  (plus:SF
320	    (vec_select:SF
321	      (match_operand:V2SF 1 "register_operand" "0")
322	      (parallel [(const_int  0)]))
323	    (vec_select:SF (match_dup 1) (parallel [(const_int 1)])))
324	  (plus:SF
325            (vec_select:SF
326	      (match_operand:V2SF 2 "nonimmediate_operand" "ym")
327	      (parallel [(const_int  0)]))
328	    (vec_select:SF (match_dup 2) (parallel [(const_int 1)])))))]
329  "TARGET_3DNOW"
330  "pfacc\\t{%2, %0|%0, %2}"
331  [(set_attr "type" "mmxadd")
332   (set_attr "mode" "V2SF")])
333
334(define_insn "mmx_hsubv2sf3"
335  [(set (match_operand:V2SF 0 "register_operand" "=y")
336	(vec_concat:V2SF
337	  (minus:SF
338	    (vec_select:SF
339	      (match_operand:V2SF 1 "register_operand" "0")
340	      (parallel [(const_int  0)]))
341	    (vec_select:SF (match_dup 1) (parallel [(const_int 1)])))
342	  (minus:SF
343            (vec_select:SF
344	      (match_operand:V2SF 2 "nonimmediate_operand" "ym")
345	      (parallel [(const_int  0)]))
346	    (vec_select:SF (match_dup 2) (parallel [(const_int 1)])))))]
347  "TARGET_3DNOW_A"
348  "pfnacc\\t{%2, %0|%0, %2}"
349  [(set_attr "type" "mmxadd")
350   (set_attr "mode" "V2SF")])
351
352(define_insn "mmx_addsubv2sf3"
353  [(set (match_operand:V2SF 0 "register_operand" "=y")
354        (vec_merge:V2SF
355          (plus:V2SF
356            (match_operand:V2SF 1 "register_operand" "0")
357            (match_operand:V2SF 2 "nonimmediate_operand" "ym"))
358          (minus:V2SF (match_dup 1) (match_dup 2))
359          (const_int 1)))]
360  "TARGET_3DNOW_A"
361  "pfpnacc\\t{%2, %0|%0, %2}"
362  [(set_attr "type" "mmxadd")
363   (set_attr "mode" "V2SF")])
364
365;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
366;;
367;; Parallel single-precision floating point comparisons
368;;
369;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
370
371(define_insn "mmx_gtv2sf3"
372  [(set (match_operand:V2SI 0 "register_operand" "=y")
373	(gt:V2SI (match_operand:V2SF 1 "register_operand" "0")
374		 (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
375  "TARGET_3DNOW"
376  "pfcmpgt\\t{%2, %0|%0, %2}"
377  [(set_attr "type" "mmxcmp")
378   (set_attr "mode" "V2SF")])
379
380(define_insn "mmx_gev2sf3"
381  [(set (match_operand:V2SI 0 "register_operand" "=y")
382	(ge:V2SI (match_operand:V2SF 1 "register_operand" "0")
383		 (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
384  "TARGET_3DNOW"
385  "pfcmpge\\t{%2, %0|%0, %2}"
386  [(set_attr "type" "mmxcmp")
387   (set_attr "mode" "V2SF")])
388
389(define_insn "mmx_eqv2sf3"
390  [(set (match_operand:V2SI 0 "register_operand" "=y")
391	(eq:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "%0")
392		 (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
393  "TARGET_3DNOW && ix86_binary_operator_ok (EQ, V2SFmode, operands)"
394  "pfcmpeq\\t{%2, %0|%0, %2}"
395  [(set_attr "type" "mmxcmp")
396   (set_attr "mode" "V2SF")])
397
398;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
399;;
400;; Parallel single-precision floating point conversion operations
401;;
402;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
403
404(define_insn "mmx_pf2id"
405  [(set (match_operand:V2SI 0 "register_operand" "=y")
406	(fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))]
407  "TARGET_3DNOW"
408  "pf2id\\t{%1, %0|%0, %1}"
409  [(set_attr "type" "mmxcvt")
410   (set_attr "mode" "V2SF")])
411
412(define_insn "mmx_pf2iw"
413  [(set (match_operand:V2SI 0 "register_operand" "=y")
414	(sign_extend:V2SI
415	  (ss_truncate:V2HI
416	    (fix:V2SI
417	      (match_operand:V2SF 1 "nonimmediate_operand" "ym")))))]
418  "TARGET_3DNOW_A"
419  "pf2iw\\t{%1, %0|%0, %1}"
420  [(set_attr "type" "mmxcvt")
421   (set_attr "mode" "V2SF")])
422
423(define_insn "mmx_pi2fw"
424  [(set (match_operand:V2SF 0 "register_operand" "=y")
425	(float:V2SF
426	  (sign_extend:V2SI
427	    (truncate:V2HI
428	      (match_operand:V2SI 1 "nonimmediate_operand" "ym")))))]
429  "TARGET_3DNOW_A"
430  "pi2fw\\t{%1, %0|%0, %1}"
431  [(set_attr "type" "mmxcvt")
432   (set_attr "mode" "V2SF")])
433
434(define_insn "mmx_floatv2si2"
435  [(set (match_operand:V2SF 0 "register_operand" "=y")
436	(float:V2SF (match_operand:V2SI 1 "nonimmediate_operand" "ym")))]
437  "TARGET_3DNOW"
438  "pi2fd\\t{%1, %0|%0, %1}"
439  [(set_attr "type" "mmxcvt")
440   (set_attr "mode" "V2SF")])
441
442;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
443;;
444;; Parallel single-precision floating point element swizzling
445;;
446;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
447
448(define_insn "mmx_pswapdv2sf2"
449  [(set (match_operand:V2SF 0 "register_operand" "=y")
450	(vec_select:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "ym")
451			 (parallel [(const_int 1) (const_int 0)])))]
452  "TARGET_3DNOW_A"
453  "pswapd\\t{%1, %0|%0, %1}"
454  [(set_attr "type" "mmxcvt")
455   (set_attr "mode" "V2SF")])
456
457(define_insn "*vec_dupv2sf"
458  [(set (match_operand:V2SF 0 "register_operand" "=y")
459	(vec_duplicate:V2SF
460	  (match_operand:SF 1 "register_operand" "0")))]
461  "TARGET_MMX"
462  "punpckldq\t%0, %0"
463  [(set_attr "type" "mmxcvt")
464   (set_attr "mode" "DI")])
465
466(define_insn "*mmx_concatv2sf"
467  [(set (match_operand:V2SF 0 "register_operand"     "=y,y")
468	(vec_concat:V2SF
469	  (match_operand:SF 1 "nonimmediate_operand" " 0,rm")
470	  (match_operand:SF 2 "vector_move_operand"  "ym,C")))]
471  "TARGET_MMX && !TARGET_SSE"
472  "@
473   punpckldq\t{%2, %0|%0, %2}
474   movd\t{%1, %0|%0, %1}"
475  [(set_attr "type" "mmxcvt,mmxmov")
476   (set_attr "mode" "DI")])
477
478(define_expand "vec_setv2sf"
479  [(match_operand:V2SF 0 "register_operand" "")
480   (match_operand:SF 1 "register_operand" "")
481   (match_operand 2 "const_int_operand" "")]
482  "TARGET_MMX"
483{
484  ix86_expand_vector_set (false, operands[0], operands[1],
485			  INTVAL (operands[2]));
486  DONE;
487})
488
489(define_insn_and_split "*vec_extractv2sf_0"
490  [(set (match_operand:SF 0 "nonimmediate_operand"     "=x,y,m,m,frxy")
491	(vec_select:SF
492	  (match_operand:V2SF 1 "nonimmediate_operand" " x,y,x,y,m")
493	  (parallel [(const_int 0)])))]
494  "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
495  "#"
496  "&& reload_completed"
497  [(const_int 0)]
498{
499  rtx op1 = operands[1];
500  if (REG_P (op1))
501    op1 = gen_rtx_REG (SFmode, REGNO (op1));
502  else
503    op1 = gen_lowpart (SFmode, op1);
504  emit_move_insn (operands[0], op1);
505  DONE;
506})
507
508(define_insn "*vec_extractv2sf_1"
509  [(set (match_operand:SF 0 "nonimmediate_operand"     "=y,x,frxy")
510	(vec_select:SF
511	  (match_operand:V2SF 1 "nonimmediate_operand" " 0,0,o")
512	  (parallel [(const_int 1)])))]
513  "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
514  "@
515   punpckhdq\t%0, %0
516   unpckhps\t%0, %0
517   #"
518  [(set_attr "type" "mmxcvt,sselog1,*")
519   (set_attr "mode" "DI,V4SF,SI")])
520
521(define_split
522  [(set (match_operand:SF 0 "register_operand" "")
523	(vec_select:SF
524	  (match_operand:V2SF 1 "memory_operand" "")
525	  (parallel [(const_int 1)])))]
526  "TARGET_MMX && reload_completed"
527  [(const_int 0)]
528{
529  operands[1] = adjust_address (operands[1], SFmode, 4);
530  emit_move_insn (operands[0], operands[1]);
531  DONE;
532})
533
534(define_expand "vec_extractv2sf"
535  [(match_operand:SF 0 "register_operand" "")
536   (match_operand:V2SF 1 "register_operand" "")
537   (match_operand 2 "const_int_operand" "")]
538  "TARGET_MMX"
539{
540  ix86_expand_vector_extract (false, operands[0], operands[1],
541			      INTVAL (operands[2]));
542  DONE;
543})
544
545(define_expand "vec_initv2sf"
546  [(match_operand:V2SF 0 "register_operand" "")
547   (match_operand 1 "" "")]
548  "TARGET_SSE"
549{
550  ix86_expand_vector_init (false, operands[0], operands[1]);
551  DONE;
552})
553
554;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
555;;
556;; Parallel integral arithmetic
557;;
558;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
559
560(define_insn "mmx_add<mode>3"
561  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
562        (plus:MMXMODEI
563	  (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
564	  (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
565  "TARGET_MMX && ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
566  "padd<mmxvecsize>\t{%2, %0|%0, %2}"
567  [(set_attr "type" "mmxadd")
568   (set_attr "mode" "DI")])
569
570(define_insn "mmx_adddi3"
571  [(set (match_operand:DI 0 "register_operand" "=y")
572        (unspec:DI
573	 [(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
574		   (match_operand:DI 2 "nonimmediate_operand" "ym"))]
575	 UNSPEC_NOP))]
576  "TARGET_MMX && ix86_binary_operator_ok (PLUS, DImode, operands)"
577  "paddq\t{%2, %0|%0, %2}"
578  [(set_attr "type" "mmxadd")
579   (set_attr "mode" "DI")])
580
581(define_insn "mmx_ssadd<mode>3"
582  [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
583        (ss_plus:MMXMODE12
584	  (match_operand:MMXMODE12 1 "nonimmediate_operand" "%0")
585	  (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
586  "TARGET_MMX"
587  "padds<mmxvecsize>\t{%2, %0|%0, %2}"
588  [(set_attr "type" "mmxadd")
589   (set_attr "mode" "DI")])
590
591(define_insn "mmx_usadd<mode>3"
592  [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
593        (us_plus:MMXMODE12
594	  (match_operand:MMXMODE12 1 "nonimmediate_operand" "%0")
595	  (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
596  "TARGET_MMX"
597  "paddus<mmxvecsize>\t{%2, %0|%0, %2}"
598  [(set_attr "type" "mmxadd")
599   (set_attr "mode" "DI")])
600
601(define_insn "mmx_sub<mode>3"
602  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
603        (minus:MMXMODEI
604	  (match_operand:MMXMODEI 1 "register_operand" "0")
605	  (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
606  "TARGET_MMX"
607  "psub<mmxvecsize>\t{%2, %0|%0, %2}"
608  [(set_attr "type" "mmxadd")
609   (set_attr "mode" "DI")])
610
611(define_insn "mmx_subdi3"
612  [(set (match_operand:DI 0 "register_operand" "=y")
613        (unspec:DI
614	 [(minus:DI (match_operand:DI 1 "register_operand" "0")
615		    (match_operand:DI 2 "nonimmediate_operand" "ym"))]
616	 UNSPEC_NOP))]
617  "TARGET_MMX"
618  "psubq\t{%2, %0|%0, %2}"
619  [(set_attr "type" "mmxadd")
620   (set_attr "mode" "DI")])
621
622(define_insn "mmx_sssub<mode>3"
623  [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
624        (ss_minus:MMXMODE12
625	  (match_operand:MMXMODE12 1 "register_operand" "0")
626	  (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
627  "TARGET_MMX"
628  "psubs<mmxvecsize>\t{%2, %0|%0, %2}"
629  [(set_attr "type" "mmxadd")
630   (set_attr "mode" "DI")])
631
632(define_insn "mmx_ussub<mode>3"
633  [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
634        (us_minus:MMXMODE12
635	  (match_operand:MMXMODE12 1 "register_operand" "0")
636	  (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
637  "TARGET_MMX"
638  "psubus<mmxvecsize>\t{%2, %0|%0, %2}"
639  [(set_attr "type" "mmxadd")
640   (set_attr "mode" "DI")])
641
642(define_insn "mmx_mulv4hi3"
643  [(set (match_operand:V4HI 0 "register_operand" "=y")
644        (mult:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0")
645		   (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
646  "TARGET_MMX && ix86_binary_operator_ok (MULT, V4HImode, operands)"
647  "pmullw\t{%2, %0|%0, %2}"
648  [(set_attr "type" "mmxmul")
649   (set_attr "mode" "DI")])
650
651(define_insn "mmx_smulv4hi3_highpart"
652  [(set (match_operand:V4HI 0 "register_operand" "=y")
653	(truncate:V4HI
654	 (lshiftrt:V4SI
655	  (mult:V4SI (sign_extend:V4SI
656		      (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
657		     (sign_extend:V4SI
658		      (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
659	  (const_int 16))))]
660  "TARGET_MMX && ix86_binary_operator_ok (MULT, V4HImode, operands)"
661  "pmulhw\t{%2, %0|%0, %2}"
662  [(set_attr "type" "mmxmul")
663   (set_attr "mode" "DI")])
664
665(define_insn "mmx_umulv4hi3_highpart"
666  [(set (match_operand:V4HI 0 "register_operand" "=y")
667	(truncate:V4HI
668	 (lshiftrt:V4SI
669	  (mult:V4SI (zero_extend:V4SI
670		      (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
671		     (zero_extend:V4SI
672		      (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
673	  (const_int 16))))]
674  "(TARGET_SSE || TARGET_3DNOW_A)
675   && ix86_binary_operator_ok (MULT, V4HImode, operands)"
676  "pmulhuw\t{%2, %0|%0, %2}"
677  [(set_attr "type" "mmxmul")
678   (set_attr "mode" "DI")])
679
680(define_insn "mmx_pmaddwd"
681  [(set (match_operand:V2SI 0 "register_operand" "=y")
682        (plus:V2SI
683	  (mult:V2SI
684	    (sign_extend:V2SI
685	      (vec_select:V2HI
686		(match_operand:V4HI 1 "nonimmediate_operand" "%0")
687		(parallel [(const_int 0) (const_int 2)])))
688	    (sign_extend:V2SI
689	      (vec_select:V2HI
690		(match_operand:V4HI 2 "nonimmediate_operand" "ym")
691		(parallel [(const_int 0) (const_int 2)]))))
692	  (mult:V2SI
693	    (sign_extend:V2SI
694	      (vec_select:V2HI (match_dup 1)
695		(parallel [(const_int 1) (const_int 3)])))
696	    (sign_extend:V2SI
697	      (vec_select:V2HI (match_dup 2)
698		(parallel [(const_int 1) (const_int 3)]))))))]
699  "TARGET_MMX && ix86_binary_operator_ok (MULT, V4HImode, operands)"
700  "pmaddwd\t{%2, %0|%0, %2}"
701  [(set_attr "type" "mmxmul")
702   (set_attr "mode" "DI")])
703
704(define_insn "mmx_pmulhrwv4hi3"
705  [(set (match_operand:V4HI 0 "register_operand" "=y")
706	(truncate:V4HI
707	  (lshiftrt:V4SI
708	    (plus:V4SI
709	      (mult:V4SI
710	        (sign_extend:V4SI
711		  (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
712	        (sign_extend:V4SI
713		  (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
714	      (const_vector:V4SI [(const_int 32768) (const_int 32768)
715				  (const_int 32768) (const_int 32768)]))
716	    (const_int 16))))]
717  "TARGET_3DNOW && ix86_binary_operator_ok (MULT, V4HImode, operands)"
718  "pmulhrw\\t{%2, %0|%0, %2}"
719  [(set_attr "type" "mmxmul")
720   (set_attr "mode" "DI")])
721
722(define_insn "sse2_umulsidi3"
723  [(set (match_operand:DI 0 "register_operand" "=y")
724        (mult:DI
725	  (zero_extend:DI
726	    (vec_select:SI
727	      (match_operand:V2SI 1 "nonimmediate_operand" "%0")
728	      (parallel [(const_int 0)])))
729	  (zero_extend:DI
730	    (vec_select:SI
731	      (match_operand:V2SI 2 "nonimmediate_operand" "ym")
732	      (parallel [(const_int 0)])))))]
733  "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V2SImode, operands)"
734  "pmuludq\t{%2, %0|%0, %2}"
735  [(set_attr "type" "mmxmul")
736   (set_attr "mode" "DI")])
737
738(define_insn "mmx_umaxv8qi3"
739  [(set (match_operand:V8QI 0 "register_operand" "=y")
740        (umax:V8QI (match_operand:V8QI 1 "nonimmediate_operand" "%0")
741		   (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
742  "(TARGET_SSE || TARGET_3DNOW_A)
743   && ix86_binary_operator_ok (UMAX, V8QImode, operands)"
744  "pmaxub\t{%2, %0|%0, %2}"
745  [(set_attr "type" "mmxadd")
746   (set_attr "mode" "DI")])
747
748(define_insn "mmx_smaxv4hi3"
749  [(set (match_operand:V4HI 0 "register_operand" "=y")
750        (smax:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0")
751		   (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
752  "(TARGET_SSE || TARGET_3DNOW_A)
753   && ix86_binary_operator_ok (SMAX, V4HImode, operands)"
754  "pmaxsw\t{%2, %0|%0, %2}"
755  [(set_attr "type" "mmxadd")
756   (set_attr "mode" "DI")])
757
758(define_insn "mmx_uminv8qi3"
759  [(set (match_operand:V8QI 0 "register_operand" "=y")
760        (umin:V8QI (match_operand:V8QI 1 "nonimmediate_operand" "%0")
761		   (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
762  "(TARGET_SSE || TARGET_3DNOW_A)
763   && ix86_binary_operator_ok (UMIN, V8QImode, operands)"
764  "pminub\t{%2, %0|%0, %2}"
765  [(set_attr "type" "mmxadd")
766   (set_attr "mode" "DI")])
767
768(define_insn "mmx_sminv4hi3"
769  [(set (match_operand:V4HI 0 "register_operand" "=y")
770        (smin:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0")
771		   (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
772  "(TARGET_SSE || TARGET_3DNOW_A)
773   && ix86_binary_operator_ok (SMIN, V4HImode, operands)"
774  "pminsw\t{%2, %0|%0, %2}"
775  [(set_attr "type" "mmxadd")
776   (set_attr "mode" "DI")])
777
778(define_insn "mmx_ashr<mode>3"
779  [(set (match_operand:MMXMODE24 0 "register_operand" "=y")
780        (ashiftrt:MMXMODE24
781	  (match_operand:MMXMODE24 1 "register_operand" "0")
782	  (match_operand:DI 2 "nonmemory_operand" "yi")))]
783  "TARGET_MMX"
784  "psra<mmxvecsize>\t{%2, %0|%0, %2}"
785  [(set_attr "type" "mmxshft")
786   (set_attr "mode" "DI")])
787
788(define_insn "mmx_lshr<mode>3"
789  [(set (match_operand:MMXMODE24 0 "register_operand" "=y")
790        (lshiftrt:MMXMODE24
791	  (match_operand:MMXMODE24 1 "register_operand" "0")
792	  (match_operand:DI 2 "nonmemory_operand" "yi")))]
793  "TARGET_MMX"
794  "psrl<mmxvecsize>\t{%2, %0|%0, %2}"
795  [(set_attr "type" "mmxshft")
796   (set_attr "mode" "DI")])
797
798(define_insn "mmx_lshrdi3"
799  [(set (match_operand:DI 0 "register_operand" "=y")
800        (unspec:DI
801	  [(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
802		       (match_operand:DI 2 "nonmemory_operand" "yi"))]
803	  UNSPEC_NOP))]
804  "TARGET_MMX"
805  "psrlq\t{%2, %0|%0, %2}"
806  [(set_attr "type" "mmxshft")
807   (set_attr "mode" "DI")])
808
809(define_insn "mmx_ashl<mode>3"
810  [(set (match_operand:MMXMODE24 0 "register_operand" "=y")
811        (ashift:MMXMODE24
812	  (match_operand:MMXMODE24 1 "register_operand" "0")
813	  (match_operand:DI 2 "nonmemory_operand" "yi")))]
814  "TARGET_MMX"
815  "psll<mmxvecsize>\t{%2, %0|%0, %2}"
816  [(set_attr "type" "mmxshft")
817   (set_attr "mode" "DI")])
818
819(define_insn "mmx_ashldi3"
820  [(set (match_operand:DI 0 "register_operand" "=y")
821        (unspec:DI
822	 [(ashift:DI (match_operand:DI 1 "register_operand" "0")
823		     (match_operand:DI 2 "nonmemory_operand" "yi"))]
824	 UNSPEC_NOP))]
825  "TARGET_MMX"
826  "psllq\t{%2, %0|%0, %2}"
827  [(set_attr "type" "mmxshft")
828   (set_attr "mode" "DI")])
829
830;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
831;;
832;; Parallel integral comparisons
833;;
834;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
835
836(define_insn "mmx_eq<mode>3"
837  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
838        (eq:MMXMODEI
839	  (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
840	  (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
841  "TARGET_MMX && ix86_binary_operator_ok (EQ, <MODE>mode, operands)"
842  "pcmpeq<mmxvecsize>\t{%2, %0|%0, %2}"
843  [(set_attr "type" "mmxcmp")
844   (set_attr "mode" "DI")])
845
846(define_insn "mmx_gt<mode>3"
847  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
848        (gt:MMXMODEI
849	  (match_operand:MMXMODEI 1 "register_operand" "0")
850	  (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
851  "TARGET_MMX"
852  "pcmpgt<mmxvecsize>\t{%2, %0|%0, %2}"
853  [(set_attr "type" "mmxcmp")
854   (set_attr "mode" "DI")])
855
856;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
857;;
858;; Parallel integral logical operations
859;;
860;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
861
862(define_insn "mmx_and<mode>3"
863  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
864	(and:MMXMODEI
865	  (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
866	  (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
867  "TARGET_MMX && ix86_binary_operator_ok (AND, <MODE>mode, operands)"
868  "pand\t{%2, %0|%0, %2}"
869  [(set_attr "type" "mmxadd")
870   (set_attr "mode" "DI")])
871
872(define_insn "mmx_nand<mode>3"
873  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
874	(and:MMXMODEI
875	  (not:MMXMODEI (match_operand:MMXMODEI 1 "register_operand" "0"))
876	  (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
877  "TARGET_MMX"
878  "pandn\t{%2, %0|%0, %2}"
879  [(set_attr "type" "mmxadd")
880   (set_attr "mode" "DI")])
881
882(define_insn "mmx_ior<mode>3"
883  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
884        (ior:MMXMODEI
885	  (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
886	  (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
887  "TARGET_MMX && ix86_binary_operator_ok (IOR, <MODE>mode, operands)"
888  "por\t{%2, %0|%0, %2}"
889  [(set_attr "type" "mmxadd")
890   (set_attr "mode" "DI")])
891
892(define_insn "mmx_xor<mode>3"
893  [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
894	(xor:MMXMODEI
895	  (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
896	  (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
897  "TARGET_MMX && ix86_binary_operator_ok (XOR, <MODE>mode, operands)"
898  "pxor\t{%2, %0|%0, %2}"
899  [(set_attr "type" "mmxadd")
900   (set_attr "mode" "DI")
901   (set_attr "memory" "none")])
902
903;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
904;;
905;; Parallel integral element swizzling
906;;
907;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
908
909(define_insn "mmx_packsswb"
910  [(set (match_operand:V8QI 0 "register_operand" "=y")
911	(vec_concat:V8QI
912	  (ss_truncate:V4QI
913	    (match_operand:V4HI 1 "register_operand" "0"))
914	  (ss_truncate:V4QI
915	    (match_operand:V4HI 2 "nonimmediate_operand" "ym"))))]
916  "TARGET_MMX"
917  "packsswb\t{%2, %0|%0, %2}"
918  [(set_attr "type" "mmxshft")
919   (set_attr "mode" "DI")])
920
921(define_insn "mmx_packssdw"
922  [(set (match_operand:V4HI 0 "register_operand" "=y")
923	(vec_concat:V4HI
924	  (ss_truncate:V2HI
925	    (match_operand:V2SI 1 "register_operand" "0"))
926	  (ss_truncate:V2HI
927	    (match_operand:V2SI 2 "nonimmediate_operand" "ym"))))]
928  "TARGET_MMX"
929  "packssdw\t{%2, %0|%0, %2}"
930  [(set_attr "type" "mmxshft")
931   (set_attr "mode" "DI")])
932
933(define_insn "mmx_packuswb"
934  [(set (match_operand:V8QI 0 "register_operand" "=y")
935	(vec_concat:V8QI
936	  (us_truncate:V4QI
937	    (match_operand:V4HI 1 "register_operand" "0"))
938	  (us_truncate:V4QI
939	    (match_operand:V4HI 2 "nonimmediate_operand" "ym"))))]
940  "TARGET_MMX"
941  "packuswb\t{%2, %0|%0, %2}"
942  [(set_attr "type" "mmxshft")
943   (set_attr "mode" "DI")])
944
945(define_insn "mmx_punpckhbw"
946  [(set (match_operand:V8QI 0 "register_operand" "=y")
947	(vec_select:V8QI
948	  (vec_concat:V16QI
949	    (match_operand:V8QI 1 "register_operand" "0")
950	    (match_operand:V8QI 2 "nonimmediate_operand" "ym"))
951          (parallel [(const_int 4) (const_int 12)
952                     (const_int 5) (const_int 13)
953                     (const_int 6) (const_int 14)
954                     (const_int 7) (const_int 15)])))]
955  "TARGET_MMX"
956  "punpckhbw\t{%2, %0|%0, %2}"
957  [(set_attr "type" "mmxcvt")
958   (set_attr "mode" "DI")])
959
960(define_insn "mmx_punpcklbw"
961  [(set (match_operand:V8QI 0 "register_operand" "=y")
962	(vec_select:V8QI
963	  (vec_concat:V16QI
964	    (match_operand:V8QI 1 "register_operand" "0")
965	    (match_operand:V8QI 2 "nonimmediate_operand" "ym"))
966          (parallel [(const_int 0) (const_int 8)
967                     (const_int 1) (const_int 9)
968                     (const_int 2) (const_int 10)
969                     (const_int 3) (const_int 11)])))]
970  "TARGET_MMX"
971  "punpcklbw\t{%2, %0|%0, %2}"
972  [(set_attr "type" "mmxcvt")
973   (set_attr "mode" "DI")])
974
975(define_insn "mmx_punpckhwd"
976  [(set (match_operand:V4HI 0 "register_operand" "=y")
977	(vec_select:V4HI
978	  (vec_concat:V8HI
979	    (match_operand:V4HI 1 "register_operand" "0")
980	    (match_operand:V4HI 2 "nonimmediate_operand" "ym"))
981          (parallel [(const_int 2) (const_int 6)
982                     (const_int 3) (const_int 7)])))]
983  "TARGET_MMX"
984  "punpckhwd\t{%2, %0|%0, %2}"
985  [(set_attr "type" "mmxcvt")
986   (set_attr "mode" "DI")])
987
988(define_insn "mmx_punpcklwd"
989  [(set (match_operand:V4HI 0 "register_operand" "=y")
990	(vec_select:V4HI
991	  (vec_concat:V8HI
992	    (match_operand:V4HI 1 "register_operand" "0")
993	    (match_operand:V4HI 2 "nonimmediate_operand" "ym"))
994          (parallel [(const_int 0) (const_int 4)
995                     (const_int 1) (const_int 5)])))]
996  "TARGET_MMX"
997  "punpcklwd\t{%2, %0|%0, %2}"
998  [(set_attr "type" "mmxcvt")
999   (set_attr "mode" "DI")])
1000
1001(define_insn "mmx_punpckhdq"
1002  [(set (match_operand:V2SI 0 "register_operand" "=y")
1003	(vec_select:V2SI
1004	  (vec_concat:V4SI
1005	    (match_operand:V2SI 1 "register_operand" "0")
1006	    (match_operand:V2SI 2 "nonimmediate_operand" "ym"))
1007	  (parallel [(const_int 1)
1008		     (const_int 3)])))]
1009  "TARGET_MMX"
1010  "punpckhdq\t{%2, %0|%0, %2}"
1011  [(set_attr "type" "mmxcvt")
1012   (set_attr "mode" "DI")])
1013
1014(define_insn "mmx_punpckldq"
1015  [(set (match_operand:V2SI 0 "register_operand" "=y")
1016	(vec_select:V2SI
1017	  (vec_concat:V4SI
1018	    (match_operand:V2SI 1 "register_operand" "0")
1019	    (match_operand:V2SI 2 "nonimmediate_operand" "ym"))
1020	  (parallel [(const_int 0)
1021		     (const_int 2)])))]
1022  "TARGET_MMX"
1023  "punpckldq\t{%2, %0|%0, %2}"
1024  [(set_attr "type" "mmxcvt")
1025   (set_attr "mode" "DI")])
1026
1027(define_expand "mmx_pinsrw"
1028  [(set (match_operand:V4HI 0 "register_operand" "")
1029        (vec_merge:V4HI
1030          (vec_duplicate:V4HI
1031            (match_operand:SI 2 "nonimmediate_operand" ""))
1032	  (match_operand:V4HI 1 "register_operand" "")
1033          (match_operand:SI 3 "const_0_to_3_operand" "")))]
1034  "TARGET_SSE || TARGET_3DNOW_A"
1035{
1036  operands[2] = gen_lowpart (HImode, operands[2]);
1037  operands[3] = GEN_INT (1 << INTVAL (operands[3]));
1038})
1039
1040(define_insn "*mmx_pinsrw"
1041  [(set (match_operand:V4HI 0 "register_operand" "=y")
1042        (vec_merge:V4HI
1043          (vec_duplicate:V4HI
1044            (match_operand:HI 2 "nonimmediate_operand" "rm"))
1045	  (match_operand:V4HI 1 "register_operand" "0")
1046          (match_operand:SI 3 "const_pow2_1_to_8_operand" "n")))]
1047  "TARGET_SSE || TARGET_3DNOW_A"
1048{
1049  operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])));
1050  return "pinsrw\t{%3, %k2, %0|%0, %k2, %3}";
1051}
1052  [(set_attr "type" "mmxcvt")
1053   (set_attr "mode" "DI")])
1054
1055(define_insn "mmx_pextrw"
1056  [(set (match_operand:SI 0 "register_operand" "=r")
1057        (zero_extend:SI
1058	  (vec_select:HI
1059	    (match_operand:V4HI 1 "register_operand" "y")
1060	    (parallel [(match_operand:SI 2 "const_0_to_3_operand" "n")]))))]
1061  "TARGET_SSE || TARGET_3DNOW_A"
1062  "pextrw\t{%2, %1, %0|%0, %1, %2}"
1063  [(set_attr "type" "mmxcvt")
1064   (set_attr "mode" "DI")])
1065
1066(define_expand "mmx_pshufw"
1067  [(match_operand:V4HI 0 "register_operand" "")
1068   (match_operand:V4HI 1 "nonimmediate_operand" "")
1069   (match_operand:SI 2 "const_int_operand" "")]
1070  "TARGET_SSE || TARGET_3DNOW_A"
1071{
1072  int mask = INTVAL (operands[2]);
1073  emit_insn (gen_mmx_pshufw_1 (operands[0], operands[1],
1074                               GEN_INT ((mask >> 0) & 3),
1075                               GEN_INT ((mask >> 2) & 3),
1076                               GEN_INT ((mask >> 4) & 3),
1077                               GEN_INT ((mask >> 6) & 3)));
1078  DONE;
1079})
1080
1081(define_insn "mmx_pshufw_1"
1082  [(set (match_operand:V4HI 0 "register_operand" "=y")
1083        (vec_select:V4HI
1084          (match_operand:V4HI 1 "nonimmediate_operand" "ym")
1085          (parallel [(match_operand 2 "const_0_to_3_operand" "")
1086                     (match_operand 3 "const_0_to_3_operand" "")
1087                     (match_operand 4 "const_0_to_3_operand" "")
1088                     (match_operand 5 "const_0_to_3_operand" "")])))]
1089  "TARGET_SSE || TARGET_3DNOW_A"
1090{
1091  int mask = 0;
1092  mask |= INTVAL (operands[2]) << 0;
1093  mask |= INTVAL (operands[3]) << 2;
1094  mask |= INTVAL (operands[4]) << 4;
1095  mask |= INTVAL (operands[5]) << 6;
1096  operands[2] = GEN_INT (mask);
1097
1098  return "pshufw\t{%2, %1, %0|%0, %1, %2}";
1099}
1100  [(set_attr "type" "mmxcvt")
1101   (set_attr "mode" "DI")])
1102
1103(define_insn "mmx_pswapdv2si2"
1104  [(set (match_operand:V2SI 0 "register_operand" "=y")
1105	(vec_select:V2SI
1106	  (match_operand:V2SI 1 "nonimmediate_operand" "ym")
1107	  (parallel [(const_int 1) (const_int 0)])))]
1108  "TARGET_3DNOW_A"
1109  "pswapd\\t{%1, %0|%0, %1}"
1110  [(set_attr "type" "mmxcvt")
1111   (set_attr "mode" "DI")])
1112
1113(define_insn "*vec_dupv4hi"
1114  [(set (match_operand:V4HI 0 "register_operand" "=y")
1115	(vec_duplicate:V4HI
1116	  (truncate:HI
1117	    (match_operand:SI 1 "register_operand" "0"))))]
1118  "TARGET_SSE || TARGET_3DNOW_A"
1119  "pshufw\t{$0, %0, %0|%0, %0, 0}"
1120  [(set_attr "type" "mmxcvt")
1121   (set_attr "mode" "DI")])
1122
1123(define_insn "*vec_dupv2si"
1124  [(set (match_operand:V2SI 0 "register_operand" "=y")
1125	(vec_duplicate:V2SI
1126	  (match_operand:SI 1 "register_operand" "0")))]
1127  "TARGET_MMX"
1128  "punpckldq\t%0, %0"
1129  [(set_attr "type" "mmxcvt")
1130   (set_attr "mode" "DI")])
1131
1132(define_insn "*mmx_concatv2si"
1133  [(set (match_operand:V2SI 0 "register_operand"     "=y,y")
1134	(vec_concat:V2SI
1135	  (match_operand:SI 1 "nonimmediate_operand" " 0,rm")
1136	  (match_operand:SI 2 "vector_move_operand"  "ym,C")))]
1137  "TARGET_MMX && !TARGET_SSE"
1138  "@
1139   punpckldq\t{%2, %0|%0, %2}
1140   movd\t{%1, %0|%0, %1}"
1141  [(set_attr "type" "mmxcvt,mmxmov")
1142   (set_attr "mode" "DI")])
1143
1144(define_expand "vec_setv2si"
1145  [(match_operand:V2SI 0 "register_operand" "")
1146   (match_operand:SI 1 "register_operand" "")
1147   (match_operand 2 "const_int_operand" "")]
1148  "TARGET_MMX"
1149{
1150  ix86_expand_vector_set (false, operands[0], operands[1],
1151			  INTVAL (operands[2]));
1152  DONE;
1153})
1154
1155(define_insn_and_split "*vec_extractv2si_0"
1156  [(set (match_operand:SI 0 "nonimmediate_operand"     "=x,y,m,m,frxy")
1157	(vec_select:SI
1158	  (match_operand:V2SI 1 "nonimmediate_operand" " x,y,x,y,m")
1159	  (parallel [(const_int 0)])))]
1160  "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
1161  "#"
1162  "&& reload_completed"
1163  [(const_int 0)]
1164{
1165  rtx op1 = operands[1];
1166  if (REG_P (op1))
1167    op1 = gen_rtx_REG (SImode, REGNO (op1));
1168  else
1169    op1 = gen_lowpart (SImode, op1);
1170  emit_move_insn (operands[0], op1);
1171  DONE;
1172})
1173
1174(define_insn "*vec_extractv2si_1"
1175  [(set (match_operand:SI 0 "nonimmediate_operand"     "=y,Y,Y,x,frxy")
1176	(vec_select:SI
1177	  (match_operand:V2SI 1 "nonimmediate_operand" " 0,0,Y,0,o")
1178	  (parallel [(const_int 1)])))]
1179  "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
1180  "@
1181   punpckhdq\t%0, %0
1182   punpckhdq\t%0, %0
1183   pshufd\t{$85, %1, %0|%0, %1, 85}
1184   unpckhps\t%0, %0
1185   #"
1186  [(set_attr "type" "mmxcvt,sselog1,sselog1,sselog1,*")
1187   (set_attr "mode" "DI,TI,TI,V4SF,SI")])
1188
1189(define_split
1190  [(set (match_operand:SI 0 "register_operand" "")
1191	(vec_select:SI
1192	  (match_operand:V2SI 1 "memory_operand" "")
1193	  (parallel [(const_int 1)])))]
1194  "TARGET_MMX && reload_completed"
1195  [(const_int 0)]
1196{
1197  operands[1] = adjust_address (operands[1], SImode, 4);
1198  emit_move_insn (operands[0], operands[1]);
1199  DONE;
1200})
1201
1202(define_expand "vec_extractv2si"
1203  [(match_operand:SI 0 "register_operand" "")
1204   (match_operand:V2SI 1 "register_operand" "")
1205   (match_operand 2 "const_int_operand" "")]
1206  "TARGET_MMX"
1207{
1208  ix86_expand_vector_extract (false, operands[0], operands[1],
1209			      INTVAL (operands[2]));
1210  DONE;
1211})
1212
1213(define_expand "vec_initv2si"
1214  [(match_operand:V2SI 0 "register_operand" "")
1215   (match_operand 1 "" "")]
1216  "TARGET_SSE"
1217{
1218  ix86_expand_vector_init (false, operands[0], operands[1]);
1219  DONE;
1220})
1221
1222(define_expand "vec_setv4hi"
1223  [(match_operand:V4HI 0 "register_operand" "")
1224   (match_operand:HI 1 "register_operand" "")
1225   (match_operand 2 "const_int_operand" "")]
1226  "TARGET_MMX"
1227{
1228  ix86_expand_vector_set (false, operands[0], operands[1],
1229			  INTVAL (operands[2]));
1230  DONE;
1231})
1232
1233(define_expand "vec_extractv4hi"
1234  [(match_operand:HI 0 "register_operand" "")
1235   (match_operand:V4HI 1 "register_operand" "")
1236   (match_operand 2 "const_int_operand" "")]
1237  "TARGET_MMX"
1238{
1239  ix86_expand_vector_extract (false, operands[0], operands[1],
1240			      INTVAL (operands[2]));
1241  DONE;
1242})
1243
1244(define_expand "vec_initv4hi"
1245  [(match_operand:V4HI 0 "register_operand" "")
1246   (match_operand 1 "" "")]
1247  "TARGET_SSE"
1248{
1249  ix86_expand_vector_init (false, operands[0], operands[1]);
1250  DONE;
1251})
1252
1253(define_expand "vec_setv8qi"
1254  [(match_operand:V8QI 0 "register_operand" "")
1255   (match_operand:QI 1 "register_operand" "")
1256   (match_operand 2 "const_int_operand" "")]
1257  "TARGET_MMX"
1258{
1259  ix86_expand_vector_set (false, operands[0], operands[1],
1260			  INTVAL (operands[2]));
1261  DONE;
1262})
1263
1264(define_expand "vec_extractv8qi"
1265  [(match_operand:QI 0 "register_operand" "")
1266   (match_operand:V8QI 1 "register_operand" "")
1267   (match_operand 2 "const_int_operand" "")]
1268  "TARGET_MMX"
1269{
1270  ix86_expand_vector_extract (false, operands[0], operands[1],
1271			      INTVAL (operands[2]));
1272  DONE;
1273})
1274
1275(define_expand "vec_initv8qi"
1276  [(match_operand:V8QI 0 "register_operand" "")
1277   (match_operand 1 "" "")]
1278  "TARGET_SSE"
1279{
1280  ix86_expand_vector_init (false, operands[0], operands[1]);
1281  DONE;
1282})
1283
1284;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1285;;
1286;; Miscellaneous
1287;;
1288;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1289
1290(define_insn "mmx_uavgv8qi3"
1291  [(set (match_operand:V8QI 0 "register_operand" "=y")
1292	(truncate:V8QI
1293	  (lshiftrt:V8HI
1294	    (plus:V8HI
1295	      (plus:V8HI
1296		(zero_extend:V8HI
1297		  (match_operand:V8QI 1 "nonimmediate_operand" "%0"))
1298		(zero_extend:V8HI
1299		  (match_operand:V8QI 2 "nonimmediate_operand" "ym")))
1300	      (const_vector:V8HI [(const_int 1) (const_int 1)
1301				  (const_int 1) (const_int 1)
1302				  (const_int 1) (const_int 1)
1303				  (const_int 1) (const_int 1)]))
1304	    (const_int 1))))]
1305  "(TARGET_SSE || TARGET_3DNOW)
1306   && ix86_binary_operator_ok (PLUS, V8QImode, operands)"
1307{
1308  /* These two instructions have the same operation, but their encoding
1309     is different.  Prefer the one that is de facto standard.  */
1310  if (TARGET_SSE || TARGET_3DNOW_A)
1311    return "pavgb\t{%2, %0|%0, %2}";
1312  else
1313    return "pavgusb\\t{%2, %0|%0, %2}";
1314}
1315  [(set_attr "type" "mmxshft")
1316   (set_attr "mode" "DI")])
1317
1318(define_insn "mmx_uavgv4hi3"
1319  [(set (match_operand:V4HI 0 "register_operand" "=y")
1320	(truncate:V4HI
1321	  (lshiftrt:V4SI
1322	    (plus:V4SI
1323	      (plus:V4SI
1324		(zero_extend:V4SI
1325		  (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
1326		(zero_extend:V4SI
1327		  (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
1328	      (const_vector:V4SI [(const_int 1) (const_int 1)
1329				  (const_int 1) (const_int 1)]))
1330	    (const_int 1))))]
1331  "(TARGET_SSE || TARGET_3DNOW_A)
1332   && ix86_binary_operator_ok (PLUS, V4HImode, operands)"
1333  "pavgw\t{%2, %0|%0, %2}"
1334  [(set_attr "type" "mmxshft")
1335   (set_attr "mode" "DI")])
1336
1337(define_insn "mmx_psadbw"
1338  [(set (match_operand:DI 0 "register_operand" "=y")
1339        (unspec:DI [(match_operand:V8QI 1 "register_operand" "0")
1340		    (match_operand:V8QI 2 "nonimmediate_operand" "ym")]
1341		   UNSPEC_PSADBW))]
1342  "TARGET_SSE || TARGET_3DNOW_A"
1343  "psadbw\t{%2, %0|%0, %2}"
1344  [(set_attr "type" "mmxshft")
1345   (set_attr "mode" "DI")])
1346
1347(define_insn "mmx_pmovmskb"
1348  [(set (match_operand:SI 0 "register_operand" "=r")
1349	(unspec:SI [(match_operand:V8QI 1 "register_operand" "y")]
1350		   UNSPEC_MOVMSK))]
1351  "TARGET_SSE || TARGET_3DNOW_A"
1352  "pmovmskb\t{%1, %0|%0, %1}"
1353  [(set_attr "type" "mmxcvt")
1354   (set_attr "mode" "DI")])
1355
1356(define_expand "mmx_maskmovq"
1357  [(set (match_operand:V8QI 0 "memory_operand" "")
1358	(unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
1359		      (match_operand:V8QI 2 "register_operand" "y")
1360		      (match_dup 0)]
1361		     UNSPEC_MASKMOV))]
1362  "TARGET_SSE || TARGET_3DNOW_A"
1363  "")
1364
1365(define_insn "*mmx_maskmovq"
1366  [(set (mem:V8QI (match_operand:SI 0 "register_operand" "D"))
1367	(unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
1368		      (match_operand:V8QI 2 "register_operand" "y")
1369		      (mem:V8QI (match_dup 0))]
1370		     UNSPEC_MASKMOV))]
1371  "(TARGET_SSE || TARGET_3DNOW_A) && !TARGET_64BIT"
1372  ;; @@@ check ordering of operands in intel/nonintel syntax
1373  "maskmovq\t{%2, %1|%1, %2}"
1374  [(set_attr "type" "mmxcvt")
1375   (set_attr "mode" "DI")])
1376
1377(define_insn "*mmx_maskmovq_rex"
1378  [(set (mem:V8QI (match_operand:DI 0 "register_operand" "D"))
1379	(unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
1380		      (match_operand:V8QI 2 "register_operand" "y")
1381		      (mem:V8QI (match_dup 0))]
1382		     UNSPEC_MASKMOV))]
1383  "(TARGET_SSE || TARGET_3DNOW_A) && TARGET_64BIT"
1384  ;; @@@ check ordering of operands in intel/nonintel syntax
1385  "maskmovq\t{%2, %1|%1, %2}"
1386  [(set_attr "type" "mmxcvt")
1387   (set_attr "mode" "DI")])
1388
1389(define_insn "mmx_emms"
1390  [(unspec_volatile [(const_int 0)] UNSPECV_EMMS)
1391   (clobber (reg:XF 8))
1392   (clobber (reg:XF 9))
1393   (clobber (reg:XF 10))
1394   (clobber (reg:XF 11))
1395   (clobber (reg:XF 12))
1396   (clobber (reg:XF 13))
1397   (clobber (reg:XF 14))
1398   (clobber (reg:XF 15))
1399   (clobber (reg:DI 29))
1400   (clobber (reg:DI 30))
1401   (clobber (reg:DI 31))
1402   (clobber (reg:DI 32))
1403   (clobber (reg:DI 33))
1404   (clobber (reg:DI 34))
1405   (clobber (reg:DI 35))
1406   (clobber (reg:DI 36))]
1407  "TARGET_MMX"
1408  "emms"
1409  [(set_attr "type" "mmx")
1410   (set_attr "memory" "unknown")])
1411
1412(define_insn "mmx_femms"
1413  [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS)
1414   (clobber (reg:XF 8))
1415   (clobber (reg:XF 9))
1416   (clobber (reg:XF 10))
1417   (clobber (reg:XF 11))
1418   (clobber (reg:XF 12))
1419   (clobber (reg:XF 13))
1420   (clobber (reg:XF 14))
1421   (clobber (reg:XF 15))
1422   (clobber (reg:DI 29))
1423   (clobber (reg:DI 30))
1424   (clobber (reg:DI 31))
1425   (clobber (reg:DI 32))
1426   (clobber (reg:DI 33))
1427   (clobber (reg:DI 34))
1428   (clobber (reg:DI 35))
1429   (clobber (reg:DI 36))]
1430  "TARGET_3DNOW"
1431  "femms"
1432  [(set_attr "type" "mmx")
1433   (set_attr "memory" "none")]) 
1434