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