2 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef MacroAssembler_h
27 #define MacroAssembler_h
32 #include "MacroAssemblerARMv7.h"
33 namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; };
35 #elif CPU(ARM_TRADITIONAL)
36 #include "MacroAssemblerARM.h"
37 namespace JSC { typedef MacroAssemblerARM MacroAssemblerBase; };
40 #include "MacroAssemblerMIPS.h"
42 typedef MacroAssemblerMIPS MacroAssemblerBase;
46 #include "MacroAssemblerX86.h"
47 namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; };
50 #include "MacroAssemblerX86_64.h"
51 namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; };
54 #include "MacroAssemblerSH4.h"
56 typedef MacroAssemblerSH4 MacroAssemblerBase;
60 #error "The MacroAssembler is not supported on this platform."
65 class MacroAssembler : public MacroAssemblerBase {
68 using MacroAssemblerBase::pop;
69 using MacroAssemblerBase::jump;
70 using MacroAssemblerBase::branch32;
72 using MacroAssemblerBase::branchPtr;
73 using MacroAssemblerBase::branchTestPtr;
75 using MacroAssemblerBase::move;
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;
92 // Utilities used by the DFG JIT.
94 using MacroAssemblerBase::invert;
96 static DoubleCondition invert(DoubleCondition cond)
100 return DoubleNotEqualOrUnordered;
102 return DoubleEqualOrUnordered;
103 case DoubleGreaterThan:
104 return DoubleLessThanOrEqualOrUnordered;
105 case DoubleGreaterThanOrEqual:
106 return DoubleLessThanOrUnordered;
108 return DoubleGreaterThanOrEqualOrUnordered;
109 case DoubleLessThanOrEqual:
110 return DoubleGreaterThanOrUnordered;
111 case DoubleEqualOrUnordered:
112 return DoubleNotEqual;
113 case DoubleNotEqualOrUnordered:
115 case DoubleGreaterThanOrUnordered:
116 return DoubleLessThanOrEqual;
117 case DoubleGreaterThanOrEqualOrUnordered:
118 return DoubleLessThan;
119 case DoubleLessThanOrUnordered:
120 return DoubleGreaterThanOrEqual;
121 case DoubleLessThanOrEqualOrUnordered:
122 return DoubleGreaterThan;
124 ASSERT_NOT_REACHED();
125 return DoubleEqual; // make compiler happy
129 static bool isInvertible(ResultCondition cond)
140 static ResultCondition invert(ResultCondition cond)
148 ASSERT_NOT_REACHED();
149 return Zero; // Make compiler happy for release builds.
154 // Platform agnostic onvenience functions,
155 // described in terms of other macro assembly methods.
158 addPtr(TrustedImm32(sizeof(void*)), stackPointerRegister);
161 void peek(RegisterID dest, int index = 0)
163 loadPtr(Address(stackPointerRegister, (index * sizeof(void*))), dest);
166 Address addressForPoke(int index)
168 return Address(stackPointerRegister, (index * sizeof(void*)));
171 void poke(RegisterID src, int index = 0)
173 storePtr(src, addressForPoke(index));
176 void poke(TrustedImm32 value, int index = 0)
178 store32(value, addressForPoke(index));
181 void poke(TrustedImmPtr imm, int index = 0)
183 storePtr(imm, addressForPoke(index));
187 // Backwards banches, these are currently all implemented using existing forwards branch mechanisms.
188 void branchPtr(RelationalCondition cond, RegisterID op1, TrustedImmPtr imm, Label target)
190 branchPtr(cond, op1, imm).linkTo(target, this);
192 void branchPtr(RelationalCondition cond, RegisterID op1, ImmPtr imm, Label target)
194 branchPtr(cond, op1, imm).linkTo(target, this);
197 void branch32(RelationalCondition cond, RegisterID op1, RegisterID op2, Label target)
199 branch32(cond, op1, op2).linkTo(target, this);
202 void branch32(RelationalCondition cond, RegisterID op1, TrustedImm32 imm, Label target)
204 branch32(cond, op1, imm).linkTo(target, this);
207 void branch32(RelationalCondition cond, RegisterID op1, Imm32 imm, Label target)
209 branch32(cond, op1, imm).linkTo(target, this);
212 void branch32(RelationalCondition cond, RegisterID left, Address right, Label target)
214 branch32(cond, left, right).linkTo(target, this);
217 Jump branch32(RelationalCondition cond, TrustedImm32 left, RegisterID right)
219 return branch32(commute(cond), right, left);
222 Jump branch32(RelationalCondition cond, Imm32 left, RegisterID right)
224 return branch32(commute(cond), right, left);
227 void branchTestPtr(ResultCondition cond, RegisterID reg, Label target)
229 branchTestPtr(cond, reg).linkTo(target, this);
233 PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
235 return PatchableJump(branchPtrWithPatch(cond, left, dataLabel, initialRightValue));
238 PatchableJump patchableJump()
240 return PatchableJump(jump());
244 void jump(Label target)
246 jump().linkTo(target, this);
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)
264 case GreaterThanOrEqual:
265 return LessThanOrEqual;
268 case LessThanOrEqual:
269 return GreaterThanOrEqual;
274 ASSERT(condition == Equal || condition == NotEqual);
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?
283 void addPtr(Address src, RegisterID dest)
288 void addPtr(AbsoluteAddress src, RegisterID dest)
293 void addPtr(RegisterID src, RegisterID dest)
298 void addPtr(TrustedImm32 imm, RegisterID srcDest)
303 void addPtr(TrustedImmPtr imm, RegisterID dest)
305 add32(TrustedImm32(imm), dest);
308 void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
310 add32(imm, src, dest);
313 void addPtr(TrustedImm32 imm, AbsoluteAddress address)
318 void andPtr(RegisterID src, RegisterID dest)
323 void andPtr(TrustedImm32 imm, RegisterID srcDest)
328 void negPtr(RegisterID dest)
333 void orPtr(RegisterID src, RegisterID dest)
338 void orPtr(RegisterID op1, RegisterID op2, RegisterID dest)
340 or32(op1, op2, dest);
343 void orPtr(TrustedImmPtr imm, RegisterID dest)
345 or32(TrustedImm32(imm), dest);
348 void orPtr(TrustedImm32 imm, RegisterID dest)
353 void subPtr(RegisterID src, RegisterID dest)
358 void subPtr(TrustedImm32 imm, RegisterID dest)
363 void subPtr(TrustedImmPtr imm, RegisterID dest)
365 sub32(TrustedImm32(imm), dest);
368 void xorPtr(RegisterID src, RegisterID dest)
373 void xorPtr(TrustedImm32 imm, RegisterID srcDest)
379 void loadPtr(ImplicitAddress address, RegisterID dest)
381 load32(address, dest);
384 void loadPtr(BaseIndex address, RegisterID dest)
386 load32(address, dest);
389 void loadPtr(const void* address, RegisterID dest)
391 load32(address, dest);
394 DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
396 return load32WithAddressOffsetPatch(address, dest);
399 DataLabelCompact loadPtrWithCompactAddressOffsetPatch(Address address, RegisterID dest)
401 return load32WithCompactAddressOffsetPatch(address, dest);
404 void move(ImmPtr imm, RegisterID dest)
406 move(Imm32(imm.asTrustedImmPtr()), dest);
409 void comparePtr(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
411 compare32(cond, left, right, dest);
414 void storePtr(RegisterID src, ImplicitAddress address)
416 store32(src, address);
419 void storePtr(RegisterID src, BaseIndex address)
421 store32(src, address);
424 void storePtr(RegisterID src, void* address)
426 store32(src, address);
429 void storePtr(TrustedImmPtr imm, ImplicitAddress address)
431 store32(TrustedImm32(imm), address);
434 void storePtr(ImmPtr imm, Address address)
436 store32(Imm32(imm.asTrustedImmPtr()), address);
439 void storePtr(TrustedImmPtr imm, void* address)
441 store32(TrustedImm32(imm), address);
444 DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
446 return store32WithAddressOffsetPatch(src, address);
449 Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
451 return branch32(cond, left, right);
454 Jump branchPtr(RelationalCondition cond, RegisterID left, TrustedImmPtr right)
456 return branch32(cond, left, TrustedImm32(right));
459 Jump branchPtr(RelationalCondition cond, RegisterID left, ImmPtr right)
461 return branch32(cond, left, Imm32(right.asTrustedImmPtr()));
464 Jump branchPtr(RelationalCondition cond, RegisterID left, Address right)
466 return branch32(cond, left, right);
469 Jump branchPtr(RelationalCondition cond, Address left, RegisterID right)
471 return branch32(cond, left, right);
474 Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
476 return branch32(cond, left, right);
479 Jump branchPtr(RelationalCondition cond, Address left, TrustedImmPtr right)
481 return branch32(cond, left, TrustedImm32(right));
484 Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, TrustedImmPtr right)
486 return branch32(cond, left, TrustedImm32(right));
489 Jump branchTestPtr(ResultCondition cond, RegisterID reg, RegisterID mask)
491 return branchTest32(cond, reg, mask);
494 Jump branchTestPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
496 return branchTest32(cond, reg, mask);
499 Jump branchTestPtr(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
501 return branchTest32(cond, address, mask);
504 Jump branchTestPtr(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
506 return branchTest32(cond, address, mask);
509 Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
511 return branchAdd32(cond, src, dest);
514 Jump branchSubPtr(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
516 return branchSub32(cond, imm, dest);
518 using MacroAssemblerBase::branchTest8;
519 Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1))
521 return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask);
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;
534 bool shouldBlindDouble(double value)
536 // Don't trust NaN or +/-Infinity
537 if (!isfinite(value))
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))
546 // Only allow a limited set of fractional components
547 double scaledValue = value * 8;
548 if (scaledValue / 8 != value)
550 double frac = scaledValue - floor(scaledValue);
557 bool shouldBlind(ImmPtr imm)
561 // Debug always blind all constants, if only so we know
562 // if we've broken blinding during patch development.
566 // First off we'll special case common, "safe" values to avoid hurting
567 // performance too much
568 uintptr_t value = imm.asTrustedImmPtr().asIntptr();
574 case 0xffffffffffffL:
575 case 0xffffffffffffffL:
576 case 0xffffffffffffffffL:
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()))
588 if (!shouldBlindDouble(bitwise_cast<double>(value)))
593 return shouldBlindForSpecificArch(value);
596 struct RotatedImmPtr {
597 RotatedImmPtr(uintptr_t v1, uint8_t v2)
603 TrustedImm32 rotation;
606 RotatedImmPtr rotationBlindConstant(ImmPtr imm)
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);
614 void loadRotationBlindedConstant(RotatedImmPtr constant, RegisterID dest)
616 move(constant.value, dest);
617 rotateRightPtr(constant.rotation, dest);
620 void convertInt32ToDouble(Imm32 imm, FPRegisterID dest)
622 if (shouldBlind(imm)) {
623 RegisterID scratchRegister = scratchRegisterForBlinding();
624 loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister);
625 convertInt32ToDouble(scratchRegister, dest);
627 convertInt32ToDouble(imm.asTrustedImm32(), dest);
630 void move(ImmPtr imm, RegisterID dest)
632 if (shouldBlind(imm))
633 loadRotationBlindedConstant(rotationBlindConstant(imm), dest);
635 move(imm.asTrustedImmPtr(), dest);
638 Jump branchPtr(RelationalCondition cond, RegisterID left, ImmPtr right)
640 if (shouldBlind(right)) {
641 RegisterID scratchRegister = scratchRegisterForBlinding();
642 loadRotationBlindedConstant(rotationBlindConstant(right), scratchRegister);
643 return branchPtr(cond, left, scratchRegister);
645 return branchPtr(cond, left, right.asTrustedImmPtr());
648 void storePtr(ImmPtr imm, Address dest)
650 if (shouldBlind(imm)) {
651 RegisterID scratchRegister = scratchRegisterForBlinding();
652 loadRotationBlindedConstant(rotationBlindConstant(imm), scratchRegister);
653 storePtr(scratchRegister, dest);
655 storePtr(imm.asTrustedImmPtr(), dest);
660 #endif // !CPU(X86_64)
662 #if ENABLE(JIT_CONSTANT_BLINDING)
663 bool shouldBlind(Imm32 imm)
667 // Debug always blind all constants, if only so we know
668 // if we've broken blinding during patch development.
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;
684 return shouldBlindForSpecificArch(value);
688 struct BlindedImm32 {
689 BlindedImm32(int32_t v1, int32_t v2)
698 uint32_t keyForConstant(uint32_t value, uint32_t& mask)
700 uint32_t key = random();
703 else if (value <= 0xffff)
705 else if (value <= 0xffffff)
712 uint32_t keyForConstant(uint32_t value)
715 return keyForConstant(value, mask);
718 BlindedImm32 xorBlindConstant(Imm32 imm)
720 uint32_t baseValue = imm.asTrustedImm32().m_value;
721 uint32_t key = keyForConstant(baseValue);
722 return BlindedImm32(baseValue ^ key, key);
725 BlindedImm32 additionBlindedConstant(Imm32 imm)
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 };
730 uint32_t baseValue = imm.asTrustedImm32().m_value;
731 uint32_t key = keyForConstant(baseValue) & maskTable[baseValue & 3];
733 key = key - baseValue;
734 return BlindedImm32(baseValue - key, key);
737 BlindedImm32 andBlindedConstant(Imm32 imm)
739 uint32_t baseValue = imm.asTrustedImm32().m_value;
741 uint32_t key = keyForConstant(baseValue, mask);
742 ASSERT((baseValue & mask) == baseValue);
743 return BlindedImm32(((baseValue & key) | ~key) & mask, ((baseValue & ~key) | key) & mask);
746 BlindedImm32 orBlindedConstant(Imm32 imm)
748 uint32_t baseValue = imm.asTrustedImm32().m_value;
750 uint32_t key = keyForConstant(baseValue, mask);
751 ASSERT((baseValue & mask) == baseValue);
752 return BlindedImm32((baseValue & key) & mask, (baseValue & ~key) & mask);
755 void loadXorBlindedConstant(BlindedImm32 constant, RegisterID dest)
757 move(constant.value1, dest);
758 xor32(constant.value2, dest);
761 void add32(Imm32 imm, RegisterID dest)
763 if (shouldBlind(imm)) {
764 BlindedImm32 key = additionBlindedConstant(imm);
765 add32(key.value1, dest);
766 add32(key.value2, dest);
768 add32(imm.asTrustedImm32(), dest);
771 void addPtr(Imm32 imm, RegisterID dest)
773 if (shouldBlind(imm)) {
774 BlindedImm32 key = additionBlindedConstant(imm);
775 addPtr(key.value1, dest);
776 addPtr(key.value2, dest);
778 addPtr(imm.asTrustedImm32(), dest);
781 void and32(Imm32 imm, RegisterID dest)
783 if (shouldBlind(imm)) {
784 BlindedImm32 key = andBlindedConstant(imm);
785 and32(key.value1, dest);
786 and32(key.value2, dest);
788 and32(imm.asTrustedImm32(), dest);
791 void andPtr(Imm32 imm, RegisterID dest)
793 if (shouldBlind(imm)) {
794 BlindedImm32 key = andBlindedConstant(imm);
795 andPtr(key.value1, dest);
796 andPtr(key.value2, dest);
798 andPtr(imm.asTrustedImm32(), dest);
801 void and32(Imm32 imm, RegisterID src, RegisterID dest)
803 if (shouldBlind(imm)) {
805 return and32(imm.asTrustedImm32(), dest);
806 loadXorBlindedConstant(xorBlindConstant(imm), dest);
809 and32(imm.asTrustedImm32(), src, dest);
812 void move(Imm32 imm, RegisterID dest)
814 if (shouldBlind(imm))
815 loadXorBlindedConstant(xorBlindConstant(imm), dest);
817 move(imm.asTrustedImm32(), dest);
820 void or32(Imm32 imm, RegisterID src, RegisterID dest)
822 if (shouldBlind(imm)) {
824 return or32(imm, dest);
825 loadXorBlindedConstant(xorBlindConstant(imm), dest);
828 or32(imm.asTrustedImm32(), src, dest);
831 void or32(Imm32 imm, RegisterID dest)
833 if (shouldBlind(imm)) {
834 BlindedImm32 key = orBlindedConstant(imm);
835 or32(key.value1, dest);
836 or32(key.value2, dest);
838 or32(imm.asTrustedImm32(), dest);
841 void poke(Imm32 value, int index = 0)
843 store32(value, addressForPoke(index));
846 void poke(ImmPtr value, int index = 0)
848 storePtr(value, addressForPoke(index));
851 void store32(Imm32 imm, Address dest)
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);
859 if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
860 loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister);
861 store32(scratchRegister, dest);
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;
868 store32(imm.asTrustedImm32(), dest);
872 store32(imm.asTrustedImm32(), dest);
875 void sub32(Imm32 imm, RegisterID dest)
877 if (shouldBlind(imm)) {
878 BlindedImm32 key = additionBlindedConstant(imm);
879 sub32(key.value1, dest);
880 sub32(key.value2, dest);
882 sub32(imm.asTrustedImm32(), dest);
885 void subPtr(Imm32 imm, RegisterID dest)
887 if (shouldBlind(imm)) {
888 BlindedImm32 key = additionBlindedConstant(imm);
889 subPtr(key.value1, dest);
890 subPtr(key.value2, dest);
892 subPtr(imm.asTrustedImm32(), dest);
895 void xor32(Imm32 imm, RegisterID src, RegisterID dest)
897 if (shouldBlind(imm)) {
898 BlindedImm32 blind = xorBlindConstant(imm);
899 xor32(blind.value1, src, dest);
900 xor32(blind.value2, dest);
902 xor32(imm.asTrustedImm32(), src, dest);
905 void xor32(Imm32 imm, RegisterID dest)
907 if (shouldBlind(imm)) {
908 BlindedImm32 blind = xorBlindConstant(imm);
909 xor32(blind.value1, dest);
910 xor32(blind.value2, dest);
912 xor32(imm.asTrustedImm32(), dest);
915 Jump branch32(RelationalCondition cond, RegisterID left, Imm32 right)
917 if (shouldBlind(right)) {
918 if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
919 loadXorBlindedConstant(xorBlindConstant(right), scratchRegister);
920 return branch32(cond, left, scratchRegister);
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;
927 return branch32(cond, left, right.asTrustedImm32());
930 return branch32(cond, left, right.asTrustedImm32());
933 Jump branchAdd32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest)
936 if (!scratchRegisterForBlinding()) {
937 // Release mode ASSERT, if this fails we will perform incorrect codegen.
941 if (shouldBlind(imm)) {
943 if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
944 move(src, scratchRegister);
945 src = scratchRegister;
948 loadXorBlindedConstant(xorBlindConstant(imm), dest);
949 return branchAdd32(cond, src, dest);
951 return branchAdd32(cond, src, imm.asTrustedImm32(), dest);
954 Jump branchMul32(ResultCondition cond, Imm32 imm, RegisterID src, RegisterID dest)
957 if (!scratchRegisterForBlinding()) {
958 // Release mode ASSERT, if this fails we will perform incorrect codegen.
962 if (shouldBlind(imm)) {
964 if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) {
965 move(src, scratchRegister);
966 src = scratchRegister;
969 loadXorBlindedConstant(xorBlindConstant(imm), dest);
970 return branchMul32(cond, src, dest);
972 return branchMul32(cond, imm.asTrustedImm32(), src, dest);
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)
979 if (shouldBlind(imm)) {
980 ASSERT(scratch != dest);
981 ASSERT(scratch != src);
982 loadXorBlindedConstant(xorBlindConstant(imm), scratch);
983 return branchSub32(cond, src, scratch, dest);
985 return branchSub32(cond, src, imm.asTrustedImm32(), dest);
988 // Immediate shifts only have 5 controllable bits
989 // so we'll consider them safe for now.
990 TrustedImm32 trustedImm32ForShift(Imm32 imm)
992 return TrustedImm32(imm.asTrustedImm32().m_value & 31);
995 void lshift32(Imm32 imm, RegisterID dest)
997 lshift32(trustedImm32ForShift(imm), dest);
1000 void lshift32(RegisterID src, Imm32 amount, RegisterID dest)
1002 lshift32(src, trustedImm32ForShift(amount), dest);
1005 void rshift32(Imm32 imm, RegisterID dest)
1007 rshift32(trustedImm32ForShift(imm), dest);
1010 void rshift32(RegisterID src, Imm32 amount, RegisterID dest)
1012 rshift32(src, trustedImm32ForShift(amount), dest);
1015 void urshift32(Imm32 imm, RegisterID dest)
1017 urshift32(trustedImm32ForShift(imm), dest);
1020 void urshift32(RegisterID src, Imm32 amount, RegisterID dest)
1022 urshift32(src, trustedImm32ForShift(amount), dest);
1029 #else // ENABLE(ASSEMBLER)
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 {
1036 MacroAssembler() { }
1040 enum RegisterID { NoRegister };
1041 enum FPRegisterID { NoFPRegister };
1044 #endif // ENABLE(ASSEMBLER)
1046 #endif // MacroAssembler_h