MacroAssembler-loong64-inl.h (79793B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef jit_loong64_MacroAssembler_loong64_inl_h 8 #define jit_loong64_MacroAssembler_loong64_inl_h 9 10 #include "jit/loong64/MacroAssembler-loong64.h" 11 12 namespace js { 13 namespace jit { 14 15 //{{{ check_macroassembler_style 16 17 void MacroAssembler::move64(Register64 src, Register64 dest) { 18 movePtr(src.reg, dest.reg); 19 } 20 21 void MacroAssembler::move64(Imm64 imm, Register64 dest) { 22 movePtr(ImmWord(imm.value), dest.reg); 23 } 24 25 void MacroAssembler::moveDoubleToGPR64(FloatRegister src, Register64 dest) { 26 moveFromDouble(src, dest.reg); 27 } 28 29 void MacroAssembler::moveGPR64ToDouble(Register64 src, FloatRegister dest) { 30 moveToDouble(src.reg, dest); 31 } 32 33 void MacroAssembler::moveLowDoubleToGPR(FloatRegister src, Register dest) { 34 MOZ_CRASH("Not supported for this target"); 35 } 36 37 void MacroAssembler::move64To32(Register64 src, Register dest) { 38 as_slli_w(dest, src.reg, 0); 39 } 40 41 void MacroAssembler::move32To64ZeroExtend(Register src, Register64 dest) { 42 as_bstrpick_d(dest.reg, src, 31, 0); 43 } 44 45 void MacroAssembler::move8To64SignExtend(Register src, Register64 dest) { 46 move32To64SignExtend(src, dest); 47 move8SignExtend(dest.reg, dest.reg); 48 } 49 50 void MacroAssembler::move16To64SignExtend(Register src, Register64 dest) { 51 move32To64SignExtend(src, dest); 52 move16SignExtend(dest.reg, dest.reg); 53 } 54 55 void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) { 56 as_slli_w(dest.reg, src, 0); 57 } 58 59 void MacroAssembler::moveFloat32ToGPR(FloatRegister src, Register dest) { 60 moveFromFloat32(src, dest); 61 } 62 63 void MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest) { 64 moveToFloat32(src, dest); 65 } 66 67 void MacroAssembler::moveFloat16ToGPR(FloatRegister src, Register dest) { 68 MOZ_CRASH("Not supported for this target"); 69 } 70 71 void MacroAssembler::moveGPRToFloat16(Register src, FloatRegister dest) { 72 MOZ_CRASH("Not supported for this target"); 73 } 74 75 void MacroAssembler::move8ZeroExtend(Register src, Register dest) { 76 as_bstrpick_d(dest, src, 7, 0); 77 } 78 79 void MacroAssembler::move8SignExtend(Register src, Register dest) { 80 as_ext_w_b(dest, src); 81 } 82 83 void MacroAssembler::move16SignExtend(Register src, Register dest) { 84 as_ext_w_h(dest, src); 85 } 86 87 void MacroAssembler::move8SignExtendToPtr(Register src, Register dest) { 88 move8To64SignExtend(src, Register64(dest)); 89 } 90 91 void MacroAssembler::move16SignExtendToPtr(Register src, Register dest) { 92 move16To64SignExtend(src, Register64(dest)); 93 } 94 95 void MacroAssembler::move32SignExtendToPtr(Register src, Register dest) { 96 as_slli_w(dest, src, 0); 97 } 98 99 void MacroAssembler::move32ZeroExtendToPtr(Register src, Register dest) { 100 as_bstrpick_d(dest, src, 31, 0); 101 } 102 103 // =============================================================== 104 // Load instructions 105 106 void MacroAssembler::load32SignExtendToPtr(const Address& src, Register dest) { 107 load32(src, dest); 108 } 109 110 void MacroAssembler::loadAbiReturnAddress(Register dest) { movePtr(ra, dest); } 111 112 // =============================================================== 113 // Logical instructions 114 115 void MacroAssembler::not32(Register reg) { as_nor(reg, reg, zero); } 116 117 void MacroAssembler::notPtr(Register reg) { as_nor(reg, reg, zero); } 118 119 void MacroAssembler::andPtr(Register src, Register dest) { 120 as_and(dest, dest, src); 121 } 122 123 void MacroAssembler::andPtr(Imm32 imm, Register dest) { 124 ma_and(dest, dest, imm); 125 } 126 127 void MacroAssembler::andPtr(Imm32 imm, Register src, Register dest) { 128 ma_and(dest, src, imm); 129 } 130 131 void MacroAssembler::and64(Imm64 imm, Register64 dest) { 132 UseScratchRegisterScope temps(asMasm()); 133 Register scratch = temps.Acquire(); 134 ma_li(scratch, ImmWord(imm.value)); 135 as_and(dest.reg, dest.reg, scratch); 136 } 137 138 void MacroAssembler::and64(Register64 src, Register64 dest) { 139 as_and(dest.reg, dest.reg, src.reg); 140 } 141 142 void MacroAssembler::and32(Register src, Register dest) { 143 as_and(dest, dest, src); 144 } 145 146 void MacroAssembler::and32(Imm32 imm, Register dest) { 147 ma_and(dest, dest, imm); 148 } 149 150 void MacroAssembler::and32(Imm32 imm, Register src, Register dest) { 151 ma_and(dest, src, imm); 152 } 153 154 void MacroAssembler::and32(Imm32 imm, const Address& dest) { 155 UseScratchRegisterScope temps(asMasm()); 156 Register scratch = temps.Acquire(); 157 load32(dest, scratch); 158 and32(imm, scratch); 159 store32(scratch, dest); 160 } 161 162 void MacroAssembler::and32(const Address& src, Register dest) { 163 UseScratchRegisterScope temps(asMasm()); 164 Register scratch = temps.Acquire(); 165 load32(src, scratch); 166 as_and(dest, dest, scratch); 167 } 168 169 void MacroAssembler::or64(Imm64 imm, Register64 dest) { 170 UseScratchRegisterScope temps(asMasm()); 171 Register scratch = temps.Acquire(); 172 ma_li(scratch, ImmWord(imm.value)); 173 as_or(dest.reg, dest.reg, scratch); 174 } 175 176 void MacroAssembler::or32(Register src, Register dest) { 177 as_or(dest, dest, src); 178 } 179 180 void MacroAssembler::or32(Imm32 imm, Register dest) { ma_or(dest, dest, imm); } 181 182 void MacroAssembler::or32(Imm32 imm, Register src, Register dest) { 183 ma_or(dest, src, imm); 184 } 185 186 void MacroAssembler::or32(Imm32 imm, const Address& dest) { 187 UseScratchRegisterScope temps(asMasm()); 188 Register scratch = temps.Acquire(); 189 load32(dest, scratch); 190 or32(imm, scratch); 191 store32(scratch, dest); 192 } 193 194 void MacroAssembler::xor64(Imm64 imm, Register64 dest) { 195 UseScratchRegisterScope temps(asMasm()); 196 Register scratch = temps.Acquire(); 197 ma_li(scratch, ImmWord(imm.value)); 198 as_xor(dest.reg, dest.reg, scratch); 199 } 200 201 void MacroAssembler::orPtr(Register src, Register dest) { 202 as_or(dest, dest, src); 203 } 204 205 void MacroAssembler::orPtr(Imm32 imm, Register dest) { ma_or(dest, dest, imm); } 206 207 void MacroAssembler::orPtr(Imm32 imm, Register src, Register dest) { 208 ma_or(dest, src, imm); 209 } 210 211 void MacroAssembler::or64(Register64 src, Register64 dest) { 212 as_or(dest.reg, dest.reg, src.reg); 213 } 214 215 void MacroAssembler::xor64(Register64 src, Register64 dest) { 216 as_xor(dest.reg, dest.reg, src.reg); 217 } 218 219 void MacroAssembler::xorPtr(Register src, Register dest) { 220 as_xor(dest, dest, src); 221 } 222 223 void MacroAssembler::xorPtr(Imm32 imm, Register dest) { 224 ma_xor(dest, dest, imm); 225 } 226 227 void MacroAssembler::xorPtr(Imm32 imm, Register src, Register dest) { 228 ma_xor(dest, src, imm); 229 } 230 231 void MacroAssembler::xor32(Register src, Register dest) { 232 as_xor(dest, dest, src); 233 } 234 235 void MacroAssembler::xor32(Imm32 imm, Register dest) { 236 ma_xor(dest, dest, imm); 237 } 238 239 void MacroAssembler::xor32(Imm32 imm, Register src, Register dest) { 240 ma_xor(dest, src, imm); 241 } 242 243 void MacroAssembler::xor32(Imm32 imm, const Address& dest) { 244 UseScratchRegisterScope temps(asMasm()); 245 Register scratch = temps.Acquire(); 246 load32(dest, scratch); 247 xor32(imm, scratch); 248 store32(scratch, dest); 249 } 250 251 void MacroAssembler::xor32(const Address& src, Register dest) { 252 UseScratchRegisterScope temps(asMasm()); 253 Register scratch = temps.Acquire(); 254 load32(src, scratch); 255 xor32(scratch, dest); 256 } 257 258 // =============================================================== 259 // Swap instructions 260 261 void MacroAssembler::byteSwap16SignExtend(Register reg) { 262 as_revb_2h(reg, reg); 263 as_ext_w_h(reg, reg); 264 } 265 266 void MacroAssembler::byteSwap16ZeroExtend(Register reg) { 267 as_revb_2h(reg, reg); 268 as_bstrpick_d(reg, reg, 15, 0); 269 } 270 271 void MacroAssembler::byteSwap32(Register reg) { 272 as_revb_2w(reg, reg); 273 as_slli_w(reg, reg, 0); 274 } 275 276 void MacroAssembler::byteSwap64(Register64 reg64) { 277 as_revb_d(reg64.reg, reg64.reg); 278 } 279 280 // =============================================================== 281 // Arithmetic functions 282 283 void MacroAssembler::addPtr(Register src, Register dest) { 284 as_add_d(dest, dest, src); 285 } 286 287 void MacroAssembler::addPtr(Imm32 imm, Register dest) { 288 ma_add_d(dest, dest, imm); 289 } 290 291 void MacroAssembler::addPtr(ImmWord imm, Register dest) { 292 UseScratchRegisterScope temps(asMasm()); 293 Register scratch = temps.Acquire(); 294 movePtr(imm, scratch); 295 addPtr(scratch, dest); 296 } 297 298 void MacroAssembler::add64(Register64 src, Register64 dest) { 299 addPtr(src.reg, dest.reg); 300 } 301 302 void MacroAssembler::add64(Imm32 imm, Register64 dest) { 303 ma_add_d(dest.reg, dest.reg, imm); 304 } 305 306 void MacroAssembler::add64(Imm64 imm, Register64 dest) { 307 UseScratchRegisterScope temps(asMasm()); 308 Register scratch = temps.Acquire(); 309 MOZ_ASSERT(dest.reg != scratch); 310 mov(ImmWord(imm.value), scratch); 311 as_add_d(dest.reg, dest.reg, scratch); 312 } 313 314 void MacroAssembler::add32(Register src, Register dest) { 315 as_add_w(dest, dest, src); 316 } 317 318 void MacroAssembler::add32(Imm32 imm, Register dest) { 319 ma_add_w(dest, dest, imm); 320 } 321 322 void MacroAssembler::add32(Imm32 imm, Register src, Register dest) { 323 ma_add_w(dest, src, imm); 324 } 325 326 void MacroAssembler::add32(Imm32 imm, const Address& dest) { 327 UseScratchRegisterScope temps(asMasm()); 328 Register scratch = temps.Acquire(); 329 load32(dest, scratch); 330 ma_add_w(scratch, scratch, imm); 331 store32(scratch, dest); 332 } 333 334 void MacroAssembler::add32(const Address& src, Register dest) { 335 UseScratchRegisterScope temps(asMasm()); 336 Register scratch = temps.Acquire(); 337 load32(src, scratch); 338 as_add_w(dest, dest, scratch); 339 } 340 341 void MacroAssembler::addPtr(Imm32 imm, const Address& dest) { 342 UseScratchRegisterScope temps(asMasm()); 343 Register scratch = temps.Acquire(); 344 loadPtr(dest, scratch); 345 addPtr(imm, scratch); 346 storePtr(scratch, dest); 347 } 348 349 void MacroAssembler::addPtr(const Address& src, Register dest) { 350 UseScratchRegisterScope temps(asMasm()); 351 Register scratch = temps.Acquire(); 352 loadPtr(src, scratch); 353 addPtr(scratch, dest); 354 } 355 356 void MacroAssembler::addDouble(FloatRegister src, FloatRegister dest) { 357 as_fadd_d(dest, dest, src); 358 } 359 360 void MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest) { 361 as_fadd_s(dest, dest, src); 362 } 363 364 CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) { 365 CodeOffset offset = CodeOffset(currentOffset()); 366 MacroAssemblerLOONG64::ma_liPatchable(dest, Imm32(0)); 367 as_sub_d(dest, StackPointer, dest); 368 return offset; 369 } 370 371 void MacroAssembler::patchSub32FromStackPtr(CodeOffset offset, Imm32 imm) { 372 // TODO: by wangqing 373 InstImm* lu12i_w = (InstImm*)m_buffer.getInst(BufferOffset(offset.offset())); 374 InstImm* ori = (InstImm*)m_buffer.getInst(BufferOffset(offset.offset() + 4)); 375 376 MOZ_ASSERT((lu12i_w->extractBitField(31, 25)) == 377 ((uint32_t)op_lu12i_w >> 25)); 378 MOZ_ASSERT((ori->extractBitField(31, 22)) == ((uint32_t)op_ori >> 22)); 379 380 *lu12i_w = InstImm(op_lu12i_w, (int32_t)((imm.value >> 12) & 0xfffff), 381 Register::FromCode(lu12i_w->extractRD()), false); 382 *ori = InstImm(op_ori, (int32_t)(imm.value & 0xfff), 383 Register::FromCode(ori->extractRJ()), 384 Register::FromCode(ori->extractRD()), 12); 385 } 386 387 void MacroAssembler::subPtr(Register src, Register dest) { 388 as_sub_d(dest, dest, src); 389 } 390 391 void MacroAssembler::subPtr(Imm32 imm, Register dest) { 392 ma_sub_d(dest, dest, imm); 393 } 394 395 void MacroAssembler::sub64(Register64 src, Register64 dest) { 396 as_sub_d(dest.reg, dest.reg, src.reg); 397 } 398 399 void MacroAssembler::sub64(Imm64 imm, Register64 dest) { 400 UseScratchRegisterScope temps(asMasm()); 401 Register scratch = temps.Acquire(); 402 MOZ_ASSERT(dest.reg != scratch); 403 mov(ImmWord(imm.value), scratch); 404 as_sub_d(dest.reg, dest.reg, scratch); 405 } 406 407 void MacroAssembler::sub32(Register src, Register dest) { 408 as_sub_w(dest, dest, src); 409 } 410 411 void MacroAssembler::sub32(Imm32 imm, Register dest) { 412 ma_sub_w(dest, dest, imm); 413 } 414 415 void MacroAssembler::sub32(const Address& src, Register dest) { 416 UseScratchRegisterScope temps(asMasm()); 417 Register scratch = temps.Acquire(); 418 load32(src, scratch); 419 as_sub_w(dest, dest, scratch); 420 } 421 422 void MacroAssembler::subPtr(Register src, const Address& dest) { 423 UseScratchRegisterScope temps(asMasm()); 424 Register scratch = temps.Acquire(); 425 loadPtr(dest, scratch); 426 subPtr(src, scratch); 427 storePtr(scratch, dest); 428 } 429 430 void MacroAssembler::subPtr(const Address& addr, Register dest) { 431 UseScratchRegisterScope temps(asMasm()); 432 Register scratch = temps.Acquire(); 433 loadPtr(addr, scratch); 434 subPtr(scratch, dest); 435 } 436 437 void MacroAssembler::subDouble(FloatRegister src, FloatRegister dest) { 438 as_fsub_d(dest, dest, src); 439 } 440 441 void MacroAssembler::subFloat32(FloatRegister src, FloatRegister dest) { 442 as_fsub_s(dest, dest, src); 443 } 444 445 void MacroAssembler::mul64(Imm64 imm, const Register64& dest) { 446 UseScratchRegisterScope temps(asMasm()); 447 Register scratch = temps.Acquire(); 448 MOZ_ASSERT(dest.reg != scratch); 449 mov(ImmWord(imm.value), scratch); 450 as_mul_d(dest.reg, dest.reg, scratch); 451 } 452 453 void MacroAssembler::mul64(Imm64 imm, const Register64& dest, 454 const Register temp) { 455 MOZ_ASSERT(temp == Register::Invalid()); 456 mul64(imm, dest); 457 } 458 459 void MacroAssembler::mul64(const Register64& src, const Register64& dest, 460 const Register temp) { 461 MOZ_ASSERT(temp == Register::Invalid()); 462 as_mul_d(dest.reg, dest.reg, src.reg); 463 } 464 465 void MacroAssembler::mulPtr(Register rhs, Register srcDest) { 466 as_mul_d(srcDest, srcDest, rhs); 467 } 468 469 void MacroAssembler::mulPtr(ImmWord rhs, Register srcDest) { 470 UseScratchRegisterScope temps(asMasm()); 471 Register scratch = temps.Acquire(); 472 MOZ_ASSERT(srcDest != scratch); 473 mov(rhs, scratch); 474 mulPtr(scratch, srcDest); 475 } 476 477 void MacroAssembler::mulBy3(Register src, Register dest) { 478 UseScratchRegisterScope temps(asMasm()); 479 Register scratch = temps.Acquire(); 480 MOZ_ASSERT(src != scratch); 481 as_add_d(scratch, src, src); 482 as_add_d(dest, scratch, src); 483 } 484 485 void MacroAssembler::mul32(Register rhs, Register srcDest) { 486 as_mul_w(srcDest, srcDest, rhs); 487 } 488 489 void MacroAssembler::mul32(Imm32 imm, Register srcDest) { 490 UseScratchRegisterScope temps(asMasm()); 491 Register scratch = temps.Acquire(); 492 move32(imm, scratch); 493 mul32(scratch, srcDest); 494 } 495 496 void MacroAssembler::mulHighUnsigned32(Imm32 imm, Register src, Register dest) { 497 UseScratchRegisterScope temps(asMasm()); 498 Register scratch = temps.Acquire(); 499 MOZ_ASSERT(src != scratch); 500 move32(imm, scratch); 501 as_mulh_wu(dest, src, scratch); 502 } 503 504 void MacroAssembler::mulFloat32(FloatRegister src, FloatRegister dest) { 505 as_fmul_s(dest, dest, src); 506 } 507 508 void MacroAssembler::mulDouble(FloatRegister src, FloatRegister dest) { 509 as_fmul_d(dest, dest, src); 510 } 511 512 void MacroAssembler::mulDoublePtr(ImmPtr imm, Register temp, 513 FloatRegister dest) { 514 UseScratchRegisterScope temps(asMasm()); 515 Register scratch = temps.Acquire(); 516 ScratchDoubleScope fpscratch(asMasm()); 517 movePtr(imm, scratch); 518 loadDouble(Address(scratch, 0), fpscratch); 519 mulDouble(fpscratch, dest); 520 } 521 522 void MacroAssembler::inc64(AbsoluteAddress dest) { 523 UseScratchRegisterScope temps(asMasm()); 524 Register scratch = temps.Acquire(); 525 Register scratch2 = temps.Acquire(); 526 ma_li(scratch, ImmWord(uintptr_t(dest.addr))); 527 as_ld_d(scratch2, scratch, 0); 528 as_addi_d(scratch2, scratch2, 1); 529 as_st_d(scratch2, scratch, 0); 530 } 531 532 void MacroAssembler::quotient32(Register lhs, Register rhs, Register dest, 533 bool isUnsigned) { 534 if (isUnsigned) { 535 as_div_wu(dest, lhs, rhs); 536 } else { 537 as_div_w(dest, lhs, rhs); 538 } 539 } 540 541 void MacroAssembler::quotient64(Register lhs, Register rhs, Register dest, 542 bool isUnsigned) { 543 if (isUnsigned) { 544 as_div_du(dest, lhs, rhs); 545 } else { 546 as_div_d(dest, lhs, rhs); 547 } 548 } 549 550 void MacroAssembler::remainder32(Register lhs, Register rhs, Register dest, 551 bool isUnsigned) { 552 if (isUnsigned) { 553 as_mod_wu(dest, lhs, rhs); 554 } else { 555 as_mod_w(dest, lhs, rhs); 556 } 557 } 558 559 void MacroAssembler::remainder64(Register lhs, Register rhs, Register dest, 560 bool isUnsigned) { 561 if (isUnsigned) { 562 as_mod_du(dest, lhs, rhs); 563 } else { 564 as_mod_d(dest, lhs, rhs); 565 } 566 } 567 568 void MacroAssembler::divFloat32(FloatRegister src, FloatRegister dest) { 569 as_fdiv_s(dest, dest, src); 570 } 571 572 void MacroAssembler::divDouble(FloatRegister src, FloatRegister dest) { 573 as_fdiv_d(dest, dest, src); 574 } 575 576 void MacroAssembler::neg64(Register64 reg) { as_sub_d(reg.reg, zero, reg.reg); } 577 578 void MacroAssembler::negPtr(Register reg) { as_sub_d(reg, zero, reg); } 579 580 void MacroAssembler::neg32(Register reg) { as_sub_w(reg, zero, reg); } 581 582 void MacroAssembler::negateDouble(FloatRegister reg) { as_fneg_d(reg, reg); } 583 584 void MacroAssembler::negateFloat(FloatRegister reg) { as_fneg_s(reg, reg); } 585 586 void MacroAssembler::abs32(Register src, Register dest) { 587 UseScratchRegisterScope temps(asMasm()); 588 Register scratch = temps.Acquire(); 589 as_srai_w(scratch, src, 31); 590 as_xor(dest, src, scratch); 591 as_sub_w(dest, dest, scratch); 592 } 593 594 void MacroAssembler::absFloat32(FloatRegister src, FloatRegister dest) { 595 as_fabs_s(dest, src); 596 } 597 598 void MacroAssembler::absDouble(FloatRegister src, FloatRegister dest) { 599 as_fabs_d(dest, src); 600 } 601 602 void MacroAssembler::sqrtFloat32(FloatRegister src, FloatRegister dest) { 603 as_fsqrt_s(dest, src); 604 } 605 606 void MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest) { 607 as_fsqrt_d(dest, src); 608 } 609 610 void MacroAssembler::min32(Register lhs, Register rhs, Register dest) { 611 minMaxPtr(lhs, rhs, dest, /* isMax = */ false); 612 } 613 614 void MacroAssembler::min32(Register lhs, Imm32 rhs, Register dest) { 615 minMaxPtr(lhs, ImmWord(rhs.value), dest, /* isMax = */ false); 616 } 617 618 void MacroAssembler::max32(Register lhs, Register rhs, Register dest) { 619 minMaxPtr(lhs, rhs, dest, /* isMax = */ true); 620 } 621 622 void MacroAssembler::max32(Register lhs, Imm32 rhs, Register dest) { 623 minMaxPtr(lhs, ImmWord(rhs.value), dest, /* isMax = */ true); 624 } 625 626 void MacroAssembler::minPtr(Register lhs, Register rhs, Register dest) { 627 minMaxPtr(lhs, rhs, dest, /* isMax = */ false); 628 } 629 630 void MacroAssembler::minPtr(Register lhs, ImmWord rhs, Register dest) { 631 minMaxPtr(lhs, rhs, dest, /* isMax = */ false); 632 } 633 634 void MacroAssembler::maxPtr(Register lhs, Register rhs, Register dest) { 635 minMaxPtr(lhs, rhs, dest, /* isMax = */ true); 636 } 637 638 void MacroAssembler::maxPtr(Register lhs, ImmWord rhs, Register dest) { 639 minMaxPtr(lhs, rhs, dest, /* isMax = */ true); 640 } 641 642 void MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest, 643 bool handleNaN) { 644 minMaxFloat32(srcDest, other, handleNaN, false); 645 } 646 647 void MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest, 648 bool handleNaN) { 649 minMaxDouble(srcDest, other, handleNaN, false); 650 } 651 652 void MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest, 653 bool handleNaN) { 654 minMaxFloat32(srcDest, other, handleNaN, true); 655 } 656 657 void MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest, 658 bool handleNaN) { 659 minMaxDouble(srcDest, other, handleNaN, true); 660 } 661 662 // =============================================================== 663 // Shift functions 664 665 void MacroAssembler::lshift32(Register src, Register dest) { 666 as_sll_w(dest, dest, src); 667 } 668 669 void MacroAssembler::lshift32(Imm32 imm, Register dest) { 670 lshift32(imm, dest, dest); 671 } 672 673 void MacroAssembler::lshift32(Imm32 imm, Register src, Register dest) { 674 as_slli_w(dest, src, imm.value & 0x1f); 675 } 676 677 void MacroAssembler::flexibleLshift32(Register src, Register dest) { 678 lshift32(src, dest); 679 } 680 681 void MacroAssembler::lshift64(Register shift, Register64 dest) { 682 as_sll_d(dest.reg, dest.reg, shift); 683 } 684 685 void MacroAssembler::lshift64(Imm32 imm, Register64 dest) { 686 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 687 as_slli_d(dest.reg, dest.reg, imm.value); 688 } 689 690 void MacroAssembler::lshiftPtr(Register shift, Register dest) { 691 as_sll_d(dest, dest, shift); 692 } 693 694 void MacroAssembler::lshiftPtr(Imm32 imm, Register dest) { 695 lshiftPtr(imm, dest, dest); 696 } 697 698 void MacroAssembler::lshiftPtr(Imm32 imm, Register src, Register dest) { 699 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 700 as_slli_d(dest, src, imm.value); 701 } 702 703 void MacroAssembler::flexibleLshiftPtr(Register shift, Register srcDest) { 704 lshiftPtr(shift, srcDest); 705 } 706 707 void MacroAssembler::rshift32(Register src, Register dest) { 708 as_srl_w(dest, dest, src); 709 } 710 711 void MacroAssembler::rshift32(Imm32 imm, Register dest) { 712 rshift32(imm, dest, dest); 713 } 714 715 void MacroAssembler::rshift32(Imm32 imm, Register src, Register dest) { 716 as_srli_w(dest, src, imm.value & 0x1f); 717 } 718 719 void MacroAssembler::flexibleRshift32(Register src, Register dest) { 720 rshift32(src, dest); 721 } 722 723 void MacroAssembler::rshift32Arithmetic(Register src, Register dest) { 724 as_sra_w(dest, dest, src); 725 } 726 727 void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register dest) { 728 rshift32Arithmetic(imm, dest, dest); 729 } 730 731 void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register src, 732 Register dest) { 733 as_srai_w(dest, src, imm.value & 0x1f); 734 } 735 736 void MacroAssembler::flexibleRshift32Arithmetic(Register src, Register dest) { 737 rshift32Arithmetic(src, dest); 738 } 739 740 void MacroAssembler::rshift64(Register shift, Register64 dest) { 741 as_srl_d(dest.reg, dest.reg, shift); 742 } 743 744 void MacroAssembler::rshift64(Imm32 imm, Register64 dest) { 745 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 746 as_srli_d(dest.reg, dest.reg, imm.value); 747 } 748 749 void MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest) { 750 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 751 as_srai_d(dest.reg, dest.reg, imm.value); 752 } 753 754 void MacroAssembler::rshift64Arithmetic(Register shift, Register64 dest) { 755 as_sra_d(dest.reg, dest.reg, shift); 756 } 757 758 void MacroAssembler::rshiftPtr(Register shift, Register dest) { 759 as_srl_d(dest, dest, shift); 760 } 761 762 void MacroAssembler::rshiftPtr(Imm32 imm, Register dest) { 763 rshiftPtr(imm, dest, dest); 764 } 765 766 void MacroAssembler::rshiftPtr(Imm32 imm, Register src, Register dest) { 767 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 768 as_srli_d(dest, src, imm.value); 769 } 770 771 void MacroAssembler::flexibleRshiftPtr(Register shift, Register srcDest) { 772 rshiftPtr(shift, srcDest); 773 } 774 775 void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest) { 776 rshiftPtrArithmetic(imm, dest, dest); 777 } 778 779 void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register src, 780 Register dest) { 781 MOZ_ASSERT(0 <= imm.value && imm.value < 64); 782 as_srai_d(dest, src, imm.value); 783 } 784 785 void MacroAssembler::rshiftPtrArithmetic(Register shift, Register dest) { 786 as_sra_d(dest, dest, shift); 787 } 788 789 void MacroAssembler::flexibleRshiftPtrArithmetic(Register shift, 790 Register srcDest) { 791 rshiftPtrArithmetic(shift, srcDest); 792 } 793 794 // =============================================================== 795 // Rotation functions 796 797 void MacroAssembler::rotateLeft(Register count, Register input, Register dest) { 798 UseScratchRegisterScope temps(asMasm()); 799 Register scratch = temps.Acquire(); 800 as_sub_w(scratch, zero, count); 801 as_rotr_w(dest, input, scratch); 802 } 803 804 void MacroAssembler::rotateLeft(Imm32 count, Register input, Register dest) { 805 as_rotri_w(dest, input, (32 - count.value) & 31); 806 } 807 808 void MacroAssembler::rotateLeft64(Register count, Register64 src, 809 Register64 dest, Register temp) { 810 MOZ_ASSERT(temp == Register::Invalid()); 811 UseScratchRegisterScope temps(asMasm()); 812 Register scratch = temps.Acquire(); 813 as_sub_d(scratch, zero, count); 814 as_rotr_d(dest.reg, src.reg, scratch); 815 } 816 817 void MacroAssembler::rotateLeft64(Imm32 count, Register64 src, Register64 dest, 818 Register temp) { 819 MOZ_ASSERT(temp == Register::Invalid()); 820 as_rotri_d(dest.reg, src.reg, (64 - count.value) & 63); 821 } 822 823 void MacroAssembler::rotateRight(Register count, Register input, 824 Register dest) { 825 as_rotr_w(dest, input, count); 826 } 827 828 void MacroAssembler::rotateRight(Imm32 count, Register input, Register dest) { 829 as_rotri_w(dest, input, count.value & 31); 830 } 831 832 void MacroAssembler::rotateRight64(Register count, Register64 src, 833 Register64 dest, Register temp) { 834 MOZ_ASSERT(temp == Register::Invalid()); 835 as_rotr_d(dest.reg, src.reg, count); 836 } 837 838 void MacroAssembler::rotateRight64(Imm32 count, Register64 src, Register64 dest, 839 Register temp) { 840 MOZ_ASSERT(temp == Register::Invalid()); 841 as_rotri_d(dest.reg, src.reg, count.value & 63); 842 } 843 844 // Bit counting functions 845 846 void MacroAssembler::clz64(Register64 src, Register64 dest) { 847 as_clz_d(dest.reg, src.reg); 848 } 849 850 void MacroAssembler::ctz64(Register64 src, Register64 dest) { 851 as_ctz_d(dest.reg, src.reg); 852 } 853 854 void MacroAssembler::popcnt64(Register64 input, Register64 output, 855 Register tmp) { 856 UseScratchRegisterScope temps(asMasm()); 857 Register scratch = temps.Acquire(); 858 as_or(output.reg, input.reg, zero); 859 as_srai_d(tmp, input.reg, 1); 860 ma_li(scratch, Imm32(0x55555555)); 861 as_bstrins_d(scratch, scratch, 63, 32); 862 as_and(tmp, tmp, scratch); 863 as_sub_d(output.reg, output.reg, tmp); 864 as_srai_d(tmp, output.reg, 2); 865 ma_li(scratch, Imm32(0x33333333)); 866 as_bstrins_d(scratch, scratch, 63, 32); 867 as_and(output.reg, output.reg, scratch); 868 as_and(tmp, tmp, scratch); 869 as_add_d(output.reg, output.reg, tmp); 870 as_srli_d(tmp, output.reg, 4); 871 as_add_d(output.reg, output.reg, tmp); 872 ma_li(scratch, Imm32(0xF0F0F0F)); 873 as_bstrins_d(scratch, scratch, 63, 32); 874 as_and(output.reg, output.reg, scratch); 875 ma_li(tmp, Imm32(0x1010101)); 876 as_bstrins_d(tmp, tmp, 63, 32); 877 as_mul_d(output.reg, output.reg, tmp); 878 as_srai_d(output.reg, output.reg, 56); 879 } 880 881 void MacroAssembler::clz32(Register src, Register dest, bool knownNotZero) { 882 as_clz_w(dest, src); 883 } 884 885 void MacroAssembler::ctz32(Register src, Register dest, bool knownNotZero) { 886 as_ctz_w(dest, src); 887 } 888 889 void MacroAssembler::popcnt32(Register input, Register output, Register tmp) { 890 // Equivalent to GCC output of mozilla::CountPopulation32() 891 as_or(output, input, zero); 892 as_srai_w(tmp, input, 1); 893 ma_and(tmp, tmp, Imm32(0x55555555)); 894 as_sub_w(output, output, tmp); 895 as_srai_w(tmp, output, 2); 896 ma_and(output, output, Imm32(0x33333333)); 897 ma_and(tmp, tmp, Imm32(0x33333333)); 898 as_add_w(output, output, tmp); 899 as_srli_w(tmp, output, 4); 900 as_add_w(output, output, tmp); 901 ma_and(output, output, Imm32(0xF0F0F0F)); 902 as_slli_w(tmp, output, 8); 903 as_add_w(output, output, tmp); 904 as_slli_w(tmp, output, 16); 905 as_add_w(output, output, tmp); 906 as_srai_w(output, output, 24); 907 } 908 909 // =============================================================== 910 // Condition functions 911 912 void MacroAssembler::cmp8Set(Condition cond, Address lhs, Imm32 rhs, 913 Register dest) { 914 UseScratchRegisterScope temps(*this); 915 Register scratch = temps.Acquire(); 916 MOZ_ASSERT(scratch != lhs.base); 917 918 switch (cond) { 919 case Assembler::Equal: 920 case Assembler::NotEqual: 921 case Assembler::Above: 922 case Assembler::AboveOrEqual: 923 case Assembler::Below: 924 case Assembler::BelowOrEqual: 925 load8ZeroExtend(lhs, scratch); 926 ma_cmp_set(dest, scratch, Imm32(uint8_t(rhs.value)), cond); 927 break; 928 929 case Assembler::GreaterThan: 930 case Assembler::GreaterThanOrEqual: 931 case Assembler::LessThan: 932 case Assembler::LessThanOrEqual: 933 load8SignExtend(lhs, scratch); 934 ma_cmp_set(dest, scratch, Imm32(int8_t(rhs.value)), cond); 935 break; 936 937 default: 938 MOZ_CRASH("unexpected condition"); 939 } 940 } 941 942 void MacroAssembler::cmp16Set(Condition cond, Address lhs, Imm32 rhs, 943 Register dest) { 944 UseScratchRegisterScope temps(*this); 945 Register scratch = temps.Acquire(); 946 MOZ_ASSERT(scratch != lhs.base); 947 948 switch (cond) { 949 case Assembler::Equal: 950 case Assembler::NotEqual: 951 case Assembler::Above: 952 case Assembler::AboveOrEqual: 953 case Assembler::Below: 954 case Assembler::BelowOrEqual: 955 load16ZeroExtend(lhs, scratch); 956 ma_cmp_set(dest, scratch, Imm32(uint16_t(rhs.value)), cond); 957 break; 958 959 case Assembler::GreaterThan: 960 case Assembler::GreaterThanOrEqual: 961 case Assembler::LessThan: 962 case Assembler::LessThanOrEqual: 963 load16SignExtend(lhs, scratch); 964 ma_cmp_set(dest, scratch, Imm32(int16_t(rhs.value)), cond); 965 break; 966 967 default: 968 MOZ_CRASH("unexpected condition"); 969 } 970 } 971 972 // Also see below for specializations of cmpPtrSet. 973 template <typename T1, typename T2> 974 void MacroAssembler::cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest) { 975 ma_cmp_set(dest, lhs, rhs, cond); 976 } 977 978 void MacroAssembler::cmp64Set(Condition cond, Register64 lhs, Register64 rhs, 979 Register dest) { 980 ma_cmp_set(dest, lhs.reg, rhs.reg, cond); 981 } 982 983 void MacroAssembler::cmp64Set(Condition cond, Register64 lhs, Imm64 rhs, 984 Register dest) { 985 ma_cmp_set(dest, lhs.reg, ImmWord(uint64_t(rhs.value)), cond); 986 } 987 988 void MacroAssembler::cmp64Set(Condition cond, Address lhs, Register64 rhs, 989 Register dest) { 990 ma_cmp_set(dest, lhs, rhs.reg, cond); 991 } 992 993 void MacroAssembler::cmp64Set(Condition cond, Address lhs, Imm64 rhs, 994 Register dest) { 995 ma_cmp_set(dest, lhs, ImmWord(uint64_t(rhs.value)), cond); 996 } 997 998 template <typename T1, typename T2> 999 void MacroAssembler::cmpPtrSet(Condition cond, T1 lhs, T2 rhs, Register dest) { 1000 ma_cmp_set(dest, lhs, rhs, cond); 1001 } 1002 1003 // =============================================================== 1004 // Branch functions 1005 1006 void MacroAssembler::branch8(Condition cond, const Address& lhs, Imm32 rhs, 1007 Label* label) { 1008 UseScratchRegisterScope temps(*this); 1009 Register scratch = temps.Acquire(); 1010 MOZ_ASSERT(scratch != lhs.base); 1011 1012 switch (cond) { 1013 case Assembler::Equal: 1014 case Assembler::NotEqual: 1015 case Assembler::Above: 1016 case Assembler::AboveOrEqual: 1017 case Assembler::Below: 1018 case Assembler::BelowOrEqual: 1019 load8ZeroExtend(lhs, scratch); 1020 branch32(cond, scratch, Imm32(uint8_t(rhs.value)), label); 1021 break; 1022 1023 case Assembler::GreaterThan: 1024 case Assembler::GreaterThanOrEqual: 1025 case Assembler::LessThan: 1026 case Assembler::LessThanOrEqual: 1027 load8SignExtend(lhs, scratch); 1028 branch32(cond, scratch, Imm32(int8_t(rhs.value)), label); 1029 break; 1030 1031 default: 1032 MOZ_CRASH("unexpected condition"); 1033 } 1034 } 1035 1036 void MacroAssembler::branch8(Condition cond, const BaseIndex& lhs, Register rhs, 1037 Label* label) { 1038 UseScratchRegisterScope temps(*this); 1039 Register scratch = temps.Acquire(); 1040 MOZ_ASSERT(scratch != lhs.base); 1041 1042 computeScaledAddress(lhs, scratch); 1043 1044 switch (cond) { 1045 case Assembler::Equal: 1046 case Assembler::NotEqual: 1047 case Assembler::Above: 1048 case Assembler::AboveOrEqual: 1049 case Assembler::Below: 1050 case Assembler::BelowOrEqual: 1051 load8ZeroExtend(Address(scratch, lhs.offset), scratch); 1052 branch32(cond, scratch, rhs, label); 1053 break; 1054 1055 case Assembler::GreaterThan: 1056 case Assembler::GreaterThanOrEqual: 1057 case Assembler::LessThan: 1058 case Assembler::LessThanOrEqual: 1059 load8SignExtend(Address(scratch, lhs.offset), scratch); 1060 branch32(cond, scratch, rhs, label); 1061 break; 1062 1063 default: 1064 MOZ_CRASH("unexpected condition"); 1065 } 1066 } 1067 1068 void MacroAssembler::branch16(Condition cond, const Address& lhs, Imm32 rhs, 1069 Label* label) { 1070 UseScratchRegisterScope temps(*this); 1071 Register scratch = temps.Acquire(); 1072 MOZ_ASSERT(scratch != lhs.base); 1073 1074 switch (cond) { 1075 case Assembler::Equal: 1076 case Assembler::NotEqual: 1077 case Assembler::Above: 1078 case Assembler::AboveOrEqual: 1079 case Assembler::Below: 1080 case Assembler::BelowOrEqual: 1081 load16ZeroExtend(lhs, scratch); 1082 branch32(cond, scratch, Imm32(uint16_t(rhs.value)), label); 1083 break; 1084 1085 case Assembler::GreaterThan: 1086 case Assembler::GreaterThanOrEqual: 1087 case Assembler::LessThan: 1088 case Assembler::LessThanOrEqual: 1089 load16SignExtend(lhs, scratch); 1090 branch32(cond, scratch, Imm32(int16_t(rhs.value)), label); 1091 break; 1092 1093 default: 1094 MOZ_CRASH("unexpected condition"); 1095 } 1096 } 1097 1098 void MacroAssembler::branch32(Condition cond, Register lhs, Register rhs, 1099 Label* label) { 1100 ma_b(lhs, rhs, label, cond); 1101 } 1102 1103 void MacroAssembler::branch32(Condition cond, Register lhs, Imm32 imm, 1104 Label* label) { 1105 ma_b(lhs, imm, label, cond); 1106 } 1107 1108 void MacroAssembler::branch32(Condition cond, const Address& lhs, Register rhs, 1109 Label* label) { 1110 UseScratchRegisterScope temps(asMasm()); 1111 Register scratch = temps.Acquire(); 1112 load32(lhs, scratch); 1113 ma_b(scratch, rhs, label, cond); 1114 } 1115 1116 void MacroAssembler::branch32(Condition cond, const Address& lhs, Imm32 rhs, 1117 Label* label) { 1118 UseScratchRegisterScope temps(asMasm()); 1119 Register scratch = temps.Acquire(); 1120 load32(lhs, scratch); 1121 ma_b(scratch, rhs, label, cond); 1122 } 1123 1124 void MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs, 1125 Register rhs, Label* label) { 1126 UseScratchRegisterScope temps(asMasm()); 1127 Register scratch = temps.Acquire(); 1128 load32(lhs, scratch); 1129 ma_b(scratch, rhs, label, cond); 1130 } 1131 1132 void MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs, 1133 Imm32 rhs, Label* label) { 1134 UseScratchRegisterScope temps(asMasm()); 1135 Register scratch = temps.Acquire(); 1136 load32(lhs, scratch); 1137 ma_b(scratch, rhs, label, cond); 1138 } 1139 1140 void MacroAssembler::branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs, 1141 Label* label) { 1142 UseScratchRegisterScope temps(asMasm()); 1143 Register scratch = temps.Acquire(); 1144 load32(lhs, scratch); 1145 ma_b(scratch, rhs, label, cond); 1146 } 1147 1148 void MacroAssembler::branch32(Condition cond, wasm::SymbolicAddress addr, 1149 Imm32 imm, Label* label) { 1150 UseScratchRegisterScope temps(asMasm()); 1151 Register scratch = temps.Acquire(); 1152 load32(addr, scratch); 1153 ma_b(scratch, imm, label, cond); 1154 } 1155 1156 void MacroAssembler::branch64(Condition cond, Register64 lhs, Imm64 val, 1157 Label* success, Label* fail) { 1158 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 1159 cond == Assembler::LessThan || 1160 cond == Assembler::LessThanOrEqual || 1161 cond == Assembler::GreaterThan || 1162 cond == Assembler::GreaterThanOrEqual || 1163 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 1164 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 1165 "other condition codes not supported"); 1166 1167 branchPtr(cond, lhs.reg, ImmWord(val.value), success); 1168 if (fail) { 1169 jump(fail); 1170 } 1171 } 1172 1173 void MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs, 1174 Label* success, Label* fail) { 1175 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 1176 cond == Assembler::LessThan || 1177 cond == Assembler::LessThanOrEqual || 1178 cond == Assembler::GreaterThan || 1179 cond == Assembler::GreaterThanOrEqual || 1180 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 1181 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 1182 "other condition codes not supported"); 1183 1184 branchPtr(cond, lhs.reg, rhs.reg, success); 1185 if (fail) { 1186 jump(fail); 1187 } 1188 } 1189 1190 void MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val, 1191 Label* success, Label* fail) { 1192 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 1193 cond == Assembler::LessThan || 1194 cond == Assembler::LessThanOrEqual || 1195 cond == Assembler::GreaterThan || 1196 cond == Assembler::GreaterThanOrEqual || 1197 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 1198 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 1199 "other condition codes not supported"); 1200 1201 branchPtr(cond, lhs, ImmWord(val.value), success); 1202 if (fail) { 1203 jump(fail); 1204 } 1205 } 1206 1207 void MacroAssembler::branch64(Condition cond, const Address& lhs, 1208 Register64 rhs, Label* success, Label* fail) { 1209 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal || 1210 cond == Assembler::LessThan || 1211 cond == Assembler::LessThanOrEqual || 1212 cond == Assembler::GreaterThan || 1213 cond == Assembler::GreaterThanOrEqual || 1214 cond == Assembler::Below || cond == Assembler::BelowOrEqual || 1215 cond == Assembler::Above || cond == Assembler::AboveOrEqual, 1216 "other condition codes not supported"); 1217 1218 branchPtr(cond, lhs, rhs.reg, success); 1219 if (fail) { 1220 jump(fail); 1221 } 1222 } 1223 1224 void MacroAssembler::branch64(Condition cond, const Address& lhs, 1225 const Address& rhs, Register scratch, 1226 Label* label) { 1227 MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal, 1228 "other condition codes not supported"); 1229 MOZ_ASSERT(lhs.base != scratch); 1230 MOZ_ASSERT(rhs.base != scratch); 1231 1232 loadPtr(rhs, scratch); 1233 branchPtr(cond, lhs, scratch, label); 1234 } 1235 1236 void MacroAssembler::branchPtr(Condition cond, Register lhs, Register rhs, 1237 Label* label) { 1238 ma_b(lhs, rhs, label, cond); 1239 } 1240 1241 void MacroAssembler::branchPtr(Condition cond, Register lhs, Imm32 rhs, 1242 Label* label) { 1243 ma_b(lhs, rhs, label, cond); 1244 } 1245 1246 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmPtr rhs, 1247 Label* label) { 1248 ma_b(lhs, rhs, label, cond); 1249 } 1250 1251 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmGCPtr rhs, 1252 Label* label) { 1253 ma_b(lhs, rhs, label, cond); 1254 } 1255 1256 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmWord rhs, 1257 Label* label) { 1258 ma_b(lhs, rhs, label, cond); 1259 } 1260 1261 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, Register rhs, 1262 Label* label) { 1263 UseScratchRegisterScope temps(asMasm()); 1264 Register scratch = temps.Acquire(); 1265 loadPtr(lhs, scratch); 1266 branchPtr(cond, scratch, rhs, label); 1267 } 1268 1269 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmPtr rhs, 1270 Label* label) { 1271 UseScratchRegisterScope temps(asMasm()); 1272 Register scratch = temps.Acquire(); 1273 loadPtr(lhs, scratch); 1274 branchPtr(cond, scratch, rhs, label); 1275 } 1276 1277 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmGCPtr rhs, 1278 Label* label) { 1279 UseScratchRegisterScope temps(asMasm()); 1280 Register scratch = temps.Acquire(); 1281 loadPtr(lhs, scratch); 1282 branchPtr(cond, scratch, rhs, label); 1283 } 1284 1285 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmWord rhs, 1286 Label* label) { 1287 UseScratchRegisterScope temps(asMasm()); 1288 Register scratch = temps.Acquire(); 1289 loadPtr(lhs, scratch); 1290 branchPtr(cond, scratch, rhs, label); 1291 } 1292 1293 void MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs, 1294 Register rhs, Label* label) { 1295 UseScratchRegisterScope temps(asMasm()); 1296 Register scratch = temps.Acquire(); 1297 loadPtr(lhs, scratch); 1298 branchPtr(cond, scratch, rhs, label); 1299 } 1300 1301 void MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs, 1302 ImmWord rhs, Label* label) { 1303 UseScratchRegisterScope temps(asMasm()); 1304 Register scratch = temps.Acquire(); 1305 loadPtr(lhs, scratch); 1306 branchPtr(cond, scratch, rhs, label); 1307 } 1308 1309 void MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs, 1310 Register rhs, Label* label) { 1311 UseScratchRegisterScope temps(asMasm()); 1312 Register scratch = temps.Acquire(); 1313 loadPtr(lhs, scratch); 1314 branchPtr(cond, scratch, rhs, label); 1315 } 1316 1317 void MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs, 1318 Register rhs, Label* label) { 1319 UseScratchRegisterScope temps(asMasm()); 1320 Register scratch = temps.Acquire(); 1321 loadPtr(lhs, scratch); 1322 branchPtr(cond, scratch, rhs, label); 1323 } 1324 1325 void MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs, 1326 ImmWord rhs, Label* label) { 1327 UseScratchRegisterScope temps(asMasm()); 1328 Register scratch = temps.Acquire(); 1329 loadPtr(lhs, scratch); 1330 branchPtr(cond, scratch, rhs, label); 1331 } 1332 1333 void MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs, 1334 Register rhs, Label* label) { 1335 branchPtr(cond, lhs, rhs, label); 1336 } 1337 1338 void MacroAssembler::branchFloat(DoubleCondition cond, FloatRegister lhs, 1339 FloatRegister rhs, Label* label) { 1340 ma_bc_s(lhs, rhs, label, cond); 1341 } 1342 1343 void MacroAssembler::branchTruncateFloat32MaybeModUint32(FloatRegister src, 1344 Register dest, 1345 Label* fail) { 1346 UseScratchRegisterScope temps(asMasm()); 1347 Register scratch = temps.Acquire(); 1348 ScratchDoubleScope fpscratch(asMasm()); 1349 as_ftintrz_l_s(fpscratch, src); 1350 as_movfcsr2gr(scratch); 1351 moveFromDouble(fpscratch, dest); 1352 MOZ_ASSERT(Assembler::CauseV < 32); 1353 as_bstrpick_w(scratch, scratch, Assembler::CauseV, Assembler::CauseV); 1354 ma_b(scratch, Imm32(0), fail, Assembler::NotEqual); 1355 1356 as_slli_w(dest, dest, 0); 1357 } 1358 1359 void MacroAssembler::branchTruncateFloat32ToInt32(FloatRegister src, 1360 Register dest, Label* fail) { 1361 convertFloat32ToInt32(src, dest, fail, false); 1362 } 1363 1364 void MacroAssembler::branchDouble(DoubleCondition cond, FloatRegister lhs, 1365 FloatRegister rhs, Label* label) { 1366 ma_bc_d(lhs, rhs, label, cond); 1367 } 1368 1369 void MacroAssembler::branchTruncateDoubleMaybeModUint32(FloatRegister src, 1370 Register dest, 1371 Label* fail) { 1372 UseScratchRegisterScope temps(asMasm()); 1373 Register scratch = temps.Acquire(); 1374 ScratchDoubleScope fpscratch(asMasm()); 1375 as_ftintrz_l_d(fpscratch, src); 1376 as_movfcsr2gr(scratch); 1377 moveFromDouble(fpscratch, dest); 1378 MOZ_ASSERT(Assembler::CauseV < 32); 1379 as_bstrpick_w(scratch, scratch, Assembler::CauseV, Assembler::CauseV); 1380 ma_b(scratch, Imm32(0), fail, Assembler::NotEqual); 1381 1382 as_slli_w(dest, dest, 0); 1383 } 1384 1385 void MacroAssembler::branchTruncateDoubleToInt32(FloatRegister src, 1386 Register dest, Label* fail) { 1387 UseScratchRegisterScope temps(asMasm()); 1388 Register scratch = temps.Acquire(); 1389 ScratchDoubleScope fpscratch(asMasm()); 1390 1391 // Convert scalar to signed 64-bit fixed-point, rounding toward zero. 1392 // In the case of overflow, the output is saturated. 1393 // In the case of NaN and -0, the output is zero. 1394 as_ftintrz_l_d(fpscratch, src); 1395 moveFromDouble(fpscratch, dest); 1396 1397 // Fail on overflow cases. 1398 as_slli_w(scratch, dest, 0); 1399 ma_b(dest, scratch, fail, Assembler::NotEqual); 1400 } 1401 1402 void MacroAssembler::branchInt64NotInPtrRange(Register64 src, Label* label) { 1403 // No-op on 64-bit platforms. 1404 } 1405 1406 void MacroAssembler::branchUInt64NotInPtrRange(Register64 src, Label* label) { 1407 branchTest64(Assembler::Signed, src, src, label); 1408 } 1409 1410 template <typename T> 1411 void MacroAssembler::branchAdd32(Condition cond, T src, Register dest, 1412 Label* overflow) { 1413 switch (cond) { 1414 case Overflow: 1415 ma_add32TestOverflow(dest, dest, src, overflow); 1416 break; 1417 case CarryClear: 1418 case CarrySet: 1419 ma_add32TestCarry(cond, dest, dest, src, overflow); 1420 break; 1421 default: 1422 MOZ_CRASH("NYI"); 1423 } 1424 } 1425 1426 // the type of 'T src' maybe a Register, maybe a Imm32,depends on who call it. 1427 template <typename T> 1428 void MacroAssembler::branchSub32(Condition cond, T src, Register dest, 1429 Label* overflow) { 1430 switch (cond) { 1431 case Overflow: 1432 ma_sub32TestOverflow(dest, dest, src, overflow); 1433 break; 1434 case NonZero: 1435 case Zero: 1436 case Signed: 1437 case NotSigned: 1438 ma_sub_w(dest, dest, src); 1439 ma_b(dest, dest, overflow, cond); 1440 break; 1441 default: 1442 MOZ_CRASH("NYI"); 1443 } 1444 } 1445 1446 template <typename T> 1447 void MacroAssembler::branchMul32(Condition cond, T src, Register dest, 1448 Label* overflow) { 1449 MOZ_ASSERT(cond == Assembler::Overflow); 1450 ma_mul32TestOverflow(dest, dest, src, overflow); 1451 } 1452 1453 template <typename T> 1454 void MacroAssembler::branchRshift32(Condition cond, T src, Register dest, 1455 Label* label) { 1456 MOZ_ASSERT(cond == Zero || cond == NonZero); 1457 rshift32(src, dest); 1458 branch32(cond == Zero ? Equal : NotEqual, dest, Imm32(0), label); 1459 } 1460 1461 void MacroAssembler::branchNeg32(Condition cond, Register reg, Label* label) { 1462 MOZ_ASSERT(cond == Overflow); 1463 neg32(reg); 1464 branch32(Assembler::Equal, reg, Imm32(INT32_MIN), label); 1465 } 1466 1467 template <typename T> 1468 void MacroAssembler::branchAddPtr(Condition cond, T src, Register dest, 1469 Label* label) { 1470 switch (cond) { 1471 case Overflow: 1472 ma_addPtrTestOverflow(dest, dest, src, label); 1473 break; 1474 case CarryClear: 1475 case CarrySet: 1476 ma_addPtrTestCarry(cond, dest, dest, src, label); 1477 break; 1478 case Signed: 1479 case NotSigned: 1480 ma_addPtrTestSigned(cond, dest, dest, src, label); 1481 break; 1482 default: 1483 MOZ_CRASH("NYI"); 1484 } 1485 } 1486 1487 template <typename T> 1488 void MacroAssembler::branchSubPtr(Condition cond, T src, Register dest, 1489 Label* label) { 1490 switch (cond) { 1491 case Overflow: 1492 ma_subPtrTestOverflow(dest, dest, src, label); 1493 break; 1494 case NonZero: 1495 case Zero: 1496 case Signed: 1497 case NotSigned: 1498 subPtr(src, dest); 1499 ma_b(dest, dest, label, cond); 1500 break; 1501 default: 1502 MOZ_CRASH("NYI"); 1503 } 1504 } 1505 1506 void MacroAssembler::branchMulPtr(Condition cond, Register src, Register dest, 1507 Label* label) { 1508 MOZ_ASSERT(cond == Assembler::Overflow); 1509 ma_mulPtrTestOverflow(dest, dest, src, label); 1510 } 1511 1512 void MacroAssembler::branchNegPtr(Condition cond, Register reg, Label* label) { 1513 MOZ_ASSERT(cond == Overflow); 1514 negPtr(reg); 1515 branchPtr(Assembler::Equal, reg, ImmWord(INTPTR_MIN), label); 1516 } 1517 1518 void MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs, 1519 Label* label) { 1520 subPtr(rhs, lhs); 1521 branchPtr(cond, lhs, Imm32(0), label); 1522 } 1523 1524 void MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, 1525 Label* label) { 1526 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 1527 cond == NotSigned); 1528 if (lhs == rhs) { 1529 ma_b(lhs, rhs, label, cond); 1530 } else { 1531 UseScratchRegisterScope temps(asMasm()); 1532 Register scratch = temps.Acquire(); 1533 as_and(scratch, lhs, rhs); 1534 ma_b(scratch, scratch, label, cond); 1535 } 1536 } 1537 1538 void MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs, 1539 Label* label) { 1540 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 1541 cond == NotSigned); 1542 UseScratchRegisterScope temps(asMasm()); 1543 Register scratch = temps.Acquire(); 1544 ma_and(scratch, lhs, rhs); 1545 ma_b(scratch, scratch, label, cond); 1546 } 1547 1548 void MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs, 1549 Label* label) { 1550 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 1551 cond == NotSigned); 1552 UseScratchRegisterScope temps(asMasm()); 1553 Register scratch = temps.Acquire(); 1554 load32(lhs, scratch); 1555 and32(rhs, scratch); 1556 ma_b(scratch, scratch, label, cond); 1557 } 1558 1559 void MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs, 1560 Imm32 rhs, Label* label) { 1561 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 1562 cond == NotSigned); 1563 UseScratchRegisterScope temps(asMasm()); 1564 Register scratch = temps.Acquire(); 1565 load32(lhs, scratch); 1566 and32(rhs, scratch); 1567 ma_b(scratch, scratch, label, cond); 1568 } 1569 1570 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs, 1571 Label* label) { 1572 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 1573 cond == NotSigned); 1574 if (lhs == rhs) { 1575 ma_b(lhs, rhs, label, cond); 1576 } else { 1577 UseScratchRegisterScope temps(asMasm()); 1578 Register scratch = temps.Acquire(); 1579 as_and(scratch, lhs, rhs); 1580 ma_b(scratch, scratch, label, cond); 1581 } 1582 } 1583 1584 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, Imm32 rhs, 1585 Label* label) { 1586 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 1587 cond == NotSigned); 1588 UseScratchRegisterScope temps(asMasm()); 1589 Register scratch = temps.Acquire(); 1590 ma_and(scratch, lhs, rhs); 1591 ma_b(scratch, scratch, label, cond); 1592 } 1593 1594 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, ImmWord rhs, 1595 Label* label) { 1596 MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || 1597 cond == NotSigned); 1598 UseScratchRegisterScope temps(asMasm()); 1599 Register scratch = temps.Acquire(); 1600 ma_li(scratch, rhs); 1601 as_and(scratch, lhs, scratch); 1602 ma_b(scratch, scratch, label, cond); 1603 } 1604 1605 void MacroAssembler::branchTestPtr(Condition cond, const Address& lhs, 1606 Imm32 rhs, Label* label) { 1607 UseScratchRegisterScope temps(asMasm()); 1608 Register scratch = temps.Acquire(); 1609 loadPtr(lhs, scratch); 1610 branchTestPtr(cond, scratch, rhs, label); 1611 } 1612 1613 void MacroAssembler::branchTest64(Condition cond, Register64 lhs, 1614 Register64 rhs, Register temp, Label* success, 1615 Label* fail) { 1616 branchTestPtr(cond, lhs.reg, rhs.reg, success); 1617 if (fail) { 1618 jump(fail); 1619 } 1620 } 1621 1622 void MacroAssembler::branchTest64(Condition cond, Register64 lhs, Imm64 rhs, 1623 Label* success, Label* fail) { 1624 branchTestPtr(cond, lhs.reg, ImmWord(rhs.value), success); 1625 if (fail) { 1626 jump(fail); 1627 } 1628 } 1629 1630 void MacroAssembler::branchTestUndefined(Condition cond, Register tag, 1631 Label* label) { 1632 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1633 ma_b(tag, ImmTag(JSVAL_TAG_UNDEFINED), label, cond); 1634 } 1635 1636 void MacroAssembler::branchTestUndefined(Condition cond, 1637 const ValueOperand& value, 1638 Label* label) { 1639 UseScratchRegisterScope temps(*this); 1640 Register scratch = temps.Acquire(); 1641 splitTag(value, scratch); 1642 branchTestUndefined(cond, scratch, label); 1643 } 1644 1645 void MacroAssembler::branchTestUndefined(Condition cond, const Address& address, 1646 Label* label) { 1647 UseScratchRegisterScope temps(*this); 1648 Register scratch = temps.Acquire(); 1649 Register tag = extractTag(address, scratch); 1650 branchTestUndefined(cond, tag, label); 1651 } 1652 1653 void MacroAssembler::branchTestUndefined(Condition cond, 1654 const BaseIndex& address, 1655 Label* label) { 1656 UseScratchRegisterScope temps(*this); 1657 Register scratch = temps.Acquire(); 1658 Register tag = extractTag(address, scratch); 1659 branchTestUndefined(cond, tag, label); 1660 } 1661 1662 void MacroAssembler::branchTestInt32(Condition cond, Register tag, 1663 Label* label) { 1664 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1665 ma_b(tag, ImmTag(JSVAL_TAG_INT32), label, cond); 1666 } 1667 1668 void MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value, 1669 Label* label) { 1670 UseScratchRegisterScope temps(*this); 1671 Register scratch = temps.Acquire(); 1672 splitTag(value, scratch); 1673 branchTestInt32(cond, scratch, label); 1674 } 1675 1676 void MacroAssembler::branchTestInt32(Condition cond, const Address& address, 1677 Label* label) { 1678 UseScratchRegisterScope temps(*this); 1679 Register scratch = temps.Acquire(); 1680 Register tag = extractTag(address, scratch); 1681 branchTestInt32(cond, tag, label); 1682 } 1683 1684 void MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address, 1685 Label* label) { 1686 UseScratchRegisterScope temps(*this); 1687 Register scratch = temps.Acquire(); 1688 Register tag = extractTag(address, scratch); 1689 branchTestInt32(cond, tag, label); 1690 } 1691 1692 void MacroAssembler::branchTestInt32Truthy(bool b, const ValueOperand& value, 1693 Label* label) { 1694 UseScratchRegisterScope temps(*this); 1695 Register scratch = temps.Acquire(); 1696 as_bstrpick_d(scratch, value.valueReg(), 31, 0); 1697 ma_b(scratch, scratch, label, b ? NonZero : Zero); 1698 } 1699 1700 void MacroAssembler::branchTestDouble(Condition cond, Register tag, 1701 Label* label) { 1702 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1703 Condition actual = (cond == Equal) ? BelowOrEqual : Above; 1704 ma_b(tag, ImmTag(JSVAL_TAG_MAX_DOUBLE), label, actual); 1705 } 1706 1707 void MacroAssembler::branchTestDouble(Condition cond, const ValueOperand& value, 1708 Label* label) { 1709 UseScratchRegisterScope temps(*this); 1710 Register scratch = temps.Acquire(); 1711 splitTag(value, scratch); 1712 branchTestDouble(cond, scratch, label); 1713 } 1714 1715 void MacroAssembler::branchTestDouble(Condition cond, const Address& address, 1716 Label* label) { 1717 UseScratchRegisterScope temps(*this); 1718 Register scratch = temps.Acquire(); 1719 Register tag = extractTag(address, scratch); 1720 branchTestDouble(cond, tag, label); 1721 } 1722 1723 void MacroAssembler::branchTestDouble(Condition cond, const BaseIndex& address, 1724 Label* label) { 1725 UseScratchRegisterScope temps(*this); 1726 Register scratch = temps.Acquire(); 1727 Register tag = extractTag(address, scratch); 1728 branchTestDouble(cond, tag, label); 1729 } 1730 1731 void MacroAssembler::branchTestDoubleTruthy(bool b, FloatRegister value, 1732 Label* label) { 1733 ScratchDoubleScope fpscratch(*this); 1734 ma_lid(fpscratch, 0.0); 1735 DoubleCondition cond = b ? DoubleNotEqual : DoubleEqualOrUnordered; 1736 ma_bc_d(value, fpscratch, label, cond); 1737 } 1738 1739 void MacroAssembler::branchTestNumber(Condition cond, Register tag, 1740 Label* label) { 1741 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1742 Condition actual = cond == Equal ? BelowOrEqual : Above; 1743 ma_b(tag, ImmTag(JS::detail::ValueUpperInclNumberTag), label, actual); 1744 } 1745 1746 void MacroAssembler::branchTestNumber(Condition cond, const ValueOperand& value, 1747 Label* label) { 1748 UseScratchRegisterScope temps(*this); 1749 Register scratch = temps.Acquire(); 1750 splitTag(value, scratch); 1751 branchTestNumber(cond, scratch, label); 1752 } 1753 1754 void MacroAssembler::branchTestBoolean(Condition cond, Register tag, 1755 Label* label) { 1756 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1757 ma_b(tag, ImmTag(JSVAL_TAG_BOOLEAN), label, cond); 1758 } 1759 1760 void MacroAssembler::branchTestBoolean(Condition cond, 1761 const ValueOperand& value, 1762 Label* label) { 1763 UseScratchRegisterScope temps(*this); 1764 Register scratch = temps.Acquire(); 1765 splitTag(value, scratch); 1766 branchTestBoolean(cond, scratch, label); 1767 } 1768 1769 void MacroAssembler::branchTestBoolean(Condition cond, const Address& address, 1770 Label* label) { 1771 UseScratchRegisterScope temps(*this); 1772 Register scratch = temps.Acquire(); 1773 Register tag = extractTag(address, scratch); 1774 branchTestBoolean(cond, tag, label); 1775 } 1776 1777 void MacroAssembler::branchTestBoolean(Condition cond, const BaseIndex& address, 1778 Label* label) { 1779 UseScratchRegisterScope temps(*this); 1780 Register scratch = temps.Acquire(); 1781 Register tag = extractTag(address, scratch); 1782 branchTestBoolean(cond, tag, label); 1783 } 1784 1785 void MacroAssembler::branchTestBooleanTruthy(bool b, const ValueOperand& value, 1786 Label* label) { 1787 UseScratchRegisterScope temps(*this); 1788 Register scratch = temps.Acquire(); 1789 unboxBoolean(value, scratch); 1790 ma_b(scratch, scratch, label, b ? NonZero : Zero); 1791 } 1792 1793 void MacroAssembler::branchTestString(Condition cond, Register tag, 1794 Label* label) { 1795 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1796 ma_b(tag, ImmTag(JSVAL_TAG_STRING), label, cond); 1797 } 1798 1799 void MacroAssembler::branchTestString(Condition cond, const ValueOperand& value, 1800 Label* label) { 1801 UseScratchRegisterScope temps(*this); 1802 Register scratch = temps.Acquire(); 1803 splitTag(value, scratch); 1804 branchTestString(cond, scratch, label); 1805 } 1806 1807 void MacroAssembler::branchTestString(Condition cond, const Address& address, 1808 Label* label) { 1809 UseScratchRegisterScope temps(*this); 1810 Register scratch = temps.Acquire(); 1811 Register tag = extractTag(address, scratch); 1812 branchTestString(cond, tag, label); 1813 } 1814 1815 void MacroAssembler::branchTestString(Condition cond, const BaseIndex& address, 1816 Label* label) { 1817 UseScratchRegisterScope temps(*this); 1818 Register scratch = temps.Acquire(); 1819 Register tag = extractTag(address, scratch); 1820 branchTestString(cond, tag, label); 1821 } 1822 1823 void MacroAssembler::branchTestStringTruthy(bool b, const ValueOperand& value, 1824 Label* label) { 1825 UseScratchRegisterScope temps(*this); 1826 Register scratch = temps.Acquire(); 1827 unboxString(value, scratch); 1828 load32(Address(scratch, JSString::offsetOfLength()), scratch); 1829 ma_b(scratch, Imm32(0), label, b ? NotEqual : Equal); 1830 } 1831 1832 void MacroAssembler::branchTestSymbol(Condition cond, Register tag, 1833 Label* label) { 1834 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1835 ma_b(tag, ImmTag(JSVAL_TAG_SYMBOL), label, cond); 1836 } 1837 1838 void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value, 1839 Label* label) { 1840 UseScratchRegisterScope temps(*this); 1841 Register scratch = temps.Acquire(); 1842 splitTag(value, scratch); 1843 branchTestSymbol(cond, scratch, label); 1844 } 1845 1846 void MacroAssembler::branchTestSymbol(Condition cond, const BaseIndex& address, 1847 Label* label) { 1848 UseScratchRegisterScope temps(*this); 1849 Register scratch = temps.Acquire(); 1850 Register tag = extractTag(address, scratch); 1851 branchTestSymbol(cond, tag, label); 1852 } 1853 1854 void MacroAssembler::branchTestSymbol(Condition cond, const Address& address, 1855 Label* label) { 1856 UseScratchRegisterScope temps(*this); 1857 Register scratch = temps.Acquire(); 1858 Register tag = extractTag(address, scratch); 1859 branchTestSymbol(cond, tag, label); 1860 } 1861 1862 void MacroAssembler::branchTestBigInt(Condition cond, Register tag, 1863 Label* label) { 1864 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1865 ma_b(tag, ImmTag(JSVAL_TAG_BIGINT), label, cond); 1866 } 1867 1868 void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value, 1869 Label* label) { 1870 UseScratchRegisterScope temps(*this); 1871 Register scratch = temps.Acquire(); 1872 splitTag(value, scratch); 1873 branchTestBigInt(cond, scratch, label); 1874 } 1875 1876 void MacroAssembler::branchTestBigInt(Condition cond, const Address& address, 1877 Label* label) { 1878 UseScratchRegisterScope temps(*this); 1879 Register scratch = temps.Acquire(); 1880 Register tag = extractTag(address, scratch); 1881 branchTestBigInt(cond, tag, label); 1882 } 1883 1884 void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address, 1885 Label* label) { 1886 UseScratchRegisterScope temps(*this); 1887 Register scratch = temps.Acquire(); 1888 computeEffectiveAddress(address, scratch); 1889 splitTag(scratch, scratch); 1890 branchTestBigInt(cond, scratch, label); 1891 } 1892 1893 void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value, 1894 Label* label) { 1895 UseScratchRegisterScope temps(*this); 1896 Register scratch = temps.Acquire(); 1897 unboxBigInt(value, scratch); 1898 load32(Address(scratch, BigInt::offsetOfDigitLength()), scratch); 1899 ma_b(scratch, Imm32(0), label, b ? NotEqual : Equal); 1900 } 1901 1902 void MacroAssembler::branchTestNull(Condition cond, Register tag, 1903 Label* label) { 1904 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1905 ma_b(tag, ImmTag(JSVAL_TAG_NULL), label, cond); 1906 } 1907 1908 void MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value, 1909 Label* label) { 1910 UseScratchRegisterScope temps(*this); 1911 Register scratch = temps.Acquire(); 1912 splitTag(value, scratch); 1913 branchTestNull(cond, scratch, label); 1914 } 1915 1916 void MacroAssembler::branchTestNull(Condition cond, const Address& address, 1917 Label* label) { 1918 UseScratchRegisterScope temps(*this); 1919 Register scratch = temps.Acquire(); 1920 Register tag = extractTag(address, scratch); 1921 branchTestNull(cond, tag, label); 1922 } 1923 1924 void MacroAssembler::branchTestNull(Condition cond, const BaseIndex& address, 1925 Label* label) { 1926 UseScratchRegisterScope temps(*this); 1927 Register scratch = temps.Acquire(); 1928 Register tag = extractTag(address, scratch); 1929 branchTestNull(cond, tag, label); 1930 } 1931 1932 void MacroAssembler::branchTestObject(Condition cond, Register tag, 1933 Label* label) { 1934 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1935 ma_b(tag, ImmTag(JSVAL_TAG_OBJECT), label, cond); 1936 } 1937 1938 void MacroAssembler::branchTestObject(Condition cond, const ValueOperand& value, 1939 Label* label) { 1940 UseScratchRegisterScope temps(*this); 1941 Register scratch = temps.Acquire(); 1942 splitTag(value, scratch); 1943 branchTestObject(cond, scratch, label); 1944 } 1945 1946 void MacroAssembler::branchTestObject(Condition cond, const Address& address, 1947 Label* label) { 1948 UseScratchRegisterScope temps(*this); 1949 Register scratch = temps.Acquire(); 1950 Register tag = extractTag(address, scratch); 1951 branchTestObject(cond, tag, label); 1952 } 1953 1954 void MacroAssembler::branchTestObject(Condition cond, const BaseIndex& address, 1955 Label* label) { 1956 UseScratchRegisterScope temps(*this); 1957 Register scratch = temps.Acquire(); 1958 Register tag = extractTag(address, scratch); 1959 branchTestObject(cond, tag, label); 1960 } 1961 1962 void MacroAssembler::branchTestPrimitive(Condition cond, 1963 const ValueOperand& value, 1964 Label* label) { 1965 UseScratchRegisterScope temps(*this); 1966 Register scratch = temps.Acquire(); 1967 splitTag(value, scratch); 1968 branchTestPrimitive(cond, scratch, label); 1969 } 1970 1971 void MacroAssembler::branchTestGCThing(Condition cond, const Address& address, 1972 Label* label) { 1973 branchTestGCThingImpl(cond, address, label); 1974 } 1975 1976 void MacroAssembler::branchTestGCThing(Condition cond, const BaseIndex& address, 1977 Label* label) { 1978 branchTestGCThingImpl(cond, address, label); 1979 } 1980 1981 void MacroAssembler::branchTestGCThing(Condition cond, 1982 const ValueOperand& address, 1983 Label* label) { 1984 branchTestGCThingImpl(cond, address, label); 1985 } 1986 1987 template <typename T> 1988 void MacroAssembler::branchTestGCThingImpl(Condition cond, const T& address, 1989 Label* label) { 1990 MOZ_ASSERT(cond == Equal || cond == NotEqual); 1991 UseScratchRegisterScope temps(*this); 1992 Register scratch = temps.Acquire(); 1993 Register tag = extractTag(address, scratch); 1994 ma_b(tag, ImmTag(JS::detail::ValueLowerInclGCThingTag), label, 1995 (cond == Equal) ? AboveOrEqual : Below); 1996 } 1997 1998 void MacroAssembler::branchTestPrimitive(Condition cond, Register tag, 1999 Label* label) { 2000 MOZ_ASSERT(cond == Equal || cond == NotEqual); 2001 ma_b(tag, ImmTag(JS::detail::ValueUpperExclPrimitiveTag), label, 2002 (cond == Equal) ? Below : AboveOrEqual); 2003 } 2004 2005 void MacroAssembler::branchTestMagic(Condition cond, Register tag, 2006 Label* label) { 2007 MOZ_ASSERT(cond == Equal || cond == NotEqual); 2008 ma_b(tag, ImmTag(JSVAL_TAG_MAGIC), label, cond); 2009 } 2010 2011 void MacroAssembler::branchTestMagic(Condition cond, const Address& address, 2012 Label* label) { 2013 UseScratchRegisterScope temps(*this); 2014 Register scratch = temps.Acquire(); 2015 Register tag = extractTag(address, scratch); 2016 branchTestMagic(cond, tag, label); 2017 } 2018 2019 void MacroAssembler::branchTestMagic(Condition cond, const BaseIndex& address, 2020 Label* label) { 2021 UseScratchRegisterScope temps(*this); 2022 Register scratch = temps.Acquire(); 2023 Register tag = extractTag(address, scratch); 2024 branchTestMagic(cond, tag, label); 2025 } 2026 2027 void MacroAssembler::branchTestMagic(Condition cond, const ValueOperand& value, 2028 Label* label) { 2029 UseScratchRegisterScope temps(*this); 2030 Register scratch = temps.Acquire(); 2031 splitTag(value, scratch); 2032 ma_b(scratch, ImmTag(JSVAL_TAG_MAGIC), label, cond); 2033 } 2034 2035 void MacroAssembler::branchTestMagic(Condition cond, const Address& valaddr, 2036 JSWhyMagic why, Label* label) { 2037 uint64_t magic = MagicValue(why).asRawBits(); 2038 UseScratchRegisterScope temp(*this); 2039 Register scratch = temp.Acquire(); 2040 loadPtr(valaddr, scratch); 2041 ma_b(scratch, ImmWord(magic), label, cond); 2042 } 2043 2044 template <typename T> 2045 void MacroAssembler::branchTestValue(Condition cond, const T& lhs, 2046 const ValueOperand& rhs, Label* label) { 2047 MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); 2048 branchPtr(cond, lhs, rhs.valueReg(), label); 2049 } 2050 2051 template <typename T> 2052 void MacroAssembler::testNumberSet(Condition cond, const T& src, 2053 Register dest) { 2054 MOZ_ASSERT(cond == Equal || cond == NotEqual); 2055 UseScratchRegisterScope temps(*this); 2056 Register scratch = temps.Acquire(); 2057 Register tag = extractTag(src, scratch); 2058 ma_cmp_set(dest, tag, ImmTag(JS::detail::ValueUpperInclNumberTag), 2059 cond == Equal ? BelowOrEqual : Above); 2060 } 2061 2062 template <typename T> 2063 void MacroAssembler::testBooleanSet(Condition cond, const T& src, 2064 Register dest) { 2065 MOZ_ASSERT(cond == Equal || cond == NotEqual); 2066 UseScratchRegisterScope temps(*this); 2067 Register scratch = temps.Acquire(); 2068 Register tag = extractTag(src, scratch); 2069 ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_BOOLEAN), cond); 2070 } 2071 2072 template <typename T> 2073 void MacroAssembler::testStringSet(Condition cond, const T& src, 2074 Register dest) { 2075 MOZ_ASSERT(cond == Equal || cond == NotEqual); 2076 UseScratchRegisterScope temps(*this); 2077 Register scratch = temps.Acquire(); 2078 Register tag = extractTag(src, scratch); 2079 ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_STRING), cond); 2080 } 2081 2082 template <typename T> 2083 void MacroAssembler::testSymbolSet(Condition cond, const T& src, 2084 Register dest) { 2085 MOZ_ASSERT(cond == Equal || cond == NotEqual); 2086 UseScratchRegisterScope temps(*this); 2087 Register scratch = temps.Acquire(); 2088 Register tag = extractTag(src, scratch); 2089 ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_SYMBOL), cond); 2090 } 2091 2092 template <typename T> 2093 void MacroAssembler::testBigIntSet(Condition cond, const T& src, 2094 Register dest) { 2095 MOZ_ASSERT(cond == Equal || cond == NotEqual); 2096 UseScratchRegisterScope temps(*this); 2097 Register scratch = temps.Acquire(); 2098 Register tag = extractTag(src, scratch); 2099 ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_BIGINT), cond); 2100 } 2101 2102 void MacroAssembler::branchToComputedAddress(const BaseIndex& addr) { 2103 UseScratchRegisterScope temps(asMasm()); 2104 Register scratch = temps.Acquire(); 2105 loadPtr(addr, scratch); 2106 branch(scratch); 2107 } 2108 2109 void MacroAssembler::cmp32Move32(Condition cond, Register lhs, Imm32 rhs, 2110 Register src, Register dest) { 2111 UseScratchRegisterScope temps(asMasm()); 2112 Register scratch = temps.Acquire(); 2113 cmp32Set(cond, lhs, rhs, scratch); 2114 moveIfNotZero(dest, src, scratch); 2115 } 2116 2117 void MacroAssembler::cmp32Move32(Condition cond, Register lhs, Register rhs, 2118 Register src, Register dest) { 2119 UseScratchRegisterScope temps(asMasm()); 2120 Register scratch = temps.Acquire(); 2121 cmp32Set(cond, lhs, rhs, scratch); 2122 moveIfNotZero(dest, src, scratch); 2123 } 2124 2125 void MacroAssembler::cmp32Move32(Condition cond, Register lhs, 2126 const Address& rhs, Register src, 2127 Register dest) { 2128 UseScratchRegisterScope temps(*this); 2129 Register scratch = temps.Acquire(); 2130 MOZ_ASSERT(lhs != scratch && src != scratch && dest != scratch); 2131 load32(rhs, scratch); 2132 cmp32Move32(cond, lhs, scratch, src, dest); 2133 } 2134 2135 void MacroAssembler::cmp32MovePtr(Condition cond, Register lhs, Imm32 rhs, 2136 Register src, Register dest) { 2137 UseScratchRegisterScope temps(asMasm()); 2138 Register scratch = temps.Acquire(); 2139 cmp32Set(cond, lhs, rhs, scratch); 2140 moveIfNotZero(dest, src, scratch); 2141 } 2142 2143 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, Imm32 rhs, 2144 Register src, Register dest) { 2145 UseScratchRegisterScope temps(asMasm()); 2146 Register scratch = temps.Acquire(); 2147 cmpPtrSet(cond, lhs, rhs, scratch); 2148 moveIfNotZero(dest, src, scratch); 2149 } 2150 2151 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, Register rhs, 2152 Register src, Register dest) { 2153 UseScratchRegisterScope temps(asMasm()); 2154 Register scratch = temps.Acquire(); 2155 cmpPtrSet(cond, lhs, rhs, scratch); 2156 moveIfNotZero(dest, src, scratch); 2157 } 2158 2159 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, 2160 const Address& rhs, Register src, 2161 Register dest) { 2162 MOZ_CRASH("NYI"); 2163 } 2164 2165 void MacroAssembler::cmp32Load32(Condition cond, Register lhs, 2166 const Address& rhs, const Address& src, 2167 Register dest) { 2168 UseScratchRegisterScope temps(*this); 2169 Register scratch = temps.Acquire(); 2170 MOZ_ASSERT(lhs != scratch && dest != scratch); 2171 load32(rhs, scratch); 2172 cmp32Load32(cond, lhs, scratch, src, dest); 2173 } 2174 2175 void MacroAssembler::cmp32Load32(Condition cond, Register lhs, Register rhs, 2176 const Address& src, Register dest) { 2177 Label skip; 2178 branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip); 2179 load32(src, dest); 2180 bind(&skip); 2181 } 2182 2183 void MacroAssembler::cmp32Load32(Condition cond, Register lhs, Imm32 rhs, 2184 const Address& src, Register dest) { 2185 Label skip; 2186 branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip); 2187 load32(src, dest); 2188 bind(&skip); 2189 } 2190 2191 void MacroAssembler::cmp32LoadPtr(Condition cond, const Address& lhs, Imm32 rhs, 2192 const Address& src, Register dest) { 2193 Label skip; 2194 branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip); 2195 loadPtr(src, dest); 2196 bind(&skip); 2197 } 2198 2199 void MacroAssembler::test32LoadPtr(Condition cond, const Address& addr, 2200 Imm32 mask, const Address& src, 2201 Register dest) { 2202 MOZ_RELEASE_ASSERT(!JitOptions.spectreStringMitigations); 2203 Label skip; 2204 branchTest32(Assembler::InvertCondition(cond), addr, mask, &skip); 2205 loadPtr(src, dest); 2206 bind(&skip); 2207 } 2208 2209 void MacroAssembler::test32MovePtr(Condition cond, Register operand, Imm32 mask, 2210 Register src, Register dest) { 2211 MOZ_ASSERT(cond == Assembler::Zero || cond == Assembler::NonZero); 2212 Label skip; 2213 branchTest32(Assembler::InvertCondition(cond), operand, mask, &skip); 2214 movePtr(src, dest); 2215 bind(&skip); 2216 } 2217 2218 void MacroAssembler::test32MovePtr(Condition cond, const Address& addr, 2219 Imm32 mask, Register src, Register dest) { 2220 MOZ_ASSERT(cond == Assembler::Zero || cond == Assembler::NonZero); 2221 Label skip; 2222 branchTest32(Assembler::InvertCondition(cond), addr, mask, &skip); 2223 movePtr(src, dest); 2224 bind(&skip); 2225 } 2226 2227 void MacroAssembler::spectreMovePtr(Condition cond, Register src, 2228 Register dest) { 2229 MOZ_CRASH(); 2230 } 2231 2232 void MacroAssembler::spectreZeroRegister(Condition cond, Register scratch, 2233 Register dest) { 2234 MOZ_CRASH(); 2235 } 2236 2237 void MacroAssembler::spectreBoundsCheck32(Register index, Register length, 2238 Register maybeScratch, 2239 Label* failure) { 2240 MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking); 2241 branch32(Assembler::BelowOrEqual, length, index, failure); 2242 } 2243 2244 void MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, 2245 Register maybeScratch, 2246 Label* failure) { 2247 MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking); 2248 branch32(Assembler::BelowOrEqual, length, index, failure); 2249 } 2250 2251 void MacroAssembler::spectreBoundsCheckPtr(Register index, Register length, 2252 Register maybeScratch, 2253 Label* failure) { 2254 MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking); 2255 branchPtr(Assembler::BelowOrEqual, length, index, failure); 2256 } 2257 2258 void MacroAssembler::spectreBoundsCheckPtr(Register index, 2259 const Address& length, 2260 Register maybeScratch, 2261 Label* failure) { 2262 MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking); 2263 branchPtr(Assembler::BelowOrEqual, length, index, failure); 2264 } 2265 2266 // ======================================================================== 2267 // Memory access primitives. 2268 2269 FaultingCodeOffset MacroAssembler::storeFloat32(FloatRegister src, 2270 const Address& addr) { 2271 return ma_fst_s(src, addr); 2272 } 2273 FaultingCodeOffset MacroAssembler::storeFloat32(FloatRegister src, 2274 const BaseIndex& addr) { 2275 return ma_fst_s(src, addr); 2276 } 2277 2278 FaultingCodeOffset MacroAssembler::storeDouble(FloatRegister src, 2279 const Address& addr) { 2280 return ma_fst_d(src, addr); 2281 } 2282 FaultingCodeOffset MacroAssembler::storeDouble(FloatRegister src, 2283 const BaseIndex& addr) { 2284 return ma_fst_d(src, addr); 2285 } 2286 2287 FaultingCodeOffset MacroAssembler::storeFloat16(FloatRegister src, 2288 const Address& dest, Register) { 2289 MOZ_CRASH("Not supported for this target"); 2290 } 2291 FaultingCodeOffset MacroAssembler::storeFloat16(FloatRegister src, 2292 const BaseIndex& dest, 2293 Register) { 2294 MOZ_CRASH("Not supported for this target"); 2295 } 2296 2297 void MacroAssembler::memoryBarrier(MemoryBarrier barrier) { 2298 if (!barrier.isNone()) { 2299 as_dbar(0); 2300 } 2301 } 2302 2303 // =============================================================== 2304 // Clamping functions. 2305 2306 void MacroAssembler::clampIntToUint8(Register reg) { 2307 UseScratchRegisterScope temps(*this); 2308 Register scratch = temps.Acquire(); 2309 // If reg is < 0, then we want to clamp to 0. 2310 as_slti(scratch, reg, 0); 2311 as_masknez(reg, reg, scratch); 2312 2313 // If reg is >= 255, then we want to clamp to 255. 2314 as_addi_d(reg, reg, -255); 2315 as_slt(scratch, reg, zero); 2316 as_maskeqz(reg, reg, scratch); 2317 as_addi_d(reg, reg, 255); 2318 } 2319 2320 void MacroAssembler::fallibleUnboxPtr(const ValueOperand& src, Register dest, 2321 JSValueType type, Label* fail) { 2322 MOZ_ASSERT(type == JSVAL_TYPE_OBJECT || type == JSVAL_TYPE_STRING || 2323 type == JSVAL_TYPE_SYMBOL || type == JSVAL_TYPE_BIGINT); 2324 // dest := src XOR mask 2325 // scratch := dest >> JSVAL_TAG_SHIFT 2326 // fail if scratch != 0 2327 // 2328 // Note: src and dest can be the same register 2329 UseScratchRegisterScope temps(asMasm()); 2330 Register scratch = temps.Acquire(); 2331 MOZ_ASSERT(src.valueReg() != scratch); 2332 mov(ImmShiftedTag(type), scratch); 2333 as_xor(dest, src.valueReg(), scratch); 2334 as_srli_d(scratch, dest, JSVAL_TAG_SHIFT); 2335 ma_b(scratch, Imm32(0), fail, Assembler::NotEqual); 2336 } 2337 2338 void MacroAssembler::fallibleUnboxPtr(const Address& src, Register dest, 2339 JSValueType type, Label* fail) { 2340 loadValue(src, ValueOperand(dest)); 2341 fallibleUnboxPtr(ValueOperand(dest), dest, type, fail); 2342 } 2343 2344 void MacroAssembler::fallibleUnboxPtr(const BaseIndex& src, Register dest, 2345 JSValueType type, Label* fail) { 2346 loadValue(src, ValueOperand(dest)); 2347 fallibleUnboxPtr(ValueOperand(dest), dest, type, fail); 2348 } 2349 2350 //}}} check_macroassembler_style 2351 // =============================================================== 2352 2353 // The specializations for cmpPtrSet are outside the braces because 2354 // check_macroassembler_style can't yet deal with specializations. 2355 2356 template <> 2357 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs, 2358 ImmPtr rhs, Register dest) { 2359 UseScratchRegisterScope temps(asMasm()); 2360 Register scratch = temps.Acquire(); 2361 loadPtr(lhs, scratch); 2362 cmpPtrSet(cond, Register(scratch), rhs, dest); 2363 } 2364 2365 template <> 2366 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Register lhs, 2367 Address rhs, Register dest) { 2368 UseScratchRegisterScope temps(asMasm()); 2369 Register scratch = temps.Acquire(); 2370 MOZ_ASSERT(lhs != scratch); 2371 loadPtr(rhs, scratch); 2372 cmpPtrSet(cond, lhs, Register(scratch), dest); 2373 } 2374 2375 template <> 2376 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs, 2377 Register rhs, Register dest) { 2378 UseScratchRegisterScope temps(asMasm()); 2379 Register scratch = temps.Acquire(); 2380 MOZ_ASSERT(rhs != scratch); 2381 loadPtr(lhs, scratch); 2382 cmpPtrSet(cond, Register(scratch), rhs, dest); 2383 } 2384 2385 template <> 2386 inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Register lhs, 2387 Address rhs, Register dest) { 2388 UseScratchRegisterScope temps(asMasm()); 2389 Register scratch = temps.Acquire(); 2390 MOZ_ASSERT(lhs != scratch); 2391 load32(rhs, scratch); 2392 cmp32Set(cond, lhs, Register(scratch), dest); 2393 } 2394 2395 template <> 2396 inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Address lhs, 2397 Register rhs, Register dest) { 2398 UseScratchRegisterScope temps(asMasm()); 2399 Register scratch = temps.Acquire(); 2400 MOZ_ASSERT(rhs != scratch); 2401 load32(lhs, scratch); 2402 cmp32Set(cond, Register(scratch), rhs, dest); 2403 } 2404 2405 void MacroAssemblerLOONG64Compat::incrementInt32Value(const Address& addr) { 2406 asMasm().add32(Imm32(1), addr); 2407 } 2408 2409 void MacroAssemblerLOONG64Compat::retn(Imm32 n) { 2410 // pc <- [sp]; sp += n 2411 loadPtr(Address(StackPointer, 0), ra); 2412 asMasm().addPtr(n, StackPointer); 2413 as_jirl(zero, ra, BOffImm16(0)); 2414 } 2415 2416 } // namespace jit 2417 } // namespace js 2418 2419 #endif /* jit_loong64_MacroAssembler_loong64_inl_h */