]> gitweb.factorcode.org Git - factor.git/blob - basis/cpu/x86/sse/sse.factor
basis: removing unnecessary method stack effects.
[factor.git] / basis / cpu / x86 / sse / sse.factor
1 ! Copyright (C) 2009, 2010 Joe Groff, Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien.data arrays assocs combinators compiler.cfg.comparisons
4 compiler.cfg.intrinsics cpu.architecture cpu.x86 cpu.x86.assembler
5 cpu.x86.assembler.operands cpu.x86.features fry kernel locals macros
6 math math.vectors quotations sequences system ;
7 QUALIFIED-WITH: alien.c-types c
8 IN: cpu.x86.sse
9
10 ! Scalar floating point with SSE2
11 M: x86 %load-float c:float <ref> float-rep %load-vector ;
12 M: x86 %load-double c:double <ref> double-rep %load-vector ;
13
14 M: float-rep copy-register* drop MOVAPS ;
15 M: double-rep copy-register* drop MOVAPS ;
16
17 M: float-rep copy-memory* drop MOVSS ;
18 M: double-rep copy-memory* drop MOVSD ;
19
20 M: x86 %add-float double-rep two-operand ADDSD ;
21 M: x86 %sub-float double-rep two-operand SUBSD ;
22 M: x86 %mul-float double-rep two-operand MULSD ;
23 M: x86 %div-float double-rep two-operand DIVSD ;
24 M: x86 %min-float double-rep two-operand MINSD ;
25 M: x86 %max-float double-rep two-operand MAXSD ;
26 M: x86 %sqrt SQRTSD ;
27
28 : %clear-unless-in-place ( dst src -- )
29     over = [ drop ] [ dup XORPS ] if ;
30
31 M: x86 %single>double-float [ %clear-unless-in-place ] [ CVTSS2SD ] 2bi ;
32 M: x86 %double>single-float [ %clear-unless-in-place ] [ CVTSD2SS ] 2bi ;
33
34 M: x86 integer-float-needs-stack-frame? f ;
35 M: x86 %integer>float [ drop dup XORPS ] [ CVTSI2SD ] 2bi ;
36 M: x86 %float>integer CVTTSD2SI ;
37
38 M: x86 %compare-float-ordered
39     [ COMISD ] (%compare-float) ;
40
41 M: x86 %compare-float-unordered
42     [ UCOMISD ] (%compare-float) ;
43
44 M: x86 %compare-float-ordered-branch
45     [ COMISD ] (%compare-float-branch) ;
46
47 M: x86 %compare-float-unordered-branch
48     [ UCOMISD ] (%compare-float-branch) ;
49
50 ! SIMD
51 M: float-4-rep copy-register* drop MOVAPS ;
52 M: double-2-rep copy-register* drop MOVAPS ;
53 M: vector-rep copy-register* drop MOVDQA ;
54
55 MACRO: available-reps ( alist -- quot )
56     ! Each SSE version adds new representations and supports
57     ! all old ones
58     unzip { } [ append ] accumulate*
59     [ [ 1quotation ] map ] bi@ zip
60     reverse [ { } ] suffix
61     '[ _ cond ] ;
62
63 M: x86 %alien-vector-reps
64     {
65         { sse? { float-4-rep } }
66         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
67     } available-reps ;
68
69 M: x86 %zero-vector
70     {
71         { double-2-rep [ dup XORPS ] }
72         { float-4-rep [ dup XORPS ] }
73         [ drop dup PXOR ]
74     } case ;
75
76 M: x86 %zero-vector-reps
77     {
78         { sse? { float-4-rep } }
79         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
80     } available-reps ;
81
82 M: x86 %fill-vector
83     {
84         { double-2-rep [ dup [ XORPS ] [ CMPEQPS ] 2bi ] }
85         { float-4-rep  [ dup [ XORPS ] [ CMPEQPS ] 2bi ] }
86         [ drop dup PCMPEQB ]
87     } case ;
88
89 M: x86 %fill-vector-reps
90     {
91         { sse? { float-4-rep } }
92         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
93     } available-reps ;
94
95 M:: x86 %gather-vector-4 ( dst src1 src2 src3 src4 rep -- )
96     rep signed-rep {
97         { float-4-rep [
98             dst src1 float-4-rep %copy
99             dst src2 UNPCKLPS
100             src3 src4 UNPCKLPS
101             dst src3 MOVLHPS
102         ] }
103         { int-4-rep [
104             dst src1 int-4-rep %copy
105             dst src2 PUNPCKLDQ
106             src3 src4 PUNPCKLDQ
107             dst src3 PUNPCKLQDQ
108         ] }
109     } case ;
110
111 M: x86 %gather-vector-4-reps
112     {
113         ! Can't do this with sse1 since it will want to unbox
114         ! double-precision floats and convert to single precision
115         { sse2? { float-4-rep int-4-rep uint-4-rep } }
116     } available-reps ;
117
118 M:: x86 %gather-int-vector-4 ( dst src1 src2 src3 src4 rep -- )
119     dst rep %zero-vector
120     dst src1 32-bit-version-of 0 PINSRD
121     dst src2 32-bit-version-of 1 PINSRD
122     dst src3 32-bit-version-of 2 PINSRD
123     dst src4 32-bit-version-of 3 PINSRD ;
124
125 M: x86 %gather-int-vector-4-reps
126     {
127         { sse4.1? { int-4-rep uint-4-rep } }
128     } available-reps ;
129
130 M:: x86 %gather-vector-2 ( dst src1 src2 rep -- )
131     rep signed-rep {
132         { double-2-rep [
133             dst src1 double-2-rep %copy
134             dst src2 MOVLHPS
135         ] }
136         { longlong-2-rep [
137             dst src1 longlong-2-rep %copy
138             dst src2 PUNPCKLQDQ
139         ] }
140     } case ;
141
142 M: x86 %gather-vector-2-reps
143     {
144         { sse2? { double-2-rep longlong-2-rep ulonglong-2-rep } }
145     } available-reps ;
146
147 M:: x86.64 %gather-int-vector-2 ( dst src1 src2 rep -- )
148     dst rep %zero-vector
149     dst src1 0 PINSRQ
150     dst src2 1 PINSRQ ;
151
152 M: x86.64 %gather-int-vector-2-reps
153     {
154         { sse4.1? { longlong-2-rep ulonglong-2-rep } }
155     } available-reps ;
156
157 :: %select-vector-32 ( dst src n rep -- )
158     rep {
159         { char-16-rep [
160             dst 32-bit-version-of src n PEXTRB
161             dst dst 8-bit-version-of MOVSX
162         ] }
163         { uchar-16-rep [
164             dst 32-bit-version-of src n PEXTRB
165         ] }
166         { short-8-rep [
167             dst 32-bit-version-of src n PEXTRW
168             dst dst 16-bit-version-of MOVSX
169         ] }
170         { ushort-8-rep [
171             dst 32-bit-version-of src n PEXTRW
172         ] }
173         { int-4-rep [
174             dst 32-bit-version-of src n PEXTRD
175             dst dst 32-bit-version-of 2dup = [ 2drop ] [ MOVSX ] if
176         ] }
177         { uint-4-rep [
178             dst 32-bit-version-of src n PEXTRD
179         ] }
180     } case ;
181
182 M: x86.32 %select-vector
183     %select-vector-32 ;
184
185 M: x86.32 %select-vector-reps
186     {
187         { sse4.1? { uchar-16-rep char-16-rep ushort-8-rep short-8-rep uint-4-rep int-4-rep } }
188     } available-reps ;
189
190 M: x86.64 %select-vector
191     {
192         { longlong-2-rep  [ PEXTRQ ] }
193         { ulonglong-2-rep [ PEXTRQ ] }
194         [ %select-vector-32 ]
195     } case ;
196
197 M: x86.64 %select-vector-reps
198     {
199         { sse4.1? { uchar-16-rep char-16-rep ushort-8-rep short-8-rep uint-4-rep int-4-rep ulonglong-2-rep longlong-2-rep } }
200     } available-reps ;
201
202 : sse1-float-4-shuffle ( dst shuffle -- )
203     {
204         { { 0 1 2 3 } [ drop ] }
205         { { 0 1 0 1 } [ dup MOVLHPS ] }
206         { { 2 3 2 3 } [ dup MOVHLPS ] }
207         { { 0 0 1 1 } [ dup UNPCKLPS ] }
208         { { 2 2 3 3 } [ dup UNPCKHPS ] }
209         [ dupd SHUFPS ]
210     } case ;
211
212 : float-4-shuffle ( dst shuffle -- )
213     sse3? [
214         {
215             { { 0 0 2 2 } [ dup MOVSLDUP ] }
216             { { 1 1 3 3 } [ dup MOVSHDUP ] }
217             [ sse1-float-4-shuffle ]
218         } case
219     ] [ sse1-float-4-shuffle ] if ;
220
221 : int-4-shuffle ( dst shuffle -- )
222     {
223         { { 0 1 2 3 } [ drop ] }
224         { { 0 0 1 1 } [ dup PUNPCKLDQ ] }
225         { { 2 2 3 3 } [ dup PUNPCKHDQ ] }
226         { { 0 1 0 1 } [ dup PUNPCKLQDQ ] }
227         { { 2 3 2 3 } [ dup PUNPCKHQDQ ] }
228         [ dupd PSHUFD ]
229     } case ;
230
231 : longlong-2-shuffle ( dst shuffle -- )
232     first2 [ 2 * dup 1 + ] bi@ 4array int-4-shuffle ;
233
234 : >float-4-shuffle ( double-2-shuffle -- float-4-shuffle )
235     [ 2 * { 0 1 } n+v ] map concat ;
236
237 M:: x86 %shuffle-vector-imm ( dst src shuffle rep -- )
238     dst src rep %copy
239     dst shuffle rep signed-rep {
240         { double-2-rep [ >float-4-shuffle float-4-shuffle ] }
241         { float-4-rep [ float-4-shuffle ] }
242         { int-4-rep [ int-4-shuffle ] }
243         { longlong-2-rep [ longlong-2-shuffle ] }
244     } case ;
245
246 M: x86 %shuffle-vector-imm-reps
247     {
248         { sse? { float-4-rep } }
249         { sse2? { double-2-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
250     } available-reps ;
251
252 M:: x86 %shuffle-vector-halves-imm ( dst src1 src2 shuffle rep -- )
253     dst src1 src2 rep two-operand
254     shuffle rep {
255         { double-2-rep [ >float-4-shuffle SHUFPS ] }
256         { float-4-rep [ SHUFPS ] }
257     } case ;
258
259 M: x86 %shuffle-vector-halves-imm-reps
260     {
261         { sse? { float-4-rep } }
262         { sse2? { double-2-rep } }
263     } available-reps ;
264
265 M: x86 %shuffle-vector
266     two-operand PSHUFB ;
267
268 M: x86 %shuffle-vector-reps
269     {
270         { ssse3? { float-4-rep double-2-rep longlong-2-rep ulonglong-2-rep int-4-rep uint-4-rep short-8-rep ushort-8-rep char-16-rep uchar-16-rep } }
271     } available-reps ;
272
273 M: x86 %merge-vector-head
274     [ two-operand ] keep
275     signed-rep {
276         { double-2-rep   [ MOVLHPS ] }
277         { float-4-rep    [ UNPCKLPS ] }
278         { longlong-2-rep [ PUNPCKLQDQ ] }
279         { int-4-rep      [ PUNPCKLDQ ] }
280         { short-8-rep    [ PUNPCKLWD ] }
281         { char-16-rep    [ PUNPCKLBW ] }
282     } case ;
283
284 M: x86 %merge-vector-tail
285     [ two-operand ] keep
286     signed-rep {
287         { double-2-rep   [ UNPCKHPD ] }
288         { float-4-rep    [ UNPCKHPS ] }
289         { longlong-2-rep [ PUNPCKHQDQ ] }
290         { int-4-rep      [ PUNPCKHDQ ] }
291         { short-8-rep    [ PUNPCKHWD ] }
292         { char-16-rep    [ PUNPCKHBW ] }
293     } case ;
294
295 M: x86 %merge-vector-reps
296     {
297         { sse? { float-4-rep } }
298         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
299     } available-reps ;
300
301 M: x86 %float-pack-vector
302     drop CVTPD2PS ;
303
304 M: x86 %float-pack-vector-reps
305     {
306         { sse2? { double-2-rep } }
307     } available-reps ;
308
309 M: x86 %signed-pack-vector
310     [ two-operand ] keep
311     {
312         { int-4-rep    [ PACKSSDW ] }
313         { short-8-rep  [ PACKSSWB ] }
314     } case ;
315
316 M: x86 %signed-pack-vector-reps
317     {
318         { sse2? { short-8-rep int-4-rep } }
319     } available-reps ;
320
321 M: x86 %unsigned-pack-vector
322     [ two-operand ] keep
323     signed-rep {
324         { int-4-rep   [ PACKUSDW ] }
325         { short-8-rep [ PACKUSWB ] }
326     } case ;
327
328 M: x86 %unsigned-pack-vector-reps
329     {
330         { sse2? { short-8-rep } }
331         { sse4.1? { int-4-rep } }
332     } available-reps ;
333
334 M: x86 %tail>head-vector
335     dup {
336         { float-4-rep [ drop UNPCKHPD ] }
337         { double-2-rep [ drop UNPCKHPD ] }
338         [ drop [ %copy ] [ drop PUNPCKHQDQ ] 3bi ]
339     } case ;
340
341 M: x86 %unpack-vector-head
342     {
343         { char-16-rep  [ PMOVSXBW ] }
344         { uchar-16-rep [ PMOVZXBW ] }
345         { short-8-rep  [ PMOVSXWD ] }
346         { ushort-8-rep [ PMOVZXWD ] }
347         { int-4-rep    [ PMOVSXDQ ] }
348         { uint-4-rep   [ PMOVZXDQ ] }
349         { float-4-rep  [ CVTPS2PD ] }
350     } case ;
351
352 M: x86 %unpack-vector-head-reps
353     {
354         { sse2? { float-4-rep } }
355         { sse4.1? { char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep } }
356     } available-reps ;
357
358 M: x86 %integer>float-vector
359     {
360         { int-4-rep [ CVTDQ2PS ] }
361     } case ;
362
363 M: x86 %integer>float-vector-reps
364     {
365         { sse2? { int-4-rep } }
366     } available-reps ;
367
368 M: x86 %float>integer-vector
369     {
370         { float-4-rep [ CVTTPS2DQ ] }
371     } case ;
372
373 M: x86 %float>integer-vector-reps
374     {
375         { sse2? { float-4-rep } }
376     } available-reps ;
377
378 : (%compare-float-vector) ( dst src rep double single -- )
379     [ double-2-rep eq? ] 2dip if ; inline
380
381 : %compare-float-vector ( dst src rep cc -- )
382     {
383         { cc<    [ [ CMPLTPD    ] [ CMPLTPS    ] (%compare-float-vector) ] }
384         { cc<=   [ [ CMPLEPD    ] [ CMPLEPS    ] (%compare-float-vector) ] }
385         { cc=    [ [ CMPEQPD    ] [ CMPEQPS    ] (%compare-float-vector) ] }
386         { cc<>=  [ [ CMPORDPD   ] [ CMPORDPS   ] (%compare-float-vector) ] }
387         { cc/<   [ [ CMPNLTPD   ] [ CMPNLTPS   ] (%compare-float-vector) ] }
388         { cc/<=  [ [ CMPNLEPD   ] [ CMPNLEPS   ] (%compare-float-vector) ] }
389         { cc/=   [ [ CMPNEQPD   ] [ CMPNEQPS   ] (%compare-float-vector) ] }
390         { cc/<>= [ [ CMPUNORDPD ] [ CMPUNORDPS ] (%compare-float-vector) ] }
391     } case ;
392
393 :: (%compare-int-vector) ( dst src rep int64 int32 int16 int8 -- )
394     rep signed-rep :> rep'
395     dst src rep' {
396         { longlong-2-rep [ int64 call ] }
397         { int-4-rep      [ int32 call ] }
398         { short-8-rep    [ int16 call ] }
399         { char-16-rep    [ int8  call ] }
400     } case ; inline
401
402 : %compare-int-vector ( dst src rep cc -- )
403     {
404         { cc= [ [ PCMPEQQ ] [ PCMPEQD ] [ PCMPEQW ] [ PCMPEQB ] (%compare-int-vector) ] }
405         { cc> [ [ PCMPGTQ ] [ PCMPGTD ] [ PCMPGTW ] [ PCMPGTB ] (%compare-int-vector) ] }
406     } case ;
407
408 M: x86 %compare-vector
409     [ [ two-operand ] keep ] dip
410     over float-vector-rep?
411     [ %compare-float-vector ]
412     [ %compare-int-vector ] if ;
413
414 : %compare-vector-eq-reps ( -- reps )
415     {
416         { sse? { float-4-rep } }
417         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep } }
418         { sse4.1? { longlong-2-rep ulonglong-2-rep } }
419     } available-reps ;
420
421 : %compare-vector-ord-reps ( -- reps )
422     {
423         { sse? { float-4-rep } }
424         { sse2? { double-2-rep char-16-rep short-8-rep int-4-rep } }
425         { sse4.2? { longlong-2-rep } }
426     } available-reps ;
427
428 M: x86 %compare-vector-reps
429     {
430         { [ dup { cc= cc/= cc/<>= cc<>= } member-eq? ] [ drop %compare-vector-eq-reps ] }
431         [ drop %compare-vector-ord-reps ]
432     } cond ;
433
434 : %compare-float-vector-ccs ( cc -- ccs not? )
435     {
436         { cc<    [ { { cc<  f   }              } f ] }
437         { cc<=   [ { { cc<= f   }              } f ] }
438         { cc>    [ { { cc<  t   }              } f ] }
439         { cc>=   [ { { cc<= t   }              } f ] }
440         { cc=    [ { { cc=  f   }              } f ] }
441         { cc<>   [ { { cc<  f   } { cc<    t } } f ] }
442         { cc<>=  [ { { cc<>= f  }              } f ] }
443         { cc/<   [ { { cc/<  f  }              } f ] }
444         { cc/<=  [ { { cc/<= f  }              } f ] }
445         { cc/>   [ { { cc/<  t  }              } f ] }
446         { cc/>=  [ { { cc/<= t  }              } f ] }
447         { cc/=   [ { { cc/=  f  }              } f ] }
448         { cc/<>  [ { { cc/=  f  } { cc/<>= f } } f ] }
449         { cc/<>= [ { { cc/<>= f }              } f ] }
450     } case ;
451
452 : %compare-int-vector-ccs ( cc -- ccs not? )
453     order-cc {
454         { cc<    [ { { cc> t } } f ] }
455         { cc<=   [ { { cc> f } } t ] }
456         { cc>    [ { { cc> f } } f ] }
457         { cc>=   [ { { cc> t } } t ] }
458         { cc=    [ { { cc= f } } f ] }
459         { cc/=   [ { { cc= f } } t ] }
460         { t      [ {           } t ] }
461         { f      [ {           } f ] }
462     } case ;
463
464 M: x86 %compare-vector-ccs
465     swap float-vector-rep?
466     [ %compare-float-vector-ccs ]
467     [ %compare-int-vector-ccs ] if ;
468
469 :: %test-vector-mask ( dst temp mask vcc -- )
470     vcc {
471         { vcc-any    [ dst dst TEST dst temp \ CMOVNE (%boolean) ] }
472         { vcc-none   [ dst dst TEST dst temp \ CMOVE  (%boolean) ] }
473         { vcc-all    [ dst mask CMP dst temp \ CMOVE  (%boolean) ] }
474         { vcc-notall [ dst mask CMP dst temp \ CMOVNE (%boolean) ] }
475     } case ;
476
477 : (%move-vector-mask) ( dst src rep -- mask )
478     {
479         { double-2-rep [ MOVMSKPS 0xf ] }
480         { float-4-rep  [ MOVMSKPS 0xf ] }
481         [ drop PMOVMSKB 0xffff ]
482     } case ;
483
484 M: x86 %move-vector-mask
485     (%move-vector-mask) drop ;
486
487 M: x86 %move-vector-mask-reps
488     {
489         { sse? { float-4-rep } }
490         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
491     } available-reps ;
492
493 M:: x86 %test-vector ( dst src temp rep vcc -- )
494     dst src rep (%move-vector-mask) :> mask
495     dst temp mask vcc %test-vector-mask ;
496
497 :: %test-vector-mask-branch ( label temp mask vcc -- )
498     vcc {
499         { vcc-any    [ temp temp TEST label JNE ] }
500         { vcc-none   [ temp temp TEST label JE ] }
501         { vcc-all    [ temp mask CMP label JE ] }
502         { vcc-notall [ temp mask CMP label JNE ] }
503     } case ;
504
505 M:: x86 %test-vector-branch ( label src temp rep vcc -- )
506     temp src rep (%move-vector-mask) :> mask
507     label temp mask vcc %test-vector-mask-branch ;
508
509 M: x86 %test-vector-reps
510     {
511         { sse? { float-4-rep } }
512         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
513     } available-reps ;
514
515 M: x86 %add-vector
516     [ two-operand ] keep
517     {
518         { float-4-rep [ ADDPS ] }
519         { double-2-rep [ ADDPD ] }
520         { char-16-rep [ PADDB ] }
521         { uchar-16-rep [ PADDB ] }
522         { short-8-rep [ PADDW ] }
523         { ushort-8-rep [ PADDW ] }
524         { int-4-rep [ PADDD ] }
525         { uint-4-rep [ PADDD ] }
526         { longlong-2-rep [ PADDQ ] }
527         { ulonglong-2-rep [ PADDQ ] }
528     } case ;
529
530 M: x86 %add-vector-reps
531     {
532         { sse? { float-4-rep } }
533         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
534     } available-reps ;
535
536 M: x86 %saturated-add-vector
537     [ two-operand ] keep
538     {
539         { char-16-rep [ PADDSB ] }
540         { uchar-16-rep [ PADDUSB ] }
541         { short-8-rep [ PADDSW ] }
542         { ushort-8-rep [ PADDUSW ] }
543     } case ;
544
545 M: x86 %saturated-add-vector-reps
546     {
547         { sse2? { char-16-rep uchar-16-rep short-8-rep ushort-8-rep } }
548     } available-reps ;
549
550 M: x86 %add-sub-vector
551     [ two-operand ] keep
552     {
553         { float-4-rep [ ADDSUBPS ] }
554         { double-2-rep [ ADDSUBPD ] }
555     } case ;
556
557 M: x86 %add-sub-vector-reps
558     {
559         { sse3? { float-4-rep double-2-rep } }
560     } available-reps ;
561
562 M: x86 %sub-vector
563     [ two-operand ] keep
564     {
565         { float-4-rep [ SUBPS ] }
566         { double-2-rep [ SUBPD ] }
567         { char-16-rep [ PSUBB ] }
568         { uchar-16-rep [ PSUBB ] }
569         { short-8-rep [ PSUBW ] }
570         { ushort-8-rep [ PSUBW ] }
571         { int-4-rep [ PSUBD ] }
572         { uint-4-rep [ PSUBD ] }
573         { longlong-2-rep [ PSUBQ ] }
574         { ulonglong-2-rep [ PSUBQ ] }
575     } case ;
576
577 M: x86 %sub-vector-reps
578     {
579         { sse? { float-4-rep } }
580         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
581     } available-reps ;
582
583 M: x86 %saturated-sub-vector
584     [ two-operand ] keep
585     {
586         { char-16-rep [ PSUBSB ] }
587         { uchar-16-rep [ PSUBUSB ] }
588         { short-8-rep [ PSUBSW ] }
589         { ushort-8-rep [ PSUBUSW ] }
590     } case ;
591
592 M: x86 %saturated-sub-vector-reps
593     {
594         { sse2? { char-16-rep uchar-16-rep short-8-rep ushort-8-rep } }
595     } available-reps ;
596
597 M: x86 %mul-vector
598     [ two-operand ] keep
599     {
600         { float-4-rep [ MULPS ] }
601         { double-2-rep [ MULPD ] }
602         { short-8-rep [ PMULLW ] }
603         { ushort-8-rep [ PMULLW ] }
604         { int-4-rep [ PMULLD ] }
605         { uint-4-rep [ PMULLD ] }
606     } case ;
607
608 M: x86 %mul-vector-reps
609     {
610         { sse? { float-4-rep } }
611         { sse2? { double-2-rep short-8-rep ushort-8-rep } }
612         { sse4.1? { int-4-rep uint-4-rep } }
613     } available-reps ;
614
615 M: x86 %mul-high-vector
616     [ two-operand ] keep
617     {
618         { short-8-rep  [ PMULHW ] }
619         { ushort-8-rep [ PMULHUW ] }
620     } case ;
621
622 M: x86 %mul-high-vector-reps
623     {
624         { sse2? { short-8-rep ushort-8-rep } }
625     } available-reps ;
626
627 M: x86 %mul-horizontal-add-vector
628     [ two-operand ] keep
629     {
630         { char-16-rep  [ PMADDUBSW ] }
631         { uchar-16-rep [ PMADDUBSW ] }
632         { short-8-rep  [ PMADDWD ] }
633     } case ;
634
635 M: x86 %mul-horizontal-add-vector-reps
636     {
637         { sse2?  { short-8-rep } }
638         { ssse3? { char-16-rep uchar-16-rep } }
639     } available-reps ;
640
641 M: x86 %div-vector
642     [ two-operand ] keep
643     {
644         { float-4-rep [ DIVPS ] }
645         { double-2-rep [ DIVPD ] }
646     } case ;
647
648 M: x86 %div-vector-reps
649     {
650         { sse? { float-4-rep } }
651         { sse2? { double-2-rep } }
652     } available-reps ;
653
654 M: x86 %min-vector
655     [ two-operand ] keep
656     {
657         { char-16-rep [ PMINSB ] }
658         { uchar-16-rep [ PMINUB ] }
659         { short-8-rep [ PMINSW ] }
660         { ushort-8-rep [ PMINUW ] }
661         { int-4-rep [ PMINSD ] }
662         { uint-4-rep [ PMINUD ] }
663         { float-4-rep [ MINPS ] }
664         { double-2-rep [ MINPD ] }
665     } case ;
666
667 M: x86 %min-vector-reps
668     {
669         { sse? { float-4-rep } }
670         { sse2? { uchar-16-rep short-8-rep double-2-rep } }
671         { sse4.1? { char-16-rep ushort-8-rep int-4-rep uint-4-rep } }
672     } available-reps ;
673
674 M: x86 %max-vector
675     [ two-operand ] keep
676     {
677         { char-16-rep [ PMAXSB ] }
678         { uchar-16-rep [ PMAXUB ] }
679         { short-8-rep [ PMAXSW ] }
680         { ushort-8-rep [ PMAXUW ] }
681         { int-4-rep [ PMAXSD ] }
682         { uint-4-rep [ PMAXUD ] }
683         { float-4-rep [ MAXPS ] }
684         { double-2-rep [ MAXPD ] }
685     } case ;
686
687 M: x86 %max-vector-reps
688     {
689         { sse? { float-4-rep } }
690         { sse2? { uchar-16-rep short-8-rep double-2-rep } }
691         { sse4.1? { char-16-rep ushort-8-rep int-4-rep uint-4-rep } }
692     } available-reps ;
693
694 M: x86 %avg-vector
695     [ two-operand ] keep
696     {
697         { uchar-16-rep [ PAVGB ] }
698         { ushort-8-rep [ PAVGW ] }
699     } case ;
700
701 M: x86 %avg-vector-reps
702     {
703         { sse2? { uchar-16-rep ushort-8-rep } }
704     } available-reps ;
705
706 M: x86 %dot-vector
707     [ two-operand ] keep
708     {
709         { float-4-rep [ 0xff DPPS ] }
710         { double-2-rep [ 0xff DPPD ] }
711     } case ;
712
713 M: x86 %dot-vector-reps
714     {
715         { sse4.1? { float-4-rep double-2-rep } }
716     } available-reps ;
717
718 M: x86 %sad-vector
719     [ two-operand ] keep
720     {
721         { uchar-16-rep [ PSADBW ] }
722     } case ;
723
724 M: x86 %sad-vector-reps
725     {
726         { sse2? { uchar-16-rep } }
727     } available-reps ;
728
729 M: x86 %horizontal-add-vector
730     [ two-operand ] keep
731     signed-rep {
732         { float-4-rep  [ HADDPS ] }
733         { double-2-rep [ HADDPD ] }
734         { int-4-rep    [ PHADDD ] }
735         { short-8-rep  [ PHADDW ] }
736     } case ;
737
738 M: x86 %horizontal-add-vector-reps
739     {
740         { sse3? { float-4-rep double-2-rep } }
741         { ssse3? { int-4-rep uint-4-rep short-8-rep ushort-8-rep } }
742     } available-reps ;
743
744 M: x86 %horizontal-shl-vector-imm
745     two-operand PSLLDQ ;
746
747 M: x86 %horizontal-shl-vector-imm-reps
748     {
749         { sse2? { char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep float-4-rep double-2-rep } }
750     } available-reps ;
751
752 M: x86 %horizontal-shr-vector-imm
753     two-operand PSRLDQ ;
754
755 M: x86 %horizontal-shr-vector-imm-reps
756     {
757         { sse2? { char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep float-4-rep double-2-rep } }
758     } available-reps ;
759
760 M: x86 %abs-vector
761     {
762         { char-16-rep [ PABSB ] }
763         { short-8-rep [ PABSW ] }
764         { int-4-rep [ PABSD ] }
765     } case ;
766
767 M: x86 %abs-vector-reps
768     {
769         { ssse3? { char-16-rep short-8-rep int-4-rep } }
770     } available-reps ;
771
772 M: x86 %sqrt-vector
773     {
774         { float-4-rep [ SQRTPS ] }
775         { double-2-rep [ SQRTPD ] }
776     } case ;
777
778 M: x86 %sqrt-vector-reps
779     {
780         { sse? { float-4-rep } }
781         { sse2? { double-2-rep } }
782     } available-reps ;
783
784 M: x86 %and-vector
785     [ two-operand ] keep
786     {
787         { float-4-rep [ ANDPS ] }
788         { double-2-rep [ ANDPS ] }
789         [ drop PAND ]
790     } case ;
791
792 M: x86 %and-vector-reps
793     {
794         { sse? { float-4-rep } }
795         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
796     } available-reps ;
797
798 M: x86 %andn-vector
799     [ two-operand ] keep
800     {
801         { float-4-rep [ ANDNPS ] }
802         { double-2-rep [ ANDNPS ] }
803         [ drop PANDN ]
804     } case ;
805
806 M: x86 %andn-vector-reps
807     {
808         { sse? { float-4-rep } }
809         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
810     } available-reps ;
811
812 M: x86 %or-vector
813     [ two-operand ] keep
814     {
815         { float-4-rep [ ORPS ] }
816         { double-2-rep [ ORPS ] }
817         [ drop POR ]
818     } case ;
819
820 M: x86 %or-vector-reps
821     {
822         { sse? { float-4-rep } }
823         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
824     } available-reps ;
825
826 M: x86 %xor-vector
827     [ two-operand ] keep
828     {
829         { float-4-rep [ XORPS ] }
830         { double-2-rep [ XORPS ] }
831         [ drop PXOR ]
832     } case ;
833
834 M: x86 %xor-vector-reps
835     {
836         { sse? { float-4-rep } }
837         { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
838     } available-reps ;
839
840 M: x86 %shl-vector
841     [ two-operand ] keep
842     {
843         { short-8-rep [ PSLLW ] }
844         { ushort-8-rep [ PSLLW ] }
845         { int-4-rep [ PSLLD ] }
846         { uint-4-rep [ PSLLD ] }
847         { longlong-2-rep [ PSLLQ ] }
848         { ulonglong-2-rep [ PSLLQ ] }
849     } case ;
850
851 M: x86 %shl-vector-reps
852     {
853         { sse2? { short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
854     } available-reps ;
855
856 M: x86 %shr-vector
857     [ two-operand ] keep
858     {
859         { short-8-rep [ PSRAW ] }
860         { ushort-8-rep [ PSRLW ] }
861         { int-4-rep [ PSRAD ] }
862         { uint-4-rep [ PSRLD ] }
863         { ulonglong-2-rep [ PSRLQ ] }
864     } case ;
865
866 M: x86 %shr-vector-reps
867     {
868         { sse2? { short-8-rep ushort-8-rep int-4-rep uint-4-rep ulonglong-2-rep } }
869     } available-reps ;
870
871 M: x86 %shl-vector-imm %shl-vector ;
872 M: x86 %shl-vector-imm-reps %shl-vector-reps ;
873 M: x86 %shr-vector-imm %shr-vector ;
874 M: x86 %shr-vector-imm-reps %shr-vector-reps ;
875
876 M: x86 %integer>scalar drop MOVD ;
877
878 :: %scalar>integer-32 ( dst src rep -- )
879     rep {
880         { int-scalar-rep [
881             dst 32-bit-version-of src MOVD
882             dst dst 32-bit-version-of
883             2dup eq? [ 2drop ] [ MOVSX ] if
884         ] }
885         { uint-scalar-rep [
886             dst 32-bit-version-of src MOVD
887         ] }
888         { short-scalar-rep [
889             dst 32-bit-version-of src MOVD
890             dst dst 16-bit-version-of MOVSX
891         ] }
892         { ushort-scalar-rep [
893             dst 32-bit-version-of src MOVD
894             dst dst 16-bit-version-of MOVZX
895         ] }
896         { char-scalar-rep [
897             dst 32-bit-version-of src MOVD
898             dst { } 8 [| tmp-dst |
899                 tmp-dst dst int-rep %copy
900                 tmp-dst tmp-dst 8-bit-version-of MOVSX
901                 dst tmp-dst int-rep %copy
902             ] with-small-register
903         ] }
904         { uchar-scalar-rep [
905             dst 32-bit-version-of src MOVD
906             dst { } 8 [| tmp-dst |
907                 tmp-dst dst int-rep %copy
908                 tmp-dst tmp-dst 8-bit-version-of MOVZX
909                 dst tmp-dst int-rep %copy
910             ] with-small-register
911         ] }
912     } case ;
913
914 M: x86.32 %scalar>integer %scalar>integer-32 ;
915
916 M: x86.64 %scalar>integer
917     {
918         { longlong-scalar-rep  [ MOVD ] }
919         { ulonglong-scalar-rep [ MOVD ] }
920         [ %scalar>integer-32 ]
921     } case ;
922
923 M: x86 %vector>scalar %copy ;
924
925 M: x86 %scalar>vector %copy ;