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