tor-browser

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

MacroAssembler-mips-shared-inl.h (50252B)


      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_mips_shared_MacroAssembler_mips_shared_inl_h
      8 #define jit_mips_shared_MacroAssembler_mips_shared_inl_h
      9 
     10 #include "jit/mips-shared/MacroAssembler-mips-shared.h"
     11 
     12 namespace js {
     13 namespace jit {
     14 
     15 //{{{ check_macroassembler_style
     16 
     17 void MacroAssembler::moveFloat16ToGPR(FloatRegister src, Register dest) {
     18  MOZ_CRASH("Not supported for this target");
     19 }
     20 
     21 void MacroAssembler::moveGPRToFloat16(Register src, FloatRegister dest) {
     22  MOZ_CRASH("Not supported for this target");
     23 }
     24 
     25 void MacroAssembler::moveFloat32ToGPR(FloatRegister src, Register dest) {
     26  moveFromFloat32(src, dest);
     27 }
     28 
     29 void MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest) {
     30  moveToFloat32(src, dest);
     31 }
     32 
     33 void MacroAssembler::moveLowDoubleToGPR(FloatRegister src, Register dest) {
     34  MOZ_CRASH("Not supported for this target");
     35 }
     36 
     37 void MacroAssembler::move8ZeroExtend(Register src, Register dest) {
     38  as_andi(dest, src, 0xff);
     39 }
     40 
     41 void MacroAssembler::move8SignExtend(Register src, Register dest) {
     42  ma_seb(dest, src);
     43 }
     44 
     45 void MacroAssembler::move16SignExtend(Register src, Register dest) {
     46  ma_seh(dest, src);
     47 }
     48 
     49 void MacroAssembler::loadAbiReturnAddress(Register dest) { movePtr(ra, dest); }
     50 
     51 // ===============================================================
     52 // Logical instructions
     53 
     54 void MacroAssembler::not32(Register reg) { ma_not(reg, reg); }
     55 
     56 void MacroAssembler::and32(Register src, Register dest) {
     57  as_and(dest, dest, src);
     58 }
     59 
     60 void MacroAssembler::and32(Imm32 imm, Register dest) { ma_and(dest, imm); }
     61 
     62 void MacroAssembler::and32(Imm32 imm, Register src, Register dest) {
     63  ma_and(dest, src, imm);
     64 }
     65 
     66 void MacroAssembler::and32(Imm32 imm, const Address& dest) {
     67  UseScratchRegisterScope temps(*this);
     68  Register scratch2 = temps.Acquire();
     69  load32(dest, scratch2);
     70  ma_and(scratch2, imm);
     71  store32(scratch2, dest);
     72 }
     73 
     74 void MacroAssembler::and32(const Address& src, Register dest) {
     75  UseScratchRegisterScope temps(*this);
     76  Register scratch2 = temps.Acquire();
     77  load32(src, scratch2);
     78  ma_and(dest, scratch2);
     79 }
     80 
     81 void MacroAssembler::or32(Register src, Register dest) { ma_or(dest, src); }
     82 
     83 void MacroAssembler::or32(Imm32 imm, Register dest) { ma_or(dest, imm); }
     84 
     85 void MacroAssembler::or32(Imm32 imm, Register src, Register dest) {
     86  ma_or(dest, src, imm);
     87 }
     88 
     89 void MacroAssembler::or32(Imm32 imm, const Address& dest) {
     90  UseScratchRegisterScope temps(*this);
     91  Register scratch2 = temps.Acquire();
     92  load32(dest, scratch2);
     93  ma_or(scratch2, imm);
     94  store32(scratch2, dest);
     95 }
     96 
     97 void MacroAssembler::xor32(Register src, Register dest) { ma_xor(dest, src); }
     98 
     99 void MacroAssembler::xor32(Imm32 imm, Register dest) { ma_xor(dest, imm); }
    100 
    101 void MacroAssembler::xor32(Imm32 imm, Register src, Register dest) {
    102  ma_xor(dest, src, imm);
    103 }
    104 
    105 void MacroAssembler::xor32(Imm32 imm, const Address& dest) {
    106  UseScratchRegisterScope temps(*this);
    107  Register scratch2 = temps.Acquire();
    108  load32(dest, scratch2);
    109  ma_xor(scratch2, imm);
    110  store32(scratch2, dest);
    111 }
    112 
    113 void MacroAssembler::xor32(const Address& src, Register dest) {
    114  UseScratchRegisterScope temps(*this);
    115  Register scratch2 = temps.Acquire();
    116  load32(src, scratch2);
    117  ma_xor(dest, scratch2);
    118 }
    119 
    120 // ===============================================================
    121 // Swap instructions
    122 
    123 void MacroAssembler::byteSwap16SignExtend(Register reg) {
    124  ma_wsbh(reg, reg);
    125  ma_seh(reg, reg);
    126 }
    127 
    128 void MacroAssembler::byteSwap16ZeroExtend(Register reg) {
    129  ma_wsbh(reg, reg);
    130  ma_and(reg, Imm32(0xFFFF));
    131 }
    132 
    133 void MacroAssembler::byteSwap32(Register reg) {
    134  ma_wsbh(reg, reg);
    135  ma_ror(reg, reg, Imm32(16));
    136 }
    137 
    138 // ===============================================================
    139 // Arithmetic instructions
    140 
    141 void MacroAssembler::add32(Register src, Register dest) {
    142  as_addu(dest, dest, src);
    143 }
    144 
    145 void MacroAssembler::add32(Imm32 imm, Register dest) {
    146  ma_addu(dest, dest, imm);
    147 }
    148 
    149 void MacroAssembler::add32(Imm32 imm, Register src, Register dest) {
    150  ma_addu(dest, src, imm);
    151 }
    152 
    153 void MacroAssembler::add32(Imm32 imm, const Address& dest) {
    154  UseScratchRegisterScope temps(*this);
    155  Register scratch2 = temps.Acquire();
    156  load32(dest, scratch2);
    157  ma_addu(scratch2, imm);
    158  store32(scratch2, dest);
    159 }
    160 
    161 void MacroAssembler::add32(const Address& src, Register dest) {
    162  UseScratchRegisterScope temps(*this);
    163  Register scratch2 = temps.Acquire();
    164  load32(src, scratch2);
    165  as_addu(dest, dest, scratch2);
    166 }
    167 
    168 void MacroAssembler::addPtr(Imm32 imm, const Address& dest) {
    169  UseScratchRegisterScope temps(*this);
    170  Register scratch = temps.Acquire();
    171  loadPtr(dest, scratch);
    172  addPtr(imm, scratch);
    173  storePtr(scratch, dest);
    174 }
    175 
    176 void MacroAssembler::addPtr(const Address& src, Register dest) {
    177  UseScratchRegisterScope temps(*this);
    178  Register scratch = temps.Acquire();
    179  loadPtr(src, scratch);
    180  addPtr(scratch, dest);
    181 }
    182 
    183 void MacroAssembler::addDouble(FloatRegister src, FloatRegister dest) {
    184  as_addd(dest, dest, src);
    185 }
    186 
    187 void MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest) {
    188  as_adds(dest, dest, src);
    189 }
    190 
    191 void MacroAssembler::sub32(Register src, Register dest) {
    192  as_subu(dest, dest, src);
    193 }
    194 
    195 void MacroAssembler::sub32(Imm32 imm, Register dest) {
    196  ma_subu(dest, dest, imm);
    197 }
    198 
    199 void MacroAssembler::sub32(const Address& src, Register dest) {
    200  UseScratchRegisterScope temps(*this);
    201  Register scratch2 = temps.Acquire();
    202  load32(src, scratch2);
    203  as_subu(dest, dest, scratch2);
    204 }
    205 
    206 void MacroAssembler::subPtr(Register src, const Address& dest) {
    207  UseScratchRegisterScope temps(*this);
    208  Register scratch2 = temps.Acquire();
    209  loadPtr(dest, scratch2);
    210  subPtr(src, scratch2);
    211  storePtr(scratch2, dest);
    212 }
    213 
    214 void MacroAssembler::subPtr(const Address& addr, Register dest) {
    215  UseScratchRegisterScope temps(*this);
    216  Register scratch2 = temps.Acquire();
    217  loadPtr(addr, scratch2);
    218  subPtr(scratch2, dest);
    219 }
    220 
    221 void MacroAssembler::subDouble(FloatRegister src, FloatRegister dest) {
    222  as_subd(dest, dest, src);
    223 }
    224 
    225 void MacroAssembler::subFloat32(FloatRegister src, FloatRegister dest) {
    226  as_subs(dest, dest, src);
    227 }
    228 
    229 void MacroAssembler::mul32(Register rhs, Register srcDest) {
    230  as_mul(srcDest, srcDest, rhs);
    231 }
    232 
    233 void MacroAssembler::mul32(Imm32 imm, Register srcDest) {
    234  UseScratchRegisterScope temps(*this);
    235  Register scratch2 = temps.Acquire();
    236  move32(imm, scratch2);
    237  mul32(scratch2, srcDest);
    238 }
    239 
    240 void MacroAssembler::mulFloat32(FloatRegister src, FloatRegister dest) {
    241  as_muls(dest, dest, src);
    242 }
    243 
    244 void MacroAssembler::mulDouble(FloatRegister src, FloatRegister dest) {
    245  as_muld(dest, dest, src);
    246 }
    247 
    248 void MacroAssembler::mulDoublePtr(ImmPtr imm, Register temp,
    249                                  FloatRegister dest) {
    250  UseScratchRegisterScope temps(*this);
    251  Register scratch = temps.Acquire();
    252  movePtr(imm, scratch);
    253  loadDouble(Address(scratch, 0), ScratchDoubleReg);
    254  mulDouble(ScratchDoubleReg, dest);
    255 }
    256 
    257 void MacroAssembler::quotient32(Register lhs, Register rhs, Register dest,
    258                                bool isUnsigned) {
    259 #ifdef MIPSR6
    260  if (isUnsigned) {
    261    as_divu(dest, lhs, rhs);
    262  } else {
    263    as_div(dest, lhs, rhs);
    264  }
    265 #else
    266  if (isUnsigned) {
    267    as_divu(lhs, rhs);
    268  } else {
    269    as_div(lhs, rhs);
    270  }
    271  as_mflo(dest);
    272 #endif
    273 }
    274 
    275 void MacroAssembler::remainder32(Register lhs, Register rhs, Register dest,
    276                                 bool isUnsigned) {
    277 #ifdef MIPSR6
    278  if (isUnsigned) {
    279    as_modu(dest, lhs, rhs);
    280  } else {
    281    as_mod(dest, lhs, rhs);
    282  }
    283 #else
    284  if (isUnsigned) {
    285    as_divu(lhs, rhs);
    286  } else {
    287    as_div(lhs, rhs);
    288  }
    289  as_mfhi(dest);
    290 #endif
    291 }
    292 
    293 void MacroAssembler::divFloat32(FloatRegister src, FloatRegister dest) {
    294  as_divs(dest, dest, src);
    295 }
    296 
    297 void MacroAssembler::divDouble(FloatRegister src, FloatRegister dest) {
    298  as_divd(dest, dest, src);
    299 }
    300 
    301 void MacroAssembler::neg32(Register reg) { ma_negu(reg, reg); }
    302 
    303 void MacroAssembler::negateDouble(FloatRegister reg) { as_negd(reg, reg); }
    304 
    305 void MacroAssembler::negateFloat(FloatRegister reg) { as_negs(reg, reg); }
    306 
    307 void MacroAssembler::abs32(Register src, Register dest) {
    308  // TODO: There's probably a better way to do this.
    309  if (src != dest) {
    310    move32(src, dest);
    311  }
    312  Label positive;
    313  branchTest32(Assembler::NotSigned, dest, dest, &positive);
    314  neg32(dest);
    315  bind(&positive);
    316 }
    317 
    318 void MacroAssembler::absFloat32(FloatRegister src, FloatRegister dest) {
    319  as_abss(dest, src);
    320 }
    321 
    322 void MacroAssembler::absDouble(FloatRegister src, FloatRegister dest) {
    323  as_absd(dest, src);
    324 }
    325 
    326 void MacroAssembler::sqrtFloat32(FloatRegister src, FloatRegister dest) {
    327  as_sqrts(dest, src);
    328 }
    329 
    330 void MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest) {
    331  as_sqrtd(dest, src);
    332 }
    333 
    334 void MacroAssembler::min32(Register lhs, Register rhs, Register dest) {
    335  minMax32(lhs, rhs, dest, /* isMax = */ false);
    336 }
    337 
    338 void MacroAssembler::min32(Register lhs, Imm32 rhs, Register dest) {
    339  minMax32(lhs, rhs, dest, /* isMax = */ false);
    340 }
    341 
    342 void MacroAssembler::max32(Register lhs, Register rhs, Register dest) {
    343  minMax32(lhs, rhs, dest, /* isMax = */ true);
    344 }
    345 
    346 void MacroAssembler::max32(Register lhs, Imm32 rhs, Register dest) {
    347  minMax32(lhs, rhs, dest, /* isMax = */ true);
    348 }
    349 
    350 void MacroAssembler::minPtr(Register lhs, Register rhs, Register dest) {
    351  minMaxPtr(lhs, rhs, dest, /* isMax = */ false);
    352 }
    353 
    354 void MacroAssembler::minPtr(Register lhs, ImmWord rhs, Register dest) {
    355  minMaxPtr(lhs, rhs, dest, /* isMax = */ false);
    356 }
    357 
    358 void MacroAssembler::maxPtr(Register lhs, Register rhs, Register dest) {
    359  minMaxPtr(lhs, rhs, dest, /* isMax = */ true);
    360 }
    361 
    362 void MacroAssembler::maxPtr(Register lhs, ImmWord rhs, Register dest) {
    363  minMaxPtr(lhs, rhs, dest, /* isMax = */ true);
    364 }
    365 
    366 void MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest,
    367                                bool handleNaN) {
    368  minMaxFloat32(srcDest, other, handleNaN, false);
    369 }
    370 
    371 void MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest,
    372                               bool handleNaN) {
    373  minMaxDouble(srcDest, other, handleNaN, false);
    374 }
    375 
    376 void MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest,
    377                                bool handleNaN) {
    378  minMaxFloat32(srcDest, other, handleNaN, true);
    379 }
    380 
    381 void MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest,
    382                               bool handleNaN) {
    383  minMaxDouble(srcDest, other, handleNaN, true);
    384 }
    385 
    386 // ===============================================================
    387 // Shift functions
    388 
    389 void MacroAssembler::lshift32(Register src, Register dest) {
    390  ma_sll(dest, dest, src);
    391 }
    392 
    393 void MacroAssembler::flexibleLshift32(Register src, Register dest) {
    394  lshift32(src, dest);
    395 }
    396 
    397 void MacroAssembler::flexibleLshiftPtr(Register shift, Register srcDest) {
    398  lshiftPtr(shift, srcDest);
    399 }
    400 
    401 void MacroAssembler::lshift32(Imm32 imm, Register dest) {
    402  lshift32(imm, dest, dest);
    403 }
    404 
    405 void MacroAssembler::lshift32(Imm32 imm, Register src, Register dest) {
    406  ma_sll(dest, src, imm);
    407 }
    408 
    409 void MacroAssembler::rshift32(Register src, Register dest) {
    410  ma_srl(dest, dest, src);
    411 }
    412 
    413 void MacroAssembler::flexibleRshift32(Register src, Register dest) {
    414  rshift32(src, dest);
    415 }
    416 
    417 void MacroAssembler::rshift32(Imm32 imm, Register dest) {
    418  rshift32(imm, dest, dest);
    419 }
    420 
    421 void MacroAssembler::rshift32(Imm32 imm, Register src, Register dest) {
    422  ma_srl(dest, src, imm);
    423 }
    424 
    425 void MacroAssembler::rshift32Arithmetic(Register src, Register dest) {
    426  ma_sra(dest, dest, src);
    427 }
    428 
    429 void MacroAssembler::flexibleRshift32Arithmetic(Register src, Register dest) {
    430  rshift32Arithmetic(src, dest);
    431 }
    432 
    433 void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register dest) {
    434  rshift32Arithmetic(imm, dest, dest);
    435 }
    436 
    437 void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register src,
    438                                        Register dest) {
    439  ma_sra(dest, src, imm);
    440 }
    441 
    442 void MacroAssembler::flexibleRshiftPtr(Register shift, Register srcDest) {
    443  rshiftPtr(shift, srcDest);
    444 }
    445 
    446 void MacroAssembler::flexibleRshiftPtrArithmetic(Register shift,
    447                                                 Register srcDest) {
    448  rshiftPtrArithmetic(shift, srcDest);
    449 }
    450 
    451 // ===============================================================
    452 // Rotation functions
    453 void MacroAssembler::rotateLeft(Imm32 count, Register input, Register dest) {
    454  if (count.value) {
    455    ma_rol(dest, input, count);
    456  } else {
    457    ma_move(dest, input);
    458  }
    459 }
    460 void MacroAssembler::rotateLeft(Register count, Register input, Register dest) {
    461  ma_rol(dest, input, count);
    462 }
    463 void MacroAssembler::rotateRight(Imm32 count, Register input, Register dest) {
    464  if (count.value) {
    465    ma_ror(dest, input, count);
    466  } else {
    467    ma_move(dest, input);
    468  }
    469 }
    470 void MacroAssembler::rotateRight(Register count, Register input,
    471                                 Register dest) {
    472  ma_ror(dest, input, count);
    473 }
    474 
    475 // ===============================================================
    476 // Bit counting functions
    477 
    478 void MacroAssembler::clz32(Register src, Register dest, bool knownNotZero) {
    479  as_clz(dest, src);
    480 }
    481 
    482 void MacroAssembler::ctz32(Register src, Register dest, bool knownNotZero) {
    483  ma_ctz(dest, src);
    484 }
    485 
    486 void MacroAssembler::popcnt32(Register input, Register output, Register tmp) {
    487  // Equivalent to GCC output of mozilla::CountPopulation32()
    488  ma_move(output, input);
    489  ma_sra(tmp, input, Imm32(1));
    490  ma_and(tmp, Imm32(0x55555555));
    491  ma_subu(output, tmp);
    492  ma_sra(tmp, output, Imm32(2));
    493  ma_and(output, Imm32(0x33333333));
    494  ma_and(tmp, Imm32(0x33333333));
    495  ma_addu(output, tmp);
    496  ma_srl(tmp, output, Imm32(4));
    497  ma_addu(output, tmp);
    498  ma_and(output, Imm32(0xF0F0F0F));
    499  ma_sll(tmp, output, Imm32(8));
    500  ma_addu(output, tmp);
    501  ma_sll(tmp, output, Imm32(16));
    502  ma_addu(output, tmp);
    503  ma_sra(output, output, Imm32(24));
    504 }
    505 
    506 // ===============================================================
    507 // Condition functions
    508 
    509 void MacroAssembler::cmp8Set(Condition cond, Address lhs, Imm32 rhs,
    510                             Register dest) {
    511  UseScratchRegisterScope temps(*this);
    512  Register scratch2 = temps.Acquire();
    513  MOZ_ASSERT(scratch2 != lhs.base);
    514 
    515  switch (cond) {
    516    case Assembler::Equal:
    517    case Assembler::NotEqual:
    518    case Assembler::Above:
    519    case Assembler::AboveOrEqual:
    520    case Assembler::Below:
    521    case Assembler::BelowOrEqual:
    522      load8ZeroExtend(lhs, scratch2);
    523      ma_cmp_set(dest, scratch2, Imm32(uint8_t(rhs.value)), cond);
    524      break;
    525 
    526    case Assembler::GreaterThan:
    527    case Assembler::GreaterThanOrEqual:
    528    case Assembler::LessThan:
    529    case Assembler::LessThanOrEqual:
    530      load8SignExtend(lhs, scratch2);
    531      ma_cmp_set(dest, scratch2, Imm32(int8_t(rhs.value)), cond);
    532      break;
    533 
    534    default:
    535      MOZ_CRASH("unexpected condition");
    536  }
    537 }
    538 
    539 void MacroAssembler::cmp16Set(Condition cond, Address lhs, Imm32 rhs,
    540                              Register dest) {
    541  UseScratchRegisterScope temps(*this);
    542  Register scratch2 = temps.Acquire();
    543  MOZ_ASSERT(scratch2 != lhs.base);
    544 
    545  switch (cond) {
    546    case Assembler::Equal:
    547    case Assembler::NotEqual:
    548    case Assembler::Above:
    549    case Assembler::AboveOrEqual:
    550    case Assembler::Below:
    551    case Assembler::BelowOrEqual:
    552      load16ZeroExtend(lhs, scratch2);
    553      ma_cmp_set(dest, scratch2, Imm32(uint16_t(rhs.value)), cond);
    554      break;
    555 
    556    case Assembler::GreaterThan:
    557    case Assembler::GreaterThanOrEqual:
    558    case Assembler::LessThan:
    559    case Assembler::LessThanOrEqual:
    560      load16SignExtend(lhs, scratch2);
    561      ma_cmp_set(dest, scratch2, Imm32(int16_t(rhs.value)), cond);
    562      break;
    563 
    564    default:
    565      MOZ_CRASH("unexpected condition");
    566  }
    567 }
    568 
    569 // ===============================================================
    570 // Branch functions
    571 
    572 void MacroAssembler::branch8(Condition cond, const Address& lhs, Imm32 rhs,
    573                             Label* label) {
    574  UseScratchRegisterScope temps(*this);
    575  Register scratch2 = temps.Acquire();
    576  MOZ_ASSERT(scratch2 != lhs.base);
    577 
    578  switch (cond) {
    579    case Assembler::Equal:
    580    case Assembler::NotEqual:
    581    case Assembler::Above:
    582    case Assembler::AboveOrEqual:
    583    case Assembler::Below:
    584    case Assembler::BelowOrEqual:
    585      load8ZeroExtend(lhs, scratch2);
    586      branch32(cond, scratch2, Imm32(uint8_t(rhs.value)), label);
    587      break;
    588 
    589    case Assembler::GreaterThan:
    590    case Assembler::GreaterThanOrEqual:
    591    case Assembler::LessThan:
    592    case Assembler::LessThanOrEqual:
    593      load8SignExtend(lhs, scratch2);
    594      branch32(cond, scratch2, Imm32(int8_t(rhs.value)), label);
    595      break;
    596 
    597    default:
    598      MOZ_CRASH("unexpected condition");
    599  }
    600 }
    601 
    602 void MacroAssembler::branch8(Condition cond, const BaseIndex& lhs, Register rhs,
    603                             Label* label) {
    604  UseScratchRegisterScope temps(*this);
    605  Register scratch2 = temps.Acquire();
    606  MOZ_ASSERT(scratch2 != lhs.base);
    607 
    608  computeScaledAddress(lhs, scratch2);
    609 
    610  switch (cond) {
    611    case Assembler::Equal:
    612    case Assembler::NotEqual:
    613    case Assembler::Above:
    614    case Assembler::AboveOrEqual:
    615    case Assembler::Below:
    616    case Assembler::BelowOrEqual:
    617      load8ZeroExtend(Address(scratch2, lhs.offset), scratch2);
    618      branch32(cond, scratch2, rhs, label);
    619      break;
    620 
    621    case Assembler::GreaterThan:
    622    case Assembler::GreaterThanOrEqual:
    623    case Assembler::LessThan:
    624    case Assembler::LessThanOrEqual:
    625      load8SignExtend(Address(scratch2, lhs.offset), scratch2);
    626      branch32(cond, scratch2, rhs, label);
    627      break;
    628 
    629    default:
    630      MOZ_CRASH("unexpected condition");
    631  }
    632 }
    633 
    634 void MacroAssembler::branch16(Condition cond, const Address& lhs, Imm32 rhs,
    635                              Label* label) {
    636  UseScratchRegisterScope temps(*this);
    637  Register scratch2 = temps.Acquire();
    638  MOZ_ASSERT(scratch2 != lhs.base);
    639 
    640  switch (cond) {
    641    case Assembler::Equal:
    642    case Assembler::NotEqual:
    643    case Assembler::Above:
    644    case Assembler::AboveOrEqual:
    645    case Assembler::Below:
    646    case Assembler::BelowOrEqual:
    647      load16ZeroExtend(lhs, scratch2);
    648      branch32(cond, scratch2, Imm32(uint16_t(rhs.value)), label);
    649      break;
    650 
    651    case Assembler::GreaterThan:
    652    case Assembler::GreaterThanOrEqual:
    653    case Assembler::LessThan:
    654    case Assembler::LessThanOrEqual:
    655      load16SignExtend(lhs, scratch2);
    656      branch32(cond, scratch2, Imm32(int16_t(rhs.value)), label);
    657      break;
    658 
    659    default:
    660      MOZ_CRASH("unexpected condition");
    661  }
    662 }
    663 
    664 void MacroAssembler::branch32(Condition cond, Register lhs, Register rhs,
    665                              Label* label) {
    666  ma_b(lhs, rhs, label, cond);
    667 }
    668 
    669 void MacroAssembler::branch32(Condition cond, Register lhs, Imm32 imm,
    670                              Label* label) {
    671  ma_b(lhs, imm, label, cond);
    672 }
    673 
    674 void MacroAssembler::branch32(Condition cond, const Address& lhs, Register rhs,
    675                              Label* label) {
    676  UseScratchRegisterScope temps(*this);
    677  Register scratch2 = temps.Acquire();
    678  load32(lhs, scratch2);
    679  ma_b(scratch2, rhs, label, cond);
    680 }
    681 
    682 void MacroAssembler::branch32(Condition cond, const Address& lhs, Imm32 rhs,
    683                              Label* label) {
    684  UseScratchRegisterScope temps(*this);
    685  Register scratch2 = temps.Acquire();
    686  load32(lhs, scratch2);
    687  ma_b(scratch2, rhs, label, cond);
    688 }
    689 
    690 void MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs,
    691                              Register rhs, Label* label) {
    692  UseScratchRegisterScope temps(*this);
    693  Register scratch2 = temps.Acquire();
    694  load32(lhs, scratch2);
    695  ma_b(scratch2, rhs, label, cond);
    696 }
    697 
    698 void MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs,
    699                              Imm32 rhs, Label* label) {
    700  UseScratchRegisterScope temps(*this);
    701  Register scratch2 = temps.Acquire();
    702  load32(lhs, scratch2);
    703  ma_b(scratch2, rhs, label, cond);
    704 }
    705 
    706 void MacroAssembler::branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs,
    707                              Label* label) {
    708  UseScratchRegisterScope temps(*this);
    709  Register scratch2 = temps.Acquire();
    710  load32(lhs, scratch2);
    711  ma_b(scratch2, rhs, label, cond);
    712 }
    713 
    714 void MacroAssembler::branch32(Condition cond, wasm::SymbolicAddress addr,
    715                              Imm32 imm, Label* label) {
    716  UseScratchRegisterScope temps(*this);
    717  Register scratch2 = temps.Acquire();
    718  load32(addr, scratch2);
    719  ma_b(scratch2, imm, label, cond);
    720 }
    721 
    722 void MacroAssembler::branchPtr(Condition cond, Register lhs, Register rhs,
    723                               Label* label) {
    724  ma_b(lhs, rhs, label, cond);
    725 }
    726 
    727 void MacroAssembler::branchPtr(Condition cond, Register lhs, Imm32 rhs,
    728                               Label* label) {
    729  ma_b(lhs, rhs, label, cond);
    730 }
    731 
    732 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmPtr rhs,
    733                               Label* label) {
    734  ma_b(lhs, rhs, label, cond);
    735 }
    736 
    737 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmGCPtr rhs,
    738                               Label* label) {
    739  ma_b(lhs, rhs, label, cond);
    740 }
    741 
    742 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmWord rhs,
    743                               Label* label) {
    744  ma_b(lhs, rhs, label, cond);
    745 }
    746 
    747 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, Register rhs,
    748                               Label* label) {
    749  UseScratchRegisterScope temps(*this);
    750  Register scratch2 = temps.Acquire();
    751  loadPtr(lhs, scratch2);
    752  branchPtr(cond, scratch2, rhs, label);
    753 }
    754 
    755 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmPtr rhs,
    756                               Label* label) {
    757  UseScratchRegisterScope temps(*this);
    758  Register scratch2 = temps.Acquire();
    759  loadPtr(lhs, scratch2);
    760  branchPtr(cond, scratch2, rhs, label);
    761 }
    762 
    763 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmGCPtr rhs,
    764                               Label* label) {
    765  UseScratchRegisterScope temps(*this);
    766  Register scratch2 = temps.Acquire();
    767  loadPtr(lhs, scratch2);
    768  branchPtr(cond, scratch2, rhs, label);
    769 }
    770 
    771 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmWord rhs,
    772                               Label* label) {
    773  UseScratchRegisterScope temps(*this);
    774  Register scratch2 = temps.Acquire();
    775  loadPtr(lhs, scratch2);
    776  branchPtr(cond, scratch2, rhs, label);
    777 }
    778 
    779 void MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs,
    780                               Register rhs, Label* label) {
    781  UseScratchRegisterScope temps(*this);
    782  Register scratch2 = temps.Acquire();
    783  loadPtr(lhs, scratch2);
    784  branchPtr(cond, scratch2, rhs, label);
    785 }
    786 
    787 void MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs,
    788                               ImmWord rhs, Label* label) {
    789  UseScratchRegisterScope temps(*this);
    790  Register scratch2 = temps.Acquire();
    791  loadPtr(lhs, scratch2);
    792  branchPtr(cond, scratch2, rhs, label);
    793 }
    794 
    795 void MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs,
    796                               Register rhs, Label* label) {
    797  UseScratchRegisterScope temps(*this);
    798  Register scratch2 = temps.Acquire();
    799  loadPtr(lhs, scratch2);
    800  branchPtr(cond, scratch2, rhs, label);
    801 }
    802 
    803 void MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs,
    804                               ImmWord rhs, Label* label) {
    805  UseScratchRegisterScope temps(*this);
    806  Register scratch2 = temps.Acquire();
    807  loadPtr(lhs, scratch2);
    808  branchPtr(cond, scratch2, rhs, label);
    809 }
    810 
    811 void MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs,
    812                               Register rhs, Label* label) {
    813  UseScratchRegisterScope temps(*this);
    814  Register scratch = temps.Acquire();
    815  loadPtr(lhs, scratch);
    816  branchPtr(cond, scratch, rhs, label);
    817 }
    818 
    819 void MacroAssembler::branchFloat(DoubleCondition cond, FloatRegister lhs,
    820                                 FloatRegister rhs, Label* label) {
    821  ma_bc1s(lhs, rhs, label, cond);
    822 }
    823 
    824 void MacroAssembler::branchTruncateFloat32ToInt32(FloatRegister src,
    825                                                  Register dest, Label* fail) {
    826  convertFloat32ToInt32(src, dest, fail, false);
    827 }
    828 
    829 void MacroAssembler::branchDouble(DoubleCondition cond, FloatRegister lhs,
    830                                  FloatRegister rhs, Label* label) {
    831  ma_bc1d(lhs, rhs, label, cond);
    832 }
    833 
    834 template <typename T>
    835 void MacroAssembler::branchAdd32(Condition cond, T src, Register dest,
    836                                 Label* overflow) {
    837  switch (cond) {
    838    case Overflow:
    839      ma_add32TestOverflow(dest, dest, src, overflow);
    840      break;
    841    case CarryClear:
    842    case CarrySet:
    843      ma_add32TestCarry(cond, dest, dest, src, overflow);
    844      break;
    845    default:
    846      MOZ_CRASH("NYI");
    847  }
    848 }
    849 
    850 template <typename T>
    851 void MacroAssembler::branchSub32(Condition cond, T src, Register dest,
    852                                 Label* overflow) {
    853  switch (cond) {
    854    case Overflow:
    855      ma_sub32TestOverflow(dest, dest, src, overflow);
    856      break;
    857    case NonZero:
    858    case Zero:
    859    case Signed:
    860    case NotSigned:
    861      ma_subu(dest, src);
    862      ma_b(dest, dest, overflow, cond);
    863      break;
    864    default:
    865      MOZ_CRASH("NYI");
    866  }
    867 }
    868 
    869 template <typename T>
    870 void MacroAssembler::branchMul32(Condition cond, T src, Register dest,
    871                                 Label* overflow) {
    872  MOZ_ASSERT(cond == Assembler::Overflow);
    873  ma_mul32TestOverflow(dest, dest, src, overflow);
    874 }
    875 
    876 template <typename T>
    877 void MacroAssembler::branchRshift32(Condition cond, T src, Register dest,
    878                                    Label* label) {
    879  MOZ_ASSERT(cond == Zero || cond == NonZero);
    880  rshift32(src, dest);
    881  branch32(cond == Zero ? Equal : NotEqual, dest, Imm32(0), label);
    882 }
    883 
    884 void MacroAssembler::branchNeg32(Condition cond, Register reg, Label* label) {
    885  MOZ_ASSERT(cond == Overflow);
    886  neg32(reg);
    887  branch32(Assembler::Equal, reg, Imm32(INT32_MIN), label);
    888 }
    889 
    890 template <typename T>
    891 void MacroAssembler::branchAddPtr(Condition cond, T src, Register dest,
    892                                  Label* label) {
    893  switch (cond) {
    894    case Overflow:
    895      ma_addPtrTestOverflow(dest, dest, src, label);
    896      break;
    897    case CarryClear:
    898    case CarrySet:
    899      ma_addPtrTestCarry(cond, dest, dest, src, label);
    900      break;
    901    case Signed:
    902    case NotSigned:
    903      ma_addPtrTestSigned(cond, dest, dest, src, label);
    904      break;
    905    default:
    906      MOZ_CRASH("NYI");
    907  }
    908 }
    909 
    910 template <typename T>
    911 void MacroAssembler::branchSubPtr(Condition cond, T src, Register dest,
    912                                  Label* label) {
    913  switch (cond) {
    914    case Overflow:
    915      ma_subPtrTestOverflow(dest, dest, src, label);
    916      break;
    917    case NonZero:
    918    case Zero:
    919    case Signed:
    920    case NotSigned:
    921      subPtr(src, dest);
    922      ma_b(dest, dest, label, cond);
    923      break;
    924    default:
    925      MOZ_CRASH("NYI");
    926  }
    927 }
    928 
    929 void MacroAssembler::branchMulPtr(Condition cond, Register src, Register dest,
    930                                  Label* label) {
    931  MOZ_ASSERT(cond == Assembler::Overflow);
    932  ma_mulPtrTestOverflow(dest, dest, src, label);
    933 }
    934 
    935 void MacroAssembler::branchNegPtr(Condition cond, Register reg, Label* label) {
    936  MOZ_ASSERT(cond == Assembler::Overflow);
    937  negPtr(reg);
    938  branchPtr(Assembler::Equal, reg, ImmWord(INTPTR_MIN), label);
    939 }
    940 
    941 void MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs,
    942                                  Label* label) {
    943  subPtr(rhs, lhs);
    944  branchPtr(cond, lhs, Imm32(0), label);
    945 }
    946 
    947 void MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs,
    948                                  Label* label) {
    949  MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
    950             cond == NotSigned);
    951  if (lhs == rhs) {
    952    ma_b(lhs, rhs, label, cond);
    953  } else {
    954    UseScratchRegisterScope temps(*this);
    955    Register scratch = temps.Acquire();
    956    as_and(scratch, lhs, rhs);
    957    ma_b(scratch, scratch, label, cond);
    958  }
    959 }
    960 
    961 void MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs,
    962                                  Label* label) {
    963  MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
    964             cond == NotSigned);
    965  UseScratchRegisterScope temps(*this);
    966  Register scratch = temps.Acquire();
    967  ma_and(scratch, lhs, rhs);
    968  ma_b(scratch, scratch, label, cond);
    969 }
    970 
    971 void MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs,
    972                                  Label* label) {
    973  MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
    974             cond == NotSigned);
    975  UseScratchRegisterScope temps(*this);
    976  Register scratch = temps.Acquire();
    977  load32(lhs, scratch);
    978  and32(rhs, scratch);
    979  ma_b(scratch, scratch, label, cond);
    980 }
    981 
    982 void MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs,
    983                                  Imm32 rhs, Label* label) {
    984  MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
    985             cond == NotSigned);
    986  UseScratchRegisterScope temps(*this);
    987  Register scratch = temps.Acquire();
    988  load32(lhs, scratch);
    989  and32(rhs, scratch);
    990  ma_b(scratch, scratch, label, cond);
    991 }
    992 
    993 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs,
    994                                   Label* label) {
    995  MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
    996             cond == NotSigned);
    997  if (lhs == rhs) {
    998    ma_b(lhs, rhs, label, cond);
    999  } else {
   1000    UseScratchRegisterScope temps(*this);
   1001    Register scratch = temps.Acquire();
   1002    as_and(scratch, lhs, rhs);
   1003    ma_b(scratch, scratch, label, cond);
   1004  }
   1005 }
   1006 
   1007 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, Imm32 rhs,
   1008                                   Label* label) {
   1009  MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
   1010             cond == NotSigned);
   1011  UseScratchRegisterScope temps(*this);
   1012  Register scratch = temps.Acquire();
   1013  ma_and(scratch, lhs, rhs);
   1014  ma_b(scratch, scratch, label, cond);
   1015 }
   1016 
   1017 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, ImmWord rhs,
   1018                                   Label* label) {
   1019  MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
   1020             cond == NotSigned);
   1021  UseScratchRegisterScope temps(*this);
   1022  Register scratch = temps.Acquire();
   1023  ma_li(scratch, rhs);
   1024  as_and(scratch, lhs, scratch);
   1025  ma_b(scratch, scratch, label, cond);
   1026 }
   1027 
   1028 void MacroAssembler::branchTestPtr(Condition cond, const Address& lhs,
   1029                                   Imm32 rhs, Label* label) {
   1030  UseScratchRegisterScope temps(*this);
   1031  Register scratch2 = temps.Acquire();
   1032  loadPtr(lhs, scratch2);
   1033  branchTestPtr(cond, scratch2, rhs, label);
   1034 }
   1035 
   1036 void MacroAssembler::branchTestUndefined(Condition cond, Register tag,
   1037                                         Label* label) {
   1038  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1039  ma_b(tag, ImmTag(JSVAL_TAG_UNDEFINED), label, cond);
   1040 }
   1041 
   1042 void MacroAssembler::branchTestUndefined(Condition cond, const Address& address,
   1043                                         Label* label) {
   1044  UseScratchRegisterScope temps(*this);
   1045  Register scratch2 = temps.Acquire();
   1046  Register tag = extractTag(address, scratch2);
   1047  branchTestUndefined(cond, tag, label);
   1048 }
   1049 
   1050 void MacroAssembler::branchTestUndefined(Condition cond,
   1051                                         const BaseIndex& address,
   1052                                         Label* label) {
   1053  UseScratchRegisterScope temps(*this);
   1054  Register scratch2 = temps.Acquire();
   1055  Register tag = extractTag(address, scratch2);
   1056  branchTestUndefined(cond, tag, label);
   1057 }
   1058 
   1059 void MacroAssembler::branchTestInt32(Condition cond, Register tag,
   1060                                     Label* label) {
   1061  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1062  ma_b(tag, ImmTag(JSVAL_TAG_INT32), label, cond);
   1063 }
   1064 
   1065 void MacroAssembler::branchTestInt32(Condition cond, const Address& address,
   1066                                     Label* label) {
   1067  UseScratchRegisterScope temps(*this);
   1068  Register scratch2 = temps.Acquire();
   1069  Register tag = extractTag(address, scratch2);
   1070  branchTestInt32(cond, tag, label);
   1071 }
   1072 
   1073 void MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address,
   1074                                     Label* label) {
   1075  UseScratchRegisterScope temps(*this);
   1076  Register scratch2 = temps.Acquire();
   1077  Register tag = extractTag(address, scratch2);
   1078  branchTestInt32(cond, tag, label);
   1079 }
   1080 
   1081 void MacroAssembler::branchTestDouble(Condition cond, const Address& address,
   1082                                      Label* label) {
   1083  UseScratchRegisterScope temps(*this);
   1084  Register scratch2 = temps.Acquire();
   1085  Register tag = extractTag(address, scratch2);
   1086  branchTestDouble(cond, tag, label);
   1087 }
   1088 
   1089 void MacroAssembler::branchTestDouble(Condition cond, const BaseIndex& address,
   1090                                      Label* label) {
   1091  UseScratchRegisterScope temps(*this);
   1092  Register scratch2 = temps.Acquire();
   1093  Register tag = extractTag(address, scratch2);
   1094  branchTestDouble(cond, tag, label);
   1095 }
   1096 
   1097 void MacroAssembler::branchTestDoubleTruthy(bool b, FloatRegister value,
   1098                                            Label* label) {
   1099  ma_lid(ScratchDoubleReg, 0.0);
   1100  DoubleCondition cond = b ? DoubleNotEqual : DoubleEqualOrUnordered;
   1101  ma_bc1d(value, ScratchDoubleReg, label, cond);
   1102 }
   1103 
   1104 void MacroAssembler::branchTestNumber(Condition cond, Register tag,
   1105                                      Label* label) {
   1106  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1107  Condition actual = cond == Equal ? BelowOrEqual : Above;
   1108  ma_b(tag, ImmTag(JS::detail::ValueUpperInclNumberTag), label, actual);
   1109 }
   1110 
   1111 void MacroAssembler::branchTestBoolean(Condition cond, Register tag,
   1112                                       Label* label) {
   1113  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1114  ma_b(tag, ImmTag(JSVAL_TAG_BOOLEAN), label, cond);
   1115 }
   1116 
   1117 void MacroAssembler::branchTestBoolean(Condition cond, const Address& address,
   1118                                       Label* label) {
   1119  UseScratchRegisterScope temps(*this);
   1120  Register scratch2 = temps.Acquire();
   1121  Register tag = extractTag(address, scratch2);
   1122  branchTestBoolean(cond, tag, label);
   1123 }
   1124 
   1125 void MacroAssembler::branchTestBoolean(Condition cond, const BaseIndex& address,
   1126                                       Label* label) {
   1127  UseScratchRegisterScope temps(*this);
   1128  Register scratch2 = temps.Acquire();
   1129  Register tag = extractTag(address, scratch2);
   1130  branchTestBoolean(cond, tag, label);
   1131 }
   1132 
   1133 void MacroAssembler::branchTestString(Condition cond, Register tag,
   1134                                      Label* label) {
   1135  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1136  ma_b(tag, ImmTag(JSVAL_TAG_STRING), label, cond);
   1137 }
   1138 
   1139 void MacroAssembler::branchTestString(Condition cond, const Address& address,
   1140                                      Label* label) {
   1141  UseScratchRegisterScope temps(*this);
   1142  Register scratch2 = temps.Acquire();
   1143  Register tag = extractTag(address, scratch2);
   1144  branchTestString(cond, tag, label);
   1145 }
   1146 
   1147 void MacroAssembler::branchTestString(Condition cond, const BaseIndex& address,
   1148                                      Label* label) {
   1149  UseScratchRegisterScope temps(*this);
   1150  Register scratch2 = temps.Acquire();
   1151  Register tag = extractTag(address, scratch2);
   1152  branchTestString(cond, tag, label);
   1153 }
   1154 
   1155 void MacroAssembler::branchTestSymbol(Condition cond, Register tag,
   1156                                      Label* label) {
   1157  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1158  ma_b(tag, ImmTag(JSVAL_TAG_SYMBOL), label, cond);
   1159 }
   1160 
   1161 void MacroAssembler::branchTestSymbol(Condition cond, const BaseIndex& address,
   1162                                      Label* label) {
   1163  UseScratchRegisterScope temps(*this);
   1164  Register scratch2 = temps.Acquire();
   1165  Register tag = extractTag(address, scratch2);
   1166  branchTestSymbol(cond, tag, label);
   1167 }
   1168 
   1169 void MacroAssembler::branchTestSymbol(Condition cond, const Address& address,
   1170                                      Label* label) {
   1171  UseScratchRegisterScope temps(*this);
   1172  Register scratch2 = temps.Acquire();
   1173  Register tag = extractTag(address, scratch2);
   1174  branchTestSymbol(cond, tag, label);
   1175 }
   1176 
   1177 void MacroAssembler::branchTestBigInt(Condition cond, Register tag,
   1178                                      Label* label) {
   1179  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1180  ma_b(tag, ImmTag(JSVAL_TAG_BIGINT), label, cond);
   1181 }
   1182 
   1183 void MacroAssembler::branchTestBigInt(Condition cond, const Address& address,
   1184                                      Label* label) {
   1185  UseScratchRegisterScope temps(*this);
   1186  Register scratch2 = temps.Acquire();
   1187  Register tag = extractTag(address, scratch2);
   1188  branchTestBigInt(cond, tag, label);
   1189 }
   1190 
   1191 void MacroAssembler::branchTestNull(Condition cond, Register tag,
   1192                                    Label* label) {
   1193  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1194  ma_b(tag, ImmTag(JSVAL_TAG_NULL), label, cond);
   1195 }
   1196 
   1197 void MacroAssembler::branchTestNull(Condition cond, const Address& address,
   1198                                    Label* label) {
   1199  UseScratchRegisterScope temps(*this);
   1200  Register scratch2 = temps.Acquire();
   1201  Register tag = extractTag(address, scratch2);
   1202  branchTestNull(cond, tag, label);
   1203 }
   1204 
   1205 void MacroAssembler::branchTestNull(Condition cond, const BaseIndex& address,
   1206                                    Label* label) {
   1207  UseScratchRegisterScope temps(*this);
   1208  Register scratch2 = temps.Acquire();
   1209  Register tag = extractTag(address, scratch2);
   1210  branchTestNull(cond, tag, label);
   1211 }
   1212 
   1213 void MacroAssembler::branchTestObject(Condition cond, Register tag,
   1214                                      Label* label) {
   1215  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1216  ma_b(tag, ImmTag(JSVAL_TAG_OBJECT), label, cond);
   1217 }
   1218 
   1219 void MacroAssembler::branchTestObject(Condition cond, const Address& address,
   1220                                      Label* label) {
   1221  UseScratchRegisterScope temps(*this);
   1222  Register scratch2 = temps.Acquire();
   1223  Register tag = extractTag(address, scratch2);
   1224  branchTestObject(cond, tag, label);
   1225 }
   1226 
   1227 void MacroAssembler::branchTestObject(Condition cond, const BaseIndex& address,
   1228                                      Label* label) {
   1229  UseScratchRegisterScope temps(*this);
   1230  Register scratch2 = temps.Acquire();
   1231  Register tag = extractTag(address, scratch2);
   1232  branchTestObject(cond, tag, label);
   1233 }
   1234 
   1235 void MacroAssembler::branchTestGCThing(Condition cond, const Address& address,
   1236                                       Label* label) {
   1237  branchTestGCThingImpl(cond, address, label);
   1238 }
   1239 
   1240 void MacroAssembler::branchTestGCThing(Condition cond, const BaseIndex& address,
   1241                                       Label* label) {
   1242  branchTestGCThingImpl(cond, address, label);
   1243 }
   1244 
   1245 void MacroAssembler::branchTestGCThing(Condition cond,
   1246                                       const ValueOperand& address,
   1247                                       Label* label) {
   1248  branchTestGCThingImpl(cond, address, label);
   1249 }
   1250 
   1251 template <typename T>
   1252 void MacroAssembler::branchTestGCThingImpl(Condition cond, const T& address,
   1253                                           Label* label) {
   1254  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1255  UseScratchRegisterScope temps(*this);
   1256  Register scratch2 = temps.Acquire();
   1257  Register tag = extractTag(address, scratch2);
   1258  ma_b(tag, ImmTag(JS::detail::ValueLowerInclGCThingTag), label,
   1259       (cond == Equal) ? AboveOrEqual : Below);
   1260 }
   1261 
   1262 void MacroAssembler::branchTestPrimitive(Condition cond, Register tag,
   1263                                         Label* label) {
   1264  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1265  ma_b(tag, ImmTag(JS::detail::ValueUpperExclPrimitiveTag), label,
   1266       (cond == Equal) ? Below : AboveOrEqual);
   1267 }
   1268 
   1269 void MacroAssembler::branchTestMagic(Condition cond, Register tag,
   1270                                     Label* label) {
   1271  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1272  ma_b(tag, ImmTag(JSVAL_TAG_MAGIC), label, cond);
   1273 }
   1274 
   1275 void MacroAssembler::branchTestMagic(Condition cond, const Address& address,
   1276                                     Label* label) {
   1277  UseScratchRegisterScope temps(*this);
   1278  Register scratch2 = temps.Acquire();
   1279  Register tag = extractTag(address, scratch2);
   1280  branchTestMagic(cond, tag, label);
   1281 }
   1282 
   1283 void MacroAssembler::branchTestMagic(Condition cond, const BaseIndex& address,
   1284                                     Label* label) {
   1285  UseScratchRegisterScope temps(*this);
   1286  Register scratch2 = temps.Acquire();
   1287  Register tag = extractTag(address, scratch2);
   1288  branchTestMagic(cond, tag, label);
   1289 }
   1290 
   1291 template <typename T>
   1292 void MacroAssembler::testNumberSet(Condition cond, const T& src,
   1293                                   Register dest) {
   1294  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1295  UseScratchRegisterScope temps(*this);
   1296  Register scratch2 = temps.Acquire();
   1297  Register tag = extractTag(src, scratch2);
   1298  ma_cmp_set(dest, tag, ImmTag(JS::detail::ValueUpperInclNumberTag),
   1299             cond == Equal ? BelowOrEqual : Above);
   1300 }
   1301 
   1302 template <typename T>
   1303 void MacroAssembler::testBooleanSet(Condition cond, const T& src,
   1304                                    Register dest) {
   1305  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1306  UseScratchRegisterScope temps(*this);
   1307  Register scratch2 = temps.Acquire();
   1308  Register tag = extractTag(src, scratch2);
   1309  ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_BOOLEAN), cond);
   1310 }
   1311 
   1312 template <typename T>
   1313 void MacroAssembler::testStringSet(Condition cond, const T& src,
   1314                                   Register dest) {
   1315  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1316  UseScratchRegisterScope temps(*this);
   1317  Register scratch2 = temps.Acquire();
   1318  Register tag = extractTag(src, scratch2);
   1319  ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_STRING), cond);
   1320 }
   1321 
   1322 template <typename T>
   1323 void MacroAssembler::testSymbolSet(Condition cond, const T& src,
   1324                                   Register dest) {
   1325  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1326  UseScratchRegisterScope temps(*this);
   1327  Register scratch2 = temps.Acquire();
   1328  Register tag = extractTag(src, scratch2);
   1329  ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_SYMBOL), cond);
   1330 }
   1331 
   1332 template <typename T>
   1333 void MacroAssembler::testBigIntSet(Condition cond, const T& src,
   1334                                   Register dest) {
   1335  MOZ_ASSERT(cond == Equal || cond == NotEqual);
   1336  UseScratchRegisterScope temps(*this);
   1337  Register scratch2 = temps.Acquire();
   1338  Register tag = extractTag(src, scratch2);
   1339  ma_cmp_set(dest, tag, ImmTag(JSVAL_TAG_BIGINT), cond);
   1340 }
   1341 
   1342 void MacroAssembler::branchToComputedAddress(const BaseIndex& addr) {
   1343  UseScratchRegisterScope temps(*this);
   1344  Register scratch = temps.Acquire();
   1345  loadPtr(addr, scratch);
   1346  branch(scratch);
   1347 }
   1348 
   1349 void MacroAssembler::cmp32Move32(Condition cond, Register lhs, Imm32 rhs,
   1350                                 Register src, Register dest) {
   1351  UseScratchRegisterScope temps(*this);
   1352  Register scratch = temps.Acquire();
   1353  MOZ_ASSERT(src != scratch && dest != scratch);
   1354  cmp32Set(cond, lhs, rhs, scratch);
   1355 #ifdef MIPSR6
   1356  as_selnez(src, src, scratch);
   1357  as_seleqz(dest, dest, scratch);
   1358  as_or(dest, dest, src);
   1359 #else
   1360  as_movn(dest, src, scratch);
   1361 #endif
   1362 }
   1363 
   1364 void MacroAssembler::cmp32Move32(Condition cond, Register lhs, Register rhs,
   1365                                 Register src, Register dest) {
   1366  UseScratchRegisterScope temps(*this);
   1367  Register scratch = temps.Acquire();
   1368  MOZ_ASSERT(src != scratch && dest != scratch);
   1369  cmp32Set(cond, lhs, rhs, scratch);
   1370 #ifdef MIPSR6
   1371  as_selnez(src, src, scratch);
   1372  as_seleqz(dest, dest, scratch);
   1373  as_or(dest, dest, src);
   1374 #else
   1375  as_movn(dest, src, scratch);
   1376 #endif
   1377 }
   1378 
   1379 void MacroAssembler::cmp32MovePtr(Condition cond, Register lhs, Imm32 rhs,
   1380                                  Register src, Register dest) {
   1381  UseScratchRegisterScope temps(*this);
   1382  Register scratch = temps.Acquire();
   1383  MOZ_ASSERT(src != scratch && dest != scratch);
   1384  cmp32Set(cond, lhs, rhs, scratch);
   1385 #ifdef MIPSR6
   1386  as_selnez(src, src, scratch);
   1387  as_seleqz(dest, dest, scratch);
   1388  as_or(dest, dest, src);
   1389 #else
   1390  as_movn(dest, src, scratch);
   1391 #endif
   1392 }
   1393 
   1394 void MacroAssembler::cmp32Move32(Condition cond, Register lhs,
   1395                                 const Address& rhs, Register src,
   1396                                 Register dest) {
   1397  UseScratchRegisterScope temps(*this);
   1398  Register scratch2 = temps.Acquire();
   1399  load32(rhs, scratch2);
   1400  cmp32Move32(cond, lhs, scratch2, src, dest);
   1401 }
   1402 
   1403 void MacroAssembler::cmp32Load32(Condition cond, Register lhs,
   1404                                 const Address& rhs, const Address& src,
   1405                                 Register dest) {
   1406  UseScratchRegisterScope temps(*this);
   1407  Register scratch = temps.Acquire();
   1408  MOZ_ASSERT(lhs != scratch && dest != scratch);
   1409  load32(rhs, scratch);
   1410  cmp32Load32(cond, lhs, scratch, src, dest);
   1411 }
   1412 
   1413 void MacroAssembler::cmp32Load32(Condition cond, Register lhs, Register rhs,
   1414                                 const Address& src, Register dest) {
   1415  Label skip;
   1416  branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip);
   1417  load32(src, dest);
   1418  bind(&skip);
   1419 }
   1420 
   1421 void MacroAssembler::cmp32Load32(Condition cond, Register lhs, Imm32 rhs,
   1422                                 const Address& src, Register dest) {
   1423  Label skip;
   1424  branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip);
   1425  load32(src, dest);
   1426  bind(&skip);
   1427 }
   1428 
   1429 void MacroAssembler::cmp32LoadPtr(Condition cond, const Address& lhs, Imm32 rhs,
   1430                                  const Address& src, Register dest) {
   1431  Label skip;
   1432  branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip);
   1433  loadPtr(src, dest);
   1434  bind(&skip);
   1435 }
   1436 
   1437 void MacroAssembler::test32LoadPtr(Condition cond, const Address& addr,
   1438                                   Imm32 mask, const Address& src,
   1439                                   Register dest) {
   1440  MOZ_RELEASE_ASSERT(!JitOptions.spectreStringMitigations);
   1441  Label skip;
   1442  branchTest32(Assembler::InvertCondition(cond), addr, mask, &skip);
   1443  loadPtr(src, dest);
   1444  bind(&skip);
   1445 }
   1446 
   1447 void MacroAssembler::test32MovePtr(Condition cond, Register operand, Imm32 mask,
   1448                                   Register src, Register dest) {
   1449  MOZ_ASSERT(cond == Assembler::Zero || cond == Assembler::NonZero);
   1450  Label skip;
   1451  branchTest32(Assembler::InvertCondition(cond), operand, mask, &skip);
   1452  movePtr(src, dest);
   1453  bind(&skip);
   1454 }
   1455 
   1456 void MacroAssembler::test32MovePtr(Condition cond, const Address& addr,
   1457                                   Imm32 mask, Register src, Register dest) {
   1458  MOZ_ASSERT(cond == Assembler::Zero || cond == Assembler::NonZero);
   1459  Label skip;
   1460  branchTest32(Assembler::InvertCondition(cond), addr, mask, &skip);
   1461  movePtr(src, dest);
   1462  bind(&skip);
   1463 }
   1464 
   1465 void MacroAssembler::spectreBoundsCheck32(Register index, Register length,
   1466                                          Register maybeScratch,
   1467                                          Label* failure) {
   1468  MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking);
   1469  branch32(Assembler::BelowOrEqual, length, index, failure);
   1470 }
   1471 
   1472 void MacroAssembler::spectreBoundsCheck32(Register index, const Address& length,
   1473                                          Register maybeScratch,
   1474                                          Label* failure) {
   1475  MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking);
   1476  branch32(Assembler::BelowOrEqual, length, index, failure);
   1477 }
   1478 
   1479 void MacroAssembler::spectreBoundsCheckPtr(Register index, Register length,
   1480                                           Register maybeScratch,
   1481                                           Label* failure) {
   1482  MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking);
   1483  branchPtr(Assembler::BelowOrEqual, length, index, failure);
   1484 }
   1485 
   1486 void MacroAssembler::spectreBoundsCheckPtr(Register index,
   1487                                           const Address& length,
   1488                                           Register maybeScratch,
   1489                                           Label* failure) {
   1490  MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking);
   1491  branchPtr(Assembler::BelowOrEqual, length, index, failure);
   1492 }
   1493 
   1494 void MacroAssembler::spectreMovePtr(Condition cond, Register src,
   1495                                    Register dest) {
   1496  MOZ_CRASH();
   1497 }
   1498 
   1499 void MacroAssembler::spectreZeroRegister(Condition cond, Register scratch,
   1500                                         Register dest) {
   1501  MOZ_CRASH();
   1502 }
   1503 
   1504 // ========================================================================
   1505 // Memory access primitives.
   1506 
   1507 FaultingCodeOffset MacroAssembler::storeDouble(FloatRegister src,
   1508                                               const Address& addr) {
   1509  return ma_sd(src, addr);
   1510 }
   1511 FaultingCodeOffset MacroAssembler::storeDouble(FloatRegister src,
   1512                                               const BaseIndex& addr) {
   1513  return ma_sd(src, addr);
   1514 }
   1515 
   1516 FaultingCodeOffset MacroAssembler::storeFloat32(FloatRegister src,
   1517                                                const Address& addr) {
   1518  return ma_ss(src, addr);
   1519 }
   1520 FaultingCodeOffset MacroAssembler::storeFloat32(FloatRegister src,
   1521                                                const BaseIndex& addr) {
   1522  return ma_ss(src, addr);
   1523 }
   1524 
   1525 FaultingCodeOffset MacroAssembler::storeFloat16(FloatRegister src,
   1526                                                const Address& dest, Register) {
   1527  MOZ_CRASH("Not supported for this target");
   1528 }
   1529 FaultingCodeOffset MacroAssembler::storeFloat16(FloatRegister src,
   1530                                                const BaseIndex& dest,
   1531                                                Register) {
   1532  MOZ_CRASH("Not supported for this target");
   1533 }
   1534 
   1535 void MacroAssembler::memoryBarrier(MemoryBarrier barrier) {
   1536  if (!barrier.isNone()) {
   1537    as_sync();
   1538  }
   1539 }
   1540 
   1541 // ===============================================================
   1542 // Clamping functions.
   1543 
   1544 void MacroAssembler::clampIntToUint8(Register reg) {
   1545  // If reg is < 0, then we want to clamp to 0.
   1546  UseScratchRegisterScope temps(*this);
   1547  Register scratch = temps.Acquire();
   1548  Register scratch2 = temps.Acquire();
   1549  as_slti(scratch, reg, 0);
   1550 #ifdef MIPSR6
   1551  as_seleqz(reg, reg, scratch);
   1552 #else
   1553  as_movn(reg, zero, scratch);
   1554 #endif
   1555  // If reg is >= 255, then we want to clamp to 255.
   1556  ma_li(scratch2, Imm32(255));
   1557  as_slti(scratch, reg, 255);
   1558 #ifdef MIPSR6
   1559  as_seleqz(scratch2, scratch2, scratch);
   1560  as_selnez(reg, reg, scratch);
   1561  as_or(reg, reg, scratch2);
   1562 #else
   1563  as_movz(reg, scratch2, scratch);
   1564 #endif
   1565 }
   1566 
   1567 //}}} check_macroassembler_style
   1568 // ===============================================================
   1569 
   1570 }  // namespace jit
   1571 }  // namespace js
   1572 
   1573 #endif /* jit_mips_shared_MacroAssembler_mips_shared_inl_h */