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