tor-browser

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

MacroAssembler-riscv64-inl.h (78357B)


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