tor-browser

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

Assembler-loong64.h (70781B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef jit_loong64_Assembler_loong64_h
      8 #define jit_loong64_Assembler_loong64_h
      9 
     10 #include "mozilla/Sprintf.h"
     11 
     12 #include "jit/CompactBuffer.h"
     13 #include "jit/JitCode.h"
     14 #include "jit/JitSpewer.h"
     15 #include "jit/loong64/Architecture-loong64.h"
     16 #include "jit/shared/Assembler-shared.h"
     17 #include "jit/shared/Disassembler-shared.h"
     18 #include "jit/shared/IonAssemblerBuffer.h"
     19 #include "wasm/WasmTypeDecls.h"
     20 
     21 namespace js {
     22 namespace jit {
     23 
     24 static constexpr Register zero{Registers::zero};
     25 static constexpr Register ra{Registers::ra};
     26 static constexpr Register tp{Registers::tp};
     27 static constexpr Register sp{Registers::sp};
     28 static constexpr Register a0{Registers::a0};
     29 static constexpr Register a1{Registers::a1};
     30 static constexpr Register a2{Registers::a2};
     31 static constexpr Register a3{Registers::a3};
     32 static constexpr Register a4{Registers::a4};
     33 static constexpr Register a5{Registers::a5};
     34 static constexpr Register a6{Registers::a6};
     35 static constexpr Register a7{Registers::a7};
     36 static constexpr Register t0{Registers::t0};
     37 static constexpr Register t1{Registers::t1};
     38 static constexpr Register t2{Registers::t2};
     39 static constexpr Register t3{Registers::t3};
     40 static constexpr Register t4{Registers::t4};
     41 static constexpr Register t5{Registers::t5};
     42 static constexpr Register t6{Registers::t6};
     43 static constexpr Register t7{Registers::t7};
     44 static constexpr Register t8{Registers::t8};
     45 static constexpr Register rx{Registers::rx};
     46 static constexpr Register fp{Registers::fp};
     47 static constexpr Register s0{Registers::s0};
     48 static constexpr Register s1{Registers::s1};
     49 static constexpr Register s2{Registers::s2};
     50 static constexpr Register s3{Registers::s3};
     51 static constexpr Register s4{Registers::s4};
     52 static constexpr Register s5{Registers::s5};
     53 static constexpr Register s6{Registers::s6};
     54 static constexpr Register s7{Registers::s7};
     55 static constexpr Register s8{Registers::s8};
     56 
     57 static constexpr FloatRegister f0{FloatRegisters::f0, FloatRegisters::Double};
     58 static constexpr FloatRegister f1{FloatRegisters::f1, FloatRegisters::Double};
     59 static constexpr FloatRegister f2{FloatRegisters::f2, FloatRegisters::Double};
     60 static constexpr FloatRegister f3{FloatRegisters::f3, FloatRegisters::Double};
     61 static constexpr FloatRegister f4{FloatRegisters::f4, FloatRegisters::Double};
     62 static constexpr FloatRegister f5{FloatRegisters::f5, FloatRegisters::Double};
     63 static constexpr FloatRegister f6{FloatRegisters::f6, FloatRegisters::Double};
     64 static constexpr FloatRegister f7{FloatRegisters::f7, FloatRegisters::Double};
     65 static constexpr FloatRegister f8{FloatRegisters::f8, FloatRegisters::Double};
     66 static constexpr FloatRegister f9{FloatRegisters::f9, FloatRegisters::Double};
     67 static constexpr FloatRegister f10{FloatRegisters::f10, FloatRegisters::Double};
     68 static constexpr FloatRegister f11{FloatRegisters::f11, FloatRegisters::Double};
     69 static constexpr FloatRegister f12{FloatRegisters::f12, FloatRegisters::Double};
     70 static constexpr FloatRegister f13{FloatRegisters::f13, FloatRegisters::Double};
     71 static constexpr FloatRegister f14{FloatRegisters::f14, FloatRegisters::Double};
     72 static constexpr FloatRegister f15{FloatRegisters::f15, FloatRegisters::Double};
     73 static constexpr FloatRegister f16{FloatRegisters::f16, FloatRegisters::Double};
     74 static constexpr FloatRegister f17{FloatRegisters::f17, FloatRegisters::Double};
     75 static constexpr FloatRegister f18{FloatRegisters::f18, FloatRegisters::Double};
     76 static constexpr FloatRegister f19{FloatRegisters::f19, FloatRegisters::Double};
     77 static constexpr FloatRegister f20{FloatRegisters::f20, FloatRegisters::Double};
     78 static constexpr FloatRegister f21{FloatRegisters::f21, FloatRegisters::Double};
     79 static constexpr FloatRegister f22{FloatRegisters::f22, FloatRegisters::Double};
     80 static constexpr FloatRegister f23{FloatRegisters::f23, FloatRegisters::Double};
     81 static constexpr FloatRegister f24{FloatRegisters::f24, FloatRegisters::Double};
     82 static constexpr FloatRegister f25{FloatRegisters::f25, FloatRegisters::Double};
     83 static constexpr FloatRegister f26{FloatRegisters::f26, FloatRegisters::Double};
     84 static constexpr FloatRegister f27{FloatRegisters::f27, FloatRegisters::Double};
     85 static constexpr FloatRegister f28{FloatRegisters::f28, FloatRegisters::Double};
     86 static constexpr FloatRegister f29{FloatRegisters::f29, FloatRegisters::Double};
     87 static constexpr FloatRegister f30{FloatRegisters::f30, FloatRegisters::Double};
     88 static constexpr FloatRegister f31{FloatRegisters::f31, FloatRegisters::Double};
     89 
     90 static constexpr Register InvalidReg{Registers::Invalid};
     91 static constexpr FloatRegister InvalidFloatReg;
     92 
     93 static constexpr Register StackPointer = sp;
     94 static constexpr Register FramePointer = fp;
     95 static constexpr Register ReturnReg = a0;
     96 static constexpr Register64 ReturnReg64(ReturnReg);
     97 static constexpr FloatRegister ReturnFloat32Reg{FloatRegisters::f0,
     98                                                FloatRegisters::Single};
     99 static constexpr FloatRegister ReturnDoubleReg = f0;
    100 static constexpr FloatRegister ReturnSimd128Reg = InvalidFloatReg;
    101 
    102 // Scratch register used for runtime call patching.
    103 // See MacroAssembler::patchNopToCall and MacroAssembler::PatchWrite_NearCall.
    104 static constexpr Register SavedScratchRegister = s8;
    105 
    106 static constexpr FloatRegister ScratchFloat32Reg{FloatRegisters::f23,
    107                                                 FloatRegisters::Single};
    108 static constexpr FloatRegister ScratchDoubleReg = f23;
    109 static constexpr FloatRegister ScratchSimd128Reg = InvalidFloatReg;
    110 
    111 struct ScratchFloat32Scope : public AutoFloatRegisterScope {
    112  explicit ScratchFloat32Scope(MacroAssembler& masm)
    113      : AutoFloatRegisterScope(masm, ScratchFloat32Reg) {}
    114 };
    115 
    116 struct ScratchDoubleScope : public AutoFloatRegisterScope {
    117  explicit ScratchDoubleScope(MacroAssembler& masm)
    118      : AutoFloatRegisterScope(masm, ScratchDoubleReg) {}
    119 };
    120 
    121 class Assembler;
    122 
    123 class UseScratchRegisterScope {
    124 public:
    125  explicit UseScratchRegisterScope(Assembler& assembler);
    126  explicit UseScratchRegisterScope(Assembler* assembler);
    127  ~UseScratchRegisterScope();
    128 
    129  Register Acquire();
    130  void Release(const Register& reg);
    131  bool hasAvailable() const;
    132  void Include(const GeneralRegisterSet& list) {
    133    *available_ = GeneralRegisterSet::Union(*available_, list);
    134  }
    135  void Exclude(const GeneralRegisterSet& list) {
    136    *available_ = GeneralRegisterSet::Subtract(*available_, list);
    137  }
    138 
    139 private:
    140  GeneralRegisterSet* available_;
    141  GeneralRegisterSet old_available_;
    142 };
    143 
    144 // Use arg reg from EnterJIT function as OsrFrameReg.
    145 static constexpr Register OsrFrameReg = a3;
    146 static constexpr Register PreBarrierReg = a1;
    147 static constexpr Register InterpreterPCReg = t0;
    148 static constexpr Register CallTempReg0 = t0;
    149 static constexpr Register CallTempReg1 = t1;
    150 static constexpr Register CallTempReg2 = t2;
    151 static constexpr Register CallTempReg3 = t3;
    152 static constexpr Register CallTempReg4 = t4;
    153 static constexpr Register CallTempReg5 = t5;
    154 static constexpr Register CallTempNonArgRegs[] = {t0, t1, t2, t3};
    155 static const uint32_t NumCallTempNonArgRegs = std::size(CallTempNonArgRegs);
    156 
    157 static constexpr Register IntArgReg0 = a0;
    158 static constexpr Register IntArgReg1 = a1;
    159 static constexpr Register IntArgReg2 = a2;
    160 static constexpr Register IntArgReg3 = a3;
    161 static constexpr Register IntArgReg4 = a4;
    162 static constexpr Register IntArgReg5 = a5;
    163 static constexpr Register IntArgReg6 = a6;
    164 static constexpr Register IntArgReg7 = a7;
    165 
    166 // Registers used by RegExpMatcher and RegExpExecMatch stubs (do not use
    167 // JSReturnOperand).
    168 static constexpr Register RegExpMatcherRegExpReg = CallTempReg0;
    169 static constexpr Register RegExpMatcherStringReg = CallTempReg1;
    170 static constexpr Register RegExpMatcherLastIndexReg = CallTempReg2;
    171 
    172 // Registers used by RegExpExecTest stub (do not use ReturnReg).
    173 static constexpr Register RegExpExecTestRegExpReg = CallTempReg0;
    174 static constexpr Register RegExpExecTestStringReg = CallTempReg1;
    175 
    176 // Registers used by RegExpSearcher stub (do not use ReturnReg).
    177 static constexpr Register RegExpSearcherRegExpReg = CallTempReg0;
    178 static constexpr Register RegExpSearcherStringReg = CallTempReg1;
    179 static constexpr Register RegExpSearcherLastIndexReg = CallTempReg2;
    180 
    181 static constexpr Register JSReturnReg_Type = a3;
    182 static constexpr Register JSReturnReg_Data = a2;
    183 static constexpr Register JSReturnReg = a2;
    184 static constexpr ValueOperand JSReturnOperand = ValueOperand(JSReturnReg);
    185 
    186 // See "ABI special registers" in Assembler-shared.h for more information.
    187 static constexpr Register ABINonArgReg0 = t0;
    188 static constexpr Register ABINonArgReg1 = t1;
    189 static constexpr Register ABINonArgReg2 = t2;
    190 static constexpr Register ABINonArgReg3 = t3;
    191 
    192 // See "ABI special registers" in Assembler-shared.h for more information.
    193 static constexpr Register ABINonArgReturnReg0 = t0;
    194 static constexpr Register ABINonArgReturnReg1 = t1;
    195 static constexpr Register ABINonVolatileReg = s0;
    196 
    197 // See "ABI special registers" in Assembler-shared.h for more information.
    198 static constexpr Register ABINonArgReturnVolatileReg = ra;
    199 
    200 // See "ABI special registers" in Assembler-shared.h for more information.
    201 // Avoid f23 which is the scratch register.
    202 static constexpr FloatRegister ABINonArgDoubleReg{FloatRegisters::f21,
    203                                                  FloatRegisters::Double};
    204 
    205 // See "ABI special registers" in Assembler-shared.h, and "The WASM ABIs" in
    206 // WasmFrame.h for more information.
    207 static constexpr Register InstanceReg = s4;
    208 static constexpr Register HeapReg = s7;
    209 
    210 // Registers used for wasm table calls. These registers must be disjoint
    211 // from the ABI argument registers, InstanceReg and each other.
    212 static constexpr Register WasmTableCallScratchReg0 = ABINonArgReg0;
    213 static constexpr Register WasmTableCallScratchReg1 = ABINonArgReg1;
    214 static constexpr Register WasmTableCallSigReg = ABINonArgReg2;
    215 static constexpr Register WasmTableCallIndexReg = ABINonArgReg3;
    216 
    217 // Registers used for ref calls.
    218 static constexpr Register WasmCallRefCallScratchReg0 = ABINonArgReg0;
    219 static constexpr Register WasmCallRefCallScratchReg1 = ABINonArgReg1;
    220 static constexpr Register WasmCallRefCallScratchReg2 = ABINonArgReg2;
    221 static constexpr Register WasmCallRefReg = ABINonArgReg3;
    222 
    223 // Registers used for wasm tail calls operations.
    224 static constexpr Register WasmTailCallInstanceScratchReg = ABINonArgReg1;
    225 static constexpr Register WasmTailCallRAScratchReg = ra;
    226 static constexpr Register WasmTailCallFPScratchReg = ABINonArgReg3;
    227 
    228 // Register used as a scratch along the return path in the fast js -> wasm stub
    229 // code. This must not overlap ReturnReg, JSReturnOperand, or InstanceReg.
    230 // It must be a volatile register.
    231 static constexpr Register WasmJitEntryReturnScratch = t1;
    232 
    233 static constexpr uint32_t ABIStackAlignment = 16;
    234 static constexpr uint32_t CodeAlignment = 16;
    235 static constexpr uint32_t JitStackAlignment = 16;
    236 
    237 static constexpr uint32_t JitStackValueAlignment =
    238    JitStackAlignment / sizeof(Value);
    239 static_assert(JitStackAlignment % sizeof(Value) == 0 &&
    240                  JitStackValueAlignment >= 1,
    241              "Stack alignment should be a non-zero multiple of sizeof(Value)");
    242 
    243 // TODO(loong64): this is just a filler to prevent a build failure. The
    244 // LoongArch SIMD alignment requirements still need to be explored.
    245 static constexpr uint32_t SimdMemoryAlignment = 16;
    246 
    247 static_assert(CodeAlignment % SimdMemoryAlignment == 0,
    248              "Code alignment should be larger than any of the alignments "
    249              "which are used for "
    250              "the constant sections of the code buffer.  Thus it should be "
    251              "larger than the "
    252              "alignment for SIMD constants.");
    253 
    254 static constexpr uint32_t WasmStackAlignment = SimdMemoryAlignment;
    255 static const uint32_t WasmTrapInstructionLength = 4;
    256 
    257 // See comments in wasm::GenerateFunctionPrologue.  The difference between these
    258 // is the size of the largest callable prologue on the platform.
    259 static constexpr uint32_t WasmCheckedCallEntryOffset = 0u;
    260 
    261 static constexpr Scale ScalePointer = TimesEight;
    262 
    263 // TODO(loong64): Add LoongArch instruction types description.
    264 
    265 // LoongArch instruction encoding constants.
    266 static const uint32_t RJShift = 5;
    267 static const uint32_t RJBits = 5;
    268 static const uint32_t RKShift = 10;
    269 static const uint32_t RKBits = 5;
    270 static const uint32_t RDShift = 0;
    271 static const uint32_t RDBits = 5;
    272 static const uint32_t FJShift = 5;
    273 static const uint32_t FJBits = 5;
    274 static const uint32_t FKShift = 10;
    275 static const uint32_t FKBits = 5;
    276 static const uint32_t FDShift = 0;
    277 static const uint32_t FDBits = 5;
    278 static const uint32_t FAShift = 15;
    279 static const uint32_t FABits = 5;
    280 static const uint32_t CJShift = 5;
    281 static const uint32_t CJBits = 3;
    282 static const uint32_t CDShift = 0;
    283 static const uint32_t CDBits = 3;
    284 static const uint32_t CAShift = 15;
    285 static const uint32_t CABits = 3;
    286 static const uint32_t CONDShift = 15;
    287 static const uint32_t CONDBits = 5;
    288 
    289 static const uint32_t SAShift = 15;
    290 static const uint32_t SA2Bits = 2;
    291 static const uint32_t SA3Bits = 3;
    292 static const uint32_t LSBWShift = 10;
    293 static const uint32_t LSBWBits = 5;
    294 static const uint32_t LSBDShift = 10;
    295 static const uint32_t LSBDBits = 6;
    296 static const uint32_t MSBWShift = 16;
    297 static const uint32_t MSBWBits = 5;
    298 static const uint32_t MSBDShift = 16;
    299 static const uint32_t MSBDBits = 6;
    300 static const uint32_t Imm5Shift = 10;
    301 static const uint32_t Imm5Bits = 5;
    302 static const uint32_t Imm6Shift = 10;
    303 static const uint32_t Imm6Bits = 6;
    304 static const uint32_t Imm12Shift = 10;
    305 static const uint32_t Imm12Bits = 12;
    306 static const uint32_t Imm14Shift = 10;
    307 static const uint32_t Imm14Bits = 14;
    308 static const uint32_t Imm15Shift = 0;
    309 static const uint32_t Imm15Bits = 15;
    310 static const uint32_t Imm16Shift = 10;
    311 static const uint32_t Imm16Bits = 16;
    312 static const uint32_t Imm20Shift = 5;
    313 static const uint32_t Imm20Bits = 20;
    314 static const uint32_t Imm21Shift = 0;
    315 static const uint32_t Imm21Bits = 21;
    316 static const uint32_t Imm26Shift = 0;
    317 static const uint32_t Imm26Bits = 26;
    318 static const uint32_t CODEShift = 0;
    319 static const uint32_t CODEBits = 15;
    320 static const uint32_t HINTBits = 5;
    321 
    322 // LoongArch instruction field bit masks.
    323 static const uint32_t RJMask = (1 << RJBits) - 1;
    324 static const uint32_t RKMask = (1 << RKBits) - 1;
    325 static const uint32_t RDMask = (1 << RDBits) - 1;
    326 static const uint32_t SA2Mask = (1 << SA2Bits) - 1;
    327 static const uint32_t SA3Mask = (1 << SA3Bits) - 1;
    328 static const uint32_t CDMask = (1 << CDBits) - 1;
    329 static const uint32_t CONDMask = (1 << CONDBits) - 1;
    330 static const uint32_t HINTMask = (1 << HINTBits) - 1;
    331 static const uint32_t LSBWMask = (1 << LSBWBits) - 1;
    332 static const uint32_t LSBDMask = (1 << LSBDBits) - 1;
    333 static const uint32_t MSBWMask = (1 << MSBWBits) - 1;
    334 static const uint32_t MSBDMask = (1 << MSBDBits) - 1;
    335 static const uint32_t CODEMask = (1 << CODEBits) - 1;
    336 static const uint32_t Imm5Mask = (1 << Imm5Bits) - 1;
    337 static const uint32_t Imm6Mask = (1 << Imm6Bits) - 1;
    338 static const uint32_t Imm12Mask = (1 << Imm12Bits) - 1;
    339 static const uint32_t Imm14Mask = (1 << Imm14Bits) - 1;
    340 static const uint32_t Imm15Mask = (1 << Imm15Bits) - 1;
    341 static const uint32_t Imm16Mask = (1 << Imm16Bits) - 1;
    342 static const uint32_t Imm20Mask = (1 << Imm20Bits) - 1;
    343 static const uint32_t Imm21Mask = (1 << Imm21Bits) - 1;
    344 static const uint32_t Imm26Mask = (1 << Imm26Bits) - 1;
    345 static const uint32_t BOffImm16Mask = ((1 << Imm16Bits) - 1) << Imm16Shift;
    346 static const uint32_t BOffImm21Mask = ((1 << Imm21Bits) - 1) << Imm21Shift;
    347 static const uint32_t BOffImm26Mask = ((1 << Imm26Bits) - 1) << Imm26Shift;
    348 static const uint32_t RegMask = Registers::Total - 1;
    349 
    350 // TODO(loong64) Change to syscall?
    351 static const uint32_t MAX_BREAK_CODE = 1024 - 1;
    352 static const uint32_t WASM_TRAP = 6;  // BRK_OVERFLOW
    353 
    354 // TODO(loong64) Change to LoongArch instruction type.
    355 class Instruction;
    356 class InstReg;
    357 class InstImm;
    358 class InstJump;
    359 
    360 uint32_t RJ(Register r);
    361 uint32_t RK(Register r);
    362 uint32_t RD(Register r);
    363 uint32_t FJ(FloatRegister r);
    364 uint32_t FK(FloatRegister r);
    365 uint32_t FD(FloatRegister r);
    366 uint32_t FA(FloatRegister r);
    367 uint32_t SA2(uint32_t value);
    368 uint32_t SA2(FloatRegister r);
    369 uint32_t SA3(uint32_t value);
    370 uint32_t SA3(FloatRegister r);
    371 
    372 Register toRK(Instruction& i);
    373 Register toRJ(Instruction& i);
    374 Register toRD(Instruction& i);
    375 Register toR(Instruction& i);
    376 
    377 // LoongArch enums for instruction fields
    378 enum OpcodeField {
    379  op_beqz = 0x10U << 26,
    380  op_bnez = 0x11U << 26,
    381  op_bcz = 0x12U << 26,  // bceqz & bcnez
    382  op_jirl = 0x13U << 26,
    383  op_b = 0x14U << 26,
    384  op_bl = 0x15U << 26,
    385  op_beq = 0x16U << 26,
    386  op_bne = 0x17U << 26,
    387  op_blt = 0x18U << 26,
    388  op_bge = 0x19U << 26,
    389  op_bltu = 0x1aU << 26,
    390  op_bgeu = 0x1bU << 26,
    391 
    392  op_addu16i_d = 0x4U << 26,
    393 
    394  op_lu12i_w = 0xaU << 25,
    395  op_lu32i_d = 0xbU << 25,
    396  op_pcaddi = 0xcU << 25,
    397  op_pcalau12i = 0xdU << 25,
    398  op_pcaddu12i = 0xeU << 25,
    399  op_pcaddu18i = 0xfU << 25,
    400  op_ll_w = 0x20U << 24,
    401  op_sc_w = 0x21U << 24,
    402  op_ll_d = 0x22U << 24,
    403  op_sc_d = 0x23U << 24,
    404  op_ldptr_w = 0x24U << 24,
    405  op_stptr_w = 0x25U << 24,
    406  op_ldptr_d = 0x26U << 24,
    407  op_stptr_d = 0x27U << 24,
    408  op_bstrins_d = 0x2U << 22,
    409  op_bstrpick_d = 0x3U << 22,
    410  op_slti = 0x8U << 22,
    411  op_sltui = 0x9U << 22,
    412  op_addi_w = 0xaU << 22,
    413  op_addi_d = 0xbU << 22,
    414  op_lu52i_d = 0xcU << 22,
    415  op_andi = 0xdU << 22,
    416  op_ori = 0xeU << 22,
    417  op_xori = 0xfU << 22,
    418  op_ld_b = 0xa0U << 22,
    419  op_ld_h = 0xa1U << 22,
    420  op_ld_w = 0xa2U << 22,
    421  op_ld_d = 0xa3U << 22,
    422  op_st_b = 0xa4U << 22,
    423  op_st_h = 0xa5U << 22,
    424  op_st_w = 0xa6U << 22,
    425  op_st_d = 0xa7U << 22,
    426  op_ld_bu = 0xa8U << 22,
    427  op_ld_hu = 0xa9U << 22,
    428  op_ld_wu = 0xaaU << 22,
    429  op_preld = 0xabU << 22,
    430  op_fld_s = 0xacU << 22,
    431  op_fst_s = 0xadU << 22,
    432  op_fld_d = 0xaeU << 22,
    433  op_fst_d = 0xafU << 22,
    434  op_bstr_w = 0x3U << 21,  // BSTRINS_W & BSTRPICK_W
    435  op_fmadd_s = 0x81U << 20,
    436  op_fmadd_d = 0x82U << 20,
    437  op_fmsub_s = 0x85U << 20,
    438  op_fmsub_d = 0x86U << 20,
    439  op_fnmadd_s = 0x89U << 20,
    440  op_fnmadd_d = 0x8aU << 20,
    441  op_fnmsub_s = 0x8dU << 20,
    442  op_fnmsub_d = 0x8eU << 20,
    443  op_fcmp_cond_s = 0xc1U << 20,
    444  op_fcmp_cond_d = 0xc2U << 20,
    445 
    446  op_bytepick_d = 0x3U << 18,
    447  op_fsel = 0x340U << 18,
    448 
    449  op_bytepick_w = 0x4U << 17,
    450  op_alsl_w = 0x2U << 17,
    451  op_alsl_wu = 0x3U << 17,
    452  op_alsl_d = 0x16U << 17,
    453 
    454  op_slli_d = 0x41U << 16,
    455  op_srli_d = 0x45U << 16,
    456  op_srai_d = 0x49U << 16,
    457 
    458  op_slli_w = 0x81U << 15,
    459  op_srli_w = 0x89U << 15,
    460  op_srai_w = 0x91U << 15,
    461  op_add_w = 0x20U << 15,
    462  op_add_d = 0x21U << 15,
    463  op_sub_w = 0x22U << 15,
    464  op_sub_d = 0x23U << 15,
    465  op_slt = 0x24U << 15,
    466  op_sltu = 0x25U << 15,
    467  op_maskeqz = 0x26U << 15,
    468  op_masknez = 0x27U << 15,
    469  op_nor = 0x28U << 15,
    470  op_and = 0x29U << 15,
    471  op_or = 0x2aU << 15,
    472  op_xor = 0x2bU << 15,
    473  op_orn = 0x2cU << 15,
    474  op_andn = 0x2dU << 15,
    475  op_sll_w = 0x2eU << 15,
    476  op_srl_w = 0x2fU << 15,
    477  op_sra_w = 0x30U << 15,
    478  op_sll_d = 0x31U << 15,
    479  op_srl_d = 0x32U << 15,
    480  op_sra_d = 0x33U << 15,
    481  op_rotr_w = 0x36U << 15,
    482  op_rotr_d = 0x37U << 15,
    483  op_rotri_w = 0x99U << 15,
    484  op_rotri_d = 0x4DU << 16,
    485  op_mul_w = 0x38U << 15,
    486  op_mulh_w = 0x39U << 15,
    487  op_mulh_wu = 0x3aU << 15,
    488  op_mul_d = 0x3bU << 15,
    489  op_mulh_d = 0x3cU << 15,
    490  op_mulh_du = 0x3dU << 15,
    491  op_mulw_d_w = 0x3eU << 15,
    492  op_mulw_d_wu = 0x3fU << 15,
    493  op_div_w = 0x40U << 15,
    494  op_mod_w = 0x41U << 15,
    495  op_div_wu = 0x42U << 15,
    496  op_mod_wu = 0x43U << 15,
    497  op_div_d = 0x44U << 15,
    498  op_mod_d = 0x45U << 15,
    499  op_div_du = 0x46U << 15,
    500  op_mod_du = 0x47U << 15,
    501  op_break = 0x54U << 15,
    502  op_syscall = 0x56U << 15,
    503  op_fadd_s = 0x201U << 15,
    504  op_fadd_d = 0x202U << 15,
    505  op_fsub_s = 0x205U << 15,
    506  op_fsub_d = 0x206U << 15,
    507  op_fmul_s = 0x209U << 15,
    508  op_fmul_d = 0x20aU << 15,
    509  op_fdiv_s = 0x20dU << 15,
    510  op_fdiv_d = 0x20eU << 15,
    511  op_fmax_s = 0x211U << 15,
    512  op_fmax_d = 0x212U << 15,
    513  op_fmin_s = 0x215U << 15,
    514  op_fmin_d = 0x216U << 15,
    515  op_fmaxa_s = 0x219U << 15,
    516  op_fmaxa_d = 0x21aU << 15,
    517  op_fmina_s = 0x21dU << 15,
    518  op_fmina_d = 0x21eU << 15,
    519  op_fcopysign_s = 0x225U << 15,
    520  op_fcopysign_d = 0x226U << 15,
    521  op_ldx_b = 0x7000U << 15,
    522  op_ldx_h = 0x7008U << 15,
    523  op_ldx_w = 0x7010U << 15,
    524  op_ldx_d = 0x7018U << 15,
    525  op_stx_b = 0x7020U << 15,
    526  op_stx_h = 0x7028U << 15,
    527  op_stx_w = 0x7030U << 15,
    528  op_stx_d = 0x7038U << 15,
    529  op_ldx_bu = 0x7040U << 15,
    530  op_ldx_hu = 0x7048U << 15,
    531  op_ldx_wu = 0x7050U << 15,
    532  op_fldx_s = 0x7060U << 15,
    533  op_fldx_d = 0x7068U << 15,
    534  op_fstx_s = 0x7070U << 15,
    535  op_fstx_d = 0x7078U << 15,
    536  op_amswap_w = 0x70c0U << 15,
    537  op_amswap_d = 0x70c1U << 15,
    538  op_amadd_w = 0x70c2U << 15,
    539  op_amadd_d = 0x70c3U << 15,
    540  op_amand_w = 0x70c4U << 15,
    541  op_amand_d = 0x70c5U << 15,
    542  op_amor_w = 0x70c6U << 15,
    543  op_amor_d = 0x70c7U << 15,
    544  op_amxor_w = 0x70c8U << 15,
    545  op_amxor_d = 0x70c9U << 15,
    546  op_ammax_w = 0x70caU << 15,
    547  op_ammax_d = 0x70cbU << 15,
    548  op_ammin_w = 0x70ccU << 15,
    549  op_ammin_d = 0x70cdU << 15,
    550  op_ammax_wu = 0x70ceU << 15,
    551  op_ammax_du = 0x70cfU << 15,
    552  op_ammin_wu = 0x70d0U << 15,
    553  op_ammin_du = 0x70d1U << 15,
    554  op_amswap_db_w = 0x70d2U << 15,
    555  op_amswap_db_d = 0x70d3U << 15,
    556  op_amadd_db_w = 0x70d4U << 15,
    557  op_amadd_db_d = 0x70d5U << 15,
    558  op_amand_db_w = 0x70d6U << 15,
    559  op_amand_db_d = 0x70d7U << 15,
    560  op_amor_db_w = 0x70d8U << 15,
    561  op_amor_db_d = 0x70d9U << 15,
    562  op_amxor_db_w = 0x70daU << 15,
    563  op_amxor_db_d = 0x70dbU << 15,
    564  op_ammax_db_w = 0x70dcU << 15,
    565  op_ammax_db_d = 0x70ddU << 15,
    566  op_ammin_db_w = 0x70deU << 15,
    567  op_ammin_db_d = 0x70dfU << 15,
    568  op_ammax_db_wu = 0x70e0U << 15,
    569  op_ammax_db_du = 0x70e1U << 15,
    570  op_ammin_db_wu = 0x70e2U << 15,
    571  op_ammin_db_du = 0x70e3U << 15,
    572  op_dbar = 0x70e4U << 15,
    573  op_ibar = 0x70e5U << 15,
    574  op_clo_w = 0x4U << 10,
    575  op_clz_w = 0x5U << 10,
    576  op_cto_w = 0x6U << 10,
    577  op_ctz_w = 0x7U << 10,
    578  op_clo_d = 0x8U << 10,
    579  op_clz_d = 0x9U << 10,
    580  op_cto_d = 0xaU << 10,
    581  op_ctz_d = 0xbU << 10,
    582  op_revb_2h = 0xcU << 10,
    583  op_revb_4h = 0xdU << 10,
    584  op_revb_2w = 0xeU << 10,
    585  op_revb_d = 0xfU << 10,
    586  op_revh_2w = 0x10U << 10,
    587  op_revh_d = 0x11U << 10,
    588  op_bitrev_4b = 0x12U << 10,
    589  op_bitrev_8b = 0x13U << 10,
    590  op_bitrev_w = 0x14U << 10,
    591  op_bitrev_d = 0x15U << 10,
    592  op_ext_w_h = 0x16U << 10,
    593  op_ext_w_b = 0x17U << 10,
    594  op_fabs_s = 0x4501U << 10,
    595  op_fabs_d = 0x4502U << 10,
    596  op_fneg_s = 0x4505U << 10,
    597  op_fneg_d = 0x4506U << 10,
    598  op_fsqrt_s = 0x4511U << 10,
    599  op_fsqrt_d = 0x4512U << 10,
    600  op_fmov_s = 0x4525U << 10,
    601  op_fmov_d = 0x4526U << 10,
    602  op_movgr2fr_w = 0x4529U << 10,
    603  op_movgr2fr_d = 0x452aU << 10,
    604  op_movgr2frh_w = 0x452bU << 10,
    605  op_movfr2gr_s = 0x452dU << 10,
    606  op_movfr2gr_d = 0x452eU << 10,
    607  op_movfrh2gr_s = 0x452fU << 10,
    608  op_movgr2fcsr = 0x4530U << 10,
    609  op_movfcsr2gr = 0x4532U << 10,
    610  op_movfr2cf = 0x4534U << 10,
    611  op_movgr2cf = 0x4536U << 10,
    612  op_fcvt_s_d = 0x4646U << 10,
    613  op_fcvt_d_s = 0x4649U << 10,
    614  op_ftintrm_w_s = 0x4681U << 10,
    615  op_ftintrm_w_d = 0x4682U << 10,
    616  op_ftintrm_l_s = 0x4689U << 10,
    617  op_ftintrm_l_d = 0x468aU << 10,
    618  op_ftintrp_w_s = 0x4691U << 10,
    619  op_ftintrp_w_d = 0x4692U << 10,
    620  op_ftintrp_l_s = 0x4699U << 10,
    621  op_ftintrp_l_d = 0x469aU << 10,
    622  op_ftintrz_w_s = 0x46a1U << 10,
    623  op_ftintrz_w_d = 0x46a2U << 10,
    624  op_ftintrz_l_s = 0x46a9U << 10,
    625  op_ftintrz_l_d = 0x46aaU << 10,
    626  op_ftintrne_w_s = 0x46b1U << 10,
    627  op_ftintrne_w_d = 0x46b2U << 10,
    628  op_ftintrne_l_s = 0x46b9U << 10,
    629  op_ftintrne_l_d = 0x46baU << 10,
    630  op_ftint_w_s = 0x46c1U << 10,
    631  op_ftint_w_d = 0x46c2U << 10,
    632  op_ftint_l_s = 0x46c9U << 10,
    633  op_ftint_l_d = 0x46caU << 10,
    634  op_ffint_s_w = 0x4744U << 10,
    635  op_ffint_s_l = 0x4746U << 10,
    636  op_ffint_d_w = 0x4748U << 10,
    637  op_ffint_d_l = 0x474aU << 10,
    638  op_frint_s = 0x4791U << 10,
    639  op_frint_d = 0x4792U << 10,
    640  op_movcf2fr = 0x114d4U << 8,
    641  op_movcf2gr = 0x114dcU << 8,
    642 };
    643 
    644 class Operand;
    645 
    646 // A BOffImm16 is a 16 bit immediate that is used for branches.
    647 class BOffImm16 {
    648  uint32_t data;
    649 
    650 public:
    651  uint32_t encode() {
    652    MOZ_ASSERT(!isInvalid());
    653    return data;
    654  }
    655  int32_t decode() {
    656    MOZ_ASSERT(!isInvalid());
    657    return (int32_t(data << 18) >> 16);
    658  }
    659 
    660  explicit BOffImm16(int offset) : data((offset) >> 2 & Imm16Mask) {
    661    MOZ_ASSERT((offset & 0x3) == 0);
    662    MOZ_ASSERT(IsInRange(offset));
    663  }
    664  static bool IsInRange(int offset) {
    665    if ((offset) < int(unsigned(INT16_MIN) << 2)) {
    666      return false;
    667    }
    668    if ((offset) > (INT16_MAX << 2)) {
    669      return false;
    670    }
    671    return true;
    672  }
    673  static const uint32_t INVALID = 0x00020000;
    674  BOffImm16() : data(INVALID) {}
    675 
    676  bool isInvalid() { return data == INVALID; }
    677  Instruction* getDest(Instruction* src) const;
    678 
    679  explicit BOffImm16(InstImm inst);
    680 };
    681 
    682 // A JOffImm26 is a 26 bit immediate that is used for unconditional jumps.
    683 class JOffImm26 {
    684  uint32_t data;
    685 
    686 public:
    687  uint32_t encode() {
    688    MOZ_ASSERT(!isInvalid());
    689    return data;
    690  }
    691  int32_t decode() {
    692    MOZ_ASSERT(!isInvalid());
    693    return (int32_t(data << 8) >> 6);
    694  }
    695 
    696  explicit JOffImm26(int offset) : data((offset) >> 2 & Imm26Mask) {
    697    MOZ_ASSERT((offset & 0x3) == 0);
    698    MOZ_ASSERT(IsInRange(offset));
    699  }
    700  static bool IsInRange(int offset) {
    701    if ((offset) < -536870912) {
    702      return false;
    703    }
    704    if ((offset) > 536870908) {
    705      return false;
    706    }
    707    return true;
    708  }
    709  static const uint32_t INVALID = 0x20000000;
    710  JOffImm26() : data(INVALID) {}
    711 
    712  bool isInvalid() { return data == INVALID; }
    713  Instruction* getDest(Instruction* src);
    714 };
    715 
    716 class Imm16 {
    717  uint16_t value;
    718 
    719 public:
    720  Imm16();
    721  explicit Imm16(uint32_t imm) : value(imm) {}
    722  uint32_t encode() { return value; }
    723  int32_t decodeSigned() { return value; }
    724  uint32_t decodeUnsigned() { return value; }
    725 
    726  static bool IsInSignedRange(int32_t imm) {
    727    return imm >= INT16_MIN && imm <= INT16_MAX;
    728  }
    729 
    730  static bool IsInUnsignedRange(uint32_t imm) { return imm <= UINT16_MAX; }
    731 };
    732 
    733 class Imm8 {
    734  uint8_t value;
    735 
    736 public:
    737  Imm8();
    738  explicit Imm8(uint32_t imm) : value(imm) {}
    739  uint32_t encode(uint32_t shift) { return value << shift; }
    740  int32_t decodeSigned() { return value; }
    741  uint32_t decodeUnsigned() { return value; }
    742  static bool IsInSignedRange(int32_t imm) {
    743    return imm >= INT8_MIN && imm <= INT8_MAX;
    744  }
    745  static bool IsInUnsignedRange(uint32_t imm) { return imm <= UINT8_MAX; }
    746  static Imm8 Lower(Imm16 imm) { return Imm8(imm.decodeSigned() & 0xff); }
    747  static Imm8 Upper(Imm16 imm) {
    748    return Imm8((imm.decodeSigned() >> 8) & 0xff);
    749  }
    750 };
    751 
    752 class Operand {
    753 public:
    754  enum Tag { REG, FREG, MEM };
    755 
    756 private:
    757  Tag tag : 3;
    758  uint32_t reg : 5;
    759  int32_t offset;
    760 
    761 public:
    762  MOZ_IMPLICIT Operand(Register reg_) : tag(REG), reg(reg_.code()) {}
    763 
    764  explicit Operand(FloatRegister freg) : tag(FREG), reg(freg.code()) {}
    765 
    766  Operand(Register base, Imm32 off)
    767      : tag(MEM), reg(base.code()), offset(off.value) {}
    768 
    769  Operand(Register base, int32_t off)
    770      : tag(MEM), reg(base.code()), offset(off) {}
    771 
    772  explicit Operand(const Address& addr)
    773      : tag(MEM), reg(addr.base.code()), offset(addr.offset) {}
    774 
    775  Tag getTag() const { return tag; }
    776 
    777  Register toReg() const {
    778    MOZ_ASSERT(tag == REG);
    779    return Register::FromCode(reg);
    780  }
    781 
    782  FloatRegister toFReg() const {
    783    MOZ_ASSERT(tag == FREG);
    784    return FloatRegister::FromCode(reg);
    785  }
    786 
    787  void toAddr(Register* r, Imm32* dest) const {
    788    MOZ_ASSERT(tag == MEM);
    789    *r = Register::FromCode(reg);
    790    *dest = Imm32(offset);
    791  }
    792  Address toAddress() const {
    793    MOZ_ASSERT(tag == MEM);
    794    return Address(Register::FromCode(reg), offset);
    795  }
    796  int32_t disp() const {
    797    MOZ_ASSERT(tag == MEM);
    798    return offset;
    799  }
    800 
    801  int32_t base() const {
    802    MOZ_ASSERT(tag == MEM);
    803    return reg;
    804  }
    805  Register baseReg() const {
    806    MOZ_ASSERT(tag == MEM);
    807    return Register::FromCode(reg);
    808  }
    809 };
    810 
    811 // int check.
    812 inline bool is_intN(int64_t x, unsigned n) {
    813  MOZ_ASSERT((0 < n) && (n < 64));
    814  int64_t limit = static_cast<int64_t>(1) << (n - 1);
    815  return (-limit <= x) && (x < limit);
    816 }
    817 
    818 inline bool is_uintN(int32_t x, unsigned n) {
    819  MOZ_ASSERT((0 < n) && (n < (sizeof(x) * 8)));
    820  return !(x >> n);
    821 }
    822 
    823 static constexpr int32_t SliceSize = 1024;
    824 typedef js::jit::AssemblerBuffer<SliceSize, Instruction> LOONGBuffer;
    825 
    826 class LOONGBufferWithExecutableCopy : public LOONGBuffer {
    827 public:
    828  void executableCopy(uint8_t* buffer) {
    829    if (this->oom()) {
    830      return;
    831    }
    832 
    833    for (Slice* cur = head; cur != nullptr; cur = cur->getNext()) {
    834      memcpy(buffer, &cur->instructions, cur->length());
    835      buffer += cur->length();
    836    }
    837  }
    838 
    839  bool appendRawCode(const uint8_t* code, size_t numBytes) {
    840    if (this->oom()) {
    841      return false;
    842    }
    843    while (numBytes > SliceSize) {
    844      this->putBytes(SliceSize, code);
    845      numBytes -= SliceSize;
    846      code += SliceSize;
    847    }
    848    this->putBytes(numBytes, code);
    849    return !this->oom();
    850  }
    851 };
    852 
    853 class AssemblerLOONG64 : public AssemblerShared {
    854 public:
    855  // TODO(loong64): Should we remove these conditions here?
    856  enum Condition {
    857    Equal,
    858    NotEqual,
    859    Above,
    860    AboveOrEqual,
    861    Below,
    862    BelowOrEqual,
    863    GreaterThan,
    864    GreaterThanOrEqual,
    865    GreaterThanOrEqual_Signed,
    866    GreaterThanOrEqual_NotSigned,
    867    LessThan,
    868    LessThan_Signed,
    869    LessThan_NotSigned,
    870    LessThanOrEqual,
    871    Overflow,
    872    CarrySet,
    873    CarryClear,
    874    Signed,
    875    NotSigned,
    876    Zero,
    877    NonZero,
    878    Always,
    879  };
    880 
    881  enum DoubleCondition {
    882    DoubleOrdered,
    883    DoubleEqual,
    884    DoubleNotEqual,
    885    DoubleGreaterThan,
    886    DoubleGreaterThanOrEqual,
    887    DoubleLessThan,
    888    DoubleLessThanOrEqual,
    889    DoubleUnordered,
    890    DoubleEqualOrUnordered,
    891    DoubleNotEqualOrUnordered,
    892    DoubleGreaterThanOrUnordered,
    893    DoubleGreaterThanOrEqualOrUnordered,
    894    DoubleLessThanOrUnordered,
    895    DoubleLessThanOrEqualOrUnordered
    896  };
    897 
    898  enum FPUCondition {
    899    kNoFPUCondition = -1,
    900 
    901    CAF = 0x00,
    902    SAF = 0x01,
    903    CLT = 0x02,
    904    SLT = 0x03,
    905    CEQ = 0x04,
    906    SEQ = 0x05,
    907    CLE = 0x06,
    908    SLE = 0x07,
    909    CUN = 0x08,
    910    SUN = 0x09,
    911    CULT = 0x0a,
    912    SULT = 0x0b,
    913    CUEQ = 0x0c,
    914    SUEQ = 0x0d,
    915    CULE = 0x0e,
    916    SULE = 0x0f,
    917    CNE = 0x10,
    918    SNE = 0x11,
    919    COR = 0x14,
    920    SOR = 0x15,
    921    CUNE = 0x18,
    922    SUNE = 0x19,
    923  };
    924 
    925  enum FPConditionBit { FCC0 = 0, FCC1, FFC2, FCC3, FCC4, FCC5, FCC6, FCC7 };
    926 
    927  enum FPControl { FCSR = 0 };
    928 
    929  enum FCSRBit { CauseI = 24, CauseU, CauseO, CauseZ, CauseV };
    930 
    931  enum FloatFormat { SingleFloat, DoubleFloat };
    932 
    933  enum JumpOrCall { BranchIsJump, BranchIsCall };
    934 
    935  enum FloatTestKind { TestForTrue, TestForFalse };
    936 
    937  // :( this should be protected, but since CodeGenerator
    938  // wants to use it, It needs to go out here :(
    939 
    940  BufferOffset nextOffset() { return m_buffer.nextOffset(); }
    941 
    942 protected:
    943  Instruction* editSrc(BufferOffset bo) { return m_buffer.getInst(bo); }
    944 
    945  // structure for fixing up pc-relative loads/jumps when a the machine code
    946  // gets moved (executable copy, gc, etc.)
    947  struct RelativePatch {
    948    // the offset within the code buffer where the value is loaded that
    949    // we want to fix-up
    950    BufferOffset offset;
    951    void* target;
    952    RelocationKind kind;
    953 
    954    RelativePatch(BufferOffset offset, void* target, RelocationKind kind)
    955        : offset(offset), target(target), kind(kind) {}
    956  };
    957 
    958  js::Vector<RelativePatch, 8, SystemAllocPolicy> jumps_;
    959 
    960  CompactBufferWriter jumpRelocations_;
    961  CompactBufferWriter dataRelocations_;
    962 
    963  LOONGBufferWithExecutableCopy m_buffer;
    964 
    965 #ifdef JS_JITSPEW
    966  Sprinter* printer;
    967 #endif
    968 
    969 public:
    970  AssemblerLOONG64()
    971      : m_buffer(),
    972 #ifdef JS_JITSPEW
    973        printer(nullptr),
    974 #endif
    975        isFinished(false),
    976        scratch_register_list_((1 << t7.code()) | (1 << t8.code())) {
    977  }
    978 
    979  static Condition InvertCondition(Condition cond);
    980  static DoubleCondition InvertCondition(DoubleCondition cond);
    981  // This is changing the condition codes for cmp a, b to the same codes for cmp
    982  // b, a.
    983  static Condition SwapCmpOperandsCondition(Condition cond);
    984 
    985  // As opposed to x86/x64 version, the data relocation has to be executed
    986  // before to recover the pointer, and not after.
    987  void writeDataRelocation(ImmGCPtr ptr) {
    988    // Raw GC pointer relocations and Value relocations both end up in
    989    // TraceOneDataRelocation.
    990    if (ptr.value) {
    991      if (gc::IsInsideNursery(ptr.value)) {
    992        embedsNurseryPointers_ = true;
    993      }
    994      dataRelocations_.writeUnsigned(nextOffset().getOffset());
    995    }
    996  }
    997 
    998  void assertNoGCThings() const {
    999 #ifdef DEBUG
   1000    MOZ_ASSERT(dataRelocations_.length() == 0);
   1001    for (auto& j : jumps_) {
   1002      MOZ_ASSERT(j.kind == RelocationKind::HARDCODED);
   1003    }
   1004 #endif
   1005  }
   1006 
   1007 public:
   1008  void setUnlimitedBuffer() { m_buffer.setUnlimited(); }
   1009  bool oom() const;
   1010 
   1011  void setPrinter(Sprinter* sp) {
   1012 #ifdef JS_JITSPEW
   1013    printer = sp;
   1014 #endif
   1015  }
   1016 
   1017 #ifdef JS_JITSPEW
   1018  inline void spew(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3) {
   1019    if (MOZ_UNLIKELY(printer || JitSpewEnabled(JitSpew_Codegen))) {
   1020      va_list va;
   1021      va_start(va, fmt);
   1022      spew(fmt, va);
   1023      va_end(va);
   1024    }
   1025  }
   1026 
   1027  void decodeBranchInstAndSpew(InstImm branch);
   1028 #else
   1029  MOZ_ALWAYS_INLINE void spew(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3) {}
   1030 #endif
   1031 
   1032 #ifdef JS_JITSPEW
   1033  MOZ_COLD void spew(const char* fmt, va_list va) MOZ_FORMAT_PRINTF(2, 0) {
   1034    // Buffer to hold the formatted string. Note that this may contain
   1035    // '%' characters, so do not pass it directly to printf functions.
   1036    char buf[200];
   1037 
   1038    int i = VsprintfLiteral(buf, fmt, va);
   1039    if (i > -1) {
   1040      if (printer) {
   1041        printer->printf("%s\n", buf);
   1042      }
   1043      js::jit::JitSpew(js::jit::JitSpew_Codegen, "%s", buf);
   1044    }
   1045  }
   1046 #endif
   1047 
   1048  Register getStackPointer() const { return StackPointer; }
   1049 
   1050 protected:
   1051  bool isFinished;
   1052 
   1053 public:
   1054  void finish();
   1055  bool appendRawCode(const uint8_t* code, size_t numBytes);
   1056  bool reserve(size_t size);
   1057  bool swapBuffer(wasm::Bytes& bytes);
   1058  void executableCopy(void* buffer);
   1059  void copyJumpRelocationTable(uint8_t* dest);
   1060  void copyDataRelocationTable(uint8_t* dest);
   1061 
   1062  // Size of the instruction stream, in bytes.
   1063  size_t size() const;
   1064  // Size of the jump relocation table, in bytes.
   1065  size_t jumpRelocationTableBytes() const;
   1066  size_t dataRelocationTableBytes() const;
   1067 
   1068  // Size of the data table, in bytes.
   1069  size_t bytesNeeded() const;
   1070 
   1071  // Write a blob of binary into the instruction stream *OR*
   1072  // into a destination address. If dest is nullptr (the default), then the
   1073  // instruction gets written into the instruction stream. If dest is not null
   1074  // it is interpreted as a pointer to the location that we want the
   1075  // instruction to be written.
   1076  BufferOffset writeInst(uint32_t x, uint32_t* dest = nullptr);
   1077  // A static variant for the cases where we don't want to have an assembler
   1078  // object at all. Normally, you would use the dummy (nullptr) object.
   1079  static void WriteInstStatic(uint32_t x, uint32_t* dest);
   1080 
   1081 public:
   1082  BufferOffset haltingAlign(int alignment);
   1083  BufferOffset nopAlign(int alignment);
   1084  BufferOffset as_nop() { return as_andi(zero, zero, 0); }
   1085 
   1086  // Branch and jump instructions
   1087  BufferOffset as_b(JOffImm26 off);
   1088  BufferOffset as_bl(JOffImm26 off);
   1089  BufferOffset as_jirl(Register rd, Register rj, BOffImm16 off);
   1090 
   1091  InstImm getBranchCode(JumpOrCall jumpOrCall);  // b, bl
   1092  InstImm getBranchCode(Register rd, Register rj,
   1093                        Condition c);  // beq, bne, bge, bgeu, blt, bltu
   1094  InstImm getBranchCode(Register rj, Condition c);  // beqz, bnez
   1095  InstImm getBranchCode(FPConditionBit cj);         // bceqz, bcnez
   1096 
   1097  // Arithmetic instructions
   1098  BufferOffset as_add_w(Register rd, Register rj, Register rk);
   1099  BufferOffset as_add_d(Register rd, Register rj, Register rk);
   1100  BufferOffset as_sub_w(Register rd, Register rj, Register rk);
   1101  BufferOffset as_sub_d(Register rd, Register rj, Register rk);
   1102 
   1103  BufferOffset as_addi_w(Register rd, Register rj, int32_t si12);
   1104  BufferOffset as_addi_d(Register rd, Register rj, int32_t si12);
   1105  BufferOffset as_addu16i_d(Register rd, Register rj, int32_t si16);
   1106 
   1107  BufferOffset as_alsl_w(Register rd, Register rj, Register rk, uint32_t sa2);
   1108  BufferOffset as_alsl_wu(Register rd, Register rj, Register rk, uint32_t sa2);
   1109  BufferOffset as_alsl_d(Register rd, Register rj, Register rk, uint32_t sa2);
   1110 
   1111  BufferOffset as_lu12i_w(Register rd, int32_t si20);
   1112  BufferOffset as_lu32i_d(Register rd, int32_t si20);
   1113  BufferOffset as_lu52i_d(Register rd, Register rj, int32_t si12);
   1114 
   1115  BufferOffset as_slt(Register rd, Register rj, Register rk);
   1116  BufferOffset as_sltu(Register rd, Register rj, Register rk);
   1117  BufferOffset as_slti(Register rd, Register rj, int32_t si12);
   1118  BufferOffset as_sltui(Register rd, Register rj, int32_t si12);
   1119 
   1120  BufferOffset as_pcaddi(Register rd, int32_t si20);
   1121  BufferOffset as_pcaddu12i(Register rd, int32_t si20);
   1122  BufferOffset as_pcaddu18i(Register rd, int32_t si20);
   1123  BufferOffset as_pcalau12i(Register rd, int32_t si20);
   1124 
   1125  BufferOffset as_mul_w(Register rd, Register rj, Register rk);
   1126  BufferOffset as_mulh_w(Register rd, Register rj, Register rk);
   1127  BufferOffset as_mulh_wu(Register rd, Register rj, Register rk);
   1128  BufferOffset as_mul_d(Register rd, Register rj, Register rk);
   1129  BufferOffset as_mulh_d(Register rd, Register rj, Register rk);
   1130  BufferOffset as_mulh_du(Register rd, Register rj, Register rk);
   1131 
   1132  BufferOffset as_mulw_d_w(Register rd, Register rj, Register rk);
   1133  BufferOffset as_mulw_d_wu(Register rd, Register rj, Register rk);
   1134 
   1135  BufferOffset as_div_w(Register rd, Register rj, Register rk);
   1136  BufferOffset as_mod_w(Register rd, Register rj, Register rk);
   1137  BufferOffset as_div_wu(Register rd, Register rj, Register rk);
   1138  BufferOffset as_mod_wu(Register rd, Register rj, Register rk);
   1139  BufferOffset as_div_d(Register rd, Register rj, Register rk);
   1140  BufferOffset as_mod_d(Register rd, Register rj, Register rk);
   1141  BufferOffset as_div_du(Register rd, Register rj, Register rk);
   1142  BufferOffset as_mod_du(Register rd, Register rj, Register rk);
   1143 
   1144  // Logical instructions
   1145  BufferOffset as_and(Register rd, Register rj, Register rk);
   1146  BufferOffset as_or(Register rd, Register rj, Register rk);
   1147  BufferOffset as_xor(Register rd, Register rj, Register rk);
   1148  BufferOffset as_nor(Register rd, Register rj, Register rk);
   1149  BufferOffset as_andn(Register rd, Register rj, Register rk);
   1150  BufferOffset as_orn(Register rd, Register rj, Register rk);
   1151 
   1152  BufferOffset as_andi(Register rd, Register rj, int32_t ui12);
   1153  BufferOffset as_ori(Register rd, Register rj, int32_t ui12);
   1154  BufferOffset as_xori(Register rd, Register rj, int32_t ui12);
   1155 
   1156  // Shift instructions
   1157  BufferOffset as_sll_w(Register rd, Register rj, Register rk);
   1158  BufferOffset as_srl_w(Register rd, Register rj, Register rk);
   1159  BufferOffset as_sra_w(Register rd, Register rj, Register rk);
   1160  BufferOffset as_rotr_w(Register rd, Register rj, Register rk);
   1161 
   1162  BufferOffset as_slli_w(Register rd, Register rj, int32_t ui5);
   1163  BufferOffset as_srli_w(Register rd, Register rj, int32_t ui5);
   1164  BufferOffset as_srai_w(Register rd, Register rj, int32_t ui5);
   1165  BufferOffset as_rotri_w(Register rd, Register rj, int32_t ui5);
   1166 
   1167  BufferOffset as_sll_d(Register rd, Register rj, Register rk);
   1168  BufferOffset as_srl_d(Register rd, Register rj, Register rk);
   1169  BufferOffset as_sra_d(Register rd, Register rj, Register rk);
   1170  BufferOffset as_rotr_d(Register rd, Register rj, Register rk);
   1171 
   1172  BufferOffset as_slli_d(Register rd, Register rj, int32_t ui6);
   1173  BufferOffset as_srli_d(Register rd, Register rj, int32_t ui6);
   1174  BufferOffset as_srai_d(Register rd, Register rj, int32_t ui6);
   1175  BufferOffset as_rotri_d(Register rd, Register rj, int32_t ui6);
   1176 
   1177  // Bit operation instrucitons
   1178  BufferOffset as_ext_w_b(Register rd, Register rj);
   1179  BufferOffset as_ext_w_h(Register rd, Register rj);
   1180 
   1181  BufferOffset as_clo_w(Register rd, Register rj);
   1182  BufferOffset as_clz_w(Register rd, Register rj);
   1183  BufferOffset as_cto_w(Register rd, Register rj);
   1184  BufferOffset as_ctz_w(Register rd, Register rj);
   1185  BufferOffset as_clo_d(Register rd, Register rj);
   1186  BufferOffset as_clz_d(Register rd, Register rj);
   1187  BufferOffset as_cto_d(Register rd, Register rj);
   1188  BufferOffset as_ctz_d(Register rd, Register rj);
   1189 
   1190  BufferOffset as_bytepick_w(Register rd, Register rj, Register rk,
   1191                             int32_t sa2);
   1192  BufferOffset as_bytepick_d(Register rd, Register rj, Register rk,
   1193                             int32_t sa3);
   1194 
   1195  BufferOffset as_revb_2h(Register rd, Register rj);
   1196  BufferOffset as_revb_4h(Register rd, Register rj);
   1197  BufferOffset as_revb_2w(Register rd, Register rj);
   1198  BufferOffset as_revb_d(Register rd, Register rj);
   1199 
   1200  BufferOffset as_revh_2w(Register rd, Register rj);
   1201  BufferOffset as_revh_d(Register rd, Register rj);
   1202 
   1203  BufferOffset as_bitrev_4b(Register rd, Register rj);
   1204  BufferOffset as_bitrev_8b(Register rd, Register rj);
   1205 
   1206  BufferOffset as_bitrev_w(Register rd, Register rj);
   1207  BufferOffset as_bitrev_d(Register rd, Register rj);
   1208 
   1209  BufferOffset as_bstrins_w(Register rd, Register rj, int32_t msbw,
   1210                            int32_t lsbw);
   1211  BufferOffset as_bstrins_d(Register rd, Register rj, int32_t msbd,
   1212                            int32_t lsbd);
   1213  BufferOffset as_bstrpick_w(Register rd, Register rj, int32_t msbw,
   1214                             int32_t lsbw);
   1215  BufferOffset as_bstrpick_d(Register rd, Register rj, int32_t msbd,
   1216                             int32_t lsbd);
   1217 
   1218  BufferOffset as_maskeqz(Register rd, Register rj, Register rk);
   1219  BufferOffset as_masknez(Register rd, Register rj, Register rk);
   1220 
   1221  // Load and store instructions
   1222  BufferOffset as_ld_b(Register rd, Register rj, int32_t si12);
   1223  BufferOffset as_ld_h(Register rd, Register rj, int32_t si12);
   1224  BufferOffset as_ld_w(Register rd, Register rj, int32_t si12);
   1225  BufferOffset as_ld_d(Register rd, Register rj, int32_t si12);
   1226  BufferOffset as_ld_bu(Register rd, Register rj, int32_t si12);
   1227  BufferOffset as_ld_hu(Register rd, Register rj, int32_t si12);
   1228  BufferOffset as_ld_wu(Register rd, Register rj, int32_t si12);
   1229  BufferOffset as_st_b(Register rd, Register rj, int32_t si12);
   1230  BufferOffset as_st_h(Register rd, Register rj, int32_t si12);
   1231  BufferOffset as_st_w(Register rd, Register rj, int32_t si12);
   1232  BufferOffset as_st_d(Register rd, Register rj, int32_t si12);
   1233 
   1234  BufferOffset as_ldx_b(Register rd, Register rj, Register rk);
   1235  BufferOffset as_ldx_h(Register rd, Register rj, Register rk);
   1236  BufferOffset as_ldx_w(Register rd, Register rj, Register rk);
   1237  BufferOffset as_ldx_d(Register rd, Register rj, Register rk);
   1238  BufferOffset as_ldx_bu(Register rd, Register rj, Register rk);
   1239  BufferOffset as_ldx_hu(Register rd, Register rj, Register rk);
   1240  BufferOffset as_ldx_wu(Register rd, Register rj, Register rk);
   1241  BufferOffset as_stx_b(Register rd, Register rj, Register rk);
   1242  BufferOffset as_stx_h(Register rd, Register rj, Register rk);
   1243  BufferOffset as_stx_w(Register rd, Register rj, Register rk);
   1244  BufferOffset as_stx_d(Register rd, Register rj, Register rk);
   1245 
   1246  BufferOffset as_ldptr_w(Register rd, Register rj, int32_t si14);
   1247  BufferOffset as_ldptr_d(Register rd, Register rj, int32_t si14);
   1248  BufferOffset as_stptr_w(Register rd, Register rj, int32_t si14);
   1249  BufferOffset as_stptr_d(Register rd, Register rj, int32_t si14);
   1250 
   1251  BufferOffset as_preld(int32_t hint, Register rj, int32_t si12);
   1252 
   1253  // Atomic instructions
   1254  BufferOffset as_amswap_w(Register rd, Register rj, Register rk);
   1255  BufferOffset as_amswap_d(Register rd, Register rj, Register rk);
   1256  BufferOffset as_amadd_w(Register rd, Register rj, Register rk);
   1257  BufferOffset as_amadd_d(Register rd, Register rj, Register rk);
   1258  BufferOffset as_amand_w(Register rd, Register rj, Register rk);
   1259  BufferOffset as_amand_d(Register rd, Register rj, Register rk);
   1260  BufferOffset as_amor_w(Register rd, Register rj, Register rk);
   1261  BufferOffset as_amor_d(Register rd, Register rj, Register rk);
   1262  BufferOffset as_amxor_w(Register rd, Register rj, Register rk);
   1263  BufferOffset as_amxor_d(Register rd, Register rj, Register rk);
   1264  BufferOffset as_ammax_w(Register rd, Register rj, Register rk);
   1265  BufferOffset as_ammax_d(Register rd, Register rj, Register rk);
   1266  BufferOffset as_ammin_w(Register rd, Register rj, Register rk);
   1267  BufferOffset as_ammin_d(Register rd, Register rj, Register rk);
   1268  BufferOffset as_ammax_wu(Register rd, Register rj, Register rk);
   1269  BufferOffset as_ammax_du(Register rd, Register rj, Register rk);
   1270  BufferOffset as_ammin_wu(Register rd, Register rj, Register rk);
   1271  BufferOffset as_ammin_du(Register rd, Register rj, Register rk);
   1272 
   1273  BufferOffset as_amswap_db_w(Register rd, Register rj, Register rk);
   1274  BufferOffset as_amswap_db_d(Register rd, Register rj, Register rk);
   1275  BufferOffset as_amadd_db_w(Register rd, Register rj, Register rk);
   1276  BufferOffset as_amadd_db_d(Register rd, Register rj, Register rk);
   1277  BufferOffset as_amand_db_w(Register rd, Register rj, Register rk);
   1278  BufferOffset as_amand_db_d(Register rd, Register rj, Register rk);
   1279  BufferOffset as_amor_db_w(Register rd, Register rj, Register rk);
   1280  BufferOffset as_amor_db_d(Register rd, Register rj, Register rk);
   1281  BufferOffset as_amxor_db_w(Register rd, Register rj, Register rk);
   1282  BufferOffset as_amxor_db_d(Register rd, Register rj, Register rk);
   1283  BufferOffset as_ammax_db_w(Register rd, Register rj, Register rk);
   1284  BufferOffset as_ammax_db_d(Register rd, Register rj, Register rk);
   1285  BufferOffset as_ammin_db_w(Register rd, Register rj, Register rk);
   1286  BufferOffset as_ammin_db_d(Register rd, Register rj, Register rk);
   1287  BufferOffset as_ammax_db_wu(Register rd, Register rj, Register rk);
   1288  BufferOffset as_ammax_db_du(Register rd, Register rj, Register rk);
   1289  BufferOffset as_ammin_db_wu(Register rd, Register rj, Register rk);
   1290  BufferOffset as_ammin_db_du(Register rd, Register rj, Register rk);
   1291 
   1292  BufferOffset as_ll_w(Register rd, Register rj, int32_t si14);
   1293  BufferOffset as_ll_d(Register rd, Register rj, int32_t si14);
   1294  BufferOffset as_sc_w(Register rd, Register rj, int32_t si14);
   1295  BufferOffset as_sc_d(Register rd, Register rj, int32_t si14);
   1296 
   1297  // Barrier instructions
   1298  BufferOffset as_dbar(int32_t hint);
   1299  BufferOffset as_ibar(int32_t hint);
   1300 
   1301  // FP Arithmetic instructions
   1302  BufferOffset as_fadd_s(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1303  BufferOffset as_fadd_d(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1304  BufferOffset as_fsub_s(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1305  BufferOffset as_fsub_d(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1306  BufferOffset as_fmul_s(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1307  BufferOffset as_fmul_d(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1308  BufferOffset as_fdiv_s(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1309  BufferOffset as_fdiv_d(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1310 
   1311  BufferOffset as_fmadd_s(FloatRegister fd, FloatRegister fj, FloatRegister fk,
   1312                          FloatRegister fa);
   1313  BufferOffset as_fmadd_d(FloatRegister fd, FloatRegister fj, FloatRegister fk,
   1314                          FloatRegister fa);
   1315  BufferOffset as_fmsub_s(FloatRegister fd, FloatRegister fj, FloatRegister fk,
   1316                          FloatRegister fa);
   1317  BufferOffset as_fmsub_d(FloatRegister fd, FloatRegister fj, FloatRegister fk,
   1318                          FloatRegister fa);
   1319  BufferOffset as_fnmadd_s(FloatRegister fd, FloatRegister fj, FloatRegister fk,
   1320                           FloatRegister fa);
   1321  BufferOffset as_fnmadd_d(FloatRegister fd, FloatRegister fj, FloatRegister fk,
   1322                           FloatRegister fa);
   1323  BufferOffset as_fnmsub_s(FloatRegister fd, FloatRegister fj, FloatRegister fk,
   1324                           FloatRegister fa);
   1325  BufferOffset as_fnmsub_d(FloatRegister fd, FloatRegister fj, FloatRegister fk,
   1326                           FloatRegister fa);
   1327 
   1328  BufferOffset as_fmax_s(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1329  BufferOffset as_fmax_d(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1330  BufferOffset as_fmin_s(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1331  BufferOffset as_fmin_d(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1332 
   1333  BufferOffset as_fmaxa_s(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1334  BufferOffset as_fmaxa_d(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1335  BufferOffset as_fmina_s(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1336  BufferOffset as_fmina_d(FloatRegister fd, FloatRegister fj, FloatRegister fk);
   1337 
   1338  BufferOffset as_fabs_s(FloatRegister fd, FloatRegister fj);
   1339  BufferOffset as_fabs_d(FloatRegister fd, FloatRegister fj);
   1340  BufferOffset as_fneg_s(FloatRegister fd, FloatRegister fj);
   1341  BufferOffset as_fneg_d(FloatRegister fd, FloatRegister fj);
   1342 
   1343  BufferOffset as_fsqrt_s(FloatRegister fd, FloatRegister fj);
   1344  BufferOffset as_fsqrt_d(FloatRegister fd, FloatRegister fj);
   1345  BufferOffset as_fcopysign_s(FloatRegister fd, FloatRegister fj,
   1346                              FloatRegister fk);
   1347  BufferOffset as_fcopysign_d(FloatRegister fd, FloatRegister fj,
   1348                              FloatRegister fk);
   1349 
   1350  // FP compare instructions (fcmp.cond.s fcmp.cond.d)
   1351  BufferOffset as_fcmp_cor(FloatFormat fmt, FloatRegister fj, FloatRegister fk,
   1352                           FPConditionBit cd);
   1353  BufferOffset as_fcmp_ceq(FloatFormat fmt, FloatRegister fj, FloatRegister fk,
   1354                           FPConditionBit cd);
   1355  BufferOffset as_fcmp_cne(FloatFormat fmt, FloatRegister fj, FloatRegister fk,
   1356                           FPConditionBit cd);
   1357  BufferOffset as_fcmp_cle(FloatFormat fmt, FloatRegister fj, FloatRegister fk,
   1358                           FPConditionBit cd);
   1359  BufferOffset as_fcmp_clt(FloatFormat fmt, FloatRegister fj, FloatRegister fk,
   1360                           FPConditionBit cd);
   1361  BufferOffset as_fcmp_cun(FloatFormat fmt, FloatRegister fj, FloatRegister fk,
   1362                           FPConditionBit cd);
   1363  BufferOffset as_fcmp_cueq(FloatFormat fmt, FloatRegister fj, FloatRegister fk,
   1364                            FPConditionBit cd);
   1365  BufferOffset as_fcmp_cune(FloatFormat fmt, FloatRegister fj, FloatRegister fk,
   1366                            FPConditionBit cd);
   1367  BufferOffset as_fcmp_cule(FloatFormat fmt, FloatRegister fj, FloatRegister fk,
   1368                            FPConditionBit cd);
   1369  BufferOffset as_fcmp_cult(FloatFormat fmt, FloatRegister fj, FloatRegister fk,
   1370                            FPConditionBit cd);
   1371 
   1372  // FP conversion instructions
   1373  BufferOffset as_fcvt_s_d(FloatRegister fd, FloatRegister fj);
   1374  BufferOffset as_fcvt_d_s(FloatRegister fd, FloatRegister fj);
   1375 
   1376  BufferOffset as_ffint_s_w(FloatRegister fd, FloatRegister fj);
   1377  BufferOffset as_ffint_s_l(FloatRegister fd, FloatRegister fj);
   1378  BufferOffset as_ffint_d_w(FloatRegister fd, FloatRegister fj);
   1379  BufferOffset as_ffint_d_l(FloatRegister fd, FloatRegister fj);
   1380  BufferOffset as_ftint_w_s(FloatRegister fd, FloatRegister fj);
   1381  BufferOffset as_ftint_w_d(FloatRegister fd, FloatRegister fj);
   1382  BufferOffset as_ftint_l_s(FloatRegister fd, FloatRegister fj);
   1383  BufferOffset as_ftint_l_d(FloatRegister fd, FloatRegister fj);
   1384 
   1385  BufferOffset as_ftintrm_w_s(FloatRegister fd, FloatRegister fj);
   1386  BufferOffset as_ftintrm_w_d(FloatRegister fd, FloatRegister fj);
   1387  BufferOffset as_ftintrm_l_s(FloatRegister fd, FloatRegister fj);
   1388  BufferOffset as_ftintrm_l_d(FloatRegister fd, FloatRegister fj);
   1389  BufferOffset as_ftintrp_w_s(FloatRegister fd, FloatRegister fj);
   1390  BufferOffset as_ftintrp_w_d(FloatRegister fd, FloatRegister fj);
   1391  BufferOffset as_ftintrp_l_s(FloatRegister fd, FloatRegister fj);
   1392  BufferOffset as_ftintrp_l_d(FloatRegister fd, FloatRegister fj);
   1393  BufferOffset as_ftintrz_w_s(FloatRegister fd, FloatRegister fj);
   1394  BufferOffset as_ftintrz_w_d(FloatRegister fd, FloatRegister fj);
   1395  BufferOffset as_ftintrz_l_s(FloatRegister fd, FloatRegister fj);
   1396  BufferOffset as_ftintrz_l_d(FloatRegister fd, FloatRegister fj);
   1397  BufferOffset as_ftintrne_w_s(FloatRegister fd, FloatRegister fj);
   1398  BufferOffset as_ftintrne_w_d(FloatRegister fd, FloatRegister fj);
   1399  BufferOffset as_ftintrne_l_s(FloatRegister fd, FloatRegister fj);
   1400  BufferOffset as_ftintrne_l_d(FloatRegister fd, FloatRegister fj);
   1401 
   1402  BufferOffset as_frint_s(FloatRegister fd, FloatRegister fj);
   1403  BufferOffset as_frint_d(FloatRegister fd, FloatRegister fj);
   1404 
   1405  // FP mov instructions
   1406  BufferOffset as_fmov_s(FloatRegister fd, FloatRegister fj);
   1407  BufferOffset as_fmov_d(FloatRegister fd, FloatRegister fj);
   1408 
   1409  BufferOffset as_fsel(FloatRegister fd, FloatRegister fj, FloatRegister fk,
   1410                       FPConditionBit ca);
   1411 
   1412  BufferOffset as_movgr2fr_w(FloatRegister fd, Register rj);
   1413  BufferOffset as_movgr2fr_d(FloatRegister fd, Register rj);
   1414  BufferOffset as_movgr2frh_w(FloatRegister fd, Register rj);
   1415 
   1416  BufferOffset as_movfr2gr_s(Register rd, FloatRegister fj);
   1417  BufferOffset as_movfr2gr_d(Register rd, FloatRegister fj);
   1418  BufferOffset as_movfrh2gr_s(Register rd, FloatRegister fj);
   1419 
   1420  BufferOffset as_movgr2fcsr(Register rj);
   1421  BufferOffset as_movfcsr2gr(Register rd);
   1422 
   1423  BufferOffset as_movfr2cf(FPConditionBit cd, FloatRegister fj);
   1424  BufferOffset as_movcf2fr(FloatRegister fd, FPConditionBit cj);
   1425 
   1426  BufferOffset as_movgr2cf(FPConditionBit cd, Register rj);
   1427  BufferOffset as_movcf2gr(Register rd, FPConditionBit cj);
   1428 
   1429  // FP load/store instructions
   1430  BufferOffset as_fld_s(FloatRegister fd, Register rj, int32_t si12);
   1431  BufferOffset as_fld_d(FloatRegister fd, Register rj, int32_t si12);
   1432  BufferOffset as_fst_s(FloatRegister fd, Register rj, int32_t si12);
   1433  BufferOffset as_fst_d(FloatRegister fd, Register rj, int32_t si12);
   1434 
   1435  BufferOffset as_fldx_s(FloatRegister fd, Register rj, Register rk);
   1436  BufferOffset as_fldx_d(FloatRegister fd, Register rj, Register rk);
   1437  BufferOffset as_fstx_s(FloatRegister fd, Register rj, Register rk);
   1438  BufferOffset as_fstx_d(FloatRegister fd, Register rj, Register rk);
   1439 
   1440  // label operations
   1441  void bind(Label* label, BufferOffset boff = BufferOffset());
   1442  virtual void bind(InstImm* inst, uintptr_t branch, uintptr_t target) = 0;
   1443  void bind(CodeLabel* label) { label->target()->bind(currentOffset()); }
   1444  uint32_t currentOffset() { return nextOffset().getOffset(); }
   1445  void retarget(Label* label, Label* target);
   1446 
   1447  void call(Label* label);
   1448  void call(void* target);
   1449 
   1450  void as_break(uint32_t code);
   1451 
   1452 public:
   1453  static bool SupportsFloatingPoint() {
   1454 #if defined(__loongarch_hard_float) || defined(JS_SIMULATOR_LOONG64)
   1455    return true;
   1456 #else
   1457    return false;
   1458 #endif
   1459  }
   1460  static bool SupportsUnalignedAccesses() { return true; }
   1461  static bool SupportsFastUnalignedFPAccesses() { return true; }
   1462  static bool SupportsFloat64To16() { return false; }
   1463  static bool SupportsFloat32To16() { return false; }
   1464 
   1465  static bool HasRoundInstruction(RoundingMode mode) { return false; }
   1466 
   1467 protected:
   1468  InstImm invertBranch(InstImm branch, BOffImm16 skipOffset);
   1469  void addPendingJump(BufferOffset src, ImmPtr target, RelocationKind kind) {
   1470    enoughMemory_ &= jumps_.append(RelativePatch(src, target.value, kind));
   1471    if (kind == RelocationKind::JITCODE) {
   1472      jumpRelocations_.writeUnsigned(src.getOffset());
   1473    }
   1474  }
   1475 
   1476  void addLongJump(BufferOffset src, BufferOffset dst) {
   1477    CodeLabel cl;
   1478    cl.patchAt()->bind(src.getOffset());
   1479    cl.target()->bind(dst.getOffset());
   1480    cl.setLinkMode(CodeLabel::JumpImmediate);
   1481    addCodeLabel(std::move(cl));
   1482  }
   1483 
   1484 public:
   1485  void flushBuffer() {}
   1486 
   1487  void comment(const char* msg) { spew("; %s", msg); }
   1488 
   1489  static uint32_t NopSize() { return 4; }
   1490 
   1491  static void PatchWrite_Imm32(CodeLocationLabel label, Imm32 imm);
   1492 
   1493  static uint8_t* NextInstruction(uint8_t* instruction,
   1494                                  uint32_t* count = nullptr);
   1495 
   1496  static void ToggleToJmp(CodeLocationLabel inst_);
   1497  static void ToggleToCmp(CodeLocationLabel inst_);
   1498 
   1499  void verifyHeapAccessDisassembly(uint32_t begin, uint32_t end,
   1500                                   const Disassembler::HeapAccess& heapAccess) {
   1501    // Implement this if we implement a disassembler.
   1502  }
   1503 
   1504 private:
   1505  GeneralRegisterSet scratch_register_list_;
   1506 
   1507 public:
   1508  GeneralRegisterSet* GetScratchRegisterList() {
   1509    return &scratch_register_list_;
   1510  }
   1511 };  // AssemblerLOONG64
   1512 
   1513 // andi r0, r0, 0
   1514 const uint32_t NopInst = 0x03400000;
   1515 
   1516 // An Instruction is a structure for both encoding and decoding any and all
   1517 // LoongArch instructions.
   1518 class Instruction {
   1519 public:
   1520  uint32_t data;
   1521 
   1522 protected:
   1523  // Standard constructor
   1524  explicit Instruction(uint32_t data_) : data(data_) {}
   1525  // You should never create an instruction directly.  You should create a
   1526  // more specific instruction which will eventually call one of these
   1527  // constructors for you.
   1528 
   1529 public:
   1530  uint32_t encode() const { return data; }
   1531 
   1532  void makeNop() { data = NopInst; }
   1533 
   1534  void setData(uint32_t data) { this->data = data; }
   1535 
   1536  const Instruction& operator=(const Instruction& src) {
   1537    data = src.data;
   1538    return *this;
   1539  }
   1540 
   1541  // Extract the one particular bit.
   1542  uint32_t extractBit(uint32_t bit) { return (encode() >> bit) & 1; }
   1543  // Extract a bit field out of the instruction
   1544  uint32_t extractBitField(uint32_t hi, uint32_t lo) {
   1545    return (encode() >> lo) & ((2 << (hi - lo)) - 1);
   1546  }
   1547 
   1548  // Get the next instruction in the instruction stream.
   1549  // This does neat things like ignoreconstant pools and their guards.
   1550  Instruction* next();
   1551 
   1552  // Sometimes, an api wants a uint32_t (or a pointer to it) rather than
   1553  // an instruction.  raw() just coerces this into a pointer to a uint32_t
   1554  const uint32_t* raw() const { return &data; }
   1555  uint32_t size() const { return 4; }
   1556 };  // Instruction
   1557 
   1558 // make sure that it is the right size
   1559 static_assert(sizeof(Instruction) == 4,
   1560              "Size of Instruction class has to be 4 bytes.");
   1561 
   1562 class InstNOP : public Instruction {
   1563 public:
   1564  InstNOP() : Instruction(NopInst) {}
   1565 };
   1566 
   1567 // Class for register type instructions.
   1568 class InstReg : public Instruction {
   1569 public:
   1570  InstReg(OpcodeField op, Register rj, Register rd)
   1571      : Instruction(op | RJ(rj) | RD(rd)) {}
   1572  InstReg(OpcodeField op, Register rk, Register rj, Register rd)
   1573      : Instruction(op | RK(rk) | RJ(rj) | RD(rd)) {}
   1574  InstReg(OpcodeField op, uint32_t sa, Register rk, Register rj, Register rd,
   1575          uint32_t sa_bit)
   1576      : Instruction(sa_bit == 2 ? op | SA2(sa) | RK(rk) | RJ(rj) | RD(rd)
   1577                                : op | SA3(sa) | RK(rk) | RJ(rj) | RD(rd)) {
   1578    MOZ_ASSERT(sa_bit == 2 || sa_bit == 3);
   1579  }
   1580  InstReg(OpcodeField op, Register rj, Register rd, bool HasRd)
   1581      : Instruction(HasRd ? op | RJ(rj) | RD(rd) : op | RK(rj) | RJ(rd)) {}
   1582 
   1583  // For floating-point
   1584  InstReg(OpcodeField op, Register rj, FloatRegister fd)
   1585      : Instruction(op | RJ(rj) | FD(fd)) {}
   1586  InstReg(OpcodeField op, FloatRegister fj, FloatRegister fd)
   1587      : Instruction(op | FJ(fj) | FD(fd)) {}
   1588  InstReg(OpcodeField op, FloatRegister fk, FloatRegister fj, FloatRegister fd)
   1589      : Instruction(op | FK(fk) | FJ(fj) | FD(fd)) {}
   1590  InstReg(OpcodeField op, Register rk, Register rj, FloatRegister fd)
   1591      : Instruction(op | RK(rk) | RJ(rj) | FD(fd)) {}
   1592  InstReg(OpcodeField op, FloatRegister fa, FloatRegister fk, FloatRegister fj,
   1593          FloatRegister fd)
   1594      : Instruction(op | FA(fa) | FK(fk) | FJ(fj) | FD(fd)) {}
   1595  InstReg(OpcodeField op, AssemblerLOONG64::FPConditionBit ca, FloatRegister fk,
   1596          FloatRegister fj, FloatRegister fd)
   1597      : Instruction(op | ca << CAShift | FK(fk) | FJ(fj) | FD(fd)) {
   1598    MOZ_ASSERT(op == op_fsel);
   1599  }
   1600  InstReg(OpcodeField op, FloatRegister fj, Register rd)
   1601      : Instruction(op | FJ(fj) | RD(rd)) {
   1602    MOZ_ASSERT((op == op_movfr2gr_s) || (op == op_movfr2gr_d) ||
   1603               (op == op_movfrh2gr_s));
   1604  }
   1605  InstReg(OpcodeField op, Register rj, uint32_t fd)
   1606      : Instruction(op | RJ(rj) | fd) {
   1607    MOZ_ASSERT(op == op_movgr2fcsr);
   1608  }
   1609  InstReg(OpcodeField op, uint32_t fj, Register rd)
   1610      : Instruction(op | (fj << FJShift) | RD(rd)) {
   1611    MOZ_ASSERT(op == op_movfcsr2gr);
   1612  }
   1613  InstReg(OpcodeField op, FloatRegister fj, AssemblerLOONG64::FPConditionBit cd)
   1614      : Instruction(op | FJ(fj) | cd) {
   1615    MOZ_ASSERT(op == op_movfr2cf);
   1616  }
   1617  InstReg(OpcodeField op, AssemblerLOONG64::FPConditionBit cj, FloatRegister fd)
   1618      : Instruction(op | (cj << CJShift) | FD(fd)) {
   1619    MOZ_ASSERT(op == op_movcf2fr);
   1620  }
   1621  InstReg(OpcodeField op, Register rj, AssemblerLOONG64::FPConditionBit cd)
   1622      : Instruction(op | RJ(rj) | cd) {
   1623    MOZ_ASSERT(op == op_movgr2cf);
   1624  }
   1625  InstReg(OpcodeField op, AssemblerLOONG64::FPConditionBit cj, Register rd)
   1626      : Instruction(op | (cj << CJShift) | RD(rd)) {
   1627    MOZ_ASSERT(op == op_movcf2gr);
   1628  }
   1629  InstReg(OpcodeField op, int32_t cond, FloatRegister fk, FloatRegister fj,
   1630          AssemblerLOONG64::FPConditionBit cd)
   1631      : Instruction(op | (cond & CONDMask) << CONDShift | FK(fk) | FJ(fj) |
   1632                    (cd & CDMask)) {
   1633    MOZ_ASSERT(is_uintN(cond, 5));
   1634  }
   1635 
   1636  uint32_t extractRK() {
   1637    return extractBitField(RKShift + RKBits - 1, RKShift);
   1638  }
   1639  uint32_t extractRJ() {
   1640    return extractBitField(RJShift + RJBits - 1, RJShift);
   1641  }
   1642  uint32_t extractRD() {
   1643    return extractBitField(RDShift + RDBits - 1, RDShift);
   1644  }
   1645  uint32_t extractSA2() {
   1646    return extractBitField(SAShift + SA2Bits - 1, SAShift);
   1647  }
   1648  uint32_t extractSA3() {
   1649    return extractBitField(SAShift + SA3Bits - 1, SAShift);
   1650  }
   1651 };
   1652 
   1653 // Class for branch, load and store instructions with immediate offset.
   1654 class InstImm : public Instruction {
   1655 public:
   1656  void extractImm16(BOffImm16* dest);
   1657  uint32_t genImm(int32_t value, uint32_t value_bits) {
   1658    uint32_t imm = value & Imm5Mask;
   1659    if (value_bits == 6) {
   1660      imm = value & Imm6Mask;
   1661    } else if (value_bits == 12) {
   1662      imm = value & Imm12Mask;
   1663    } else if (value_bits == 14) {
   1664      imm = value & Imm14Mask;
   1665    }
   1666 
   1667    return imm;
   1668  }
   1669 
   1670  InstImm(OpcodeField op, int32_t value, Register rj, Register rd,
   1671          uint32_t value_bits)
   1672      : Instruction(op | genImm(value, value_bits) << RKShift | RJ(rj) |
   1673                    RD(rd)) {
   1674    MOZ_ASSERT(value_bits == 5 || value_bits == 6 || value_bits == 12 ||
   1675               value_bits == 14);
   1676  }
   1677  InstImm(OpcodeField op, BOffImm16 off, Register rj, Register rd)
   1678      : Instruction(op | (off.encode() & Imm16Mask) << Imm16Shift | RJ(rj) |
   1679                    RD(rd)) {}
   1680  InstImm(OpcodeField op, int32_t si21, Register rj, bool NotHasRd)
   1681      : Instruction(NotHasRd ? op | (si21 & Imm16Mask) << RKShift | RJ(rj) |
   1682                                   (si21 & Imm21Mask) >> 16
   1683                             : op | (si21 & Imm20Mask) << Imm20Shift | RD(rj)) {
   1684    if (NotHasRd) {
   1685      MOZ_ASSERT(op == op_beqz || op == op_bnez);
   1686      MOZ_ASSERT(is_intN(si21, 21));
   1687    } else {
   1688      MOZ_ASSERT(op == op_lu12i_w || op == op_lu32i_d || op == op_pcaddi ||
   1689                 op == op_pcaddu12i || op == op_pcaddu18i ||
   1690                 op == op_pcalau12i);
   1691      // si20
   1692      MOZ_ASSERT(is_intN(si21, 20) || is_uintN(si21, 20));
   1693    }
   1694  }
   1695  InstImm(OpcodeField op, int32_t si21, AssemblerLOONG64::FPConditionBit cj,
   1696          bool isNotEqual)
   1697      : Instruction(isNotEqual
   1698                        ? op | (si21 & Imm16Mask) << RKShift |
   1699                              (cj + 8) << CJShift | (si21 & Imm21Mask) >> 16
   1700                        : op | (si21 & Imm16Mask) << RKShift | cj << CJShift |
   1701                              (si21 & Imm21Mask) >> 16) {
   1702    MOZ_ASSERT(is_intN(si21, 21));
   1703    MOZ_ASSERT(op == op_bcz);
   1704    MOZ_ASSERT(cj >= 0 && cj <= 7);
   1705  }
   1706  InstImm(OpcodeField op, Imm16 off, Register rj, Register rd)
   1707      : Instruction(op | (off.encode() & Imm16Mask) << Imm16Shift | RJ(rj) |
   1708                    RD(rd)) {}
   1709  InstImm(OpcodeField op, int32_t bit15)
   1710      : Instruction(op | (bit15 & Imm15Mask)) {
   1711    MOZ_ASSERT(is_uintN(bit15, 15));
   1712  }
   1713 
   1714  InstImm(OpcodeField op, int32_t bit26, bool jump)
   1715      : Instruction(op | (bit26 & Imm16Mask) << Imm16Shift |
   1716                    (bit26 & Imm26Mask) >> 16) {
   1717    MOZ_ASSERT(is_intN(bit26, 26));
   1718  }
   1719  InstImm(OpcodeField op, int32_t si12, Register rj, int32_t hint)
   1720      : Instruction(op | (si12 & Imm12Mask) << Imm12Shift | RJ(rj) |
   1721                    (hint & HINTMask)) {
   1722    MOZ_ASSERT(op == op_preld);
   1723  }
   1724  InstImm(OpcodeField op, int32_t msb, int32_t lsb, Register rj, Register rd,
   1725          uint32_t sb_bits)
   1726      : Instruction((sb_bits == 5)
   1727                        ? op | (msb & MSBWMask) << MSBWShift |
   1728                              (lsb & LSBWMask) << LSBWShift | RJ(rj) | RD(rd)
   1729                        : op | (msb & MSBDMask) << MSBDShift |
   1730                              (lsb & LSBDMask) << LSBDShift | RJ(rj) | RD(rd)) {
   1731    MOZ_ASSERT(sb_bits == 5 || sb_bits == 6);
   1732    MOZ_ASSERT(op == op_bstr_w || op == op_bstrins_d || op == op_bstrpick_d);
   1733  }
   1734  InstImm(OpcodeField op, int32_t msb, int32_t lsb, Register rj, Register rd)
   1735      : Instruction(op | (msb & MSBWMask) << MSBWShift |
   1736                    ((lsb + 0x20) & LSBDMask) << LSBWShift | RJ(rj) | RD(rd)) {
   1737    MOZ_ASSERT(op == op_bstr_w);
   1738  }
   1739 
   1740  // For floating-point loads and stores.
   1741  InstImm(OpcodeField op, int32_t si12, Register rj, FloatRegister fd)
   1742      : Instruction(op | (si12 & Imm12Mask) << Imm12Shift | RJ(rj) | FD(fd)) {
   1743    MOZ_ASSERT(is_intN(si12, 12));
   1744  }
   1745 
   1746  void setOpcode(OpcodeField op, uint32_t opBits) {
   1747    // opBits not greater than 24.
   1748    MOZ_ASSERT(opBits < 25);
   1749    uint32_t OpcodeShift = 32 - opBits;
   1750    uint32_t OpcodeMask = ((1 << opBits) - 1) << OpcodeShift;
   1751    data = (data & ~OpcodeMask) | op;
   1752  }
   1753  uint32_t extractRK() {
   1754    return extractBitField(RKShift + RKBits - 1, RKShift);
   1755  }
   1756  uint32_t extractRJ() {
   1757    return extractBitField(RJShift + RJBits - 1, RJShift);
   1758  }
   1759  void setRJ(uint32_t rj) {
   1760    data = (data & ~(RJMask << RJShift)) | (rj << RJShift);
   1761  }
   1762  uint32_t extractRD() {
   1763    return extractBitField(RDShift + RDBits - 1, RDShift);
   1764  }
   1765  uint32_t extractImm16Value() {
   1766    return extractBitField(Imm16Shift + Imm16Bits - 1, Imm16Shift);
   1767  }
   1768  void setBOffImm16(BOffImm16 off) {
   1769    // Reset immediate field and replace it
   1770    data = (data & ~BOffImm16Mask) | (off.encode() << Imm16Shift);
   1771  }
   1772  void setImm21(int32_t off) {
   1773    // Reset immediate field and replace it
   1774    uint32_t low16 = (off >> 2) & Imm16Mask;
   1775    int32_t high5 = (off >> 18) & Imm5Mask;
   1776    uint32_t fcc_info = (data >> 5) & 0x1F;
   1777    data = (data & ~BOffImm26Mask) | (low16 << Imm16Shift) | high5 |
   1778           (fcc_info << 5);
   1779  }
   1780 };
   1781 
   1782 // Class for Jump type instructions.
   1783 class InstJump : public Instruction {
   1784 public:
   1785  InstJump(OpcodeField op, JOffImm26 off)
   1786      : Instruction(op | (off.encode() & Imm16Mask) << Imm16Shift |
   1787                    (off.encode() & Imm26Mask) >> 16) {
   1788    MOZ_ASSERT(op == op_b || op == op_bl);
   1789  }
   1790 
   1791  void setJOffImm26(JOffImm26 off) {
   1792    // Reset immediate field and replace it
   1793    data = (data & ~BOffImm26Mask) |
   1794           ((off.encode() & Imm16Mask) << Imm16Shift) |
   1795           ((off.encode() >> 16) & 0x3ff);
   1796  }
   1797  uint32_t extractImm26Value() {
   1798    return extractBitField(Imm26Shift + Imm26Bits - 1, Imm26Shift);
   1799  }
   1800 };
   1801 
   1802 class ABIArgGenerator : public ABIArgGeneratorShared {
   1803 public:
   1804  explicit ABIArgGenerator(ABIKind kind)
   1805      : ABIArgGeneratorShared(kind),
   1806        intRegIndex_(0),
   1807        floatRegIndex_(0),
   1808        current_() {}
   1809 
   1810  ABIArg next(MIRType argType);
   1811  ABIArg& current() { return current_; }
   1812 
   1813 protected:
   1814  unsigned intRegIndex_;
   1815  unsigned floatRegIndex_;
   1816  ABIArg current_;
   1817 };
   1818 
   1819 class Assembler : public AssemblerLOONG64 {
   1820 public:
   1821  Assembler() : AssemblerLOONG64() {}
   1822 
   1823  static uintptr_t GetPointer(uint8_t*);
   1824 
   1825  using AssemblerLOONG64::bind;
   1826 
   1827  static void Bind(uint8_t* rawCode, const CodeLabel& label);
   1828 
   1829  void processCodeLabels(uint8_t* rawCode);
   1830 
   1831  static void TraceJumpRelocations(JSTracer* trc, JitCode* code,
   1832                                   CompactBufferReader& reader);
   1833  static void TraceDataRelocations(JSTracer* trc, JitCode* code,
   1834                                   CompactBufferReader& reader);
   1835 
   1836  void bind(InstImm* inst, uintptr_t branch, uintptr_t target);
   1837 
   1838  // Copy the assembly code to the given buffer, and perform any pending
   1839  // relocations relying on the target address.
   1840  void executableCopy(uint8_t* buffer);
   1841 
   1842  static uint32_t PatchWrite_NearCallSize();
   1843 
   1844  static uint64_t ExtractLoad64Value(Instruction* inst0);
   1845  static void UpdateLoad64Value(Instruction* inst0, uint64_t value);
   1846  static void WriteLoad64Instructions(Instruction* inst0, Register reg,
   1847                                      uint64_t value);
   1848 
   1849  static void PatchWrite_NearCall(CodeLocationLabel start,
   1850                                  CodeLocationLabel toCall);
   1851  static void PatchDataWithValueCheck(CodeLocationLabel label, ImmPtr newValue,
   1852                                      ImmPtr expectedValue);
   1853  static void PatchDataWithValueCheck(CodeLocationLabel label,
   1854                                      PatchedImmPtr newValue,
   1855                                      PatchedImmPtr expectedValue);
   1856 
   1857  static uint64_t ExtractInstructionImmediate(uint8_t* code);
   1858 
   1859  static void ToggleCall(CodeLocationLabel inst_, bool enabled);
   1860 };  // Assembler
   1861 
   1862 static const uint32_t NumIntArgRegs = 8;
   1863 static const uint32_t NumFloatArgRegs = 8;
   1864 
   1865 static inline bool GetIntArgReg(uint32_t usedIntArgs, Register* out) {
   1866  if (usedIntArgs < NumIntArgRegs) {
   1867    *out = Register::FromCode(a0.code() + usedIntArgs);
   1868    return true;
   1869  }
   1870  return false;
   1871 }
   1872 
   1873 static inline bool GetFloatArgReg(uint32_t usedFloatArgs, FloatRegister* out) {
   1874  if (usedFloatArgs < NumFloatArgRegs) {
   1875    *out = FloatRegister::FromCode(f0.code() + usedFloatArgs);
   1876    return true;
   1877  }
   1878  return false;
   1879 }
   1880 
   1881 // Get a register in which we plan to put a quantity that will be used as an
   1882 // integer argument. This differs from GetIntArgReg in that if we have no more
   1883 // actual argument registers to use we will fall back on using whatever
   1884 // CallTempReg* don't overlap the argument registers, and only fail once those
   1885 // run out too.
   1886 static inline bool GetTempRegForIntArg(uint32_t usedIntArgs,
   1887                                       uint32_t usedFloatArgs, Register* out) {
   1888  // NOTE: We can't properly determine which regs are used if there are
   1889  // float arguments. If this is needed, we will have to guess.
   1890  MOZ_ASSERT(usedFloatArgs == 0);
   1891 
   1892  if (GetIntArgReg(usedIntArgs, out)) {
   1893    return true;
   1894  }
   1895  // Unfortunately, we have to assume things about the point at which
   1896  // GetIntArgReg returns false, because we need to know how many registers it
   1897  // can allocate.
   1898  usedIntArgs -= NumIntArgRegs;
   1899  if (usedIntArgs >= NumCallTempNonArgRegs) {
   1900    return false;
   1901  }
   1902  *out = CallTempNonArgRegs[usedIntArgs];
   1903  return true;
   1904 }
   1905 
   1906 }  // namespace jit
   1907 }  // namespace js
   1908 
   1909 #endif /* jit_loong64_Assembler_loong64_h */