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