tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */