tor-browser

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

Assembler-loong64.cpp (96942B)


      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 #include "jit/loong64/Assembler-loong64.h"
      8 
      9 #include "mozilla/DebugOnly.h"
     10 #include "mozilla/Maybe.h"
     11 
     12 #include "gc/Marking.h"
     13 #include "jit/AutoWritableJitCode.h"
     14 #include "jit/ExecutableAllocator.h"
     15 #include "vm/Realm.h"
     16 #include "wasm/WasmFrame.h"
     17 
     18 using mozilla::DebugOnly;
     19 
     20 using namespace js;
     21 using namespace js::jit;
     22 
     23 ABIArg ABIArgGenerator::next(MIRType type) {
     24  switch (type) {
     25    case MIRType::Int32:
     26    case MIRType::Int64:
     27    case MIRType::Pointer:
     28    case MIRType::WasmAnyRef:
     29    case MIRType::WasmArrayData:
     30    case MIRType::StackResults: {
     31      if (intRegIndex_ == NumIntArgRegs) {
     32        current_ = ABIArg(stackOffset_);
     33        stackOffset_ += sizeof(uintptr_t);
     34        break;
     35      }
     36      current_ = ABIArg(Register::FromCode(intRegIndex_ + a0.encoding()));
     37      intRegIndex_++;
     38      break;
     39    }
     40    case MIRType::Float32:
     41    case MIRType::Double: {
     42      if (floatRegIndex_ == NumFloatArgRegs) {
     43        // LoongArch floating-point parameters calling convention:
     44        //   The first 8 floating-point parameters should be passed in f0-f7,
     45        //   and the rest will be passed like integer parameters.
     46        if (kind_ == ABIKind::System && intRegIndex_ != NumIntArgRegs) {
     47          current_ = ABIArg(Register::FromCode(intRegIndex_ + a0.encoding()));
     48          intRegIndex_++;
     49          break;
     50        }
     51        current_ = ABIArg(stackOffset_);
     52        stackOffset_ += sizeof(double);
     53        break;
     54      }
     55      current_ = ABIArg(FloatRegister(
     56          FloatRegisters::Encoding(floatRegIndex_ + f0.encoding()),
     57          type == MIRType::Double ? FloatRegisters::Double
     58                                  : FloatRegisters::Single));
     59      floatRegIndex_++;
     60      break;
     61    }
     62    case MIRType::Simd128: {
     63      MOZ_CRASH("LoongArch does not support simd yet.");
     64      break;
     65    }
     66    default:
     67      MOZ_CRASH("Unexpected argument type");
     68  }
     69  return current_;
     70 }
     71 
     72 // Encode a standard register when it is being used as rd, the rj, and
     73 // an extra register(rk). These should never be called with an InvalidReg.
     74 uint32_t js::jit::RJ(Register r) {
     75  MOZ_ASSERT(r != InvalidReg);
     76  return r.encoding() << RJShift;
     77 }
     78 
     79 uint32_t js::jit::RK(Register r) {
     80  MOZ_ASSERT(r != InvalidReg);
     81  return r.encoding() << RKShift;
     82 }
     83 
     84 uint32_t js::jit::RD(Register r) {
     85  MOZ_ASSERT(r != InvalidReg);
     86  return r.encoding() << RDShift;
     87 }
     88 
     89 uint32_t js::jit::FJ(FloatRegister r) { return r.encoding() << RJShift; }
     90 
     91 uint32_t js::jit::FK(FloatRegister r) { return r.encoding() << RKShift; }
     92 
     93 uint32_t js::jit::FD(FloatRegister r) { return r.encoding() << RDShift; }
     94 
     95 uint32_t js::jit::FA(FloatRegister r) { return r.encoding() << FAShift; }
     96 
     97 uint32_t js::jit::SA2(uint32_t value) {
     98  MOZ_ASSERT(value < 4);
     99  return (value & SA2Mask) << SAShift;
    100 }
    101 
    102 uint32_t js::jit::SA3(uint32_t value) {
    103  MOZ_ASSERT(value < 8);
    104  return (value & SA3Mask) << SAShift;
    105 }
    106 
    107 Register js::jit::toRK(Instruction& i) {
    108  return Register::FromCode(((i.encode() >> RKShift) & RKMask));
    109 }
    110 
    111 Register js::jit::toRJ(Instruction& i) {
    112  return Register::FromCode(((i.encode() >> RJShift) & RJMask));
    113 }
    114 
    115 Register js::jit::toRD(Instruction& i) {
    116  return Register::FromCode(((i.encode() >> RDShift) & RDMask));
    117 }
    118 
    119 Register js::jit::toR(Instruction& i) {
    120  return Register::FromCode(i.encode() & RegMask);
    121 }
    122 
    123 void InstImm::extractImm16(BOffImm16* dest) { *dest = BOffImm16(*this); }
    124 
    125 void AssemblerLOONG64::finish() {
    126  MOZ_ASSERT(!isFinished);
    127  isFinished = true;
    128 }
    129 
    130 bool AssemblerLOONG64::appendRawCode(const uint8_t* code, size_t numBytes) {
    131  return m_buffer.appendRawCode(code, numBytes);
    132 }
    133 
    134 bool AssemblerLOONG64::reserve(size_t size) {
    135  // This buffer uses fixed-size chunks so there's no point in reserving
    136  // now vs. on-demand.
    137  return !oom();
    138 }
    139 
    140 bool AssemblerLOONG64::swapBuffer(wasm::Bytes& bytes) {
    141  // For now, specialize to the one use case. As long as wasm::Bytes is a
    142  // Vector, not a linked-list of chunks, there's not much we can do other
    143  // than copy.
    144  MOZ_ASSERT(bytes.empty());
    145  if (!bytes.resize(bytesNeeded())) {
    146    return false;
    147  }
    148  m_buffer.executableCopy(bytes.begin());
    149  return true;
    150 }
    151 
    152 void AssemblerLOONG64::copyJumpRelocationTable(uint8_t* dest) {
    153  if (jumpRelocations_.length()) {
    154    memcpy(dest, jumpRelocations_.buffer(), jumpRelocations_.length());
    155  }
    156 }
    157 
    158 void AssemblerLOONG64::copyDataRelocationTable(uint8_t* dest) {
    159  if (dataRelocations_.length()) {
    160    memcpy(dest, dataRelocations_.buffer(), dataRelocations_.length());
    161  }
    162 }
    163 
    164 AssemblerLOONG64::Condition AssemblerLOONG64::InvertCondition(Condition cond) {
    165  switch (cond) {
    166    case Equal:
    167      return NotEqual;
    168    case NotEqual:
    169      return Equal;
    170    case Zero:
    171      return NonZero;
    172    case NonZero:
    173      return Zero;
    174    case LessThan:
    175      return GreaterThanOrEqual;
    176    case LessThanOrEqual:
    177      return GreaterThan;
    178    case GreaterThan:
    179      return LessThanOrEqual;
    180    case GreaterThanOrEqual:
    181      return LessThan;
    182    case Above:
    183      return BelowOrEqual;
    184    case AboveOrEqual:
    185      return Below;
    186    case Below:
    187      return AboveOrEqual;
    188    case BelowOrEqual:
    189      return Above;
    190    case Signed:
    191      return NotSigned;
    192    case NotSigned:
    193      return Signed;
    194    default:
    195      MOZ_CRASH("unexpected condition");
    196  }
    197 }
    198 
    199 AssemblerLOONG64::DoubleCondition AssemblerLOONG64::InvertCondition(
    200    DoubleCondition cond) {
    201  switch (cond) {
    202    case DoubleOrdered:
    203      return DoubleUnordered;
    204    case DoubleEqual:
    205      return DoubleNotEqualOrUnordered;
    206    case DoubleNotEqual:
    207      return DoubleEqualOrUnordered;
    208    case DoubleGreaterThan:
    209      return DoubleLessThanOrEqualOrUnordered;
    210    case DoubleGreaterThanOrEqual:
    211      return DoubleLessThanOrUnordered;
    212    case DoubleLessThan:
    213      return DoubleGreaterThanOrEqualOrUnordered;
    214    case DoubleLessThanOrEqual:
    215      return DoubleGreaterThanOrUnordered;
    216    case DoubleUnordered:
    217      return DoubleOrdered;
    218    case DoubleEqualOrUnordered:
    219      return DoubleNotEqual;
    220    case DoubleNotEqualOrUnordered:
    221      return DoubleEqual;
    222    case DoubleGreaterThanOrUnordered:
    223      return DoubleLessThanOrEqual;
    224    case DoubleGreaterThanOrEqualOrUnordered:
    225      return DoubleLessThan;
    226    case DoubleLessThanOrUnordered:
    227      return DoubleGreaterThanOrEqual;
    228    case DoubleLessThanOrEqualOrUnordered:
    229      return DoubleGreaterThan;
    230    default:
    231      MOZ_CRASH("unexpected condition");
    232  }
    233 }
    234 
    235 AssemblerLOONG64::Condition AssemblerLOONG64::SwapCmpOperandsCondition(
    236    Condition cond) {
    237  switch (cond) {
    238    case Equal:
    239    case NotEqual:
    240      return cond;
    241    case LessThan:
    242      return GreaterThan;
    243    case LessThanOrEqual:
    244      return GreaterThanOrEqual;
    245    case GreaterThan:
    246      return LessThan;
    247    case GreaterThanOrEqual:
    248      return LessThanOrEqual;
    249    case Above:
    250      return Below;
    251    case AboveOrEqual:
    252      return BelowOrEqual;
    253    case Below:
    254      return Above;
    255    case BelowOrEqual:
    256      return AboveOrEqual;
    257    default:
    258      MOZ_CRASH("no meaningful swapped-operand condition");
    259  }
    260 }
    261 
    262 BOffImm16::BOffImm16(InstImm inst)
    263    : data((inst.encode() >> Imm16Shift) & Imm16Mask) {}
    264 
    265 Instruction* BOffImm16::getDest(Instruction* src) const {
    266  return &src[(((int32_t)data << 16) >> 16) + 1];
    267 }
    268 
    269 bool AssemblerLOONG64::oom() const {
    270  return AssemblerShared::oom() || m_buffer.oom() || jumpRelocations_.oom() ||
    271         dataRelocations_.oom();
    272 }
    273 
    274 // Size of the instruction stream, in bytes.
    275 size_t AssemblerLOONG64::size() const { return m_buffer.size(); }
    276 
    277 // Size of the relocation table, in bytes.
    278 size_t AssemblerLOONG64::jumpRelocationTableBytes() const {
    279  return jumpRelocations_.length();
    280 }
    281 
    282 size_t AssemblerLOONG64::dataRelocationTableBytes() const {
    283  return dataRelocations_.length();
    284 }
    285 
    286 // Size of the data table, in bytes.
    287 size_t AssemblerLOONG64::bytesNeeded() const {
    288  return size() + jumpRelocationTableBytes() + dataRelocationTableBytes();
    289 }
    290 
    291 // write a blob of binary into the instruction stream
    292 BufferOffset AssemblerLOONG64::writeInst(uint32_t x, uint32_t* dest) {
    293  MOZ_ASSERT(hasCreator());
    294  if (dest == nullptr) {
    295    return m_buffer.putInt(x);
    296  }
    297 
    298  WriteInstStatic(x, dest);
    299  return BufferOffset();
    300 }
    301 
    302 void AssemblerLOONG64::WriteInstStatic(uint32_t x, uint32_t* dest) {
    303  MOZ_ASSERT(dest != nullptr);
    304  *dest = x;
    305 }
    306 
    307 BufferOffset AssemblerLOONG64::haltingAlign(int alignment) {
    308  // TODO(loong64): Implement a proper halting align.
    309  return nopAlign(alignment);
    310 }
    311 
    312 BufferOffset AssemblerLOONG64::nopAlign(int alignment) {
    313  BufferOffset ret;
    314  MOZ_ASSERT(m_buffer.isAligned(4));
    315  if (alignment == 8) {
    316    if (!m_buffer.isAligned(alignment)) {
    317      BufferOffset tmp = as_nop();
    318      if (!ret.assigned()) {
    319        ret = tmp;
    320      }
    321    }
    322  } else {
    323    MOZ_ASSERT((alignment & (alignment - 1)) == 0);
    324    while (size() & (alignment - 1)) {
    325      BufferOffset tmp = as_nop();
    326      if (!ret.assigned()) {
    327        ret = tmp;
    328      }
    329    }
    330  }
    331  return ret;
    332 }
    333 
    334 // Logical operations.
    335 BufferOffset AssemblerLOONG64::as_and(Register rd, Register rj, Register rk) {
    336  spew("and    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    337  return writeInst(InstReg(op_and, rk, rj, rd).encode());
    338 }
    339 
    340 BufferOffset AssemblerLOONG64::as_or(Register rd, Register rj, Register rk) {
    341  spew("or     %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    342  return writeInst(InstReg(op_or, rk, rj, rd).encode());
    343 }
    344 
    345 BufferOffset AssemblerLOONG64::as_xor(Register rd, Register rj, Register rk) {
    346  spew("xor    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    347  return writeInst(InstReg(op_xor, rk, rj, rd).encode());
    348 }
    349 
    350 BufferOffset AssemblerLOONG64::as_nor(Register rd, Register rj, Register rk) {
    351  spew("nor    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    352  return writeInst(InstReg(op_nor, rk, rj, rd).encode());
    353 }
    354 
    355 BufferOffset AssemblerLOONG64::as_andn(Register rd, Register rj, Register rk) {
    356  spew("andn    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    357  return writeInst(InstReg(op_andn, rk, rj, rd).encode());
    358 }
    359 
    360 BufferOffset AssemblerLOONG64::as_orn(Register rd, Register rj, Register rk) {
    361  spew("orn     %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    362  return writeInst(InstReg(op_orn, rk, rj, rd).encode());
    363 }
    364 
    365 BufferOffset AssemblerLOONG64::as_andi(Register rd, Register rj, int32_t ui12) {
    366  MOZ_ASSERT(is_uintN(ui12, 12));
    367  spew("andi   %3s,%3s,0x%x", rd.name(), rj.name(), ui12);
    368  return writeInst(InstImm(op_andi, ui12, rj, rd, 12).encode());
    369 }
    370 
    371 BufferOffset AssemblerLOONG64::as_ori(Register rd, Register rj, int32_t ui12) {
    372  MOZ_ASSERT(is_uintN(ui12, 12));
    373  spew("ori    %3s,%3s,0x%x", rd.name(), rj.name(), ui12);
    374  return writeInst(InstImm(op_ori, ui12, rj, rd, 12).encode());
    375 }
    376 
    377 BufferOffset AssemblerLOONG64::as_xori(Register rd, Register rj, int32_t ui12) {
    378  MOZ_ASSERT(is_uintN(ui12, 12));
    379  spew("xori   %3s,%3s,0x%x", rd.name(), rj.name(), ui12);
    380  return writeInst(InstImm(op_xori, ui12, rj, rd, 12).encode());
    381 }
    382 
    383 // Branch and jump instructions
    384 BufferOffset AssemblerLOONG64::as_b(JOffImm26 off) {
    385  spew("b    %d", off.decode());
    386  return writeInst(InstJump(op_b, off).encode());
    387 }
    388 
    389 BufferOffset AssemblerLOONG64::as_bl(JOffImm26 off) {
    390  spew("bl    %d", off.decode());
    391  return writeInst(InstJump(op_bl, off).encode());
    392 }
    393 
    394 BufferOffset AssemblerLOONG64::as_jirl(Register rd, Register rj,
    395                                       BOffImm16 off) {
    396  spew("jirl   %3s, %3s, %d", rd.name(), rj.name(), off.decode());
    397  return writeInst(InstImm(op_jirl, off, rj, rd).encode());
    398 }
    399 
    400 InstImm AssemblerLOONG64::getBranchCode(JumpOrCall jumpOrCall) {
    401  // jirl or beq
    402  if (jumpOrCall == BranchIsCall) {
    403    return InstImm(op_jirl, BOffImm16(0), zero, ra);
    404  }
    405 
    406  return InstImm(op_beq, BOffImm16(0), zero, zero);
    407 }
    408 
    409 InstImm AssemblerLOONG64::getBranchCode(Register rj, Register rd, Condition c) {
    410  // beq, bne
    411  MOZ_ASSERT(c == AssemblerLOONG64::Equal || c == AssemblerLOONG64::NotEqual);
    412  return InstImm(c == AssemblerLOONG64::Equal ? op_beq : op_bne, BOffImm16(0),
    413                 rj, rd);
    414 }
    415 
    416 InstImm AssemblerLOONG64::getBranchCode(Register rj, Condition c) {
    417  // beq, bne, blt, bge
    418  switch (c) {
    419    case AssemblerLOONG64::Equal:
    420    case AssemblerLOONG64::Zero:
    421    case AssemblerLOONG64::BelowOrEqual:
    422      return InstImm(op_beq, BOffImm16(0), rj, zero);
    423    case AssemblerLOONG64::NotEqual:
    424    case AssemblerLOONG64::NonZero:
    425    case AssemblerLOONG64::Above:
    426      return InstImm(op_bne, BOffImm16(0), rj, zero);
    427    case AssemblerLOONG64::GreaterThan:
    428      return InstImm(op_blt, BOffImm16(0), zero, rj);
    429    case AssemblerLOONG64::GreaterThanOrEqual:
    430    case AssemblerLOONG64::NotSigned:
    431      return InstImm(op_bge, BOffImm16(0), rj, zero);
    432    case AssemblerLOONG64::LessThan:
    433    case AssemblerLOONG64::Signed:
    434      return InstImm(op_blt, BOffImm16(0), rj, zero);
    435    case AssemblerLOONG64::LessThanOrEqual:
    436      return InstImm(op_bge, BOffImm16(0), zero, rj);
    437    default:
    438      MOZ_CRASH("Condition not supported.");
    439  }
    440 }
    441 
    442 // Code semantics must conform to compareFloatingpoint
    443 InstImm AssemblerLOONG64::getBranchCode(FPConditionBit cj) {
    444  return InstImm(op_bcz, 0, cj, true);  // bcnez
    445 }
    446 
    447 // Arithmetic instructions
    448 BufferOffset AssemblerLOONG64::as_add_w(Register rd, Register rj, Register rk) {
    449  spew("add_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    450  return writeInst(InstReg(op_add_w, rk, rj, rd).encode());
    451 }
    452 
    453 BufferOffset AssemblerLOONG64::as_add_d(Register rd, Register rj, Register rk) {
    454  spew("add_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    455  return writeInst(InstReg(op_add_d, rk, rj, rd).encode());
    456 }
    457 
    458 BufferOffset AssemblerLOONG64::as_sub_w(Register rd, Register rj, Register rk) {
    459  spew("sub_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    460  return writeInst(InstReg(op_sub_w, rk, rj, rd).encode());
    461 }
    462 
    463 BufferOffset AssemblerLOONG64::as_sub_d(Register rd, Register rj, Register rk) {
    464  spew("sub_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    465  return writeInst(InstReg(op_sub_d, rk, rj, rd).encode());
    466 }
    467 
    468 BufferOffset AssemblerLOONG64::as_addi_w(Register rd, Register rj,
    469                                         int32_t si12) {
    470  MOZ_ASSERT(is_intN(si12, 12));
    471  spew("addi_w   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    472  return writeInst(InstImm(op_addi_w, si12, rj, rd, 12).encode());
    473 }
    474 
    475 BufferOffset AssemblerLOONG64::as_addi_d(Register rd, Register rj,
    476                                         int32_t si12) {
    477  MOZ_ASSERT(is_intN(si12, 12));
    478  spew("addi_d   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    479  return writeInst(InstImm(op_addi_d, si12, rj, rd, 12).encode());
    480 }
    481 
    482 BufferOffset AssemblerLOONG64::as_addu16i_d(Register rd, Register rj,
    483                                            int32_t si16) {
    484  MOZ_ASSERT(Imm16::IsInSignedRange(si16));
    485  spew("addu16i_d   %3s,%3s,0x%x", rd.name(), rj.name(), si16);
    486  return writeInst(InstImm(op_addu16i_d, Imm16(si16), rj, rd).encode());
    487 }
    488 
    489 BufferOffset AssemblerLOONG64::as_alsl_w(Register rd, Register rj, Register rk,
    490                                         uint32_t sa2) {
    491  MOZ_ASSERT(sa2 < 4);
    492  spew("alsl_w   %3s,%3s,0x%x", rd.name(), rj.name(), sa2);
    493  return writeInst(InstReg(op_alsl_w, sa2, rk, rj, rd, 2).encode());
    494 }
    495 
    496 BufferOffset AssemblerLOONG64::as_alsl_wu(Register rd, Register rj, Register rk,
    497                                          uint32_t sa2) {
    498  MOZ_ASSERT(sa2 < 4);
    499  spew("alsl_wu   %3s,%3s,0x%x", rd.name(), rj.name(), sa2);
    500  return writeInst(InstReg(op_alsl_wu, sa2, rk, rj, rd, 2).encode());
    501 }
    502 
    503 BufferOffset AssemblerLOONG64::as_alsl_d(Register rd, Register rj, Register rk,
    504                                         uint32_t sa2) {
    505  MOZ_ASSERT(sa2 < 4);
    506  spew("alsl_d   %3s,%3s,%3s,0x%x", rd.name(), rj.name(), rk.name(), sa2);
    507  return writeInst(InstReg(op_alsl_d, sa2, rk, rj, rd, 2).encode());
    508 }
    509 
    510 BufferOffset AssemblerLOONG64::as_lu12i_w(Register rd, int32_t si20) {
    511  spew("lu12i_w   %3s,0x%x", rd.name(), si20);
    512  return writeInst(InstImm(op_lu12i_w, si20, rd, false).encode());
    513 }
    514 
    515 BufferOffset AssemblerLOONG64::as_lu32i_d(Register rd, int32_t si20) {
    516  spew("lu32i_d   %3s,0x%x", rd.name(), si20);
    517  return writeInst(InstImm(op_lu32i_d, si20, rd, false).encode());
    518 }
    519 
    520 BufferOffset AssemblerLOONG64::as_lu52i_d(Register rd, Register rj,
    521                                          int32_t si12) {
    522  MOZ_ASSERT(is_uintN(si12, 12));
    523  spew("lu52i_d   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    524  return writeInst(InstImm(op_lu52i_d, si12, rj, rd, 12).encode());
    525 }
    526 
    527 BufferOffset AssemblerLOONG64::as_slt(Register rd, Register rj, Register rk) {
    528  spew("slt   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    529  return writeInst(InstReg(op_slt, rk, rj, rd).encode());
    530 }
    531 
    532 BufferOffset AssemblerLOONG64::as_sltu(Register rd, Register rj, Register rk) {
    533  spew("sltu   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    534  return writeInst(InstReg(op_sltu, rk, rj, rd).encode());
    535 }
    536 
    537 BufferOffset AssemblerLOONG64::as_slti(Register rd, Register rj, int32_t si12) {
    538  MOZ_ASSERT(is_intN(si12, 12));
    539  spew("slti   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    540  return writeInst(InstImm(op_slti, si12, rj, rd, 12).encode());
    541 }
    542 
    543 BufferOffset AssemblerLOONG64::as_sltui(Register rd, Register rj,
    544                                        int32_t si12) {
    545  MOZ_ASSERT(is_intN(si12, 12));
    546  spew("sltui   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    547  return writeInst(InstImm(op_sltui, si12, rj, rd, 12).encode());
    548 }
    549 
    550 BufferOffset AssemblerLOONG64::as_pcaddi(Register rd, int32_t si20) {
    551  spew("pcaddi   %3s,0x%x", rd.name(), si20);
    552  return writeInst(InstImm(op_pcaddi, si20, rd, false).encode());
    553 }
    554 
    555 BufferOffset AssemblerLOONG64::as_pcaddu12i(Register rd, int32_t si20) {
    556  spew("pcaddu12i   %3s,0x%x", rd.name(), si20);
    557  return writeInst(InstImm(op_pcaddu12i, si20, rd, false).encode());
    558 }
    559 
    560 BufferOffset AssemblerLOONG64::as_pcaddu18i(Register rd, int32_t si20) {
    561  spew("pcaddu18i   %3s,0x%x", rd.name(), si20);
    562  return writeInst(InstImm(op_pcaddu18i, si20, rd, false).encode());
    563 }
    564 
    565 BufferOffset AssemblerLOONG64::as_pcalau12i(Register rd, int32_t si20) {
    566  spew("pcalau12i   %3s,0x%x", rd.name(), si20);
    567  return writeInst(InstImm(op_pcalau12i, si20, rd, false).encode());
    568 }
    569 
    570 BufferOffset AssemblerLOONG64::as_mul_w(Register rd, Register rj, Register rk) {
    571  spew("mul_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    572  return writeInst(InstReg(op_mul_w, rk, rj, rd).encode());
    573 }
    574 
    575 BufferOffset AssemblerLOONG64::as_mulh_w(Register rd, Register rj,
    576                                         Register rk) {
    577  spew("mulh_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    578  return writeInst(InstReg(op_mulh_w, rk, rj, rd).encode());
    579 }
    580 
    581 BufferOffset AssemblerLOONG64::as_mulh_wu(Register rd, Register rj,
    582                                          Register rk) {
    583  spew("mulh_wu   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    584  return writeInst(InstReg(op_mulh_wu, rk, rj, rd).encode());
    585 }
    586 
    587 BufferOffset AssemblerLOONG64::as_mul_d(Register rd, Register rj, Register rk) {
    588  spew("mul_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    589  return writeInst(InstReg(op_mul_d, rk, rj, rd).encode());
    590 }
    591 
    592 BufferOffset AssemblerLOONG64::as_mulh_d(Register rd, Register rj,
    593                                         Register rk) {
    594  spew("mulh_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    595  return writeInst(InstReg(op_mulh_d, rk, rj, rd).encode());
    596 }
    597 
    598 BufferOffset AssemblerLOONG64::as_mulh_du(Register rd, Register rj,
    599                                          Register rk) {
    600  spew("mulh_du   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    601  return writeInst(InstReg(op_mulh_du, rk, rj, rd).encode());
    602 }
    603 
    604 BufferOffset AssemblerLOONG64::as_mulw_d_w(Register rd, Register rj,
    605                                           Register rk) {
    606  spew("mulw_d_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    607  return writeInst(InstReg(op_mulw_d_w, rk, rj, rd).encode());
    608 }
    609 
    610 BufferOffset AssemblerLOONG64::as_mulw_d_wu(Register rd, Register rj,
    611                                            Register rk) {
    612  spew("mulw_d_wu   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    613  return writeInst(InstReg(op_mulw_d_wu, rk, rj, rd).encode());
    614 }
    615 
    616 BufferOffset AssemblerLOONG64::as_div_w(Register rd, Register rj, Register rk) {
    617  spew("div_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    618  return writeInst(InstReg(op_div_w, rk, rj, rd).encode());
    619 }
    620 
    621 BufferOffset AssemblerLOONG64::as_mod_w(Register rd, Register rj, Register rk) {
    622  spew("mod_w   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    623  return writeInst(InstReg(op_mod_w, rk, rj, rd).encode());
    624 }
    625 
    626 BufferOffset AssemblerLOONG64::as_div_wu(Register rd, Register rj,
    627                                         Register rk) {
    628  spew("div_wu   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    629  return writeInst(InstReg(op_div_wu, rk, rj, rd).encode());
    630 }
    631 
    632 BufferOffset AssemblerLOONG64::as_mod_wu(Register rd, Register rj,
    633                                         Register rk) {
    634  spew("mod_wu   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    635  return writeInst(InstReg(op_mod_wu, rk, rj, rd).encode());
    636 }
    637 
    638 BufferOffset AssemblerLOONG64::as_div_d(Register rd, Register rj, Register rk) {
    639  spew("div_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    640  return writeInst(InstReg(op_div_d, rk, rj, rd).encode());
    641 }
    642 
    643 BufferOffset AssemblerLOONG64::as_mod_d(Register rd, Register rj, Register rk) {
    644  spew("mod_d   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    645  return writeInst(InstReg(op_mod_d, rk, rj, rd).encode());
    646 }
    647 
    648 BufferOffset AssemblerLOONG64::as_div_du(Register rd, Register rj,
    649                                         Register rk) {
    650  spew("div_du   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    651  return writeInst(InstReg(op_div_du, rk, rj, rd).encode());
    652 }
    653 
    654 BufferOffset AssemblerLOONG64::as_mod_du(Register rd, Register rj,
    655                                         Register rk) {
    656  spew("mod_du   %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    657  return writeInst(InstReg(op_mod_du, rk, rj, rd).encode());
    658 }
    659 
    660 // Shift instructions
    661 BufferOffset AssemblerLOONG64::as_sll_w(Register rd, Register rj, Register rk) {
    662  spew("sll_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    663  return writeInst(InstReg(op_sll_w, rk, rj, rd).encode());
    664 }
    665 
    666 BufferOffset AssemblerLOONG64::as_srl_w(Register rd, Register rj, Register rk) {
    667  spew("srl_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    668  return writeInst(InstReg(op_srl_w, rk, rj, rd).encode());
    669 }
    670 
    671 BufferOffset AssemblerLOONG64::as_sra_w(Register rd, Register rj, Register rk) {
    672  spew("sra_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    673  return writeInst(InstReg(op_sra_w, rk, rj, rd).encode());
    674 }
    675 
    676 BufferOffset AssemblerLOONG64::as_rotr_w(Register rd, Register rj,
    677                                         Register rk) {
    678  spew("rotr_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    679  return writeInst(InstReg(op_rotr_w, rk, rj, rd).encode());
    680 }
    681 
    682 BufferOffset AssemblerLOONG64::as_slli_w(Register rd, Register rj,
    683                                         int32_t ui5) {
    684  MOZ_ASSERT(is_uintN(ui5, 5));
    685  spew("slli_w   %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
    686  return writeInst(InstImm(op_slli_w, ui5, rj, rd, 5).encode());
    687 }
    688 
    689 BufferOffset AssemblerLOONG64::as_srli_w(Register rd, Register rj,
    690                                         int32_t ui5) {
    691  MOZ_ASSERT(is_uintN(ui5, 5));
    692  spew("srli_w   %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
    693  return writeInst(InstImm(op_srli_w, ui5, rj, rd, 5).encode());
    694 }
    695 
    696 BufferOffset AssemblerLOONG64::as_srai_w(Register rd, Register rj,
    697                                         int32_t ui5) {
    698  MOZ_ASSERT(is_uintN(ui5, 5));
    699  spew("srai_w   %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
    700  return writeInst(InstImm(op_srai_w, ui5, rj, rd, 5).encode());
    701 }
    702 
    703 BufferOffset AssemblerLOONG64::as_rotri_w(Register rd, Register rj,
    704                                          int32_t ui5) {
    705  MOZ_ASSERT(is_uintN(ui5, 5));
    706  spew("rotri_w   %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
    707  return writeInst(InstImm(op_rotri_w, ui5, rj, rd, 5).encode());
    708 }
    709 
    710 BufferOffset AssemblerLOONG64::as_sll_d(Register rd, Register rj, Register rk) {
    711  spew("sll_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    712  return writeInst(InstReg(op_sll_d, rk, rj, rd).encode());
    713 }
    714 
    715 BufferOffset AssemblerLOONG64::as_srl_d(Register rd, Register rj, Register rk) {
    716  spew("srl_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    717  return writeInst(InstReg(op_srl_d, rk, rj, rd).encode());
    718 }
    719 
    720 BufferOffset AssemblerLOONG64::as_sra_d(Register rd, Register rj, Register rk) {
    721  spew("sra_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    722  return writeInst(InstReg(op_sra_d, rk, rj, rd).encode());
    723 }
    724 
    725 BufferOffset AssemblerLOONG64::as_rotr_d(Register rd, Register rj,
    726                                         Register rk) {
    727  spew("rotr_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    728  return writeInst(InstReg(op_rotr_d, rk, rj, rd).encode());
    729 }
    730 
    731 BufferOffset AssemblerLOONG64::as_slli_d(Register rd, Register rj,
    732                                         int32_t ui6) {
    733  MOZ_ASSERT(is_uintN(ui6, 6));
    734  spew("slli_d   %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
    735  return writeInst(InstImm(op_slli_d, ui6, rj, rd, 6).encode());
    736 }
    737 
    738 BufferOffset AssemblerLOONG64::as_srli_d(Register rd, Register rj,
    739                                         int32_t ui6) {
    740  MOZ_ASSERT(is_uintN(ui6, 6));
    741  spew("srli_d   %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
    742  return writeInst(InstImm(op_srli_d, ui6, rj, rd, 6).encode());
    743 }
    744 
    745 BufferOffset AssemblerLOONG64::as_srai_d(Register rd, Register rj,
    746                                         int32_t ui6) {
    747  MOZ_ASSERT(is_uintN(ui6, 6));
    748  spew("srai_d   %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
    749  return writeInst(InstImm(op_srai_d, ui6, rj, rd, 6).encode());
    750 }
    751 
    752 BufferOffset AssemblerLOONG64::as_rotri_d(Register rd, Register rj,
    753                                          int32_t ui6) {
    754  MOZ_ASSERT(is_uintN(ui6, 6));
    755  spew("rotri_d   %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
    756  return writeInst(InstImm(op_rotri_d, ui6, rj, rd, 6).encode());
    757 }
    758 
    759 // Bit operation instrucitons
    760 BufferOffset AssemblerLOONG64::as_ext_w_b(Register rd, Register rj) {
    761  spew("ext_w_b    %3s,%3s", rd.name(), rj.name());
    762  return writeInst(InstReg(op_ext_w_b, rj, rd).encode());
    763 }
    764 
    765 BufferOffset AssemblerLOONG64::as_ext_w_h(Register rd, Register rj) {
    766  spew("ext_w_h    %3s,%3s", rd.name(), rj.name());
    767  return writeInst(InstReg(op_ext_w_h, rj, rd).encode());
    768 }
    769 
    770 BufferOffset AssemblerLOONG64::as_clo_w(Register rd, Register rj) {
    771  spew("clo_w    %3s,%3s", rd.name(), rj.name());
    772  return writeInst(InstReg(op_clo_w, rj, rd).encode());
    773 }
    774 
    775 BufferOffset AssemblerLOONG64::as_clz_w(Register rd, Register rj) {
    776  spew("clz_w    %3s,%3s", rd.name(), rj.name());
    777  return writeInst(InstReg(op_clz_w, rj, rd).encode());
    778 }
    779 
    780 BufferOffset AssemblerLOONG64::as_cto_w(Register rd, Register rj) {
    781  spew("cto_w    %3s,%3s", rd.name(), rj.name());
    782  return writeInst(InstReg(op_cto_w, rj, rd).encode());
    783 }
    784 
    785 BufferOffset AssemblerLOONG64::as_ctz_w(Register rd, Register rj) {
    786  spew("ctz_w    %3s,%3s", rd.name(), rj.name());
    787  return writeInst(InstReg(op_ctz_w, rj, rd).encode());
    788 }
    789 
    790 BufferOffset AssemblerLOONG64::as_clo_d(Register rd, Register rj) {
    791  spew("clo_d    %3s,%3s", rd.name(), rj.name());
    792  return writeInst(InstReg(op_clo_d, rj, rd).encode());
    793 }
    794 
    795 BufferOffset AssemblerLOONG64::as_clz_d(Register rd, Register rj) {
    796  spew("clz_d    %3s,%3s", rd.name(), rj.name());
    797  return writeInst(InstReg(op_clz_d, rj, rd).encode());
    798 }
    799 
    800 BufferOffset AssemblerLOONG64::as_cto_d(Register rd, Register rj) {
    801  spew("cto_d    %3s,%3s", rd.name(), rj.name());
    802  return writeInst(InstReg(op_cto_d, rj, rd).encode());
    803 }
    804 
    805 BufferOffset AssemblerLOONG64::as_ctz_d(Register rd, Register rj) {
    806  spew("ctz_d    %3s,%3s", rd.name(), rj.name());
    807  return writeInst(InstReg(op_ctz_d, rj, rd).encode());
    808 }
    809 
    810 BufferOffset AssemblerLOONG64::as_bytepick_w(Register rd, Register rj,
    811                                             Register rk, int32_t sa2) {
    812  MOZ_ASSERT(sa2 < 4);
    813  spew("bytepick_w    %3s,%3s,%3s, 0x%x", rd.name(), rj.name(), rk.name(), sa2);
    814  return writeInst(InstReg(op_bytepick_w, sa2, rk, rj, rd, 2).encode());
    815 }
    816 
    817 BufferOffset AssemblerLOONG64::as_bytepick_d(Register rd, Register rj,
    818                                             Register rk, int32_t sa3) {
    819  MOZ_ASSERT(sa3 < 8);
    820  spew("bytepick_d    %3s,%3s,%3s, 0x%x", rd.name(), rj.name(), rk.name(), sa3);
    821  return writeInst(InstReg(op_bytepick_d, sa3, rk, rj, rd, 3).encode());
    822 }
    823 
    824 BufferOffset AssemblerLOONG64::as_revb_2h(Register rd, Register rj) {
    825  spew("revb_2h    %3s,%3s", rd.name(), rj.name());
    826  return writeInst(InstReg(op_revb_2h, rj, rd).encode());
    827 }
    828 
    829 BufferOffset AssemblerLOONG64::as_revb_4h(Register rd, Register rj) {
    830  spew("revb_4h    %3s,%3s", rd.name(), rj.name());
    831  return writeInst(InstReg(op_revb_4h, rj, rd).encode());
    832 }
    833 
    834 BufferOffset AssemblerLOONG64::as_revb_2w(Register rd, Register rj) {
    835  spew("revb_2w    %3s,%3s", rd.name(), rj.name());
    836  return writeInst(InstReg(op_revb_2w, rj, rd).encode());
    837 }
    838 
    839 BufferOffset AssemblerLOONG64::as_revb_d(Register rd, Register rj) {
    840  spew("revb_d    %3s,%3s", rd.name(), rj.name());
    841  return writeInst(InstReg(op_revb_d, rj, rd).encode());
    842 }
    843 
    844 BufferOffset AssemblerLOONG64::as_revh_2w(Register rd, Register rj) {
    845  spew("revh_2w    %3s,%3s", rd.name(), rj.name());
    846  return writeInst(InstReg(op_revh_2w, rj, rd).encode());
    847 }
    848 
    849 BufferOffset AssemblerLOONG64::as_revh_d(Register rd, Register rj) {
    850  spew("revh_d    %3s,%3s", rd.name(), rj.name());
    851  return writeInst(InstReg(op_revh_d, rj, rd).encode());
    852 }
    853 
    854 BufferOffset AssemblerLOONG64::as_bitrev_4b(Register rd, Register rj) {
    855  spew("bitrev_4b    %3s,%3s", rd.name(), rj.name());
    856  return writeInst(InstReg(op_bitrev_4b, rj, rd).encode());
    857 }
    858 
    859 BufferOffset AssemblerLOONG64::as_bitrev_8b(Register rd, Register rj) {
    860  spew("bitrev_8b    %3s,%3s", rd.name(), rj.name());
    861  return writeInst(InstReg(op_bitrev_8b, rj, rd).encode());
    862 }
    863 
    864 BufferOffset AssemblerLOONG64::as_bitrev_w(Register rd, Register rj) {
    865  spew("bitrev_w    %3s,%3s", rd.name(), rj.name());
    866  return writeInst(InstReg(op_bitrev_w, rj, rd).encode());
    867 }
    868 
    869 BufferOffset AssemblerLOONG64::as_bitrev_d(Register rd, Register rj) {
    870  spew("bitrev_d    %3s,%3s", rd.name(), rj.name());
    871  return writeInst(InstReg(op_bitrev_d, rj, rd).encode());
    872 }
    873 
    874 BufferOffset AssemblerLOONG64::as_bstrins_w(Register rd, Register rj,
    875                                            int32_t msbw, int32_t lsbw) {
    876  MOZ_ASSERT(lsbw <= msbw);
    877  spew("bstrins_w   %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbw, lsbw);
    878  return writeInst(InstImm(op_bstr_w, msbw, lsbw, rj, rd, 5).encode());
    879 }
    880 
    881 BufferOffset AssemblerLOONG64::as_bstrins_d(Register rd, Register rj,
    882                                            int32_t msbd, int32_t lsbd) {
    883  MOZ_ASSERT(lsbd <= msbd);
    884  spew("bstrins_d   %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbd, lsbd);
    885  return writeInst(InstImm(op_bstrins_d, msbd, lsbd, rj, rd, 6).encode());
    886 }
    887 
    888 BufferOffset AssemblerLOONG64::as_bstrpick_w(Register rd, Register rj,
    889                                             int32_t msbw, int32_t lsbw) {
    890  MOZ_ASSERT(lsbw <= msbw);
    891  spew("bstrpick_w   %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbw, lsbw);
    892  return writeInst(InstImm(op_bstr_w, msbw, lsbw, rj, rd).encode());
    893 }
    894 
    895 BufferOffset AssemblerLOONG64::as_bstrpick_d(Register rd, Register rj,
    896                                             int32_t msbd, int32_t lsbd) {
    897  MOZ_ASSERT(lsbd <= msbd);
    898  spew("bstrpick_d   %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbd, lsbd);
    899  return writeInst(InstImm(op_bstrpick_d, msbd, lsbd, rj, rd, 6).encode());
    900 }
    901 
    902 BufferOffset AssemblerLOONG64::as_maskeqz(Register rd, Register rj,
    903                                          Register rk) {
    904  spew("maskeqz    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    905  return writeInst(InstReg(op_maskeqz, rk, rj, rd).encode());
    906 }
    907 
    908 BufferOffset AssemblerLOONG64::as_masknez(Register rd, Register rj,
    909                                          Register rk) {
    910  spew("masknez    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    911  return writeInst(InstReg(op_masknez, rk, rj, rd).encode());
    912 }
    913 
    914 // Load and store instructions
    915 BufferOffset AssemblerLOONG64::as_ld_b(Register rd, Register rj, int32_t si12) {
    916  MOZ_ASSERT(is_intN(si12, 12));
    917  spew("ld_b   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    918  return writeInst(InstImm(op_ld_b, si12, rj, rd, 12).encode());
    919 }
    920 
    921 BufferOffset AssemblerLOONG64::as_ld_h(Register rd, Register rj, int32_t si12) {
    922  MOZ_ASSERT(is_intN(si12, 12));
    923  spew("ld_h   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    924  return writeInst(InstImm(op_ld_h, si12, rj, rd, 12).encode());
    925 }
    926 
    927 BufferOffset AssemblerLOONG64::as_ld_w(Register rd, Register rj, int32_t si12) {
    928  MOZ_ASSERT(is_intN(si12, 12));
    929  spew("ld_w   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    930  return writeInst(InstImm(op_ld_w, si12, rj, rd, 12).encode());
    931 }
    932 
    933 BufferOffset AssemblerLOONG64::as_ld_d(Register rd, Register rj, int32_t si12) {
    934  MOZ_ASSERT(is_intN(si12, 12));
    935  spew("ld_d   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    936  return writeInst(InstImm(op_ld_d, si12, rj, rd, 12).encode());
    937 }
    938 
    939 BufferOffset AssemblerLOONG64::as_ld_bu(Register rd, Register rj,
    940                                        int32_t si12) {
    941  MOZ_ASSERT(is_intN(si12, 12));
    942  spew("ld_bu   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    943  return writeInst(InstImm(op_ld_bu, si12, rj, rd, 12).encode());
    944 }
    945 
    946 BufferOffset AssemblerLOONG64::as_ld_hu(Register rd, Register rj,
    947                                        int32_t si12) {
    948  MOZ_ASSERT(is_intN(si12, 12));
    949  spew("ld_hu   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    950  return writeInst(InstImm(op_ld_hu, si12, rj, rd, 12).encode());
    951 }
    952 
    953 BufferOffset AssemblerLOONG64::as_ld_wu(Register rd, Register rj,
    954                                        int32_t si12) {
    955  MOZ_ASSERT(is_intN(si12, 12));
    956  spew("ld_wu   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    957  return writeInst(InstImm(op_ld_wu, si12, rj, rd, 12).encode());
    958 }
    959 
    960 BufferOffset AssemblerLOONG64::as_st_b(Register rd, Register rj, int32_t si12) {
    961  MOZ_ASSERT(is_intN(si12, 12));
    962  spew("st_b   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    963  return writeInst(InstImm(op_st_b, si12, rj, rd, 12).encode());
    964 }
    965 
    966 BufferOffset AssemblerLOONG64::as_st_h(Register rd, Register rj, int32_t si12) {
    967  MOZ_ASSERT(is_intN(si12, 12));
    968  spew("st_h   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    969  return writeInst(InstImm(op_st_h, si12, rj, rd, 12).encode());
    970 }
    971 
    972 BufferOffset AssemblerLOONG64::as_st_w(Register rd, Register rj, int32_t si12) {
    973  MOZ_ASSERT(is_intN(si12, 12));
    974  spew("st_w   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    975  return writeInst(InstImm(op_st_w, si12, rj, rd, 12).encode());
    976 }
    977 
    978 BufferOffset AssemblerLOONG64::as_st_d(Register rd, Register rj, int32_t si12) {
    979  MOZ_ASSERT(is_intN(si12, 12));
    980  spew("st_d   %3s,%3s,0x%x", rd.name(), rj.name(), si12);
    981  return writeInst(InstImm(op_st_d, si12, rj, rd, 12).encode());
    982 }
    983 
    984 BufferOffset AssemblerLOONG64::as_ldx_b(Register rd, Register rj, Register rk) {
    985  spew("ldx_b    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    986  return writeInst(InstReg(op_ldx_b, rk, rj, rd).encode());
    987 }
    988 
    989 BufferOffset AssemblerLOONG64::as_ldx_h(Register rd, Register rj, Register rk) {
    990  spew("ldx_h    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    991  return writeInst(InstReg(op_ldx_h, rk, rj, rd).encode());
    992 }
    993 
    994 BufferOffset AssemblerLOONG64::as_ldx_w(Register rd, Register rj, Register rk) {
    995  spew("ldx_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
    996  return writeInst(InstReg(op_ldx_w, rk, rj, rd).encode());
    997 }
    998 
    999 BufferOffset AssemblerLOONG64::as_ldx_d(Register rd, Register rj, Register rk) {
   1000  spew("ldx_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1001  return writeInst(InstReg(op_ldx_d, rk, rj, rd).encode());
   1002 }
   1003 
   1004 BufferOffset AssemblerLOONG64::as_ldx_bu(Register rd, Register rj,
   1005                                         Register rk) {
   1006  spew("ldx_bu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1007  return writeInst(InstReg(op_ldx_bu, rk, rj, rd).encode());
   1008 }
   1009 
   1010 BufferOffset AssemblerLOONG64::as_ldx_hu(Register rd, Register rj,
   1011                                         Register rk) {
   1012  spew("ldx_hu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1013  return writeInst(InstReg(op_ldx_hu, rk, rj, rd).encode());
   1014 }
   1015 
   1016 BufferOffset AssemblerLOONG64::as_ldx_wu(Register rd, Register rj,
   1017                                         Register rk) {
   1018  spew("ldx_wu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1019  return writeInst(InstReg(op_ldx_wu, rk, rj, rd).encode());
   1020 }
   1021 
   1022 BufferOffset AssemblerLOONG64::as_stx_b(Register rd, Register rj, Register rk) {
   1023  spew("stx_b    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1024  return writeInst(InstReg(op_stx_b, rk, rj, rd).encode());
   1025 }
   1026 
   1027 BufferOffset AssemblerLOONG64::as_stx_h(Register rd, Register rj, Register rk) {
   1028  spew("stx_h    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1029  return writeInst(InstReg(op_stx_h, rk, rj, rd).encode());
   1030 }
   1031 
   1032 BufferOffset AssemblerLOONG64::as_stx_w(Register rd, Register rj, Register rk) {
   1033  spew("stx_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1034  return writeInst(InstReg(op_stx_w, rk, rj, rd).encode());
   1035 }
   1036 
   1037 BufferOffset AssemblerLOONG64::as_stx_d(Register rd, Register rj, Register rk) {
   1038  spew("stx_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1039  return writeInst(InstReg(op_stx_d, rk, rj, rd).encode());
   1040 }
   1041 
   1042 BufferOffset AssemblerLOONG64::as_ldptr_w(Register rd, Register rj,
   1043                                          int32_t si14) {
   1044  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
   1045  spew("ldptr_w   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
   1046  return writeInst(InstImm(op_ldptr_w, si14 >> 2, rj, rd, 14).encode());
   1047 }
   1048 
   1049 BufferOffset AssemblerLOONG64::as_ldptr_d(Register rd, Register rj,
   1050                                          int32_t si14) {
   1051  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
   1052  spew("ldptr_d   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
   1053  return writeInst(InstImm(op_ldptr_d, si14 >> 2, rj, rd, 14).encode());
   1054 }
   1055 
   1056 BufferOffset AssemblerLOONG64::as_stptr_w(Register rd, Register rj,
   1057                                          int32_t si14) {
   1058  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
   1059  spew("stptr_w   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
   1060  return writeInst(InstImm(op_stptr_w, si14 >> 2, rj, rd, 14).encode());
   1061 }
   1062 
   1063 BufferOffset AssemblerLOONG64::as_stptr_d(Register rd, Register rj,
   1064                                          int32_t si14) {
   1065  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
   1066  spew("stptr_d   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
   1067  return writeInst(InstImm(op_stptr_d, si14 >> 2, rj, rd, 14).encode());
   1068 }
   1069 
   1070 BufferOffset AssemblerLOONG64::as_preld(int32_t hint, Register rj,
   1071                                        int32_t si12) {
   1072  MOZ_ASSERT(is_intN(si12, 12));
   1073  spew("preld   0x%x,%3s,0x%x", hint, rj.name(), si12);
   1074  return writeInst(InstImm(op_preld, si12, rj, hint).encode());
   1075 }
   1076 
   1077 // Atomic instructions
   1078 BufferOffset AssemblerLOONG64::as_amswap_w(Register rd, Register rj,
   1079                                           Register rk) {
   1080  spew("amswap_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1081  return writeInst(InstReg(op_amswap_w, rk, rj, rd).encode());
   1082 }
   1083 
   1084 BufferOffset AssemblerLOONG64::as_amswap_d(Register rd, Register rj,
   1085                                           Register rk) {
   1086  spew("amswap_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1087  return writeInst(InstReg(op_amswap_d, rk, rj, rd).encode());
   1088 }
   1089 
   1090 BufferOffset AssemblerLOONG64::as_amadd_w(Register rd, Register rj,
   1091                                          Register rk) {
   1092  spew("amadd_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1093  return writeInst(InstReg(op_amadd_w, rk, rj, rd).encode());
   1094 }
   1095 
   1096 BufferOffset AssemblerLOONG64::as_amadd_d(Register rd, Register rj,
   1097                                          Register rk) {
   1098  spew("amadd_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1099  return writeInst(InstReg(op_amadd_d, rk, rj, rd).encode());
   1100 }
   1101 
   1102 BufferOffset AssemblerLOONG64::as_amand_w(Register rd, Register rj,
   1103                                          Register rk) {
   1104  spew("amand_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1105  return writeInst(InstReg(op_amand_w, rk, rj, rd).encode());
   1106 }
   1107 
   1108 BufferOffset AssemblerLOONG64::as_amand_d(Register rd, Register rj,
   1109                                          Register rk) {
   1110  spew("amand_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1111  return writeInst(InstReg(op_amand_d, rk, rj, rd).encode());
   1112 }
   1113 
   1114 BufferOffset AssemblerLOONG64::as_amor_w(Register rd, Register rj,
   1115                                         Register rk) {
   1116  spew("amor_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1117  return writeInst(InstReg(op_amor_w, rk, rj, rd).encode());
   1118 }
   1119 
   1120 BufferOffset AssemblerLOONG64::as_amor_d(Register rd, Register rj,
   1121                                         Register rk) {
   1122  spew("amor_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1123  return writeInst(InstReg(op_amor_d, rk, rj, rd).encode());
   1124 }
   1125 
   1126 BufferOffset AssemblerLOONG64::as_amxor_w(Register rd, Register rj,
   1127                                          Register rk) {
   1128  spew("amxor_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1129  return writeInst(InstReg(op_amxor_w, rk, rj, rd).encode());
   1130 }
   1131 
   1132 BufferOffset AssemblerLOONG64::as_amxor_d(Register rd, Register rj,
   1133                                          Register rk) {
   1134  spew("amxor_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1135  return writeInst(InstReg(op_amxor_d, rk, rj, rd).encode());
   1136 }
   1137 
   1138 BufferOffset AssemblerLOONG64::as_ammax_w(Register rd, Register rj,
   1139                                          Register rk) {
   1140  spew("ammax_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1141  return writeInst(InstReg(op_ammax_w, rk, rj, rd).encode());
   1142 }
   1143 
   1144 BufferOffset AssemblerLOONG64::as_ammax_d(Register rd, Register rj,
   1145                                          Register rk) {
   1146  spew("ammax_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1147  return writeInst(InstReg(op_ammax_d, rk, rj, rd).encode());
   1148 }
   1149 
   1150 BufferOffset AssemblerLOONG64::as_ammin_w(Register rd, Register rj,
   1151                                          Register rk) {
   1152  spew("ammin_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1153  return writeInst(InstReg(op_ammin_w, rk, rj, rd).encode());
   1154 }
   1155 
   1156 BufferOffset AssemblerLOONG64::as_ammin_d(Register rd, Register rj,
   1157                                          Register rk) {
   1158  spew("ammin_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1159  return writeInst(InstReg(op_ammin_d, rk, rj, rd).encode());
   1160 }
   1161 
   1162 BufferOffset AssemblerLOONG64::as_ammax_wu(Register rd, Register rj,
   1163                                           Register rk) {
   1164  spew("ammax_wu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1165  return writeInst(InstReg(op_ammax_wu, rk, rj, rd).encode());
   1166 }
   1167 
   1168 BufferOffset AssemblerLOONG64::as_ammax_du(Register rd, Register rj,
   1169                                           Register rk) {
   1170  spew("ammax_du    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1171  return writeInst(InstReg(op_ammax_du, rk, rj, rd).encode());
   1172 }
   1173 
   1174 BufferOffset AssemblerLOONG64::as_ammin_wu(Register rd, Register rj,
   1175                                           Register rk) {
   1176  spew("ammin_wu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1177  return writeInst(InstReg(op_ammin_wu, rk, rj, rd).encode());
   1178 }
   1179 
   1180 BufferOffset AssemblerLOONG64::as_ammin_du(Register rd, Register rj,
   1181                                           Register rk) {
   1182  spew("ammin_du    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1183  return writeInst(InstReg(op_ammin_du, rk, rj, rd).encode());
   1184 }
   1185 
   1186 BufferOffset AssemblerLOONG64::as_amswap_db_w(Register rd, Register rj,
   1187                                              Register rk) {
   1188  spew("amswap_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1189  return writeInst(InstReg(op_amswap_db_w, rk, rj, rd).encode());
   1190 }
   1191 
   1192 BufferOffset AssemblerLOONG64::as_amswap_db_d(Register rd, Register rj,
   1193                                              Register rk) {
   1194  spew("amswap_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1195  return writeInst(InstReg(op_amswap_db_d, rk, rj, rd).encode());
   1196 }
   1197 
   1198 BufferOffset AssemblerLOONG64::as_amadd_db_w(Register rd, Register rj,
   1199                                             Register rk) {
   1200  spew("amadd_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1201  return writeInst(InstReg(op_amadd_db_w, rk, rj, rd).encode());
   1202 }
   1203 
   1204 BufferOffset AssemblerLOONG64::as_amadd_db_d(Register rd, Register rj,
   1205                                             Register rk) {
   1206  spew("amadd_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1207  return writeInst(InstReg(op_amadd_db_d, rk, rj, rd).encode());
   1208 }
   1209 
   1210 BufferOffset AssemblerLOONG64::as_amand_db_w(Register rd, Register rj,
   1211                                             Register rk) {
   1212  spew("amand_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1213  return writeInst(InstReg(op_amand_db_w, rk, rj, rd).encode());
   1214 }
   1215 
   1216 BufferOffset AssemblerLOONG64::as_amand_db_d(Register rd, Register rj,
   1217                                             Register rk) {
   1218  spew("amand_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1219  return writeInst(InstReg(op_amand_db_d, rk, rj, rd).encode());
   1220 }
   1221 
   1222 BufferOffset AssemblerLOONG64::as_amor_db_w(Register rd, Register rj,
   1223                                            Register rk) {
   1224  spew("amor_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1225  return writeInst(InstReg(op_amor_db_w, rk, rj, rd).encode());
   1226 }
   1227 
   1228 BufferOffset AssemblerLOONG64::as_amor_db_d(Register rd, Register rj,
   1229                                            Register rk) {
   1230  spew("amor_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1231  return writeInst(InstReg(op_amor_db_d, rk, rj, rd).encode());
   1232 }
   1233 
   1234 BufferOffset AssemblerLOONG64::as_amxor_db_w(Register rd, Register rj,
   1235                                             Register rk) {
   1236  spew("amxor_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1237  return writeInst(InstReg(op_amxor_db_w, rk, rj, rd).encode());
   1238 }
   1239 
   1240 BufferOffset AssemblerLOONG64::as_amxor_db_d(Register rd, Register rj,
   1241                                             Register rk) {
   1242  spew("amxor_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1243  return writeInst(InstReg(op_amxor_db_d, rk, rj, rd).encode());
   1244 }
   1245 
   1246 BufferOffset AssemblerLOONG64::as_ammax_db_w(Register rd, Register rj,
   1247                                             Register rk) {
   1248  spew("ammax_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1249  return writeInst(InstReg(op_ammax_db_w, rk, rj, rd).encode());
   1250 }
   1251 
   1252 BufferOffset AssemblerLOONG64::as_ammax_db_d(Register rd, Register rj,
   1253                                             Register rk) {
   1254  spew("ammax_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1255  return writeInst(InstReg(op_ammax_db_d, rk, rj, rd).encode());
   1256 }
   1257 
   1258 BufferOffset AssemblerLOONG64::as_ammin_db_w(Register rd, Register rj,
   1259                                             Register rk) {
   1260  spew("ammin_db_w    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1261  return writeInst(InstReg(op_ammin_db_w, rk, rj, rd).encode());
   1262 }
   1263 
   1264 BufferOffset AssemblerLOONG64::as_ammin_db_d(Register rd, Register rj,
   1265                                             Register rk) {
   1266  spew("ammin_db_d    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1267  return writeInst(InstReg(op_ammin_db_d, rk, rj, rd).encode());
   1268 }
   1269 
   1270 BufferOffset AssemblerLOONG64::as_ammax_db_wu(Register rd, Register rj,
   1271                                              Register rk) {
   1272  spew("ammax_db_wu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1273  return writeInst(InstReg(op_ammax_db_wu, rk, rj, rd).encode());
   1274 }
   1275 
   1276 BufferOffset AssemblerLOONG64::as_ammax_db_du(Register rd, Register rj,
   1277                                              Register rk) {
   1278  spew("ammax_db_du    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1279  return writeInst(InstReg(op_ammax_db_du, rk, rj, rd).encode());
   1280 }
   1281 
   1282 BufferOffset AssemblerLOONG64::as_ammin_db_wu(Register rd, Register rj,
   1283                                              Register rk) {
   1284  spew("ammin_db_wu    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1285  return writeInst(InstReg(op_ammin_db_wu, rk, rj, rd).encode());
   1286 }
   1287 
   1288 BufferOffset AssemblerLOONG64::as_ammin_db_du(Register rd, Register rj,
   1289                                              Register rk) {
   1290  spew("ammin_db_du    %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
   1291  return writeInst(InstReg(op_ammin_db_du, rk, rj, rd).encode());
   1292 }
   1293 
   1294 BufferOffset AssemblerLOONG64::as_ll_w(Register rd, Register rj, int32_t si14) {
   1295  spew("ll_w   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
   1296  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
   1297  return writeInst(InstImm(op_ll_w, si14 >> 2, rj, rd, 14).encode());
   1298 }
   1299 
   1300 BufferOffset AssemblerLOONG64::as_ll_d(Register rd, Register rj, int32_t si14) {
   1301  spew("ll_d   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
   1302  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
   1303  return writeInst(InstImm(op_ll_d, si14 >> 2, rj, rd, 14).encode());
   1304 }
   1305 
   1306 BufferOffset AssemblerLOONG64::as_sc_w(Register rd, Register rj, int32_t si14) {
   1307  spew("sc_w   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
   1308  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
   1309  return writeInst(InstImm(op_sc_w, si14 >> 2, rj, rd, 14).encode());
   1310 }
   1311 
   1312 BufferOffset AssemblerLOONG64::as_sc_d(Register rd, Register rj, int32_t si14) {
   1313  spew("sc_d   %3s,%3s,0x%x", rd.name(), rj.name(), si14);
   1314  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
   1315  return writeInst(InstImm(op_sc_d, si14 >> 2, rj, rd, 14).encode());
   1316 }
   1317 
   1318 // Barrier instructions
   1319 BufferOffset AssemblerLOONG64::as_dbar(int32_t hint) {
   1320  MOZ_ASSERT(is_uintN(hint, 15));
   1321  spew("dbar   0x%x", hint);
   1322  return writeInst(InstImm(op_dbar, hint).encode());
   1323 }
   1324 
   1325 BufferOffset AssemblerLOONG64::as_ibar(int32_t hint) {
   1326  MOZ_ASSERT(is_uintN(hint, 15));
   1327  spew("ibar   0x%x", hint);
   1328  return writeInst(InstImm(op_ibar, hint).encode());
   1329 }
   1330 
   1331 /* =============================================================== */
   1332 
   1333 // FP Arithmetic instructions
   1334 BufferOffset AssemblerLOONG64::as_fadd_s(FloatRegister fd, FloatRegister fj,
   1335                                         FloatRegister fk) {
   1336  spew("fadd_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1337  return writeInst(InstReg(op_fadd_s, fk, fj, fd).encode());
   1338 }
   1339 
   1340 BufferOffset AssemblerLOONG64::as_fadd_d(FloatRegister fd, FloatRegister fj,
   1341                                         FloatRegister fk) {
   1342  spew("fadd_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1343  return writeInst(InstReg(op_fadd_d, fk, fj, fd).encode());
   1344 }
   1345 
   1346 BufferOffset AssemblerLOONG64::as_fsub_s(FloatRegister fd, FloatRegister fj,
   1347                                         FloatRegister fk) {
   1348  spew("fsub_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1349  return writeInst(InstReg(op_fsub_s, fk, fj, fd).encode());
   1350 }
   1351 
   1352 BufferOffset AssemblerLOONG64::as_fsub_d(FloatRegister fd, FloatRegister fj,
   1353                                         FloatRegister fk) {
   1354  spew("fsub_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1355  return writeInst(InstReg(op_fsub_d, fk, fj, fd).encode());
   1356 }
   1357 
   1358 BufferOffset AssemblerLOONG64::as_fmul_s(FloatRegister fd, FloatRegister fj,
   1359                                         FloatRegister fk) {
   1360  spew("fmul_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1361  return writeInst(InstReg(op_fmul_s, fk, fj, fd).encode());
   1362 }
   1363 
   1364 BufferOffset AssemblerLOONG64::as_fmul_d(FloatRegister fd, FloatRegister fj,
   1365                                         FloatRegister fk) {
   1366  spew("fmul_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1367  return writeInst(InstReg(op_fmul_d, fk, fj, fd).encode());
   1368 }
   1369 
   1370 BufferOffset AssemblerLOONG64::as_fdiv_s(FloatRegister fd, FloatRegister fj,
   1371                                         FloatRegister fk) {
   1372  spew("fdiv_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1373  return writeInst(InstReg(op_fdiv_s, fk, fj, fd).encode());
   1374 }
   1375 
   1376 BufferOffset AssemblerLOONG64::as_fdiv_d(FloatRegister fd, FloatRegister fj,
   1377                                         FloatRegister fk) {
   1378  spew("fdiv_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1379  return writeInst(InstReg(op_fdiv_d, fk, fj, fd).encode());
   1380 }
   1381 
   1382 BufferOffset AssemblerLOONG64::as_fmadd_s(FloatRegister fd, FloatRegister fj,
   1383                                          FloatRegister fk, FloatRegister fa) {
   1384  spew("fmadd_s    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
   1385       fa.name());
   1386  return writeInst(InstReg(op_fmadd_s, fa, fk, fj, fd).encode());
   1387 }
   1388 
   1389 BufferOffset AssemblerLOONG64::as_fmadd_d(FloatRegister fd, FloatRegister fj,
   1390                                          FloatRegister fk, FloatRegister fa) {
   1391  spew("fmadd_d    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
   1392       fa.name());
   1393  return writeInst(InstReg(op_fmadd_d, fa, fk, fj, fd).encode());
   1394 }
   1395 
   1396 BufferOffset AssemblerLOONG64::as_fmsub_s(FloatRegister fd, FloatRegister fj,
   1397                                          FloatRegister fk, FloatRegister fa) {
   1398  spew("fmsub_s    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
   1399       fa.name());
   1400  return writeInst(InstReg(op_fmsub_s, fa, fk, fj, fd).encode());
   1401 }
   1402 
   1403 BufferOffset AssemblerLOONG64::as_fmsub_d(FloatRegister fd, FloatRegister fj,
   1404                                          FloatRegister fk, FloatRegister fa) {
   1405  spew("fmsub_d    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
   1406       fa.name());
   1407  return writeInst(InstReg(op_fmsub_d, fa, fk, fj, fd).encode());
   1408 }
   1409 
   1410 BufferOffset AssemblerLOONG64::as_fnmadd_s(FloatRegister fd, FloatRegister fj,
   1411                                           FloatRegister fk, FloatRegister fa) {
   1412  spew("fnmadd_s    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
   1413       fa.name());
   1414  return writeInst(InstReg(op_fnmadd_s, fa, fk, fj, fd).encode());
   1415 }
   1416 
   1417 BufferOffset AssemblerLOONG64::as_fnmadd_d(FloatRegister fd, FloatRegister fj,
   1418                                           FloatRegister fk, FloatRegister fa) {
   1419  spew("fnmadd_d    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
   1420       fa.name());
   1421  return writeInst(InstReg(op_fnmadd_d, fa, fk, fj, fd).encode());
   1422 }
   1423 
   1424 BufferOffset AssemblerLOONG64::as_fnmsub_s(FloatRegister fd, FloatRegister fj,
   1425                                           FloatRegister fk, FloatRegister fa) {
   1426  spew("fnmsub_s    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
   1427       fa.name());
   1428  return writeInst(InstReg(op_fnmsub_s, fa, fk, fj, fd).encode());
   1429 }
   1430 
   1431 BufferOffset AssemblerLOONG64::as_fnmsub_d(FloatRegister fd, FloatRegister fj,
   1432                                           FloatRegister fk, FloatRegister fa) {
   1433  spew("fnmsub_d    %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
   1434       fa.name());
   1435  return writeInst(InstReg(op_fnmsub_d, fa, fk, fj, fd).encode());
   1436 }
   1437 
   1438 BufferOffset AssemblerLOONG64::as_fmax_s(FloatRegister fd, FloatRegister fj,
   1439                                         FloatRegister fk) {
   1440  spew("fmax_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1441  return writeInst(InstReg(op_fmax_s, fk, fj, fd).encode());
   1442 }
   1443 
   1444 BufferOffset AssemblerLOONG64::as_fmax_d(FloatRegister fd, FloatRegister fj,
   1445                                         FloatRegister fk) {
   1446  spew("fmax_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1447  return writeInst(InstReg(op_fmax_d, fk, fj, fd).encode());
   1448 }
   1449 
   1450 BufferOffset AssemblerLOONG64::as_fmin_s(FloatRegister fd, FloatRegister fj,
   1451                                         FloatRegister fk) {
   1452  spew("fmin_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1453  return writeInst(InstReg(op_fmin_s, fk, fj, fd).encode());
   1454 }
   1455 
   1456 BufferOffset AssemblerLOONG64::as_fmin_d(FloatRegister fd, FloatRegister fj,
   1457                                         FloatRegister fk) {
   1458  spew("fmin_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1459  return writeInst(InstReg(op_fmin_d, fk, fj, fd).encode());
   1460 }
   1461 
   1462 BufferOffset AssemblerLOONG64::as_fmaxa_s(FloatRegister fd, FloatRegister fj,
   1463                                          FloatRegister fk) {
   1464  spew("fmaxa_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1465  return writeInst(InstReg(op_fmaxa_s, fk, fj, fd).encode());
   1466 }
   1467 
   1468 BufferOffset AssemblerLOONG64::as_fmaxa_d(FloatRegister fd, FloatRegister fj,
   1469                                          FloatRegister fk) {
   1470  spew("fmaxa_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1471  return writeInst(InstReg(op_fmaxa_d, fk, fj, fd).encode());
   1472 }
   1473 
   1474 BufferOffset AssemblerLOONG64::as_fmina_s(FloatRegister fd, FloatRegister fj,
   1475                                          FloatRegister fk) {
   1476  spew("fmina_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1477  return writeInst(InstReg(op_fmina_s, fk, fj, fd).encode());
   1478 }
   1479 
   1480 BufferOffset AssemblerLOONG64::as_fmina_d(FloatRegister fd, FloatRegister fj,
   1481                                          FloatRegister fk) {
   1482  spew("fmina_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1483  return writeInst(InstReg(op_fmina_d, fk, fj, fd).encode());
   1484 }
   1485 
   1486 BufferOffset AssemblerLOONG64::as_fabs_s(FloatRegister fd, FloatRegister fj) {
   1487  spew("fabs_s    %3s,%3s", fd.name(), fj.name());
   1488  return writeInst(InstReg(op_fabs_s, fj, fd).encode());
   1489 }
   1490 
   1491 BufferOffset AssemblerLOONG64::as_fabs_d(FloatRegister fd, FloatRegister fj) {
   1492  spew("fabs_d    %3s,%3s", fd.name(), fj.name());
   1493  return writeInst(InstReg(op_fabs_d, fj, fd).encode());
   1494 }
   1495 
   1496 BufferOffset AssemblerLOONG64::as_fneg_s(FloatRegister fd, FloatRegister fj) {
   1497  spew("fneg_s    %3s,%3s", fd.name(), fj.name());
   1498  return writeInst(InstReg(op_fneg_s, fj, fd).encode());
   1499 }
   1500 
   1501 BufferOffset AssemblerLOONG64::as_fneg_d(FloatRegister fd, FloatRegister fj) {
   1502  spew("fneg_d    %3s,%3s", fd.name(), fj.name());
   1503  return writeInst(InstReg(op_fneg_d, fj, fd).encode());
   1504 }
   1505 
   1506 BufferOffset AssemblerLOONG64::as_fsqrt_s(FloatRegister fd, FloatRegister fj) {
   1507  spew("fsqrt_s    %3s,%3s", fd.name(), fj.name());
   1508  return writeInst(InstReg(op_fsqrt_s, fj, fd).encode());
   1509 }
   1510 
   1511 BufferOffset AssemblerLOONG64::as_fsqrt_d(FloatRegister fd, FloatRegister fj) {
   1512  spew("fsqrt_d    %3s,%3s", fd.name(), fj.name());
   1513  return writeInst(InstReg(op_fsqrt_d, fj, fd).encode());
   1514 }
   1515 
   1516 BufferOffset AssemblerLOONG64::as_fcopysign_s(FloatRegister fd,
   1517                                              FloatRegister fj,
   1518                                              FloatRegister fk) {
   1519  spew("fcopysign_s    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1520  return writeInst(InstReg(op_fcopysign_s, fk, fj, fd).encode());
   1521 }
   1522 
   1523 BufferOffset AssemblerLOONG64::as_fcopysign_d(FloatRegister fd,
   1524                                              FloatRegister fj,
   1525                                              FloatRegister fk) {
   1526  spew("fcopysign_d    %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
   1527  return writeInst(InstReg(op_fcopysign_d, fk, fj, fd).encode());
   1528 }
   1529 
   1530 // FP compare instructions
   1531 // fcmp.cond.s and fcmp.cond.d instructions
   1532 BufferOffset AssemblerLOONG64::as_fcmp_cor(FloatFormat fmt, FloatRegister fj,
   1533                                           FloatRegister fk,
   1534                                           FPConditionBit cd) {
   1535  if (fmt == DoubleFloat) {
   1536    spew("fcmp_cor_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1537    return writeInst(InstReg(op_fcmp_cond_d, COR, fk, fj, cd).encode());
   1538  } else {
   1539    spew("fcmp_cor_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1540    return writeInst(InstReg(op_fcmp_cond_s, COR, fk, fj, cd).encode());
   1541  }
   1542 }
   1543 
   1544 BufferOffset AssemblerLOONG64::as_fcmp_ceq(FloatFormat fmt, FloatRegister fj,
   1545                                           FloatRegister fk,
   1546                                           FPConditionBit cd) {
   1547  if (fmt == DoubleFloat) {
   1548    spew("fcmp_ceq_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1549    return writeInst(InstReg(op_fcmp_cond_d, CEQ, fk, fj, cd).encode());
   1550  } else {
   1551    spew("fcmp_ceq_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1552    return writeInst(InstReg(op_fcmp_cond_s, CEQ, fk, fj, cd).encode());
   1553  }
   1554 }
   1555 
   1556 BufferOffset AssemblerLOONG64::as_fcmp_cne(FloatFormat fmt, FloatRegister fj,
   1557                                           FloatRegister fk,
   1558                                           FPConditionBit cd) {
   1559  if (fmt == DoubleFloat) {
   1560    spew("fcmp_cne_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1561    return writeInst(InstReg(op_fcmp_cond_d, CNE, fk, fj, cd).encode());
   1562  } else {
   1563    spew("fcmp_cne_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1564    return writeInst(InstReg(op_fcmp_cond_s, CNE, fk, fj, cd).encode());
   1565  }
   1566 }
   1567 
   1568 BufferOffset AssemblerLOONG64::as_fcmp_cle(FloatFormat fmt, FloatRegister fj,
   1569                                           FloatRegister fk,
   1570                                           FPConditionBit cd) {
   1571  if (fmt == DoubleFloat) {
   1572    spew("fcmp_cle_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1573    return writeInst(InstReg(op_fcmp_cond_d, CLE, fk, fj, cd).encode());
   1574  } else {
   1575    spew("fcmp_cle_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1576    return writeInst(InstReg(op_fcmp_cond_s, CLE, fk, fj, cd).encode());
   1577  }
   1578 }
   1579 
   1580 BufferOffset AssemblerLOONG64::as_fcmp_clt(FloatFormat fmt, FloatRegister fj,
   1581                                           FloatRegister fk,
   1582                                           FPConditionBit cd) {
   1583  if (fmt == DoubleFloat) {
   1584    spew("fcmp_clt_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1585    return writeInst(InstReg(op_fcmp_cond_d, CLT, fk, fj, cd).encode());
   1586  } else {
   1587    spew("fcmp_clt_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1588    return writeInst(InstReg(op_fcmp_cond_s, CLT, fk, fj, cd).encode());
   1589  }
   1590 }
   1591 
   1592 BufferOffset AssemblerLOONG64::as_fcmp_cun(FloatFormat fmt, FloatRegister fj,
   1593                                           FloatRegister fk,
   1594                                           FPConditionBit cd) {
   1595  if (fmt == DoubleFloat) {
   1596    spew("fcmp_cun_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1597    return writeInst(InstReg(op_fcmp_cond_d, CUN, fk, fj, cd).encode());
   1598  } else {
   1599    spew("fcmp_cun_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1600    return writeInst(InstReg(op_fcmp_cond_s, CUN, fk, fj, cd).encode());
   1601  }
   1602 }
   1603 
   1604 BufferOffset AssemblerLOONG64::as_fcmp_cueq(FloatFormat fmt, FloatRegister fj,
   1605                                            FloatRegister fk,
   1606                                            FPConditionBit cd) {
   1607  if (fmt == DoubleFloat) {
   1608    spew("fcmp_cueq_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1609    return writeInst(InstReg(op_fcmp_cond_d, CUEQ, fk, fj, cd).encode());
   1610  } else {
   1611    spew("fcmp_cueq_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1612    return writeInst(InstReg(op_fcmp_cond_s, CUEQ, fk, fj, cd).encode());
   1613  }
   1614 }
   1615 
   1616 BufferOffset AssemblerLOONG64::as_fcmp_cune(FloatFormat fmt, FloatRegister fj,
   1617                                            FloatRegister fk,
   1618                                            FPConditionBit cd) {
   1619  if (fmt == DoubleFloat) {
   1620    spew("fcmp_cune_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1621    return writeInst(InstReg(op_fcmp_cond_d, CUNE, fk, fj, cd).encode());
   1622  } else {
   1623    spew("fcmp_cune_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1624    return writeInst(InstReg(op_fcmp_cond_s, CUNE, fk, fj, cd).encode());
   1625  }
   1626 }
   1627 
   1628 BufferOffset AssemblerLOONG64::as_fcmp_cule(FloatFormat fmt, FloatRegister fj,
   1629                                            FloatRegister fk,
   1630                                            FPConditionBit cd) {
   1631  if (fmt == DoubleFloat) {
   1632    spew("fcmp_cule_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1633    return writeInst(InstReg(op_fcmp_cond_d, CULE, fk, fj, cd).encode());
   1634  } else {
   1635    spew("fcmp_cule_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1636    return writeInst(InstReg(op_fcmp_cond_s, CULE, fk, fj, cd).encode());
   1637  }
   1638 }
   1639 
   1640 BufferOffset AssemblerLOONG64::as_fcmp_cult(FloatFormat fmt, FloatRegister fj,
   1641                                            FloatRegister fk,
   1642                                            FPConditionBit cd) {
   1643  if (fmt == DoubleFloat) {
   1644    spew("fcmp_cult_d    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1645    return writeInst(InstReg(op_fcmp_cond_d, CULT, fk, fj, cd).encode());
   1646  } else {
   1647    spew("fcmp_cult_s    FCC%d,%3s,%3s", cd, fj.name(), fk.name());
   1648    return writeInst(InstReg(op_fcmp_cond_s, CULT, fk, fj, cd).encode());
   1649  }
   1650 }
   1651 
   1652 // FP conversion instructions
   1653 BufferOffset AssemblerLOONG64::as_fcvt_s_d(FloatRegister fd, FloatRegister fj) {
   1654  spew("fcvt_s_d    %3s,%3s", fd.name(), fj.name());
   1655  return writeInst(InstReg(op_fcvt_s_d, fj, fd).encode());
   1656 }
   1657 
   1658 BufferOffset AssemblerLOONG64::as_fcvt_d_s(FloatRegister fd, FloatRegister fj) {
   1659  spew("fcvt_d_s    %3s,%3s", fd.name(), fj.name());
   1660  return writeInst(InstReg(op_fcvt_d_s, fj, fd).encode());
   1661 }
   1662 
   1663 BufferOffset AssemblerLOONG64::as_ffint_s_w(FloatRegister fd,
   1664                                            FloatRegister fj) {
   1665  spew("ffint_s_w    %3s,%3s", fd.name(), fj.name());
   1666  return writeInst(InstReg(op_ffint_s_w, fj, fd).encode());
   1667 }
   1668 
   1669 BufferOffset AssemblerLOONG64::as_ffint_s_l(FloatRegister fd,
   1670                                            FloatRegister fj) {
   1671  spew("ffint_s_l    %3s,%3s", fd.name(), fj.name());
   1672  return writeInst(InstReg(op_ffint_s_l, fj, fd).encode());
   1673 }
   1674 
   1675 BufferOffset AssemblerLOONG64::as_ffint_d_w(FloatRegister fd,
   1676                                            FloatRegister fj) {
   1677  spew("ffint_d_w    %3s,%3s", fd.name(), fj.name());
   1678  return writeInst(InstReg(op_ffint_d_w, fj, fd).encode());
   1679 }
   1680 
   1681 BufferOffset AssemblerLOONG64::as_ffint_d_l(FloatRegister fd,
   1682                                            FloatRegister fj) {
   1683  spew("ffint_d_l    %3s,%3s", fd.name(), fj.name());
   1684  return writeInst(InstReg(op_ffint_d_l, fj, fd).encode());
   1685 }
   1686 
   1687 BufferOffset AssemblerLOONG64::as_ftint_w_s(FloatRegister fd,
   1688                                            FloatRegister fj) {
   1689  spew("ftint_w_s    %3s,%3s", fd.name(), fj.name());
   1690  return writeInst(InstReg(op_ftint_w_s, fj, fd).encode());
   1691 }
   1692 
   1693 BufferOffset AssemblerLOONG64::as_ftint_w_d(FloatRegister fd,
   1694                                            FloatRegister fj) {
   1695  spew("ftint_w_d    %3s,%3s", fd.name(), fj.name());
   1696  return writeInst(InstReg(op_ftint_w_d, fj, fd).encode());
   1697 }
   1698 
   1699 BufferOffset AssemblerLOONG64::as_ftint_l_s(FloatRegister fd,
   1700                                            FloatRegister fj) {
   1701  spew("ftint_l_s    %3s,%3s", fd.name(), fj.name());
   1702  return writeInst(InstReg(op_ftint_l_s, fj, fd).encode());
   1703 }
   1704 
   1705 BufferOffset AssemblerLOONG64::as_ftint_l_d(FloatRegister fd,
   1706                                            FloatRegister fj) {
   1707  spew("ftint_l_d    %3s,%3s", fd.name(), fj.name());
   1708  return writeInst(InstReg(op_ftint_l_d, fj, fd).encode());
   1709 }
   1710 
   1711 BufferOffset AssemblerLOONG64::as_ftintrm_w_s(FloatRegister fd,
   1712                                              FloatRegister fj) {
   1713  spew("ftintrm_w_s    %3s,%3s", fd.name(), fj.name());
   1714  return writeInst(InstReg(op_ftintrm_w_s, fj, fd).encode());
   1715 }
   1716 
   1717 BufferOffset AssemblerLOONG64::as_ftintrm_w_d(FloatRegister fd,
   1718                                              FloatRegister fj) {
   1719  spew("ftintrm_w_d    %3s,%3s", fd.name(), fj.name());
   1720  return writeInst(InstReg(op_ftintrm_w_d, fj, fd).encode());
   1721 }
   1722 
   1723 BufferOffset AssemblerLOONG64::as_ftintrm_l_s(FloatRegister fd,
   1724                                              FloatRegister fj) {
   1725  spew("ftintrm_l_s    %3s,%3s", fd.name(), fj.name());
   1726  return writeInst(InstReg(op_ftintrm_l_s, fj, fd).encode());
   1727 }
   1728 
   1729 BufferOffset AssemblerLOONG64::as_ftintrm_l_d(FloatRegister fd,
   1730                                              FloatRegister fj) {
   1731  spew("ftintrm_l_d    %3s,%3s", fd.name(), fj.name());
   1732  return writeInst(InstReg(op_ftintrm_l_d, fj, fd).encode());
   1733 }
   1734 
   1735 BufferOffset AssemblerLOONG64::as_ftintrp_w_s(FloatRegister fd,
   1736                                              FloatRegister fj) {
   1737  spew("ftintrp_w_s    %3s,%3s", fd.name(), fj.name());
   1738  return writeInst(InstReg(op_ftintrp_w_s, fj, fd).encode());
   1739 }
   1740 
   1741 BufferOffset AssemblerLOONG64::as_ftintrp_w_d(FloatRegister fd,
   1742                                              FloatRegister fj) {
   1743  spew("ftintrp_w_d    %3s,%3s", fd.name(), fj.name());
   1744  return writeInst(InstReg(op_ftintrp_w_d, fj, fd).encode());
   1745 }
   1746 
   1747 BufferOffset AssemblerLOONG64::as_ftintrp_l_s(FloatRegister fd,
   1748                                              FloatRegister fj) {
   1749  spew("ftintrp_l_s    %3s,%3s", fd.name(), fj.name());
   1750  return writeInst(InstReg(op_ftintrp_l_s, fj, fd).encode());
   1751 }
   1752 
   1753 BufferOffset AssemblerLOONG64::as_ftintrp_l_d(FloatRegister fd,
   1754                                              FloatRegister fj) {
   1755  spew("ftintrp_l_d    %3s,%3s", fd.name(), fj.name());
   1756  return writeInst(InstReg(op_ftintrp_l_d, fj, fd).encode());
   1757 }
   1758 
   1759 BufferOffset AssemblerLOONG64::as_ftintrz_w_s(FloatRegister fd,
   1760                                              FloatRegister fj) {
   1761  spew("ftintrz_w_s    %3s,%3s", fd.name(), fj.name());
   1762  return writeInst(InstReg(op_ftintrz_w_s, fj, fd).encode());
   1763 }
   1764 
   1765 BufferOffset AssemblerLOONG64::as_ftintrz_w_d(FloatRegister fd,
   1766                                              FloatRegister fj) {
   1767  spew("ftintrz_w_d    %3s,%3s", fd.name(), fj.name());
   1768  return writeInst(InstReg(op_ftintrz_w_d, fj, fd).encode());
   1769 }
   1770 
   1771 BufferOffset AssemblerLOONG64::as_ftintrz_l_s(FloatRegister fd,
   1772                                              FloatRegister fj) {
   1773  spew("ftintrz_l_s    %3s,%3s", fd.name(), fj.name());
   1774  return writeInst(InstReg(op_ftintrz_l_s, fj, fd).encode());
   1775 }
   1776 
   1777 BufferOffset AssemblerLOONG64::as_ftintrz_l_d(FloatRegister fd,
   1778                                              FloatRegister fj) {
   1779  spew("ftintrz_l_d    %3s,%3s", fd.name(), fj.name());
   1780  return writeInst(InstReg(op_ftintrz_l_d, fj, fd).encode());
   1781 }
   1782 BufferOffset AssemblerLOONG64::as_ftintrne_w_s(FloatRegister fd,
   1783                                               FloatRegister fj) {
   1784  spew("ftintrne_w_s    %3s,%3s", fd.name(), fj.name());
   1785  return writeInst(InstReg(op_ftintrne_w_s, fj, fd).encode());
   1786 }
   1787 
   1788 BufferOffset AssemblerLOONG64::as_ftintrne_w_d(FloatRegister fd,
   1789                                               FloatRegister fj) {
   1790  spew("ftintrne_w_d    %3s,%3s", fd.name(), fj.name());
   1791  return writeInst(InstReg(op_ftintrne_w_d, fj, fd).encode());
   1792 }
   1793 
   1794 BufferOffset AssemblerLOONG64::as_ftintrne_l_s(FloatRegister fd,
   1795                                               FloatRegister fj) {
   1796  spew("ftintrne_l_s    %3s,%3s", fd.name(), fj.name());
   1797  return writeInst(InstReg(op_ftintrne_l_s, fj, fd).encode());
   1798 }
   1799 
   1800 BufferOffset AssemblerLOONG64::as_ftintrne_l_d(FloatRegister fd,
   1801                                               FloatRegister fj) {
   1802  spew("ftintrne_l_d    %3s,%3s", fd.name(), fj.name());
   1803  return writeInst(InstReg(op_ftintrne_l_d, fj, fd).encode());
   1804 }
   1805 
   1806 BufferOffset AssemblerLOONG64::as_frint_s(FloatRegister fd, FloatRegister fj) {
   1807  spew("frint_s    %3s,%3s", fd.name(), fj.name());
   1808  return writeInst(InstReg(op_frint_s, fj, fd).encode());
   1809 }
   1810 
   1811 BufferOffset AssemblerLOONG64::as_frint_d(FloatRegister fd, FloatRegister fj) {
   1812  spew("frint_d    %3s,%3s", fd.name(), fj.name());
   1813  return writeInst(InstReg(op_frint_d, fj, fd).encode());
   1814 }
   1815 
   1816 // FP mov instructions
   1817 BufferOffset AssemblerLOONG64::as_fmov_s(FloatRegister fd, FloatRegister fj) {
   1818  spew("fmov_s    %3s,%3s", fd.name(), fj.name());
   1819  return writeInst(InstReg(op_fmov_s, fj, fd).encode());
   1820 }
   1821 
   1822 BufferOffset AssemblerLOONG64::as_fmov_d(FloatRegister fd, FloatRegister fj) {
   1823  spew("fmov_d    %3s,%3s", fd.name(), fj.name());
   1824  return writeInst(InstReg(op_fmov_d, fj, fd).encode());
   1825 }
   1826 
   1827 BufferOffset AssemblerLOONG64::as_fsel(FloatRegister fd, FloatRegister fj,
   1828                                       FloatRegister fk, FPConditionBit ca) {
   1829  spew("fsel      %3s,%3s,%3s,%d", fd.name(), fj.name(), fk.name(), ca);
   1830  return writeInst(InstReg(op_fsel, ca, fk, fj, fd).encode());
   1831 }
   1832 
   1833 BufferOffset AssemblerLOONG64::as_movgr2fr_w(FloatRegister fd, Register rj) {
   1834  spew("movgr2fr_w    %3s,%3s", fd.name(), rj.name());
   1835  return writeInst(InstReg(op_movgr2fr_w, rj, fd).encode());
   1836 }
   1837 
   1838 BufferOffset AssemblerLOONG64::as_movgr2fr_d(FloatRegister fd, Register rj) {
   1839  spew("movgr2fr_d    %3s,%3s", fd.name(), rj.name());
   1840  return writeInst(InstReg(op_movgr2fr_d, rj, fd).encode());
   1841 }
   1842 
   1843 BufferOffset AssemblerLOONG64::as_movgr2frh_w(FloatRegister fd, Register rj) {
   1844  spew("movgr2frh_w    %3s,%3s", fd.name(), rj.name());
   1845  return writeInst(InstReg(op_movgr2frh_w, rj, fd).encode());
   1846 }
   1847 
   1848 BufferOffset AssemblerLOONG64::as_movfr2gr_s(Register rd, FloatRegister fj) {
   1849  spew("movfr2gr_s    %3s,%3s", rd.name(), fj.name());
   1850  return writeInst(InstReg(op_movfr2gr_s, fj, rd).encode());
   1851 }
   1852 
   1853 BufferOffset AssemblerLOONG64::as_movfr2gr_d(Register rd, FloatRegister fj) {
   1854  spew("movfr2gr_d    %3s,%3s", rd.name(), fj.name());
   1855  return writeInst(InstReg(op_movfr2gr_d, fj, rd).encode());
   1856 }
   1857 
   1858 BufferOffset AssemblerLOONG64::as_movfrh2gr_s(Register rd, FloatRegister fj) {
   1859  spew("movfrh2gr_s    %3s,%3s", rd.name(), fj.name());
   1860  return writeInst(InstReg(op_movfrh2gr_s, fj, rd).encode());
   1861 }
   1862 
   1863 BufferOffset AssemblerLOONG64::as_movgr2fcsr(Register rj) {
   1864  spew("movgr2fcsr    %3s", rj.name());
   1865  return writeInst(InstReg(op_movgr2fcsr, rj, FCSR).encode());
   1866 }
   1867 
   1868 BufferOffset AssemblerLOONG64::as_movfcsr2gr(Register rd) {
   1869  spew("movfcsr2gr    %3s", rd.name());
   1870  return writeInst(InstReg(op_movfcsr2gr, FCSR, rd).encode());
   1871 }
   1872 
   1873 BufferOffset AssemblerLOONG64::as_movfr2cf(FPConditionBit cd,
   1874                                           FloatRegister fj) {
   1875  spew("movfr2cf    %d,%3s", cd, fj.name());
   1876  return writeInst(InstReg(op_movfr2cf, fj, cd).encode());
   1877 }
   1878 
   1879 BufferOffset AssemblerLOONG64::as_movcf2fr(FloatRegister fd,
   1880                                           FPConditionBit cj) {
   1881  spew("movcf2fr    %3s,%d", fd.name(), cj);
   1882  return writeInst(InstReg(op_movcf2fr, cj, fd).encode());
   1883 }
   1884 
   1885 BufferOffset AssemblerLOONG64::as_movgr2cf(FPConditionBit cd, Register rj) {
   1886  spew("movgr2cf    %d,%3s", cd, rj.name());
   1887  return writeInst(InstReg(op_movgr2cf, rj, cd).encode());
   1888 }
   1889 
   1890 BufferOffset AssemblerLOONG64::as_movcf2gr(Register rd, FPConditionBit cj) {
   1891  spew("movcf2gr    %3s,%d", rd.name(), cj);
   1892  return writeInst(InstReg(op_movcf2gr, cj, rd).encode());
   1893 }
   1894 
   1895 // FP load/store instructions
   1896 BufferOffset AssemblerLOONG64::as_fld_s(FloatRegister fd, Register rj,
   1897                                        int32_t si12) {
   1898  MOZ_ASSERT(is_intN(si12, 12));
   1899  spew("fld_s   %3s,%3s,0x%x", fd.name(), rj.name(), si12);
   1900  return writeInst(InstImm(op_fld_s, si12, rj, fd).encode());
   1901 }
   1902 
   1903 BufferOffset AssemblerLOONG64::as_fld_d(FloatRegister fd, Register rj,
   1904                                        int32_t si12) {
   1905  MOZ_ASSERT(is_intN(si12, 12));
   1906  spew("fld_d   %3s,%3s,0x%x", fd.name(), rj.name(), si12);
   1907  return writeInst(InstImm(op_fld_d, si12, rj, fd).encode());
   1908 }
   1909 
   1910 BufferOffset AssemblerLOONG64::as_fst_s(FloatRegister fd, Register rj,
   1911                                        int32_t si12) {
   1912  MOZ_ASSERT(is_intN(si12, 12));
   1913  spew("fst_s   %3s,%3s,0x%x", fd.name(), rj.name(), si12);
   1914  return writeInst(InstImm(op_fst_s, si12, rj, fd).encode());
   1915 }
   1916 
   1917 BufferOffset AssemblerLOONG64::as_fst_d(FloatRegister fd, Register rj,
   1918                                        int32_t si12) {
   1919  MOZ_ASSERT(is_intN(si12, 12));
   1920  spew("fst_d   %3s,%3s,0x%x", fd.name(), rj.name(), si12);
   1921  return writeInst(InstImm(op_fst_d, si12, rj, fd).encode());
   1922 }
   1923 
   1924 BufferOffset AssemblerLOONG64::as_fldx_s(FloatRegister fd, Register rj,
   1925                                         Register rk) {
   1926  spew("fldx_s    %3s,%3s,%3s", fd.name(), rj.name(), rk.name());
   1927  return writeInst(InstReg(op_fldx_s, rk, rj, fd).encode());
   1928 }
   1929 
   1930 BufferOffset AssemblerLOONG64::as_fldx_d(FloatRegister fd, Register rj,
   1931                                         Register rk) {
   1932  spew("fldx_d    %3s,%3s,%3s", fd.name(), rj.name(), rk.name());
   1933  return writeInst(InstReg(op_fldx_d, rk, rj, fd).encode());
   1934 }
   1935 
   1936 BufferOffset AssemblerLOONG64::as_fstx_s(FloatRegister fd, Register rj,
   1937                                         Register rk) {
   1938  spew("fstx_s    %3s,%3s,%3s", fd.name(), rj.name(), rk.name());
   1939  return writeInst(InstReg(op_fstx_s, rk, rj, fd).encode());
   1940 }
   1941 
   1942 BufferOffset AssemblerLOONG64::as_fstx_d(FloatRegister fd, Register rj,
   1943                                         Register rk) {
   1944  spew("fstx_d    %3s,%3s,%3s", fd.name(), rj.name(), rk.name());
   1945  return writeInst(InstReg(op_fstx_d, rk, rj, fd).encode());
   1946 }
   1947 
   1948 /* ========================================================================= */
   1949 
   1950 void AssemblerLOONG64::bind(Label* label, BufferOffset boff) {
   1951  spew(".set Llabel %p", label);
   1952  // If our caller didn't give us an explicit target to bind to
   1953  // then we want to bind to the location of the next instruction
   1954  BufferOffset dest = boff.assigned() ? boff : nextOffset();
   1955  if (label->used()) {
   1956    int32_t next;
   1957 
   1958    // A used label holds a link to branch that uses it.
   1959    BufferOffset b(label);
   1960    do {
   1961      // Even a 0 offset may be invalid if we're out of memory.
   1962      if (oom()) {
   1963        return;
   1964      }
   1965 
   1966      Instruction* inst = editSrc(b);
   1967 
   1968      // Second word holds a pointer to the next branch in label's chain.
   1969      next = inst[1].encode();
   1970      bind(reinterpret_cast<InstImm*>(inst), b.getOffset(), dest.getOffset());
   1971 
   1972      b = BufferOffset(next);
   1973    } while (next != LabelBase::INVALID_OFFSET);
   1974  }
   1975  label->bind(dest.getOffset());
   1976 }
   1977 
   1978 void AssemblerLOONG64::retarget(Label* label, Label* target) {
   1979  spew("retarget %p -> %p", label, target);
   1980  if (label->used() && !oom()) {
   1981    if (target->bound()) {
   1982      bind(label, BufferOffset(target));
   1983    } else if (target->used()) {
   1984      // The target is not bound but used. Prepend label's branch list
   1985      // onto target's.
   1986      int32_t next;
   1987      BufferOffset labelBranchOffset(label);
   1988 
   1989      // Find the head of the use chain for label.
   1990      do {
   1991        Instruction* inst = editSrc(labelBranchOffset);
   1992 
   1993        // Second word holds a pointer to the next branch in chain.
   1994        next = inst[1].encode();
   1995        labelBranchOffset = BufferOffset(next);
   1996      } while (next != LabelBase::INVALID_OFFSET);
   1997 
   1998      // Then patch the head of label's use chain to the tail of
   1999      // target's use chain, prepending the entire use chain of target.
   2000      Instruction* inst = editSrc(labelBranchOffset);
   2001      int32_t prev = target->offset();
   2002      target->use(label->offset());
   2003      inst[1].setData(prev);
   2004    } else {
   2005      // The target is unbound and unused.  We can just take the head of
   2006      // the list hanging off of label, and dump that into target.
   2007      target->use(label->offset());
   2008    }
   2009  }
   2010  label->reset();
   2011 }
   2012 
   2013 void dbg_break() {}
   2014 
   2015 void AssemblerLOONG64::as_break(uint32_t code) {
   2016  MOZ_ASSERT(code <= MAX_BREAK_CODE);
   2017  spew("break %d", code);
   2018  writeInst(InstImm(op_break, code).encode());
   2019 }
   2020 
   2021 // This just stomps over memory with 32 bits of raw data. Its purpose is to
   2022 // overwrite the call of JITed code with 32 bits worth of an offset. This will
   2023 // is only meant to function on code that has been invalidated, so it should
   2024 // be totally safe. Since that instruction will never be executed again, a
   2025 // ICache flush should not be necessary
   2026 void AssemblerLOONG64::PatchWrite_Imm32(CodeLocationLabel label, Imm32 imm) {
   2027  // Raw is going to be the return address.
   2028  uint32_t* raw = (uint32_t*)label.raw();
   2029  // Overwrite the 4 bytes before the return address, which will
   2030  // end up being the call instruction.
   2031  *(raw - 1) = imm.value;
   2032 }
   2033 
   2034 uint8_t* AssemblerLOONG64::NextInstruction(uint8_t* inst_, uint32_t* count) {
   2035  Instruction* inst = reinterpret_cast<Instruction*>(inst_);
   2036  if (count != nullptr) {
   2037    *count += sizeof(Instruction);
   2038  }
   2039  return reinterpret_cast<uint8_t*>(inst->next());
   2040 }
   2041 
   2042 void AssemblerLOONG64::ToggleToJmp(CodeLocationLabel inst_) {
   2043  InstImm* inst = (InstImm*)inst_.raw();
   2044 
   2045  MOZ_ASSERT(inst->extractBitField(31, 26) == (uint32_t)op_addu16i_d >> 26);
   2046  // We converted beq to addu16i_d, so now we restore it.
   2047  inst->setOpcode(op_beq, 6);
   2048 }
   2049 
   2050 void AssemblerLOONG64::ToggleToCmp(CodeLocationLabel inst_) {
   2051  InstImm* inst = (InstImm*)inst_.raw();
   2052 
   2053  // toggledJump is allways used for short jumps.
   2054  MOZ_ASSERT(inst->extractBitField(31, 26) == (uint32_t)op_beq >> 26);
   2055  // Replace "beq $zero, $zero, offset" with "addu16i_d $zero, $zero, offset"
   2056  inst->setOpcode(op_addu16i_d, 6);
   2057 }
   2058 
   2059 // Since there are no pools in LoongArch64 implementation, this should be
   2060 // simple.
   2061 Instruction* Instruction::next() { return this + 1; }
   2062 
   2063 InstImm AssemblerLOONG64::invertBranch(InstImm branch, BOffImm16 skipOffset) {
   2064  uint32_t rj = 0;
   2065  OpcodeField opcode = (OpcodeField)((branch.extractBitField(31, 26)) << 26);
   2066  switch (opcode) {
   2067    case op_beq:
   2068      branch.setBOffImm16(skipOffset);
   2069      branch.setOpcode(op_bne, 6);
   2070      return branch;
   2071    case op_bne:
   2072      branch.setBOffImm16(skipOffset);
   2073      branch.setOpcode(op_beq, 6);
   2074      return branch;
   2075    case op_bge:
   2076      branch.setBOffImm16(skipOffset);
   2077      branch.setOpcode(op_blt, 6);
   2078      return branch;
   2079    case op_bgeu:
   2080      branch.setBOffImm16(skipOffset);
   2081      branch.setOpcode(op_bltu, 6);
   2082      return branch;
   2083    case op_blt:
   2084      branch.setBOffImm16(skipOffset);
   2085      branch.setOpcode(op_bge, 6);
   2086      return branch;
   2087    case op_bltu:
   2088      branch.setBOffImm16(skipOffset);
   2089      branch.setOpcode(op_bgeu, 6);
   2090      return branch;
   2091    case op_beqz:
   2092      branch.setBOffImm16(skipOffset);
   2093      branch.setOpcode(op_bnez, 6);
   2094      return branch;
   2095    case op_bnez:
   2096      branch.setBOffImm16(skipOffset);
   2097      branch.setOpcode(op_beqz, 6);
   2098      return branch;
   2099    case op_bcz:
   2100      branch.setBOffImm16(skipOffset);
   2101      rj = branch.extractRJ();
   2102      if (rj & 0x8) {
   2103        branch.setRJ(rj & 0x17);
   2104      } else {
   2105        branch.setRJ(rj | 0x8);
   2106      }
   2107      return branch;
   2108    default:
   2109      MOZ_CRASH("Error creating long branch.");
   2110  }
   2111 }
   2112 
   2113 #ifdef JS_JITSPEW
   2114 void AssemblerLOONG64::decodeBranchInstAndSpew(InstImm branch) {
   2115  OpcodeField opcode = (OpcodeField)((branch.extractBitField(31, 26)) << 26);
   2116  uint32_t rd_id;
   2117  uint32_t rj_id;
   2118  uint32_t cj_id;
   2119  uint32_t immi = branch.extractImm16Value();
   2120  switch (opcode) {
   2121    case op_beq:
   2122      rd_id = branch.extractRD();
   2123      rj_id = branch.extractRJ();
   2124      spew("beq    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
   2125           Registers::GetName(rj_id), Registers::GetName(rd_id));
   2126      break;
   2127    case op_bne:
   2128      rd_id = branch.extractRD();
   2129      rj_id = branch.extractRJ();
   2130      spew("bne    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
   2131           Registers::GetName(rj_id), Registers::GetName(rd_id));
   2132      break;
   2133    case op_bge:
   2134      rd_id = branch.extractRD();
   2135      rj_id = branch.extractRJ();
   2136      spew("bge    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
   2137           Registers::GetName(rj_id), Registers::GetName(rd_id));
   2138      break;
   2139    case op_bgeu:
   2140      rd_id = branch.extractRD();
   2141      rj_id = branch.extractRJ();
   2142      spew("bgeu    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
   2143           Registers::GetName(rj_id), Registers::GetName(rd_id));
   2144      break;
   2145    case op_blt:
   2146      rd_id = branch.extractRD();
   2147      rj_id = branch.extractRJ();
   2148      spew("blt    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
   2149           Registers::GetName(rj_id), Registers::GetName(rd_id));
   2150      break;
   2151    case op_bltu:
   2152      rd_id = branch.extractRD();
   2153      rj_id = branch.extractRJ();
   2154      spew("bltu    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
   2155           Registers::GetName(rj_id), Registers::GetName(rd_id));
   2156      break;
   2157    case op_beqz:
   2158      rd_id = branch.extractRD();
   2159      rj_id = branch.extractRJ();
   2160      spew("beqz    0x%x,%3s,0x%x", (int32_t(immi << 18) >> 16) + 4,
   2161           Registers::GetName(rj_id), rd_id);
   2162      break;
   2163    case op_bnez:
   2164      rd_id = branch.extractRD();
   2165      rj_id = branch.extractRJ();
   2166      spew("bnez    0x%x,%3s,0x%x", (int32_t(immi << 18) >> 16) + 4,
   2167           Registers::GetName(rj_id), rd_id);
   2168      break;
   2169    case op_bcz:
   2170      rd_id = branch.extractRD();
   2171      rj_id = branch.extractRJ();
   2172      cj_id = branch.extractBitField(CJShift + CJBits - 1, CJShift);
   2173      if (rj_id & 0x8) {
   2174        spew("bcnez    0x%x,FCC%d,0x%x", (int32_t(immi << 18) >> 16) + 4, cj_id,
   2175             rd_id);
   2176      } else {
   2177        spew("bceqz    0x%x,FCC%d,0x%x", (int32_t(immi << 18) >> 16) + 4, cj_id,
   2178             rd_id);
   2179      }
   2180      break;
   2181    case op_jirl:
   2182      rd_id = branch.extractRD();
   2183      rj_id = branch.extractRJ();
   2184      spew("beqz    0x%x,%3s,%3s", (int32_t(immi << 18) >> 16) + 4,
   2185           Registers::GetName(rj_id), Registers::GetName(rd_id));
   2186      break;
   2187    default:
   2188      MOZ_CRASH("Error disassemble branch.");
   2189  }
   2190 }
   2191 #endif
   2192 
   2193 void Assembler::executableCopy(uint8_t* buffer) {
   2194  MOZ_ASSERT(isFinished);
   2195  m_buffer.executableCopy(buffer);
   2196 }
   2197 
   2198 uintptr_t Assembler::GetPointer(uint8_t* instPtr) {
   2199  Instruction* inst = (Instruction*)instPtr;
   2200  return Assembler::ExtractLoad64Value(inst);
   2201 }
   2202 
   2203 static JitCode* CodeFromJump(Instruction* jump) {
   2204  uint8_t* target = (uint8_t*)Assembler::ExtractLoad64Value(jump);
   2205  return JitCode::FromExecutable(target);
   2206 }
   2207 
   2208 void Assembler::TraceJumpRelocations(JSTracer* trc, JitCode* code,
   2209                                     CompactBufferReader& reader) {
   2210  while (reader.more()) {
   2211    JitCode* child =
   2212        CodeFromJump((Instruction*)(code->raw() + reader.readUnsigned()));
   2213    TraceManuallyBarrieredEdge(trc, &child, "rel32");
   2214  }
   2215 }
   2216 
   2217 static void TraceOneDataRelocation(JSTracer* trc,
   2218                                   mozilla::Maybe<AutoWritableJitCode>& awjc,
   2219                                   JitCode* code, Instruction* inst) {
   2220  void* ptr = (void*)Assembler::ExtractLoad64Value(inst);
   2221  void* prior = ptr;
   2222 
   2223  // Data relocations can be for Values or for raw pointers. If a Value is
   2224  // zero-tagged, we can trace it as if it were a raw pointer. If a Value
   2225  // is not zero-tagged, we have to interpret it as a Value to ensure that the
   2226  // tag bits are masked off to recover the actual pointer.
   2227  uintptr_t word = reinterpret_cast<uintptr_t>(ptr);
   2228  if (word >> JSVAL_TAG_SHIFT) {
   2229    // This relocation is a Value with a non-zero tag.
   2230    Value v = Value::fromRawBits(word);
   2231    TraceManuallyBarrieredEdge(trc, &v, "jit-masm-value");
   2232    ptr = (void*)v.bitsAsPunboxPointer();
   2233  } else {
   2234    // This relocation is a raw pointer or a Value with a zero tag.
   2235    // No barrier needed since these are constants.
   2236    TraceManuallyBarrieredGenericPointerEdge(
   2237        trc, reinterpret_cast<gc::Cell**>(&ptr), "jit-masm-ptr");
   2238  }
   2239 
   2240  if (ptr != prior) {
   2241    if (awjc.isNothing()) {
   2242      awjc.emplace(code);
   2243    }
   2244    Assembler::UpdateLoad64Value(inst, uint64_t(ptr));
   2245  }
   2246 }
   2247 
   2248 /* static */
   2249 void Assembler::TraceDataRelocations(JSTracer* trc, JitCode* code,
   2250                                     CompactBufferReader& reader) {
   2251  mozilla::Maybe<AutoWritableJitCode> awjc;
   2252  while (reader.more()) {
   2253    size_t offset = reader.readUnsigned();
   2254    Instruction* inst = (Instruction*)(code->raw() + offset);
   2255    TraceOneDataRelocation(trc, awjc, code, inst);
   2256  }
   2257 }
   2258 
   2259 void Assembler::Bind(uint8_t* rawCode, const CodeLabel& label) {
   2260  if (label.patchAt().bound()) {
   2261    auto mode = label.linkMode();
   2262    intptr_t offset = label.patchAt().offset();
   2263    intptr_t target = label.target().offset();
   2264 
   2265    if (mode == CodeLabel::RawPointer) {
   2266      *reinterpret_cast<const void**>(rawCode + offset) = rawCode + target;
   2267    } else {
   2268      MOZ_ASSERT(mode == CodeLabel::MoveImmediate ||
   2269                 mode == CodeLabel::JumpImmediate);
   2270      Instruction* inst = (Instruction*)(rawCode + offset);
   2271      Assembler::UpdateLoad64Value(inst, (uint64_t)(rawCode + target));
   2272    }
   2273  }
   2274 }
   2275 
   2276 void Assembler::bind(InstImm* inst, uintptr_t branch, uintptr_t target) {
   2277  int64_t offset = target - branch;
   2278  InstImm inst_jirl = InstImm(op_jirl, BOffImm16(0), zero, ra);
   2279  InstImm inst_beq = InstImm(op_beq, BOffImm16(0), zero, zero);
   2280 
   2281  // If encoded offset is 4, then the jump must be short
   2282  if (BOffImm16(inst[0]).decode() == 4) {
   2283    MOZ_ASSERT(BOffImm16::IsInRange(offset));
   2284    inst[0].setBOffImm16(BOffImm16(offset));
   2285    inst[1].makeNop();  // because before set INVALID_OFFSET
   2286    return;
   2287  }
   2288 
   2289  UseScratchRegisterScope temps(*this);
   2290 
   2291  // Generate the long jump for calls because return address has to be the
   2292  // address after the reserved block.
   2293  if (inst[0].encode() == inst_jirl.encode()) {
   2294    Register scratch = temps.Acquire();
   2295    addLongJump(BufferOffset(branch), BufferOffset(target));
   2296    Assembler::WriteLoad64Instructions(inst, scratch,
   2297                                       LabelBase::INVALID_OFFSET);
   2298    inst[3].makeNop();  // There are 1 nop.
   2299    inst[4] = InstImm(op_jirl, BOffImm16(0), scratch, ra);
   2300    return;
   2301  }
   2302 
   2303  if (BOffImm16::IsInRange(offset)) {
   2304    // Skip trailing nops .
   2305    bool skipNops = (inst[0].encode() != inst_jirl.encode() &&
   2306                     inst[0].encode() != inst_beq.encode());
   2307 
   2308    inst[0].setBOffImm16(BOffImm16(offset));
   2309    inst[1].makeNop();
   2310 
   2311    if (skipNops) {
   2312      inst[2] = InstImm(op_bge, BOffImm16(3 * sizeof(uint32_t)), zero, zero);
   2313      // There are 2 nops after this
   2314    }
   2315    return;
   2316  }
   2317 
   2318  if (inst[0].encode() == inst_beq.encode()) {
   2319    // Handle long unconditional jump. Only four 4 instruction.
   2320    addLongJump(BufferOffset(branch), BufferOffset(target));
   2321    Register scratch = temps.Acquire();
   2322    Assembler::WriteLoad64Instructions(inst, scratch,
   2323                                       LabelBase::INVALID_OFFSET);
   2324    inst[3] = InstImm(op_jirl, BOffImm16(0), scratch, zero);
   2325  } else {
   2326    // Handle long conditional jump.
   2327    inst[0] = invertBranch(inst[0], BOffImm16(5 * sizeof(uint32_t)));
   2328    // No need for a "nop" here because we can clobber scratch.
   2329    addLongJump(BufferOffset(branch + sizeof(uint32_t)), BufferOffset(target));
   2330    Register scratch = temps.Acquire();
   2331    Assembler::WriteLoad64Instructions(&inst[1], scratch,
   2332                                       LabelBase::INVALID_OFFSET);
   2333    inst[4] = InstImm(op_jirl, BOffImm16(0), scratch, zero);
   2334  }
   2335 }
   2336 
   2337 void Assembler::processCodeLabels(uint8_t* rawCode) {
   2338  for (const CodeLabel& label : codeLabels_) {
   2339    Bind(rawCode, label);
   2340  }
   2341 }
   2342 
   2343 uint32_t Assembler::PatchWrite_NearCallSize() {
   2344  // Load an address needs 3 instructions, and a jump.
   2345  return (3 + 1) * sizeof(uint32_t);
   2346 }
   2347 
   2348 void Assembler::PatchWrite_NearCall(CodeLocationLabel start,
   2349                                    CodeLocationLabel toCall) {
   2350  Instruction* inst = (Instruction*)start.raw();
   2351  uint8_t* dest = toCall.raw();
   2352 
   2353  // Overwrite whatever instruction used to be here with a call.
   2354  // Always use long jump for two reasons:
   2355  // - Jump has to be the same size because of PatchWrite_NearCallSize.
   2356  // - Return address has to be at the end of replaced block.
   2357  // Short jump wouldn't be more efficient.
   2358  Assembler::WriteLoad64Instructions(inst, SavedScratchRegister,
   2359                                     (uint64_t)dest);
   2360  inst[3] = InstImm(op_jirl, BOffImm16(0), SavedScratchRegister, ra);
   2361 }
   2362 
   2363 uint64_t Assembler::ExtractLoad64Value(Instruction* inst0) {
   2364  InstImm* i0 = (InstImm*)inst0;
   2365  InstImm* i1 = (InstImm*)i0->next();
   2366  InstImm* i2 = (InstImm*)i1->next();
   2367  InstImm* i3 = (InstImm*)i2->next();
   2368 
   2369  MOZ_ASSERT((i0->extractBitField(31, 25)) == ((uint32_t)op_lu12i_w >> 25));
   2370  MOZ_ASSERT((i1->extractBitField(31, 22)) == ((uint32_t)op_ori >> 22));
   2371  MOZ_ASSERT((i2->extractBitField(31, 25)) == ((uint32_t)op_lu32i_d >> 25));
   2372 
   2373  if ((i3->extractBitField(31, 22)) == ((uint32_t)op_lu52i_d >> 22)) {
   2374    // Li64
   2375    uint64_t value =
   2376        (uint64_t(i0->extractBitField(Imm20Bits + Imm20Shift - 1, Imm20Shift))
   2377         << 12) |
   2378        (uint64_t(
   2379            i1->extractBitField(Imm12Bits + Imm12Shift - 1, Imm12Shift))) |
   2380        (uint64_t(i2->extractBitField(Imm20Bits + Imm20Shift - 1, Imm20Shift))
   2381         << 32) |
   2382        (uint64_t(i3->extractBitField(Imm12Bits + Imm12Shift - 1, Imm12Shift))
   2383         << 52);
   2384    return value;
   2385  } else {
   2386    // Li48
   2387    uint64_t value =
   2388        (uint64_t(i0->extractBitField(Imm20Bits + Imm20Shift - 1, Imm20Shift))
   2389         << 12) |
   2390        (uint64_t(
   2391            i1->extractBitField(Imm12Bits + Imm12Shift - 1, Imm12Shift))) |
   2392        (uint64_t(i2->extractBitField(Imm20Bits + Imm20Shift - 1, Imm20Shift))
   2393         << 32);
   2394 
   2395    return uint64_t((int64_t(value) << 16) >> 16);
   2396  }
   2397 }
   2398 
   2399 void Assembler::UpdateLoad64Value(Instruction* inst0, uint64_t value) {
   2400  // Todo: with ma_liPatchable
   2401  InstImm* i0 = (InstImm*)inst0;
   2402  InstImm* i1 = (InstImm*)i0->next();
   2403  InstImm* i2 = (InstImm*)i1->next();
   2404  InstImm* i3 = (InstImm*)i2->next();
   2405 
   2406  MOZ_ASSERT((i0->extractBitField(31, 25)) == ((uint32_t)op_lu12i_w >> 25));
   2407  MOZ_ASSERT((i1->extractBitField(31, 22)) == ((uint32_t)op_ori >> 22));
   2408  MOZ_ASSERT((i2->extractBitField(31, 25)) == ((uint32_t)op_lu32i_d >> 25));
   2409 
   2410  if ((i3->extractBitField(31, 22)) == ((uint32_t)op_lu52i_d >> 22)) {
   2411    // Li64
   2412    *i0 = InstImm(op_lu12i_w, (int32_t)((value >> 12) & 0xfffff),
   2413                  Register::FromCode(i0->extractRD()), false);
   2414    *i1 = InstImm(op_ori, (int32_t)(value & 0xfff),
   2415                  Register::FromCode(i1->extractRJ()),
   2416                  Register::FromCode(i1->extractRD()), 12);
   2417    *i2 = InstImm(op_lu32i_d, (int32_t)((value >> 32) & 0xfffff),
   2418                  Register::FromCode(i2->extractRD()), false);
   2419    *i3 = InstImm(op_lu52i_d, (int32_t)((value >> 52) & 0xfff),
   2420                  Register::FromCode(i3->extractRJ()),
   2421                  Register::FromCode(i3->extractRD()), 12);
   2422  } else {
   2423    // Li48
   2424    *i0 = InstImm(op_lu12i_w, (int32_t)((value >> 12) & 0xfffff),
   2425                  Register::FromCode(i0->extractRD()), false);
   2426    *i1 = InstImm(op_ori, (int32_t)(value & 0xfff),
   2427                  Register::FromCode(i1->extractRJ()),
   2428                  Register::FromCode(i1->extractRD()), 12);
   2429    *i2 = InstImm(op_lu32i_d, (int32_t)((value >> 32) & 0xfffff),
   2430                  Register::FromCode(i2->extractRD()), false);
   2431  }
   2432 }
   2433 
   2434 void Assembler::WriteLoad64Instructions(Instruction* inst0, Register reg,
   2435                                        uint64_t value) {
   2436  Instruction* inst1 = inst0->next();
   2437  Instruction* inst2 = inst1->next();
   2438  *inst0 = InstImm(op_lu12i_w, (int32_t)((value >> 12) & 0xfffff), reg, false);
   2439  *inst1 = InstImm(op_ori, (int32_t)(value & 0xfff), reg, reg, 12);
   2440  *inst2 = InstImm(op_lu32i_d, (int32_t)((value >> 32) & 0xfffff), reg, false);
   2441 }
   2442 
   2443 void Assembler::PatchDataWithValueCheck(CodeLocationLabel label,
   2444                                        ImmPtr newValue, ImmPtr expectedValue) {
   2445  PatchDataWithValueCheck(label, PatchedImmPtr(newValue.value),
   2446                          PatchedImmPtr(expectedValue.value));
   2447 }
   2448 
   2449 void Assembler::PatchDataWithValueCheck(CodeLocationLabel label,
   2450                                        PatchedImmPtr newValue,
   2451                                        PatchedImmPtr expectedValue) {
   2452  Instruction* inst = (Instruction*)label.raw();
   2453 
   2454  // Extract old Value
   2455  DebugOnly<uint64_t> value = Assembler::ExtractLoad64Value(inst);
   2456  MOZ_ASSERT(value == uint64_t(expectedValue.value));
   2457 
   2458  // Replace with new value
   2459  Assembler::UpdateLoad64Value(inst, uint64_t(newValue.value));
   2460 }
   2461 
   2462 uint64_t Assembler::ExtractInstructionImmediate(uint8_t* code) {
   2463  InstImm* inst = (InstImm*)code;
   2464  return Assembler::ExtractLoad64Value(inst);
   2465 }
   2466 
   2467 void Assembler::ToggleCall(CodeLocationLabel inst_, bool enabled) {
   2468  Instruction* inst = (Instruction*)inst_.raw();
   2469  InstImm* i0 = (InstImm*)inst;
   2470  InstImm* i1 = (InstImm*)i0->next();
   2471  InstImm* i2 = (InstImm*)i1->next();
   2472  Instruction* i3 = (Instruction*)i2->next();
   2473 
   2474  MOZ_ASSERT((i0->extractBitField(31, 25)) == ((uint32_t)op_lu12i_w >> 25));
   2475  MOZ_ASSERT((i1->extractBitField(31, 22)) == ((uint32_t)op_ori >> 22));
   2476  MOZ_ASSERT((i2->extractBitField(31, 25)) == ((uint32_t)op_lu32i_d >> 25));
   2477 
   2478  if (enabled) {
   2479    MOZ_ASSERT((i3->extractBitField(31, 25)) != ((uint32_t)op_lu12i_w >> 25));
   2480    InstImm jirl =
   2481        InstImm(op_jirl, BOffImm16(0), Register::FromCode(i2->extractRD()), ra);
   2482    *i3 = jirl;
   2483  } else {
   2484    InstNOP nop;
   2485    *i3 = nop;
   2486  }
   2487 }
   2488 
   2489 UseScratchRegisterScope::UseScratchRegisterScope(Assembler& assembler)
   2490    : available_(assembler.GetScratchRegisterList()),
   2491      old_available_(*available_) {}
   2492 
   2493 UseScratchRegisterScope::UseScratchRegisterScope(Assembler* assembler)
   2494    : available_(assembler->GetScratchRegisterList()),
   2495      old_available_(*available_) {}
   2496 
   2497 UseScratchRegisterScope::~UseScratchRegisterScope() {
   2498  *available_ = old_available_;
   2499 }
   2500 
   2501 Register UseScratchRegisterScope::Acquire() {
   2502  MOZ_ASSERT(available_ != nullptr);
   2503  MOZ_ASSERT(!available_->empty());
   2504  Register index = GeneralRegisterSet::FirstRegister(available_->bits());
   2505  available_->takeRegisterIndex(index);
   2506  return index;
   2507 }
   2508 
   2509 void UseScratchRegisterScope::Release(const Register& reg) {
   2510  MOZ_ASSERT(available_ != nullptr);
   2511  MOZ_ASSERT(old_available_.hasRegisterIndex(reg));
   2512  MOZ_ASSERT(!available_->hasRegisterIndex(reg));
   2513  Include(GeneralRegisterSet(1 << reg.code()));
   2514 }
   2515 
   2516 bool UseScratchRegisterScope::hasAvailable() const {
   2517  return (available_->size()) != 0;
   2518 }