tor-browser

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

MacroAssembler-mips64-inl.h (31252B)


      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_mips64_MacroAssembler_mips64_inl_h
      8 #define jit_mips64_MacroAssembler_mips64_inl_h
      9 
     10 #include "jit/mips64/MacroAssembler-mips64.h"
     11 
     12 #include "vm/BigIntType.h"  // JS::BigInt
     13 
     14 #include "jit/mips-shared/MacroAssembler-mips-shared-inl.h"
     15 
     16 namespace js {
     17 namespace jit {
     18 
     19 //{{{ check_macroassembler_style
     20 
     21 void MacroAssembler::move64(Register64 src, Register64 dest) {
     22  movePtr(src.reg, dest.reg);
     23 }
     24 
     25 void MacroAssembler::move64(Imm64 imm, Register64 dest) {
     26  movePtr(ImmWord(imm.value), dest.reg);
     27 }
     28 
     29 void MacroAssembler::moveDoubleToGPR64(FloatRegister src, Register64 dest) {
     30  moveFromDouble(src, dest.reg);
     31 }
     32 
     33 void MacroAssembler::moveGPR64ToDouble(Register64 src, FloatRegister dest) {
     34  moveToDouble(src.reg, dest);
     35 }
     36 
     37 void MacroAssembler::move64To32(Register64 src, Register dest) {
     38  ma_sll(dest, src.reg, Imm32(0));
     39 }
     40 
     41 void MacroAssembler::move32To64ZeroExtend(Register src, Register64 dest) {
     42  ma_dext(dest.reg, src, Imm32(0), Imm32(32));
     43 }
     44 
     45 void MacroAssembler::move8To64SignExtend(Register src, Register64 dest) {
     46  move32To64SignExtend(src, dest);
     47  move8SignExtend(dest.reg, dest.reg);
     48 }
     49 
     50 void MacroAssembler::move16To64SignExtend(Register src, Register64 dest) {
     51  move32To64SignExtend(src, dest);
     52  move16SignExtend(dest.reg, dest.reg);
     53 }
     54 
     55 void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) {
     56  ma_sll(dest.reg, src, Imm32(0));
     57 }
     58 
     59 void MacroAssembler::move8SignExtendToPtr(Register src, Register dest) {
     60  move8To64SignExtend(src, Register64(dest));
     61 }
     62 
     63 void MacroAssembler::move16SignExtendToPtr(Register src, Register dest) {
     64  move16To64SignExtend(src, Register64(dest));
     65 }
     66 
     67 void MacroAssembler::move32SignExtendToPtr(Register src, Register dest) {
     68  ma_sll(dest, src, Imm32(0));
     69 }
     70 
     71 void MacroAssembler::move32ZeroExtendToPtr(Register src, Register dest) {
     72  ma_dext(dest, src, Imm32(0), Imm32(32));
     73 }
     74 
     75 // ===============================================================
     76 // Load instructions
     77 
     78 void MacroAssembler::load32SignExtendToPtr(const Address& src, Register dest) {
     79  load32(src, dest);
     80 }
     81 
     82 // ===============================================================
     83 // Logical instructions
     84 
     85 void MacroAssembler::notPtr(Register reg) { ma_not(reg, reg); }
     86 
     87 void MacroAssembler::andPtr(Register src, Register dest) { ma_and(dest, src); }
     88 
     89 void MacroAssembler::andPtr(Imm32 imm, Register dest) { ma_and(dest, imm); }
     90 
     91 void MacroAssembler::andPtr(Imm32 imm, Register src, Register dest) {
     92  ma_and(dest, src, imm);
     93 }
     94 
     95 void MacroAssembler::and64(Imm64 imm, Register64 dest) {
     96  UseScratchRegisterScope temps(*this);
     97  Register scratch = temps.Acquire();
     98  ma_li(scratch, ImmWord(imm.value));
     99  ma_and(dest.reg, scratch);
    100 }
    101 
    102 void MacroAssembler::and64(Register64 src, Register64 dest) {
    103  ma_and(dest.reg, src.reg);
    104 }
    105 
    106 void MacroAssembler::or64(Imm64 imm, Register64 dest) {
    107  UseScratchRegisterScope temps(*this);
    108  Register scratch = temps.Acquire();
    109  ma_li(scratch, ImmWord(imm.value));
    110  ma_or(dest.reg, scratch);
    111 }
    112 
    113 void MacroAssembler::xor64(Imm64 imm, Register64 dest) {
    114  UseScratchRegisterScope temps(*this);
    115  Register scratch = temps.Acquire();
    116  ma_li(scratch, ImmWord(imm.value));
    117  ma_xor(dest.reg, scratch);
    118 }
    119 
    120 void MacroAssembler::orPtr(Register src, Register dest) { ma_or(dest, src); }
    121 
    122 void MacroAssembler::orPtr(Imm32 imm, Register dest) { ma_or(dest, imm); }
    123 
    124 void MacroAssembler::orPtr(Imm32 imm, Register src, Register dest) {
    125  ma_or(dest, src, imm);
    126 }
    127 
    128 void MacroAssembler::or64(Register64 src, Register64 dest) {
    129  ma_or(dest.reg, src.reg);
    130 }
    131 
    132 void MacroAssembler::xor64(Register64 src, Register64 dest) {
    133  ma_xor(dest.reg, src.reg);
    134 }
    135 
    136 void MacroAssembler::xorPtr(Register src, Register dest) { ma_xor(dest, src); }
    137 
    138 void MacroAssembler::xorPtr(Imm32 imm, Register dest) { ma_xor(dest, imm); }
    139 
    140 void MacroAssembler::xorPtr(Imm32 imm, Register src, Register dest) {
    141  ma_xor(dest, src, imm);
    142 }
    143 
    144 // ===============================================================
    145 // Swap instructions
    146 
    147 void MacroAssembler::byteSwap64(Register64 reg64) {
    148  Register reg = reg64.reg;
    149  ma_dsbh(reg, reg);
    150  ma_dshd(reg, reg);
    151 }
    152 
    153 // ===============================================================
    154 // Arithmetic functions
    155 
    156 void MacroAssembler::addPtr(Register src, Register dest) {
    157  ma_daddu(dest, src);
    158 }
    159 
    160 void MacroAssembler::addPtr(Imm32 imm, Register dest) { ma_daddu(dest, imm); }
    161 
    162 void MacroAssembler::addPtr(ImmWord imm, Register dest) {
    163  UseScratchRegisterScope temps(*this);
    164  Register scratch = temps.Acquire();
    165  movePtr(imm, scratch);
    166  addPtr(scratch, dest);
    167 }
    168 
    169 void MacroAssembler::add64(Register64 src, Register64 dest) {
    170  addPtr(src.reg, dest.reg);
    171 }
    172 
    173 void MacroAssembler::add64(Imm32 imm, Register64 dest) {
    174  ma_daddu(dest.reg, imm);
    175 }
    176 
    177 void MacroAssembler::add64(Imm64 imm, Register64 dest) {
    178  UseScratchRegisterScope temps(*this);
    179  Register scratch = temps.Acquire();
    180  mov(ImmWord(imm.value), scratch);
    181  ma_daddu(dest.reg, scratch);
    182 }
    183 
    184 CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) {
    185  CodeOffset offset = CodeOffset(currentOffset());
    186  ma_liPatchable(dest, Imm32(0));
    187  as_dsubu(dest, StackPointer, dest);
    188  return offset;
    189 }
    190 
    191 void MacroAssembler::patchSub32FromStackPtr(CodeOffset offset, Imm32 imm) {
    192  Instruction* lui =
    193      (Instruction*)m_buffer.getInst(BufferOffset(offset.offset()));
    194  Instruction* ori =
    195      (Instruction*)m_buffer.getInst(BufferOffset(offset.offset() + 4));
    196 
    197  MOZ_ASSERT(lui->extractOpcode() == ((uint32_t)op_lui >> OpcodeShift));
    198  MOZ_ASSERT(ori->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));
    199 
    200  MacroAssemblerMIPSShared::UpdateLuiOriValue(lui, ori, imm.value);
    201 }
    202 
    203 void MacroAssembler::subPtr(Register src, Register dest) {
    204  as_dsubu(dest, dest, src);
    205 }
    206 
    207 void MacroAssembler::subPtr(Imm32 imm, Register dest) {
    208  ma_dsubu(dest, dest, imm);
    209 }
    210 
    211 void MacroAssembler::sub64(Register64 src, Register64 dest) {
    212  as_dsubu(dest.reg, dest.reg, src.reg);
    213 }
    214 
    215 void MacroAssembler::sub64(Imm64 imm, Register64 dest) {
    216  UseScratchRegisterScope temps(*this);
    217  Register scratch = temps.Acquire();
    218  mov(ImmWord(imm.value), scratch);
    219  as_dsubu(dest.reg, dest.reg, scratch);
    220 }
    221 
    222 void MacroAssembler::mulHighUnsigned32(Imm32 imm, Register src, Register dest) {
    223  UseScratchRegisterScope temps(*this);
    224  Register scratch = temps.Acquire();
    225  MOZ_ASSERT(src != scratch);
    226  move32(imm, scratch);
    227 #ifdef MIPSR6
    228  as_muhu(dest, src, scratch);
    229 #else
    230  as_multu(src, scratch);
    231  as_mfhi(dest);
    232 #endif
    233 }
    234 
    235 void MacroAssembler::mulPtr(Register rhs, Register srcDest) {
    236 #ifdef MIPSR6
    237  as_dmulu(srcDest, srcDest, rhs);
    238 #else
    239  as_dmultu(srcDest, rhs);
    240  as_mflo(srcDest);
    241 #endif
    242 }
    243 
    244 void MacroAssembler::mulPtr(ImmWord rhs, Register srcDest) {
    245  UseScratchRegisterScope temps(*this);
    246  Register scratch = temps.Acquire();
    247  MOZ_ASSERT(srcDest != scratch);
    248  mov(rhs, scratch);
    249  mulPtr(scratch, srcDest);
    250 }
    251 
    252 void MacroAssembler::mul64(Imm64 imm, const Register64& dest) {
    253  UseScratchRegisterScope temps(*this);
    254  Register scratch = temps.Acquire();
    255  mov(ImmWord(imm.value), scratch);
    256 #ifdef MIPSR6
    257  as_dmulu(dest.reg, scratch, dest.reg);
    258 #else
    259  as_dmultu(dest.reg, scratch);
    260  as_mflo(dest.reg);
    261 #endif
    262 }
    263 
    264 void MacroAssembler::mul64(Imm64 imm, const Register64& dest,
    265                           const Register temp) {
    266  MOZ_ASSERT(temp == InvalidReg);
    267  mul64(imm, dest);
    268 }
    269 
    270 void MacroAssembler::mul64(const Register64& src, const Register64& dest,
    271                           const Register temp) {
    272  MOZ_ASSERT(temp == InvalidReg);
    273 #ifdef MIPSR6
    274  as_dmulu(dest.reg, src.reg, dest.reg);
    275 #else
    276  as_dmultu(dest.reg, src.reg);
    277  as_mflo(dest.reg);
    278 #endif
    279 }
    280 
    281 void MacroAssembler::mulBy3(Register src, Register dest) {
    282  UseScratchRegisterScope temps(*this);
    283  Register scratch = temps.Acquire();
    284  MOZ_ASSERT(src != scratch);
    285  as_daddu(scratch, src, src);
    286  as_daddu(dest, scratch, src);
    287 }
    288 
    289 void MacroAssembler::inc64(AbsoluteAddress dest) {
    290  UseScratchRegisterScope temps(*this);
    291  Register scratch = temps.Acquire();
    292  Register scratch2 = temps.Acquire();
    293  ma_li(scratch, ImmWord(uintptr_t(dest.addr)));
    294  as_ld(scratch2, scratch, 0);
    295  as_daddiu(scratch2, scratch2, 1);
    296  as_sd(scratch2, scratch, 0);
    297 }
    298 
    299 void MacroAssembler::quotient64(Register lhs, Register rhs, Register dest,
    300                                bool isUnsigned) {
    301 #ifdef MIPSR6
    302  if (isUnsigned) {
    303    as_ddivu(dest, lhs, rhs);
    304  } else {
    305    as_ddiv(dest, lhs, rhs);
    306  }
    307 #else
    308  if (isUnsigned) {
    309    as_ddivu(lhs, rhs);
    310  } else {
    311    as_ddiv(lhs, rhs);
    312  }
    313  as_mflo(dest);
    314 #endif
    315 }
    316 
    317 void MacroAssembler::remainder64(Register lhs, Register rhs, Register dest,
    318                                 bool isUnsigned) {
    319 #ifdef MIPSR6
    320  if (isUnsigned) {
    321    as_dmodu(dest, lhs, rhs);
    322  } else {
    323    as_dmod(dest, lhs, rhs);
    324  }
    325 #else
    326  if (isUnsigned) {
    327    as_ddivu(lhs, rhs);
    328  } else {
    329    as_ddiv(lhs, rhs);
    330  }
    331  as_mfhi(dest);
    332 #endif
    333 }
    334 
    335 void MacroAssembler::neg64(Register64 reg) { as_dsubu(reg.reg, zero, reg.reg); }
    336 
    337 void MacroAssembler::negPtr(Register reg) { as_dsubu(reg, zero, reg); }
    338 
    339 // ===============================================================
    340 // Shift functions
    341 
    342 void MacroAssembler::lshiftPtr(Imm32 imm, Register dest) {
    343  lshiftPtr(imm, dest, dest);
    344 }
    345 
    346 void MacroAssembler::lshiftPtr(Imm32 imm, Register src, Register dest) {
    347  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
    348  ma_dsll(dest, src, imm);
    349 }
    350 
    351 void MacroAssembler::lshiftPtr(Register shift, Register dest) {
    352  ma_dsll(dest, dest, shift);
    353 }
    354 
    355 void MacroAssembler::lshift64(Imm32 imm, Register64 dest) {
    356  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
    357  ma_dsll(dest.reg, dest.reg, imm);
    358 }
    359 
    360 void MacroAssembler::lshift64(Register shift, Register64 dest) {
    361  ma_dsll(dest.reg, dest.reg, shift);
    362 }
    363 
    364 void MacroAssembler::rshiftPtr(Imm32 imm, Register dest) {
    365  rshiftPtr(imm, dest, dest);
    366 }
    367 
    368 void MacroAssembler::rshiftPtr(Imm32 imm, Register src, Register dest) {
    369  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
    370  ma_dsrl(dest, src, imm);
    371 }
    372 
    373 void MacroAssembler::rshiftPtr(Register shift, Register dest) {
    374  ma_dsrl(dest, dest, shift);
    375 }
    376 
    377 void MacroAssembler::rshift64(Imm32 imm, Register64 dest) {
    378  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
    379  ma_dsrl(dest.reg, dest.reg, imm);
    380 }
    381 
    382 void MacroAssembler::rshift64(Register shift, Register64 dest) {
    383  ma_dsrl(dest.reg, dest.reg, shift);
    384 }
    385 
    386 void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest) {
    387  rshiftPtrArithmetic(imm, dest, dest);
    388 }
    389 
    390 void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register src,
    391                                         Register dest) {
    392  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
    393  ma_dsra(dest, src, imm);
    394 }
    395 
    396 void MacroAssembler::rshiftPtrArithmetic(Register shift, Register dest) {
    397  ma_dsra(dest, dest, shift);
    398 }
    399 
    400 void MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest) {
    401  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
    402  ma_dsra(dest.reg, dest.reg, imm);
    403 }
    404 
    405 void MacroAssembler::rshift64Arithmetic(Register shift, Register64 dest) {
    406  ma_dsra(dest.reg, dest.reg, shift);
    407 }
    408 
    409 // ===============================================================
    410 // Rotation functions
    411 
    412 void MacroAssembler::rotateLeft64(Imm32 count, Register64 src, Register64 dest,
    413                                  Register temp) {
    414  MOZ_ASSERT(temp == InvalidReg);
    415 
    416  if (count.value) {
    417    ma_drol(dest.reg, src.reg, count);
    418  } else {
    419    ma_move(dest.reg, src.reg);
    420  }
    421 }
    422 
    423 void MacroAssembler::rotateLeft64(Register count, Register64 src,
    424                                  Register64 dest, Register temp) {
    425  MOZ_ASSERT(temp == InvalidReg);
    426  ma_drol(dest.reg, src.reg, count);
    427 }
    428 
    429 void MacroAssembler::rotateRight64(Imm32 count, Register64 src, Register64 dest,
    430                                   Register temp) {
    431  MOZ_ASSERT(temp == InvalidReg);
    432 
    433  if (count.value) {
    434    ma_dror(dest.reg, src.reg, count);
    435  } else {
    436    ma_move(dest.reg, src.reg);
    437  }
    438 }
    439 
    440 void MacroAssembler::rotateRight64(Register count, Register64 src,
    441                                   Register64 dest, Register temp) {
    442  MOZ_ASSERT(temp == InvalidReg);
    443  ma_dror(dest.reg, src.reg, count);
    444 }
    445 
    446 // ===============================================================
    447 // Condition functions
    448 
    449 template <typename T1, typename T2>
    450 void MacroAssembler::cmpPtrSet(Condition cond, T1 lhs, T2 rhs, Register dest) {
    451  ma_cmp_set(dest, lhs, rhs, cond);
    452 }
    453 
    454 // Also see below for specializations of cmpPtrSet.
    455 
    456 template <typename T1, typename T2>
    457 void MacroAssembler::cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest) {
    458  ma_cmp_set(dest, lhs, rhs, cond);
    459 }
    460 
    461 void MacroAssembler::cmp64Set(Condition cond, Register64 lhs, Register64 rhs,
    462                              Register dest) {
    463  ma_cmp_set(dest, lhs.reg, rhs.reg, cond);
    464 }
    465 
    466 void MacroAssembler::cmp64Set(Condition cond, Register64 lhs, Imm64 rhs,
    467                              Register dest) {
    468  ma_cmp_set(dest, lhs.reg, ImmWord(uint64_t(rhs.value)), cond);
    469 }
    470 
    471 void MacroAssembler::cmp64Set(Condition cond, Address lhs, Register64 rhs,
    472                              Register dest) {
    473  ma_cmp_set(dest, lhs, rhs.reg, cond);
    474 }
    475 
    476 void MacroAssembler::cmp64Set(Condition cond, Address lhs, Imm64 rhs,
    477                              Register dest) {
    478  ma_cmp_set(dest, lhs, ImmWord(uint64_t(rhs.value)), cond);
    479 }
    480 
    481 // ===============================================================
    482 // Bit counting functions
    483 
    484 void MacroAssembler::clz64(Register64 src, Register64 dest) {
    485  as_dclz(dest.reg, src.reg);
    486 }
    487 
    488 void MacroAssembler::ctz64(Register64 src, Register64 dest) {
    489  ma_dctz(dest.reg, src.reg);
    490 }
    491 
    492 void MacroAssembler::popcnt64(Register64 input, Register64 output,
    493                              Register tmp) {
    494  UseScratchRegisterScope temps(*this);
    495  Register scratch = temps.Acquire();
    496  ma_move(output.reg, input.reg);
    497  ma_dsra(tmp, input.reg, Imm32(1));
    498  ma_li(scratch, ImmWord(0x5555555555555555UL));
    499  ma_and(tmp, scratch);
    500  ma_dsubu(output.reg, tmp);
    501  ma_dsra(tmp, output.reg, Imm32(2));
    502  ma_li(scratch, ImmWord(0x3333333333333333UL));
    503  ma_and(output.reg, scratch);
    504  ma_and(tmp, scratch);
    505  ma_daddu(output.reg, tmp);
    506  ma_dsrl(tmp, output.reg, Imm32(4));
    507  ma_daddu(output.reg, tmp);
    508  ma_li(scratch, ImmWord(0xF0F0F0F0F0F0F0FUL));
    509  ma_and(output.reg, scratch);
    510  ma_dsll(tmp, output.reg, Imm32(8));
    511  ma_daddu(output.reg, tmp);
    512  ma_dsll(tmp, output.reg, Imm32(16));
    513  ma_daddu(output.reg, tmp);
    514  ma_dsll(tmp, output.reg, Imm32(32));
    515  ma_daddu(output.reg, tmp);
    516  ma_dsra(output.reg, output.reg, Imm32(56));
    517 }
    518 
    519 // ===============================================================
    520 // Branch functions
    521 
    522 void MacroAssembler::branch64(Condition cond, Register64 lhs, Imm64 val,
    523                              Label* success, Label* fail) {
    524  MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal ||
    525                 cond == Assembler::LessThan ||
    526                 cond == Assembler::LessThanOrEqual ||
    527                 cond == Assembler::GreaterThan ||
    528                 cond == Assembler::GreaterThanOrEqual ||
    529                 cond == Assembler::Below || cond == Assembler::BelowOrEqual ||
    530                 cond == Assembler::Above || cond == Assembler::AboveOrEqual,
    531             "other condition codes not supported");
    532 
    533  branchPtr(cond, lhs.reg, ImmWord(val.value), success);
    534  if (fail) {
    535    jump(fail);
    536  }
    537 }
    538 
    539 void MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs,
    540                              Label* success, Label* fail) {
    541  MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal ||
    542                 cond == Assembler::LessThan ||
    543                 cond == Assembler::LessThanOrEqual ||
    544                 cond == Assembler::GreaterThan ||
    545                 cond == Assembler::GreaterThanOrEqual ||
    546                 cond == Assembler::Below || cond == Assembler::BelowOrEqual ||
    547                 cond == Assembler::Above || cond == Assembler::AboveOrEqual,
    548             "other condition codes not supported");
    549 
    550  branchPtr(cond, lhs.reg, rhs.reg, success);
    551  if (fail) {
    552    jump(fail);
    553  }
    554 }
    555 
    556 void MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val,
    557                              Label* success, Label* fail) {
    558  MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal ||
    559                 cond == Assembler::LessThan ||
    560                 cond == Assembler::LessThanOrEqual ||
    561                 cond == Assembler::GreaterThan ||
    562                 cond == Assembler::GreaterThanOrEqual ||
    563                 cond == Assembler::Below || cond == Assembler::BelowOrEqual ||
    564                 cond == Assembler::Above || cond == Assembler::AboveOrEqual,
    565             "other condition codes not supported");
    566 
    567  branchPtr(cond, lhs, ImmWord(val.value), success);
    568  if (fail) {
    569    jump(fail);
    570  }
    571 }
    572 
    573 void MacroAssembler::branch64(Condition cond, const Address& lhs,
    574                              Register64 rhs, Label* success, Label* fail) {
    575  MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal ||
    576                 cond == Assembler::LessThan ||
    577                 cond == Assembler::LessThanOrEqual ||
    578                 cond == Assembler::GreaterThan ||
    579                 cond == Assembler::GreaterThanOrEqual ||
    580                 cond == Assembler::Below || cond == Assembler::BelowOrEqual ||
    581                 cond == Assembler::Above || cond == Assembler::AboveOrEqual,
    582             "other condition codes not supported");
    583 
    584  branchPtr(cond, lhs, rhs.reg, success);
    585  if (fail) {
    586    jump(fail);
    587  }
    588 }
    589 
    590 void MacroAssembler::branch64(Condition cond, const Address& lhs,
    591                              const Address& rhs, Register scratch,
    592                              Label* label) {
    593  MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal,
    594             "other condition codes not supported");
    595  MOZ_ASSERT(lhs.base != scratch);
    596  MOZ_ASSERT(rhs.base != scratch);
    597 
    598  loadPtr(rhs, scratch);
    599  branchPtr(cond, lhs, scratch, label);
    600 }
    601 
    602 void MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs,
    603                                      Register rhs, Label* label) {
    604  branchPtr(cond, lhs, rhs, label);
    605 }
    606 
    607 void MacroAssembler::branchTest64(Condition cond, Register64 lhs,
    608                                  Register64 rhs, Register temp, Label* success,
    609                                  Label* fail) {
    610  branchTestPtr(cond, lhs.reg, rhs.reg, success);
    611  if (fail) {
    612    jump(fail);
    613  }
    614 }
    615 
    616 void MacroAssembler::branchTest64(Condition cond, Register64 lhs, Imm64 rhs,
    617                                  Label* success, Label* fail) {
    618  branchTestPtr(cond, lhs.reg, ImmWord(rhs.value), success);
    619  if (fail) {
    620    jump(fail);
    621  }
    622 }
    623 
    624 void MacroAssembler::branchTestUndefined(Condition cond,
    625                                         const ValueOperand& value,
    626                                         Label* label) {
    627  UseScratchRegisterScope temps(*this);
    628  Register scratch2 = temps.Acquire();
    629  splitTag(value, scratch2);
    630  branchTestUndefined(cond, scratch2, label);
    631 }
    632 
    633 void MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value,
    634                                     Label* label) {
    635  UseScratchRegisterScope temps(*this);
    636  Register scratch2 = temps.Acquire();
    637  splitTag(value, scratch2);
    638  branchTestInt32(cond, scratch2, label);
    639 }
    640 
    641 void MacroAssembler::branchTestInt32Truthy(bool b, const ValueOperand& value,
    642                                           Label* label) {
    643  UseScratchRegisterScope temps(*this);
    644  Register scratch = temps.Acquire();
    645  ma_dext(scratch, value.valueReg(), Imm32(0), Imm32(32));
    646  ma_b(scratch, scratch, label, b ? NonZero : Zero);
    647 }
    648 
    649 void MacroAssembler::branchTestDouble(Condition cond, Register tag,
    650                                      Label* label) {
    651  MOZ_ASSERT(cond == Equal || cond == NotEqual);
    652  Condition actual = (cond == Equal) ? BelowOrEqual : Above;
    653  ma_b(tag, ImmTag(JSVAL_TAG_MAX_DOUBLE), label, actual);
    654 }
    655 
    656 void MacroAssembler::branchTestDouble(Condition cond, const ValueOperand& value,
    657                                      Label* label) {
    658  UseScratchRegisterScope temps(*this);
    659  Register scratch2 = temps.Acquire();
    660  splitTag(value, scratch2);
    661  branchTestDouble(cond, scratch2, label);
    662 }
    663 
    664 void MacroAssembler::branchTestNumber(Condition cond, const ValueOperand& value,
    665                                      Label* label) {
    666  UseScratchRegisterScope temps(*this);
    667  Register scratch2 = temps.Acquire();
    668  splitTag(value, scratch2);
    669  branchTestNumber(cond, scratch2, label);
    670 }
    671 
    672 void MacroAssembler::branchTestBoolean(Condition cond,
    673                                       const ValueOperand& value,
    674                                       Label* label) {
    675  UseScratchRegisterScope temps(*this);
    676  Register scratch2 = temps.Acquire();
    677  splitTag(value, scratch2);
    678  branchTestBoolean(cond, scratch2, label);
    679 }
    680 
    681 void MacroAssembler::branchTestBooleanTruthy(bool b, const ValueOperand& value,
    682                                             Label* label) {
    683  UseScratchRegisterScope temps(*this);
    684  Register scratch2 = temps.Acquire();
    685  unboxBoolean(value, scratch2);
    686  ma_b(scratch2, scratch2, label, b ? NonZero : Zero);
    687 }
    688 
    689 void MacroAssembler::branchTestString(Condition cond, const ValueOperand& value,
    690                                      Label* label) {
    691  UseScratchRegisterScope temps(*this);
    692  Register scratch2 = temps.Acquire();
    693  splitTag(value, scratch2);
    694  branchTestString(cond, scratch2, label);
    695 }
    696 
    697 void MacroAssembler::branchTestStringTruthy(bool b, const ValueOperand& value,
    698                                            Label* label) {
    699  UseScratchRegisterScope temps(*this);
    700  Register scratch2 = temps.Acquire();
    701  unboxString(value, scratch2);
    702  load32(Address(scratch2, JSString::offsetOfLength()), scratch2);
    703  ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal);
    704 }
    705 
    706 void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value,
    707                                      Label* label) {
    708  UseScratchRegisterScope temps(*this);
    709  Register scratch2 = temps.Acquire();
    710  splitTag(value, scratch2);
    711  branchTestSymbol(cond, scratch2, label);
    712 }
    713 
    714 void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address,
    715                                      Label* label) {
    716  UseScratchRegisterScope temps(*this);
    717  Register scratch2 = temps.Acquire();
    718  computeEffectiveAddress(address, scratch2);
    719  splitTag(scratch2, scratch2);
    720  branchTestBigInt(cond, scratch2, label);
    721 }
    722 
    723 void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value,
    724                                      Label* label) {
    725  UseScratchRegisterScope temps(*this);
    726  Register scratch2 = temps.Acquire();
    727  splitTag(value, scratch2);
    728  branchTestBigInt(cond, scratch2, label);
    729 }
    730 
    731 void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value,
    732                                            Label* label) {
    733  UseScratchRegisterScope temps(*this);
    734  Register scratch2 = temps.Acquire();
    735  unboxBigInt(value, scratch2);
    736  load32(Address(scratch2, BigInt::offsetOfDigitLength()), scratch2);
    737  ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal);
    738 }
    739 
    740 void MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value,
    741                                    Label* label) {
    742  UseScratchRegisterScope temps(*this);
    743  Register scratch2 = temps.Acquire();
    744  splitTag(value, scratch2);
    745  branchTestNull(cond, scratch2, label);
    746 }
    747 
    748 void MacroAssembler::branchTestObject(Condition cond, const ValueOperand& value,
    749                                      Label* label) {
    750  UseScratchRegisterScope temps(*this);
    751  Register scratch2 = temps.Acquire();
    752  splitTag(value, scratch2);
    753  branchTestObject(cond, scratch2, label);
    754 }
    755 
    756 void MacroAssembler::branchTestPrimitive(Condition cond,
    757                                         const ValueOperand& value,
    758                                         Label* label) {
    759  UseScratchRegisterScope temps(*this);
    760  Register scratch2 = temps.Acquire();
    761  splitTag(value, scratch2);
    762  branchTestPrimitive(cond, scratch2, label);
    763 }
    764 
    765 void MacroAssembler::branchTestMagic(Condition cond, const ValueOperand& value,
    766                                     Label* label) {
    767  UseScratchRegisterScope temps(*this);
    768  Register scratch2 = temps.Acquire();
    769  splitTag(value, scratch2);
    770  ma_b(scratch2, ImmTag(JSVAL_TAG_MAGIC), label, cond);
    771 }
    772 
    773 void MacroAssembler::branchTestMagic(Condition cond, const Address& valaddr,
    774                                     JSWhyMagic why, Label* label) {
    775  uint64_t magic = MagicValue(why).asRawBits();
    776  UseScratchRegisterScope temps(*this);
    777  Register scratch = temps.Acquire();
    778  loadPtr(valaddr, scratch);
    779  ma_b(scratch, ImmWord(magic), label, cond);
    780 }
    781 
    782 template <typename T>
    783 void MacroAssembler::branchTestValue(Condition cond, const T& lhs,
    784                                     const ValueOperand& rhs, Label* label) {
    785  MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
    786  branchPtr(cond, lhs, rhs.valueReg(), label);
    787 }
    788 
    789 void MacroAssembler::branchTruncateDoubleMaybeModUint32(FloatRegister src,
    790                                                        Register dest,
    791                                                        Label* fail) {
    792  UseScratchRegisterScope temps(*this);
    793  Register scratch = temps.Acquire();
    794  as_truncld(ScratchDoubleReg, src);
    795  as_cfc1(scratch, Assembler::FCSR);
    796  moveFromDouble(ScratchDoubleReg, dest);
    797  ma_ext(scratch, scratch, Assembler::CauseV, 1);
    798  ma_b(scratch, Imm32(0), fail, Assembler::NotEqual);
    799 
    800  as_sll(dest, dest, 0);
    801 }
    802 
    803 void MacroAssembler::branchTruncateFloat32MaybeModUint32(FloatRegister src,
    804                                                         Register dest,
    805                                                         Label* fail) {
    806  UseScratchRegisterScope temps(*this);
    807  Register scratch = temps.Acquire();
    808  as_truncls(ScratchDoubleReg, src);
    809  as_cfc1(scratch, Assembler::FCSR);
    810  moveFromDouble(ScratchDoubleReg, dest);
    811  ma_ext(scratch, scratch, Assembler::CauseV, 1);
    812  ma_b(scratch, Imm32(0), fail, Assembler::NotEqual);
    813 
    814  as_sll(dest, dest, 0);
    815 }
    816 
    817 void MacroAssembler::branchTruncateDoubleToInt32(FloatRegister src,
    818                                                 Register dest, Label* fail) {
    819  UseScratchRegisterScope temps(*this);
    820  Register scratch = temps.Acquire();
    821  ScratchDoubleScope fpscratch(asMasm());
    822 
    823  // Convert scalar to signed 64-bit fixed-point, rounding toward zero.
    824  // In the case of -0, the output is zero.
    825  // In the case of overflow, the output is:
    826  //   - MIPS64R2: 2^63-1
    827  //   - MIPS64R6: saturated
    828  // In the case of NaN, the output is:
    829  //   - MIPS64R2: 2^63-1
    830  //   - MIPS64R6: 0
    831  as_truncld(fpscratch, src);
    832  moveFromDouble(fpscratch, dest);
    833 
    834  // Fail on overflow cases, besides MIPS64R2 will also fail here on NaN cases.
    835  as_sll(scratch, dest, 0);
    836  ma_b(dest, scratch, fail, Assembler::NotEqual);
    837 }
    838 
    839 void MacroAssembler::branchInt64NotInPtrRange(Register64 src, Label* label) {
    840  // No-op on 64-bit platforms.
    841 }
    842 
    843 void MacroAssembler::branchUInt64NotInPtrRange(Register64 src, Label* label) {
    844  branchTest64(Assembler::Signed, src, src, label);
    845 }
    846 
    847 void MacroAssembler::fallibleUnboxPtr(const ValueOperand& src, Register dest,
    848                                      JSValueType type, Label* fail) {
    849  MOZ_ASSERT(type == JSVAL_TYPE_OBJECT || type == JSVAL_TYPE_STRING ||
    850             type == JSVAL_TYPE_SYMBOL || type == JSVAL_TYPE_BIGINT);
    851  // dest := src XOR mask
    852  // scratch := dest >> JSVAL_TAG_SHIFT
    853  // fail if scratch != 0
    854  //
    855  // Note: src and dest can be the same register
    856  UseScratchRegisterScope temps(*this);
    857  Register scratch = temps.Acquire();
    858  mov(ImmShiftedTag(type), scratch);
    859  ma_xor(scratch, src.valueReg());
    860  ma_move(dest, scratch);
    861  ma_dsrl(scratch, scratch, Imm32(JSVAL_TAG_SHIFT));
    862  ma_b(scratch, Imm32(0), fail, Assembler::NotEqual);
    863 }
    864 
    865 void MacroAssembler::fallibleUnboxPtr(const Address& src, Register dest,
    866                                      JSValueType type, Label* fail) {
    867  loadValue(src, ValueOperand(dest));
    868  fallibleUnboxPtr(ValueOperand(dest), dest, type, fail);
    869 }
    870 
    871 void MacroAssembler::fallibleUnboxPtr(const BaseIndex& src, Register dest,
    872                                      JSValueType type, Label* fail) {
    873  loadValue(src, ValueOperand(dest));
    874  fallibleUnboxPtr(ValueOperand(dest), dest, type, fail);
    875 }
    876 
    877 //}}} check_macroassembler_style
    878 // ===============================================================
    879 
    880 // The specializations for cmpPtrSet are outside the braces because
    881 // check_macroassembler_style can't yet deal with specializations.
    882 
    883 template <>
    884 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs,
    885                                      ImmPtr rhs, Register dest) {
    886  UseScratchRegisterScope temps(*this);
    887  Register scratch2 = temps.Acquire();
    888  loadPtr(lhs, scratch2);
    889  cmpPtrSet(cond, scratch2, rhs, dest);
    890 }
    891 
    892 template <>
    893 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Register lhs,
    894                                      Address rhs, Register dest) {
    895  UseScratchRegisterScope temps(*this);
    896  Register scratch = temps.Acquire();
    897  loadPtr(rhs, scratch);
    898  cmpPtrSet(cond, lhs, scratch, dest);
    899 }
    900 
    901 template <>
    902 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs,
    903                                      Register rhs, Register dest) {
    904  UseScratchRegisterScope temps(*this);
    905  Register scratch = temps.Acquire();
    906  loadPtr(lhs, scratch);
    907  cmpPtrSet(cond, scratch, rhs, dest);
    908 }
    909 
    910 template <>
    911 inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Register lhs,
    912                                     Address rhs, Register dest) {
    913  UseScratchRegisterScope temps(*this);
    914  Register scratch = temps.Acquire();
    915  load32(rhs, scratch);
    916  cmp32Set(cond, lhs, scratch, dest);
    917 }
    918 
    919 template <>
    920 inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Address lhs,
    921                                     Register rhs, Register dest) {
    922  UseScratchRegisterScope temps(*this);
    923  Register scratch = temps.Acquire();
    924  load32(lhs, scratch);
    925  cmp32Set(cond, scratch, rhs, dest);
    926 }
    927 
    928 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, Register rhs,
    929                                   Register src, Register dest) {
    930  UseScratchRegisterScope temps(*this);
    931  Register scratch = temps.Acquire();
    932  MOZ_ASSERT(src != scratch && dest != scratch);
    933  cmpPtrSet(cond, lhs, rhs, scratch);
    934 #ifdef MIPSR6
    935  as_selnez(src, src, scratch);
    936  as_seleqz(dest, dest, scratch);
    937  as_or(dest, dest, src);
    938 #else
    939  as_movn(dest, src, scratch);
    940 #endif
    941 }
    942 
    943 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs,
    944                                   const Address& rhs, Register src,
    945                                   Register dest) {
    946  MOZ_CRASH("NYI");
    947 }
    948 
    949 void MacroAssemblerMIPS64Compat::incrementInt32Value(const Address& addr) {
    950  asMasm().add32(Imm32(1), addr);
    951 }
    952 
    953 void MacroAssemblerMIPS64Compat::retn(Imm32 n) {
    954  // pc <- [sp]; sp += n
    955  loadPtr(Address(StackPointer, 0), ra);
    956  asMasm().addPtr(n, StackPointer);
    957  as_jr(ra);
    958  as_nop();
    959 }
    960 
    961 }  // namespace jit
    962 }  // namespace js
    963 
    964 #endif /* jit_mips64_MacroAssembler_mips64_inl_h */