d6785d8d15b24cb1dc6f667a3de9f9c99be9e978
[WebKit-https.git] / Source / JavaScriptCore / assembler / MacroAssemblerX86Common.h
1 /*
2  * Copyright (C) 2008, 2014-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef MacroAssemblerX86Common_h
27 #define MacroAssemblerX86Common_h
28
29 #if ENABLE(ASSEMBLER)
30
31 #include "X86Assembler.h"
32 #include "AbstractMacroAssembler.h"
33 #include <wtf/Optional.h>
34
35 namespace JSC {
36
37 class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler, MacroAssemblerX86Common> {
38 public:
39 #if CPU(X86_64)
40     // Use this directly only if you're not generating code with it.
41     static const X86Registers::RegisterID s_scratchRegister = X86Registers::r11;
42
43     // Use this when generating code so that we get enforcement of the disallowing of scratch register
44     // usage.
45     X86Registers::RegisterID scratchRegister()
46     {
47         RELEASE_ASSERT(m_allowScratchRegister);
48         return s_scratchRegister;
49     }
50 #endif
51
52 protected:
53     static const int DoubleConditionBitInvert = 0x10;
54     static const int DoubleConditionBitSpecial = 0x20;
55     static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
56
57 public:
58     typedef X86Assembler::XMMRegisterID XMMRegisterID;
59     
60     static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
61     {
62         return value >= -128 && value <= 127;
63     }
64
65     enum RelationalCondition {
66         Equal = X86Assembler::ConditionE,
67         NotEqual = X86Assembler::ConditionNE,
68         Above = X86Assembler::ConditionA,
69         AboveOrEqual = X86Assembler::ConditionAE,
70         Below = X86Assembler::ConditionB,
71         BelowOrEqual = X86Assembler::ConditionBE,
72         GreaterThan = X86Assembler::ConditionG,
73         GreaterThanOrEqual = X86Assembler::ConditionGE,
74         LessThan = X86Assembler::ConditionL,
75         LessThanOrEqual = X86Assembler::ConditionLE
76     };
77
78     enum ResultCondition {
79         Overflow = X86Assembler::ConditionO,
80         Signed = X86Assembler::ConditionS,
81         PositiveOrZero = X86Assembler::ConditionNS,
82         Zero = X86Assembler::ConditionE,
83         NonZero = X86Assembler::ConditionNE
84     };
85
86     // FIXME: it would be neat to rename this to FloatingPointCondition in every assembler.
87     enum DoubleCondition {
88         // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
89         DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial,
90         DoubleNotEqual = X86Assembler::ConditionNE,
91         DoubleGreaterThan = X86Assembler::ConditionA,
92         DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
93         DoubleLessThan = X86Assembler::ConditionA | DoubleConditionBitInvert,
94         DoubleLessThanOrEqual = X86Assembler::ConditionAE | DoubleConditionBitInvert,
95         // If either operand is NaN, these conditions always evaluate to true.
96         DoubleEqualOrUnordered = X86Assembler::ConditionE,
97         DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial,
98         DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert,
99         DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert,
100         DoubleLessThanOrUnordered = X86Assembler::ConditionB,
101         DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE,
102     };
103     COMPILE_ASSERT(
104         !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
105         DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
106
107     static const RegisterID stackPointerRegister = X86Registers::esp;
108     static const RegisterID framePointerRegister = X86Registers::ebp;
109     
110     static bool canBlind() { return true; }
111     static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
112     static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
113
114     // Integer arithmetic operations:
115     //
116     // Operations are typically two operand - operation(source, srcDst)
117     // For many operations the source may be an TrustedImm32, the srcDst operand
118     // may often be a memory location (explictly described using an Address
119     // object).
120
121     void add32(RegisterID src, RegisterID dest)
122     {
123         m_assembler.addl_rr(src, dest);
124     }
125
126     void add32(TrustedImm32 imm, Address address)
127     {
128         m_assembler.addl_im(imm.m_value, address.offset, address.base);
129     }
130
131     void add32(TrustedImm32 imm, BaseIndex address)
132     {
133         m_assembler.addl_im(imm.m_value, address.offset, address.base, address.index, address.scale);
134     }
135
136     void add8(TrustedImm32 imm, Address address)
137     {
138         m_assembler.addb_im(imm.m_value, address.offset, address.base);
139     }
140
141     void add8(TrustedImm32 imm, BaseIndex address)
142     {
143         m_assembler.addb_im(imm.m_value, address.offset, address.base, address.index, address.scale);
144     }
145
146     void add16(TrustedImm32 imm, Address address)
147     {
148         m_assembler.addw_im(imm.m_value, address.offset, address.base);
149     }
150
151     void add16(TrustedImm32 imm, BaseIndex address)
152     {
153         m_assembler.addw_im(imm.m_value, address.offset, address.base, address.index, address.scale);
154     }
155
156     void add32(TrustedImm32 imm, RegisterID dest)
157     {
158         if (imm.m_value == 1)
159             m_assembler.inc_r(dest);
160         else
161             m_assembler.addl_ir(imm.m_value, dest);
162     }
163     
164     void add32(Address src, RegisterID dest)
165     {
166         m_assembler.addl_mr(src.offset, src.base, dest);
167     }
168
169     void add32(RegisterID src, Address dest)
170     {
171         m_assembler.addl_rm(src, dest.offset, dest.base);
172     }
173
174     void add32(RegisterID src, BaseIndex dest)
175     {
176         m_assembler.addl_rm(src, dest.offset, dest.base, dest.index, dest.scale);
177     }
178
179     void add8(RegisterID src, Address dest)
180     {
181         m_assembler.addb_rm(src, dest.offset, dest.base);
182     }
183
184     void add8(RegisterID src, BaseIndex dest)
185     {
186         m_assembler.addb_rm(src, dest.offset, dest.base, dest.index, dest.scale);
187     }
188
189     void add16(RegisterID src, Address dest)
190     {
191         m_assembler.addw_rm(src, dest.offset, dest.base);
192     }
193
194     void add16(RegisterID src, BaseIndex dest)
195     {
196         m_assembler.addw_rm(src, dest.offset, dest.base, dest.index, dest.scale);
197     }
198
199     void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
200     {
201         if (!imm.m_value) {
202             zeroExtend32ToPtr(src, dest);
203             return;
204         }
205
206         if (src == dest) {
207             add32(imm, dest);
208             return;
209         }
210
211         m_assembler.leal_mr(imm.m_value, src, dest);
212     }
213
214     void add32(RegisterID a, RegisterID b, RegisterID dest)
215     {
216         x86Lea32(BaseIndex(a, b, TimesOne), dest);
217     }
218
219     void x86Lea32(BaseIndex index, RegisterID dest)
220     {
221         if (!index.scale && !index.offset) {
222             if (index.base == dest) {
223                 add32(index.index, dest);
224                 return;
225             }
226             if (index.index == dest) {
227                 add32(index.base, dest);
228                 return;
229             }
230         }
231         m_assembler.leal_mr(index.offset, index.base, index.index, index.scale, dest);
232     }
233
234     void and32(RegisterID src, RegisterID dest)
235     {
236         m_assembler.andl_rr(src, dest);
237     }
238
239     void and32(TrustedImm32 imm, RegisterID dest)
240     {
241         m_assembler.andl_ir(imm.m_value, dest);
242     }
243
244     void and32(RegisterID src, Address dest)
245     {
246         m_assembler.andl_rm(src, dest.offset, dest.base);
247     }
248
249     void and32(Address src, RegisterID dest)
250     {
251         m_assembler.andl_mr(src.offset, src.base, dest);
252     }
253
254     void and32(TrustedImm32 imm, Address address)
255     {
256         m_assembler.andl_im(imm.m_value, address.offset, address.base);
257     }
258
259     void and32(RegisterID op1, RegisterID op2, RegisterID dest)
260     {
261         if (op1 == op2)
262             zeroExtend32ToPtr(op1, dest);
263         else if (op1 == dest)
264             and32(op2, dest);
265         else {
266             move32IfNeeded(op2, dest);
267             and32(op1, dest);
268         }
269     }
270
271     void and32(Address op1, RegisterID op2, RegisterID dest)
272     {
273         if (op2 == dest)
274             and32(op1, dest);
275         else if (op1.base == dest) {
276             load32(op1, dest);
277             and32(op2, dest);
278         } else {
279             zeroExtend32ToPtr(op2, dest);
280             and32(op1, dest);
281         }
282     }
283
284     void and32(RegisterID op1, Address op2, RegisterID dest)
285     {
286         and32(op2, op1, dest);
287     }
288
289     void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
290     {
291         move32IfNeeded(src, dest);
292         and32(imm, dest);
293     }
294
295     void countLeadingZeros32(RegisterID src, RegisterID dst)
296     {
297         if (supportsLZCNT()) {
298             m_assembler.lzcnt_rr(src, dst);
299             return;
300         }
301         m_assembler.bsr_rr(src, dst);
302         clz32AfterBsr(dst);
303     }
304
305     void countLeadingZeros32(Address src, RegisterID dst)
306     {
307         if (supportsLZCNT()) {
308             m_assembler.lzcnt_mr(src.offset, src.base, dst);
309             return;
310         }
311         m_assembler.bsr_mr(src.offset, src.base, dst);
312         clz32AfterBsr(dst);
313     }
314
315     void lshift32(RegisterID shift_amount, RegisterID dest)
316     {
317         if (shift_amount == X86Registers::ecx)
318             m_assembler.shll_CLr(dest);
319         else {
320             ASSERT(shift_amount != dest);
321             // On x86 we can only shift by ecx; if asked to shift by another register we'll
322             // need rejig the shift amount into ecx first, and restore the registers afterwards.
323             // If we dest is ecx, then shift the swapped register!
324             swap(shift_amount, X86Registers::ecx);
325             m_assembler.shll_CLr(dest == X86Registers::ecx ? shift_amount : dest);
326             swap(shift_amount, X86Registers::ecx);
327         }
328     }
329
330     void lshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
331     {
332         ASSERT(shift_amount != dest);
333
334         move32IfNeeded(src, dest);
335         lshift32(shift_amount, dest);
336     }
337
338     void lshift32(TrustedImm32 imm, RegisterID dest)
339     {
340         m_assembler.shll_i8r(imm.m_value, dest);
341     }
342     
343     void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
344     {
345         move32IfNeeded(src, dest);
346         lshift32(imm, dest);
347     }
348     
349     void mul32(RegisterID src, RegisterID dest)
350     {
351         m_assembler.imull_rr(src, dest);
352     }
353
354     void mul32(RegisterID src1, RegisterID src2, RegisterID dest)
355     {
356         if (src2 == dest) {
357             m_assembler.imull_rr(src1, dest);
358             return;
359         }
360         move32IfNeeded(src1, dest);
361         m_assembler.imull_rr(src2, dest);
362     }
363
364     void mul32(Address src, RegisterID dest)
365     {
366         m_assembler.imull_mr(src.offset, src.base, dest);
367     }
368
369     void mul32(Address op1, RegisterID op2, RegisterID dest)
370     {
371         if (op2 == dest)
372             mul32(op1, dest);
373         else if (op1.base == dest) {
374             load32(op1, dest);
375             mul32(op2, dest);
376         } else {
377             zeroExtend32ToPtr(op2, dest);
378             mul32(op1, dest);
379         }
380     }
381
382     void mul32(RegisterID src1, Address src2, RegisterID dest)
383     {
384         mul32(src2, src1, dest);
385     }
386     
387     void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
388     {
389         m_assembler.imull_i32r(src, imm.m_value, dest);
390     }
391
392     void x86ConvertToDoubleWord32()
393     {
394         m_assembler.cdq();
395     }
396
397     void x86ConvertToDoubleWord32(RegisterID eax, RegisterID edx)
398     {
399         ASSERT_UNUSED(eax, eax == X86Registers::eax);
400         ASSERT_UNUSED(edx, edx == X86Registers::edx);
401         x86ConvertToDoubleWord32();
402     }
403
404     void x86Div32(RegisterID denominator)
405     {
406         m_assembler.idivl_r(denominator);
407     }
408
409     void x86Div32(RegisterID eax, RegisterID edx, RegisterID denominator)
410     {
411         ASSERT_UNUSED(eax, eax == X86Registers::eax);
412         ASSERT_UNUSED(edx, edx == X86Registers::edx);
413         x86Div32(denominator);
414     }
415
416     void neg32(RegisterID srcDest)
417     {
418         m_assembler.negl_r(srcDest);
419     }
420
421     void neg32(Address srcDest)
422     {
423         m_assembler.negl_m(srcDest.offset, srcDest.base);
424     }
425
426     void or32(RegisterID src, RegisterID dest)
427     {
428         m_assembler.orl_rr(src, dest);
429     }
430
431     void or32(TrustedImm32 imm, RegisterID dest)
432     {
433         m_assembler.orl_ir(imm.m_value, dest);
434     }
435
436     void or32(RegisterID src, Address dest)
437     {
438         m_assembler.orl_rm(src, dest.offset, dest.base);
439     }
440
441     void or32(Address src, RegisterID dest)
442     {
443         m_assembler.orl_mr(src.offset, src.base, dest);
444     }
445
446     void or32(TrustedImm32 imm, Address address)
447     {
448         m_assembler.orl_im(imm.m_value, address.offset, address.base);
449     }
450
451     void or32(RegisterID op1, RegisterID op2, RegisterID dest)
452     {
453         if (op1 == op2)
454             zeroExtend32ToPtr(op1, dest);
455         else if (op1 == dest)
456             or32(op2, dest);
457         else {
458             move32IfNeeded(op2, dest);
459             or32(op1, dest);
460         }
461     }
462
463     void or32(Address op1, RegisterID op2, RegisterID dest)
464     {
465         if (op2 == dest)
466             or32(op1, dest);
467         else if (op1.base == dest) {
468             load32(op1, dest);
469             or32(op2, dest);
470         } else {
471             zeroExtend32ToPtr(op2, dest);
472             or32(op1, dest);
473         }
474     }
475
476     void or32(RegisterID op1, Address op2, RegisterID dest)
477     {
478         or32(op2, op1, dest);
479     }
480
481     void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
482     {
483         move32IfNeeded(src, dest);
484         or32(imm, dest);
485     }
486
487     void rshift32(RegisterID shift_amount, RegisterID dest)
488     {
489         if (shift_amount == X86Registers::ecx)
490             m_assembler.sarl_CLr(dest);
491         else {
492             ASSERT(shift_amount != dest);
493             
494             // On x86 we can only shift by ecx; if asked to shift by another register we'll
495             // need rejig the shift amount into ecx first, and restore the registers afterwards.
496             // If we dest is ecx, then shift the swapped register!
497             swap(shift_amount, X86Registers::ecx);
498             m_assembler.sarl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
499             swap(shift_amount, X86Registers::ecx);
500         }
501     }
502
503     void rshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
504     {
505         ASSERT(shift_amount != dest);
506
507         move32IfNeeded(src, dest);
508         rshift32(shift_amount, dest);
509     }
510
511     void rshift32(TrustedImm32 imm, RegisterID dest)
512     {
513         m_assembler.sarl_i8r(imm.m_value, dest);
514     }
515     
516     void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
517     {
518         move32IfNeeded(src, dest);
519         rshift32(imm, dest);
520     }
521     
522     void urshift32(RegisterID shift_amount, RegisterID dest)
523     {
524         if (shift_amount == X86Registers::ecx)
525             m_assembler.shrl_CLr(dest);
526         else {
527             ASSERT(shift_amount != dest);
528         
529             // On x86 we can only shift by ecx; if asked to shift by another register we'll
530             // need rejig the shift amount into ecx first, and restore the registers afterwards.
531             // If we dest is ecx, then shift the swapped register!
532             swap(shift_amount, X86Registers::ecx);
533             m_assembler.shrl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
534             swap(shift_amount, X86Registers::ecx);
535         }
536     }
537
538     void urshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
539     {
540         ASSERT(shift_amount != dest);
541
542         move32IfNeeded(src, dest);
543         urshift32(shift_amount, dest);
544     }
545
546     void urshift32(TrustedImm32 imm, RegisterID dest)
547     {
548         m_assembler.shrl_i8r(imm.m_value, dest);
549     }
550     
551     void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
552     {
553         move32IfNeeded(src, dest);
554         urshift32(imm, dest);
555     }
556     
557     void sub32(RegisterID src, RegisterID dest)
558     {
559         m_assembler.subl_rr(src, dest);
560     }
561     
562     void sub32(TrustedImm32 imm, RegisterID dest)
563     {
564         if (imm.m_value == 1)
565             m_assembler.dec_r(dest);
566         else
567             m_assembler.subl_ir(imm.m_value, dest);
568     }
569     
570     void sub32(TrustedImm32 imm, Address address)
571     {
572         m_assembler.subl_im(imm.m_value, address.offset, address.base);
573     }
574
575     void sub32(Address src, RegisterID dest)
576     {
577         m_assembler.subl_mr(src.offset, src.base, dest);
578     }
579
580     void sub32(RegisterID src, Address dest)
581     {
582         m_assembler.subl_rm(src, dest.offset, dest.base);
583     }
584
585     void xor32(RegisterID src, RegisterID dest)
586     {
587         m_assembler.xorl_rr(src, dest);
588     }
589
590     void xor32(TrustedImm32 imm, Address dest)
591     {
592         if (imm.m_value == -1)
593             m_assembler.notl_m(dest.offset, dest.base);
594         else
595             m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
596     }
597
598     void xor32(TrustedImm32 imm, RegisterID dest)
599     {
600         if (imm.m_value == -1)
601             m_assembler.notl_r(dest);
602         else
603             m_assembler.xorl_ir(imm.m_value, dest);
604     }
605
606     void xor32(RegisterID src, Address dest)
607     {
608         m_assembler.xorl_rm(src, dest.offset, dest.base);
609     }
610
611     void xor32(Address src, RegisterID dest)
612     {
613         m_assembler.xorl_mr(src.offset, src.base, dest);
614     }
615     
616     void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
617     {
618         if (op1 == op2)
619             move(TrustedImm32(0), dest);
620         else if (op1 == dest)
621             xor32(op2, dest);
622         else {
623             move32IfNeeded(op2, dest);
624             xor32(op1, dest);
625         }
626     }
627
628     void xor32(Address op1, RegisterID op2, RegisterID dest)
629     {
630         if (op2 == dest)
631             xor32(op1, dest);
632         else if (op1.base == dest) {
633             load32(op1, dest);
634             xor32(op2, dest);
635         } else {
636             zeroExtend32ToPtr(op2, dest);
637             xor32(op1, dest);
638         }
639     }
640
641     void xor32(RegisterID op1, Address op2, RegisterID dest)
642     {
643         xor32(op2, op1, dest);
644     }
645
646     void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
647     {
648         move32IfNeeded(src, dest);
649         xor32(imm, dest);
650     }
651
652     void not32(RegisterID srcDest)
653     {
654         m_assembler.notl_r(srcDest);
655     }
656
657     void not32(Address dest)
658     {
659         m_assembler.notl_m(dest.offset, dest.base);
660     }
661
662     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
663     {
664         m_assembler.sqrtsd_rr(src, dst);
665     }
666
667     void sqrtDouble(Address src, FPRegisterID dst)
668     {
669         m_assembler.sqrtsd_mr(src.offset, src.base, dst);
670     }
671
672     void sqrtFloat(FPRegisterID src, FPRegisterID dst)
673     {
674         m_assembler.sqrtss_rr(src, dst);
675     }
676
677     void sqrtFloat(Address src, FPRegisterID dst)
678     {
679         m_assembler.sqrtss_mr(src.offset, src.base, dst);
680     }
681
682     void absDouble(FPRegisterID src, FPRegisterID dst)
683     {
684         ASSERT(src != dst);
685         static const double negativeZeroConstant = -0.0;
686         loadDouble(TrustedImmPtr(&negativeZeroConstant), dst);
687         m_assembler.andnpd_rr(src, dst);
688     }
689
690     void negateDouble(FPRegisterID src, FPRegisterID dst)
691     {
692         ASSERT(src != dst);
693         static const double negativeZeroConstant = -0.0;
694         loadDouble(TrustedImmPtr(&negativeZeroConstant), dst);
695         m_assembler.xorpd_rr(src, dst);
696     }
697
698     void ceilDouble(FPRegisterID src, FPRegisterID dst)
699     {
700         m_assembler.roundsd_rr(src, dst, X86Assembler::RoundingType::TowardInfiniti);
701     }
702
703     void ceilDouble(Address src, FPRegisterID dst)
704     {
705         m_assembler.roundsd_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardInfiniti);
706     }
707
708     void ceilFloat(FPRegisterID src, FPRegisterID dst)
709     {
710         m_assembler.roundss_rr(src, dst, X86Assembler::RoundingType::TowardInfiniti);
711     }
712
713     void ceilFloat(Address src, FPRegisterID dst)
714     {
715         m_assembler.roundss_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardInfiniti);
716     }
717
718     void floorDouble(FPRegisterID src, FPRegisterID dst)
719     {
720         m_assembler.roundsd_rr(src, dst, X86Assembler::RoundingType::TowardNegativeInfiniti);
721     }
722
723     void floorDouble(Address src, FPRegisterID dst)
724     {
725         m_assembler.roundsd_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardNegativeInfiniti);
726     }
727
728     void floorFloat(FPRegisterID src, FPRegisterID dst)
729     {
730         m_assembler.roundss_rr(src, dst, X86Assembler::RoundingType::TowardNegativeInfiniti);
731     }
732
733     void floorFloat(Address src, FPRegisterID dst)
734     {
735         m_assembler.roundss_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardNegativeInfiniti);
736     }
737
738     void roundTowardZeroDouble(FPRegisterID src, FPRegisterID dst)
739     {
740         m_assembler.roundsd_rr(src, dst, X86Assembler::RoundingType::TowardZero);
741     }
742
743     void roundTowardZeroDouble(Address src, FPRegisterID dst)
744     {
745         m_assembler.roundsd_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardZero);
746     }
747
748     void roundTowardZeroFloat(FPRegisterID src, FPRegisterID dst)
749     {
750         m_assembler.roundss_rr(src, dst, X86Assembler::RoundingType::TowardZero);
751     }
752
753     void roundTowardZeroFloat(Address src, FPRegisterID dst)
754     {
755         m_assembler.roundss_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardZero);
756     }
757
758     // Memory access operations:
759     //
760     // Loads are of the form load(address, destination) and stores of the form
761     // store(source, address).  The source for a store may be an TrustedImm32.  Address
762     // operand objects to loads and store will be implicitly constructed if a
763     // register is passed.
764
765     void load32(ImplicitAddress address, RegisterID dest)
766     {
767         m_assembler.movl_mr(address.offset, address.base, dest);
768     }
769
770     void load32(BaseIndex address, RegisterID dest)
771     {
772         m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
773     }
774
775     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
776     {
777         load32(address, dest);
778     }
779
780     void load16Unaligned(BaseIndex address, RegisterID dest)
781     {
782         load16(address, dest);
783     }
784
785     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
786     {
787         padBeforePatch();
788         m_assembler.movl_mr_disp32(address.offset, address.base, dest);
789         return DataLabel32(this);
790     }
791     
792     DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
793     {
794         padBeforePatch();
795         m_assembler.movl_mr_disp8(address.offset, address.base, dest);
796         return DataLabelCompact(this);
797     }
798     
799     static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
800     {
801         ASSERT(isCompactPtrAlignedAddressOffset(value));
802         AssemblerType_T::repatchCompact(dataLabelCompact.dataLocation(), value);
803     }
804     
805     DataLabelCompact loadCompactWithAddressOffsetPatch(Address address, RegisterID dest)
806     {
807         padBeforePatch();
808         m_assembler.movl_mr_disp8(address.offset, address.base, dest);
809         return DataLabelCompact(this);
810     }
811
812     void load8(BaseIndex address, RegisterID dest)
813     {
814         m_assembler.movzbl_mr(address.offset, address.base, address.index, address.scale, dest);
815     }
816
817     void load8(ImplicitAddress address, RegisterID dest)
818     {
819         m_assembler.movzbl_mr(address.offset, address.base, dest);
820     }
821     
822     void load8SignedExtendTo32(BaseIndex address, RegisterID dest)
823     {
824         m_assembler.movsbl_mr(address.offset, address.base, address.index, address.scale, dest);
825     }
826
827     void load8SignedExtendTo32(ImplicitAddress address, RegisterID dest)
828     {
829         m_assembler.movsbl_mr(address.offset, address.base, dest);
830     }
831
832     void zeroExtend8To32(RegisterID src, RegisterID dest)
833     {
834         m_assembler.movzbl_rr(src, dest);
835     }
836     
837     void signExtend8To32(RegisterID src, RegisterID dest)
838     {
839         m_assembler.movsbl_rr(src, dest);
840     }
841     
842     void load16(BaseIndex address, RegisterID dest)
843     {
844         m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
845     }
846     
847     void load16(Address address, RegisterID dest)
848     {
849         m_assembler.movzwl_mr(address.offset, address.base, dest);
850     }
851
852     void load16SignedExtendTo32(BaseIndex address, RegisterID dest)
853     {
854         m_assembler.movswl_mr(address.offset, address.base, address.index, address.scale, dest);
855     }
856     
857     void load16SignedExtendTo32(Address address, RegisterID dest)
858     {
859         m_assembler.movswl_mr(address.offset, address.base, dest);
860     }
861
862     void zeroExtend16To32(RegisterID src, RegisterID dest)
863     {
864         m_assembler.movzwl_rr(src, dest);
865     }
866     
867     void signExtend16To32(RegisterID src, RegisterID dest)
868     {
869         m_assembler.movswl_rr(src, dest);
870     }
871     
872     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
873     {
874         padBeforePatch();
875         m_assembler.movl_rm_disp32(src, address.offset, address.base);
876         return DataLabel32(this);
877     }
878
879     void store32(RegisterID src, ImplicitAddress address)
880     {
881         m_assembler.movl_rm(src, address.offset, address.base);
882     }
883
884     void store32(RegisterID src, BaseIndex address)
885     {
886         m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
887     }
888
889     void store32(TrustedImm32 imm, ImplicitAddress address)
890     {
891         m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
892     }
893     
894     void store32(TrustedImm32 imm, BaseIndex address)
895     {
896         m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
897     }
898
899     void storeZero32(ImplicitAddress address)
900     {
901         store32(TrustedImm32(0), address);
902     }
903
904     void storeZero32(BaseIndex address)
905     {
906         store32(TrustedImm32(0), address);
907     }
908
909     void store8(TrustedImm32 imm, Address address)
910     {
911         m_assembler.movb_i8m(static_cast<int8_t>(imm.m_value), address.offset, address.base);
912     }
913
914     void store8(TrustedImm32 imm, BaseIndex address)
915     {
916         m_assembler.movb_i8m(static_cast<int8_t>(imm.m_value), address.offset, address.base, address.index, address.scale);
917     }
918
919     static ALWAYS_INLINE RegisterID getUnusedRegister(BaseIndex address)
920     {
921         if (address.base != X86Registers::eax && address.index != X86Registers::eax)
922             return X86Registers::eax;
923
924         if (address.base != X86Registers::ebx && address.index != X86Registers::ebx)
925             return X86Registers::ebx;
926
927         ASSERT(address.base != X86Registers::ecx && address.index != X86Registers::ecx);
928         return X86Registers::ecx;
929     }
930
931     static ALWAYS_INLINE RegisterID getUnusedRegister(Address address)
932     {
933         if (address.base != X86Registers::eax)
934             return X86Registers::eax;
935
936         ASSERT(address.base != X86Registers::edx);
937         return X86Registers::edx;
938     }
939
940     void store8(RegisterID src, BaseIndex address)
941     {
942 #if CPU(X86)
943         // On 32-bit x86 we can only store from the first 4 registers;
944         // esp..edi are mapped to the 'h' registers!
945         if (src >= 4) {
946             // Pick a temporary register.
947             RegisterID temp = getUnusedRegister(address);
948
949             // Swap to the temporary register to perform the store.
950             swap(src, temp);
951             m_assembler.movb_rm(temp, address.offset, address.base, address.index, address.scale);
952             swap(src, temp);
953             return;
954         }
955 #endif
956         m_assembler.movb_rm(src, address.offset, address.base, address.index, address.scale);
957     }
958     
959     void store8(RegisterID src, Address address)
960     {
961 #if CPU(X86)
962         // On 32-bit x86 we can only store from the first 4 registers;
963         // esp..edi are mapped to the 'h' registers!
964         if (src >= 4) {
965             // Pick a temporary register.
966             RegisterID temp = getUnusedRegister(address);
967
968             // Swap to the temporary register to perform the store.
969             swap(src, temp);
970             m_assembler.movb_rm(temp, address.offset, address.base);
971             swap(src, temp);
972             return;
973         }
974 #endif
975         m_assembler.movb_rm(src, address.offset, address.base);
976     }
977
978     void store16(RegisterID src, BaseIndex address)
979     {
980 #if CPU(X86)
981         // On 32-bit x86 we can only store from the first 4 registers;
982         // esp..edi are mapped to the 'h' registers!
983         if (src >= 4) {
984             // Pick a temporary register.
985             RegisterID temp = getUnusedRegister(address);
986
987             // Swap to the temporary register to perform the store.
988             swap(src, temp);
989             m_assembler.movw_rm(temp, address.offset, address.base, address.index, address.scale);
990             swap(src, temp);
991             return;
992         }
993 #endif
994         m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
995     }
996
997     void store16(RegisterID src, Address address)
998     {
999 #if CPU(X86)
1000         // On 32-bit x86 we can only store from the first 4 registers;
1001         // esp..edi are mapped to the 'h' registers!
1002         if (src >= 4) {
1003             // Pick a temporary register.
1004             RegisterID temp = getUnusedRegister(address);
1005
1006             // Swap to the temporary register to perform the store.
1007             swap(src, temp);
1008             m_assembler.movw_rm(temp, address.offset, address.base);
1009             swap(src, temp);
1010             return;
1011         }
1012 #endif
1013         m_assembler.movw_rm(src, address.offset, address.base);
1014     }
1015
1016
1017     // Floating-point operation:
1018     //
1019     // Presently only supports SSE, not x87 floating point.
1020
1021     void moveDouble(FPRegisterID src, FPRegisterID dest)
1022     {
1023         ASSERT(isSSE2Present());
1024         if (src != dest)
1025             m_assembler.movaps_rr(src, dest);
1026     }
1027
1028     void loadDouble(TrustedImmPtr address, FPRegisterID dest)
1029     {
1030 #if CPU(X86)
1031         ASSERT(isSSE2Present());
1032         m_assembler.movsd_mr(address.m_value, dest);
1033 #else
1034         move(address, scratchRegister());
1035         loadDouble(scratchRegister(), dest);
1036 #endif
1037     }
1038
1039     void loadDouble(ImplicitAddress address, FPRegisterID dest)
1040     {
1041         ASSERT(isSSE2Present());
1042         m_assembler.movsd_mr(address.offset, address.base, dest);
1043     }
1044
1045     void loadDouble(BaseIndex address, FPRegisterID dest)
1046     {
1047         ASSERT(isSSE2Present());
1048         m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
1049     }
1050
1051     void loadFloat(ImplicitAddress address, FPRegisterID dest)
1052     {
1053         ASSERT(isSSE2Present());
1054         m_assembler.movss_mr(address.offset, address.base, dest);
1055     }
1056
1057     void loadFloat(BaseIndex address, FPRegisterID dest)
1058     {
1059         ASSERT(isSSE2Present());
1060         m_assembler.movss_mr(address.offset, address.base, address.index, address.scale, dest);
1061     }
1062
1063     void storeDouble(FPRegisterID src, ImplicitAddress address)
1064     {
1065         ASSERT(isSSE2Present());
1066         m_assembler.movsd_rm(src, address.offset, address.base);
1067     }
1068     
1069     void storeDouble(FPRegisterID src, BaseIndex address)
1070     {
1071         ASSERT(isSSE2Present());
1072         m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
1073     }
1074
1075     void storeFloat(FPRegisterID src, ImplicitAddress address)
1076     {
1077         ASSERT(isSSE2Present());
1078         m_assembler.movss_rm(src, address.offset, address.base);
1079     }
1080
1081     void storeFloat(FPRegisterID src, BaseIndex address)
1082     {
1083         ASSERT(isSSE2Present());
1084         m_assembler.movss_rm(src, address.offset, address.base, address.index, address.scale);
1085     }
1086     
1087     void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
1088     {
1089         ASSERT(isSSE2Present());
1090         m_assembler.cvtsd2ss_rr(src, dst);
1091     }
1092
1093     void convertDoubleToFloat(Address address, FPRegisterID dst)
1094     {
1095         ASSERT(isSSE2Present());
1096         m_assembler.cvtsd2ss_mr(address.offset, address.base, dst);
1097     }
1098
1099     void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
1100     {
1101         ASSERT(isSSE2Present());
1102         m_assembler.cvtss2sd_rr(src, dst);
1103     }
1104
1105     void convertFloatToDouble(Address address, FPRegisterID dst)
1106     {
1107         ASSERT(isSSE2Present());
1108         m_assembler.cvtss2sd_mr(address.offset, address.base, dst);
1109     }
1110
1111     void addDouble(FPRegisterID src, FPRegisterID dest)
1112     {
1113         addDouble(src, dest, dest);
1114     }
1115
1116     void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1117     {
1118         if (supportsAVX())
1119             m_assembler.vaddsd_rr(op1, op2, dest);
1120         else {
1121             ASSERT(isSSE2Present());
1122             if (op1 == dest)
1123                 m_assembler.addsd_rr(op2, dest);
1124             else {
1125                 moveDouble(op2, dest);
1126                 m_assembler.addsd_rr(op1, dest);
1127             }
1128         }
1129     }
1130
1131     void addDouble(Address src, FPRegisterID dest)
1132     {
1133         addDouble(src, dest, dest);
1134     }
1135
1136     void addDouble(Address op1, FPRegisterID op2, FPRegisterID dest)
1137     {
1138         if (supportsAVX())
1139             m_assembler.vaddsd_mr(op1.offset, op1.base, op2, dest);
1140         else {
1141             ASSERT(isSSE2Present());
1142             if (op2 == dest) {
1143                 m_assembler.addsd_mr(op1.offset, op1.base, dest);
1144                 return;
1145             }
1146
1147             loadDouble(op1, dest);
1148             addDouble(op2, dest);
1149         }
1150     }
1151
1152     void addDouble(FPRegisterID op1, Address op2, FPRegisterID dest)
1153     {
1154         addDouble(op2, op1, dest);
1155     }
1156
1157     void addDouble(BaseIndex op1, FPRegisterID op2, FPRegisterID dest)
1158     {
1159         if (supportsAVX())
1160             m_assembler.vaddsd_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest);
1161         else {
1162             ASSERT(isSSE2Present());
1163             if (op2 == dest) {
1164                 m_assembler.addsd_mr(op1.offset, op1.base, op1.index, op1.scale, dest);
1165                 return;
1166             }
1167             loadDouble(op1, dest);
1168             addDouble(op2, dest);
1169         }
1170     }
1171
1172     void addFloat(FPRegisterID src, FPRegisterID dest)
1173     {
1174         addFloat(src, dest, dest);
1175     }
1176
1177     void addFloat(Address src, FPRegisterID dest)
1178     {
1179         addFloat(src, dest, dest);
1180     }
1181
1182     void addFloat(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1183     {
1184         if (supportsAVX())
1185             m_assembler.vaddss_rr(op1, op2, dest);
1186         else {
1187             ASSERT(isSSE2Present());
1188             if (op1 == dest)
1189                 m_assembler.addss_rr(op2, dest);
1190             else {
1191                 moveDouble(op2, dest);
1192                 m_assembler.addss_rr(op1, dest);
1193             }
1194         }
1195     }
1196
1197     void addFloat(Address op1, FPRegisterID op2, FPRegisterID dest)
1198     {
1199         if (supportsAVX())
1200             m_assembler.vaddss_mr(op1.offset, op1.base, op2, dest);
1201         else {
1202             ASSERT(isSSE2Present());
1203             if (op2 == dest) {
1204                 m_assembler.addss_mr(op1.offset, op1.base, dest);
1205                 return;
1206             }
1207
1208             loadFloat(op1, dest);
1209             addFloat(op2, dest);
1210         }
1211     }
1212
1213     void addFloat(FPRegisterID op1, Address op2, FPRegisterID dest)
1214     {
1215         addFloat(op2, op1, dest);
1216     }
1217
1218     void addFloat(BaseIndex op1, FPRegisterID op2, FPRegisterID dest)
1219     {
1220         if (supportsAVX())
1221             m_assembler.vaddss_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest);
1222         else {
1223             ASSERT(isSSE2Present());
1224             if (op2 == dest) {
1225                 m_assembler.addss_mr(op1.offset, op1.base, op1.index, op1.scale, dest);
1226                 return;
1227             }
1228             loadFloat(op1, dest);
1229             addFloat(op2, dest);
1230         }
1231     }
1232
1233     void divDouble(FPRegisterID src, FPRegisterID dest)
1234     {
1235         ASSERT(isSSE2Present());
1236         m_assembler.divsd_rr(src, dest);
1237     }
1238
1239     void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1240     {
1241         // B := A / B is invalid.
1242         ASSERT(op1 == dest || op2 != dest);
1243
1244         moveDouble(op1, dest);
1245         divDouble(op2, dest);
1246     }
1247
1248     void divDouble(Address src, FPRegisterID dest)
1249     {
1250         ASSERT(isSSE2Present());
1251         m_assembler.divsd_mr(src.offset, src.base, dest);
1252     }
1253
1254     void divFloat(FPRegisterID src, FPRegisterID dest)
1255     {
1256         ASSERT(isSSE2Present());
1257         m_assembler.divss_rr(src, dest);
1258     }
1259
1260     void divFloat(Address src, FPRegisterID dest)
1261     {
1262         ASSERT(isSSE2Present());
1263         m_assembler.divss_mr(src.offset, src.base, dest);
1264     }
1265
1266     void subDouble(FPRegisterID src, FPRegisterID dest)
1267     {
1268         subDouble(dest, src, dest);
1269     }
1270
1271     void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1272     {
1273         if (supportsAVX())
1274             m_assembler.vsubsd_rr(op1, op2, dest);
1275         else {
1276             ASSERT(isSSE2Present());
1277
1278             // B := A - B is invalid.
1279             ASSERT(op1 == dest || op2 != dest);
1280             moveDouble(op1, dest);
1281             m_assembler.subsd_rr(op2, dest);
1282         }
1283     }
1284
1285     void subDouble(FPRegisterID op1, Address op2, FPRegisterID dest)
1286     {
1287         if (supportsAVX())
1288             m_assembler.vsubsd_mr(op1, op2.offset, op2.base, dest);
1289         else {
1290             moveDouble(op1, dest);
1291             m_assembler.subsd_mr(op2.offset, op2.base, dest);
1292         }
1293     }
1294
1295     void subDouble(FPRegisterID op1, BaseIndex op2, FPRegisterID dest)
1296     {
1297         if (supportsAVX())
1298             m_assembler.vsubsd_mr(op1, op2.offset, op2.base, op2.index, op2.scale, dest);
1299         else {
1300             moveDouble(op1, dest);
1301             m_assembler.subsd_mr(op2.offset, op2.base, op2.index, op2.scale, dest);
1302         }
1303     }
1304
1305     void subDouble(Address src, FPRegisterID dest)
1306     {
1307         subDouble(dest, src, dest);
1308     }
1309
1310     void subFloat(FPRegisterID src, FPRegisterID dest)
1311     {
1312         subFloat(dest, src, dest);
1313     }
1314
1315     void subFloat(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1316     {
1317         if (supportsAVX())
1318             m_assembler.vsubss_rr(op1, op2, dest);
1319         else {
1320             ASSERT(isSSE2Present());
1321             // B := A - B is invalid.
1322             ASSERT(op1 == dest || op2 != dest);
1323             moveDouble(op1, dest);
1324             m_assembler.subss_rr(op2, dest);
1325         }
1326     }
1327
1328     void subFloat(FPRegisterID op1, Address op2, FPRegisterID dest)
1329     {
1330         if (supportsAVX())
1331             m_assembler.vsubss_mr(op1, op2.offset, op2.base, dest);
1332         else {
1333             moveDouble(op1, dest);
1334             m_assembler.subss_mr(op2.offset, op2.base, dest);
1335         }
1336     }
1337
1338     void subFloat(FPRegisterID op1, BaseIndex op2, FPRegisterID dest)
1339     {
1340         if (supportsAVX())
1341             m_assembler.vsubss_mr(op1, op2.offset, op2.base, op2.index, op2.scale, dest);
1342         else {
1343             moveDouble(op1, dest);
1344             m_assembler.subss_mr(op2.offset, op2.base, op2.index, op2.scale, dest);
1345         }
1346     }
1347
1348     void subFloat(Address src, FPRegisterID dest)
1349     {
1350         subFloat(dest, src, dest);
1351     }
1352
1353     void mulDouble(FPRegisterID src, FPRegisterID dest)
1354     {
1355         mulDouble(src, dest, dest);
1356     }
1357
1358     void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1359     {
1360         if (supportsAVX())
1361             m_assembler.vmulsd_rr(op1, op2, dest);
1362         else {
1363             ASSERT(isSSE2Present());
1364             if (op1 == dest)
1365                 m_assembler.mulsd_rr(op2, dest);
1366             else {
1367                 moveDouble(op2, dest);
1368                 m_assembler.mulsd_rr(op1, dest);
1369             }
1370         }
1371     }
1372
1373     void mulDouble(Address src, FPRegisterID dest)
1374     {
1375         mulDouble(src, dest, dest);
1376     }
1377
1378     void mulDouble(Address op1, FPRegisterID op2, FPRegisterID dest)
1379     {
1380         if (supportsAVX())
1381             m_assembler.vmulsd_mr(op1.offset, op1.base, op2, dest);
1382         else {
1383             ASSERT(isSSE2Present());
1384             if (op2 == dest) {
1385                 m_assembler.mulsd_mr(op1.offset, op1.base, dest);
1386                 return;
1387             }
1388             loadDouble(op1, dest);
1389             mulDouble(op2, dest);
1390         }
1391     }
1392
1393     void mulDouble(FPRegisterID op1, Address op2, FPRegisterID dest)
1394     {
1395         return mulDouble(op2, op1, dest);
1396     }
1397
1398     void mulDouble(BaseIndex op1, FPRegisterID op2, FPRegisterID dest)
1399     {
1400         if (supportsAVX())
1401             m_assembler.vmulsd_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest);
1402         else {
1403             ASSERT(isSSE2Present());
1404             if (op2 == dest) {
1405                 m_assembler.mulsd_mr(op1.offset, op1.base, op1.index, op1.scale, dest);
1406                 return;
1407             }
1408             loadDouble(op1, dest);
1409             mulDouble(op2, dest);
1410         }
1411     }
1412
1413     void mulFloat(FPRegisterID src, FPRegisterID dest)
1414     {
1415         mulFloat(src, dest, dest);
1416     }
1417
1418     void mulFloat(Address src, FPRegisterID dest)
1419     {
1420         mulFloat(src, dest, dest);
1421     }
1422
1423     void mulFloat(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
1424     {
1425         if (supportsAVX())
1426             m_assembler.vmulss_rr(op1, op2, dest);
1427         else {
1428             ASSERT(isSSE2Present());
1429             if (op1 == dest)
1430                 m_assembler.mulss_rr(op2, dest);
1431             else {
1432                 moveDouble(op2, dest);
1433                 m_assembler.mulss_rr(op1, dest);
1434             }
1435         }
1436     }
1437
1438     void mulFloat(Address op1, FPRegisterID op2, FPRegisterID dest)
1439     {
1440         if (supportsAVX())
1441             m_assembler.vmulss_mr(op1.offset, op1.base, op2, dest);
1442         else {
1443             ASSERT(isSSE2Present());
1444             if (op2 == dest) {
1445                 m_assembler.mulss_mr(op1.offset, op1.base, dest);
1446                 return;
1447             }
1448             loadFloat(op1, dest);
1449             mulFloat(op2, dest);
1450         }
1451     }
1452
1453     void mulFloat(FPRegisterID op1, Address op2, FPRegisterID dest)
1454     {
1455         mulFloat(op2, op1, dest);
1456     }
1457
1458     void mulFloat(BaseIndex op1, FPRegisterID op2, FPRegisterID dest)
1459     {
1460         if (supportsAVX())
1461             m_assembler.vmulss_mr(op1.offset, op1.base, op1.index, op1.scale, op2, dest);
1462         else {
1463             ASSERT(isSSE2Present());
1464             if (op2 == dest) {
1465                 m_assembler.mulss_mr(op1.offset, op1.base, op1.index, op1.scale, dest);
1466                 return;
1467             }
1468             loadFloat(op1, dest);
1469             mulFloat(op2, dest);
1470         }
1471     }
1472
1473     void andDouble(FPRegisterID src, FPRegisterID dst)
1474     {
1475         // ANDPS is defined on 128bits and is shorter than ANDPD.
1476         m_assembler.andps_rr(src, dst);
1477     }
1478
1479     void andDouble(FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
1480     {
1481         if (src1 == dst)
1482             andDouble(src2, dst);
1483         else {
1484             moveDouble(src2, dst);
1485             andDouble(src1, dst);
1486         }
1487     }
1488
1489     void andFloat(FPRegisterID src, FPRegisterID dst)
1490     {
1491         m_assembler.andps_rr(src, dst);
1492     }
1493
1494     void andFloat(FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
1495     {
1496         if (src1 == dst)
1497             andFloat(src2, dst);
1498         else {
1499             moveDouble(src2, dst);
1500             andFloat(src1, dst);
1501         }
1502     }
1503
1504     void xorDouble(FPRegisterID src, FPRegisterID dst)
1505     {
1506         m_assembler.xorps_rr(src, dst);
1507     }
1508
1509     void xorDouble(FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
1510     {
1511         if (src1 == dst)
1512             xorDouble(src2, dst);
1513         else {
1514             moveDouble(src2, dst);
1515             xorDouble(src1, dst);
1516         }
1517     }
1518
1519     void xorFloat(FPRegisterID src, FPRegisterID dst)
1520     {
1521         m_assembler.xorps_rr(src, dst);
1522     }
1523
1524     void xorFloat(FPRegisterID src1, FPRegisterID src2, FPRegisterID dst)
1525     {
1526         if (src1 == dst)
1527             xorFloat(src2, dst);
1528         else {
1529             moveDouble(src2, dst);
1530             xorFloat(src1, dst);
1531         }
1532     }
1533
1534     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
1535     {
1536         ASSERT(isSSE2Present());
1537         m_assembler.cvtsi2sd_rr(src, dest);
1538     }
1539
1540     void convertInt32ToDouble(Address src, FPRegisterID dest)
1541     {
1542         ASSERT(isSSE2Present());
1543         m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
1544     }
1545
1546     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
1547     {
1548         ASSERT(isSSE2Present());
1549
1550         if (cond & DoubleConditionBitInvert)
1551             m_assembler.ucomisd_rr(left, right);
1552         else
1553             m_assembler.ucomisd_rr(right, left);
1554         return jumpAfterFloatingPointCompare(cond, left, right);
1555     }
1556
1557     Jump branchFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
1558     {
1559         ASSERT(isSSE2Present());
1560
1561         if (cond & DoubleConditionBitInvert)
1562             m_assembler.ucomiss_rr(left, right);
1563         else
1564             m_assembler.ucomiss_rr(right, left);
1565         return jumpAfterFloatingPointCompare(cond, left, right);
1566     }
1567
1568     // Truncates 'src' to an integer, and places the resulting 'dest'.
1569     // If the result is not representable as a 32 bit value, branch.
1570     // May also branch for some values that are representable in 32 bits
1571     // (specifically, in this case, INT_MIN).
1572     enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
1573     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
1574     {
1575         ASSERT(isSSE2Present());
1576         m_assembler.cvttsd2si_rr(src, dest);
1577         return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
1578     }
1579
1580     void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
1581     {
1582         ASSERT(isSSE2Present());
1583         m_assembler.cvttsd2si_rr(src, dest);
1584     }
1585     
1586 #if CPU(X86_64)
1587     void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
1588     {
1589         ASSERT(isSSE2Present());
1590         m_assembler.cvttsd2siq_rr(src, dest);
1591     }
1592 #endif
1593     
1594     // Convert 'src' to an integer, and places the resulting 'dest'.
1595     // If the result is not representable as a 32 bit value, branch.
1596     // May also branch for some values that are representable in 32 bits
1597     // (specifically, in this case, 0).
1598     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true)
1599     {
1600         ASSERT(isSSE2Present());
1601         m_assembler.cvttsd2si_rr(src, dest);
1602
1603         // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
1604 #if CPU(X86_64)
1605         if (negZeroCheck) {
1606             Jump valueIsNonZero = branchTest32(NonZero, dest);
1607             m_assembler.movmskpd_rr(src, scratchRegister());
1608             failureCases.append(branchTest32(NonZero, scratchRegister(), TrustedImm32(1)));
1609             valueIsNonZero.link(this);
1610         }
1611 #else
1612         if (negZeroCheck)
1613             failureCases.append(branchTest32(Zero, dest));
1614 #endif
1615
1616         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
1617         convertInt32ToDouble(dest, fpTemp);
1618         m_assembler.ucomisd_rr(fpTemp, src);
1619         failureCases.append(m_assembler.jp());
1620         failureCases.append(m_assembler.jne());
1621     }
1622
1623     void moveZeroToDouble(FPRegisterID reg)
1624     {
1625         m_assembler.xorps_rr(reg, reg);
1626     }
1627
1628     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
1629     {
1630         ASSERT(isSSE2Present());
1631         m_assembler.xorpd_rr(scratch, scratch);
1632         return branchDouble(DoubleNotEqual, reg, scratch);
1633     }
1634
1635     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
1636     {
1637         ASSERT(isSSE2Present());
1638         m_assembler.xorpd_rr(scratch, scratch);
1639         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
1640     }
1641
1642     void lshiftPacked(TrustedImm32 imm, XMMRegisterID reg)
1643     {
1644         ASSERT(isSSE2Present());
1645         m_assembler.psllq_i8r(imm.m_value, reg);
1646     }
1647
1648     void rshiftPacked(TrustedImm32 imm, XMMRegisterID reg)
1649     {
1650         ASSERT(isSSE2Present());
1651         m_assembler.psrlq_i8r(imm.m_value, reg);
1652     }
1653
1654     void orPacked(XMMRegisterID src, XMMRegisterID dst)
1655     {
1656         ASSERT(isSSE2Present());
1657         m_assembler.por_rr(src, dst);
1658     }
1659
1660     void move32ToFloat(RegisterID src, XMMRegisterID dst)
1661     {
1662         ASSERT(isSSE2Present());
1663         m_assembler.movd_rr(src, dst);
1664     }
1665
1666     void moveFloatTo32(XMMRegisterID src, RegisterID dst)
1667     {
1668         ASSERT(isSSE2Present());
1669         m_assembler.movd_rr(src, dst);
1670     }
1671
1672     // Stack manipulation operations:
1673     //
1674     // The ABI is assumed to provide a stack abstraction to memory,
1675     // containing machine word sized units of data.  Push and pop
1676     // operations add and remove a single register sized unit of data
1677     // to or from the stack.  Peek and poke operations read or write
1678     // values on the stack, without moving the current stack position.
1679     
1680     void pop(RegisterID dest)
1681     {
1682         m_assembler.pop_r(dest);
1683     }
1684
1685     void push(RegisterID src)
1686     {
1687         m_assembler.push_r(src);
1688     }
1689
1690     void push(Address address)
1691     {
1692         m_assembler.push_m(address.offset, address.base);
1693     }
1694
1695     void push(TrustedImm32 imm)
1696     {
1697         m_assembler.push_i32(imm.m_value);
1698     }
1699
1700
1701     // Register move operations:
1702     //
1703     // Move values in registers.
1704
1705     void move(TrustedImm32 imm, RegisterID dest)
1706     {
1707         // Note: on 64-bit the TrustedImm32 value is zero extended into the register, it
1708         // may be useful to have a separate version that sign extends the value?
1709         if (!imm.m_value)
1710             m_assembler.xorl_rr(dest, dest);
1711         else
1712             m_assembler.movl_i32r(imm.m_value, dest);
1713     }
1714
1715 #if CPU(X86_64)
1716     void move(RegisterID src, RegisterID dest)
1717     {
1718         // Note: on 64-bit this is is a full register move; perhaps it would be
1719         // useful to have separate move32 & movePtr, with move32 zero extending?
1720         if (src != dest)
1721             m_assembler.movq_rr(src, dest);
1722     }
1723
1724     void move(TrustedImmPtr imm, RegisterID dest)
1725     {
1726         if (!imm.m_value)
1727             m_assembler.xorq_rr(dest, dest);
1728         else
1729             m_assembler.movq_i64r(imm.asIntptr(), dest);
1730     }
1731
1732     void move(TrustedImm64 imm, RegisterID dest)
1733     {
1734         if (!imm.m_value)
1735             m_assembler.xorq_rr(dest, dest);
1736         else
1737             m_assembler.movq_i64r(imm.m_value, dest);
1738     }
1739
1740     void moveConditionallyDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID src, RegisterID dest)
1741     {
1742         ASSERT(isSSE2Present());
1743
1744         if (cond & DoubleConditionBitInvert)
1745             m_assembler.ucomisd_rr(left, right);
1746         else
1747             m_assembler.ucomisd_rr(right, left);
1748         moveConditionallyAfterFloatingPointCompare(cond, left, right, src, dest);
1749     }
1750
1751     void moveConditionallyDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1752     {
1753         ASSERT(isSSE2Present());
1754
1755         if (thenCase != dest && elseCase != dest) {
1756             move(elseCase, dest);
1757             elseCase = dest;
1758         }
1759
1760         RegisterID src;
1761         if (elseCase == dest)
1762             src = thenCase;
1763         else {
1764             cond = invert(cond);
1765             src = elseCase;
1766         }
1767
1768         if (cond & DoubleConditionBitInvert)
1769             m_assembler.ucomisd_rr(left, right);
1770         else
1771             m_assembler.ucomisd_rr(right, left);
1772         moveConditionallyAfterFloatingPointCompare(cond, left, right, src, dest);
1773     }
1774
1775     void moveConditionallyFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID src, RegisterID dest)
1776     {
1777         ASSERT(isSSE2Present());
1778
1779         if (cond & DoubleConditionBitInvert)
1780             m_assembler.ucomiss_rr(left, right);
1781         else
1782             m_assembler.ucomiss_rr(right, left);
1783         moveConditionallyAfterFloatingPointCompare(cond, left, right, src, dest);
1784     }
1785
1786     void moveConditionallyFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1787     {
1788         ASSERT(isSSE2Present());
1789
1790         if (thenCase != dest && elseCase != dest) {
1791             move(elseCase, dest);
1792             elseCase = dest;
1793         }
1794
1795         RegisterID src;
1796         if (elseCase == dest)
1797             src = thenCase;
1798         else {
1799             cond = invert(cond);
1800             src = elseCase;
1801         }
1802
1803         if (cond & DoubleConditionBitInvert)
1804             m_assembler.ucomiss_rr(left, right);
1805         else
1806             m_assembler.ucomiss_rr(right, left);
1807         moveConditionallyAfterFloatingPointCompare(cond, left, right, src, dest);
1808     }
1809     
1810     void swap(RegisterID reg1, RegisterID reg2)
1811     {
1812         if (reg1 != reg2)
1813             m_assembler.xchgq_rr(reg1, reg2);
1814     }
1815
1816     void signExtend32ToPtr(TrustedImm32 imm, RegisterID dest)
1817     {
1818         if (!imm.m_value)
1819             m_assembler.xorq_rr(dest, dest);
1820         else
1821             m_assembler.mov_i32r(imm.m_value, dest);
1822     }
1823
1824     void signExtend32ToPtr(RegisterID src, RegisterID dest)
1825     {
1826         m_assembler.movsxd_rr(src, dest);
1827     }
1828
1829     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1830     {
1831         m_assembler.movl_rr(src, dest);
1832     }
1833
1834     void zeroExtend32ToPtr(TrustedImm32 src, RegisterID dest)
1835     {
1836         m_assembler.movl_i32r(src.m_value, dest);
1837     }
1838 #else
1839     void move(RegisterID src, RegisterID dest)
1840     {
1841         if (src != dest)
1842             m_assembler.movl_rr(src, dest);
1843     }
1844
1845     void move(TrustedImmPtr imm, RegisterID dest)
1846     {
1847         if (!imm.m_value)
1848             m_assembler.xorl_rr(dest, dest);
1849         else
1850             m_assembler.movl_i32r(imm.asIntptr(), dest);
1851     }
1852
1853     void moveConditionallyDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID src, RegisterID dest)
1854     {
1855         ASSERT(isSSE2Present());
1856
1857         if (cond & DoubleConditionBitInvert)
1858             m_assembler.ucomisd_rr(left, right);
1859         else
1860             m_assembler.ucomisd_rr(right, left);
1861
1862         if (cond == DoubleEqual) {
1863             if (left == right) {
1864                 m_assembler.cmovnpl_rr(src, dest);
1865                 return;
1866             }
1867
1868             Jump isUnordered(m_assembler.jp());
1869             m_assembler.cmovel_rr(src, dest);
1870             isUnordered.link(this);
1871             return;
1872         }
1873
1874         if (cond == DoubleNotEqualOrUnordered) {
1875             if (left == right) {
1876                 m_assembler.cmovpl_rr(src, dest);
1877                 return;
1878             }
1879
1880             m_assembler.cmovpl_rr(src, dest);
1881             m_assembler.cmovnel_rr(src, dest);
1882             return;
1883         }
1884
1885         ASSERT(!(cond & DoubleConditionBitSpecial));
1886         m_assembler.cmovl_rr(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits), src, dest);
1887     }
1888
1889     void swap(RegisterID reg1, RegisterID reg2)
1890     {
1891         if (reg1 != reg2)
1892             m_assembler.xchgl_rr(reg1, reg2);
1893     }
1894
1895     void signExtend32ToPtr(RegisterID src, RegisterID dest)
1896     {
1897         move(src, dest);
1898     }
1899
1900     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1901     {
1902         move(src, dest);
1903     }
1904 #endif
1905
1906     void swap32(RegisterID src, RegisterID dest)
1907     {
1908         m_assembler.xchgl_rr(src, dest);
1909     }
1910
1911     void swap32(RegisterID src, Address dest)
1912     {
1913         m_assembler.xchgl_rm(src, dest.offset, dest.base);
1914     }
1915
1916     void moveConditionally32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID src, RegisterID dest)
1917     {
1918         m_assembler.cmpl_rr(right, left);
1919         cmov(x86Condition(cond), src, dest);
1920     }
1921
1922     void moveConditionally32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1923     {
1924         m_assembler.cmpl_rr(right, left);
1925
1926         if (thenCase != dest && elseCase != dest) {
1927             move(elseCase, dest);
1928             elseCase = dest;
1929         }
1930
1931         if (elseCase == dest)
1932             cmov(x86Condition(cond), thenCase, dest);
1933         else
1934             cmov(x86Condition(invert(cond)), elseCase, dest);
1935     }
1936
1937     void moveConditionally32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1938     {
1939         if (!right.m_value) {
1940             if (auto resultCondition = commuteCompareToZeroIntoTest(cond)) {
1941                 moveConditionallyTest32(*resultCondition, left, left, thenCase, elseCase, dest);
1942                 return;
1943             }
1944         }
1945
1946         m_assembler.cmpl_ir(right.m_value, left);
1947
1948         if (thenCase != dest && elseCase != dest) {
1949             move(elseCase, dest);
1950             elseCase = dest;
1951         }
1952
1953         if (elseCase == dest)
1954             cmov(x86Condition(cond), thenCase, dest);
1955         else
1956             cmov(x86Condition(invert(cond)), elseCase, dest);
1957     }
1958
1959     void moveConditionallyTest32(ResultCondition cond, RegisterID testReg, RegisterID mask, RegisterID src, RegisterID dest)
1960     {
1961         m_assembler.testl_rr(testReg, mask);
1962         cmov(x86Condition(cond), src, dest);
1963     }
1964
1965     void moveConditionallyTest32(ResultCondition cond, RegisterID left, RegisterID right, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1966     {
1967         ASSERT(isInvertible(cond));
1968         ASSERT_WITH_MESSAGE(cond != Overflow, "TEST does not set the Overflow Flag.");
1969
1970         m_assembler.testl_rr(right, left);
1971
1972         if (thenCase != dest && elseCase != dest) {
1973             move(elseCase, dest);
1974             elseCase = dest;
1975         }
1976
1977         if (elseCase == dest)
1978             cmov(x86Condition(cond), thenCase, dest);
1979         else
1980             cmov(x86Condition(invert(cond)), elseCase, dest);
1981     }
1982
1983     void moveConditionallyTest32(ResultCondition cond, RegisterID testReg, TrustedImm32 mask, RegisterID src, RegisterID dest)
1984     {
1985         test32(testReg, mask);
1986         cmov(x86Condition(cond), src, dest);
1987     }
1988
1989     void moveConditionallyTest32(ResultCondition cond, RegisterID testReg, TrustedImm32 mask, RegisterID thenCase, RegisterID elseCase, RegisterID dest)
1990     {
1991         ASSERT(isInvertible(cond));
1992         ASSERT_WITH_MESSAGE(cond != Overflow, "TEST does not set the Overflow Flag.");
1993
1994         test32(testReg, mask);
1995
1996         if (thenCase != dest && elseCase != dest) {
1997             move(elseCase, dest);
1998             elseCase = dest;
1999         }
2000
2001         if (elseCase == dest)
2002             cmov(x86Condition(cond), thenCase, dest);
2003         else
2004             cmov(x86Condition(invert(cond)), elseCase, dest);
2005     }
2006
2007     template<typename LeftType, typename RightType>
2008     void moveDoubleConditionally32(RelationalCondition cond, LeftType left, RightType right, FPRegisterID thenCase, FPRegisterID elseCase, FPRegisterID dest)
2009     {
2010         static_assert(!std::is_same<LeftType, FPRegisterID>::value && !std::is_same<RightType, FPRegisterID>::value, "One of the tested argument could be aliased on dest. Use moveDoubleConditionallyDouble().");
2011
2012         if (thenCase != dest && elseCase != dest) {
2013             moveDouble(elseCase, dest);
2014             elseCase = dest;
2015         }
2016
2017         if (elseCase == dest) {
2018             Jump falseCase = branch32(invert(cond), left, right);
2019             moveDouble(thenCase, dest);
2020             falseCase.link(this);
2021         } else {
2022             Jump trueCase = branch32(cond, left, right);
2023             moveDouble(elseCase, dest);
2024             trueCase.link(this);
2025         }
2026     }
2027
2028     template<typename TestType, typename MaskType>
2029     void moveDoubleConditionallyTest32(ResultCondition cond, TestType test, MaskType mask, FPRegisterID thenCase, FPRegisterID elseCase, FPRegisterID dest)
2030     {
2031         static_assert(!std::is_same<TestType, FPRegisterID>::value && !std::is_same<MaskType, FPRegisterID>::value, "One of the tested argument could be aliased on dest. Use moveDoubleConditionallyDouble().");
2032
2033         if (elseCase == dest && isInvertible(cond)) {
2034             Jump falseCase = branchTest32(invert(cond), test, mask);
2035             moveDouble(thenCase, dest);
2036             falseCase.link(this);
2037         } else if (thenCase == dest) {
2038             Jump trueCase = branchTest32(cond, test, mask);
2039             moveDouble(elseCase, dest);
2040             trueCase.link(this);
2041         }
2042
2043         Jump trueCase = branchTest32(cond, test, mask);
2044         moveDouble(elseCase, dest);
2045         Jump falseCase = jump();
2046         trueCase.link(this);
2047         moveDouble(thenCase, dest);
2048         falseCase.link(this);
2049     }
2050
2051     void moveDoubleConditionallyDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, FPRegisterID thenCase, FPRegisterID elseCase, FPRegisterID dest)
2052     {
2053         if (elseCase == dest) {
2054             Jump falseCase = branchDouble(invert(cond), left, right);
2055             moveDouble(thenCase, dest);
2056             falseCase.link(this);
2057         } else if (thenCase == dest) {
2058             Jump trueCase = branchDouble(cond, left, right);
2059             moveDouble(elseCase, dest);
2060             trueCase.link(this);
2061         } else {
2062             Jump trueCase = branchDouble(cond, left, right);
2063             moveDouble(elseCase, dest);
2064             Jump falseCase = jump();
2065             trueCase.link(this);
2066             moveDouble(thenCase, dest);
2067             falseCase.link(this);
2068         }
2069     }
2070
2071     void moveDoubleConditionallyFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, FPRegisterID thenCase, FPRegisterID elseCase, FPRegisterID dest)
2072     {
2073         if (elseCase == dest) {
2074             Jump falseCase = branchFloat(invert(cond), left, right);
2075             moveDouble(thenCase, dest);
2076             falseCase.link(this);
2077         } else if (thenCase == dest) {
2078             Jump trueCase = branchFloat(cond, left, right);
2079             moveDouble(elseCase, dest);
2080             trueCase.link(this);
2081         } else {
2082             Jump trueCase = branchFloat(cond, left, right);
2083             moveDouble(elseCase, dest);
2084             Jump falseCase = jump();
2085             trueCase.link(this);
2086             moveDouble(thenCase, dest);
2087             falseCase.link(this);
2088         }
2089     }
2090
2091     // Forwards / external control flow operations:
2092     //
2093     // This set of jump and conditional branch operations return a Jump
2094     // object which may linked at a later point, allow forwards jump,
2095     // or jumps that will require external linkage (after the code has been
2096     // relocated).
2097     //
2098     // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
2099     // respecitvely, for unsigned comparisons the names b, a, be, and ae are
2100     // used (representing the names 'below' and 'above').
2101     //
2102     // Operands to the comparision are provided in the expected order, e.g.
2103     // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
2104     // treated as a signed 32bit value, is less than or equal to 5.
2105     //
2106     // jz and jnz test whether the first operand is equal to zero, and take
2107     // an optional second operand of a mask under which to perform the test.
2108
2109 public:
2110     Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
2111     {
2112         m_assembler.cmpb_im(right.m_value, left.offset, left.base);
2113         return Jump(m_assembler.jCC(x86Condition(cond)));
2114     }
2115
2116     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
2117     {
2118         m_assembler.cmpl_rr(right, left);
2119         return Jump(m_assembler.jCC(x86Condition(cond)));
2120     }
2121
2122     Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
2123     {
2124         if (!right.m_value) {
2125             if (auto resultCondition = commuteCompareToZeroIntoTest(cond))
2126                 return branchTest32(*resultCondition, left, left);
2127         }
2128
2129         m_assembler.cmpl_ir(right.m_value, left);
2130         return Jump(m_assembler.jCC(x86Condition(cond)));
2131     }
2132     
2133     Jump branch32(RelationalCondition cond, RegisterID left, Address right)
2134     {
2135         m_assembler.cmpl_mr(right.offset, right.base, left);
2136         return Jump(m_assembler.jCC(x86Condition(cond)));
2137     }
2138     
2139     Jump branch32(RelationalCondition cond, Address left, RegisterID right)
2140     {
2141         m_assembler.cmpl_rm(right, left.offset, left.base);
2142         return Jump(m_assembler.jCC(x86Condition(cond)));
2143     }
2144
2145     Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
2146     {
2147         m_assembler.cmpl_im(right.m_value, left.offset, left.base);
2148         return Jump(m_assembler.jCC(x86Condition(cond)));
2149     }
2150
2151     Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
2152     {
2153         m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
2154         return Jump(m_assembler.jCC(x86Condition(cond)));
2155     }
2156
2157     Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
2158     {
2159         return branch32(cond, left, right);
2160     }
2161
2162     Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
2163     {
2164         m_assembler.testl_rr(reg, mask);
2165         return Jump(m_assembler.jCC(x86Condition(cond)));
2166     }
2167
2168     void test32(RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
2169     {
2170         if (mask.m_value == -1)
2171             m_assembler.testl_rr(reg, reg);
2172         else if (!(mask.m_value & ~0xff) && reg < X86Registers::esp) { // Using esp and greater as a byte register yields the upper half of the 16 bit registers ax, cx, dx and bx, e.g. esp, register 4, is actually ah.
2173             if (mask.m_value == 0xff)
2174                 m_assembler.testb_rr(reg, reg);
2175             else
2176                 m_assembler.testb_i8r(mask.m_value, reg);
2177         } else
2178             m_assembler.testl_i32r(mask.m_value, reg);
2179     }
2180
2181     Jump branch(ResultCondition cond)
2182     {
2183         return Jump(m_assembler.jCC(x86Condition(cond)));
2184     }
2185
2186     Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
2187     {
2188         test32(reg, mask);
2189         return branch(cond);
2190     }
2191
2192     Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
2193     {
2194         generateTest32(address, mask);
2195         return Jump(m_assembler.jCC(x86Condition(cond)));
2196     }
2197
2198     Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
2199     {
2200         if (mask.m_value == -1)
2201             m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
2202         else
2203             m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
2204         return Jump(m_assembler.jCC(x86Condition(cond)));
2205     }
2206     
2207     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
2208     {
2209         // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
2210         ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
2211         if (mask.m_value == -1)
2212             m_assembler.cmpb_im(0, address.offset, address.base);
2213         else
2214             m_assembler.testb_im(mask.m_value, address.offset, address.base);
2215         return Jump(m_assembler.jCC(x86Condition(cond)));
2216     }
2217     
2218     Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
2219     {
2220         // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
2221         ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
2222         if (mask.m_value == -1)
2223             m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale);
2224         else
2225             m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale);
2226         return Jump(m_assembler.jCC(x86Condition(cond)));
2227     }
2228
2229     Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
2230     {
2231         ASSERT(std::numeric_limits<int8_t>::min() <= right.m_value && right.m_value <= std::numeric_limits<int8_t>::max());
2232
2233         m_assembler.cmpb_im(right.m_value, left.offset, left.base, left.index, left.scale);
2234         return Jump(m_assembler.jCC(x86Condition(cond)));
2235     }
2236
2237     Jump jump()
2238     {
2239         return Jump(m_assembler.jmp());
2240     }
2241
2242     void jump(RegisterID target)
2243     {
2244         m_assembler.jmp_r(target);
2245     }
2246
2247     // Address is a memory location containing the address to jump to
2248     void jump(Address address)
2249     {
2250         m_assembler.jmp_m(address.offset, address.base);
2251     }
2252
2253
2254     // Arithmetic control flow operations:
2255     //
2256     // This set of conditional branch operations branch based
2257     // on the result of an arithmetic operation.  The operation
2258     // is performed as normal, storing the result.
2259     //
2260     // * jz operations branch if the result is zero.
2261     // * jo operations branch if the (signed) arithmetic
2262     //   operation caused an overflow to occur.
2263     
2264     Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
2265     {
2266         add32(src, dest);
2267         return Jump(m_assembler.jCC(x86Condition(cond)));
2268     }
2269
2270     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
2271     {
2272         add32(imm, dest);
2273         return Jump(m_assembler.jCC(x86Condition(cond)));
2274     }
2275     
2276     Jump branchAdd32(ResultCondition cond, TrustedImm32 src, Address dest)
2277     {
2278         add32(src, dest);
2279         return Jump(m_assembler.jCC(x86Condition(cond)));
2280     }
2281
2282     Jump branchAdd32(ResultCondition cond, RegisterID src, Address dest)
2283     {
2284         add32(src, dest);
2285         return Jump(m_assembler.jCC(x86Condition(cond)));
2286     }
2287
2288     Jump branchAdd32(ResultCondition cond, Address src, RegisterID dest)
2289     {
2290         add32(src, dest);
2291         return Jump(m_assembler.jCC(x86Condition(cond)));
2292     }
2293
2294     Jump branchAdd32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2295     {
2296         if (src1 == dest)
2297             return branchAdd32(cond, src2, dest);
2298         move32IfNeeded(src2, dest);
2299         return branchAdd32(cond, src1, dest);
2300     }
2301
2302     Jump branchAdd32(ResultCondition cond, Address op1, RegisterID op2, RegisterID dest)
2303     {
2304         if (op2 == dest)
2305             return branchAdd32(cond, op1, dest);
2306         if (op1.base == dest) {
2307             load32(op1, dest);
2308             return branchAdd32(cond, op2, dest);
2309         }
2310         zeroExtend32ToPtr(op2, dest);
2311         return branchAdd32(cond, op1, dest);
2312     }
2313
2314     Jump branchAdd32(ResultCondition cond, RegisterID src1, Address src2, RegisterID dest)
2315     {
2316         return branchAdd32(cond, src2, src1, dest);
2317     }
2318
2319     Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
2320     {
2321         move32IfNeeded(src, dest);
2322         return branchAdd32(cond, imm, dest);
2323     }
2324
2325     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
2326     {
2327         mul32(src, dest);
2328         if (cond != Overflow)
2329             m_assembler.testl_rr(dest, dest);
2330         return Jump(m_assembler.jCC(x86Condition(cond)));
2331     }
2332
2333     Jump branchMul32(ResultCondition cond, Address src, RegisterID dest)
2334     {
2335         mul32(src, dest);
2336         if (cond != Overflow)
2337             m_assembler.testl_rr(dest, dest);
2338         return Jump(m_assembler.jCC(x86Condition(cond)));
2339     }
2340     
2341     Jump branchMul32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
2342     {
2343         mul32(imm, src, dest);
2344         if (cond != Overflow)
2345             m_assembler.testl_rr(dest, dest);
2346         return Jump(m_assembler.jCC(x86Condition(cond)));
2347     }
2348     
2349     Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2350     {
2351         if (src1 == dest)
2352             return branchMul32(cond, src2, dest);
2353         move32IfNeeded(src2, dest);
2354         return branchMul32(cond, src1, dest);
2355     }
2356
2357     Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
2358     {
2359         sub32(src, dest);
2360         return Jump(m_assembler.jCC(x86Condition(cond)));
2361     }
2362     
2363     Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
2364     {
2365         sub32(imm, dest);
2366         return Jump(m_assembler.jCC(x86Condition(cond)));
2367     }
2368
2369     Jump branchSub32(ResultCondition cond, TrustedImm32 imm, Address dest)
2370     {
2371         sub32(imm, dest);
2372         return Jump(m_assembler.jCC(x86Condition(cond)));
2373     }
2374
2375     Jump branchSub32(ResultCondition cond, RegisterID src, Address dest)
2376     {
2377         sub32(src, dest);
2378         return Jump(m_assembler.jCC(x86Condition(cond)));
2379     }
2380
2381     Jump branchSub32(ResultCondition cond, Address src, RegisterID dest)
2382     {
2383         sub32(src, dest);
2384         return Jump(m_assembler.jCC(x86Condition(cond)));
2385     }
2386
2387     Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
2388     {
2389         // B := A - B is invalid.
2390         ASSERT(src1 == dest || src2 != dest);
2391
2392         move32IfNeeded(src1, dest);
2393         return branchSub32(cond, src2, dest);
2394     }
2395
2396     Jump branchSub32(ResultCondition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest)
2397     {
2398         move32IfNeeded(src1, dest);
2399         return branchSub32(cond, src2, dest);
2400     }
2401
2402     Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
2403     {
2404         neg32(srcDest);
2405         return Jump(m_assembler.jCC(x86Condition(cond)));
2406     }
2407
2408     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
2409     {
2410         or32(src, dest);
2411         return Jump(m_assembler.jCC(x86Condition(cond)));
2412     }
2413
2414
2415     // Miscellaneous operations:
2416
2417     void breakpoint()
2418     {
2419         m_assembler.int3();
2420     }
2421
2422     Call nearTailCall()
2423     {
2424         return Call(m_assembler.jmp(), Call::LinkableNearTail);
2425     }
2426
2427     Call nearCall()
2428     {
2429         return Call(m_assembler.call(), Call::LinkableNear);
2430     }
2431
2432     Call call(RegisterID target)
2433     {
2434         return Call(m_assembler.call(target), Call::None);
2435     }
2436
2437     void call(Address address)
2438     {
2439         m_assembler.call_m(address.offset, address.base);
2440     }
2441
2442     void ret()
2443     {
2444         m_assembler.ret();
2445     }
2446
2447     void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
2448     {
2449         m_assembler.cmpb_im(right.m_value, left.offset, left.base);
2450         set32(x86Condition(cond), dest);
2451     }
2452     
2453     void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
2454     {
2455         m_assembler.cmpl_rr(right, left);
2456         set32(x86Condition(cond), dest);
2457     }
2458
2459     void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
2460     {
2461         if (!right.m_value) {
2462             if (auto resultCondition = commuteCompareToZeroIntoTest(cond)) {
2463                 test32(*resultCondition, left, left, dest);
2464                 return;
2465             }
2466         }
2467
2468         m_assembler.cmpl_ir(right.m_value, left);
2469         set32(x86Condition(cond), dest);
2470     }
2471
2472     // FIXME:
2473     // The mask should be optional... perhaps the argument order should be
2474     // dest-src, operations always have a dest? ... possibly not true, considering
2475     // asm ops like test, or pseudo ops like pop().
2476
2477     void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
2478     {
2479         if (mask.m_value == -1)
2480             m_assembler.cmpb_im(0, address.offset, address.base);
2481         else
2482             m_assembler.testb_im(mask.m_value, address.offset, address.base);
2483         set32(x86Condition(cond), dest);
2484     }
2485
2486     void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
2487     {
2488         generateTest32(address, mask);
2489         set32(x86Condition(cond), dest);
2490     }
2491
2492     void test32(ResultCondition cond, RegisterID reg, RegisterID mask, RegisterID dest)
2493     {
2494         m_assembler.testl_rr(reg, mask);
2495         set32(x86Condition(cond), dest);
2496     }
2497
2498     void test32(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
2499     {
2500         test32(reg, mask);
2501         set32(x86Condition(cond), dest);
2502     }
2503
2504     void setCarry(RegisterID dest)
2505     {
2506         set32(X86Assembler::ConditionC, dest);
2507     }
2508
2509     // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
2510     static RelationalCondition invert(RelationalCondition cond)
2511     {
2512         return static_cast<RelationalCondition>(cond ^ 1);
2513     }
2514
2515     static DoubleCondition invert(DoubleCondition cond)
2516     {
2517         switch (cond) {
2518         case DoubleEqual:
2519             return DoubleNotEqualOrUnordered;
2520         case DoubleNotEqual:
2521             return DoubleEqualOrUnordered;
2522         case DoubleGreaterThan:
2523             return DoubleLessThanOrEqualOrUnordered;
2524         case DoubleGreaterThanOrEqual:
2525             return DoubleLessThanOrUnordered;
2526         case DoubleLessThan:
2527             return DoubleGreaterThanOrEqualOrUnordered;
2528         case DoubleLessThanOrEqual:
2529             return DoubleGreaterThanOrUnordered;
2530         case DoubleEqualOrUnordered:
2531             return DoubleNotEqual;
2532         case DoubleNotEqualOrUnordered:
2533             return DoubleEqual;
2534         case DoubleGreaterThanOrUnordered:
2535             return DoubleLessThanOrEqual;
2536         case DoubleGreaterThanOrEqualOrUnordered:
2537             return DoubleLessThan;
2538         case DoubleLessThanOrUnordered:
2539             return DoubleGreaterThanOrEqual;
2540         case DoubleLessThanOrEqualOrUnordered:
2541             return DoubleGreaterThan;
2542         }
2543         RELEASE_ASSERT_NOT_REACHED();
2544         return DoubleEqual; // make compiler happy
2545     }
2546
2547     static bool isInvertible(ResultCondition cond)
2548     {
2549         switch (cond) {
2550         case Zero:
2551         case NonZero:
2552         case Signed:
2553         case PositiveOrZero:
2554             return true;
2555         default:
2556             return false;
2557         }
2558     }
2559
2560     static ResultCondition invert(ResultCondition cond)
2561     {
2562         switch (cond) {
2563         case Zero:
2564             return NonZero;
2565         case NonZero:
2566             return Zero;
2567         case Signed:
2568             return PositiveOrZero;
2569         case PositiveOrZero:
2570             return Signed;
2571         default:
2572             RELEASE_ASSERT_NOT_REACHED();
2573             return Zero; // Make compiler happy for release builds.
2574         }
2575     }
2576
2577     static Optional<ResultCondition> commuteCompareToZeroIntoTest(RelationalCondition cond)
2578     {
2579         switch (cond) {
2580         case Equal:
2581             return Zero;
2582         case NotEqual:
2583             return NonZero;
2584         case LessThan:
2585             return Signed;
2586         case GreaterThanOrEqual:
2587             return PositiveOrZero;
2588             break;
2589         default:
2590             return Nullopt;
2591         }
2592     }
2593
2594     void nop()
2595     {
2596         m_assembler.nop();
2597     }
2598     
2599     void memoryFence()
2600     {
2601         m_assembler.mfence();
2602     }
2603
2604     static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
2605     {
2606         X86Assembler::replaceWithJump(instructionStart.executableAddress(), destination.executableAddress());
2607     }
2608     
2609     static ptrdiff_t maxJumpReplacementSize()
2610     {
2611         return X86Assembler::maxJumpReplacementSize();
2612     }
2613
2614     static bool supportsFloatingPointRounding()
2615     {
2616         if (s_sse4_1CheckState == CPUIDCheckState::NotChecked)
2617             updateEax1EcxFlags();
2618         return s_sse4_1CheckState == CPUIDCheckState::Set;
2619     }
2620
2621     static bool supportsAVX()
2622     {
2623         if (s_avxCheckState == CPUIDCheckState::NotChecked)
2624             updateEax1EcxFlags();
2625         return s_avxCheckState == CPUIDCheckState::Set;
2626     }
2627
2628     static void updateEax1EcxFlags()
2629     {
2630         int flags = 0;
2631 #if COMPILER(MSVC)
2632         int cpuInfo[4];
2633         __cpuid(cpuInfo, 0x1);
2634         flags = cpuInfo[2];
2635 #elif COMPILER(GCC_OR_CLANG)
2636 #if CPU(X86_64)
2637         asm (
2638             "movl $0x1, %%eax;"
2639             "cpuid;"
2640             "movl %%ecx, %0;"
2641             : "=g" (flags)
2642             :
2643             : "%eax", "%ebx", "%ecx", "%edx"
2644             );
2645 #else
2646         asm (
2647             "movl $0x1, %%eax;"
2648             "pushl %%ebx;"
2649             "cpuid;"
2650             "popl %%ebx;"
2651             "movl %%ecx, %0;"
2652             : "=g" (flags)
2653             :
2654             : "%eax", "%ecx", "%edx"
2655             );
2656 #endif
2657 #endif // COMPILER(GCC_OR_CLANG)
2658         s_sse4_1CheckState = (flags & (1 << 19)) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
2659         s_avxCheckState = (flags & (1 << 28)) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
2660     }
2661
2662 #if ENABLE(MASM_PROBE)
2663     void probe(ProbeFunction, void* arg1, void* arg2);
2664 #endif // ENABLE(MASM_PROBE)
2665
2666 protected:
2667     X86Assembler::Condition x86Condition(RelationalCondition cond)
2668     {
2669         return static_cast<X86Assembler::Condition>(cond);
2670     }
2671
2672     X86Assembler::Condition x86Condition(ResultCondition cond)
2673     {
2674         return static_cast<X86Assembler::Condition>(cond);
2675     }
2676
2677     void set32(X86Assembler::Condition cond, RegisterID dest)
2678     {
2679 #if CPU(X86)
2680         // On 32-bit x86 we can only set the first 4 registers;
2681         // esp..edi are mapped to the 'h' registers!
2682         if (dest >= 4) {
2683             m_assembler.xchgl_rr(dest, X86Registers::eax);
2684             m_assembler.setCC_r(cond, X86Registers::eax);
2685             m_assembler.movzbl_rr(X86Registers::eax, X86Registers::eax);
2686             m_assembler.xchgl_rr(dest, X86Registers::eax);
2687             return;
2688         }
2689 #endif
2690         m_assembler.setCC_r(cond, dest);
2691         m_assembler.movzbl_rr(dest, dest);
2692     }
2693
2694     void cmov(X86Assembler::Condition cond, RegisterID src, RegisterID dest)
2695     {
2696 #if CPU(X86_64)
2697         m_assembler.cmovq_rr(cond, src, dest);
2698 #else
2699         m_assembler.cmovl_rr(cond, src, dest);
2700 #endif
2701     }
2702
2703     static bool supportsLZCNT()
2704     {
2705         if (s_lzcntCheckState == CPUIDCheckState::NotChecked) {
2706             int flags = 0;
2707 #if COMPILER(MSVC)
2708             int cpuInfo[4];
2709             __cpuid(cpuInfo, 0x80000001);
2710             flags = cpuInfo[2];
2711 #elif COMPILER(GCC_OR_CLANG)
2712 #if CPU(X86_64)
2713             asm (
2714                 "movl $0x80000001, %%eax;"
2715                 "cpuid;"
2716                 "movl %%ecx, %0;"
2717                 : "=g" (flags)
2718                 :
2719                 : "%eax", "%ebx", "%ecx", "%edx"
2720                 );
2721 #else
2722             asm (
2723                 "movl $0x80000001, %%eax;"
2724                 "pushl %%ebx;"
2725                 "cpuid;"
2726                 "popl %%ebx;"
2727                 "movl %%ecx, %0;"
2728                 : "=g" (flags)
2729                 :
2730                 : "%eax", "%ecx", "%edx"
2731                 );
2732 #endif
2733 #endif // COMPILER(GCC_OR_CLANG)
2734             s_lzcntCheckState = (flags & 0x20) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
2735         }
2736         return s_lzcntCheckState == CPUIDCheckState::Set;
2737     }
2738
2739 private:
2740     // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
2741     // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
2742     friend class MacroAssemblerX86;
2743
2744     ALWAYS_INLINE void generateTest32(Address address, TrustedImm32 mask = TrustedImm32(-1))
2745     {
2746         if (mask.m_value == -1)
2747             m_assembler.cmpl_im(0, address.offset, address.base);
2748         else if (!(mask.m_value & ~0xff))
2749             m_assembler.testb_im(mask.m_value, address.offset, address.base);
2750         else if (!(mask.m_value & ~0xff00))
2751             m_assembler.testb_im(mask.m_value >> 8, address.offset + 1, address.base);
2752         else if (!(mask.m_value & ~0xff0000))
2753             m_assembler.testb_im(mask.m_value >> 16, address.offset + 2, address.base);
2754         else if (!(mask.m_value & ~0xff000000))
2755             m_assembler.testb_im(mask.m_value >> 24, address.offset + 3, address.base);
2756         else
2757             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
2758     }
2759
2760     // If lzcnt is not available, use this after BSR
2761     // to count the leading zeros.
2762     void clz32AfterBsr(RegisterID dst)
2763     {
2764         Jump srcIsNonZero = m_assembler.jCC(x86Condition(NonZero));
2765         move(TrustedImm32(32), dst);
2766
2767         Jump skipNonZeroCase = jump();
2768         srcIsNonZero.link(this);
2769         xor32(TrustedImm32(0x1f), dst);
2770         skipNonZeroCase.link(this);
2771     }
2772
2773     Jump jumpAfterFloatingPointCompare(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
2774     {
2775         if (cond == DoubleEqual) {
2776             if (left == right)
2777                 return Jump(m_assembler.jnp());
2778             Jump isUnordered(m_assembler.jp());
2779             Jump result = Jump(m_assembler.je());
2780             isUnordered.link(this);
2781             return result;
2782         }
2783         if (cond == DoubleNotEqualOrUnordered) {
2784             if (left == right)
2785                 return Jump(m_assembler.jp());
2786             Jump isUnordered(m_assembler.jp());
2787             Jump isEqual(m_assembler.je());
2788             isUnordered.link(this);
2789             Jump result = jump();
2790             isEqual.link(this);
2791             return result;
2792         }
2793
2794         ASSERT(!(cond & DoubleConditionBitSpecial));
2795         return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits)));
2796     }
2797
2798     // The 32bit Move does not need the REX byte for low registers, making it shorter.
2799     // Use this if the top bits are irrelevant because they will be reset by the next instruction.
2800     void move32IfNeeded(RegisterID src, RegisterID dest)
2801     {
2802         if (src == dest)
2803             return;
2804         m_assembler.movl_rr(src, dest);
2805     }
2806
2807 #if CPU(X86_64)
2808     void moveConditionallyAfterFloatingPointCompare(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID src, RegisterID dest)
2809     {
2810         if (cond == DoubleEqual) {
2811             if (left == right) {
2812                 m_assembler.cmovnpq_rr(src, dest);
2813                 return;
2814             }
2815
2816             Jump isUnordered(m_assembler.jp());
2817             m_assembler.cmoveq_rr(src, dest);
2818             isUnordered.link(this);
2819             return;
2820         }
2821
2822         if (cond == DoubleNotEqualOrUnordered) {
2823             if (left == right) {
2824                 m_assembler.cmovpq_rr(src, dest);
2825                 return;
2826             }
2827
2828             m_assembler.cmovpq_rr(src, dest);
2829             m_assembler.cmovneq_rr(src, dest);
2830             return;
2831         }
2832
2833         ASSERT(!(cond & DoubleConditionBitSpecial));
2834         cmov(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits), src, dest);
2835     }
2836 #endif
2837
2838 #if CPU(X86)
2839 #if OS(MAC_OS_X)
2840
2841     // All X86 Macs are guaranteed to support at least SSE2,
2842     static bool isSSE2Present()
2843     {
2844         return true;
2845     }
2846
2847 #else // OS(MAC_OS_X)
2848
2849     enum SSE2CheckState {
2850         NotCheckedSSE2,
2851         HasSSE2,
2852         NoSSE2
2853     };
2854
2855     static bool isSSE2Present()
2856     {
2857         if (s_sse2CheckState == NotCheckedSSE2) {
2858             // Default the flags value to zero; if the compiler is
2859             // not MSVC or GCC we will read this as SSE2 not present.
2860             int flags = 0;
2861 #if COMPILER(MSVC)
2862             _asm {
2863                 mov eax, 1 // cpuid function 1 gives us the standard feature set
2864                 cpuid;
2865                 mov flags, edx;
2866             }
2867 #elif COMPILER(GCC_OR_CLANG)
2868             asm (
2869                  "movl $0x1, %%eax;"
2870                  "pushl %%ebx;"
2871                  "cpuid;"
2872                  "popl %%ebx;"
2873                  "movl %%edx, %0;"
2874                  : "=g" (flags)
2875                  :
2876                  : "%eax", "%ecx", "%edx"
2877                  );
2878 #endif
2879             static const int SSE2FeatureBit = 1 << 26;
2880             s_sse2CheckState = (flags & SSE2FeatureBit) ? HasSSE2 : NoSSE2;
2881         }
2882         // Only check once.
2883         ASSERT(s_sse2CheckState != NotCheckedSSE2);
2884
2885         return s_sse2CheckState == HasSSE2;
2886     }
2887     
2888     static SSE2CheckState s_sse2CheckState;
2889
2890 #endif // OS(MAC_OS_X)
2891 #elif !defined(NDEBUG) // CPU(X86)
2892
2893     // On x86-64 we should never be checking for SSE2 in a non-debug build,
2894     // but non debug add this method to keep the asserts above happy.
2895     static bool isSSE2Present()
2896     {
2897         return true;
2898     }
2899
2900 #endif
2901
2902     enum class CPUIDCheckState {
2903         NotChecked,
2904         Clear,
2905         Set
2906     };
2907     JS_EXPORT_PRIVATE static CPUIDCheckState s_sse4_1CheckState;
2908     JS_EXPORT_PRIVATE static CPUIDCheckState s_avxCheckState;
2909     static CPUIDCheckState s_lzcntCheckState;
2910 };
2911
2912 } // namespace JSC
2913
2914 #endif // ENABLE(ASSEMBLER)
2915
2916 #endif // MacroAssemblerX86Common_h