]> git.saurik.com Git - apple/javascriptcore.git/blob - assembler/MacroAssemblerX86Common.h
2466ac34873677ef5b8276929194e437e1f1efa3
[apple/javascriptcore.git] / 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 public:
38 #if CPU(X86_64)
39 static const X86Registers::RegisterID scratchRegister = X86Registers::r11;
40 #endif
41
42 protected:
43 static const int DoubleConditionBitInvert = 0x10;
44 static const int DoubleConditionBitSpecial = 0x20;
45 static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
46
47 public:
48 typedef X86Assembler::XMMRegisterID XMMRegisterID;
49
50 static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
51 {
52 return value >= -128 && value <= 127;
53 }
54
55 enum RelationalCondition {
56 Equal = X86Assembler::ConditionE,
57 NotEqual = X86Assembler::ConditionNE,
58 Above = X86Assembler::ConditionA,
59 AboveOrEqual = X86Assembler::ConditionAE,
60 Below = X86Assembler::ConditionB,
61 BelowOrEqual = X86Assembler::ConditionBE,
62 GreaterThan = X86Assembler::ConditionG,
63 GreaterThanOrEqual = X86Assembler::ConditionGE,
64 LessThan = X86Assembler::ConditionL,
65 LessThanOrEqual = X86Assembler::ConditionLE
66 };
67
68 enum ResultCondition {
69 Overflow = X86Assembler::ConditionO,
70 Signed = X86Assembler::ConditionS,
71 PositiveOrZero = X86Assembler::ConditionNS,
72 Zero = X86Assembler::ConditionE,
73 NonZero = X86Assembler::ConditionNE
74 };
75
76 enum DoubleCondition {
77 // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
78 DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial,
79 DoubleNotEqual = X86Assembler::ConditionNE,
80 DoubleGreaterThan = X86Assembler::ConditionA,
81 DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
82 DoubleLessThan = X86Assembler::ConditionA | DoubleConditionBitInvert,
83 DoubleLessThanOrEqual = X86Assembler::ConditionAE | DoubleConditionBitInvert,
84 // If either operand is NaN, these conditions always evaluate to true.
85 DoubleEqualOrUnordered = X86Assembler::ConditionE,
86 DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial,
87 DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert,
88 DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert,
89 DoubleLessThanOrUnordered = X86Assembler::ConditionB,
90 DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE,
91 };
92 COMPILE_ASSERT(
93 !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
94 DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
95
96 static const RegisterID stackPointerRegister = X86Registers::esp;
97 static const RegisterID framePointerRegister = X86Registers::ebp;
98
99 static bool canBlind() { return true; }
100 static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
101 static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
102
103 // Integer arithmetic operations:
104 //
105 // Operations are typically two operand - operation(source, srcDst)
106 // For many operations the source may be an TrustedImm32, the srcDst operand
107 // may often be a memory location (explictly described using an Address
108 // object).
109
110 void add32(RegisterID src, RegisterID dest)
111 {
112 m_assembler.addl_rr(src, dest);
113 }
114
115 void add32(TrustedImm32 imm, Address address)
116 {
117 m_assembler.addl_im(imm.m_value, address.offset, address.base);
118 }
119
120 void add32(TrustedImm32 imm, RegisterID dest)
121 {
122 if (imm.m_value == 1)
123 m_assembler.inc_r(dest);
124 else
125 m_assembler.addl_ir(imm.m_value, dest);
126 }
127
128 void add32(Address src, RegisterID dest)
129 {
130 m_assembler.addl_mr(src.offset, src.base, dest);
131 }
132
133 void add32(RegisterID src, Address dest)
134 {
135 m_assembler.addl_rm(src, dest.offset, dest.base);
136 }
137
138 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
139 {
140 m_assembler.leal_mr(imm.m_value, src, dest);
141 }
142
143 void and32(RegisterID src, RegisterID dest)
144 {
145 m_assembler.andl_rr(src, dest);
146 }
147
148 void and32(TrustedImm32 imm, RegisterID dest)
149 {
150 m_assembler.andl_ir(imm.m_value, dest);
151 }
152
153 void and32(RegisterID src, Address dest)
154 {
155 m_assembler.andl_rm(src, dest.offset, dest.base);
156 }
157
158 void and32(Address src, RegisterID dest)
159 {
160 m_assembler.andl_mr(src.offset, src.base, dest);
161 }
162
163 void and32(TrustedImm32 imm, Address address)
164 {
165 m_assembler.andl_im(imm.m_value, address.offset, address.base);
166 }
167
168 void and32(RegisterID op1, RegisterID op2, RegisterID dest)
169 {
170 if (op1 == op2)
171 zeroExtend32ToPtr(op1, dest);
172 else if (op1 == dest)
173 and32(op2, dest);
174 else {
175 move(op2, dest);
176 and32(op1, dest);
177 }
178 }
179
180 void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
181 {
182 move(src, dest);
183 and32(imm, dest);
184 }
185
186 void lshift32(RegisterID shift_amount, RegisterID dest)
187 {
188 ASSERT(shift_amount != dest);
189
190 if (shift_amount == X86Registers::ecx)
191 m_assembler.shll_CLr(dest);
192 else {
193 // On x86 we can only shift by ecx; if asked to shift by another register we'll
194 // need rejig the shift amount into ecx first, and restore the registers afterwards.
195 // If we dest is ecx, then shift the swapped register!
196 swap(shift_amount, X86Registers::ecx);
197 m_assembler.shll_CLr(dest == X86Registers::ecx ? shift_amount : dest);
198 swap(shift_amount, X86Registers::ecx);
199 }
200 }
201
202 void lshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
203 {
204 ASSERT(shift_amount != dest);
205
206 if (src != dest)
207 move(src, dest);
208 lshift32(shift_amount, dest);
209 }
210
211 void lshift32(TrustedImm32 imm, RegisterID dest)
212 {
213 m_assembler.shll_i8r(imm.m_value, dest);
214 }
215
216 void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
217 {
218 if (src != dest)
219 move(src, dest);
220 lshift32(imm, dest);
221 }
222
223 void mul32(RegisterID src, RegisterID dest)
224 {
225 m_assembler.imull_rr(src, dest);
226 }
227
228 void mul32(Address src, RegisterID dest)
229 {
230 m_assembler.imull_mr(src.offset, src.base, dest);
231 }
232
233 void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
234 {
235 m_assembler.imull_i32r(src, imm.m_value, dest);
236 }
237
238 void neg32(RegisterID srcDest)
239 {
240 m_assembler.negl_r(srcDest);
241 }
242
243 void neg32(Address srcDest)
244 {
245 m_assembler.negl_m(srcDest.offset, srcDest.base);
246 }
247
248 void or32(RegisterID src, RegisterID dest)
249 {
250 m_assembler.orl_rr(src, dest);
251 }
252
253 void or32(TrustedImm32 imm, RegisterID dest)
254 {
255 m_assembler.orl_ir(imm.m_value, dest);
256 }
257
258 void or32(RegisterID src, Address dest)
259 {
260 m_assembler.orl_rm(src, dest.offset, dest.base);
261 }
262
263 void or32(Address src, RegisterID dest)
264 {
265 m_assembler.orl_mr(src.offset, src.base, dest);
266 }
267
268 void or32(TrustedImm32 imm, Address address)
269 {
270 m_assembler.orl_im(imm.m_value, address.offset, address.base);
271 }
272
273 void or32(RegisterID op1, RegisterID op2, RegisterID dest)
274 {
275 if (op1 == op2)
276 zeroExtend32ToPtr(op1, dest);
277 else if (op1 == dest)
278 or32(op2, dest);
279 else {
280 move(op2, dest);
281 or32(op1, dest);
282 }
283 }
284
285 void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
286 {
287 move(src, dest);
288 or32(imm, dest);
289 }
290
291 void rshift32(RegisterID shift_amount, RegisterID dest)
292 {
293 ASSERT(shift_amount != dest);
294
295 if (shift_amount == X86Registers::ecx)
296 m_assembler.sarl_CLr(dest);
297 else {
298 // On x86 we can only shift by ecx; if asked to shift by another register we'll
299 // need rejig the shift amount into ecx first, and restore the registers afterwards.
300 // If we dest is ecx, then shift the swapped register!
301 swap(shift_amount, X86Registers::ecx);
302 m_assembler.sarl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
303 swap(shift_amount, X86Registers::ecx);
304 }
305 }
306
307 void rshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
308 {
309 ASSERT(shift_amount != dest);
310
311 if (src != dest)
312 move(src, dest);
313 rshift32(shift_amount, dest);
314 }
315
316 void rshift32(TrustedImm32 imm, RegisterID dest)
317 {
318 m_assembler.sarl_i8r(imm.m_value, dest);
319 }
320
321 void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
322 {
323 if (src != dest)
324 move(src, dest);
325 rshift32(imm, dest);
326 }
327
328 void urshift32(RegisterID shift_amount, RegisterID dest)
329 {
330 ASSERT(shift_amount != dest);
331
332 if (shift_amount == X86Registers::ecx)
333 m_assembler.shrl_CLr(dest);
334 else {
335 // On x86 we can only shift by ecx; if asked to shift by another register we'll
336 // need rejig the shift amount into ecx first, and restore the registers afterwards.
337 // If we dest is ecx, then shift the swapped register!
338 swap(shift_amount, X86Registers::ecx);
339 m_assembler.shrl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
340 swap(shift_amount, X86Registers::ecx);
341 }
342 }
343
344 void urshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
345 {
346 ASSERT(shift_amount != dest);
347
348 if (src != dest)
349 move(src, dest);
350 urshift32(shift_amount, dest);
351 }
352
353 void urshift32(TrustedImm32 imm, RegisterID dest)
354 {
355 m_assembler.shrl_i8r(imm.m_value, dest);
356 }
357
358 void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
359 {
360 if (src != dest)
361 move(src, dest);
362 urshift32(imm, dest);
363 }
364
365 void sub32(RegisterID src, RegisterID dest)
366 {
367 m_assembler.subl_rr(src, dest);
368 }
369
370 void sub32(TrustedImm32 imm, RegisterID dest)
371 {
372 if (imm.m_value == 1)
373 m_assembler.dec_r(dest);
374 else
375 m_assembler.subl_ir(imm.m_value, dest);
376 }
377
378 void sub32(TrustedImm32 imm, Address address)
379 {
380 m_assembler.subl_im(imm.m_value, address.offset, address.base);
381 }
382
383 void sub32(Address src, RegisterID dest)
384 {
385 m_assembler.subl_mr(src.offset, src.base, dest);
386 }
387
388 void sub32(RegisterID src, Address dest)
389 {
390 m_assembler.subl_rm(src, dest.offset, dest.base);
391 }
392
393 void xor32(RegisterID src, RegisterID dest)
394 {
395 m_assembler.xorl_rr(src, dest);
396 }
397
398 void xor32(TrustedImm32 imm, Address dest)
399 {
400 if (imm.m_value == -1)
401 m_assembler.notl_m(dest.offset, dest.base);
402 else
403 m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
404 }
405
406 void xor32(TrustedImm32 imm, RegisterID dest)
407 {
408 if (imm.m_value == -1)
409 m_assembler.notl_r(dest);
410 else
411 m_assembler.xorl_ir(imm.m_value, dest);
412 }
413
414 void xor32(RegisterID src, Address dest)
415 {
416 m_assembler.xorl_rm(src, dest.offset, dest.base);
417 }
418
419 void xor32(Address src, RegisterID dest)
420 {
421 m_assembler.xorl_mr(src.offset, src.base, dest);
422 }
423
424 void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
425 {
426 if (op1 == op2)
427 move(TrustedImm32(0), dest);
428 else if (op1 == dest)
429 xor32(op2, dest);
430 else {
431 move(op2, dest);
432 xor32(op1, dest);
433 }
434 }
435
436 void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
437 {
438 move(src, dest);
439 xor32(imm, dest);
440 }
441
442 void sqrtDouble(FPRegisterID src, FPRegisterID dst)
443 {
444 m_assembler.sqrtsd_rr(src, dst);
445 }
446
447 void absDouble(FPRegisterID src, FPRegisterID dst)
448 {
449 ASSERT(src != dst);
450 static const double negativeZeroConstant = -0.0;
451 loadDouble(TrustedImmPtr(&negativeZeroConstant), dst);
452 m_assembler.andnpd_rr(src, dst);
453 }
454
455 void negateDouble(FPRegisterID src, FPRegisterID dst)
456 {
457 ASSERT(src != dst);
458 static const double negativeZeroConstant = -0.0;
459 loadDouble(TrustedImmPtr(&negativeZeroConstant), dst);
460 m_assembler.xorpd_rr(src, dst);
461 }
462
463
464 // Memory access operations:
465 //
466 // Loads are of the form load(address, destination) and stores of the form
467 // store(source, address). The source for a store may be an TrustedImm32. Address
468 // operand objects to loads and store will be implicitly constructed if a
469 // register is passed.
470
471 void load32(ImplicitAddress address, RegisterID dest)
472 {
473 m_assembler.movl_mr(address.offset, address.base, dest);
474 }
475
476 void load32(BaseIndex address, RegisterID dest)
477 {
478 m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
479 }
480
481 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
482 {
483 load32(address, dest);
484 }
485
486 void load16Unaligned(BaseIndex address, RegisterID dest)
487 {
488 load16(address, dest);
489 }
490
491 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
492 {
493 padBeforePatch();
494 m_assembler.movl_mr_disp32(address.offset, address.base, dest);
495 return DataLabel32(this);
496 }
497
498 DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
499 {
500 padBeforePatch();
501 m_assembler.movl_mr_disp8(address.offset, address.base, dest);
502 return DataLabelCompact(this);
503 }
504
505 static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
506 {
507 ASSERT(isCompactPtrAlignedAddressOffset(value));
508 AssemblerType_T::repatchCompact(dataLabelCompact.dataLocation(), value);
509 }
510
511 DataLabelCompact loadCompactWithAddressOffsetPatch(Address address, RegisterID dest)
512 {
513 padBeforePatch();
514 m_assembler.movl_mr_disp8(address.offset, address.base, dest);
515 return DataLabelCompact(this);
516 }
517
518 void load8(BaseIndex address, RegisterID dest)
519 {
520 m_assembler.movzbl_mr(address.offset, address.base, address.index, address.scale, dest);
521 }
522
523 void load8(ImplicitAddress address, RegisterID dest)
524 {
525 m_assembler.movzbl_mr(address.offset, address.base, dest);
526 }
527
528 void load8Signed(BaseIndex address, RegisterID dest)
529 {
530 m_assembler.movsbl_mr(address.offset, address.base, address.index, address.scale, dest);
531 }
532
533 void load8Signed(ImplicitAddress address, RegisterID dest)
534 {
535 m_assembler.movsbl_mr(address.offset, address.base, dest);
536 }
537
538 void load16(BaseIndex address, RegisterID dest)
539 {
540 m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
541 }
542
543 void load16(Address address, RegisterID dest)
544 {
545 m_assembler.movzwl_mr(address.offset, address.base, dest);
546 }
547
548 void load16Signed(BaseIndex address, RegisterID dest)
549 {
550 m_assembler.movswl_mr(address.offset, address.base, address.index, address.scale, dest);
551 }
552
553 void load16Signed(Address address, RegisterID dest)
554 {
555 m_assembler.movswl_mr(address.offset, address.base, dest);
556 }
557
558 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
559 {
560 padBeforePatch();
561 m_assembler.movl_rm_disp32(src, address.offset, address.base);
562 return DataLabel32(this);
563 }
564
565 void store32(RegisterID src, ImplicitAddress address)
566 {
567 m_assembler.movl_rm(src, address.offset, address.base);
568 }
569
570 void store32(RegisterID src, BaseIndex address)
571 {
572 m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
573 }
574
575 void store32(TrustedImm32 imm, ImplicitAddress address)
576 {
577 m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
578 }
579
580 void store32(TrustedImm32 imm, BaseIndex address)
581 {
582 m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
583 }
584
585 void store8(TrustedImm32 imm, Address address)
586 {
587 ASSERT(-128 <= imm.m_value && imm.m_value < 128);
588 m_assembler.movb_i8m(imm.m_value, address.offset, address.base);
589 }
590
591 void store8(TrustedImm32 imm, BaseIndex address)
592 {
593 ASSERT(-128 <= imm.m_value && imm.m_value < 128);
594 m_assembler.movb_i8m(imm.m_value, address.offset, address.base, address.index, address.scale);
595 }
596
597 static ALWAYS_INLINE RegisterID getUnusedRegister(BaseIndex address)
598 {
599 if (address.base != X86Registers::eax && address.index != X86Registers::eax)
600 return X86Registers::eax;
601
602 if (address.base != X86Registers::ebx && address.index != X86Registers::ebx)
603 return X86Registers::ebx;
604
605 ASSERT(address.base != X86Registers::ecx && address.index != X86Registers::ecx);
606 return X86Registers::ecx;
607 }
608
609 static ALWAYS_INLINE RegisterID getUnusedRegister(Address address)
610 {
611 if (address.base != X86Registers::eax)
612 return X86Registers::eax;
613
614 ASSERT(address.base != X86Registers::edx);
615 return X86Registers::edx;
616 }
617
618 void store8(RegisterID src, BaseIndex address)
619 {
620 #if CPU(X86)
621 // On 32-bit x86 we can only store from the first 4 registers;
622 // esp..edi are mapped to the 'h' registers!
623 if (src >= 4) {
624 // Pick a temporary register.
625 RegisterID temp = getUnusedRegister(address);
626
627 // Swap to the temporary register to perform the store.
628 swap(src, temp);
629 m_assembler.movb_rm(temp, address.offset, address.base, address.index, address.scale);
630 swap(src, temp);
631 return;
632 }
633 #endif
634 m_assembler.movb_rm(src, address.offset, address.base, address.index, address.scale);
635 }
636
637 void store8(RegisterID src, Address address)
638 {
639 #if CPU(X86)
640 // On 32-bit x86 we can only store from the first 4 registers;
641 // esp..edi are mapped to the 'h' registers!
642 if (src >= 4) {
643 // Pick a temporary register.
644 RegisterID temp = getUnusedRegister(address);
645
646 // Swap to the temporary register to perform the store.
647 swap(src, temp);
648 m_assembler.movb_rm(temp, address.offset, address.base);
649 swap(src, temp);
650 return;
651 }
652 #endif
653 m_assembler.movb_rm(src, address.offset, address.base);
654 }
655
656 void store16(RegisterID src, BaseIndex address)
657 {
658 #if CPU(X86)
659 // On 32-bit x86 we can only store from the first 4 registers;
660 // esp..edi are mapped to the 'h' registers!
661 if (src >= 4) {
662 // Pick a temporary register.
663 RegisterID temp = getUnusedRegister(address);
664
665 // Swap to the temporary register to perform the store.
666 swap(src, temp);
667 m_assembler.movw_rm(temp, address.offset, address.base, address.index, address.scale);
668 swap(src, temp);
669 return;
670 }
671 #endif
672 m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
673 }
674
675
676 // Floating-point operation:
677 //
678 // Presently only supports SSE, not x87 floating point.
679
680 void moveDouble(FPRegisterID src, FPRegisterID dest)
681 {
682 ASSERT(isSSE2Present());
683 if (src != dest)
684 m_assembler.movsd_rr(src, dest);
685 }
686
687 void loadDouble(TrustedImmPtr address, FPRegisterID dest)
688 {
689 #if CPU(X86)
690 ASSERT(isSSE2Present());
691 m_assembler.movsd_mr(address.m_value, dest);
692 #else
693 move(address, scratchRegister);
694 loadDouble(scratchRegister, dest);
695 #endif
696 }
697
698 void loadDouble(ImplicitAddress address, FPRegisterID dest)
699 {
700 ASSERT(isSSE2Present());
701 m_assembler.movsd_mr(address.offset, address.base, dest);
702 }
703
704 void loadDouble(BaseIndex address, FPRegisterID dest)
705 {
706 ASSERT(isSSE2Present());
707 m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
708 }
709 void loadFloat(BaseIndex address, FPRegisterID dest)
710 {
711 ASSERT(isSSE2Present());
712 m_assembler.movss_mr(address.offset, address.base, address.index, address.scale, dest);
713 }
714
715 void storeDouble(FPRegisterID src, ImplicitAddress address)
716 {
717 ASSERT(isSSE2Present());
718 m_assembler.movsd_rm(src, address.offset, address.base);
719 }
720
721 void storeDouble(FPRegisterID src, BaseIndex address)
722 {
723 ASSERT(isSSE2Present());
724 m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
725 }
726
727 void storeFloat(FPRegisterID src, BaseIndex address)
728 {
729 ASSERT(isSSE2Present());
730 m_assembler.movss_rm(src, address.offset, address.base, address.index, address.scale);
731 }
732
733 void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
734 {
735 ASSERT(isSSE2Present());
736 m_assembler.cvtsd2ss_rr(src, dst);
737 }
738
739 void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
740 {
741 ASSERT(isSSE2Present());
742 m_assembler.cvtss2sd_rr(src, dst);
743 }
744
745 void addDouble(FPRegisterID src, FPRegisterID dest)
746 {
747 ASSERT(isSSE2Present());
748 m_assembler.addsd_rr(src, dest);
749 }
750
751 void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
752 {
753 ASSERT(isSSE2Present());
754 if (op1 == dest)
755 addDouble(op2, dest);
756 else {
757 moveDouble(op2, dest);
758 addDouble(op1, dest);
759 }
760 }
761
762 void addDouble(Address src, FPRegisterID dest)
763 {
764 ASSERT(isSSE2Present());
765 m_assembler.addsd_mr(src.offset, src.base, dest);
766 }
767
768 void divDouble(FPRegisterID src, FPRegisterID dest)
769 {
770 ASSERT(isSSE2Present());
771 m_assembler.divsd_rr(src, dest);
772 }
773
774 void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
775 {
776 // B := A / B is invalid.
777 ASSERT(op1 == dest || op2 != dest);
778
779 moveDouble(op1, dest);
780 divDouble(op2, dest);
781 }
782
783 void divDouble(Address src, FPRegisterID dest)
784 {
785 ASSERT(isSSE2Present());
786 m_assembler.divsd_mr(src.offset, src.base, dest);
787 }
788
789 void subDouble(FPRegisterID src, FPRegisterID dest)
790 {
791 ASSERT(isSSE2Present());
792 m_assembler.subsd_rr(src, dest);
793 }
794
795 void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
796 {
797 // B := A - B is invalid.
798 ASSERT(op1 == dest || op2 != dest);
799
800 moveDouble(op1, dest);
801 subDouble(op2, dest);
802 }
803
804 void subDouble(Address src, FPRegisterID dest)
805 {
806 ASSERT(isSSE2Present());
807 m_assembler.subsd_mr(src.offset, src.base, dest);
808 }
809
810 void mulDouble(FPRegisterID src, FPRegisterID dest)
811 {
812 ASSERT(isSSE2Present());
813 m_assembler.mulsd_rr(src, dest);
814 }
815
816 void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
817 {
818 ASSERT(isSSE2Present());
819 if (op1 == dest)
820 mulDouble(op2, dest);
821 else {
822 moveDouble(op2, dest);
823 mulDouble(op1, dest);
824 }
825 }
826
827 void mulDouble(Address src, FPRegisterID dest)
828 {
829 ASSERT(isSSE2Present());
830 m_assembler.mulsd_mr(src.offset, src.base, dest);
831 }
832
833 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
834 {
835 ASSERT(isSSE2Present());
836 m_assembler.cvtsi2sd_rr(src, dest);
837 }
838
839 void convertInt32ToDouble(Address src, FPRegisterID dest)
840 {
841 ASSERT(isSSE2Present());
842 m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
843 }
844
845 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
846 {
847 ASSERT(isSSE2Present());
848
849 if (cond & DoubleConditionBitInvert)
850 m_assembler.ucomisd_rr(left, right);
851 else
852 m_assembler.ucomisd_rr(right, left);
853
854 if (cond == DoubleEqual) {
855 if (left == right)
856 return Jump(m_assembler.jnp());
857 Jump isUnordered(m_assembler.jp());
858 Jump result = Jump(m_assembler.je());
859 isUnordered.link(this);
860 return result;
861 } else if (cond == DoubleNotEqualOrUnordered) {
862 if (left == right)
863 return Jump(m_assembler.jp());
864 Jump isUnordered(m_assembler.jp());
865 Jump isEqual(m_assembler.je());
866 isUnordered.link(this);
867 Jump result = jump();
868 isEqual.link(this);
869 return result;
870 }
871
872 ASSERT(!(cond & DoubleConditionBitSpecial));
873 return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits)));
874 }
875
876 // Truncates 'src' to an integer, and places the resulting 'dest'.
877 // If the result is not representable as a 32 bit value, branch.
878 // May also branch for some values that are representable in 32 bits
879 // (specifically, in this case, INT_MIN).
880 enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
881 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
882 {
883 ASSERT(isSSE2Present());
884 m_assembler.cvttsd2si_rr(src, dest);
885 return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
886 }
887
888 void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
889 {
890 ASSERT(isSSE2Present());
891 m_assembler.cvttsd2si_rr(src, dest);
892 }
893
894 #if CPU(X86_64)
895 void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
896 {
897 ASSERT(isSSE2Present());
898 m_assembler.cvttsd2siq_rr(src, dest);
899 }
900 #endif
901
902 // Convert 'src' to an integer, and places the resulting 'dest'.
903 // If the result is not representable as a 32 bit value, branch.
904 // May also branch for some values that are representable in 32 bits
905 // (specifically, in this case, 0).
906 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true)
907 {
908 ASSERT(isSSE2Present());
909 m_assembler.cvttsd2si_rr(src, dest);
910
911 // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
912 if (negZeroCheck)
913 failureCases.append(branchTest32(Zero, dest));
914
915 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
916 convertInt32ToDouble(dest, fpTemp);
917 m_assembler.ucomisd_rr(fpTemp, src);
918 failureCases.append(m_assembler.jp());
919 failureCases.append(m_assembler.jne());
920 }
921
922 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
923 {
924 ASSERT(isSSE2Present());
925 m_assembler.xorpd_rr(scratch, scratch);
926 return branchDouble(DoubleNotEqual, reg, scratch);
927 }
928
929 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
930 {
931 ASSERT(isSSE2Present());
932 m_assembler.xorpd_rr(scratch, scratch);
933 return branchDouble(DoubleEqualOrUnordered, reg, scratch);
934 }
935
936 void lshiftPacked(TrustedImm32 imm, XMMRegisterID reg)
937 {
938 ASSERT(isSSE2Present());
939 m_assembler.psllq_i8r(imm.m_value, reg);
940 }
941
942 void rshiftPacked(TrustedImm32 imm, XMMRegisterID reg)
943 {
944 ASSERT(isSSE2Present());
945 m_assembler.psrlq_i8r(imm.m_value, reg);
946 }
947
948 void orPacked(XMMRegisterID src, XMMRegisterID dst)
949 {
950 ASSERT(isSSE2Present());
951 m_assembler.por_rr(src, dst);
952 }
953
954 void moveInt32ToPacked(RegisterID src, XMMRegisterID dst)
955 {
956 ASSERT(isSSE2Present());
957 m_assembler.movd_rr(src, dst);
958 }
959
960 void movePackedToInt32(XMMRegisterID src, RegisterID dst)
961 {
962 ASSERT(isSSE2Present());
963 m_assembler.movd_rr(src, dst);
964 }
965
966 // Stack manipulation operations:
967 //
968 // The ABI is assumed to provide a stack abstraction to memory,
969 // containing machine word sized units of data. Push and pop
970 // operations add and remove a single register sized unit of data
971 // to or from the stack. Peek and poke operations read or write
972 // values on the stack, without moving the current stack position.
973
974 void pop(RegisterID dest)
975 {
976 m_assembler.pop_r(dest);
977 }
978
979 void push(RegisterID src)
980 {
981 m_assembler.push_r(src);
982 }
983
984 void push(Address address)
985 {
986 m_assembler.push_m(address.offset, address.base);
987 }
988
989 void push(TrustedImm32 imm)
990 {
991 m_assembler.push_i32(imm.m_value);
992 }
993
994
995 // Register move operations:
996 //
997 // Move values in registers.
998
999 void move(TrustedImm32 imm, RegisterID dest)
1000 {
1001 // Note: on 64-bit the TrustedImm32 value is zero extended into the register, it
1002 // may be useful to have a separate version that sign extends the value?
1003 if (!imm.m_value)
1004 m_assembler.xorl_rr(dest, dest);
1005 else
1006 m_assembler.movl_i32r(imm.m_value, dest);
1007 }
1008
1009 #if CPU(X86_64)
1010 void move(RegisterID src, RegisterID dest)
1011 {
1012 // Note: on 64-bit this is is a full register move; perhaps it would be
1013 // useful to have separate move32 & movePtr, with move32 zero extending?
1014 if (src != dest)
1015 m_assembler.movq_rr(src, dest);
1016 }
1017
1018 void move(TrustedImmPtr imm, RegisterID dest)
1019 {
1020 m_assembler.movq_i64r(imm.asIntptr(), dest);
1021 }
1022
1023 void move(TrustedImm64 imm, RegisterID dest)
1024 {
1025 m_assembler.movq_i64r(imm.m_value, dest);
1026 }
1027
1028 void swap(RegisterID reg1, RegisterID reg2)
1029 {
1030 if (reg1 != reg2)
1031 m_assembler.xchgq_rr(reg1, reg2);
1032 }
1033
1034 void signExtend32ToPtr(RegisterID src, RegisterID dest)
1035 {
1036 m_assembler.movsxd_rr(src, dest);
1037 }
1038
1039 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1040 {
1041 m_assembler.movl_rr(src, dest);
1042 }
1043 #else
1044 void move(RegisterID src, RegisterID dest)
1045 {
1046 if (src != dest)
1047 m_assembler.movl_rr(src, dest);
1048 }
1049
1050 void move(TrustedImmPtr imm, RegisterID dest)
1051 {
1052 m_assembler.movl_i32r(imm.asIntptr(), dest);
1053 }
1054
1055 void swap(RegisterID reg1, RegisterID reg2)
1056 {
1057 if (reg1 != reg2)
1058 m_assembler.xchgl_rr(reg1, reg2);
1059 }
1060
1061 void signExtend32ToPtr(RegisterID src, RegisterID dest)
1062 {
1063 move(src, dest);
1064 }
1065
1066 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
1067 {
1068 move(src, dest);
1069 }
1070 #endif
1071
1072
1073 // Forwards / external control flow operations:
1074 //
1075 // This set of jump and conditional branch operations return a Jump
1076 // object which may linked at a later point, allow forwards jump,
1077 // or jumps that will require external linkage (after the code has been
1078 // relocated).
1079 //
1080 // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
1081 // respecitvely, for unsigned comparisons the names b, a, be, and ae are
1082 // used (representing the names 'below' and 'above').
1083 //
1084 // Operands to the comparision are provided in the expected order, e.g.
1085 // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
1086 // treated as a signed 32bit value, is less than or equal to 5.
1087 //
1088 // jz and jnz test whether the first operand is equal to zero, and take
1089 // an optional second operand of a mask under which to perform the test.
1090
1091 public:
1092 Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
1093 {
1094 m_assembler.cmpb_im(right.m_value, left.offset, left.base);
1095 return Jump(m_assembler.jCC(x86Condition(cond)));
1096 }
1097
1098 Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
1099 {
1100 m_assembler.cmpl_rr(right, left);
1101 return Jump(m_assembler.jCC(x86Condition(cond)));
1102 }
1103
1104 Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
1105 {
1106 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1107 m_assembler.testl_rr(left, left);
1108 else
1109 m_assembler.cmpl_ir(right.m_value, left);
1110 return Jump(m_assembler.jCC(x86Condition(cond)));
1111 }
1112
1113 Jump branch32(RelationalCondition cond, RegisterID left, Address right)
1114 {
1115 m_assembler.cmpl_mr(right.offset, right.base, left);
1116 return Jump(m_assembler.jCC(x86Condition(cond)));
1117 }
1118
1119 Jump branch32(RelationalCondition cond, Address left, RegisterID right)
1120 {
1121 m_assembler.cmpl_rm(right, left.offset, left.base);
1122 return Jump(m_assembler.jCC(x86Condition(cond)));
1123 }
1124
1125 Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
1126 {
1127 m_assembler.cmpl_im(right.m_value, left.offset, left.base);
1128 return Jump(m_assembler.jCC(x86Condition(cond)));
1129 }
1130
1131 Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1132 {
1133 m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
1134 return Jump(m_assembler.jCC(x86Condition(cond)));
1135 }
1136
1137 Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1138 {
1139 return branch32(cond, left, right);
1140 }
1141
1142 Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
1143 {
1144 m_assembler.testl_rr(reg, mask);
1145 return Jump(m_assembler.jCC(x86Condition(cond)));
1146 }
1147
1148 void test32(ResultCondition, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
1149 {
1150 if (mask.m_value == -1)
1151 m_assembler.testl_rr(reg, reg);
1152 else if (!(mask.m_value & ~0xff) && reg < X86Registers::esp) { // Using esp and greater as a byte register yields the upper half of the 16 bit registers ax, cx, dx and bx, e.g. esp, register 4, is actually ah.
1153 if (mask.m_value == 0xff)
1154 m_assembler.testb_rr(reg, reg);
1155 else
1156 m_assembler.testb_i8r(mask.m_value, reg);
1157 } else
1158 m_assembler.testl_i32r(mask.m_value, reg);
1159 }
1160
1161 Jump branch(ResultCondition cond)
1162 {
1163 return Jump(m_assembler.jCC(x86Condition(cond)));
1164 }
1165
1166 Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
1167 {
1168 test32(cond, reg, mask);
1169 return branch(cond);
1170 }
1171
1172 Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1173 {
1174 generateTest32(address, mask);
1175 return Jump(m_assembler.jCC(x86Condition(cond)));
1176 }
1177
1178 Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1179 {
1180 if (mask.m_value == -1)
1181 m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
1182 else
1183 m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
1184 return Jump(m_assembler.jCC(x86Condition(cond)));
1185 }
1186
1187 Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
1188 {
1189 // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
1190 ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
1191 if (mask.m_value == -1)
1192 m_assembler.cmpb_im(0, address.offset, address.base);
1193 else
1194 m_assembler.testb_im(mask.m_value, address.offset, address.base);
1195 return Jump(m_assembler.jCC(x86Condition(cond)));
1196 }
1197
1198 Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
1199 {
1200 // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
1201 ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
1202 if (mask.m_value == -1)
1203 m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale);
1204 else
1205 m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale);
1206 return Jump(m_assembler.jCC(x86Condition(cond)));
1207 }
1208
1209 Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
1210 {
1211 ASSERT(!(right.m_value & 0xFFFFFF00));
1212
1213 m_assembler.cmpb_im(right.m_value, left.offset, left.base, left.index, left.scale);
1214 return Jump(m_assembler.jCC(x86Condition(cond)));
1215 }
1216
1217 Jump jump()
1218 {
1219 return Jump(m_assembler.jmp());
1220 }
1221
1222 void jump(RegisterID target)
1223 {
1224 m_assembler.jmp_r(target);
1225 }
1226
1227 // Address is a memory location containing the address to jump to
1228 void jump(Address address)
1229 {
1230 m_assembler.jmp_m(address.offset, address.base);
1231 }
1232
1233
1234 // Arithmetic control flow operations:
1235 //
1236 // This set of conditional branch operations branch based
1237 // on the result of an arithmetic operation. The operation
1238 // is performed as normal, storing the result.
1239 //
1240 // * jz operations branch if the result is zero.
1241 // * jo operations branch if the (signed) arithmetic
1242 // operation caused an overflow to occur.
1243
1244 Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
1245 {
1246 add32(src, dest);
1247 return Jump(m_assembler.jCC(x86Condition(cond)));
1248 }
1249
1250 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1251 {
1252 add32(imm, dest);
1253 return Jump(m_assembler.jCC(x86Condition(cond)));
1254 }
1255
1256 Jump branchAdd32(ResultCondition cond, TrustedImm32 src, Address dest)
1257 {
1258 add32(src, dest);
1259 return Jump(m_assembler.jCC(x86Condition(cond)));
1260 }
1261
1262 Jump branchAdd32(ResultCondition cond, RegisterID src, Address dest)
1263 {
1264 add32(src, dest);
1265 return Jump(m_assembler.jCC(x86Condition(cond)));
1266 }
1267
1268 Jump branchAdd32(ResultCondition cond, Address src, RegisterID dest)
1269 {
1270 add32(src, dest);
1271 return Jump(m_assembler.jCC(x86Condition(cond)));
1272 }
1273
1274 Jump branchAdd32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
1275 {
1276 if (src1 == dest)
1277 return branchAdd32(cond, src2, dest);
1278 move(src2, dest);
1279 return branchAdd32(cond, src1, dest);
1280 }
1281
1282 Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
1283 {
1284 move(src, dest);
1285 return branchAdd32(cond, imm, dest);
1286 }
1287
1288 Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
1289 {
1290 mul32(src, dest);
1291 if (cond != Overflow)
1292 m_assembler.testl_rr(dest, dest);
1293 return Jump(m_assembler.jCC(x86Condition(cond)));
1294 }
1295
1296 Jump branchMul32(ResultCondition cond, Address src, RegisterID dest)
1297 {
1298 mul32(src, dest);
1299 if (cond != Overflow)
1300 m_assembler.testl_rr(dest, dest);
1301 return Jump(m_assembler.jCC(x86Condition(cond)));
1302 }
1303
1304 Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
1305 {
1306 mul32(imm, src, dest);
1307 if (cond != Overflow)
1308 m_assembler.testl_rr(dest, dest);
1309 return Jump(m_assembler.jCC(x86Condition(cond)));
1310 }
1311
1312 Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
1313 {
1314 if (src1 == dest)
1315 return branchMul32(cond, src2, dest);
1316 move(src2, dest);
1317 return branchMul32(cond, src1, dest);
1318 }
1319
1320 Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
1321 {
1322 sub32(src, dest);
1323 return Jump(m_assembler.jCC(x86Condition(cond)));
1324 }
1325
1326 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
1327 {
1328 sub32(imm, dest);
1329 return Jump(m_assembler.jCC(x86Condition(cond)));
1330 }
1331
1332 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, Address dest)
1333 {
1334 sub32(imm, dest);
1335 return Jump(m_assembler.jCC(x86Condition(cond)));
1336 }
1337
1338 Jump branchSub32(ResultCondition cond, RegisterID src, Address dest)
1339 {
1340 sub32(src, dest);
1341 return Jump(m_assembler.jCC(x86Condition(cond)));
1342 }
1343
1344 Jump branchSub32(ResultCondition cond, Address src, RegisterID dest)
1345 {
1346 sub32(src, dest);
1347 return Jump(m_assembler.jCC(x86Condition(cond)));
1348 }
1349
1350 Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
1351 {
1352 // B := A - B is invalid.
1353 ASSERT(src1 == dest || src2 != dest);
1354
1355 move(src1, dest);
1356 return branchSub32(cond, src2, dest);
1357 }
1358
1359 Jump branchSub32(ResultCondition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest)
1360 {
1361 move(src1, dest);
1362 return branchSub32(cond, src2, dest);
1363 }
1364
1365 Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
1366 {
1367 neg32(srcDest);
1368 return Jump(m_assembler.jCC(x86Condition(cond)));
1369 }
1370
1371 Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
1372 {
1373 or32(src, dest);
1374 return Jump(m_assembler.jCC(x86Condition(cond)));
1375 }
1376
1377
1378 // Miscellaneous operations:
1379
1380 void breakpoint()
1381 {
1382 m_assembler.int3();
1383 }
1384
1385 Call nearCall()
1386 {
1387 return Call(m_assembler.call(), Call::LinkableNear);
1388 }
1389
1390 Call call(RegisterID target)
1391 {
1392 return Call(m_assembler.call(target), Call::None);
1393 }
1394
1395 void call(Address address)
1396 {
1397 m_assembler.call_m(address.offset, address.base);
1398 }
1399
1400 void ret()
1401 {
1402 m_assembler.ret();
1403 }
1404
1405 void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
1406 {
1407 m_assembler.cmpb_im(right.m_value, left.offset, left.base);
1408 set32(x86Condition(cond), dest);
1409 }
1410
1411 void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
1412 {
1413 m_assembler.cmpl_rr(right, left);
1414 set32(x86Condition(cond), dest);
1415 }
1416
1417 void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
1418 {
1419 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
1420 m_assembler.testl_rr(left, left);
1421 else
1422 m_assembler.cmpl_ir(right.m_value, left);
1423 set32(x86Condition(cond), dest);
1424 }
1425
1426 // FIXME:
1427 // The mask should be optional... perhaps the argument order should be
1428 // dest-src, operations always have a dest? ... possibly not true, considering
1429 // asm ops like test, or pseudo ops like pop().
1430
1431 void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1432 {
1433 if (mask.m_value == -1)
1434 m_assembler.cmpb_im(0, address.offset, address.base);
1435 else
1436 m_assembler.testb_im(mask.m_value, address.offset, address.base);
1437 set32(x86Condition(cond), dest);
1438 }
1439
1440 void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
1441 {
1442 generateTest32(address, mask);
1443 set32(x86Condition(cond), dest);
1444 }
1445
1446 // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
1447 static RelationalCondition invert(RelationalCondition cond)
1448 {
1449 return static_cast<RelationalCondition>(cond ^ 1);
1450 }
1451
1452 void nop()
1453 {
1454 m_assembler.nop();
1455 }
1456
1457 void memoryFence()
1458 {
1459 m_assembler.mfence();
1460 }
1461
1462 static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
1463 {
1464 X86Assembler::replaceWithJump(instructionStart.executableAddress(), destination.executableAddress());
1465 }
1466
1467 static ptrdiff_t maxJumpReplacementSize()
1468 {
1469 return X86Assembler::maxJumpReplacementSize();
1470 }
1471
1472 #if USE(MASM_PROBE)
1473 struct CPUState {
1474 #define DECLARE_REGISTER(_type, _regName) \
1475 _type _regName;
1476 FOR_EACH_CPU_REGISTER(DECLARE_REGISTER)
1477 #undef DECLARE_REGISTER
1478 };
1479
1480 struct ProbeContext;
1481 typedef void (*ProbeFunction)(struct ProbeContext*);
1482
1483 struct ProbeContext {
1484 ProbeFunction probeFunction;
1485 void* arg1;
1486 void* arg2;
1487 CPUState cpu;
1488
1489 void dump(const char* indentation = 0);
1490 private:
1491 void dumpCPURegisters(const char* indentation);
1492 };
1493 #endif // USE(MASM_PROBE)
1494
1495 protected:
1496 X86Assembler::Condition x86Condition(RelationalCondition cond)
1497 {
1498 return static_cast<X86Assembler::Condition>(cond);
1499 }
1500
1501 X86Assembler::Condition x86Condition(ResultCondition cond)
1502 {
1503 return static_cast<X86Assembler::Condition>(cond);
1504 }
1505
1506 void set32(X86Assembler::Condition cond, RegisterID dest)
1507 {
1508 #if CPU(X86)
1509 // On 32-bit x86 we can only set the first 4 registers;
1510 // esp..edi are mapped to the 'h' registers!
1511 if (dest >= 4) {
1512 m_assembler.xchgl_rr(dest, X86Registers::eax);
1513 m_assembler.setCC_r(cond, X86Registers::eax);
1514 m_assembler.movzbl_rr(X86Registers::eax, X86Registers::eax);
1515 m_assembler.xchgl_rr(dest, X86Registers::eax);
1516 return;
1517 }
1518 #endif
1519 m_assembler.setCC_r(cond, dest);
1520 m_assembler.movzbl_rr(dest, dest);
1521 }
1522
1523 private:
1524 // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
1525 // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
1526 friend class MacroAssemblerX86;
1527
1528 ALWAYS_INLINE void generateTest32(Address address, TrustedImm32 mask = TrustedImm32(-1))
1529 {
1530 if (mask.m_value == -1)
1531 m_assembler.cmpl_im(0, address.offset, address.base);
1532 else if (!(mask.m_value & ~0xff))
1533 m_assembler.testb_im(mask.m_value, address.offset, address.base);
1534 else if (!(mask.m_value & ~0xff00))
1535 m_assembler.testb_im(mask.m_value >> 8, address.offset + 1, address.base);
1536 else if (!(mask.m_value & ~0xff0000))
1537 m_assembler.testb_im(mask.m_value >> 16, address.offset + 2, address.base);
1538 else if (!(mask.m_value & ~0xff000000))
1539 m_assembler.testb_im(mask.m_value >> 24, address.offset + 3, address.base);
1540 else
1541 m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
1542 }
1543
1544 #if CPU(X86)
1545 #if OS(MAC_OS_X)
1546
1547 // All X86 Macs are guaranteed to support at least SSE2,
1548 static bool isSSE2Present()
1549 {
1550 return true;
1551 }
1552
1553 #else // OS(MAC_OS_X)
1554
1555 enum SSE2CheckState {
1556 NotCheckedSSE2,
1557 HasSSE2,
1558 NoSSE2
1559 };
1560
1561 static bool isSSE2Present()
1562 {
1563 if (s_sse2CheckState == NotCheckedSSE2) {
1564 // Default the flags value to zero; if the compiler is
1565 // not MSVC or GCC we will read this as SSE2 not present.
1566 int flags = 0;
1567 #if COMPILER(MSVC)
1568 _asm {
1569 mov eax, 1 // cpuid function 1 gives us the standard feature set
1570 cpuid;
1571 mov flags, edx;
1572 }
1573 #elif COMPILER(GCC)
1574 asm (
1575 "movl $0x1, %%eax;"
1576 "pushl %%ebx;"
1577 "cpuid;"
1578 "popl %%ebx;"
1579 "movl %%edx, %0;"
1580 : "=g" (flags)
1581 :
1582 : "%eax", "%ecx", "%edx"
1583 );
1584 #endif
1585 static const int SSE2FeatureBit = 1 << 26;
1586 s_sse2CheckState = (flags & SSE2FeatureBit) ? HasSSE2 : NoSSE2;
1587 }
1588 // Only check once.
1589 ASSERT(s_sse2CheckState != NotCheckedSSE2);
1590
1591 return s_sse2CheckState == HasSSE2;
1592 }
1593
1594 static SSE2CheckState s_sse2CheckState;
1595
1596 #endif // OS(MAC_OS_X)
1597 #elif !defined(NDEBUG) // CPU(X86)
1598
1599 // On x86-64 we should never be checking for SSE2 in a non-debug build,
1600 // but non debug add this method to keep the asserts above happy.
1601 static bool isSSE2Present()
1602 {
1603 return true;
1604 }
1605
1606 #endif
1607 };
1608
1609 } // namespace JSC
1610
1611 #endif // ENABLE(ASSEMBLER)
1612
1613 #endif // MacroAssemblerX86Common_h