Merge "Save and re-bind previously bounded texture when using cairo_gl_surface_set_bi...
[framework/web/webkit-efl.git] / Source / JavaScriptCore / assembler / MacroAssembler.h
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef 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(ARM_TRADITIONAL)
36 #include "MacroAssemblerARM.h"
37 namespace JSC { typedef MacroAssemblerARM MacroAssemblerBase; };
38
39 #elif CPU(MIPS)
40 #include "MacroAssemblerMIPS.h"
41 namespace JSC {
42 typedef MacroAssemblerMIPS MacroAssemblerBase;
43 };
44
45 #elif CPU(X86)
46 #include "MacroAssemblerX86.h"
47 namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; };
48
49 #elif CPU(X86_64)
50 #include "MacroAssemblerX86_64.h"
51 namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; };
52
53 #elif CPU(SH4)
54 #include "MacroAssemblerSH4.h"
55 namespace JSC {
56 typedef MacroAssemblerSH4 MacroAssemblerBase;
57 };
58
59 #else
60 #error "The MacroAssembler is not supported on this platform."
61 #endif
62
63 namespace JSC {
64
65 class MacroAssembler : public MacroAssemblerBase {
66 public:
67
68     using MacroAssemblerBase::pop;
69     using MacroAssemblerBase::jump;
70     using MacroAssemblerBase::branch32;
71 #if CPU(X86_64)
72     using MacroAssemblerBase::branchPtr;
73     using MacroAssemblerBase::branchTestPtr;
74 #endif
75     using MacroAssemblerBase::move;
76
77 #if ENABLE(JIT_CONSTANT_BLINDING)
78     using MacroAssemblerBase::add32;
79     using MacroAssemblerBase::and32;
80     using MacroAssemblerBase::branchAdd32;
81     using MacroAssemblerBase::branchMul32;
82     using MacroAssemblerBase::branchSub32;
83     using MacroAssemblerBase::lshift32;
84     using MacroAssemblerBase::or32;
85     using MacroAssemblerBase::rshift32;
86     using MacroAssemblerBase::store32;
87     using MacroAssemblerBase::sub32;
88     using MacroAssemblerBase::urshift32;
89     using MacroAssemblerBase::xor32;
90 #endif
91
92     // Utilities used by the DFG JIT.
93 #if ENABLE(DFG_JIT)
94     using MacroAssemblerBase::invert;
95     
96     static DoubleCondition invert(DoubleCondition cond)
97     {
98         switch (cond) {
99         case DoubleEqual:
100             return DoubleNotEqualOrUnordered;
101         case DoubleNotEqual:
102             return DoubleEqualOrUnordered;
103         case DoubleGreaterThan:
104             return DoubleLessThanOrEqualOrUnordered;
105         case DoubleGreaterThanOrEqual:
106             return DoubleLessThanOrUnordered;
107         case DoubleLessThan:
108             return DoubleGreaterThanOrEqualOrUnordered;
109         case DoubleLessThanOrEqual:
110             return DoubleGreaterThanOrUnordered;
111         case DoubleEqualOrUnordered:
112             return DoubleNotEqual;
113         case DoubleNotEqualOrUnordered:
114             return DoubleEqual;
115         case DoubleGreaterThanOrUnordered:
116             return DoubleLessThanOrEqual;
117         case DoubleGreaterThanOrEqualOrUnordered:
118             return DoubleLessThan;
119         case DoubleLessThanOrUnordered:
120             return DoubleGreaterThanOrEqual;
121         case DoubleLessThanOrEqualOrUnordered:
122             return DoubleGreaterThan;
123         default:
124             ASSERT_NOT_REACHED();
125             return DoubleEqual; // make compiler happy
126         }
127     }
128     
129     static bool isInvertible(ResultCondition cond)
130     {
131         switch (cond) {
132         case Zero:
133         case NonZero:
134             return true;
135         default:
136             return false;
137         }
138     }
139     
140     static ResultCondition invert(ResultCondition cond)
141     {
142         switch (cond) {
143         case Zero:
144             return NonZero;
145         case NonZero:
146             return Zero;
147         default:
148             ASSERT_NOT_REACHED();
149             return Zero; // Make compiler happy for release builds.
150         }
151     }
152 #endif
153
154     // Platform agnostic onvenience functions,
155     // described in terms of other macro assembly methods.
156     void pop()
157     {
158         addPtr(TrustedImm32(sizeof(void*)), stackPointerRegister);
159     }
160     
161     void peek(RegisterID dest, int index = 0)
162     {
163         loadPtr(Address(stackPointerRegister, (index * sizeof(void*))), dest);
164     }
165
166     Address addressForPoke(int index)
167     {
168         return Address(stackPointerRegister, (index * sizeof(void*)));
169     }
170     
171     void poke(RegisterID src, int index = 0)
172     {
173         storePtr(src, addressForPoke(index));
174     }
175
176     void poke(TrustedImm32 value, int index = 0)
177     {
178         store32(value, addressForPoke(index));
179     }
180
181     void poke(TrustedImmPtr imm, int index = 0)
182     {
183         storePtr(imm, addressForPoke(index));
184     }
185
186
187     // Backwards banches, these are currently all implemented using existing forwards branch mechanisms.
188     void branchPtr(RelationalCondition cond, RegisterID op1, TrustedImmPtr imm, Label target)
189     {
190         branchPtr(cond, op1, imm).linkTo(target, this);
191     }
192     void branchPtr(RelationalCondition cond, RegisterID op1, ImmPtr imm, Label target)
193     {
194         branchPtr(cond, op1, imm).linkTo(target, this);
195     }
196
197     void branch32(RelationalCondition cond, RegisterID op1, RegisterID op2, Label target)
198     {
199         branch32(cond, op1, op2).linkTo(target, this);
200     }
201
202     void branch32(RelationalCondition cond, RegisterID op1, TrustedImm32 imm, Label target)
203     {
204         branch32(cond, op1, imm).linkTo(target, this);
205     }
206     
207     void branch32(RelationalCondition cond, RegisterID op1, Imm32 imm, Label target)
208     {
209         branch32(cond, op1, imm).linkTo(target, this);
210     }
211
212     void branch32(RelationalCondition cond, RegisterID left, Address right, Label target)
213     {
214         branch32(cond, left, right).linkTo(target, this);
215     }
216
217     Jump branch32(RelationalCondition cond, TrustedImm32 left, RegisterID right)
218     {
219         return branch32(commute(cond), right, left);
220     }
221
222     Jump branch32(RelationalCondition cond, Imm32 left, RegisterID right)
223     {
224         return branch32(commute(cond), right, left);
225     }
226
227     void branchTestPtr(ResultCondition cond, RegisterID reg, Label target)
228     {
229         branchTestPtr(cond, reg).linkTo(target, this);
230     }
231
232 #if !CPU(ARM_THUMB2)
233     PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
234     {
235         return PatchableJump(branchPtrWithPatch(cond, left, dataLabel, initialRightValue));
236     }
237
238     PatchableJump patchableJump()
239     {
240         return PatchableJump(jump());
241     }
242 #endif
243
244     void jump(Label target)
245     {
246         jump().linkTo(target, this);
247     }
248
249     // Commute a relational condition, returns a new condition that will produce
250     // the same results given the same inputs but with their positions exchanged.
251     static RelationalCondition commute(RelationalCondition condition)
252     {
253         switch (condition) {
254         case Above:
255             return Below;
256         case AboveOrEqual:
257             return BelowOrEqual;
258         case Below:
259             return Above;
260         case BelowOrEqual:
261             return AboveOrEqual;
262         case GreaterThan:
263             return LessThan;
264         case GreaterThanOrEqual:
265             return LessThanOrEqual;
266         case LessThan:
267             return GreaterThan;
268         case LessThanOrEqual:
269             return GreaterThanOrEqual;
270         default:
271             break;
272         }
273
274         ASSERT(condition == Equal || condition == NotEqual);
275         return condition;
276     }
277     
278
279     // Ptr methods
280     // On 32-bit platforms (i.e. x86), these methods directly map onto their 32-bit equivalents.
281     // FIXME: should this use a test for 32-bitness instead of this specific exception?
282 #if !CPU(X86_64)
283     void addPtr(Address src, RegisterID dest)
284     {
285         add32(src, dest);
286     }
287
288     void addPtr(AbsoluteAddress src, RegisterID dest)
289     {
290         add32(src, dest);
291     }
292
293     void addPtr(RegisterID src, RegisterID dest)
294     {
295         add32(src, dest);
296     }
297
298     void addPtr(TrustedImm32 imm, RegisterID srcDest)
299     {
300         add32(imm, srcDest);
301     }
302
303     void addPtr(TrustedImmPtr imm, RegisterID dest)
304     {
305         add32(TrustedImm32(imm), dest);
306     }
307
308     void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
309     {
310         add32(imm, src, dest);
311     }
312
313     void addPtr(TrustedImm32 imm, AbsoluteAddress address)
314     {
315         add32(imm, address);
316     }
317     
318     void andPtr(RegisterID src, RegisterID dest)
319     {
320         and32(src, dest);
321     }
322
323     void andPtr(TrustedImm32 imm, RegisterID srcDest)
324     {
325         and32(imm, srcDest);
326     }
327     
328     void negPtr(RegisterID dest)
329     {
330         neg32(dest);
331     }
332
333     void orPtr(RegisterID src, RegisterID dest)
334     {
335         or32(src, dest);
336     }
337
338     void orPtr(RegisterID op1, RegisterID op2, RegisterID dest)
339     {
340         or32(op1, op2, dest);
341     }
342
343     void orPtr(TrustedImmPtr imm, RegisterID dest)
344     {
345         or32(TrustedImm32(imm), dest);
346     }
347
348     void orPtr(TrustedImm32 imm, RegisterID dest)
349     {
350         or32(imm, dest);
351     }
352
353     void subPtr(RegisterID src, RegisterID dest)
354     {
355         sub32(src, dest);
356     }
357     
358     void subPtr(TrustedImm32 imm, RegisterID dest)
359     {
360         sub32(imm, dest);
361     }
362     
363     void subPtr(TrustedImmPtr imm, RegisterID dest)
364     {
365         sub32(TrustedImm32(imm), dest);
366     }
367
368     void xorPtr(RegisterID src, RegisterID dest)
369     {
370         xor32(src, dest);
371     }
372
373     void xorPtr(TrustedImm32 imm, RegisterID srcDest)
374     {
375         xor32(imm, srcDest);
376     }
377
378
379     void loadPtr(ImplicitAddress address, RegisterID dest)
380     {
381         load32(address, dest);
382     }
383
384     void loadPtr(BaseIndex address, RegisterID dest)
385     {
386         load32(address, dest);
387     }
388
389     void loadPtr(const void* address, RegisterID dest)
390     {
391         load32(address, dest);
392     }
393
394     DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
395     {
396         return load32WithAddressOffsetPatch(address, dest);
397     }
398     
399     DataLabelCompact loadPtrWithCompactAddressOffsetPatch(Address address, RegisterID dest)
400     {
401         return load32WithCompactAddressOffsetPatch(address, dest);
402     }
403
404     void move(ImmPtr imm, RegisterID dest)
405     {
406         move(Imm32(imm.asTrustedImmPtr()), dest);
407     }
408
409     void comparePtr(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
410     {
411         compare32(cond, left, right, dest);
412     }
413
414     void storePtr(RegisterID src, ImplicitAddress address)
415     {
416         store32(src, address);
417     }
418
419     void storePtr(RegisterID src, BaseIndex address)
420     {
421         store32(src, address);
422     }
423
424     void storePtr(RegisterID src, void* address)
425     {
426         store32(src, address);
427     }
428
429     void storePtr(TrustedImmPtr imm, ImplicitAddress address)
430     {
431         store32(TrustedImm32(imm), address);
432     }
433     
434     void storePtr(ImmPtr imm, Address address)
435     {
436         store32(Imm32(imm.asTrustedImmPtr()), address);
437     }
438
439     void storePtr(TrustedImmPtr imm, void* address)
440     {
441         store32(TrustedImm32(imm), address);
442     }
443
444     DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
445     {
446         return store32WithAddressOffsetPatch(src, address);
447     }
448
449     Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
450     {
451         return branch32(cond, left, right);
452     }
453
454     Jump branchPtr(RelationalCondition cond, RegisterID left, TrustedImmPtr right)
455     {
456         return branch32(cond, left, TrustedImm32(right));
457     }
458     
459     Jump branchPtr(RelationalCondition cond, RegisterID left, ImmPtr right)
460     {
461         return branch32(cond, left, Imm32(right.asTrustedImmPtr()));
462     }
463
464     Jump branchPtr(RelationalCondition cond, RegisterID left, Address right)
465     {
466         return branch32(cond, left, right);
467     }
468
469     Jump branchPtr(RelationalCondition cond, Address left, RegisterID right)
470     {
471         return branch32(cond, left, right);
472     }
473
474     Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
475     {
476         return branch32(cond, left, right);
477     }
478
479     Jump branchPtr(RelationalCondition cond, Address left, TrustedImmPtr right)
480     {
481         return branch32(cond, left, TrustedImm32(right));
482     }
483     
484     Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, TrustedImmPtr right)
485     {
486         return branch32(cond, left, TrustedImm32(right));
487     }
488
489     Jump branchTestPtr(ResultCondition cond, RegisterID reg, RegisterID mask)
490     {
491         return branchTest32(cond, reg, mask);
492     }
493
494     Jump branchTestPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
495     {
496         return branchTest32(cond, reg, mask);
497     }
498
499     Jump branchTestPtr(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
500     {
501         return branchTest32(cond, address, mask);
502     }
503
504     Jump branchTestPtr(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
505     {
506         return branchTest32(cond, address, mask);
507     }
508
509     Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
510     {
511         return branchAdd32(cond, src, dest);
512     }
513
514     Jump branchSubPtr(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
515     {
516         return branchSub32(cond, imm, dest);
517     }
518     using MacroAssemblerBase::branchTest8;
519     Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1))
520     {
521         return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask);
522     }
523 #else
524     
525 #if ENABLE(JIT_CONSTANT_BLINDING)
526     using MacroAssemblerBase::addPtr;
527     using MacroAssemblerBase::andPtr;
528     using MacroAssemblerBase::branchSubPtr;
529     using MacroAssemblerBase::convertInt32ToDouble;
530     using MacroAssemblerBase::storePtr;
531     using MacroAssemblerBase::subPtr;
532     using MacroAssemblerBase::xorPtr;
533     
534     bool shouldBlindDouble(double value)
535     {
536         // Don't trust NaN or +/-Infinity
537         if (!isfinite(value))
538             return true;
539
540         // Try to force normalisation, and check that there's no change
541         // in the bit pattern
542         if (bitwise_cast<uintptr_t>(value * 1.0) != bitwise_cast<uintptr_t>(value))
543             return true;
544
545         value = abs(value);
546         // Only allow a limited set of fractional components
547         double scaledValue = value * 8;
548         if (scaledValue / 8 != value)
549             return true;
550         double frac = scaledValue - floor(scaledValue);
551         if (frac != 0.0)
552             return true;
553
554         return value > 0xff;
555     }
556     
557     bool shouldBlind(ImmPtr imm)
558     { 
559 #if !defined(NDEBUG)
560         UNUSED_PARAM(imm);
561         // Debug always blind all constants, if only so we know
562         // if we've broken blinding during patch development.
563         return true;        
564 #endif
565
566         // First off we'll special case common, "safe" values to avoid hurting
567         // performance too much
568         uintptr_t value = imm.asTrustedImmPtr().asIntptr();
569         switch (value) {
570         case 0xffff:
571         case 0xffffff:
572         case 0xffffffffL:
573         case 0xffffffffffL:
574         case 0xffffffffffffL:
575         case 0xffffffffffffffL:
576         case 0xffffffffffffffffL:
577             return false;
578         default: {
579             if (value <= 0xff)
580                 return false;
581 #if CPU(X86_64)
582             JSValue jsValue = JSValue::decode(reinterpret_cast<void*>(value));
583             if (jsValue.isInt32())
584                 return shouldBlind(Imm32(jsValue.asInt32()));
585             if (jsValue.isDouble() && !shouldBlindDouble(jsValue.asDouble()))
586                 return false;
587
588             if (!shouldBlindDouble(bitwise_cast<double>(value)))
589                 return false;
590 #endif 
591         }
592         }
593         return shouldBlindForSpecificArch(value);
594     }
595     
596     struct RotatedImmPtr {
597         RotatedImmPtr(uintptr_t v1, uint8_t v2)
598             : value(v1)
599             , rotation(v2)
600         {
601         }
602         TrustedImmPtr value;
603         TrustedImm32 rotation;
604     };
605     
606     RotatedImmPtr rotationBlindConstant(ImmPtr imm)
607     {
608         uint8_t rotation = random() % (sizeof(void*) * 8);
609         uintptr_t value = imm.asTrustedImmPtr().asIntptr();
610         value = (value << rotation) | (value >> (sizeof(void*) * 8 - rotation));
611         return RotatedImmPtr(value, rotation);
612     }
613     
614     void loadRotationBlindedConstant(RotatedImmPtr constant, RegisterID dest)
615     {
616         move(constant.value, dest);
617         rotateRightPtr(constant.rotation, dest);
618     }
619
620     void convertInt32ToDouble(Imm32 imm, FPRegisterID dest)
621     {
622         if (shouldBlind(imm)) {
623             RegisterID scratchRegister = scratchRegisterForBlinding();
624             loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister);
625             convertInt32ToDouble(scratchRegister, dest);
626         } else
627             convertInt32ToDouble(imm.asTrustedImm32(), dest);
628     }
629
630     void move(ImmPtr imm, RegisterID dest)
631     {
632         if (shouldBlind(imm))
633             loadRotationBlindedConstant(rotationBlindConstant(imm), dest);
634         else
635             move(imm.asTrustedImmPtr(), dest);
636     }
637
638     Jump branchPtr(RelationalCondition cond, RegisterID left, ImmPtr right)
639     {
640         if (shouldBlind(right)) {
641             RegisterID scratchRegister = scratchRegisterForBlinding();
642             loadRotationBlindedConstant(rotationBlindConstant(right), scratchRegister);
643             return branchPtr(cond, left, scratchRegister);
644         }
645         return branchPtr(cond, left, right.asTrustedImmPtr());
646     }
647     
648     void storePtr(ImmPtr imm, Address dest)
649     {
650         if (shouldBlind(imm)) {
651             RegisterID scratchRegister = scratchRegisterForBlinding();
652             loadRotationBlindedConstant(rotationBlindConstant(imm), scratchRegister);
653             storePtr(scratchRegister, dest);
654         } else
655             storePtr(imm.asTrustedImmPtr(), dest);
656     }
657
658 #endif
659
660 #endif // !CPU(X86_64)
661
662 #if ENABLE(JIT_CONSTANT_BLINDING)
663     bool shouldBlind(Imm32 imm)
664     { 
665 #if !defined(NDEBUG)
666         UNUSED_PARAM(imm);
667         // Debug always blind all constants, if only so we know
668         // if we've broken blinding during patch development.
669         return true;
670 #else
671
672         // First off we'll special case common, "safe" values to avoid hurting
673         // performance too much
674         uint32_t value = imm.asTrustedImm32().m_value;
675         switch (value) {
676         case 0xffff:
677         case 0xffffff:
678         case 0xffffffff:
679             return false;
680         default:
681             if (value <= 0xff)
682                 return false;
683         }
684         return shouldBlindForSpecificArch(value);
685 #endif
686     }
687
688     struct BlindedImm32 {
689         BlindedImm32(int32_t v1, int32_t v2)
690             : value1(v1)
691             , value2(v2)
692         {
693         }
694         TrustedImm32 value1;
695         TrustedImm32 value2;
696     };
697
698     uint32_t keyForConstant(uint32_t value, uint32_t& mask)
699     {
700         uint32_t key = random();
701         if (value <= 0xff)
702             mask = 0xff;
703         else if (value <= 0xffff)
704             mask = 0xffff;
705         else if (value <= 0xffffff)
706             mask = 0xffffff;
707         else
708             mask = 0xffffffff;
709         return key & mask;
710     }
711
712     uint32_t keyForConstant(uint32_t value)
713     {
714         uint32_t mask = 0;
715         return keyForConstant(value, mask);
716     }
717
718     BlindedImm32 xorBlindConstant(Imm32 imm)
719     {
720         uint32_t baseValue = imm.asTrustedImm32().m_value;
721         uint32_t key = keyForConstant(baseValue);
722         return BlindedImm32(baseValue ^ key, key);
723     }
724
725     BlindedImm32 additionBlindedConstant(Imm32 imm)
726     {
727         // The addition immediate may be used as a pointer offset. Keep aligned based on "imm".
728         static uint32_t maskTable[4] = { 0xfffffffc, 0xffffffff, 0xfffffffe, 0xffffffff };
729
730         uint32_t baseValue = imm.asTrustedImm32().m_value;
731         uint32_t key = keyForConstant(baseValue) & maskTable[baseValue & 3];
732         if (key > baseValue)
733             key = key - baseValue;
734         return BlindedImm32(baseValue - key, key);
735     }
736     
737     BlindedImm32 andBlindedConstant(Imm32 imm)
738     {
739         uint32_t baseValue = imm.asTrustedImm32().m_value;
740         uint32_t mask = 0;
741         uint32_t key = keyForConstant(baseValue, mask);
742         ASSERT((baseValue & mask) == baseValue);
743         return BlindedImm32(((baseValue & key) | ~key) & mask, ((baseValue & ~key) | key) & mask);
744     }
745     
746     BlindedImm32 orBlindedConstant(Imm32 imm)
747     {
748         uint32_t baseValue = imm.asTrustedImm32().m_value;
749         uint32_t mask = 0;
750         uint32_t key = keyForConstant(baseValue, mask);
751         ASSERT((baseValue & mask) == baseValue);
752         return BlindedImm32((baseValue & key) & mask, (baseValue & ~key) & mask);
753     }
754     
755     void loadXorBlindedConstant(BlindedImm32 constant, RegisterID dest)
756     {
757         move(constant.value1, dest);
758         xor32(constant.value2, dest);
759     }
760     
761     void add32(Imm32 imm, RegisterID dest)
762     {
763         if (shouldBlind(imm)) {
764             BlindedImm32 key = additionBlindedConstant(imm);
765             add32(key.value1, dest);
766             add32(key.value2, dest);
767         } else
768             add32(imm.asTrustedImm32(), dest);
769     }
770     
771     void addPtr(Imm32 imm, RegisterID dest)
772     {
773         if (shouldBlind(imm)) {
774             BlindedImm32 key = additionBlindedConstant(imm);
775             addPtr(key.value1, dest);
776             addPtr(key.value2, dest);
777         } else
778             addPtr(imm.asTrustedImm32(), dest);
779     }
780
781     void and32(Imm32 imm, RegisterID dest)
782     {
783         if (shouldBlind(imm)) {
784             BlindedImm32 key = andBlindedConstant(imm);
785             and32(key.value1, dest);
786             and32(key.value2, dest);
787         } else
788             and32(imm.asTrustedImm32(), dest);
789     }
790
791     void andPtr(Imm32 imm, RegisterID dest)
792     {
793         if (shouldBlind(imm)) {
794             BlindedImm32 key = andBlindedConstant(imm);
795             andPtr(key.value1, dest);
796             andPtr(key.value2, dest);
797         } else
798             andPtr(imm.asTrustedImm32(), dest);
799     }
800     
801     void and32(Imm32 imm, RegisterID src, RegisterID dest)
802     {
803         if (shouldBlind(imm)) {
804             if (src == dest)
805                 return and32(imm.asTrustedImm32(), dest);
806             loadXorBlindedConstant(xorBlindConstant(imm), dest);
807             and32(src, dest);
808         } else
809             and32(imm.asTrustedImm32(), src, dest);
810     }
811
812     void move(Imm32 imm, RegisterID dest)
813     {
814         if (shouldBlind(imm))
815             loadXorBlindedConstant(xorBlindConstant(imm), dest);
816         else
817             move(imm.asTrustedImm32(), dest);
818     }
819     
820     void or32(Imm32 imm, RegisterID src, RegisterID dest)
821     {
822         if (shouldBlind(imm)) {
823             if (src == dest)
824                 return or32(imm, dest);
825             loadXorBlindedConstant(xorBlindConstant(imm), dest);
826             or32(src, dest);
827         } else
828             or32(imm.asTrustedImm32(), src, dest);
829     }
830     
831     void or32(Imm32 imm, RegisterID dest)
832     {
833         if (shouldBlind(imm)) {
834             BlindedImm32 key = orBlindedConstant(imm);
835             or32(key.value1, dest);
836             or32(key.value2, dest);
837         } else
838             or32(imm.asTrustedImm32(), dest);
839     }
840     
841     void poke(Imm32 value, int index = 0)
842     {
843         store32(value, addressForPoke(index));
844     }
845     
846     void poke(ImmPtr value, int index = 0)
847     {
848         storePtr(value, addressForPoke(index));
849     }
850     
851     void store32(Imm32 imm, Address dest)
852     {
853         if (shouldBlind(imm)) {
854 #if CPU(X86) || CPU(X86_64)
855             BlindedImm32 blind = xorBlindConstant(imm);
856             store32(blind.value1, dest);
857             xor32(blind.value2, dest);
858 #else
859             if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
860                 loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister);
861                 store32(scratchRegister, dest);
862             } else {
863                 // If we don't have a scratch register available for use, we'll just 
864                 // place a random number of nops.
865                 uint32_t nopCount = random() & 3;
866                 while (nopCount--)
867                     nop();
868                 store32(imm.asTrustedImm32(), dest);
869             }
870 #endif
871         } else
872             store32(imm.asTrustedImm32(), dest);
873     }
874     
875     void sub32(Imm32 imm, RegisterID dest)
876     {
877         if (shouldBlind(imm)) {
878             BlindedImm32 key = additionBlindedConstant(imm);
879             sub32(key.value1, dest);
880             sub32(key.value2, dest);
881         } else
882             sub32(imm.asTrustedImm32(), dest);
883     }
884     
885     void subPtr(Imm32 imm, RegisterID dest)
886     {
887         if (shouldBlind(imm)) {
888             BlindedImm32 key = additionBlindedConstant(imm);
889             subPtr(key.value1, dest);
890             subPtr(key.value2, dest);
891         } else
892             subPtr(imm.asTrustedImm32(), dest);
893     }
894     
895     void xor32(Imm32 imm, RegisterID src, RegisterID dest)
896     {
897         if (shouldBlind(imm)) {
898             BlindedImm32 blind = xorBlindConstant(imm);
899             xor32(blind.value1, src, dest);
900             xor32(blind.value2, dest);
901         } else
902             xor32(imm.asTrustedImm32(), src, dest);
903     }
904     
905     void xor32(Imm32 imm, RegisterID dest)
906     {
907         if (shouldBlind(imm)) {
908             BlindedImm32 blind = xorBlindConstant(imm);
909             xor32(blind.value1, dest);
910             xor32(blind.value2, dest);
911         } else
912             xor32(imm.asTrustedImm32(), dest);
913     }
914
915     Jump branch32(RelationalCondition cond, RegisterID left, Imm32 right)
916     {
917         if (shouldBlind(right)) {
918             if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
919                 loadXorBlindedConstant(xorBlindConstant(right), scratchRegister);
920                 return branch32(cond, left, scratchRegister);
921             }
922             // If we don't have a scratch register available for use, we'll just 
923             // place a random number of nops.
924             uint32_t nopCount = random() & 3;
925             while (nopCount--)
926                 nop();
927             return branch32(cond, left, right.asTrustedImm32());
928         }
929         
930         return branch32(cond, left, right.asTrustedImm32());
931     }
932
933     Jump branchAdd32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest)
934     {
935         if (src == dest) {
936             if (!scratchRegisterForBlinding()) {
937                 // Release mode ASSERT, if this fails we will perform incorrect codegen.
938                 CRASH();
939             }
940         }
941         if (shouldBlind(imm)) {
942             if (src == dest) {
943                 if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
944                     move(src, scratchRegister);
945                     src = scratchRegister;
946                 }
947             }
948             loadXorBlindedConstant(xorBlindConstant(imm), dest);
949             return branchAdd32(cond, src, dest);  
950         }
951         return branchAdd32(cond, src, imm.asTrustedImm32(), dest);            
952     }
953     
954     Jump branchMul32(ResultCondition cond, Imm32 imm, RegisterID src, RegisterID dest)
955     {
956         if (src == dest) {
957             if (!scratchRegisterForBlinding()) {
958                 // Release mode ASSERT, if this fails we will perform incorrect codegen.
959                 CRASH();
960             }
961         }
962         if (shouldBlind(imm)) {
963             if (src == dest) {
964                 if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
965                     move(src, scratchRegister);
966                     src = scratchRegister;
967                 }
968             }
969             loadXorBlindedConstant(xorBlindConstant(imm), dest);
970             return branchMul32(cond, src, dest);  
971         }
972         return branchMul32(cond, imm.asTrustedImm32(), src, dest);
973     }
974
975     // branchSub32 takes a scratch register as 32 bit platforms make use of this,
976     // with src == dst, and on x86-32 we don't have a platform scratch register.
977     Jump branchSub32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest, RegisterID scratch)
978     {
979         if (shouldBlind(imm)) {
980             ASSERT(scratch != dest);
981             ASSERT(scratch != src);
982             loadXorBlindedConstant(xorBlindConstant(imm), scratch);
983             return branchSub32(cond, src, scratch, dest);
984         }
985         return branchSub32(cond, src, imm.asTrustedImm32(), dest);            
986     }
987     
988     // Immediate shifts only have 5 controllable bits
989     // so we'll consider them safe for now.
990     TrustedImm32 trustedImm32ForShift(Imm32 imm)
991     {
992         return TrustedImm32(imm.asTrustedImm32().m_value & 31);
993     }
994
995     void lshift32(Imm32 imm, RegisterID dest)
996     {
997         lshift32(trustedImm32ForShift(imm), dest);
998     }
999     
1000     void lshift32(RegisterID src, Imm32 amount, RegisterID dest)
1001     {
1002         lshift32(src, trustedImm32ForShift(amount), dest);
1003     }
1004     
1005     void rshift32(Imm32 imm, RegisterID dest)
1006     {
1007         rshift32(trustedImm32ForShift(imm), dest);
1008     }
1009     
1010     void rshift32(RegisterID src, Imm32 amount, RegisterID dest)
1011     {
1012         rshift32(src, trustedImm32ForShift(amount), dest);
1013     }
1014     
1015     void urshift32(Imm32 imm, RegisterID dest)
1016     {
1017         urshift32(trustedImm32ForShift(imm), dest);
1018     }
1019     
1020     void urshift32(RegisterID src, Imm32 amount, RegisterID dest)
1021     {
1022         urshift32(src, trustedImm32ForShift(amount), dest);
1023     }
1024 #endif
1025 };
1026
1027 } // namespace JSC
1028
1029 #else // ENABLE(ASSEMBLER)
1030
1031 // If there is no assembler for this platform, at least allow code to make references to
1032 // some of the things it would otherwise define, albeit without giving that code any way
1033 // of doing anything useful.
1034 class MacroAssembler {
1035 private:
1036     MacroAssembler() { }
1037     
1038 public:
1039     
1040     enum RegisterID { NoRegister };
1041     enum FPRegisterID { NoFPRegister };
1042 };
1043
1044 #endif // ENABLE(ASSEMBLER)
1045
1046 #endif // MacroAssembler_h