]> git.saurik.com Git - apple/javascriptcore.git/blob - assembler/MacroAssembler.h
c70f2b7904e47ef99cc99a1091037f44549cf825
[apple/javascriptcore.git] / assembler / MacroAssembler.h
1 /*
2 * Copyright (C) 2008, 2012, 2013, 2014 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 MacroAssembler_h
27 #define MacroAssembler_h
28
29 #if ENABLE(ASSEMBLER)
30
31 #if CPU(ARM_THUMB2)
32 #include "MacroAssemblerARMv7.h"
33 namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; };
34
35 #elif CPU(ARM64)
36 #include "MacroAssemblerARM64.h"
37 namespace JSC { typedef MacroAssemblerARM64 MacroAssemblerBase; };
38
39 #elif CPU(ARM_TRADITIONAL)
40 #include "MacroAssemblerARM.h"
41 namespace JSC { typedef MacroAssemblerARM MacroAssemblerBase; };
42
43 #elif CPU(MIPS)
44 #include "MacroAssemblerMIPS.h"
45 namespace JSC {
46 typedef MacroAssemblerMIPS MacroAssemblerBase;
47 };
48
49 #elif CPU(X86)
50 #include "MacroAssemblerX86.h"
51 namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; };
52
53 #elif CPU(X86_64)
54 #include "MacroAssemblerX86_64.h"
55 namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; };
56
57 #elif CPU(SH4)
58 #include "MacroAssemblerSH4.h"
59 namespace JSC {
60 typedef MacroAssemblerSH4 MacroAssemblerBase;
61 };
62
63 #else
64 #error "The MacroAssembler is not supported on this platform."
65 #endif
66
67 namespace JSC {
68
69 class MacroAssembler : public MacroAssemblerBase {
70 public:
71
72 static RegisterID nextRegister(RegisterID reg)
73 {
74 return static_cast<RegisterID>(reg + 1);
75 }
76
77 static FPRegisterID nextFPRegister(FPRegisterID reg)
78 {
79 return static_cast<FPRegisterID>(reg + 1);
80 }
81
82 static unsigned numberOfRegisters()
83 {
84 return lastRegister() - firstRegister() + 1;
85 }
86
87 static unsigned registerIndex(RegisterID reg)
88 {
89 return reg - firstRegister();
90 }
91
92 static unsigned numberOfFPRegisters()
93 {
94 return lastFPRegister() - firstFPRegister() + 1;
95 }
96
97 static unsigned fpRegisterIndex(FPRegisterID reg)
98 {
99 return reg - firstFPRegister();
100 }
101
102 static unsigned registerIndex(FPRegisterID reg)
103 {
104 return fpRegisterIndex(reg) + numberOfRegisters();
105 }
106
107 static unsigned totalNumberOfRegisters()
108 {
109 return numberOfRegisters() + numberOfFPRegisters();
110 }
111
112 using MacroAssemblerBase::pop;
113 using MacroAssemblerBase::jump;
114 using MacroAssemblerBase::branch32;
115 using MacroAssemblerBase::move;
116 using MacroAssemblerBase::add32;
117 using MacroAssemblerBase::and32;
118 using MacroAssemblerBase::branchAdd32;
119 using MacroAssemblerBase::branchMul32;
120 #if CPU(ARM64) || CPU(ARM_THUMB2) || CPU(X86_64)
121 using MacroAssemblerBase::branchPtr;
122 #endif
123 using MacroAssemblerBase::branchSub32;
124 using MacroAssemblerBase::lshift32;
125 using MacroAssemblerBase::or32;
126 using MacroAssemblerBase::rshift32;
127 using MacroAssemblerBase::store32;
128 using MacroAssemblerBase::sub32;
129 using MacroAssemblerBase::urshift32;
130 using MacroAssemblerBase::xor32;
131
132 static bool isPtrAlignedAddressOffset(ptrdiff_t value)
133 {
134 return value == static_cast<int32_t>(value);
135 }
136
137 static const double twoToThe32; // This is super useful for some double code.
138
139 // Utilities used by the DFG JIT.
140 #if ENABLE(DFG_JIT)
141 using MacroAssemblerBase::invert;
142
143 static DoubleCondition invert(DoubleCondition cond)
144 {
145 switch (cond) {
146 case DoubleEqual:
147 return DoubleNotEqualOrUnordered;
148 case DoubleNotEqual:
149 return DoubleEqualOrUnordered;
150 case DoubleGreaterThan:
151 return DoubleLessThanOrEqualOrUnordered;
152 case DoubleGreaterThanOrEqual:
153 return DoubleLessThanOrUnordered;
154 case DoubleLessThan:
155 return DoubleGreaterThanOrEqualOrUnordered;
156 case DoubleLessThanOrEqual:
157 return DoubleGreaterThanOrUnordered;
158 case DoubleEqualOrUnordered:
159 return DoubleNotEqual;
160 case DoubleNotEqualOrUnordered:
161 return DoubleEqual;
162 case DoubleGreaterThanOrUnordered:
163 return DoubleLessThanOrEqual;
164 case DoubleGreaterThanOrEqualOrUnordered:
165 return DoubleLessThan;
166 case DoubleLessThanOrUnordered:
167 return DoubleGreaterThanOrEqual;
168 case DoubleLessThanOrEqualOrUnordered:
169 return DoubleGreaterThan;
170 default:
171 RELEASE_ASSERT_NOT_REACHED();
172 return DoubleEqual; // make compiler happy
173 }
174 }
175
176 static bool isInvertible(ResultCondition cond)
177 {
178 switch (cond) {
179 case Zero:
180 case NonZero:
181 return true;
182 default:
183 return false;
184 }
185 }
186
187 static ResultCondition invert(ResultCondition cond)
188 {
189 switch (cond) {
190 case Zero:
191 return NonZero;
192 case NonZero:
193 return Zero;
194 default:
195 RELEASE_ASSERT_NOT_REACHED();
196 return Zero; // Make compiler happy for release builds.
197 }
198 }
199 #endif
200
201 // Platform agnostic onvenience functions,
202 // described in terms of other macro assembly methods.
203 void pop()
204 {
205 addPtr(TrustedImm32(sizeof(void*)), stackPointerRegister);
206 }
207
208 void peek(RegisterID dest, int index = 0)
209 {
210 loadPtr(Address(stackPointerRegister, (index * sizeof(void*))), dest);
211 }
212
213 Address addressForPoke(int index)
214 {
215 return Address(stackPointerRegister, (index * sizeof(void*)));
216 }
217
218 void poke(RegisterID src, int index = 0)
219 {
220 storePtr(src, addressForPoke(index));
221 }
222
223 void poke(TrustedImm32 value, int index = 0)
224 {
225 store32(value, addressForPoke(index));
226 }
227
228 void poke(TrustedImmPtr imm, int index = 0)
229 {
230 storePtr(imm, addressForPoke(index));
231 }
232
233 #if !CPU(ARM64)
234 void pushToSave(RegisterID src)
235 {
236 push(src);
237 }
238 void pushToSaveImmediateWithoutTouchingRegisters(TrustedImm32 imm)
239 {
240 push(imm);
241 }
242 void popToRestore(RegisterID dest)
243 {
244 pop(dest);
245 }
246 void pushToSave(FPRegisterID src)
247 {
248 subPtr(TrustedImm32(sizeof(double)), stackPointerRegister);
249 storeDouble(src, stackPointerRegister);
250 }
251 void popToRestore(FPRegisterID dest)
252 {
253 loadDouble(stackPointerRegister, dest);
254 addPtr(TrustedImm32(sizeof(double)), stackPointerRegister);
255 }
256
257 static ptrdiff_t pushToSaveByteOffset() { return sizeof(void*); }
258 #endif // !CPU(ARM64)
259
260 #if CPU(X86_64) || CPU(ARM64)
261 void peek64(RegisterID dest, int index = 0)
262 {
263 load64(Address(stackPointerRegister, (index * sizeof(void*))), dest);
264 }
265
266 void poke(TrustedImm64 value, int index = 0)
267 {
268 store64(value, addressForPoke(index));
269 }
270
271 void poke64(RegisterID src, int index = 0)
272 {
273 store64(src, addressForPoke(index));
274 }
275 #endif
276
277 #if CPU(MIPS)
278 void poke(FPRegisterID src, int index = 0)
279 {
280 ASSERT(!(index & 1));
281 storeDouble(src, addressForPoke(index));
282 }
283 #endif
284
285 // Immediate shifts only have 5 controllable bits
286 // so we'll consider them safe for now.
287 TrustedImm32 trustedImm32ForShift(Imm32 imm)
288 {
289 return TrustedImm32(imm.asTrustedImm32().m_value & 31);
290 }
291
292 // Backwards banches, these are currently all implemented using existing forwards branch mechanisms.
293 void branchPtr(RelationalCondition cond, RegisterID op1, TrustedImmPtr imm, Label target)
294 {
295 branchPtr(cond, op1, imm).linkTo(target, this);
296 }
297 void branchPtr(RelationalCondition cond, RegisterID op1, ImmPtr imm, Label target)
298 {
299 branchPtr(cond, op1, imm).linkTo(target, this);
300 }
301
302 void branch32(RelationalCondition cond, RegisterID op1, RegisterID op2, Label target)
303 {
304 branch32(cond, op1, op2).linkTo(target, this);
305 }
306
307 void branch32(RelationalCondition cond, RegisterID op1, TrustedImm32 imm, Label target)
308 {
309 branch32(cond, op1, imm).linkTo(target, this);
310 }
311
312 void branch32(RelationalCondition cond, RegisterID op1, Imm32 imm, Label target)
313 {
314 branch32(cond, op1, imm).linkTo(target, this);
315 }
316
317 void branch32(RelationalCondition cond, RegisterID left, Address right, Label target)
318 {
319 branch32(cond, left, right).linkTo(target, this);
320 }
321
322 Jump branch32(RelationalCondition cond, TrustedImm32 left, RegisterID right)
323 {
324 return branch32(commute(cond), right, left);
325 }
326
327 Jump branch32(RelationalCondition cond, Imm32 left, RegisterID right)
328 {
329 return branch32(commute(cond), right, left);
330 }
331
332 void branchTestPtr(ResultCondition cond, RegisterID reg, Label target)
333 {
334 branchTestPtr(cond, reg).linkTo(target, this);
335 }
336
337 #if !CPU(ARM_THUMB2) && !CPU(ARM64)
338 PatchableJump patchableBranchPtr(RelationalCondition cond, Address left, TrustedImmPtr right = TrustedImmPtr(0))
339 {
340 return PatchableJump(branchPtr(cond, left, right));
341 }
342
343 PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
344 {
345 return PatchableJump(branchPtrWithPatch(cond, left, dataLabel, initialRightValue));
346 }
347
348 PatchableJump patchableBranch32WithPatch(RelationalCondition cond, Address left, DataLabel32& dataLabel, TrustedImm32 initialRightValue = TrustedImm32(0))
349 {
350 return PatchableJump(branch32WithPatch(cond, left, dataLabel, initialRightValue));
351 }
352
353 #if !CPU(ARM_TRADITIONAL)
354 PatchableJump patchableJump()
355 {
356 return PatchableJump(jump());
357 }
358
359 PatchableJump patchableBranchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
360 {
361 return PatchableJump(branchTest32(cond, reg, mask));
362 }
363
364 PatchableJump patchableBranch32(RelationalCondition cond, RegisterID reg, TrustedImm32 imm)
365 {
366 return PatchableJump(branch32(cond, reg, imm));
367 }
368
369 PatchableJump patchableBranch32(RelationalCondition cond, Address address, TrustedImm32 imm)
370 {
371 return PatchableJump(branch32(cond, address, imm));
372 }
373 #endif
374 #endif
375
376 void jump(Label target)
377 {
378 jump().linkTo(target, this);
379 }
380
381 // Commute a relational condition, returns a new condition that will produce
382 // the same results given the same inputs but with their positions exchanged.
383 static RelationalCondition commute(RelationalCondition condition)
384 {
385 switch (condition) {
386 case Above:
387 return Below;
388 case AboveOrEqual:
389 return BelowOrEqual;
390 case Below:
391 return Above;
392 case BelowOrEqual:
393 return AboveOrEqual;
394 case GreaterThan:
395 return LessThan;
396 case GreaterThanOrEqual:
397 return LessThanOrEqual;
398 case LessThan:
399 return GreaterThan;
400 case LessThanOrEqual:
401 return GreaterThanOrEqual;
402 default:
403 break;
404 }
405
406 ASSERT(condition == Equal || condition == NotEqual);
407 return condition;
408 }
409
410 static const unsigned BlindingModulus = 64;
411 bool shouldConsiderBlinding()
412 {
413 return !(random() & (BlindingModulus - 1));
414 }
415
416 // Ptr methods
417 // On 32-bit platforms (i.e. x86), these methods directly map onto their 32-bit equivalents.
418 // FIXME: should this use a test for 32-bitness instead of this specific exception?
419 #if !CPU(X86_64) && !CPU(ARM64)
420 void addPtr(Address src, RegisterID dest)
421 {
422 add32(src, dest);
423 }
424
425 void addPtr(AbsoluteAddress src, RegisterID dest)
426 {
427 add32(src, dest);
428 }
429
430 void addPtr(RegisterID src, RegisterID dest)
431 {
432 add32(src, dest);
433 }
434
435 void addPtr(TrustedImm32 imm, RegisterID srcDest)
436 {
437 add32(imm, srcDest);
438 }
439
440 void addPtr(TrustedImmPtr imm, RegisterID dest)
441 {
442 add32(TrustedImm32(imm), dest);
443 }
444
445 void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
446 {
447 add32(imm, src, dest);
448 }
449
450 void addPtr(TrustedImm32 imm, AbsoluteAddress address)
451 {
452 add32(imm, address);
453 }
454
455 void andPtr(RegisterID src, RegisterID dest)
456 {
457 and32(src, dest);
458 }
459
460 void andPtr(TrustedImm32 imm, RegisterID srcDest)
461 {
462 and32(imm, srcDest);
463 }
464
465 void andPtr(TrustedImmPtr imm, RegisterID srcDest)
466 {
467 and32(TrustedImm32(imm), srcDest);
468 }
469
470 void lshiftPtr(Imm32 imm, RegisterID srcDest)
471 {
472 lshift32(trustedImm32ForShift(imm), srcDest);
473 }
474
475 void negPtr(RegisterID dest)
476 {
477 neg32(dest);
478 }
479
480 void orPtr(RegisterID src, RegisterID dest)
481 {
482 or32(src, dest);
483 }
484
485 void orPtr(RegisterID op1, RegisterID op2, RegisterID dest)
486 {
487 or32(op1, op2, dest);
488 }
489
490 void orPtr(TrustedImmPtr imm, RegisterID dest)
491 {
492 or32(TrustedImm32(imm), dest);
493 }
494
495 void orPtr(TrustedImm32 imm, RegisterID dest)
496 {
497 or32(imm, dest);
498 }
499
500 void subPtr(RegisterID src, RegisterID dest)
501 {
502 sub32(src, dest);
503 }
504
505 void subPtr(TrustedImm32 imm, RegisterID dest)
506 {
507 sub32(imm, dest);
508 }
509
510 void subPtr(TrustedImmPtr imm, RegisterID dest)
511 {
512 sub32(TrustedImm32(imm), dest);
513 }
514
515 void xorPtr(RegisterID src, RegisterID dest)
516 {
517 xor32(src, dest);
518 }
519
520 void xorPtr(TrustedImm32 imm, RegisterID srcDest)
521 {
522 xor32(imm, srcDest);
523 }
524
525
526 void loadPtr(ImplicitAddress address, RegisterID dest)
527 {
528 load32(address, dest);
529 }
530
531 void loadPtr(BaseIndex address, RegisterID dest)
532 {
533 load32(address, dest);
534 }
535
536 void loadPtr(const void* address, RegisterID dest)
537 {
538 load32(address, dest);
539 }
540
541 DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
542 {
543 return load32WithAddressOffsetPatch(address, dest);
544 }
545
546 DataLabelCompact loadPtrWithCompactAddressOffsetPatch(Address address, RegisterID dest)
547 {
548 return load32WithCompactAddressOffsetPatch(address, dest);
549 }
550
551 void move(ImmPtr imm, RegisterID dest)
552 {
553 move(Imm32(imm.asTrustedImmPtr()), dest);
554 }
555
556 void comparePtr(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
557 {
558 compare32(cond, left, right, dest);
559 }
560
561 void comparePtr(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
562 {
563 compare32(cond, left, right, dest);
564 }
565
566 void storePtr(RegisterID src, ImplicitAddress address)
567 {
568 store32(src, address);
569 }
570
571 void storePtr(RegisterID src, BaseIndex address)
572 {
573 store32(src, address);
574 }
575
576 void storePtr(RegisterID src, void* address)
577 {
578 store32(src, address);
579 }
580
581 void storePtr(TrustedImmPtr imm, ImplicitAddress address)
582 {
583 store32(TrustedImm32(imm), address);
584 }
585
586 void storePtr(ImmPtr imm, Address address)
587 {
588 store32(Imm32(imm.asTrustedImmPtr()), address);
589 }
590
591 void storePtr(TrustedImmPtr imm, void* address)
592 {
593 store32(TrustedImm32(imm), address);
594 }
595
596 void storePtr(TrustedImm32 imm, ImplicitAddress address)
597 {
598 store32(imm, address);
599 }
600
601 void storePtr(TrustedImmPtr imm, BaseIndex address)
602 {
603 store32(TrustedImm32(imm), address);
604 }
605
606 DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
607 {
608 return store32WithAddressOffsetPatch(src, address);
609 }
610
611 Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
612 {
613 return branch32(cond, left, right);
614 }
615
616 Jump branchPtr(RelationalCondition cond, RegisterID left, TrustedImmPtr right)
617 {
618 return branch32(cond, left, TrustedImm32(right));
619 }
620
621 Jump branchPtr(RelationalCondition cond, RegisterID left, ImmPtr right)
622 {
623 return branch32(cond, left, Imm32(right.asTrustedImmPtr()));
624 }
625
626 Jump branchPtr(RelationalCondition cond, RegisterID left, Address right)
627 {
628 return branch32(cond, left, right);
629 }
630
631 Jump branchPtr(RelationalCondition cond, Address left, RegisterID right)
632 {
633 return branch32(cond, left, right);
634 }
635
636 Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
637 {
638 return branch32(cond, left, right);
639 }
640
641 Jump branchPtr(RelationalCondition cond, Address left, TrustedImmPtr right)
642 {
643 return branch32(cond, left, TrustedImm32(right));
644 }
645
646 Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, TrustedImmPtr right)
647 {
648 return branch32(cond, left, TrustedImm32(right));
649 }
650
651 Jump branchSubPtr(ResultCondition cond, RegisterID src, RegisterID dest)
652 {
653 return branchSub32(cond, src, dest);
654 }
655
656 Jump branchTestPtr(ResultCondition cond, RegisterID reg, RegisterID mask)
657 {
658 return branchTest32(cond, reg, mask);
659 }
660
661 Jump branchTestPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
662 {
663 return branchTest32(cond, reg, mask);
664 }
665
666 Jump branchTestPtr(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
667 {
668 return branchTest32(cond, address, mask);
669 }
670
671 Jump branchTestPtr(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
672 {
673 return branchTest32(cond, address, mask);
674 }
675
676 Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
677 {
678 return branchAdd32(cond, src, dest);
679 }
680
681 Jump branchSubPtr(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
682 {
683 return branchSub32(cond, imm, dest);
684 }
685 using MacroAssemblerBase::branchTest8;
686 Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1))
687 {
688 return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask);
689 }
690
691 #else // !CPU(X86_64)
692
693 void addPtr(RegisterID src, RegisterID dest)
694 {
695 add64(src, dest);
696 }
697
698 void addPtr(Address src, RegisterID dest)
699 {
700 add64(src, dest);
701 }
702
703 void addPtr(TrustedImm32 imm, RegisterID srcDest)
704 {
705 add64(imm, srcDest);
706 }
707
708 void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
709 {
710 add64(imm, src, dest);
711 }
712
713 void addPtr(TrustedImm32 imm, Address address)
714 {
715 add64(imm, address);
716 }
717
718 void addPtr(AbsoluteAddress src, RegisterID dest)
719 {
720 add64(src, dest);
721 }
722
723 void addPtr(TrustedImmPtr imm, RegisterID dest)
724 {
725 add64(TrustedImm64(imm), dest);
726 }
727
728 void addPtr(TrustedImm32 imm, AbsoluteAddress address)
729 {
730 add64(imm, address);
731 }
732
733 void andPtr(RegisterID src, RegisterID dest)
734 {
735 and64(src, dest);
736 }
737
738 void andPtr(TrustedImm32 imm, RegisterID srcDest)
739 {
740 and64(imm, srcDest);
741 }
742
743 void andPtr(TrustedImmPtr imm, RegisterID srcDest)
744 {
745 and64(imm, srcDest);
746 }
747
748 void lshiftPtr(Imm32 imm, RegisterID srcDest)
749 {
750 lshift64(trustedImm32ForShift(imm), srcDest);
751 }
752
753 void negPtr(RegisterID dest)
754 {
755 neg64(dest);
756 }
757
758 void orPtr(RegisterID src, RegisterID dest)
759 {
760 or64(src, dest);
761 }
762
763 void orPtr(TrustedImm32 imm, RegisterID dest)
764 {
765 or64(imm, dest);
766 }
767
768 void orPtr(TrustedImmPtr imm, RegisterID dest)
769 {
770 or64(TrustedImm64(imm), dest);
771 }
772
773 void orPtr(RegisterID op1, RegisterID op2, RegisterID dest)
774 {
775 or64(op1, op2, dest);
776 }
777
778 void orPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
779 {
780 or64(imm, src, dest);
781 }
782
783 void rotateRightPtr(TrustedImm32 imm, RegisterID srcDst)
784 {
785 rotateRight64(imm, srcDst);
786 }
787
788 void subPtr(RegisterID src, RegisterID dest)
789 {
790 sub64(src, dest);
791 }
792
793 void subPtr(TrustedImm32 imm, RegisterID dest)
794 {
795 sub64(imm, dest);
796 }
797
798 void subPtr(TrustedImmPtr imm, RegisterID dest)
799 {
800 sub64(TrustedImm64(imm), dest);
801 }
802
803 void xorPtr(RegisterID src, RegisterID dest)
804 {
805 xor64(src, dest);
806 }
807
808 void xorPtr(RegisterID src, Address dest)
809 {
810 xor64(src, dest);
811 }
812
813 void xorPtr(TrustedImm32 imm, RegisterID srcDest)
814 {
815 xor64(imm, srcDest);
816 }
817
818 void loadPtr(ImplicitAddress address, RegisterID dest)
819 {
820 load64(address, dest);
821 }
822
823 void loadPtr(BaseIndex address, RegisterID dest)
824 {
825 load64(address, dest);
826 }
827
828 void loadPtr(const void* address, RegisterID dest)
829 {
830 load64(address, dest);
831 }
832
833 DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
834 {
835 return load64WithAddressOffsetPatch(address, dest);
836 }
837
838 DataLabelCompact loadPtrWithCompactAddressOffsetPatch(Address address, RegisterID dest)
839 {
840 return load64WithCompactAddressOffsetPatch(address, dest);
841 }
842
843 void storePtr(RegisterID src, ImplicitAddress address)
844 {
845 store64(src, address);
846 }
847
848 void storePtr(RegisterID src, BaseIndex address)
849 {
850 store64(src, address);
851 }
852
853 void storePtr(RegisterID src, void* address)
854 {
855 store64(src, address);
856 }
857
858 void storePtr(TrustedImmPtr imm, ImplicitAddress address)
859 {
860 store64(TrustedImm64(imm), address);
861 }
862
863 void storePtr(TrustedImmPtr imm, BaseIndex address)
864 {
865 store64(TrustedImm64(imm), address);
866 }
867
868 DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
869 {
870 return store64WithAddressOffsetPatch(src, address);
871 }
872
873 void comparePtr(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
874 {
875 compare64(cond, left, right, dest);
876 }
877
878 void comparePtr(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
879 {
880 compare64(cond, left, right, dest);
881 }
882
883 void testPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
884 {
885 test64(cond, reg, mask, dest);
886 }
887
888 void testPtr(ResultCondition cond, RegisterID reg, RegisterID mask, RegisterID dest)
889 {
890 test64(cond, reg, mask, dest);
891 }
892
893 Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
894 {
895 return branch64(cond, left, right);
896 }
897
898 Jump branchPtr(RelationalCondition cond, RegisterID left, TrustedImmPtr right)
899 {
900 return branch64(cond, left, TrustedImm64(right));
901 }
902
903 Jump branchPtr(RelationalCondition cond, RegisterID left, Address right)
904 {
905 return branch64(cond, left, right);
906 }
907
908 Jump branchPtr(RelationalCondition cond, Address left, RegisterID right)
909 {
910 return branch64(cond, left, right);
911 }
912
913 Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
914 {
915 return branch64(cond, left, right);
916 }
917
918 Jump branchPtr(RelationalCondition cond, Address left, TrustedImmPtr right)
919 {
920 return branch64(cond, left, TrustedImm64(right));
921 }
922
923 Jump branchTestPtr(ResultCondition cond, RegisterID reg, RegisterID mask)
924 {
925 return branchTest64(cond, reg, mask);
926 }
927
928 Jump branchTestPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
929 {
930 return branchTest64(cond, reg, mask);
931 }
932
933 Jump branchTestPtr(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
934 {
935 return branchTest64(cond, address, mask);
936 }
937
938 Jump branchTestPtr(ResultCondition cond, Address address, RegisterID reg)
939 {
940 return branchTest64(cond, address, reg);
941 }
942
943 Jump branchTestPtr(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
944 {
945 return branchTest64(cond, address, mask);
946 }
947
948 Jump branchTestPtr(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
949 {
950 return branchTest64(cond, address, mask);
951 }
952
953 Jump branchAddPtr(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
954 {
955 return branchAdd64(cond, imm, dest);
956 }
957
958 Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
959 {
960 return branchAdd64(cond, src, dest);
961 }
962
963 Jump branchSubPtr(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
964 {
965 return branchSub64(cond, imm, dest);
966 }
967
968 Jump branchSubPtr(ResultCondition cond, RegisterID src, RegisterID dest)
969 {
970 return branchSub64(cond, src, dest);
971 }
972
973 Jump branchSubPtr(ResultCondition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest)
974 {
975 return branchSub64(cond, src1, src2, dest);
976 }
977
978 using MacroAssemblerBase::and64;
979 using MacroAssemblerBase::convertInt32ToDouble;
980 using MacroAssemblerBase::store64;
981 bool shouldBlindDouble(double value)
982 {
983 // Don't trust NaN or +/-Infinity
984 if (!std::isfinite(value))
985 return shouldConsiderBlinding();
986
987 // Try to force normalisation, and check that there's no change
988 // in the bit pattern
989 if (bitwise_cast<uint64_t>(value * 1.0) != bitwise_cast<uint64_t>(value))
990 return shouldConsiderBlinding();
991
992 value = fabs(value);
993 // Only allow a limited set of fractional components
994 double scaledValue = value * 8;
995 if (scaledValue / 8 != value)
996 return shouldConsiderBlinding();
997 double frac = scaledValue - floor(scaledValue);
998 if (frac != 0.0)
999 return shouldConsiderBlinding();
1000
1001 return value > 0xff;
1002 }
1003
1004 bool shouldBlindPointerForSpecificArch(uintptr_t value)
1005 {
1006 if (sizeof(void*) == 4)
1007 return shouldBlindForSpecificArch(static_cast<uint32_t>(value));
1008 return shouldBlindForSpecificArch(static_cast<uint64_t>(value));
1009 }
1010
1011 bool shouldBlind(ImmPtr imm)
1012 {
1013 if (!canBlind())
1014 return false;
1015
1016 #if ENABLE(FORCED_JIT_BLINDING)
1017 UNUSED_PARAM(imm);
1018 // Debug always blind all constants, if only so we know
1019 // if we've broken blinding during patch development.
1020 return true;
1021 #endif
1022
1023 // First off we'll special case common, "safe" values to avoid hurting
1024 // performance too much
1025 uintptr_t value = imm.asTrustedImmPtr().asIntptr();
1026 switch (value) {
1027 case 0xffff:
1028 case 0xffffff:
1029 case 0xffffffffL:
1030 case 0xffffffffffL:
1031 case 0xffffffffffffL:
1032 case 0xffffffffffffffL:
1033 case 0xffffffffffffffffL:
1034 return false;
1035 default: {
1036 if (value <= 0xff)
1037 return false;
1038 if (~value <= 0xff)
1039 return false;
1040 }
1041 }
1042
1043 if (!shouldConsiderBlinding())
1044 return false;
1045
1046 return shouldBlindPointerForSpecificArch(value);
1047 }
1048
1049 struct RotatedImmPtr {
1050 RotatedImmPtr(uintptr_t v1, uint8_t v2)
1051 : value(v1)
1052 , rotation(v2)
1053 {
1054 }
1055 TrustedImmPtr value;
1056 TrustedImm32 rotation;
1057 };
1058
1059 RotatedImmPtr rotationBlindConstant(ImmPtr imm)
1060 {
1061 uint8_t rotation = random() % (sizeof(void*) * 8);
1062 uintptr_t value = imm.asTrustedImmPtr().asIntptr();
1063 value = (value << rotation) | (value >> (sizeof(void*) * 8 - rotation));
1064 return RotatedImmPtr(value, rotation);
1065 }
1066
1067 void loadRotationBlindedConstant(RotatedImmPtr constant, RegisterID dest)
1068 {
1069 move(constant.value, dest);
1070 rotateRightPtr(constant.rotation, dest);
1071 }
1072
1073 bool shouldBlind(Imm64 imm)
1074 {
1075 #if ENABLE(FORCED_JIT_BLINDING)
1076 UNUSED_PARAM(imm);
1077 // Debug always blind all constants, if only so we know
1078 // if we've broken blinding during patch development.
1079 return true;
1080 #endif
1081
1082 // First off we'll special case common, "safe" values to avoid hurting
1083 // performance too much
1084 uint64_t value = imm.asTrustedImm64().m_value;
1085 switch (value) {
1086 case 0xffff:
1087 case 0xffffff:
1088 case 0xffffffffL:
1089 case 0xffffffffffL:
1090 case 0xffffffffffffL:
1091 case 0xffffffffffffffL:
1092 case 0xffffffffffffffffL:
1093 return false;
1094 default: {
1095 if (value <= 0xff)
1096 return false;
1097 if (~value <= 0xff)
1098 return false;
1099
1100 JSValue jsValue = JSValue::decode(value);
1101 if (jsValue.isInt32())
1102 return shouldBlind(Imm32(jsValue.asInt32()));
1103 if (jsValue.isDouble() && !shouldBlindDouble(jsValue.asDouble()))
1104 return false;
1105
1106 if (!shouldBlindDouble(bitwise_cast<double>(value)))
1107 return false;
1108 }
1109 }
1110
1111 if (!shouldConsiderBlinding())
1112 return false;
1113
1114 return shouldBlindForSpecificArch(value);
1115 }
1116
1117 struct RotatedImm64 {
1118 RotatedImm64(uint64_t v1, uint8_t v2)
1119 : value(v1)
1120 , rotation(v2)
1121 {
1122 }
1123 TrustedImm64 value;
1124 TrustedImm32 rotation;
1125 };
1126
1127 RotatedImm64 rotationBlindConstant(Imm64 imm)
1128 {
1129 uint8_t rotation = random() % (sizeof(int64_t) * 8);
1130 uint64_t value = imm.asTrustedImm64().m_value;
1131 value = (value << rotation) | (value >> (sizeof(int64_t) * 8 - rotation));
1132 return RotatedImm64(value, rotation);
1133 }
1134
1135 void loadRotationBlindedConstant(RotatedImm64 constant, RegisterID dest)
1136 {
1137 move(constant.value, dest);
1138 rotateRight64(constant.rotation, dest);
1139 }
1140
1141 void convertInt32ToDouble(Imm32 imm, FPRegisterID dest)
1142 {
1143 if (shouldBlind(imm) && haveScratchRegisterForBlinding()) {
1144 RegisterID scratchRegister = scratchRegisterForBlinding();
1145 loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister);
1146 convertInt32ToDouble(scratchRegister, dest);
1147 } else
1148 convertInt32ToDouble(imm.asTrustedImm32(), dest);
1149 }
1150
1151 void move(ImmPtr imm, RegisterID dest)
1152 {
1153 if (shouldBlind(imm))
1154 loadRotationBlindedConstant(rotationBlindConstant(imm), dest);
1155 else
1156 move(imm.asTrustedImmPtr(), dest);
1157 }
1158
1159 void move(Imm64 imm, RegisterID dest)
1160 {
1161 if (shouldBlind(imm))
1162 loadRotationBlindedConstant(rotationBlindConstant(imm), dest);
1163 else
1164 move(imm.asTrustedImm64(), dest);
1165 }
1166
1167 void and64(Imm32 imm, RegisterID dest)
1168 {
1169 if (shouldBlind(imm)) {
1170 BlindedImm32 key = andBlindedConstant(imm);
1171 and64(key.value1, dest);
1172 and64(key.value2, dest);
1173 } else
1174 and64(imm.asTrustedImm32(), dest);
1175 }
1176
1177 Jump branchPtr(RelationalCondition cond, RegisterID left, ImmPtr right)
1178 {
1179 if (shouldBlind(right) && haveScratchRegisterForBlinding()) {
1180 RegisterID scratchRegister = scratchRegisterForBlinding();
1181 loadRotationBlindedConstant(rotationBlindConstant(right), scratchRegister);
1182 return branchPtr(cond, left, scratchRegister);
1183 }
1184 return branchPtr(cond, left, right.asTrustedImmPtr());
1185 }
1186
1187 void storePtr(ImmPtr imm, Address dest)
1188 {
1189 if (shouldBlind(imm) && haveScratchRegisterForBlinding()) {
1190 RegisterID scratchRegister = scratchRegisterForBlinding();
1191 loadRotationBlindedConstant(rotationBlindConstant(imm), scratchRegister);
1192 storePtr(scratchRegister, dest);
1193 } else
1194 storePtr(imm.asTrustedImmPtr(), dest);
1195 }
1196
1197 void store64(Imm64 imm, Address dest)
1198 {
1199 if (shouldBlind(imm) && haveScratchRegisterForBlinding()) {
1200 RegisterID scratchRegister = scratchRegisterForBlinding();
1201 loadRotationBlindedConstant(rotationBlindConstant(imm), scratchRegister);
1202 store64(scratchRegister, dest);
1203 } else
1204 store64(imm.asTrustedImm64(), dest);
1205 }
1206
1207 #endif // !CPU(X86_64)
1208
1209 bool shouldBlind(Imm32 imm)
1210 {
1211 #if ENABLE(FORCED_JIT_BLINDING)
1212 UNUSED_PARAM(imm);
1213 // Debug always blind all constants, if only so we know
1214 // if we've broken blinding during patch development.
1215 return true;
1216 #else // ENABLE(FORCED_JIT_BLINDING)
1217
1218 // First off we'll special case common, "safe" values to avoid hurting
1219 // performance too much
1220 uint32_t value = imm.asTrustedImm32().m_value;
1221 switch (value) {
1222 case 0xffff:
1223 case 0xffffff:
1224 case 0xffffffff:
1225 return false;
1226 default:
1227 if (value <= 0xff)
1228 return false;
1229 if (~value <= 0xff)
1230 return false;
1231 }
1232
1233 if (!shouldConsiderBlinding())
1234 return false;
1235
1236 return shouldBlindForSpecificArch(value);
1237 #endif // ENABLE(FORCED_JIT_BLINDING)
1238 }
1239
1240 struct BlindedImm32 {
1241 BlindedImm32(int32_t v1, int32_t v2)
1242 : value1(v1)
1243 , value2(v2)
1244 {
1245 }
1246 TrustedImm32 value1;
1247 TrustedImm32 value2;
1248 };
1249
1250 uint32_t keyForConstant(uint32_t value, uint32_t& mask)
1251 {
1252 uint32_t key = random();
1253 if (value <= 0xff)
1254 mask = 0xff;
1255 else if (value <= 0xffff)
1256 mask = 0xffff;
1257 else if (value <= 0xffffff)
1258 mask = 0xffffff;
1259 else
1260 mask = 0xffffffff;
1261 return key & mask;
1262 }
1263
1264 uint32_t keyForConstant(uint32_t value)
1265 {
1266 uint32_t mask = 0;
1267 return keyForConstant(value, mask);
1268 }
1269
1270 BlindedImm32 xorBlindConstant(Imm32 imm)
1271 {
1272 uint32_t baseValue = imm.asTrustedImm32().m_value;
1273 uint32_t key = keyForConstant(baseValue);
1274 return BlindedImm32(baseValue ^ key, key);
1275 }
1276
1277 BlindedImm32 additionBlindedConstant(Imm32 imm)
1278 {
1279 // The addition immediate may be used as a pointer offset. Keep aligned based on "imm".
1280 static uint32_t maskTable[4] = { 0xfffffffc, 0xffffffff, 0xfffffffe, 0xffffffff };
1281
1282 uint32_t baseValue = imm.asTrustedImm32().m_value;
1283 uint32_t key = keyForConstant(baseValue) & maskTable[baseValue & 3];
1284 if (key > baseValue)
1285 key = key - baseValue;
1286 return BlindedImm32(baseValue - key, key);
1287 }
1288
1289 BlindedImm32 andBlindedConstant(Imm32 imm)
1290 {
1291 uint32_t baseValue = imm.asTrustedImm32().m_value;
1292 uint32_t mask = 0;
1293 uint32_t key = keyForConstant(baseValue, mask);
1294 ASSERT((baseValue & mask) == baseValue);
1295 return BlindedImm32(((baseValue & key) | ~key) & mask, ((baseValue & ~key) | key) & mask);
1296 }
1297
1298 BlindedImm32 orBlindedConstant(Imm32 imm)
1299 {
1300 uint32_t baseValue = imm.asTrustedImm32().m_value;
1301 uint32_t mask = 0;
1302 uint32_t key = keyForConstant(baseValue, mask);
1303 ASSERT((baseValue & mask) == baseValue);
1304 return BlindedImm32((baseValue & key) & mask, (baseValue & ~key) & mask);
1305 }
1306
1307 void loadXorBlindedConstant(BlindedImm32 constant, RegisterID dest)
1308 {
1309 move(constant.value1, dest);
1310 xor32(constant.value2, dest);
1311 }
1312
1313 void add32(Imm32 imm, RegisterID dest)
1314 {
1315 if (shouldBlind(imm)) {
1316 BlindedImm32 key = additionBlindedConstant(imm);
1317 add32(key.value1, dest);
1318 add32(key.value2, dest);
1319 } else
1320 add32(imm.asTrustedImm32(), dest);
1321 }
1322
1323 void addPtr(Imm32 imm, RegisterID dest)
1324 {
1325 if (shouldBlind(imm)) {
1326 BlindedImm32 key = additionBlindedConstant(imm);
1327 addPtr(key.value1, dest);
1328 addPtr(key.value2, dest);
1329 } else
1330 addPtr(imm.asTrustedImm32(), dest);
1331 }
1332
1333 void and32(Imm32 imm, RegisterID dest)
1334 {
1335 if (shouldBlind(imm)) {
1336 BlindedImm32 key = andBlindedConstant(imm);
1337 and32(key.value1, dest);
1338 and32(key.value2, dest);
1339 } else
1340 and32(imm.asTrustedImm32(), dest);
1341 }
1342
1343 void andPtr(Imm32 imm, RegisterID dest)
1344 {
1345 if (shouldBlind(imm)) {
1346 BlindedImm32 key = andBlindedConstant(imm);
1347 andPtr(key.value1, dest);
1348 andPtr(key.value2, dest);
1349 } else
1350 andPtr(imm.asTrustedImm32(), dest);
1351 }
1352
1353 void and32(Imm32 imm, RegisterID src, RegisterID dest)
1354 {
1355 if (shouldBlind(imm)) {
1356 if (src == dest)
1357 return and32(imm.asTrustedImm32(), dest);
1358 loadXorBlindedConstant(xorBlindConstant(imm), dest);
1359 and32(src, dest);
1360 } else
1361 and32(imm.asTrustedImm32(), src, dest);
1362 }
1363
1364 void move(Imm32 imm, RegisterID dest)
1365 {
1366 if (shouldBlind(imm))
1367 loadXorBlindedConstant(xorBlindConstant(imm), dest);
1368 else
1369 move(imm.asTrustedImm32(), dest);
1370 }
1371
1372 void or32(Imm32 imm, RegisterID src, RegisterID dest)
1373 {
1374 if (shouldBlind(imm)) {
1375 if (src == dest)
1376 return or32(imm, dest);
1377 loadXorBlindedConstant(xorBlindConstant(imm), dest);
1378 or32(src, dest);
1379 } else
1380 or32(imm.asTrustedImm32(), src, dest);
1381 }
1382
1383 void or32(Imm32 imm, RegisterID dest)
1384 {
1385 if (shouldBlind(imm)) {
1386 BlindedImm32 key = orBlindedConstant(imm);
1387 or32(key.value1, dest);
1388 or32(key.value2, dest);
1389 } else
1390 or32(imm.asTrustedImm32(), dest);
1391 }
1392
1393 void poke(Imm32 value, int index = 0)
1394 {
1395 store32(value, addressForPoke(index));
1396 }
1397
1398 void poke(ImmPtr value, int index = 0)
1399 {
1400 storePtr(value, addressForPoke(index));
1401 }
1402
1403 #if CPU(X86_64) || CPU(ARM64)
1404 void poke(Imm64 value, int index = 0)
1405 {
1406 store64(value, addressForPoke(index));
1407 }
1408 #endif // CPU(X86_64)
1409
1410 void store32(Imm32 imm, Address dest)
1411 {
1412 if (shouldBlind(imm)) {
1413 #if CPU(X86) || CPU(X86_64)
1414 BlindedImm32 blind = xorBlindConstant(imm);
1415 store32(blind.value1, dest);
1416 xor32(blind.value2, dest);
1417 #else // CPU(X86) || CPU(X86_64)
1418 if (haveScratchRegisterForBlinding()) {
1419 loadXorBlindedConstant(xorBlindConstant(imm), scratchRegisterForBlinding());
1420 store32(scratchRegisterForBlinding(), dest);
1421 } else {
1422 // If we don't have a scratch register available for use, we'll just
1423 // place a random number of nops.
1424 uint32_t nopCount = random() & 3;
1425 while (nopCount--)
1426 nop();
1427 store32(imm.asTrustedImm32(), dest);
1428 }
1429 #endif // CPU(X86) || CPU(X86_64)
1430 } else
1431 store32(imm.asTrustedImm32(), dest);
1432 }
1433
1434 void sub32(Imm32 imm, RegisterID dest)
1435 {
1436 if (shouldBlind(imm)) {
1437 BlindedImm32 key = additionBlindedConstant(imm);
1438 sub32(key.value1, dest);
1439 sub32(key.value2, dest);
1440 } else
1441 sub32(imm.asTrustedImm32(), dest);
1442 }
1443
1444 void subPtr(Imm32 imm, RegisterID dest)
1445 {
1446 if (shouldBlind(imm)) {
1447 BlindedImm32 key = additionBlindedConstant(imm);
1448 subPtr(key.value1, dest);
1449 subPtr(key.value2, dest);
1450 } else
1451 subPtr(imm.asTrustedImm32(), dest);
1452 }
1453
1454 void xor32(Imm32 imm, RegisterID src, RegisterID dest)
1455 {
1456 if (shouldBlind(imm)) {
1457 BlindedImm32 blind = xorBlindConstant(imm);
1458 xor32(blind.value1, src, dest);
1459 xor32(blind.value2, dest);
1460 } else
1461 xor32(imm.asTrustedImm32(), src, dest);
1462 }
1463
1464 void xor32(Imm32 imm, RegisterID dest)
1465 {
1466 if (shouldBlind(imm)) {
1467 BlindedImm32 blind = xorBlindConstant(imm);
1468 xor32(blind.value1, dest);
1469 xor32(blind.value2, dest);
1470 } else
1471 xor32(imm.asTrustedImm32(), dest);
1472 }
1473
1474 Jump branch32(RelationalCondition cond, RegisterID left, Imm32 right)
1475 {
1476 if (shouldBlind(right)) {
1477 if (haveScratchRegisterForBlinding()) {
1478 loadXorBlindedConstant(xorBlindConstant(right), scratchRegisterForBlinding());
1479 return branch32(cond, left, scratchRegisterForBlinding());
1480 }
1481 // If we don't have a scratch register available for use, we'll just
1482 // place a random number of nops.
1483 uint32_t nopCount = random() & 3;
1484 while (nopCount--)
1485 nop();
1486 return branch32(cond, left, right.asTrustedImm32());
1487 }
1488
1489 return branch32(cond, left, right.asTrustedImm32());
1490 }
1491
1492 Jump branchAdd32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest)
1493 {
1494 if (src == dest)
1495 ASSERT(haveScratchRegisterForBlinding());
1496
1497 if (shouldBlind(imm)) {
1498 if (src == dest) {
1499 move(src, scratchRegisterForBlinding());
1500 src = scratchRegisterForBlinding();
1501 }
1502 loadXorBlindedConstant(xorBlindConstant(imm), dest);
1503 return branchAdd32(cond, src, dest);
1504 }
1505 return branchAdd32(cond, src, imm.asTrustedImm32(), dest);
1506 }
1507
1508 Jump branchMul32(ResultCondition cond, Imm32 imm, RegisterID src, RegisterID dest)
1509 {
1510 if (src == dest)
1511 ASSERT(haveScratchRegisterForBlinding());
1512
1513 if (shouldBlind(imm)) {
1514 if (src == dest) {
1515 move(src, scratchRegisterForBlinding());
1516 src = scratchRegisterForBlinding();
1517 }
1518 loadXorBlindedConstant(xorBlindConstant(imm), dest);
1519 return branchMul32(cond, src, dest);
1520 }
1521 return branchMul32(cond, imm.asTrustedImm32(), src, dest);
1522 }
1523
1524 // branchSub32 takes a scratch register as 32 bit platforms make use of this,
1525 // with src == dst, and on x86-32 we don't have a platform scratch register.
1526 Jump branchSub32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest, RegisterID scratch)
1527 {
1528 if (shouldBlind(imm)) {
1529 ASSERT(scratch != dest);
1530 ASSERT(scratch != src);
1531 loadXorBlindedConstant(xorBlindConstant(imm), scratch);
1532 return branchSub32(cond, src, scratch, dest);
1533 }
1534 return branchSub32(cond, src, imm.asTrustedImm32(), dest);
1535 }
1536
1537 void lshift32(Imm32 imm, RegisterID dest)
1538 {
1539 lshift32(trustedImm32ForShift(imm), dest);
1540 }
1541
1542 void lshift32(RegisterID src, Imm32 amount, RegisterID dest)
1543 {
1544 lshift32(src, trustedImm32ForShift(amount), dest);
1545 }
1546
1547 void rshift32(Imm32 imm, RegisterID dest)
1548 {
1549 rshift32(trustedImm32ForShift(imm), dest);
1550 }
1551
1552 void rshift32(RegisterID src, Imm32 amount, RegisterID dest)
1553 {
1554 rshift32(src, trustedImm32ForShift(amount), dest);
1555 }
1556
1557 void urshift32(Imm32 imm, RegisterID dest)
1558 {
1559 urshift32(trustedImm32ForShift(imm), dest);
1560 }
1561
1562 void urshift32(RegisterID src, Imm32 amount, RegisterID dest)
1563 {
1564 urshift32(src, trustedImm32ForShift(amount), dest);
1565 }
1566 };
1567
1568 } // namespace JSC
1569
1570 #else // ENABLE(ASSEMBLER)
1571
1572 // If there is no assembler for this platform, at least allow code to make references to
1573 // some of the things it would otherwise define, albeit without giving that code any way
1574 // of doing anything useful.
1575 class MacroAssembler {
1576 private:
1577 MacroAssembler() { }
1578
1579 public:
1580
1581 enum RegisterID { NoRegister };
1582 enum FPRegisterID { NoFPRegister };
1583 };
1584
1585 #endif // ENABLE(ASSEMBLER)
1586
1587 #endif // MacroAssembler_h