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