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