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