Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / assembler / assembler / MacroAssemblerX86Common.h
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sw=4 et tw=79:
3  *
4  * ***** BEGIN LICENSE BLOCK *****
5  * Copyright (C) 2008 Apple Inc. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
27  * 
28  * ***** END LICENSE BLOCK ***** */
29
30 #ifndef MacroAssemblerX86Common_h
31 #define MacroAssemblerX86Common_h
32
33 #include "assembler/wtf/Platform.h"
34
35 #if ENABLE_ASSEMBLER
36
37 #include "X86Assembler.h"
38 #include "AbstractMacroAssembler.h"
39
40 #if WTF_COMPILER_MSVC
41 #if WTF_CPU_X86_64
42 /* for __cpuid */
43 #include <intrin.h>
44 #endif
45 #endif
46
47 namespace JSC {
48
49 class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
50     static const int DoubleConditionBitInvert = 0x10;
51     static const int DoubleConditionBitSpecial = 0x20;
52     static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
53
54 protected:
55 #if WTF_CPU_X86_64
56     static const X86Registers::RegisterID scratchRegister = X86Registers::r11;
57 #endif
58
59 public:
60
61     enum Condition {
62         Equal = X86Assembler::ConditionE,
63         NotEqual = X86Assembler::ConditionNE,
64         Above = X86Assembler::ConditionA,
65         AboveOrEqual = X86Assembler::ConditionAE,
66         Below = X86Assembler::ConditionB,
67         BelowOrEqual = X86Assembler::ConditionBE,
68         GreaterThan = X86Assembler::ConditionG,
69         GreaterThanOrEqual = X86Assembler::ConditionGE,
70         LessThan = X86Assembler::ConditionL,
71         LessThanOrEqual = X86Assembler::ConditionLE,
72         Overflow = X86Assembler::ConditionO,
73         Signed = X86Assembler::ConditionS,
74         Zero = X86Assembler::ConditionE,
75         NonZero = X86Assembler::ConditionNE
76     };
77
78     enum DoubleCondition {
79         // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
80         DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial,
81         DoubleNotEqual = X86Assembler::ConditionNE,
82         DoubleGreaterThan = X86Assembler::ConditionA,
83         DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
84         DoubleLessThan = X86Assembler::ConditionA | DoubleConditionBitInvert,
85         DoubleLessThanOrEqual = X86Assembler::ConditionAE | DoubleConditionBitInvert,
86         // If either operand is NaN, these conditions always evaluate to true.
87         DoubleEqualOrUnordered = X86Assembler::ConditionE,
88         DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial,
89         DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert,
90         DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert,
91         DoubleLessThanOrUnordered = X86Assembler::ConditionB,
92         DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE
93     };
94     COMPILE_ASSERT(
95         !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
96         DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
97
98     static const RegisterID stackPointerRegister = X86Registers::esp;
99
100     static inline bool CanUse8Bit(RegisterID reg) {
101         return !!((1 << reg) & ~((1 << X86Registers::esp) |
102                                  (1 << X86Registers::edi) |
103                                  (1 << X86Registers::esi) |
104                                  (1 << X86Registers::ebp)));
105     }
106
107     // Integer arithmetic operations:
108     //
109     // Operations are typically two operand - operation(source, srcDst)
110     // For many operations the source may be an Imm32, the srcDst operand
111     // may often be a memory location (explictly described using an Address
112     // object).
113
114     void add32(RegisterID src, RegisterID dest)
115     {
116         m_assembler.addl_rr(src, dest);
117     }
118
119     void add32(Imm32 imm, Address address)
120     {
121         m_assembler.addl_im(imm.m_value, address.offset, address.base);
122     }
123
124     void add32(Imm32 imm, RegisterID dest)
125     {
126         m_assembler.addl_ir(imm.m_value, dest);
127     }
128     
129     void add32(Address src, RegisterID dest)
130     {
131         m_assembler.addl_mr(src.offset, src.base, dest);
132     }
133
134     void add32(RegisterID src, Address dest)
135     {
136         m_assembler.addl_rm(src, dest.offset, dest.base);
137     }
138     
139     void and32(RegisterID src, RegisterID dest)
140     {
141         m_assembler.andl_rr(src, dest);
142     }
143
144     void and32(Imm32 imm, RegisterID dest)
145     {
146         m_assembler.andl_ir(imm.m_value, dest);
147     }
148
149     void and32(RegisterID src, Address dest)
150     {
151         m_assembler.andl_rm(src, dest.offset, dest.base);
152     }
153
154     void and32(Address src, RegisterID dest)
155     {
156         m_assembler.andl_mr(src.offset, src.base, dest);
157     }
158
159     void and32(Imm32 imm, Address address)
160     {
161         m_assembler.andl_im(imm.m_value, address.offset, address.base);
162     }
163
164     void lshift32(Imm32 imm, RegisterID dest)
165     {
166         m_assembler.shll_i8r(imm.m_value, dest);
167     }
168     
169     void lshift32(RegisterID shift_amount, RegisterID dest)
170     {
171         // On x86 we can only shift by ecx; if asked to shift by another register we'll
172         // need rejig the shift amount into ecx first, and restore the registers afterwards.
173         if (shift_amount != X86Registers::ecx) {
174             swap(shift_amount, X86Registers::ecx);
175
176             // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
177             if (dest == shift_amount)
178                 m_assembler.shll_CLr(X86Registers::ecx);
179             // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
180             else if (dest == X86Registers::ecx)
181                 m_assembler.shll_CLr(shift_amount);
182             // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
183             else
184                 m_assembler.shll_CLr(dest);
185         
186             swap(shift_amount, X86Registers::ecx);
187         } else
188             m_assembler.shll_CLr(dest);
189     }
190     
191     void mul32(RegisterID src, RegisterID dest)
192     {
193         m_assembler.imull_rr(src, dest);
194     }
195
196     void mul32(Address src, RegisterID dest)
197     {
198         m_assembler.imull_mr(src.offset, src.base, dest);
199     }
200     
201     void mul32(Imm32 imm, RegisterID src, RegisterID dest)
202     {
203         m_assembler.imull_i32r(src, imm.m_value, dest);
204     }
205
206     void neg32(RegisterID srcDest)
207     {
208         m_assembler.negl_r(srcDest);
209     }
210
211     void neg32(Address srcDest)
212     {
213         m_assembler.negl_m(srcDest.offset, srcDest.base);
214     }
215
216     void not32(RegisterID srcDest)
217     {
218         m_assembler.notl_r(srcDest);
219     }
220
221     void not32(Address srcDest)
222     {
223         m_assembler.notl_m(srcDest.offset, srcDest.base);
224     }
225     
226     void or32(RegisterID src, RegisterID dest)
227     {
228         m_assembler.orl_rr(src, dest);
229     }
230
231     void or32(Imm32 imm, RegisterID dest)
232     {
233         m_assembler.orl_ir(imm.m_value, dest);
234     }
235
236     void or32(RegisterID src, Address dest)
237     {
238         m_assembler.orl_rm(src, dest.offset, dest.base);
239     }
240
241     void or32(Address src, RegisterID dest)
242     {
243         m_assembler.orl_mr(src.offset, src.base, dest);
244     }
245
246     void or32(Imm32 imm, Address address)
247     {
248         m_assembler.orl_im(imm.m_value, address.offset, address.base);
249     }
250
251     void rshift32(RegisterID shift_amount, RegisterID dest)
252     {
253         // On x86 we can only shift by ecx; if asked to shift by another register we'll
254         // need rejig the shift amount into ecx first, and restore the registers afterwards.
255         if (shift_amount != X86Registers::ecx) {
256             swap(shift_amount, X86Registers::ecx);
257
258             // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
259             if (dest == shift_amount)
260                 m_assembler.sarl_CLr(X86Registers::ecx);
261             // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
262             else if (dest == X86Registers::ecx)
263                 m_assembler.sarl_CLr(shift_amount);
264             // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
265             else
266                 m_assembler.sarl_CLr(dest);
267         
268             swap(shift_amount, X86Registers::ecx);
269         } else
270             m_assembler.sarl_CLr(dest);
271     }
272
273     void rshift32(Imm32 imm, RegisterID dest)
274     {
275         m_assembler.sarl_i8r(imm.m_value, dest);
276     }
277     
278     void urshift32(RegisterID shift_amount, RegisterID dest)
279     {
280         // On x86 we can only shift by ecx; if asked to shift by another register we'll
281         // need rejig the shift amount into ecx first, and restore the registers afterwards.
282         if (shift_amount != X86Registers::ecx) {
283             swap(shift_amount, X86Registers::ecx);
284             
285             // E.g. transform "shrl %eax, %eax" -> "xchgl %eax, %ecx; shrl %ecx, %ecx; xchgl %eax, %ecx"
286             if (dest == shift_amount)
287                 m_assembler.shrl_CLr(X86Registers::ecx);
288             // E.g. transform "shrl %eax, %ecx" -> "xchgl %eax, %ecx; shrl %ecx, %eax; xchgl %eax, %ecx"
289             else if (dest == X86Registers::ecx)
290                 m_assembler.shrl_CLr(shift_amount);
291             // E.g. transform "shrl %eax, %ebx" -> "xchgl %eax, %ecx; shrl %ecx, %ebx; xchgl %eax, %ecx"
292             else
293                 m_assembler.shrl_CLr(dest);
294             
295             swap(shift_amount, X86Registers::ecx);
296         } else
297             m_assembler.shrl_CLr(dest);
298     }
299     
300     void urshift32(Imm32 imm, RegisterID dest)
301     {
302         m_assembler.shrl_i8r(imm.m_value, dest);
303     }
304
305     void sub32(RegisterID src, RegisterID dest)
306     {
307         m_assembler.subl_rr(src, dest);
308     }
309     
310     void sub32(Imm32 imm, RegisterID dest)
311     {
312         m_assembler.subl_ir(imm.m_value, dest);
313     }
314     
315     void sub32(Imm32 imm, Address address)
316     {
317         m_assembler.subl_im(imm.m_value, address.offset, address.base);
318     }
319
320     void sub32(Address src, RegisterID dest)
321     {
322         m_assembler.subl_mr(src.offset, src.base, dest);
323     }
324
325     void sub32(RegisterID src, Address dest)
326     {
327         m_assembler.subl_rm(src, dest.offset, dest.base);
328     }
329
330
331     void xor32(RegisterID src, RegisterID dest)
332     {
333         m_assembler.xorl_rr(src, dest);
334     }
335
336     void xor32(Imm32 imm, Address dest)
337     {
338         m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
339     }
340
341     void xor32(Imm32 imm, RegisterID dest)
342     {
343         m_assembler.xorl_ir(imm.m_value, dest);
344     }
345
346     void xor32(RegisterID src, Address dest)
347     {
348         m_assembler.xorl_rm(src, dest.offset, dest.base);
349     }
350
351     void xor32(Address src, RegisterID dest)
352     {
353         m_assembler.xorl_mr(src.offset, src.base, dest);
354     }
355     
356     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
357     {
358         m_assembler.sqrtsd_rr(src, dst);
359     }
360
361     // Memory access operations:
362     //
363     // Loads are of the form load(address, destination) and stores of the form
364     // store(source, address).  The source for a store may be an Imm32.  Address
365     // operand objects to loads and store will be implicitly constructed if a
366     // register is passed.
367
368     void load32(ImplicitAddress address, RegisterID dest)
369     {
370         m_assembler.movl_mr(address.offset, address.base, dest);
371     }
372
373     void load32(BaseIndex address, RegisterID dest)
374     {
375         m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
376     }
377
378     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
379     {
380         load32(address, dest);
381     }
382
383     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
384     {
385         m_assembler.movl_mr_disp32(address.offset, address.base, dest);
386         return DataLabel32(this);
387     }
388
389     void store8(RegisterID src, Address address)
390     {
391         m_assembler.movb_rm(src, address.offset, address.base);
392     }
393
394     void store8(RegisterID src, BaseIndex address)
395     {
396         m_assembler.movb_rm(src, address.offset, address.base, address.index, address.scale);
397     }
398
399     void store16(RegisterID src, Address address)
400     {
401         m_assembler.movw_rm(src, address.offset, address.base);
402     }
403
404     void store16(RegisterID src, BaseIndex address)
405     {
406         m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
407     }
408
409     void load8ZeroExtend(BaseIndex address, RegisterID dest)
410     {
411         m_assembler.movzbl_mr(address.offset, address.base, address.index, address.scale, dest);
412     }
413     
414     void load8ZeroExtend(Address address, RegisterID dest)
415     {
416         m_assembler.movzbl_mr(address.offset, address.base, dest);
417     }
418
419     void load8SignExtend(BaseIndex address, RegisterID dest)
420     {
421         m_assembler.movxbl_mr(address.offset, address.base, address.index, address.scale, dest);
422     }
423     
424     void load8SignExtend(Address address, RegisterID dest)
425     {
426         m_assembler.movxbl_mr(address.offset, address.base, dest);
427     }
428
429     void load16SignExtend(BaseIndex address, RegisterID dest)
430     {
431         m_assembler.movxwl_mr(address.offset, address.base, address.index, address.scale, dest);
432     }
433     
434     void load16SignExtend(Address address, RegisterID dest)
435     {
436         m_assembler.movxwl_mr(address.offset, address.base, dest);
437     }
438
439     void load16(BaseIndex address, RegisterID dest)
440     {
441         m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
442     }
443     
444     void load16(Address address, RegisterID dest)
445     {
446         m_assembler.movzwl_mr(address.offset, address.base, dest);
447     }
448
449     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
450     {
451         m_assembler.movl_rm_disp32(src, address.offset, address.base);
452         return DataLabel32(this);
453     }
454
455     void store32(RegisterID src, ImplicitAddress address)
456     {
457         m_assembler.movl_rm(src, address.offset, address.base);
458     }
459
460     void store32(RegisterID src, BaseIndex address)
461     {
462         m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
463     }
464
465     void store32(Imm32 imm, BaseIndex address)
466     {
467         m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
468     }
469
470     void store16(Imm32 imm, BaseIndex address)
471     {
472         m_assembler.movw_i16m(imm.m_value, address.offset, address.base, address.index, address.scale);
473     }
474
475     void store8(Imm32 imm, BaseIndex address)
476     {
477         m_assembler.movb_i8m(imm.m_value, address.offset, address.base, address.index, address.scale);
478     }
479
480     void store32(Imm32 imm, ImplicitAddress address)
481     {
482         m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
483     }
484
485     void store16(Imm32 imm, ImplicitAddress address)
486     {
487         m_assembler.movw_i16m(imm.m_value, address.offset, address.base);
488     }
489
490     void store8(Imm32 imm, ImplicitAddress address)
491     {
492         m_assembler.movb_i8m(imm.m_value, address.offset, address.base);
493     }
494
495
496     // Floating-point operation:
497     //
498     // Presently only supports SSE, not x87 floating point.
499
500     void moveDouble(FPRegisterID src, FPRegisterID dest)
501     {
502         ASSERT(isSSE2Present());
503         m_assembler.movsd_rr(src, dest);
504     }
505
506     void loadFloat(ImplicitAddress address, FPRegisterID dest)
507     {
508         ASSERT(isSSE2Present());
509         m_assembler.movss_mr(address.offset, address.base, dest);
510         m_assembler.cvtss2sd_rr(dest, dest);
511     }
512
513     void loadFloat(BaseIndex address, FPRegisterID dest)
514     {
515         ASSERT(isSSE2Present());
516         m_assembler.movss_mr(address.offset, address.base, address.index, address.scale, dest);
517         m_assembler.cvtss2sd_rr(dest, dest);
518     }
519
520     void convertDoubleToFloat(FPRegisterID src, FPRegisterID dest)
521     {
522         ASSERT(isSSE2Present());
523         m_assembler.cvtsd2ss_rr(src, dest);
524     }
525
526     void loadDouble(ImplicitAddress address, FPRegisterID dest)
527     {
528         ASSERT(isSSE2Present());
529         m_assembler.movsd_mr(address.offset, address.base, dest);
530     }
531
532     void loadDouble(BaseIndex address, FPRegisterID dest)
533     {
534         ASSERT(isSSE2Present());
535         m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
536     }
537
538     void storeFloat(ImmDouble imm, Address address)
539     {
540         union {
541             float f;
542             uint32 u32;
543         } u;
544         u.f = imm.u.d;
545         store32(Imm32(u.u32), address);
546     }
547
548     void storeFloat(ImmDouble imm, BaseIndex address)
549     {
550         union {
551             float f;
552             uint32 u32;
553         } u;
554         u.f = imm.u.d;
555         store32(Imm32(u.u32), address);
556     }
557
558     void storeDouble(FPRegisterID src, ImplicitAddress address)
559     {
560         ASSERT(isSSE2Present());
561         m_assembler.movsd_rm(src, address.offset, address.base);
562     }
563
564     void storeFloat(FPRegisterID src, ImplicitAddress address)
565     {
566         ASSERT(isSSE2Present());
567         m_assembler.movss_rm(src, address.offset, address.base);
568     }
569
570     void storeDouble(FPRegisterID src, BaseIndex address)
571     {
572         ASSERT(isSSE2Present());
573         m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
574     }
575
576     void storeFloat(FPRegisterID src, BaseIndex address)
577     {
578         ASSERT(isSSE2Present());
579         m_assembler.movss_rm(src, address.offset, address.base, address.index, address.scale);
580     }
581
582     void addDouble(FPRegisterID src, FPRegisterID dest)
583     {
584         ASSERT(isSSE2Present());
585         m_assembler.addsd_rr(src, dest);
586     }
587
588     void addDouble(Address src, FPRegisterID dest)
589     {
590         ASSERT(isSSE2Present());
591         m_assembler.addsd_mr(src.offset, src.base, dest);
592     }
593
594     void divDouble(FPRegisterID src, FPRegisterID dest)
595     {
596         ASSERT(isSSE2Present());
597         m_assembler.divsd_rr(src, dest);
598     }
599
600     void divDouble(Address src, FPRegisterID dest)
601     {
602         ASSERT(isSSE2Present());
603         m_assembler.divsd_mr(src.offset, src.base, dest);
604     }
605
606     void subDouble(FPRegisterID src, FPRegisterID dest)
607     {
608         ASSERT(isSSE2Present());
609         m_assembler.subsd_rr(src, dest);
610     }
611
612     void subDouble(Address src, FPRegisterID dest)
613     {
614         ASSERT(isSSE2Present());
615         m_assembler.subsd_mr(src.offset, src.base, dest);
616     }
617
618     void mulDouble(FPRegisterID src, FPRegisterID dest)
619     {
620         ASSERT(isSSE2Present());
621         m_assembler.mulsd_rr(src, dest);
622     }
623
624     void mulDouble(Address src, FPRegisterID dest)
625     {
626         ASSERT(isSSE2Present());
627         m_assembler.mulsd_mr(src.offset, src.base, dest);
628     }
629
630     void xorDouble(FPRegisterID src, FPRegisterID dest)
631     {
632         ASSERT(isSSE2Present());
633         m_assembler.xorpd_rr(src, dest);
634     }
635
636     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
637     {
638         ASSERT(isSSE2Present());
639         m_assembler.cvtsi2sd_rr(src, dest);
640     }
641
642     void convertInt32ToDouble(Address src, FPRegisterID dest)
643     {
644         ASSERT(isSSE2Present());
645         m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
646     }
647
648     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
649     {
650         ASSERT(isSSE2Present());
651
652         if (cond & DoubleConditionBitInvert)
653             m_assembler.ucomisd_rr(left, right);
654         else
655             m_assembler.ucomisd_rr(right, left);
656
657         if (cond == DoubleEqual) {
658             Jump isUnordered(m_assembler.jp());
659             Jump result = Jump(m_assembler.je());
660             isUnordered.link(this);
661             return result;
662         } else if (cond == DoubleNotEqualOrUnordered) {
663             Jump isUnordered(m_assembler.jp());
664             Jump isEqual(m_assembler.je());
665             isUnordered.link(this);
666             Jump result = jump();
667             isEqual.link(this);
668             return result;
669         }
670
671         ASSERT(!(cond & DoubleConditionBitSpecial));
672         return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits)));
673     }
674
675     // Truncates 'src' to an integer, and places the resulting 'dest'.
676     // If the result is not representable as a 32 bit value, branch.
677     // May also branch for some values that are representable in 32 bits
678     // (specifically, in this case, INT_MIN).
679     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
680     {
681         ASSERT(isSSE2Present());
682         m_assembler.cvttsd2si_rr(src, dest);
683         return branch32(Equal, dest, Imm32(0x80000000));
684     }
685
686     // Convert 'src' to an integer, and places the resulting 'dest'.
687     // If the result is not representable as a 32 bit value, branch.
688     // May also branch for some values that are representable in 32 bits
689     // (specifically, in this case, 0).
690     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
691     {
692         ASSERT(isSSE2Present());
693         m_assembler.cvttsd2si_rr(src, dest);
694
695         // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
696         failureCases.append(branchTest32(Zero, dest));
697
698         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
699         convertInt32ToDouble(dest, fpTemp);
700         m_assembler.ucomisd_rr(fpTemp, src);
701         failureCases.append(m_assembler.jp());
702         failureCases.append(m_assembler.jne());
703     }
704
705     void zeroDouble(FPRegisterID srcDest)
706     {
707         ASSERT(isSSE2Present());
708         m_assembler.xorpd_rr(srcDest, srcDest);
709     }
710
711
712     // Stack manipulation operations:
713     //
714     // The ABI is assumed to provide a stack abstraction to memory,
715     // containing machine word sized units of data.  Push and pop
716     // operations add and remove a single register sized unit of data
717     // to or from the stack.  Peek and poke operations read or write
718     // values on the stack, without moving the current stack position.
719     
720     void pop(RegisterID dest)
721     {
722         m_assembler.pop_r(dest);
723     }
724
725     void push(RegisterID src)
726     {
727         m_assembler.push_r(src);
728     }
729
730     void push(Address address)
731     {
732         m_assembler.push_m(address.offset, address.base);
733     }
734
735     void push(Imm32 imm)
736     {
737         m_assembler.push_i32(imm.m_value);
738     }
739
740
741     // Register move operations:
742     //
743     // Move values in registers.
744
745     void move(Imm32 imm, RegisterID dest)
746     {
747         // Note: on 64-bit the Imm32 value is zero extended into the register, it
748         // may be useful to have a separate version that sign extends the value?
749         if (!imm.m_value)
750             m_assembler.xorl_rr(dest, dest);
751         else
752             m_assembler.movl_i32r(imm.m_value, dest);
753     }
754
755 #if WTF_CPU_X86_64
756     void move(RegisterID src, RegisterID dest)
757     {
758         // Note: on 64-bit this is is a full register move; perhaps it would be
759         // useful to have separate move32 & movePtr, with move32 zero extending?
760         if (src != dest)
761             m_assembler.movq_rr(src, dest);
762     }
763
764     void move(ImmPtr imm, RegisterID dest)
765     {
766         m_assembler.movq_i64r(imm.asIntptr(), dest);
767     }
768
769     void swap(RegisterID reg1, RegisterID reg2)
770     {
771         // XCHG is extremely slow. Don't use XCHG.
772         if (reg1 != reg2) {
773             m_assembler.movq_rr(reg1, scratchRegister);
774             m_assembler.movq_rr(reg2, reg1);
775             m_assembler.movq_rr(scratchRegister, reg2);
776         }
777     }
778
779     void signExtend32ToPtr(RegisterID src, RegisterID dest)
780     {
781         m_assembler.movsxd_rr(src, dest);
782     }
783
784     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
785     {
786         m_assembler.movl_rr(src, dest);
787     }
788 #else
789     void move(RegisterID src, RegisterID dest)
790     {
791         if (src != dest)
792             m_assembler.movl_rr(src, dest);
793     }
794
795     void move(ImmPtr imm, RegisterID dest)
796     {
797         m_assembler.movl_i32r(imm.asIntptr(), dest);
798     }
799
800     void swap(RegisterID reg1, RegisterID reg2)
801     {
802         if (reg1 != reg2)
803             m_assembler.xchgl_rr(reg1, reg2);
804     }
805
806     void signExtend32ToPtr(RegisterID src, RegisterID dest)
807     {
808         move(src, dest);
809     }
810
811     void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
812     {
813         move(src, dest);
814     }
815 #endif
816
817
818     // Forwards / external control flow operations:
819     //
820     // This set of jump and conditional branch operations return a Jump
821     // object which may linked at a later point, allow forwards jump,
822     // or jumps that will require external linkage (after the code has been
823     // relocated).
824     //
825     // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
826     // respecitvely, for unsigned comparisons the names b, a, be, and ae are
827     // used (representing the names 'below' and 'above').
828     //
829     // Operands to the comparision are provided in the expected order, e.g.
830     // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
831     // treated as a signed 32bit value, is less than or equal to 5.
832     //
833     // jz and jnz test whether the first operand is equal to zero, and take
834     // an optional second operand of a mask under which to perform the test.
835
836 public:
837     Jump branch8(Condition cond, Address left, Imm32 right)
838     {
839         m_assembler.cmpb_im(right.m_value, left.offset, left.base);
840         return Jump(m_assembler.jCC(x86Condition(cond)));
841     }
842
843     Jump branch32(Condition cond, RegisterID left, RegisterID right)
844     {
845         m_assembler.cmpl_rr(right, left);
846         return Jump(m_assembler.jCC(x86Condition(cond)));
847     }
848
849     Jump branch32(Condition cond, RegisterID left, Imm32 right)
850     {
851         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
852             m_assembler.testl_rr(left, left);
853         else
854             m_assembler.cmpl_ir(right.m_value, left);
855         return Jump(m_assembler.jCC(x86Condition(cond)));
856     }
857     
858     // Branch based on a 32-bit comparison, forcing the size of the
859     // immediate operand to 32 bits in the native code stream to ensure that
860     // the length of code emitted by this instruction is consistent.
861     Jump branch32FixedLength(Condition cond, RegisterID left, Imm32 right)
862     {
863         m_assembler.cmpl_ir_force32(right.m_value, left);
864         return Jump(m_assembler.jCC(x86Condition(cond)));
865     }
866
867     // Branch and record a label after the comparison.
868     Jump branch32WithPatch(Condition cond, RegisterID left, Imm32 right, DataLabel32 &dataLabel)
869     {
870         // Always use cmpl, since the value is to be patched.
871         m_assembler.cmpl_ir_force32(right.m_value, left);
872         dataLabel = DataLabel32(this);
873         return Jump(m_assembler.jCC(x86Condition(cond)));
874     }
875
876     Jump branch32WithPatch(Condition cond, Address left, Imm32 right, DataLabel32 &dataLabel)
877     {
878         m_assembler.cmpl_im_force32(right.m_value, left.offset, left.base);
879         dataLabel = DataLabel32(this);
880         return Jump(m_assembler.jCC(x86Condition(cond)));
881     }
882
883     Jump branch32(Condition cond, RegisterID left, Address right)
884     {
885         m_assembler.cmpl_mr(right.offset, right.base, left);
886         return Jump(m_assembler.jCC(x86Condition(cond)));
887     }
888     
889     Jump branch32(Condition cond, Address left, RegisterID right)
890     {
891         m_assembler.cmpl_rm(right, left.offset, left.base);
892         return Jump(m_assembler.jCC(x86Condition(cond)));
893     }
894
895     Jump branch32(Condition cond, Address left, Imm32 right)
896     {
897         m_assembler.cmpl_im(right.m_value, left.offset, left.base);
898         return Jump(m_assembler.jCC(x86Condition(cond)));
899     }
900
901     Jump branch32(Condition cond, BaseIndex left, Imm32 right)
902     {
903         m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
904         return Jump(m_assembler.jCC(x86Condition(cond)));
905     }
906
907     Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
908     {
909         return branch32(cond, left, right);
910     }
911
912     Jump branch16(Condition cond, BaseIndex left, RegisterID right)
913     {
914         m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
915         return Jump(m_assembler.jCC(x86Condition(cond)));
916     }
917
918     Jump branch16(Condition cond, BaseIndex left, Imm32 right)
919     {
920         ASSERT(!(right.m_value & 0xFFFF0000));
921
922         m_assembler.cmpw_im(right.m_value, left.offset, left.base, left.index, left.scale);
923         return Jump(m_assembler.jCC(x86Condition(cond)));
924     }
925
926     Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
927     {
928         ASSERT((cond == Zero) || (cond == NonZero));
929         m_assembler.testl_rr(reg, mask);
930         return Jump(m_assembler.jCC(x86Condition(cond)));
931     }
932
933     Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
934     {
935         ASSERT((cond == Zero) || (cond == NonZero));
936         // if we are only interested in the low seven bits, this can be tested with a testb
937         if (mask.m_value == -1)
938             m_assembler.testl_rr(reg, reg);
939         else if (CanUse8Bit(reg) && (mask.m_value & ~0x7f) == 0)
940             m_assembler.testb_i8r(mask.m_value, reg);
941         else
942             m_assembler.testl_i32r(mask.m_value, reg);
943         return Jump(m_assembler.jCC(x86Condition(cond)));
944     }
945
946     Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
947     {
948         ASSERT((cond == Zero) || (cond == NonZero));
949         if (mask.m_value == -1)
950             m_assembler.cmpl_im(0, address.offset, address.base);
951         else
952             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
953         return Jump(m_assembler.jCC(x86Condition(cond)));
954     }
955
956     Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
957     {
958         ASSERT((cond == Zero) || (cond == NonZero));
959         if (mask.m_value == -1)
960             m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
961         else
962             m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
963         return Jump(m_assembler.jCC(x86Condition(cond)));
964     }
965     
966     Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
967     {
968         ASSERT((cond == Zero) || (cond == NonZero));
969         if (mask.m_value == -1)
970             m_assembler.cmpb_im(0, address.offset, address.base);
971         else
972             m_assembler.testb_im(mask.m_value, address.offset, address.base);
973         return Jump(m_assembler.jCC(x86Condition(cond)));
974     }
975     
976     Jump branchTest8(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
977     {
978         ASSERT((cond == Zero) || (cond == NonZero));
979         if (mask.m_value == -1)
980             m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale);
981         else
982             m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale);
983         return Jump(m_assembler.jCC(x86Condition(cond)));
984     }
985
986     Jump jump()
987     {
988         return Jump(m_assembler.jmp());
989     }
990
991     void jump(RegisterID target)
992     {
993         m_assembler.jmp_r(target);
994     }
995
996     // Address is a memory location containing the address to jump to
997     void jump(Address address)
998     {
999         m_assembler.jmp_m(address.offset, address.base);
1000     }
1001
1002     void jump(BaseIndex address)
1003     {
1004         m_assembler.jmp_m(address.offset, address.base, address.index, address.scale);
1005     }
1006
1007     // Arithmetic control flow operations:
1008     //
1009     // This set of conditional branch operations branch based
1010     // on the result of an arithmetic operation.  The operation
1011     // is performed as normal, storing the result.
1012     //
1013     // * jz operations branch if the result is zero.
1014     // * jo operations branch if the (signed) arithmetic
1015     //   operation caused an overflow to occur.
1016     
1017     Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
1018     {
1019         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1020         add32(src, dest);
1021         return Jump(m_assembler.jCC(x86Condition(cond)));
1022     }
1023
1024     Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
1025     {
1026         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1027         add32(imm, dest);
1028         return Jump(m_assembler.jCC(x86Condition(cond)));
1029     }
1030     
1031     Jump branchAdd32(Condition cond, Imm32 src, Address dest)
1032     {
1033         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1034         add32(src, dest);
1035         return Jump(m_assembler.jCC(x86Condition(cond)));
1036     }
1037
1038     Jump branchAdd32(Condition cond, RegisterID src, Address dest)
1039     {
1040         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1041         add32(src, dest);
1042         return Jump(m_assembler.jCC(x86Condition(cond)));
1043     }
1044
1045     Jump branchAdd32(Condition cond, Address src, RegisterID dest)
1046     {
1047         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1048         add32(src, dest);
1049         return Jump(m_assembler.jCC(x86Condition(cond)));
1050     }
1051
1052     Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
1053     {
1054         ASSERT(cond == Overflow);
1055         mul32(src, dest);
1056         return Jump(m_assembler.jCC(x86Condition(cond)));
1057     }
1058
1059     Jump branchMul32(Condition cond, Address src, RegisterID dest)
1060     {
1061         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1062         mul32(src, dest);
1063         return Jump(m_assembler.jCC(x86Condition(cond)));
1064     }
1065     
1066     Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
1067     {
1068         ASSERT(cond == Overflow);
1069         mul32(imm, src, dest);
1070         return Jump(m_assembler.jCC(x86Condition(cond)));
1071     }
1072     
1073     Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
1074     {
1075         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1076         sub32(src, dest);
1077         return Jump(m_assembler.jCC(x86Condition(cond)));
1078     }
1079     
1080     Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
1081     {
1082         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
1083         sub32(imm, dest);
1084         return Jump(m_assembler.jCC(x86Condition(cond)));
1085     }
1086
1087     Jump branchSub32(Condition cond, Imm32 imm, Address dest)
1088     {
1089         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1090         sub32(imm, dest);
1091         return Jump(m_assembler.jCC(x86Condition(cond)));
1092     }
1093
1094     Jump branchSub32(Condition cond, RegisterID src, Address dest)
1095     {
1096         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1097         sub32(src, dest);
1098         return Jump(m_assembler.jCC(x86Condition(cond)));
1099     }
1100
1101     Jump branchSub32(Condition cond, Address src, RegisterID dest)
1102     {
1103         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1104         sub32(src, dest);
1105         return Jump(m_assembler.jCC(x86Condition(cond)));
1106     }
1107
1108     Jump branchNeg32(Condition cond, RegisterID srcDest)
1109     {
1110         ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
1111         neg32(srcDest);
1112         return Jump(m_assembler.jCC(x86Condition(cond)));
1113     }
1114
1115     Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
1116     {
1117         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
1118         or32(src, dest);
1119         return Jump(m_assembler.jCC(x86Condition(cond)));
1120     }
1121
1122
1123     // Miscellaneous operations:
1124
1125     void breakpoint()
1126     {
1127         m_assembler.int3();
1128     }
1129
1130     Call nearCall()
1131     {
1132         return Call(m_assembler.call(), Call::LinkableNear);
1133     }
1134
1135     Call call(RegisterID target)
1136     {
1137         return Call(m_assembler.call(target), Call::None);
1138     }
1139
1140     void call(Address address)
1141     {
1142         m_assembler.call_m(address.offset, address.base);
1143     }
1144
1145     void ret()
1146     {
1147         m_assembler.ret();
1148     }
1149
1150     void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
1151     {
1152         m_assembler.cmpl_rr(right, left);
1153         m_assembler.setCC_r(x86Condition(cond), dest);
1154     }
1155
1156     void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
1157     {
1158         m_assembler.cmpl_mr(left.offset, left.base, right);
1159         m_assembler.setCC_r(x86Condition(cond), dest);
1160     }
1161
1162     void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
1163     {
1164         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1165             m_assembler.testl_rr(left, left);
1166         else
1167             m_assembler.cmpl_ir(right.m_value, left);
1168         m_assembler.setCC_r(x86Condition(cond), dest);
1169     }
1170
1171     void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
1172     {
1173         m_assembler.cmpl_rm(right, left.offset, left.base);
1174         m_assembler.setCC_r(x86Condition(cond), dest);
1175         m_assembler.movzbl_rr(dest, dest);
1176     }
1177
1178     void set32(Condition cond, RegisterID left, Address right, RegisterID dest)
1179     {
1180         m_assembler.cmpl_mr(right.offset, right.base, left);
1181         m_assembler.setCC_r(x86Condition(cond), dest);
1182         m_assembler.movzbl_rr(dest, dest);
1183     }
1184
1185     void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
1186     {
1187         m_assembler.cmpl_rr(right, left);
1188         m_assembler.setCC_r(x86Condition(cond), dest);
1189         m_assembler.movzbl_rr(dest, dest);
1190     }
1191
1192     void set32(Condition cond, Address left, Imm32 right, RegisterID dest)
1193     {
1194         m_assembler.cmpl_im(right.m_value, left.offset, left.base);
1195         m_assembler.setCC_r(x86Condition(cond), dest);
1196         m_assembler.movzbl_rr(dest, dest);
1197     }
1198
1199     void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
1200     {
1201         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1202             m_assembler.testl_rr(left, left);
1203         else
1204             m_assembler.cmpl_ir(right.m_value, left);
1205         m_assembler.setCC_r(x86Condition(cond), dest);
1206         m_assembler.movzbl_rr(dest, dest);
1207     }
1208
1209     // FIXME:
1210     // The mask should be optional... paerhaps the argument order should be
1211     // dest-src, operations always have a dest? ... possibly not true, considering
1212     // asm ops like test, or pseudo ops like pop().
1213
1214     void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
1215     {
1216         if (mask.m_value == -1)
1217             m_assembler.cmpb_im(0, address.offset, address.base);
1218         else
1219             m_assembler.testb_im(mask.m_value, address.offset, address.base);
1220         m_assembler.setCC_r(x86Condition(cond), dest);
1221         m_assembler.movzbl_rr(dest, dest);
1222     }
1223
1224     void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
1225     {
1226         if (mask.m_value == -1)
1227             m_assembler.cmpl_im(0, address.offset, address.base);
1228         else
1229             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
1230         m_assembler.setCC_r(x86Condition(cond), dest);
1231         m_assembler.movzbl_rr(dest, dest);
1232     }
1233
1234     // As the SSE's were introduced in order, the presence of a later SSE implies
1235     // the presence of an earlier SSE. For example, SSE4_2 support implies SSE2 support.
1236     enum SSECheckState {
1237         NotCheckedSSE = 0,
1238         NoSSE = 1,
1239         HasSSE = 2,
1240         HasSSE2 = 3,
1241         HasSSE3 = 4,
1242         HasSSSE3 = 5,
1243         HasSSE4_1 = 6,
1244         HasSSE4_2 = 7
1245     };
1246
1247     static SSECheckState getSSEState()
1248     {
1249         if (s_sseCheckState == NotCheckedSSE) {
1250             MacroAssemblerX86Common::setSSECheckState();
1251         }
1252         // Only check once.
1253         ASSERT(s_sseCheckState != NotCheckedSSE);
1254
1255         return s_sseCheckState;
1256     }
1257
1258 protected:
1259     X86Assembler::Condition x86Condition(Condition cond)
1260     {
1261         return static_cast<X86Assembler::Condition>(cond);
1262     }
1263
1264 private:
1265     friend class MacroAssemblerX86;
1266
1267     static SSECheckState s_sseCheckState;
1268
1269     static void setSSECheckState()
1270     {
1271         // Default the flags value to zero; if the compiler is
1272         // not MSVC or GCC we will read this as SSE2 not present.
1273         volatile int flags_edx = 0;
1274         volatile int flags_ecx = 0;
1275 #if WTF_COMPILER_MSVC
1276 #if WTF_CPU_X86_64
1277         int cpuinfo[4];
1278
1279         __cpuid(cpuinfo, 1);
1280         flags_ecx = cpuinfo[2];
1281         flags_edx = cpuinfo[3];
1282 #else
1283         _asm {
1284             mov eax, 1 // cpuid function 1 gives us the standard feature set
1285             cpuid;
1286             mov flags_ecx, ecx;
1287             mov flags_edx, edx;
1288         }
1289 #endif
1290 #elif WTF_COMPILER_GCC
1291 #if WTF_CPU_X86_64
1292         asm (
1293              "movl $0x1, %%eax;"
1294              "pushq %%rbx;"
1295              "cpuid;"
1296              "popq %%rbx;"
1297              "movl %%ecx, %0;"
1298              "movl %%edx, %1;"
1299              : "=g" (flags_ecx), "=g" (flags_edx)
1300              :
1301              : "%eax", "%ecx", "%edx"
1302              );
1303 #else
1304         asm (
1305              "movl $0x1, %%eax;"
1306              "pushl %%ebx;"
1307              "cpuid;"
1308              "popl %%ebx;"
1309              "movl %%ecx, %0;"
1310              "movl %%edx, %1;"
1311              : "=g" (flags_ecx), "=g" (flags_edx)
1312              :
1313              : "%eax", "%ecx", "%edx"
1314              );
1315 #endif
1316 #elif WTF_COMPILER_SUNPRO
1317 #if WTF_CPU_X86_64
1318         asm (
1319              "movl $0x1, %%eax;"
1320              "pushq %%rbx;"
1321              "cpuid;"
1322              "popq %%rbx;"
1323              "movl %%ecx, (%rsi);"
1324              "movl %%edx, (%rdi);"
1325              :
1326              : "S" (&flags_ecx), "D" (&flags_edx)
1327              : "%eax", "%ecx", "%edx"
1328              );
1329 #else
1330         asm (
1331              "movl $0x1, %eax;"
1332              "pushl %ebx;"
1333              "cpuid;"
1334              "popl %ebx;"
1335              "movl %ecx, (%esi);"
1336              "movl %edx, (%edi);"
1337              :
1338              : "S" (&flags_ecx), "D" (&flags_edx)
1339              : "%eax", "%ecx", "%edx"
1340              );
1341 #endif
1342 #endif
1343         static const int SSEFeatureBit = 1 << 25;
1344         static const int SSE2FeatureBit = 1 << 26;
1345         static const int SSE3FeatureBit = 1 << 0;
1346         static const int SSSE3FeatureBit = 1 << 9;
1347         static const int SSE41FeatureBit = 1 << 19;
1348         static const int SSE42FeatureBit = 1 << 20;
1349         if (flags_ecx & SSE42FeatureBit)
1350             s_sseCheckState = HasSSE4_2;
1351         else if (flags_ecx & SSE41FeatureBit)
1352             s_sseCheckState = HasSSE4_1;
1353         else if (flags_ecx & SSSE3FeatureBit)
1354             s_sseCheckState = HasSSSE3;
1355         else if (flags_ecx & SSE3FeatureBit)
1356             s_sseCheckState = HasSSE3;
1357         else if (flags_edx & SSE2FeatureBit)
1358             s_sseCheckState = HasSSE2;
1359         else if (flags_edx & SSEFeatureBit)
1360             s_sseCheckState = HasSSE;
1361         else
1362             s_sseCheckState = NoSSE;
1363     }
1364
1365 #if WTF_CPU_X86
1366 #if WTF_PLATFORM_MAC
1367
1368     // All X86 Macs are guaranteed to support at least SSE2
1369     static bool isSSEPresent()
1370     {
1371         return true;
1372     }
1373
1374     static bool isSSE2Present()
1375     {
1376         return true;
1377     }
1378
1379 #else // PLATFORM(MAC)
1380
1381     static bool isSSEPresent()
1382     {
1383         if (s_sseCheckState == NotCheckedSSE) {
1384             setSSECheckState();
1385         }
1386         // Only check once.
1387         ASSERT(s_sseCheckState != NotCheckedSSE);
1388
1389         return s_sseCheckState >= HasSSE;
1390     }
1391
1392     static bool isSSE2Present()
1393     {
1394         if (s_sseCheckState == NotCheckedSSE) {
1395             setSSECheckState();
1396         }
1397         // Only check once.
1398         ASSERT(s_sseCheckState != NotCheckedSSE);
1399
1400         return s_sseCheckState >= HasSSE2;
1401     }
1402     
1403
1404 #endif // PLATFORM(MAC)
1405 #elif !defined(NDEBUG) // CPU(X86)
1406
1407     // On x86-64 we should never be checking for SSE2 in a non-debug build,
1408     // but non debug add this method to keep the asserts above happy.
1409     static bool isSSE2Present()
1410     {
1411         return true;
1412     }
1413
1414 #endif
1415     static bool isSSE3Present()
1416     {
1417         if (s_sseCheckState == NotCheckedSSE) {
1418             setSSECheckState();
1419         }
1420         // Only check once.
1421         ASSERT(s_sseCheckState != NotCheckedSSE);
1422
1423         return s_sseCheckState >= HasSSE3;
1424     }
1425
1426     static bool isSSSE3Present()
1427     {
1428         if (s_sseCheckState == NotCheckedSSE) {
1429             setSSECheckState();
1430         }
1431         // Only check once.
1432         ASSERT(s_sseCheckState != NotCheckedSSE);
1433
1434         return s_sseCheckState >= HasSSSE3;
1435     }
1436
1437     static bool isSSE41Present()
1438     {
1439         if (s_sseCheckState == NotCheckedSSE) {
1440             setSSECheckState();
1441         }
1442         // Only check once.
1443         ASSERT(s_sseCheckState != NotCheckedSSE);
1444
1445         return s_sseCheckState >= HasSSE4_1;
1446     }
1447
1448     static bool isSSE42Present()
1449     {
1450         if (s_sseCheckState == NotCheckedSSE) {
1451             setSSECheckState();
1452         }
1453         // Only check once.
1454         ASSERT(s_sseCheckState != NotCheckedSSE);
1455
1456         return s_sseCheckState >= HasSSE4_2;
1457     }
1458 };
1459
1460 } // namespace JSC
1461
1462 #endif // ENABLE(ASSEMBLER)
1463
1464 #endif // MacroAssemblerX86Common_h