60be600dc749a380817aef6c9d092e90a74f9af3
[WebKit-https.git] / Source / JavaScriptCore / 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(X86_64)
121     using MacroAssemblerBase::branchPtr;
122 #endif // CPU(X86_64)
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 = abs(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)) {
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)) {
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)) {
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)) {
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