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