1 // Copyright 2013 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_ 6 #define V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_ 7 8 #include <ctype.h> 9 10 #include "src/globals.h" 11 12 #include "src/arm64/assembler-arm64.h" 13 #include "src/arm64/assembler-arm64-inl.h" 14 #include "src/arm64/macro-assembler-arm64.h" 15 #include "src/arm64/instrument-arm64.h" 16 17 18 namespace v8 { 19 namespace internal { 20 21 22 MemOperand FieldMemOperand(Register object, int offset) { 23 return MemOperand(object, offset - kHeapObjectTag); 24 } 25 26 27 MemOperand UntagSmiFieldMemOperand(Register object, int offset) { 28 return UntagSmiMemOperand(object, offset - kHeapObjectTag); 29 } 30 31 32 MemOperand UntagSmiMemOperand(Register object, int offset) { 33 // Assumes that Smis are shifted by 32 bits and little endianness. 34 STATIC_ASSERT(kSmiShift == 32); 35 return MemOperand(object, offset + (kSmiShift / kBitsPerByte)); 36 } 37 38 39 Handle<Object> MacroAssembler::CodeObject() { 40 ASSERT(!code_object_.is_null()); 41 return code_object_; 42 } 43 44 45 void MacroAssembler::And(const Register& rd, 46 const Register& rn, 47 const Operand& operand) { 48 ASSERT(allow_macro_instructions_); 49 ASSERT(!rd.IsZero()); 50 LogicalMacro(rd, rn, operand, AND); 51 } 52 53 54 void MacroAssembler::Ands(const Register& rd, 55 const Register& rn, 56 const Operand& operand) { 57 ASSERT(allow_macro_instructions_); 58 ASSERT(!rd.IsZero()); 59 LogicalMacro(rd, rn, operand, ANDS); 60 } 61 62 63 void MacroAssembler::Tst(const Register& rn, 64 const Operand& operand) { 65 ASSERT(allow_macro_instructions_); 66 LogicalMacro(AppropriateZeroRegFor(rn), rn, operand, ANDS); 67 } 68 69 70 void MacroAssembler::Bic(const Register& rd, 71 const Register& rn, 72 const Operand& operand) { 73 ASSERT(allow_macro_instructions_); 74 ASSERT(!rd.IsZero()); 75 LogicalMacro(rd, rn, operand, BIC); 76 } 77 78 79 void MacroAssembler::Bics(const Register& rd, 80 const Register& rn, 81 const Operand& operand) { 82 ASSERT(allow_macro_instructions_); 83 ASSERT(!rd.IsZero()); 84 LogicalMacro(rd, rn, operand, BICS); 85 } 86 87 88 void MacroAssembler::Orr(const Register& rd, 89 const Register& rn, 90 const Operand& operand) { 91 ASSERT(allow_macro_instructions_); 92 ASSERT(!rd.IsZero()); 93 LogicalMacro(rd, rn, operand, ORR); 94 } 95 96 97 void MacroAssembler::Orn(const Register& rd, 98 const Register& rn, 99 const Operand& operand) { 100 ASSERT(allow_macro_instructions_); 101 ASSERT(!rd.IsZero()); 102 LogicalMacro(rd, rn, operand, ORN); 103 } 104 105 106 void MacroAssembler::Eor(const Register& rd, 107 const Register& rn, 108 const Operand& operand) { 109 ASSERT(allow_macro_instructions_); 110 ASSERT(!rd.IsZero()); 111 LogicalMacro(rd, rn, operand, EOR); 112 } 113 114 115 void MacroAssembler::Eon(const Register& rd, 116 const Register& rn, 117 const Operand& operand) { 118 ASSERT(allow_macro_instructions_); 119 ASSERT(!rd.IsZero()); 120 LogicalMacro(rd, rn, operand, EON); 121 } 122 123 124 void MacroAssembler::Ccmp(const Register& rn, 125 const Operand& operand, 126 StatusFlags nzcv, 127 Condition cond) { 128 ASSERT(allow_macro_instructions_); 129 if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) { 130 ConditionalCompareMacro(rn, -operand.ImmediateValue(), nzcv, cond, CCMN); 131 } else { 132 ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP); 133 } 134 } 135 136 137 void MacroAssembler::Ccmn(const Register& rn, 138 const Operand& operand, 139 StatusFlags nzcv, 140 Condition cond) { 141 ASSERT(allow_macro_instructions_); 142 if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) { 143 ConditionalCompareMacro(rn, -operand.ImmediateValue(), nzcv, cond, CCMP); 144 } else { 145 ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN); 146 } 147 } 148 149 150 void MacroAssembler::Add(const Register& rd, 151 const Register& rn, 152 const Operand& operand) { 153 ASSERT(allow_macro_instructions_); 154 if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) { 155 AddSubMacro(rd, rn, -operand.ImmediateValue(), LeaveFlags, SUB); 156 } else { 157 AddSubMacro(rd, rn, operand, LeaveFlags, ADD); 158 } 159 } 160 161 void MacroAssembler::Adds(const Register& rd, 162 const Register& rn, 163 const Operand& operand) { 164 ASSERT(allow_macro_instructions_); 165 if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) { 166 AddSubMacro(rd, rn, -operand.ImmediateValue(), SetFlags, SUB); 167 } else { 168 AddSubMacro(rd, rn, operand, SetFlags, ADD); 169 } 170 } 171 172 173 void MacroAssembler::Sub(const Register& rd, 174 const Register& rn, 175 const Operand& operand) { 176 ASSERT(allow_macro_instructions_); 177 if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) { 178 AddSubMacro(rd, rn, -operand.ImmediateValue(), LeaveFlags, ADD); 179 } else { 180 AddSubMacro(rd, rn, operand, LeaveFlags, SUB); 181 } 182 } 183 184 185 void MacroAssembler::Subs(const Register& rd, 186 const Register& rn, 187 const Operand& operand) { 188 ASSERT(allow_macro_instructions_); 189 if (operand.IsImmediate() && (operand.ImmediateValue() < 0)) { 190 AddSubMacro(rd, rn, -operand.ImmediateValue(), SetFlags, ADD); 191 } else { 192 AddSubMacro(rd, rn, operand, SetFlags, SUB); 193 } 194 } 195 196 197 void MacroAssembler::Cmn(const Register& rn, const Operand& operand) { 198 ASSERT(allow_macro_instructions_); 199 Adds(AppropriateZeroRegFor(rn), rn, operand); 200 } 201 202 203 void MacroAssembler::Cmp(const Register& rn, const Operand& operand) { 204 ASSERT(allow_macro_instructions_); 205 Subs(AppropriateZeroRegFor(rn), rn, operand); 206 } 207 208 209 void MacroAssembler::Neg(const Register& rd, 210 const Operand& operand) { 211 ASSERT(allow_macro_instructions_); 212 ASSERT(!rd.IsZero()); 213 if (operand.IsImmediate()) { 214 Mov(rd, -operand.ImmediateValue()); 215 } else { 216 Sub(rd, AppropriateZeroRegFor(rd), operand); 217 } 218 } 219 220 221 void MacroAssembler::Negs(const Register& rd, 222 const Operand& operand) { 223 ASSERT(allow_macro_instructions_); 224 Subs(rd, AppropriateZeroRegFor(rd), operand); 225 } 226 227 228 void MacroAssembler::Adc(const Register& rd, 229 const Register& rn, 230 const Operand& operand) { 231 ASSERT(allow_macro_instructions_); 232 ASSERT(!rd.IsZero()); 233 AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, ADC); 234 } 235 236 237 void MacroAssembler::Adcs(const Register& rd, 238 const Register& rn, 239 const Operand& operand) { 240 ASSERT(allow_macro_instructions_); 241 ASSERT(!rd.IsZero()); 242 AddSubWithCarryMacro(rd, rn, operand, SetFlags, ADC); 243 } 244 245 246 void MacroAssembler::Sbc(const Register& rd, 247 const Register& rn, 248 const Operand& operand) { 249 ASSERT(allow_macro_instructions_); 250 ASSERT(!rd.IsZero()); 251 AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, SBC); 252 } 253 254 255 void MacroAssembler::Sbcs(const Register& rd, 256 const Register& rn, 257 const Operand& operand) { 258 ASSERT(allow_macro_instructions_); 259 ASSERT(!rd.IsZero()); 260 AddSubWithCarryMacro(rd, rn, operand, SetFlags, SBC); 261 } 262 263 264 void MacroAssembler::Ngc(const Register& rd, 265 const Operand& operand) { 266 ASSERT(allow_macro_instructions_); 267 ASSERT(!rd.IsZero()); 268 Register zr = AppropriateZeroRegFor(rd); 269 Sbc(rd, zr, operand); 270 } 271 272 273 void MacroAssembler::Ngcs(const Register& rd, 274 const Operand& operand) { 275 ASSERT(allow_macro_instructions_); 276 ASSERT(!rd.IsZero()); 277 Register zr = AppropriateZeroRegFor(rd); 278 Sbcs(rd, zr, operand); 279 } 280 281 282 void MacroAssembler::Mvn(const Register& rd, uint64_t imm) { 283 ASSERT(allow_macro_instructions_); 284 ASSERT(!rd.IsZero()); 285 Mov(rd, ~imm); 286 } 287 288 289 #define DEFINE_FUNCTION(FN, REGTYPE, REG, OP) \ 290 void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) { \ 291 ASSERT(allow_macro_instructions_); \ 292 LoadStoreMacro(REG, addr, OP); \ 293 } 294 LS_MACRO_LIST(DEFINE_FUNCTION) 295 #undef DEFINE_FUNCTION 296 297 298 void MacroAssembler::Asr(const Register& rd, 299 const Register& rn, 300 unsigned shift) { 301 ASSERT(allow_macro_instructions_); 302 ASSERT(!rd.IsZero()); 303 asr(rd, rn, shift); 304 } 305 306 307 void MacroAssembler::Asr(const Register& rd, 308 const Register& rn, 309 const Register& rm) { 310 ASSERT(allow_macro_instructions_); 311 ASSERT(!rd.IsZero()); 312 asrv(rd, rn, rm); 313 } 314 315 316 void MacroAssembler::B(Label* label) { 317 b(label); 318 CheckVeneerPool(false, false); 319 } 320 321 322 void MacroAssembler::B(Condition cond, Label* label) { 323 ASSERT(allow_macro_instructions_); 324 B(label, cond); 325 } 326 327 328 void MacroAssembler::Bfi(const Register& rd, 329 const Register& rn, 330 unsigned lsb, 331 unsigned width) { 332 ASSERT(allow_macro_instructions_); 333 ASSERT(!rd.IsZero()); 334 bfi(rd, rn, lsb, width); 335 } 336 337 338 void MacroAssembler::Bfxil(const Register& rd, 339 const Register& rn, 340 unsigned lsb, 341 unsigned width) { 342 ASSERT(allow_macro_instructions_); 343 ASSERT(!rd.IsZero()); 344 bfxil(rd, rn, lsb, width); 345 } 346 347 348 void MacroAssembler::Bind(Label* label) { 349 ASSERT(allow_macro_instructions_); 350 bind(label); 351 } 352 353 354 void MacroAssembler::Bl(Label* label) { 355 ASSERT(allow_macro_instructions_); 356 bl(label); 357 } 358 359 360 void MacroAssembler::Blr(const Register& xn) { 361 ASSERT(allow_macro_instructions_); 362 ASSERT(!xn.IsZero()); 363 blr(xn); 364 } 365 366 367 void MacroAssembler::Br(const Register& xn) { 368 ASSERT(allow_macro_instructions_); 369 ASSERT(!xn.IsZero()); 370 br(xn); 371 } 372 373 374 void MacroAssembler::Brk(int code) { 375 ASSERT(allow_macro_instructions_); 376 brk(code); 377 } 378 379 380 void MacroAssembler::Cinc(const Register& rd, 381 const Register& rn, 382 Condition cond) { 383 ASSERT(allow_macro_instructions_); 384 ASSERT(!rd.IsZero()); 385 ASSERT((cond != al) && (cond != nv)); 386 cinc(rd, rn, cond); 387 } 388 389 390 void MacroAssembler::Cinv(const Register& rd, 391 const Register& rn, 392 Condition cond) { 393 ASSERT(allow_macro_instructions_); 394 ASSERT(!rd.IsZero()); 395 ASSERT((cond != al) && (cond != nv)); 396 cinv(rd, rn, cond); 397 } 398 399 400 void MacroAssembler::Cls(const Register& rd, const Register& rn) { 401 ASSERT(allow_macro_instructions_); 402 ASSERT(!rd.IsZero()); 403 cls(rd, rn); 404 } 405 406 407 void MacroAssembler::Clz(const Register& rd, const Register& rn) { 408 ASSERT(allow_macro_instructions_); 409 ASSERT(!rd.IsZero()); 410 clz(rd, rn); 411 } 412 413 414 void MacroAssembler::Cneg(const Register& rd, 415 const Register& rn, 416 Condition cond) { 417 ASSERT(allow_macro_instructions_); 418 ASSERT(!rd.IsZero()); 419 ASSERT((cond != al) && (cond != nv)); 420 cneg(rd, rn, cond); 421 } 422 423 424 // Conditionally zero the destination register. Only X registers are supported 425 // due to the truncation side-effect when used on W registers. 426 void MacroAssembler::CzeroX(const Register& rd, 427 Condition cond) { 428 ASSERT(allow_macro_instructions_); 429 ASSERT(!rd.IsSP() && rd.Is64Bits()); 430 ASSERT((cond != al) && (cond != nv)); 431 csel(rd, xzr, rd, cond); 432 } 433 434 435 // Conditionally move a value into the destination register. Only X registers 436 // are supported due to the truncation side-effect when used on W registers. 437 void MacroAssembler::CmovX(const Register& rd, 438 const Register& rn, 439 Condition cond) { 440 ASSERT(allow_macro_instructions_); 441 ASSERT(!rd.IsSP()); 442 ASSERT(rd.Is64Bits() && rn.Is64Bits()); 443 ASSERT((cond != al) && (cond != nv)); 444 if (!rd.is(rn)) { 445 csel(rd, rn, rd, cond); 446 } 447 } 448 449 450 void MacroAssembler::Cset(const Register& rd, Condition cond) { 451 ASSERT(allow_macro_instructions_); 452 ASSERT(!rd.IsZero()); 453 ASSERT((cond != al) && (cond != nv)); 454 cset(rd, cond); 455 } 456 457 458 void MacroAssembler::Csetm(const Register& rd, Condition cond) { 459 ASSERT(allow_macro_instructions_); 460 ASSERT(!rd.IsZero()); 461 ASSERT((cond != al) && (cond != nv)); 462 csetm(rd, cond); 463 } 464 465 466 void MacroAssembler::Csinc(const Register& rd, 467 const Register& rn, 468 const Register& rm, 469 Condition cond) { 470 ASSERT(allow_macro_instructions_); 471 ASSERT(!rd.IsZero()); 472 ASSERT((cond != al) && (cond != nv)); 473 csinc(rd, rn, rm, cond); 474 } 475 476 477 void MacroAssembler::Csinv(const Register& rd, 478 const Register& rn, 479 const Register& rm, 480 Condition cond) { 481 ASSERT(allow_macro_instructions_); 482 ASSERT(!rd.IsZero()); 483 ASSERT((cond != al) && (cond != nv)); 484 csinv(rd, rn, rm, cond); 485 } 486 487 488 void MacroAssembler::Csneg(const Register& rd, 489 const Register& rn, 490 const Register& rm, 491 Condition cond) { 492 ASSERT(allow_macro_instructions_); 493 ASSERT(!rd.IsZero()); 494 ASSERT((cond != al) && (cond != nv)); 495 csneg(rd, rn, rm, cond); 496 } 497 498 499 void MacroAssembler::Dmb(BarrierDomain domain, BarrierType type) { 500 ASSERT(allow_macro_instructions_); 501 dmb(domain, type); 502 } 503 504 505 void MacroAssembler::Dsb(BarrierDomain domain, BarrierType type) { 506 ASSERT(allow_macro_instructions_); 507 dsb(domain, type); 508 } 509 510 511 void MacroAssembler::Debug(const char* message, uint32_t code, Instr params) { 512 ASSERT(allow_macro_instructions_); 513 debug(message, code, params); 514 } 515 516 517 void MacroAssembler::Extr(const Register& rd, 518 const Register& rn, 519 const Register& rm, 520 unsigned lsb) { 521 ASSERT(allow_macro_instructions_); 522 ASSERT(!rd.IsZero()); 523 extr(rd, rn, rm, lsb); 524 } 525 526 527 void MacroAssembler::Fabs(const FPRegister& fd, const FPRegister& fn) { 528 ASSERT(allow_macro_instructions_); 529 fabs(fd, fn); 530 } 531 532 533 void MacroAssembler::Fadd(const FPRegister& fd, 534 const FPRegister& fn, 535 const FPRegister& fm) { 536 ASSERT(allow_macro_instructions_); 537 fadd(fd, fn, fm); 538 } 539 540 541 void MacroAssembler::Fccmp(const FPRegister& fn, 542 const FPRegister& fm, 543 StatusFlags nzcv, 544 Condition cond) { 545 ASSERT(allow_macro_instructions_); 546 ASSERT((cond != al) && (cond != nv)); 547 fccmp(fn, fm, nzcv, cond); 548 } 549 550 551 void MacroAssembler::Fcmp(const FPRegister& fn, const FPRegister& fm) { 552 ASSERT(allow_macro_instructions_); 553 fcmp(fn, fm); 554 } 555 556 557 void MacroAssembler::Fcmp(const FPRegister& fn, double value) { 558 ASSERT(allow_macro_instructions_); 559 if (value != 0.0) { 560 UseScratchRegisterScope temps(this); 561 FPRegister tmp = temps.AcquireSameSizeAs(fn); 562 Fmov(tmp, value); 563 fcmp(fn, tmp); 564 } else { 565 fcmp(fn, value); 566 } 567 } 568 569 570 void MacroAssembler::Fcsel(const FPRegister& fd, 571 const FPRegister& fn, 572 const FPRegister& fm, 573 Condition cond) { 574 ASSERT(allow_macro_instructions_); 575 ASSERT((cond != al) && (cond != nv)); 576 fcsel(fd, fn, fm, cond); 577 } 578 579 580 void MacroAssembler::Fcvt(const FPRegister& fd, const FPRegister& fn) { 581 ASSERT(allow_macro_instructions_); 582 fcvt(fd, fn); 583 } 584 585 586 void MacroAssembler::Fcvtas(const Register& rd, const FPRegister& fn) { 587 ASSERT(allow_macro_instructions_); 588 ASSERT(!rd.IsZero()); 589 fcvtas(rd, fn); 590 } 591 592 593 void MacroAssembler::Fcvtau(const Register& rd, const FPRegister& fn) { 594 ASSERT(allow_macro_instructions_); 595 ASSERT(!rd.IsZero()); 596 fcvtau(rd, fn); 597 } 598 599 600 void MacroAssembler::Fcvtms(const Register& rd, const FPRegister& fn) { 601 ASSERT(allow_macro_instructions_); 602 ASSERT(!rd.IsZero()); 603 fcvtms(rd, fn); 604 } 605 606 607 void MacroAssembler::Fcvtmu(const Register& rd, const FPRegister& fn) { 608 ASSERT(allow_macro_instructions_); 609 ASSERT(!rd.IsZero()); 610 fcvtmu(rd, fn); 611 } 612 613 614 void MacroAssembler::Fcvtns(const Register& rd, const FPRegister& fn) { 615 ASSERT(allow_macro_instructions_); 616 ASSERT(!rd.IsZero()); 617 fcvtns(rd, fn); 618 } 619 620 621 void MacroAssembler::Fcvtnu(const Register& rd, const FPRegister& fn) { 622 ASSERT(allow_macro_instructions_); 623 ASSERT(!rd.IsZero()); 624 fcvtnu(rd, fn); 625 } 626 627 628 void MacroAssembler::Fcvtzs(const Register& rd, const FPRegister& fn) { 629 ASSERT(allow_macro_instructions_); 630 ASSERT(!rd.IsZero()); 631 fcvtzs(rd, fn); 632 } 633 void MacroAssembler::Fcvtzu(const Register& rd, const FPRegister& fn) { 634 ASSERT(allow_macro_instructions_); 635 ASSERT(!rd.IsZero()); 636 fcvtzu(rd, fn); 637 } 638 639 640 void MacroAssembler::Fdiv(const FPRegister& fd, 641 const FPRegister& fn, 642 const FPRegister& fm) { 643 ASSERT(allow_macro_instructions_); 644 fdiv(fd, fn, fm); 645 } 646 647 648 void MacroAssembler::Fmadd(const FPRegister& fd, 649 const FPRegister& fn, 650 const FPRegister& fm, 651 const FPRegister& fa) { 652 ASSERT(allow_macro_instructions_); 653 fmadd(fd, fn, fm, fa); 654 } 655 656 657 void MacroAssembler::Fmax(const FPRegister& fd, 658 const FPRegister& fn, 659 const FPRegister& fm) { 660 ASSERT(allow_macro_instructions_); 661 fmax(fd, fn, fm); 662 } 663 664 665 void MacroAssembler::Fmaxnm(const FPRegister& fd, 666 const FPRegister& fn, 667 const FPRegister& fm) { 668 ASSERT(allow_macro_instructions_); 669 fmaxnm(fd, fn, fm); 670 } 671 672 673 void MacroAssembler::Fmin(const FPRegister& fd, 674 const FPRegister& fn, 675 const FPRegister& fm) { 676 ASSERT(allow_macro_instructions_); 677 fmin(fd, fn, fm); 678 } 679 680 681 void MacroAssembler::Fminnm(const FPRegister& fd, 682 const FPRegister& fn, 683 const FPRegister& fm) { 684 ASSERT(allow_macro_instructions_); 685 fminnm(fd, fn, fm); 686 } 687 688 689 void MacroAssembler::Fmov(FPRegister fd, FPRegister fn) { 690 ASSERT(allow_macro_instructions_); 691 // Only emit an instruction if fd and fn are different, and they are both D 692 // registers. fmov(s0, s0) is not a no-op because it clears the top word of 693 // d0. Technically, fmov(d0, d0) is not a no-op either because it clears the 694 // top of q0, but FPRegister does not currently support Q registers. 695 if (!fd.Is(fn) || !fd.Is64Bits()) { 696 fmov(fd, fn); 697 } 698 } 699 700 701 void MacroAssembler::Fmov(FPRegister fd, Register rn) { 702 ASSERT(allow_macro_instructions_); 703 fmov(fd, rn); 704 } 705 706 707 void MacroAssembler::Fmov(FPRegister fd, double imm) { 708 ASSERT(allow_macro_instructions_); 709 if (fd.Is32Bits()) { 710 Fmov(fd, static_cast<float>(imm)); 711 return; 712 } 713 714 ASSERT(fd.Is64Bits()); 715 if (IsImmFP64(imm)) { 716 fmov(fd, imm); 717 } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) { 718 fmov(fd, xzr); 719 } else { 720 Ldr(fd, imm); 721 } 722 } 723 724 725 void MacroAssembler::Fmov(FPRegister fd, float imm) { 726 ASSERT(allow_macro_instructions_); 727 if (fd.Is64Bits()) { 728 Fmov(fd, static_cast<double>(imm)); 729 return; 730 } 731 732 ASSERT(fd.Is32Bits()); 733 if (IsImmFP32(imm)) { 734 fmov(fd, imm); 735 } else if ((imm == 0.0) && (copysign(1.0, imm) == 1.0)) { 736 fmov(fd, wzr); 737 } else { 738 UseScratchRegisterScope temps(this); 739 Register tmp = temps.AcquireW(); 740 // TODO(all): Use Assembler::ldr(const FPRegister& ft, float imm). 741 Mov(tmp, float_to_rawbits(imm)); 742 Fmov(fd, tmp); 743 } 744 } 745 746 747 void MacroAssembler::Fmov(Register rd, FPRegister fn) { 748 ASSERT(allow_macro_instructions_); 749 ASSERT(!rd.IsZero()); 750 fmov(rd, fn); 751 } 752 753 754 void MacroAssembler::Fmsub(const FPRegister& fd, 755 const FPRegister& fn, 756 const FPRegister& fm, 757 const FPRegister& fa) { 758 ASSERT(allow_macro_instructions_); 759 fmsub(fd, fn, fm, fa); 760 } 761 762 763 void MacroAssembler::Fmul(const FPRegister& fd, 764 const FPRegister& fn, 765 const FPRegister& fm) { 766 ASSERT(allow_macro_instructions_); 767 fmul(fd, fn, fm); 768 } 769 770 771 void MacroAssembler::Fneg(const FPRegister& fd, const FPRegister& fn) { 772 ASSERT(allow_macro_instructions_); 773 fneg(fd, fn); 774 } 775 776 777 void MacroAssembler::Fnmadd(const FPRegister& fd, 778 const FPRegister& fn, 779 const FPRegister& fm, 780 const FPRegister& fa) { 781 ASSERT(allow_macro_instructions_); 782 fnmadd(fd, fn, fm, fa); 783 } 784 785 786 void MacroAssembler::Fnmsub(const FPRegister& fd, 787 const FPRegister& fn, 788 const FPRegister& fm, 789 const FPRegister& fa) { 790 ASSERT(allow_macro_instructions_); 791 fnmsub(fd, fn, fm, fa); 792 } 793 794 795 void MacroAssembler::Frinta(const FPRegister& fd, const FPRegister& fn) { 796 ASSERT(allow_macro_instructions_); 797 frinta(fd, fn); 798 } 799 800 801 void MacroAssembler::Frintm(const FPRegister& fd, const FPRegister& fn) { 802 ASSERT(allow_macro_instructions_); 803 frintm(fd, fn); 804 } 805 806 807 void MacroAssembler::Frintn(const FPRegister& fd, const FPRegister& fn) { 808 ASSERT(allow_macro_instructions_); 809 frintn(fd, fn); 810 } 811 812 813 void MacroAssembler::Frintz(const FPRegister& fd, const FPRegister& fn) { 814 ASSERT(allow_macro_instructions_); 815 frintz(fd, fn); 816 } 817 818 819 void MacroAssembler::Fsqrt(const FPRegister& fd, const FPRegister& fn) { 820 ASSERT(allow_macro_instructions_); 821 fsqrt(fd, fn); 822 } 823 824 825 void MacroAssembler::Fsub(const FPRegister& fd, 826 const FPRegister& fn, 827 const FPRegister& fm) { 828 ASSERT(allow_macro_instructions_); 829 fsub(fd, fn, fm); 830 } 831 832 833 void MacroAssembler::Hint(SystemHint code) { 834 ASSERT(allow_macro_instructions_); 835 hint(code); 836 } 837 838 839 void MacroAssembler::Hlt(int code) { 840 ASSERT(allow_macro_instructions_); 841 hlt(code); 842 } 843 844 845 void MacroAssembler::Isb() { 846 ASSERT(allow_macro_instructions_); 847 isb(); 848 } 849 850 851 void MacroAssembler::Ldnp(const CPURegister& rt, 852 const CPURegister& rt2, 853 const MemOperand& src) { 854 ASSERT(allow_macro_instructions_); 855 ASSERT(!AreAliased(rt, rt2)); 856 ldnp(rt, rt2, src); 857 } 858 859 860 void MacroAssembler::Ldp(const CPURegister& rt, 861 const CPURegister& rt2, 862 const MemOperand& src) { 863 ASSERT(allow_macro_instructions_); 864 ASSERT(!AreAliased(rt, rt2)); 865 ldp(rt, rt2, src); 866 } 867 868 869 void MacroAssembler::Ldpsw(const Register& rt, 870 const Register& rt2, 871 const MemOperand& src) { 872 ASSERT(allow_macro_instructions_); 873 ASSERT(!rt.IsZero()); 874 ASSERT(!rt2.IsZero()); 875 ldpsw(rt, rt2, src); 876 } 877 878 879 void MacroAssembler::Ldr(const CPURegister& rt, const Immediate& imm) { 880 ASSERT(allow_macro_instructions_); 881 ldr(rt, imm); 882 } 883 884 885 void MacroAssembler::Ldr(const CPURegister& rt, double imm) { 886 ASSERT(allow_macro_instructions_); 887 ASSERT(rt.Is64Bits()); 888 ldr(rt, Immediate(double_to_rawbits(imm))); 889 } 890 891 892 void MacroAssembler::Lsl(const Register& rd, 893 const Register& rn, 894 unsigned shift) { 895 ASSERT(allow_macro_instructions_); 896 ASSERT(!rd.IsZero()); 897 lsl(rd, rn, shift); 898 } 899 900 901 void MacroAssembler::Lsl(const Register& rd, 902 const Register& rn, 903 const Register& rm) { 904 ASSERT(allow_macro_instructions_); 905 ASSERT(!rd.IsZero()); 906 lslv(rd, rn, rm); 907 } 908 909 910 void MacroAssembler::Lsr(const Register& rd, 911 const Register& rn, 912 unsigned shift) { 913 ASSERT(allow_macro_instructions_); 914 ASSERT(!rd.IsZero()); 915 lsr(rd, rn, shift); 916 } 917 918 919 void MacroAssembler::Lsr(const Register& rd, 920 const Register& rn, 921 const Register& rm) { 922 ASSERT(allow_macro_instructions_); 923 ASSERT(!rd.IsZero()); 924 lsrv(rd, rn, rm); 925 } 926 927 928 void MacroAssembler::Madd(const Register& rd, 929 const Register& rn, 930 const Register& rm, 931 const Register& ra) { 932 ASSERT(allow_macro_instructions_); 933 ASSERT(!rd.IsZero()); 934 madd(rd, rn, rm, ra); 935 } 936 937 938 void MacroAssembler::Mneg(const Register& rd, 939 const Register& rn, 940 const Register& rm) { 941 ASSERT(allow_macro_instructions_); 942 ASSERT(!rd.IsZero()); 943 mneg(rd, rn, rm); 944 } 945 946 947 void MacroAssembler::Mov(const Register& rd, const Register& rn) { 948 ASSERT(allow_macro_instructions_); 949 ASSERT(!rd.IsZero()); 950 // Emit a register move only if the registers are distinct, or if they are 951 // not X registers. Note that mov(w0, w0) is not a no-op because it clears 952 // the top word of x0. 953 if (!rd.Is(rn) || !rd.Is64Bits()) { 954 Assembler::mov(rd, rn); 955 } 956 } 957 958 959 void MacroAssembler::Movk(const Register& rd, uint64_t imm, int shift) { 960 ASSERT(allow_macro_instructions_); 961 ASSERT(!rd.IsZero()); 962 movk(rd, imm, shift); 963 } 964 965 966 void MacroAssembler::Mrs(const Register& rt, SystemRegister sysreg) { 967 ASSERT(allow_macro_instructions_); 968 ASSERT(!rt.IsZero()); 969 mrs(rt, sysreg); 970 } 971 972 973 void MacroAssembler::Msr(SystemRegister sysreg, const Register& rt) { 974 ASSERT(allow_macro_instructions_); 975 msr(sysreg, rt); 976 } 977 978 979 void MacroAssembler::Msub(const Register& rd, 980 const Register& rn, 981 const Register& rm, 982 const Register& ra) { 983 ASSERT(allow_macro_instructions_); 984 ASSERT(!rd.IsZero()); 985 msub(rd, rn, rm, ra); 986 } 987 988 989 void MacroAssembler::Mul(const Register& rd, 990 const Register& rn, 991 const Register& rm) { 992 ASSERT(allow_macro_instructions_); 993 ASSERT(!rd.IsZero()); 994 mul(rd, rn, rm); 995 } 996 997 998 void MacroAssembler::Rbit(const Register& rd, const Register& rn) { 999 ASSERT(allow_macro_instructions_); 1000 ASSERT(!rd.IsZero()); 1001 rbit(rd, rn); 1002 } 1003 1004 1005 void MacroAssembler::Ret(const Register& xn) { 1006 ASSERT(allow_macro_instructions_); 1007 ASSERT(!xn.IsZero()); 1008 ret(xn); 1009 CheckVeneerPool(false, false); 1010 } 1011 1012 1013 void MacroAssembler::Rev(const Register& rd, const Register& rn) { 1014 ASSERT(allow_macro_instructions_); 1015 ASSERT(!rd.IsZero()); 1016 rev(rd, rn); 1017 } 1018 1019 1020 void MacroAssembler::Rev16(const Register& rd, const Register& rn) { 1021 ASSERT(allow_macro_instructions_); 1022 ASSERT(!rd.IsZero()); 1023 rev16(rd, rn); 1024 } 1025 1026 1027 void MacroAssembler::Rev32(const Register& rd, const Register& rn) { 1028 ASSERT(allow_macro_instructions_); 1029 ASSERT(!rd.IsZero()); 1030 rev32(rd, rn); 1031 } 1032 1033 1034 void MacroAssembler::Ror(const Register& rd, 1035 const Register& rs, 1036 unsigned shift) { 1037 ASSERT(allow_macro_instructions_); 1038 ASSERT(!rd.IsZero()); 1039 ror(rd, rs, shift); 1040 } 1041 1042 1043 void MacroAssembler::Ror(const Register& rd, 1044 const Register& rn, 1045 const Register& rm) { 1046 ASSERT(allow_macro_instructions_); 1047 ASSERT(!rd.IsZero()); 1048 rorv(rd, rn, rm); 1049 } 1050 1051 1052 void MacroAssembler::Sbfiz(const Register& rd, 1053 const Register& rn, 1054 unsigned lsb, 1055 unsigned width) { 1056 ASSERT(allow_macro_instructions_); 1057 ASSERT(!rd.IsZero()); 1058 sbfiz(rd, rn, lsb, width); 1059 } 1060 1061 1062 void MacroAssembler::Sbfx(const Register& rd, 1063 const Register& rn, 1064 unsigned lsb, 1065 unsigned width) { 1066 ASSERT(allow_macro_instructions_); 1067 ASSERT(!rd.IsZero()); 1068 sbfx(rd, rn, lsb, width); 1069 } 1070 1071 1072 void MacroAssembler::Scvtf(const FPRegister& fd, 1073 const Register& rn, 1074 unsigned fbits) { 1075 ASSERT(allow_macro_instructions_); 1076 scvtf(fd, rn, fbits); 1077 } 1078 1079 1080 void MacroAssembler::Sdiv(const Register& rd, 1081 const Register& rn, 1082 const Register& rm) { 1083 ASSERT(allow_macro_instructions_); 1084 ASSERT(!rd.IsZero()); 1085 sdiv(rd, rn, rm); 1086 } 1087 1088 1089 void MacroAssembler::Smaddl(const Register& rd, 1090 const Register& rn, 1091 const Register& rm, 1092 const Register& ra) { 1093 ASSERT(allow_macro_instructions_); 1094 ASSERT(!rd.IsZero()); 1095 smaddl(rd, rn, rm, ra); 1096 } 1097 1098 1099 void MacroAssembler::Smsubl(const Register& rd, 1100 const Register& rn, 1101 const Register& rm, 1102 const Register& ra) { 1103 ASSERT(allow_macro_instructions_); 1104 ASSERT(!rd.IsZero()); 1105 smsubl(rd, rn, rm, ra); 1106 } 1107 1108 1109 void MacroAssembler::Smull(const Register& rd, 1110 const Register& rn, 1111 const Register& rm) { 1112 ASSERT(allow_macro_instructions_); 1113 ASSERT(!rd.IsZero()); 1114 smull(rd, rn, rm); 1115 } 1116 1117 1118 void MacroAssembler::Smulh(const Register& rd, 1119 const Register& rn, 1120 const Register& rm) { 1121 ASSERT(allow_macro_instructions_); 1122 ASSERT(!rd.IsZero()); 1123 smulh(rd, rn, rm); 1124 } 1125 1126 1127 void MacroAssembler::Stnp(const CPURegister& rt, 1128 const CPURegister& rt2, 1129 const MemOperand& dst) { 1130 ASSERT(allow_macro_instructions_); 1131 stnp(rt, rt2, dst); 1132 } 1133 1134 1135 void MacroAssembler::Stp(const CPURegister& rt, 1136 const CPURegister& rt2, 1137 const MemOperand& dst) { 1138 ASSERT(allow_macro_instructions_); 1139 stp(rt, rt2, dst); 1140 } 1141 1142 1143 void MacroAssembler::Sxtb(const Register& rd, const Register& rn) { 1144 ASSERT(allow_macro_instructions_); 1145 ASSERT(!rd.IsZero()); 1146 sxtb(rd, rn); 1147 } 1148 1149 1150 void MacroAssembler::Sxth(const Register& rd, const Register& rn) { 1151 ASSERT(allow_macro_instructions_); 1152 ASSERT(!rd.IsZero()); 1153 sxth(rd, rn); 1154 } 1155 1156 1157 void MacroAssembler::Sxtw(const Register& rd, const Register& rn) { 1158 ASSERT(allow_macro_instructions_); 1159 ASSERT(!rd.IsZero()); 1160 sxtw(rd, rn); 1161 } 1162 1163 1164 void MacroAssembler::Ubfiz(const Register& rd, 1165 const Register& rn, 1166 unsigned lsb, 1167 unsigned width) { 1168 ASSERT(allow_macro_instructions_); 1169 ASSERT(!rd.IsZero()); 1170 ubfiz(rd, rn, lsb, width); 1171 } 1172 1173 1174 void MacroAssembler::Ubfx(const Register& rd, 1175 const Register& rn, 1176 unsigned lsb, 1177 unsigned width) { 1178 ASSERT(allow_macro_instructions_); 1179 ASSERT(!rd.IsZero()); 1180 ubfx(rd, rn, lsb, width); 1181 } 1182 1183 1184 void MacroAssembler::Ucvtf(const FPRegister& fd, 1185 const Register& rn, 1186 unsigned fbits) { 1187 ASSERT(allow_macro_instructions_); 1188 ucvtf(fd, rn, fbits); 1189 } 1190 1191 1192 void MacroAssembler::Udiv(const Register& rd, 1193 const Register& rn, 1194 const Register& rm) { 1195 ASSERT(allow_macro_instructions_); 1196 ASSERT(!rd.IsZero()); 1197 udiv(rd, rn, rm); 1198 } 1199 1200 1201 void MacroAssembler::Umaddl(const Register& rd, 1202 const Register& rn, 1203 const Register& rm, 1204 const Register& ra) { 1205 ASSERT(allow_macro_instructions_); 1206 ASSERT(!rd.IsZero()); 1207 umaddl(rd, rn, rm, ra); 1208 } 1209 1210 1211 void MacroAssembler::Umsubl(const Register& rd, 1212 const Register& rn, 1213 const Register& rm, 1214 const Register& ra) { 1215 ASSERT(allow_macro_instructions_); 1216 ASSERT(!rd.IsZero()); 1217 umsubl(rd, rn, rm, ra); 1218 } 1219 1220 1221 void MacroAssembler::Uxtb(const Register& rd, const Register& rn) { 1222 ASSERT(allow_macro_instructions_); 1223 ASSERT(!rd.IsZero()); 1224 uxtb(rd, rn); 1225 } 1226 1227 1228 void MacroAssembler::Uxth(const Register& rd, const Register& rn) { 1229 ASSERT(allow_macro_instructions_); 1230 ASSERT(!rd.IsZero()); 1231 uxth(rd, rn); 1232 } 1233 1234 1235 void MacroAssembler::Uxtw(const Register& rd, const Register& rn) { 1236 ASSERT(allow_macro_instructions_); 1237 ASSERT(!rd.IsZero()); 1238 uxtw(rd, rn); 1239 } 1240 1241 1242 void MacroAssembler::BumpSystemStackPointer(const Operand& space) { 1243 ASSERT(!csp.Is(sp_)); 1244 if (!TmpList()->IsEmpty()) { 1245 if (CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) { 1246 UseScratchRegisterScope temps(this); 1247 Register temp = temps.AcquireX(); 1248 Sub(temp, StackPointer(), space); 1249 Bic(csp, temp, 0xf); 1250 } else { 1251 Sub(csp, StackPointer(), space); 1252 } 1253 } else { 1254 // TODO(jbramley): Several callers rely on this not using scratch 1255 // registers, so we use the assembler directly here. However, this means 1256 // that large immediate values of 'space' cannot be handled cleanly. (Only 1257 // 24-bits immediates or values of 'space' that can be encoded in one 1258 // instruction are accepted.) Once we implement our flexible scratch 1259 // register idea, we could greatly simplify this function. 1260 InstructionAccurateScope scope(this); 1261 ASSERT(space.IsImmediate()); 1262 // Align to 16 bytes. 1263 uint64_t imm = RoundUp(space.ImmediateValue(), 0x10); 1264 ASSERT(is_uint24(imm)); 1265 1266 Register source = StackPointer(); 1267 if (CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) { 1268 bic(csp, source, 0xf); 1269 source = csp; 1270 } 1271 if (!is_uint12(imm)) { 1272 int64_t imm_top_12_bits = imm >> 12; 1273 sub(csp, source, imm_top_12_bits << 12); 1274 source = csp; 1275 imm -= imm_top_12_bits << 12; 1276 } 1277 if (imm > 0) { 1278 sub(csp, source, imm); 1279 } 1280 } 1281 AssertStackConsistency(); 1282 } 1283 1284 1285 void MacroAssembler::SyncSystemStackPointer() { 1286 ASSERT(emit_debug_code()); 1287 ASSERT(!csp.Is(sp_)); 1288 { InstructionAccurateScope scope(this); 1289 if (CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) { 1290 bic(csp, StackPointer(), 0xf); 1291 } else { 1292 mov(csp, StackPointer()); 1293 } 1294 } 1295 AssertStackConsistency(); 1296 } 1297 1298 1299 void MacroAssembler::InitializeRootRegister() { 1300 ExternalReference roots_array_start = 1301 ExternalReference::roots_array_start(isolate()); 1302 Mov(root, Operand(roots_array_start)); 1303 } 1304 1305 1306 void MacroAssembler::SmiTag(Register dst, Register src) { 1307 ASSERT(dst.Is64Bits() && src.Is64Bits()); 1308 Lsl(dst, src, kSmiShift); 1309 } 1310 1311 1312 void MacroAssembler::SmiTag(Register smi) { SmiTag(smi, smi); } 1313 1314 1315 void MacroAssembler::SmiUntag(Register dst, Register src) { 1316 ASSERT(dst.Is64Bits() && src.Is64Bits()); 1317 if (FLAG_enable_slow_asserts) { 1318 AssertSmi(src); 1319 } 1320 Asr(dst, src, kSmiShift); 1321 } 1322 1323 1324 void MacroAssembler::SmiUntag(Register smi) { SmiUntag(smi, smi); } 1325 1326 1327 void MacroAssembler::SmiUntagToDouble(FPRegister dst, 1328 Register src, 1329 UntagMode mode) { 1330 ASSERT(dst.Is64Bits() && src.Is64Bits()); 1331 if (FLAG_enable_slow_asserts && (mode == kNotSpeculativeUntag)) { 1332 AssertSmi(src); 1333 } 1334 Scvtf(dst, src, kSmiShift); 1335 } 1336 1337 1338 void MacroAssembler::SmiUntagToFloat(FPRegister dst, 1339 Register src, 1340 UntagMode mode) { 1341 ASSERT(dst.Is32Bits() && src.Is64Bits()); 1342 if (FLAG_enable_slow_asserts && (mode == kNotSpeculativeUntag)) { 1343 AssertSmi(src); 1344 } 1345 Scvtf(dst, src, kSmiShift); 1346 } 1347 1348 1349 void MacroAssembler::SmiTagAndPush(Register src) { 1350 STATIC_ASSERT((kSmiShift == 32) && (kSmiTag == 0)); 1351 Push(src.W(), wzr); 1352 } 1353 1354 1355 void MacroAssembler::SmiTagAndPush(Register src1, Register src2) { 1356 STATIC_ASSERT((kSmiShift == 32) && (kSmiTag == 0)); 1357 Push(src1.W(), wzr, src2.W(), wzr); 1358 } 1359 1360 1361 void MacroAssembler::JumpIfSmi(Register value, 1362 Label* smi_label, 1363 Label* not_smi_label) { 1364 STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0)); 1365 // Check if the tag bit is set. 1366 if (smi_label) { 1367 Tbz(value, 0, smi_label); 1368 if (not_smi_label) { 1369 B(not_smi_label); 1370 } 1371 } else { 1372 ASSERT(not_smi_label); 1373 Tbnz(value, 0, not_smi_label); 1374 } 1375 } 1376 1377 1378 void MacroAssembler::JumpIfNotSmi(Register value, Label* not_smi_label) { 1379 JumpIfSmi(value, NULL, not_smi_label); 1380 } 1381 1382 1383 void MacroAssembler::JumpIfBothSmi(Register value1, 1384 Register value2, 1385 Label* both_smi_label, 1386 Label* not_smi_label) { 1387 STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0)); 1388 UseScratchRegisterScope temps(this); 1389 Register tmp = temps.AcquireX(); 1390 // Check if both tag bits are clear. 1391 Orr(tmp, value1, value2); 1392 JumpIfSmi(tmp, both_smi_label, not_smi_label); 1393 } 1394 1395 1396 void MacroAssembler::JumpIfEitherSmi(Register value1, 1397 Register value2, 1398 Label* either_smi_label, 1399 Label* not_smi_label) { 1400 STATIC_ASSERT((kSmiTagSize == 1) && (kSmiTag == 0)); 1401 UseScratchRegisterScope temps(this); 1402 Register tmp = temps.AcquireX(); 1403 // Check if either tag bit is clear. 1404 And(tmp, value1, value2); 1405 JumpIfSmi(tmp, either_smi_label, not_smi_label); 1406 } 1407 1408 1409 void MacroAssembler::JumpIfEitherNotSmi(Register value1, 1410 Register value2, 1411 Label* not_smi_label) { 1412 JumpIfBothSmi(value1, value2, NULL, not_smi_label); 1413 } 1414 1415 1416 void MacroAssembler::JumpIfBothNotSmi(Register value1, 1417 Register value2, 1418 Label* not_smi_label) { 1419 JumpIfEitherSmi(value1, value2, NULL, not_smi_label); 1420 } 1421 1422 1423 void MacroAssembler::ObjectTag(Register tagged_obj, Register obj) { 1424 STATIC_ASSERT(kHeapObjectTag == 1); 1425 if (emit_debug_code()) { 1426 Label ok; 1427 Tbz(obj, 0, &ok); 1428 Abort(kObjectTagged); 1429 Bind(&ok); 1430 } 1431 Orr(tagged_obj, obj, kHeapObjectTag); 1432 } 1433 1434 1435 void MacroAssembler::ObjectUntag(Register untagged_obj, Register obj) { 1436 STATIC_ASSERT(kHeapObjectTag == 1); 1437 if (emit_debug_code()) { 1438 Label ok; 1439 Tbnz(obj, 0, &ok); 1440 Abort(kObjectNotTagged); 1441 Bind(&ok); 1442 } 1443 Bic(untagged_obj, obj, kHeapObjectTag); 1444 } 1445 1446 1447 void MacroAssembler::IsObjectNameType(Register object, 1448 Register type, 1449 Label* fail) { 1450 CompareObjectType(object, type, type, LAST_NAME_TYPE); 1451 B(hi, fail); 1452 } 1453 1454 1455 void MacroAssembler::IsObjectJSObjectType(Register heap_object, 1456 Register map, 1457 Register scratch, 1458 Label* fail) { 1459 Ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset)); 1460 IsInstanceJSObjectType(map, scratch, fail); 1461 } 1462 1463 1464 void MacroAssembler::IsInstanceJSObjectType(Register map, 1465 Register scratch, 1466 Label* fail) { 1467 Ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); 1468 // If cmp result is lt, the following ccmp will clear all flags. 1469 // Z == 0, N == V implies gt condition. 1470 Cmp(scratch, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 1471 Ccmp(scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE, NoFlag, ge); 1472 1473 // If we didn't get a valid label object just fall through and leave the 1474 // flags updated. 1475 if (fail != NULL) { 1476 B(gt, fail); 1477 } 1478 } 1479 1480 1481 void MacroAssembler::IsObjectJSStringType(Register object, 1482 Register type, 1483 Label* not_string, 1484 Label* string) { 1485 Ldr(type, FieldMemOperand(object, HeapObject::kMapOffset)); 1486 Ldrb(type.W(), FieldMemOperand(type, Map::kInstanceTypeOffset)); 1487 1488 STATIC_ASSERT(kStringTag == 0); 1489 ASSERT((string != NULL) || (not_string != NULL)); 1490 if (string == NULL) { 1491 TestAndBranchIfAnySet(type.W(), kIsNotStringMask, not_string); 1492 } else if (not_string == NULL) { 1493 TestAndBranchIfAllClear(type.W(), kIsNotStringMask, string); 1494 } else { 1495 TestAndBranchIfAnySet(type.W(), kIsNotStringMask, not_string); 1496 B(string); 1497 } 1498 } 1499 1500 1501 void MacroAssembler::Push(Handle<Object> handle) { 1502 UseScratchRegisterScope temps(this); 1503 Register tmp = temps.AcquireX(); 1504 Mov(tmp, Operand(handle)); 1505 Push(tmp); 1506 } 1507 1508 1509 void MacroAssembler::Claim(uint64_t count, uint64_t unit_size) { 1510 uint64_t size = count * unit_size; 1511 1512 if (size == 0) { 1513 return; 1514 } 1515 1516 if (csp.Is(StackPointer())) { 1517 ASSERT(size % 16 == 0); 1518 } else { 1519 BumpSystemStackPointer(size); 1520 } 1521 1522 Sub(StackPointer(), StackPointer(), size); 1523 } 1524 1525 1526 void MacroAssembler::Claim(const Register& count, uint64_t unit_size) { 1527 if (unit_size == 0) return; 1528 ASSERT(IsPowerOf2(unit_size)); 1529 1530 const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits); 1531 const Operand size(count, LSL, shift); 1532 1533 if (size.IsZero()) { 1534 return; 1535 } 1536 1537 if (!csp.Is(StackPointer())) { 1538 BumpSystemStackPointer(size); 1539 } 1540 1541 Sub(StackPointer(), StackPointer(), size); 1542 } 1543 1544 1545 void MacroAssembler::ClaimBySMI(const Register& count_smi, uint64_t unit_size) { 1546 ASSERT(unit_size == 0 || IsPowerOf2(unit_size)); 1547 const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits) - kSmiShift; 1548 const Operand size(count_smi, 1549 (shift >= 0) ? (LSL) : (LSR), 1550 (shift >= 0) ? (shift) : (-shift)); 1551 1552 if (size.IsZero()) { 1553 return; 1554 } 1555 1556 if (!csp.Is(StackPointer())) { 1557 BumpSystemStackPointer(size); 1558 } 1559 1560 Sub(StackPointer(), StackPointer(), size); 1561 } 1562 1563 1564 void MacroAssembler::Drop(uint64_t count, uint64_t unit_size) { 1565 uint64_t size = count * unit_size; 1566 1567 if (size == 0) { 1568 return; 1569 } 1570 1571 Add(StackPointer(), StackPointer(), size); 1572 1573 if (csp.Is(StackPointer())) { 1574 ASSERT(size % 16 == 0); 1575 } else if (emit_debug_code()) { 1576 // It is safe to leave csp where it is when unwinding the JavaScript stack, 1577 // but if we keep it matching StackPointer, the simulator can detect memory 1578 // accesses in the now-free part of the stack. 1579 SyncSystemStackPointer(); 1580 } 1581 } 1582 1583 1584 void MacroAssembler::Drop(const Register& count, uint64_t unit_size) { 1585 if (unit_size == 0) return; 1586 ASSERT(IsPowerOf2(unit_size)); 1587 1588 const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits); 1589 const Operand size(count, LSL, shift); 1590 1591 if (size.IsZero()) { 1592 return; 1593 } 1594 1595 Add(StackPointer(), StackPointer(), size); 1596 1597 if (!csp.Is(StackPointer()) && emit_debug_code()) { 1598 // It is safe to leave csp where it is when unwinding the JavaScript stack, 1599 // but if we keep it matching StackPointer, the simulator can detect memory 1600 // accesses in the now-free part of the stack. 1601 SyncSystemStackPointer(); 1602 } 1603 } 1604 1605 1606 void MacroAssembler::DropBySMI(const Register& count_smi, uint64_t unit_size) { 1607 ASSERT(unit_size == 0 || IsPowerOf2(unit_size)); 1608 const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits) - kSmiShift; 1609 const Operand size(count_smi, 1610 (shift >= 0) ? (LSL) : (LSR), 1611 (shift >= 0) ? (shift) : (-shift)); 1612 1613 if (size.IsZero()) { 1614 return; 1615 } 1616 1617 Add(StackPointer(), StackPointer(), size); 1618 1619 if (!csp.Is(StackPointer()) && emit_debug_code()) { 1620 // It is safe to leave csp where it is when unwinding the JavaScript stack, 1621 // but if we keep it matching StackPointer, the simulator can detect memory 1622 // accesses in the now-free part of the stack. 1623 SyncSystemStackPointer(); 1624 } 1625 } 1626 1627 1628 void MacroAssembler::CompareAndBranch(const Register& lhs, 1629 const Operand& rhs, 1630 Condition cond, 1631 Label* label) { 1632 if (rhs.IsImmediate() && (rhs.ImmediateValue() == 0) && 1633 ((cond == eq) || (cond == ne))) { 1634 if (cond == eq) { 1635 Cbz(lhs, label); 1636 } else { 1637 Cbnz(lhs, label); 1638 } 1639 } else { 1640 Cmp(lhs, rhs); 1641 B(cond, label); 1642 } 1643 } 1644 1645 1646 void MacroAssembler::TestAndBranchIfAnySet(const Register& reg, 1647 const uint64_t bit_pattern, 1648 Label* label) { 1649 int bits = reg.SizeInBits(); 1650 ASSERT(CountSetBits(bit_pattern, bits) > 0); 1651 if (CountSetBits(bit_pattern, bits) == 1) { 1652 Tbnz(reg, MaskToBit(bit_pattern), label); 1653 } else { 1654 Tst(reg, bit_pattern); 1655 B(ne, label); 1656 } 1657 } 1658 1659 1660 void MacroAssembler::TestAndBranchIfAllClear(const Register& reg, 1661 const uint64_t bit_pattern, 1662 Label* label) { 1663 int bits = reg.SizeInBits(); 1664 ASSERT(CountSetBits(bit_pattern, bits) > 0); 1665 if (CountSetBits(bit_pattern, bits) == 1) { 1666 Tbz(reg, MaskToBit(bit_pattern), label); 1667 } else { 1668 Tst(reg, bit_pattern); 1669 B(eq, label); 1670 } 1671 } 1672 1673 1674 void MacroAssembler::InlineData(uint64_t data) { 1675 ASSERT(is_uint16(data)); 1676 InstructionAccurateScope scope(this, 1); 1677 movz(xzr, data); 1678 } 1679 1680 1681 void MacroAssembler::EnableInstrumentation() { 1682 InstructionAccurateScope scope(this, 1); 1683 movn(xzr, InstrumentStateEnable); 1684 } 1685 1686 1687 void MacroAssembler::DisableInstrumentation() { 1688 InstructionAccurateScope scope(this, 1); 1689 movn(xzr, InstrumentStateDisable); 1690 } 1691 1692 1693 void MacroAssembler::AnnotateInstrumentation(const char* marker_name) { 1694 ASSERT(strlen(marker_name) == 2); 1695 1696 // We allow only printable characters in the marker names. Unprintable 1697 // characters are reserved for controlling features of the instrumentation. 1698 ASSERT(isprint(marker_name[0]) && isprint(marker_name[1])); 1699 1700 InstructionAccurateScope scope(this, 1); 1701 movn(xzr, (marker_name[1] << 8) | marker_name[0]); 1702 } 1703 1704 } } // namespace v8::internal 1705 1706 #endif // V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_ 1707