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