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 19namespace v8 { 20namespace internal { 21 22 23MemOperand FieldMemOperand(Register object, int offset) { 24 return MemOperand(object, offset - kHeapObjectTag); 25} 26 27 28MemOperand UntagSmiFieldMemOperand(Register object, int offset) { 29 return UntagSmiMemOperand(object, offset - kHeapObjectTag); 30} 31 32 33MemOperand 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 40Handle<Object> MacroAssembler::CodeObject() { 41 DCHECK(!code_object_.is_null()); 42 return code_object_; 43} 44 45 46void 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 55void 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 64void MacroAssembler::Tst(const Register& rn, 65 const Operand& operand) { 66 DCHECK(allow_macro_instructions_); 67 LogicalMacro(AppropriateZeroRegFor(rn), rn, operand, ANDS); 68} 69 70 71void 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 80void 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 89void 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 98void 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 107void 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 116void 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 125void 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 138void 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 151void 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 163void 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 176void 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 189void 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 202void MacroAssembler::Cmn(const Register& rn, const Operand& operand) { 203 DCHECK(allow_macro_instructions_); 204 Adds(AppropriateZeroRegFor(rn), rn, operand); 205} 206 207 208void MacroAssembler::Cmp(const Register& rn, const Operand& operand) { 209 DCHECK(allow_macro_instructions_); 210 Subs(AppropriateZeroRegFor(rn), rn, operand); 211} 212 213 214void 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 226void MacroAssembler::Negs(const Register& rd, 227 const Operand& operand) { 228 DCHECK(allow_macro_instructions_); 229 Subs(rd, AppropriateZeroRegFor(rd), operand); 230} 231 232 233void 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 242void 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 251void 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 260void 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 269void 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 278void 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 287void 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) \ 295void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) { \ 296 DCHECK(allow_macro_instructions_); \ 297 LoadStoreMacro(REG, addr, OP); \ 298} 299LS_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 } 309LSPAIR_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 } 317LDA_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 } 326STLX_MACRO_LIST(DECLARE_FUNCTION) 327#undef DECLARE_FUNCTION 328 329void 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 338void 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 347void MacroAssembler::B(Label* label) { 348 b(label); 349 CheckVeneerPool(false, false); 350} 351 352 353void MacroAssembler::B(Condition cond, Label* label) { 354 DCHECK(allow_macro_instructions_); 355 B(label, cond); 356} 357 358 359void 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 369void 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 379void MacroAssembler::Bind(Label* label) { 380 DCHECK(allow_macro_instructions_); 381 bind(label); 382} 383 384 385void MacroAssembler::Bl(Label* label) { 386 DCHECK(allow_macro_instructions_); 387 bl(label); 388} 389 390 391void MacroAssembler::Blr(const Register& xn) { 392 DCHECK(allow_macro_instructions_); 393 DCHECK(!xn.IsZero()); 394 blr(xn); 395} 396 397 398void MacroAssembler::Br(const Register& xn) { 399 DCHECK(allow_macro_instructions_); 400 DCHECK(!xn.IsZero()); 401 br(xn); 402} 403 404 405void MacroAssembler::Brk(int code) { 406 DCHECK(allow_macro_instructions_); 407 brk(code); 408} 409 410 411void 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 421void 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 431void MacroAssembler::Cls(const Register& rd, const Register& rn) { 432 DCHECK(allow_macro_instructions_); 433 DCHECK(!rd.IsZero()); 434 cls(rd, rn); 435} 436 437 438void MacroAssembler::Clz(const Register& rd, const Register& rn) { 439 DCHECK(allow_macro_instructions_); 440 DCHECK(!rd.IsZero()); 441 clz(rd, rn); 442} 443 444 445void 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. 457void 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. 468void 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 481void 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 489void 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 497void 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 508void 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 519void 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 530void MacroAssembler::Dmb(BarrierDomain domain, BarrierType type) { 531 DCHECK(allow_macro_instructions_); 532 dmb(domain, type); 533} 534 535 536void MacroAssembler::Dsb(BarrierDomain domain, BarrierType type) { 537 DCHECK(allow_macro_instructions_); 538 dsb(domain, type); 539} 540 541 542void MacroAssembler::Debug(const char* message, uint32_t code, Instr params) { 543 DCHECK(allow_macro_instructions_); 544 debug(message, code, params); 545} 546 547 548void 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 558void MacroAssembler::Fabs(const FPRegister& fd, const FPRegister& fn) { 559 DCHECK(allow_macro_instructions_); 560 fabs(fd, fn); 561} 562 563 564void 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 572void 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 582void MacroAssembler::Fcmp(const FPRegister& fn, const FPRegister& fm) { 583 DCHECK(allow_macro_instructions_); 584 fcmp(fn, fm); 585} 586 587 588void 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 601void 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 611void MacroAssembler::Fcvt(const FPRegister& fd, const FPRegister& fn) { 612 DCHECK(allow_macro_instructions_); 613 fcvt(fd, fn); 614} 615 616 617void MacroAssembler::Fcvtas(const Register& rd, const FPRegister& fn) { 618 DCHECK(allow_macro_instructions_); 619 DCHECK(!rd.IsZero()); 620 fcvtas(rd, fn); 621} 622 623 624void MacroAssembler::Fcvtau(const Register& rd, const FPRegister& fn) { 625 DCHECK(allow_macro_instructions_); 626 DCHECK(!rd.IsZero()); 627 fcvtau(rd, fn); 628} 629 630 631void MacroAssembler::Fcvtms(const Register& rd, const FPRegister& fn) { 632 DCHECK(allow_macro_instructions_); 633 DCHECK(!rd.IsZero()); 634 fcvtms(rd, fn); 635} 636 637 638void MacroAssembler::Fcvtmu(const Register& rd, const FPRegister& fn) { 639 DCHECK(allow_macro_instructions_); 640 DCHECK(!rd.IsZero()); 641 fcvtmu(rd, fn); 642} 643 644 645void MacroAssembler::Fcvtns(const Register& rd, const FPRegister& fn) { 646 DCHECK(allow_macro_instructions_); 647 DCHECK(!rd.IsZero()); 648 fcvtns(rd, fn); 649} 650 651 652void MacroAssembler::Fcvtnu(const Register& rd, const FPRegister& fn) { 653 DCHECK(allow_macro_instructions_); 654 DCHECK(!rd.IsZero()); 655 fcvtnu(rd, fn); 656} 657 658 659void MacroAssembler::Fcvtzs(const Register& rd, const FPRegister& fn) { 660 DCHECK(allow_macro_instructions_); 661 DCHECK(!rd.IsZero()); 662 fcvtzs(rd, fn); 663} 664void MacroAssembler::Fcvtzu(const Register& rd, const FPRegister& fn) { 665 DCHECK(allow_macro_instructions_); 666 DCHECK(!rd.IsZero()); 667 fcvtzu(rd, fn); 668} 669 670 671void 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 679void 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 688void 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 696void 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 704void 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 712void 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 720void 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 732void MacroAssembler::Fmov(FPRegister fd, Register rn) { 733 DCHECK(allow_macro_instructions_); 734 fmov(fd, rn); 735} 736 737 738void 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 756void 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 778void MacroAssembler::Fmov(Register rd, FPRegister fn) { 779 DCHECK(allow_macro_instructions_); 780 DCHECK(!rd.IsZero()); 781 fmov(rd, fn); 782} 783 784 785void 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 794void 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 802void MacroAssembler::Fneg(const FPRegister& fd, const FPRegister& fn) { 803 DCHECK(allow_macro_instructions_); 804 fneg(fd, fn); 805} 806 807 808void 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 817void 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 826void MacroAssembler::Frinta(const FPRegister& fd, const FPRegister& fn) { 827 DCHECK(allow_macro_instructions_); 828 frinta(fd, fn); 829} 830 831 832void MacroAssembler::Frintm(const FPRegister& fd, const FPRegister& fn) { 833 DCHECK(allow_macro_instructions_); 834 frintm(fd, fn); 835} 836 837 838void MacroAssembler::Frintn(const FPRegister& fd, const FPRegister& fn) { 839 DCHECK(allow_macro_instructions_); 840 frintn(fd, fn); 841} 842 843 844void MacroAssembler::Frintp(const FPRegister& fd, const FPRegister& fn) { 845 DCHECK(allow_macro_instructions_); 846 frintp(fd, fn); 847} 848 849 850void MacroAssembler::Frintz(const FPRegister& fd, const FPRegister& fn) { 851 DCHECK(allow_macro_instructions_); 852 frintz(fd, fn); 853} 854 855 856void MacroAssembler::Fsqrt(const FPRegister& fd, const FPRegister& fn) { 857 DCHECK(allow_macro_instructions_); 858 fsqrt(fd, fn); 859} 860 861 862void 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 870void MacroAssembler::Hint(SystemHint code) { 871 DCHECK(allow_macro_instructions_); 872 hint(code); 873} 874 875 876void MacroAssembler::Hlt(int code) { 877 DCHECK(allow_macro_instructions_); 878 hlt(code); 879} 880 881 882void MacroAssembler::Isb() { 883 DCHECK(allow_macro_instructions_); 884 isb(); 885} 886 887 888void MacroAssembler::Ldr(const CPURegister& rt, const Immediate& imm) { 889 DCHECK(allow_macro_instructions_); 890 ldr(rt, imm); 891} 892 893 894void 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 901void 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 910void 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 919void 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 928void 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 937void 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 947void 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 956void 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 968void 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 975void MacroAssembler::Mrs(const Register& rt, SystemRegister sysreg) { 976 DCHECK(allow_macro_instructions_); 977 DCHECK(!rt.IsZero()); 978 mrs(rt, sysreg); 979} 980 981 982void MacroAssembler::Msr(SystemRegister sysreg, const Register& rt) { 983 DCHECK(allow_macro_instructions_); 984 msr(sysreg, rt); 985} 986 987 988void 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 998void 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 1007void MacroAssembler::Rbit(const Register& rd, const Register& rn) { 1008 DCHECK(allow_macro_instructions_); 1009 DCHECK(!rd.IsZero()); 1010 rbit(rd, rn); 1011} 1012 1013 1014void MacroAssembler::Ret(const Register& xn) { 1015 DCHECK(allow_macro_instructions_); 1016 DCHECK(!xn.IsZero()); 1017 ret(xn); 1018 CheckVeneerPool(false, false); 1019} 1020 1021 1022void MacroAssembler::Rev(const Register& rd, const Register& rn) { 1023 DCHECK(allow_macro_instructions_); 1024 DCHECK(!rd.IsZero()); 1025 rev(rd, rn); 1026} 1027 1028 1029void MacroAssembler::Rev16(const Register& rd, const Register& rn) { 1030 DCHECK(allow_macro_instructions_); 1031 DCHECK(!rd.IsZero()); 1032 rev16(rd, rn); 1033} 1034 1035 1036void MacroAssembler::Rev32(const Register& rd, const Register& rn) { 1037 DCHECK(allow_macro_instructions_); 1038 DCHECK(!rd.IsZero()); 1039 rev32(rd, rn); 1040} 1041 1042 1043void 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 1052void 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 1061void 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 1071void 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 1081void 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 1089void 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 1098void 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 1108void 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 1118void 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 1127void 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 1136void 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 1144void MacroAssembler::Sxtb(const Register& rd, const Register& rn) { 1145 DCHECK(allow_macro_instructions_); 1146 DCHECK(!rd.IsZero()); 1147 sxtb(rd, rn); 1148} 1149 1150 1151void MacroAssembler::Sxth(const Register& rd, const Register& rn) { 1152 DCHECK(allow_macro_instructions_); 1153 DCHECK(!rd.IsZero()); 1154 sxth(rd, rn); 1155} 1156 1157 1158void MacroAssembler::Sxtw(const Register& rd, const Register& rn) { 1159 DCHECK(allow_macro_instructions_); 1160 DCHECK(!rd.IsZero()); 1161 sxtw(rd, rn); 1162} 1163 1164 1165void 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 1175void 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 1185void 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 1193void 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 1202void 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 1212void 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 1222void MacroAssembler::Uxtb(const Register& rd, const Register& rn) { 1223 DCHECK(allow_macro_instructions_); 1224 DCHECK(!rd.IsZero()); 1225 uxtb(rd, rn); 1226} 1227 1228 1229void MacroAssembler::Uxth(const Register& rd, const Register& rn) { 1230 DCHECK(allow_macro_instructions_); 1231 DCHECK(!rd.IsZero()); 1232 uxth(rd, rn); 1233} 1234 1235 1236void MacroAssembler::Uxtw(const Register& rd, const Register& rn) { 1237 DCHECK(allow_macro_instructions_); 1238 DCHECK(!rd.IsZero()); 1239 uxtw(rd, rn); 1240} 1241 1242 1243void 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 1279void 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 1289void MacroAssembler::InitializeRootRegister() { 1290 ExternalReference roots_array_start = 1291 ExternalReference::roots_array_start(isolate()); 1292 Mov(root, Operand(roots_array_start)); 1293} 1294 1295 1296void 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 1304void MacroAssembler::SmiTag(Register smi) { SmiTag(smi, smi); } 1305 1306 1307void 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 1318void MacroAssembler::SmiUntag(Register smi) { SmiUntag(smi, smi); } 1319 1320 1321void 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 1332void 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 1343void 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 1351void 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 1359void 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 1376void MacroAssembler::JumpIfNotSmi(Register value, Label* not_smi_label) { 1377 JumpIfSmi(value, NULL, not_smi_label); 1378} 1379 1380 1381void 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 1394void 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 1407void MacroAssembler::JumpIfEitherNotSmi(Register value1, 1408 Register value2, 1409 Label* not_smi_label) { 1410 JumpIfBothSmi(value1, value2, NULL, not_smi_label); 1411} 1412 1413 1414void MacroAssembler::JumpIfBothNotSmi(Register value1, 1415 Register value2, 1416 Label* not_smi_label) { 1417 JumpIfEitherSmi(value1, value2, NULL, not_smi_label); 1418} 1419 1420 1421void 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 1433void 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 1445void 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 1453void 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 1473void 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 1481void 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 1499void 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 1519void 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 1538void 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 1559void 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 1582void 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 1604void 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 1622void 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 1636void 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 1650void MacroAssembler::InlineData(uint64_t data) { 1651 DCHECK(is_uint16(data)); 1652 InstructionAccurateScope scope(this, 1); 1653 movz(xzr, data); 1654} 1655 1656 1657void MacroAssembler::EnableInstrumentation() { 1658 InstructionAccurateScope scope(this, 1); 1659 movn(xzr, InstrumentStateEnable); 1660} 1661 1662 1663void MacroAssembler::DisableInstrumentation() { 1664 InstructionAccurateScope scope(this, 1); 1665 movn(xzr, InstrumentStateDisable); 1666} 1667 1668 1669void 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