Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  Assembler-loong64.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "jit/loong64/Assembler-loong64.h"

#include "mozilla/DebugOnly.h"
#include "mozilla/Maybe.h"

#include "gc/Marking.h"
#include "jit/AutoWritableJitCode.h"
#include "jit/ExecutableAllocator.h"
#include "vm/Realm.h"

using mozilla::DebugOnly;

using namespace js;
using namespace js::jit;

// Note this is used for inter-wasm calls and may pass arguments and results
// in floating point registers even if the system ABI does not.

// TODO(loong64): Inconsistent with LoongArch's calling convention.
// LoongArch floating-point parameters calling convention:
//   The first eight floating-point parameters should be passed in f0-f7, and
//   the other floating point parameters will be passed like integer parameters.
// But we just pass the other floating-point parameters on stack here.
ABIArg ABIArgGenerator::next(MIRType type) {
  switch (type) {
    case MIRType::Int32:
    case MIRType::Int64:
    case MIRType::Pointer:
    case MIRType::WasmAnyRef:
    case MIRType::WasmArrayData:
    case MIRType::StackResults: {
      if (intRegIndex_ == NumIntArgRegs) {
        current_ = ABIArg(stackOffset_);
        stackOffset_ += sizeof(uintptr_t);
        break;
      }
      current_ = ABIArg(Register::FromCode(intRegIndex_ + a0.encoding()));
      intRegIndex_++;
      break;
    }
    case MIRType::Float32:
    case MIRType::Double: {
      if (floatRegIndex_ == NumFloatArgRegs) {
        current_ = ABIArg(stackOffset_);
        stackOffset_ += sizeof(double);
        break;
      }
      current_ = ABIArg(FloatRegister(
          FloatRegisters::Encoding(floatRegIndex_ + f0.encoding()),
          type == MIRType::Double ? FloatRegisters::Double
                                  : FloatRegisters::Single));
      floatRegIndex_++;
      break;
    }
    case MIRType::Simd128: {
      MOZ_CRASH("LoongArch does not support simd yet.");
      break;
    }
    default:
      MOZ_CRASH("Unexpected argument type");
  }
  return current_;
}

// Encode a standard register when it is being used as rd, the rj, and
// an extra register(rk). These should never be called with an InvalidReg.
uint32_t js::jit::RJ(Register r) {
  MOZ_ASSERT(r != InvalidReg);
  return r.encoding() << RJShift;
}

uint32_t js::jit::RK(Register r) {
  MOZ_ASSERT(r != InvalidReg);
  return r.encoding() << RKShift;
}

uint32_t js::jit::RD(Register r) {
  MOZ_ASSERT(r != InvalidReg);
  return r.encoding() << RDShift;
}

uint32_t js::jit::FJ(FloatRegister r) { return r.encoding() << RJShift; }

uint32_t js::jit::FK(FloatRegister r) { return r.encoding() << RKShift; }

uint32_t js::jit::FD(FloatRegister r) { return r.encoding() << RDShift; }

uint32_t js::jit::FA(FloatRegister r) { return r.encoding() << FAShift; }

uint32_t js::jit::SA2(uint32_t value) {
  MOZ_ASSERT(value < 4);
  return (value & SA2Mask) << SAShift;
}

uint32_t js::jit::SA3(uint32_t value) {
  MOZ_ASSERT(value < 8);
  return (value & SA3Mask) << SAShift;
}

Register js::jit::toRK(Instruction& i) {
  return Register::FromCode(((i.encode() >> RKShift) & RKMask));
}

Register js::jit::toRJ(Instruction& i) {
  return Register::FromCode(((i.encode() >> RJShift) & RJMask));
}

Register js::jit::toRD(Instruction& i) {
  return Register::FromCode(((i.encode() >> RDShift) & RDMask));
}

Register js::jit::toR(Instruction& i) {
  return Register::FromCode(i.encode() & RegMask);
}

void InstImm::extractImm16(BOffImm16* dest) { *dest = BOffImm16(*this); }

void AssemblerLOONG64::finish() {
  MOZ_ASSERT(!isFinished);
  isFinished = true;
}

bool AssemblerLOONG64::appendRawCode(const uint8_t* code, size_t numBytes) {
  return m_buffer.appendRawCode(code, numBytes);
}

bool AssemblerLOONG64::reserve(size_t size) {
  // This buffer uses fixed-size chunks so there's no point in reserving
  // now vs. on-demand.
  return !oom();
}

bool AssemblerLOONG64::swapBuffer(wasm::Bytes& bytes) {
  // For now, specialize to the one use case. As long as wasm::Bytes is a
  // Vector, not a linked-list of chunks, there's not much we can do other
  // than copy.
  MOZ_ASSERT(bytes.empty());
  if (!bytes.resize(bytesNeeded())) {
    return false;
  }
  m_buffer.executableCopy(bytes.begin());
  return true;
}

void AssemblerLOONG64::copyJumpRelocationTable(uint8_t* dest) {
  if (jumpRelocations_.length()) {
    memcpy(dest, jumpRelocations_.buffer(), jumpRelocations_.length());
  }
}

void AssemblerLOONG64::copyDataRelocationTable(uint8_t* dest) {
  if (dataRelocations_.length()) {
    memcpy(dest, dataRelocations_.buffer(), dataRelocations_.length());
  }
}

AssemblerLOONG64::Condition AssemblerLOONG64::InvertCondition(Condition cond) {
  switch (cond) {
    case Equal:
      return NotEqual;
    case NotEqual:
      return Equal;
    case Zero:
      return NonZero;
    case NonZero:
      return Zero;
    case LessThan:
      return GreaterThanOrEqual;
    case LessThanOrEqual:
      return GreaterThan;
    case GreaterThan:
      return LessThanOrEqual;
    case GreaterThanOrEqual:
      return LessThan;
    case Above:
      return BelowOrEqual;
    case AboveOrEqual:
      return Below;
    case Below:
      return AboveOrEqual;
    case BelowOrEqual:
      return Above;
    case Signed:
      return NotSigned;
    case NotSigned:
      return Signed;
    default:
      MOZ_CRASH("unexpected condition");
  }
}

AssemblerLOONG64::DoubleCondition AssemblerLOONG64::InvertCondition(
    DoubleCondition cond) {
  switch (cond) {
    case DoubleOrdered:
      return DoubleUnordered;
    case DoubleEqual:
      return DoubleNotEqualOrUnordered;
    case DoubleNotEqual:
      return DoubleEqualOrUnordered;
    case DoubleGreaterThan:
      return DoubleLessThanOrEqualOrUnordered;
    case DoubleGreaterThanOrEqual:
      return DoubleLessThanOrUnordered;
    case DoubleLessThan:
      return DoubleGreaterThanOrEqualOrUnordered;
    case DoubleLessThanOrEqual:
      return DoubleGreaterThanOrUnordered;
    case DoubleUnordered:
      return DoubleOrdered;
    case DoubleEqualOrUnordered:
      return DoubleNotEqual;
    case DoubleNotEqualOrUnordered:
      return DoubleEqual;
    case DoubleGreaterThanOrUnordered:
      return DoubleLessThanOrEqual;
    case DoubleGreaterThanOrEqualOrUnordered:
      return DoubleLessThan;
    case DoubleLessThanOrUnordered:
      return DoubleGreaterThanOrEqual;
    case DoubleLessThanOrEqualOrUnordered:
      return DoubleGreaterThan;
    default:
      MOZ_CRASH("unexpected condition");
  }
}

AssemblerLOONG64::Condition AssemblerLOONG64::InvertCmpCondition(
    Condition cond) {
  switch (cond) {
    case Equal:
    case NotEqual:
      return cond;
    case LessThan:
      return GreaterThan;
    case LessThanOrEqual:
      return GreaterThanOrEqual;
    case GreaterThan:
      return LessThanOrEqual;
    case GreaterThanOrEqual:
      return LessThan;
    case Above:
      return Below;
    case AboveOrEqual:
      return BelowOrEqual;
    case Below:
      return Above;
    case BelowOrEqual:
      return AboveOrEqual;
    default:
      MOZ_CRASH("no meaningful swapped-operand condition");
  }
}

BOffImm16::BOffImm16(InstImm inst)
    : data((inst.encode() >> Imm16Shift) & Imm16Mask) {}

Instruction* BOffImm16::getDest(Instruction* src) const {
  return &src[(((int32_t)data << 16) >> 16) + 1];
}

bool AssemblerLOONG64::oom() const {
  return AssemblerShared::oom() || m_buffer.oom() || jumpRelocations_.oom() ||
         dataRelocations_.oom();
}

// Size of the instruction stream, in bytes.
size_t AssemblerLOONG64::size() const { return m_buffer.size(); }

// Size of the relocation table, in bytes.
size_t AssemblerLOONG64::jumpRelocationTableBytes() const {
  return jumpRelocations_.length();
}

size_t AssemblerLOONG64::dataRelocationTableBytes() const {
  return dataRelocations_.length();
}

// Size of the data table, in bytes.
size_t AssemblerLOONG64::bytesNeeded() const {
  return size() + jumpRelocationTableBytes() + dataRelocationTableBytes();
}

// write a blob of binary into the instruction stream
BufferOffset AssemblerLOONG64::writeInst(uint32_t x, uint32_t* dest) {
  MOZ_ASSERT(hasCreator());
  if (dest == nullptr) {
    return m_buffer.putInt(x);
  }

  WriteInstStatic(x, dest);
  return BufferOffset();
}

void AssemblerLOONG64::WriteInstStatic(uint32_t x, uint32_t* dest) {
  MOZ_ASSERT(dest != nullptr);
  *dest = x;
}

BufferOffset AssemblerLOONG64::haltingAlign(int alignment) {
  // TODO(loong64): Implement a proper halting align.
  return nopAlign(alignment);
}

BufferOffset AssemblerLOONG64::nopAlign(int alignment) {
  BufferOffset ret;
  MOZ_ASSERT(m_buffer.isAligned(4));
  if (alignment == 8) {
    if (!m_buffer.isAligned(alignment)) {
      BufferOffset tmp = as_nop();
      if (!ret.assigned()) {
        ret = tmp;
      }
    }
  } else {
    MOZ_ASSERT((alignment & (alignment - 1)) == 0);
    while (size() & (alignment - 1)) {
      BufferOffset tmp = as_nop();
      if (!ret.assigned()) {
        ret = tmp;
      }
    }
  }
  return ret;
}

// Logical operations.
BufferOffset AssemblerLOONG64::as_and(Register rd, Register rj, Register rk) {
  spew("and %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_and, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_or(Register rd, Register rj, Register rk) {
  spew("or %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_or, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_xor(Register rd, Register rj, Register rk) {
  spew("xor %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_xor, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_nor(Register rd, Register rj, Register rk) {
  spew("nor %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_nor, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_andn(Register rd, Register rj, Register rk) {
  spew("andn %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_andn, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_orn(Register rd, Register rj, Register rk) {
  spew("orn %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_orn, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_andi(Register rd, Register rj, int32_t ui12) {
  MOZ_ASSERT(is_uintN(ui12, 12));
  spew("andi %3s,%3s,0x%x", rd.name(), rj.name(), ui12);
  return writeInst(InstImm(op_andi, ui12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_ori(Register rd, Register rj, int32_t ui12) {
  MOZ_ASSERT(is_uintN(ui12, 12));
  spew("ori %3s,%3s,0x%x", rd.name(), rj.name(), ui12);
  return writeInst(InstImm(op_ori, ui12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_xori(Register rd, Register rj, int32_t ui12) {
  MOZ_ASSERT(is_uintN(ui12, 12));
  spew("xori %3s,%3s,0x%x", rd.name(), rj.name(), ui12);
  return writeInst(InstImm(op_xori, ui12, rj, rd, 12).encode());
}

// Branch and jump instructions
BufferOffset AssemblerLOONG64::as_b(JOffImm26 off) {
  spew("b %d", off.decode());
  return writeInst(InstJump(op_b, off).encode());
}

BufferOffset AssemblerLOONG64::as_bl(JOffImm26 off) {
  spew("bl %d", off.decode());
  return writeInst(InstJump(op_bl, off).encode());
}

BufferOffset AssemblerLOONG64::as_jirl(Register rd, Register rj,
                                       BOffImm16 off) {
  spew("jirl %3s, %3s, %d", rd.name(), rj.name(), off.decode());
  return writeInst(InstImm(op_jirl, off, rj, rd).encode());
}

InstImm AssemblerLOONG64::getBranchCode(JumpOrCall jumpOrCall) {
  // jirl or beq
  if (jumpOrCall == BranchIsCall) {
    return InstImm(op_jirl, BOffImm16(0), zero, ra);
  }

  return InstImm(op_beq, BOffImm16(0), zero, zero);
}

InstImm AssemblerLOONG64::getBranchCode(Register rj, Register rd, Condition c) {
  // beq, bne
  MOZ_ASSERT(c == AssemblerLOONG64::Equal || c == AssemblerLOONG64::NotEqual);
  return InstImm(c == AssemblerLOONG64::Equal ? op_beq : op_bne, BOffImm16(0),
                 rj, rd);
}

InstImm AssemblerLOONG64::getBranchCode(Register rj, Condition c) {
  // beq, bne, blt, bge
  switch (c) {
    case AssemblerLOONG64::Equal:
    case AssemblerLOONG64::Zero:
    case AssemblerLOONG64::BelowOrEqual:
      return InstImm(op_beq, BOffImm16(0), rj, zero);
    case AssemblerLOONG64::NotEqual:
    case AssemblerLOONG64::NonZero:
    case AssemblerLOONG64::Above:
      return InstImm(op_bne, BOffImm16(0), rj, zero);
    case AssemblerLOONG64::GreaterThan:
      return InstImm(op_blt, BOffImm16(0), zero, rj);
    case AssemblerLOONG64::GreaterThanOrEqual:
    case AssemblerLOONG64::NotSigned:
      return InstImm(op_bge, BOffImm16(0), rj, zero);
    case AssemblerLOONG64::LessThan:
    case AssemblerLOONG64::Signed:
      return InstImm(op_blt, BOffImm16(0), rj, zero);
    case AssemblerLOONG64::LessThanOrEqual:
      return InstImm(op_bge, BOffImm16(0), zero, rj);
    default:
      MOZ_CRASH("Condition not supported.");
  }
}

// Code semantics must conform to compareFloatingpoint
InstImm AssemblerLOONG64::getBranchCode(FPConditionBit cj) {
  return InstImm(op_bcz, 0, cj, true);  // bcnez
}

// Arithmetic instructions
BufferOffset AssemblerLOONG64::as_add_w(Register rd, Register rj, Register rk) {
  spew("add_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_add_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_add_d(Register rd, Register rj, Register rk) {
  spew("add_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_add_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_sub_w(Register rd, Register rj, Register rk) {
  spew("sub_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_sub_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_sub_d(Register rd, Register rj, Register rk) {
  spew("sub_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_sub_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_addi_w(Register rd, Register rj,
                                         int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("addi_w %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_addi_w, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_addi_d(Register rd, Register rj,
                                         int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("addi_d %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_addi_d, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_addu16i_d(Register rd, Register rj,
                                            int32_t si16) {
  MOZ_ASSERT(Imm16::IsInSignedRange(si16));
  spew("addu16i_d %3s,%3s,0x%x", rd.name(), rj.name(), si16);
  return writeInst(InstImm(op_addu16i_d, Imm16(si16), rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_alsl_w(Register rd, Register rj, Register rk,
                                         uint32_t sa2) {
  MOZ_ASSERT(sa2 < 4);
  spew("alsl_w %3s,%3s,0x%x", rd.name(), rj.name(), sa2);
  return writeInst(InstReg(op_alsl_w, sa2, rk, rj, rd, 2).encode());
}

BufferOffset AssemblerLOONG64::as_alsl_wu(Register rd, Register rj, Register rk,
                                          uint32_t sa2) {
  MOZ_ASSERT(sa2 < 4);
  spew("alsl_wu %3s,%3s,0x%x", rd.name(), rj.name(), sa2);
  return writeInst(InstReg(op_alsl_wu, sa2, rk, rj, rd, 2).encode());
}

BufferOffset AssemblerLOONG64::as_alsl_d(Register rd, Register rj, Register rk,
                                         uint32_t sa2) {
  MOZ_ASSERT(sa2 < 4);
  spew("alsl_d %3s,%3s,%3s,0x%x", rd.name(), rj.name(), rk.name(), sa2);
  return writeInst(InstReg(op_alsl_d, sa2, rk, rj, rd, 2).encode());
}

BufferOffset AssemblerLOONG64::as_lu12i_w(Register rd, int32_t si20) {
  spew("lu12i_w %3s,0x%x", rd.name(), si20);
  return writeInst(InstImm(op_lu12i_w, si20, rd, false).encode());
}

BufferOffset AssemblerLOONG64::as_lu32i_d(Register rd, int32_t si20) {
  spew("lu32i_d %3s,0x%x", rd.name(), si20);
  return writeInst(InstImm(op_lu32i_d, si20, rd, false).encode());
}

BufferOffset AssemblerLOONG64::as_lu52i_d(Register rd, Register rj,
                                          int32_t si12) {
  MOZ_ASSERT(is_uintN(si12, 12));
  spew("lu52i_d %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_lu52i_d, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_slt(Register rd, Register rj, Register rk) {
  spew("slt %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_slt, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_sltu(Register rd, Register rj, Register rk) {
  spew("sltu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_sltu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_slti(Register rd, Register rj, int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("slti %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_slti, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_sltui(Register rd, Register rj,
                                        int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("sltui %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_sltui, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_pcaddi(Register rd, int32_t si20) {
  spew("pcaddi %3s,0x%x", rd.name(), si20);
  return writeInst(InstImm(op_pcaddi, si20, rd, false).encode());
}

BufferOffset AssemblerLOONG64::as_pcaddu12i(Register rd, int32_t si20) {
  spew("pcaddu12i %3s,0x%x", rd.name(), si20);
  return writeInst(InstImm(op_pcaddu12i, si20, rd, false).encode());
}

BufferOffset AssemblerLOONG64::as_pcaddu18i(Register rd, int32_t si20) {
  spew("pcaddu18i %3s,0x%x", rd.name(), si20);
  return writeInst(InstImm(op_pcaddu18i, si20, rd, false).encode());
}

BufferOffset AssemblerLOONG64::as_pcalau12i(Register rd, int32_t si20) {
  spew("pcalau12i %3s,0x%x", rd.name(), si20);
  return writeInst(InstImm(op_pcalau12i, si20, rd, false).encode());
}

BufferOffset AssemblerLOONG64::as_mul_w(Register rd, Register rj, Register rk) {
  spew("mul_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mul_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mulh_w(Register rd, Register rj,
                                         Register rk) {
  spew("mulh_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mulh_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mulh_wu(Register rd, Register rj,
                                          Register rk) {
  spew("mulh_wu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mulh_wu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mul_d(Register rd, Register rj, Register rk) {
  spew("mul_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mul_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mulh_d(Register rd, Register rj,
                                         Register rk) {
  spew("mulh_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mulh_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mulh_du(Register rd, Register rj,
                                          Register rk) {
  spew("mulh_du %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mulh_du, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mulw_d_w(Register rd, Register rj,
                                           Register rk) {
  spew("mulw_d_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mulw_d_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mulw_d_wu(Register rd, Register rj,
                                            Register rk) {
  spew("mulw_d_wu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mulw_d_wu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_div_w(Register rd, Register rj, Register rk) {
  spew("div_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_div_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mod_w(Register rd, Register rj, Register rk) {
  spew("mod_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mod_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_div_wu(Register rd, Register rj,
                                         Register rk) {
  spew("div_wu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_div_wu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mod_wu(Register rd, Register rj,
                                         Register rk) {
  spew("mod_wu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mod_wu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_div_d(Register rd, Register rj, Register rk) {
  spew("div_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_div_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mod_d(Register rd, Register rj, Register rk) {
  spew("mod_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mod_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_div_du(Register rd, Register rj,
                                         Register rk) {
  spew("div_du %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_div_du, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_mod_du(Register rd, Register rj,
                                         Register rk) {
  spew("mod_du %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_mod_du, rk, rj, rd).encode());
}

// Shift instructions
BufferOffset AssemblerLOONG64::as_sll_w(Register rd, Register rj, Register rk) {
  spew("sll_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_sll_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_srl_w(Register rd, Register rj, Register rk) {
  spew("srl_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_srl_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_sra_w(Register rd, Register rj, Register rk) {
  spew("sra_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_sra_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_rotr_w(Register rd, Register rj,
                                         Register rk) {
  spew("rotr_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_rotr_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_slli_w(Register rd, Register rj,
                                         int32_t ui5) {
  MOZ_ASSERT(is_uintN(ui5, 5));
  spew("slli_w %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
  return writeInst(InstImm(op_slli_w, ui5, rj, rd, 5).encode());
}

BufferOffset AssemblerLOONG64::as_srli_w(Register rd, Register rj,
                                         int32_t ui5) {
  MOZ_ASSERT(is_uintN(ui5, 5));
  spew("srli_w %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
  return writeInst(InstImm(op_srli_w, ui5, rj, rd, 5).encode());
}

BufferOffset AssemblerLOONG64::as_srai_w(Register rd, Register rj,
                                         int32_t ui5) {
  MOZ_ASSERT(is_uintN(ui5, 5));
  spew("srai_w %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
  return writeInst(InstImm(op_srai_w, ui5, rj, rd, 5).encode());
}

BufferOffset AssemblerLOONG64::as_rotri_w(Register rd, Register rj,
                                          int32_t ui5) {
  MOZ_ASSERT(is_uintN(ui5, 5));
  spew("rotri_w %3s,%3s,0x%x", rd.name(), rj.name(), ui5);
  return writeInst(InstImm(op_rotri_w, ui5, rj, rd, 5).encode());
}

BufferOffset AssemblerLOONG64::as_sll_d(Register rd, Register rj, Register rk) {
  spew("sll_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_sll_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_srl_d(Register rd, Register rj, Register rk) {
  spew("srl_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_srl_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_sra_d(Register rd, Register rj, Register rk) {
  spew("sra_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_sra_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_rotr_d(Register rd, Register rj,
                                         Register rk) {
  spew("rotr_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_rotr_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_slli_d(Register rd, Register rj,
                                         int32_t ui6) {
  MOZ_ASSERT(is_uintN(ui6, 6));
  spew("slli_d %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
  return writeInst(InstImm(op_slli_d, ui6, rj, rd, 6).encode());
}

BufferOffset AssemblerLOONG64::as_srli_d(Register rd, Register rj,
                                         int32_t ui6) {
  MOZ_ASSERT(is_uintN(ui6, 6));
  spew("srli_d %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
  return writeInst(InstImm(op_srli_d, ui6, rj, rd, 6).encode());
}

BufferOffset AssemblerLOONG64::as_srai_d(Register rd, Register rj,
                                         int32_t ui6) {
  MOZ_ASSERT(is_uintN(ui6, 6));
  spew("srai_d %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
  return writeInst(InstImm(op_srai_d, ui6, rj, rd, 6).encode());
}

BufferOffset AssemblerLOONG64::as_rotri_d(Register rd, Register rj,
                                          int32_t ui6) {
  MOZ_ASSERT(is_uintN(ui6, 6));
  spew("rotri_d %3s,%3s,0x%x", rd.name(), rj.name(), ui6);
  return writeInst(InstImm(op_rotri_d, ui6, rj, rd, 6).encode());
}

// Bit operation instrucitons
BufferOffset AssemblerLOONG64::as_ext_w_b(Register rd, Register rj) {
  spew("ext_w_b %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_ext_w_b, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ext_w_h(Register rd, Register rj) {
  spew("ext_w_h %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_ext_w_h, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_clo_w(Register rd, Register rj) {
  spew("clo_w %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_clo_w, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_clz_w(Register rd, Register rj) {
  spew("clz_w %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_clz_w, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_cto_w(Register rd, Register rj) {
  spew("cto_w %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_cto_w, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ctz_w(Register rd, Register rj) {
  spew("ctz_w %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_ctz_w, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_clo_d(Register rd, Register rj) {
  spew("clo_d %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_clo_d, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_clz_d(Register rd, Register rj) {
  spew("clz_d %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_clz_d, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_cto_d(Register rd, Register rj) {
  spew("cto_d %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_cto_d, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ctz_d(Register rd, Register rj) {
  spew("ctz_d %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_ctz_d, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_bytepick_w(Register rd, Register rj,
                                             Register rk, int32_t sa2) {
  MOZ_ASSERT(sa2 < 4);
  spew("bytepick_w %3s,%3s,%3s, 0x%x", rd.name(), rj.name(), rk.name(), sa2);
  return writeInst(InstReg(op_bytepick_w, sa2, rk, rj, rd, 2).encode());
}

BufferOffset AssemblerLOONG64::as_bytepick_d(Register rd, Register rj,
                                             Register rk, int32_t sa3) {
  MOZ_ASSERT(sa3 < 8);
  spew("bytepick_d %3s,%3s,%3s, 0x%x", rd.name(), rj.name(), rk.name(), sa3);
  return writeInst(InstReg(op_bytepick_d, sa3, rk, rj, rd, 3).encode());
}

BufferOffset AssemblerLOONG64::as_revb_2h(Register rd, Register rj) {
  spew("revb_2h %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_revb_2h, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_revb_4h(Register rd, Register rj) {
  spew("revb_4h %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_revb_4h, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_revb_2w(Register rd, Register rj) {
  spew("revb_2w %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_revb_2w, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_revb_d(Register rd, Register rj) {
  spew("revb_d %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_revb_d, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_revh_2w(Register rd, Register rj) {
  spew("revh_2w %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_revh_2w, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_revh_d(Register rd, Register rj) {
  spew("revh_d %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_revh_d, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_bitrev_4b(Register rd, Register rj) {
  spew("bitrev_4b %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_bitrev_4b, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_bitrev_8b(Register rd, Register rj) {
  spew("bitrev_8b %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_bitrev_8b, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_bitrev_w(Register rd, Register rj) {
  spew("bitrev_w %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_bitrev_w, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_bitrev_d(Register rd, Register rj) {
  spew("bitrev_d %3s,%3s", rd.name(), rj.name());
  return writeInst(InstReg(op_bitrev_d, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_bstrins_w(Register rd, Register rj,
                                            int32_t msbw, int32_t lsbw) {
  MOZ_ASSERT(lsbw <= msbw);
  spew("bstrins_w %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbw, lsbw);
  return writeInst(InstImm(op_bstr_w, msbw, lsbw, rj, rd, 5).encode());
}

BufferOffset AssemblerLOONG64::as_bstrins_d(Register rd, Register rj,
                                            int32_t msbd, int32_t lsbd) {
  MOZ_ASSERT(lsbd <= msbd);
  spew("bstrins_d %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbd, lsbd);
  return writeInst(InstImm(op_bstrins_d, msbd, lsbd, rj, rd, 6).encode());
}

BufferOffset AssemblerLOONG64::as_bstrpick_w(Register rd, Register rj,
                                             int32_t msbw, int32_t lsbw) {
  MOZ_ASSERT(lsbw <= msbw);
  spew("bstrpick_w %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbw, lsbw);
  return writeInst(InstImm(op_bstr_w, msbw, lsbw, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_bstrpick_d(Register rd, Register rj,
                                             int32_t msbd, int32_t lsbd) {
  MOZ_ASSERT(lsbd <= msbd);
  spew("bstrpick_d %3s,%3s,0x%x,0x%x", rd.name(), rj.name(), msbd, lsbd);
  return writeInst(InstImm(op_bstrpick_d, msbd, lsbd, rj, rd, 6).encode());
}

BufferOffset AssemblerLOONG64::as_maskeqz(Register rd, Register rj,
                                          Register rk) {
  spew("maskeqz %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_maskeqz, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_masknez(Register rd, Register rj,
                                          Register rk) {
  spew("masknez %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_masknez, rk, rj, rd).encode());
}

// Load and store instructions
BufferOffset AssemblerLOONG64::as_ld_b(Register rd, Register rj, int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("ld_b %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_ld_b, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_ld_h(Register rd, Register rj, int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("ld_h %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_ld_h, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_ld_w(Register rd, Register rj, int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("ld_w %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_ld_w, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_ld_d(Register rd, Register rj, int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("ld_d %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_ld_d, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_ld_bu(Register rd, Register rj,
                                        int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("ld_bu %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_ld_bu, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_ld_hu(Register rd, Register rj,
                                        int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("ld_hu %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_ld_hu, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_ld_wu(Register rd, Register rj,
                                        int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("ld_wu %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_ld_wu, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_st_b(Register rd, Register rj, int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("st_b %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_st_b, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_st_h(Register rd, Register rj, int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("st_h %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_st_h, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_st_w(Register rd, Register rj, int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("st_w %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_st_w, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_st_d(Register rd, Register rj, int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("st_d %3s,%3s,0x%x", rd.name(), rj.name(), si12);
  return writeInst(InstImm(op_st_d, si12, rj, rd, 12).encode());
}

BufferOffset AssemblerLOONG64::as_ldx_b(Register rd, Register rj, Register rk) {
  spew("ldx_b %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ldx_b, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ldx_h(Register rd, Register rj, Register rk) {
  spew("ldx_h %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ldx_h, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ldx_w(Register rd, Register rj, Register rk) {
  spew("ldx_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ldx_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ldx_d(Register rd, Register rj, Register rk) {
  spew("ldx_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ldx_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ldx_bu(Register rd, Register rj,
                                         Register rk) {
  spew("ldx_bu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ldx_bu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ldx_hu(Register rd, Register rj,
                                         Register rk) {
  spew("ldx_hu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ldx_hu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ldx_wu(Register rd, Register rj,
                                         Register rk) {
  spew("ldx_wu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ldx_wu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_stx_b(Register rd, Register rj, Register rk) {
  spew("stx_b %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_stx_b, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_stx_h(Register rd, Register rj, Register rk) {
  spew("stx_h %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_stx_h, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_stx_w(Register rd, Register rj, Register rk) {
  spew("stx_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_stx_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_stx_d(Register rd, Register rj, Register rk) {
  spew("stx_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_stx_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ldptr_w(Register rd, Register rj,
                                          int32_t si14) {
  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
  spew("ldptr_w %3s,%3s,0x%x", rd.name(), rj.name(), si14);
  return writeInst(InstImm(op_ldptr_w, si14 >> 2, rj, rd, 14).encode());
}

BufferOffset AssemblerLOONG64::as_ldptr_d(Register rd, Register rj,
                                          int32_t si14) {
  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
  spew("ldptr_d %3s,%3s,0x%x", rd.name(), rj.name(), si14);
  return writeInst(InstImm(op_ldptr_d, si14 >> 2, rj, rd, 14).encode());
}

BufferOffset AssemblerLOONG64::as_stptr_w(Register rd, Register rj,
                                          int32_t si14) {
  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
  spew("stptr_w %3s,%3s,0x%x", rd.name(), rj.name(), si14);
  return writeInst(InstImm(op_stptr_w, si14 >> 2, rj, rd, 14).encode());
}

BufferOffset AssemblerLOONG64::as_stptr_d(Register rd, Register rj,
                                          int32_t si14) {
  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
  spew("stptr_d %3s,%3s,0x%x", rd.name(), rj.name(), si14);
  return writeInst(InstImm(op_stptr_d, si14 >> 2, rj, rd, 14).encode());
}

BufferOffset AssemblerLOONG64::as_preld(int32_t hint, Register rj,
                                        int32_t si12) {
  MOZ_ASSERT(is_intN(si12, 12));
  spew("preld 0x%x,%3s,0x%x", hint, rj.name(), si12);
  return writeInst(InstImm(op_preld, si12, rj, hint).encode());
}

// Atomic instructions
BufferOffset AssemblerLOONG64::as_amswap_w(Register rd, Register rj,
                                           Register rk) {
  spew("amswap_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amswap_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amswap_d(Register rd, Register rj,
                                           Register rk) {
  spew("amswap_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amswap_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amadd_w(Register rd, Register rj,
                                          Register rk) {
  spew("amadd_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amadd_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amadd_d(Register rd, Register rj,
                                          Register rk) {
  spew("amadd_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amadd_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amand_w(Register rd, Register rj,
                                          Register rk) {
  spew("amand_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amand_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amand_d(Register rd, Register rj,
                                          Register rk) {
  spew("amand_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amand_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amor_w(Register rd, Register rj,
                                         Register rk) {
  spew("amor_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amor_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amor_d(Register rd, Register rj,
                                         Register rk) {
  spew("amor_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amor_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amxor_w(Register rd, Register rj,
                                          Register rk) {
  spew("amxor_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amxor_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amxor_d(Register rd, Register rj,
                                          Register rk) {
  spew("amxor_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amxor_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammax_w(Register rd, Register rj,
                                          Register rk) {
  spew("ammax_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammax_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammax_d(Register rd, Register rj,
                                          Register rk) {
  spew("ammax_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammax_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammin_w(Register rd, Register rj,
                                          Register rk) {
  spew("ammin_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammin_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammin_d(Register rd, Register rj,
                                          Register rk) {
  spew("ammin_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammin_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammax_wu(Register rd, Register rj,
                                           Register rk) {
  spew("ammax_wu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammax_wu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammax_du(Register rd, Register rj,
                                           Register rk) {
  spew("ammax_du %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammax_du, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammin_wu(Register rd, Register rj,
                                           Register rk) {
  spew("ammin_wu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammin_wu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammin_du(Register rd, Register rj,
                                           Register rk) {
  spew("ammin_du %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammin_du, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amswap_db_w(Register rd, Register rj,
                                              Register rk) {
  spew("amswap_db_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amswap_db_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amswap_db_d(Register rd, Register rj,
                                              Register rk) {
  spew("amswap_db_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amswap_db_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amadd_db_w(Register rd, Register rj,
                                             Register rk) {
  spew("amadd_db_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amadd_db_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amadd_db_d(Register rd, Register rj,
                                             Register rk) {
  spew("amadd_db_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amadd_db_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amand_db_w(Register rd, Register rj,
                                             Register rk) {
  spew("amand_db_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amand_db_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amand_db_d(Register rd, Register rj,
                                             Register rk) {
  spew("amand_db_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amand_db_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amor_db_w(Register rd, Register rj,
                                            Register rk) {
  spew("amor_db_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amor_db_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amor_db_d(Register rd, Register rj,
                                            Register rk) {
  spew("amor_db_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amor_db_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amxor_db_w(Register rd, Register rj,
                                             Register rk) {
  spew("amxor_db_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amxor_db_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_amxor_db_d(Register rd, Register rj,
                                             Register rk) {
  spew("amxor_db_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_amxor_db_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammax_db_w(Register rd, Register rj,
                                             Register rk) {
  spew("ammax_db_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammax_db_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammax_db_d(Register rd, Register rj,
                                             Register rk) {
  spew("ammax_db_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammax_db_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammin_db_w(Register rd, Register rj,
                                             Register rk) {
  spew("ammin_db_w %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammin_db_w, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammin_db_d(Register rd, Register rj,
                                             Register rk) {
  spew("ammin_db_d %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammin_db_d, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammax_db_wu(Register rd, Register rj,
                                              Register rk) {
  spew("ammax_db_wu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammax_db_wu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammax_db_du(Register rd, Register rj,
                                              Register rk) {
  spew("ammax_db_du %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammax_db_du, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammin_db_wu(Register rd, Register rj,
                                              Register rk) {
  spew("ammin_db_wu %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammin_db_wu, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ammin_db_du(Register rd, Register rj,
                                              Register rk) {
  spew("ammin_db_du %3s,%3s,%3s", rd.name(), rj.name(), rk.name());
  return writeInst(InstReg(op_ammin_db_du, rk, rj, rd).encode());
}

BufferOffset AssemblerLOONG64::as_ll_w(Register rd, Register rj, int32_t si14) {
  spew("ll_w %3s,%3s,0x%x", rd.name(), rj.name(), si14);
  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
  return writeInst(InstImm(op_ll_w, si14 >> 2, rj, rd, 14).encode());
}

BufferOffset AssemblerLOONG64::as_ll_d(Register rd, Register rj, int32_t si14) {
  spew("ll_d %3s,%3s,0x%x", rd.name(), rj.name(), si14);
  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
  return writeInst(InstImm(op_ll_d, si14 >> 2, rj, rd, 14).encode());
}

BufferOffset AssemblerLOONG64::as_sc_w(Register rd, Register rj, int32_t si14) {
  spew("sc_w %3s,%3s,0x%x", rd.name(), rj.name(), si14);
  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
  return writeInst(InstImm(op_sc_w, si14 >> 2, rj, rd, 14).encode());
}

BufferOffset AssemblerLOONG64::as_sc_d(Register rd, Register rj, int32_t si14) {
  spew("sc_d %3s,%3s,0x%x", rd.name(), rj.name(), si14);
  MOZ_ASSERT(is_intN(si14, 16) && ((si14 & 0x3) == 0));
  return writeInst(InstImm(op_sc_d, si14 >> 2, rj, rd, 14).encode());
}

// Barrier instructions
BufferOffset AssemblerLOONG64::as_dbar(int32_t hint) {
  MOZ_ASSERT(is_uintN(hint, 15));
  spew("dbar 0x%x", hint);
  return writeInst(InstImm(op_dbar, hint).encode());
}

BufferOffset AssemblerLOONG64::as_ibar(int32_t hint) {
  MOZ_ASSERT(is_uintN(hint, 15));
  spew("ibar 0x%x", hint);
  return writeInst(InstImm(op_ibar, hint).encode());
}

/* =============================================================== */

// FP Arithmetic instructions
BufferOffset AssemblerLOONG64::as_fadd_s(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fadd_s %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fadd_s, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fadd_d(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fadd_d %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fadd_d, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fsub_s(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fsub_s %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fsub_s, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fsub_d(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fsub_d %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fsub_d, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmul_s(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fmul_s %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fmul_s, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmul_d(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fmul_d %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fmul_d, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fdiv_s(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fdiv_s %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fdiv_s, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fdiv_d(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fdiv_d %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fdiv_d, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmadd_s(FloatRegister fd, FloatRegister fj,
                                          FloatRegister fk, FloatRegister fa) {
  spew("fmadd_s %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
       fa.name());
  return writeInst(InstReg(op_fmadd_s, fa, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmadd_d(FloatRegister fd, FloatRegister fj,
                                          FloatRegister fk, FloatRegister fa) {
  spew("fmadd_d %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
       fa.name());
  return writeInst(InstReg(op_fmadd_d, fa, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmsub_s(FloatRegister fd, FloatRegister fj,
                                          FloatRegister fk, FloatRegister fa) {
  spew("fmsub_s %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
       fa.name());
  return writeInst(InstReg(op_fmsub_s, fa, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmsub_d(FloatRegister fd, FloatRegister fj,
                                          FloatRegister fk, FloatRegister fa) {
  spew("fmsub_d %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
       fa.name());
  return writeInst(InstReg(op_fmsub_d, fa, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fnmadd_s(FloatRegister fd, FloatRegister fj,
                                           FloatRegister fk, FloatRegister fa) {
  spew("fnmadd_s %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
       fa.name());
  return writeInst(InstReg(op_fnmadd_s, fa, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fnmadd_d(FloatRegister fd, FloatRegister fj,
                                           FloatRegister fk, FloatRegister fa) {
  spew("fnmadd_d %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
       fa.name());
  return writeInst(InstReg(op_fnmadd_d, fa, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fnmsub_s(FloatRegister fd, FloatRegister fj,
                                           FloatRegister fk, FloatRegister fa) {
  spew("fnmsub_s %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
       fa.name());
  return writeInst(InstReg(op_fnmsub_s, fa, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fnmsub_d(FloatRegister fd, FloatRegister fj,
                                           FloatRegister fk, FloatRegister fa) {
  spew("fnmsub_d %3s,%3s,%3s,%3s", fd.name(), fj.name(), fk.name(),
       fa.name());
  return writeInst(InstReg(op_fnmsub_d, fa, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmax_s(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fmax_s %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fmax_s, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmax_d(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fmax_d %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fmax_d, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmin_s(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fmin_s %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fmin_s, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmin_d(FloatRegister fd, FloatRegister fj,
                                         FloatRegister fk) {
  spew("fmin_d %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fmin_d, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmaxa_s(FloatRegister fd, FloatRegister fj,
                                          FloatRegister fk) {
  spew("fmaxa_s %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fmaxa_s, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmaxa_d(FloatRegister fd, FloatRegister fj,
                                          FloatRegister fk) {
  spew("fmaxa_d %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fmaxa_d, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmina_s(FloatRegister fd, FloatRegister fj,
                                          FloatRegister fk) {
  spew("fmina_s %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fmina_s, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fmina_d(FloatRegister fd, FloatRegister fj,
                                          FloatRegister fk) {
  spew("fmina_d %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fmina_d, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fabs_s(FloatRegister fd, FloatRegister fj) {
  spew("fabs_s %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_fabs_s, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fabs_d(FloatRegister fd, FloatRegister fj) {
  spew("fabs_d %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_fabs_d, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fneg_s(FloatRegister fd, FloatRegister fj) {
  spew("fneg_s %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_fneg_s, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fneg_d(FloatRegister fd, FloatRegister fj) {
  spew("fneg_d %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_fneg_d, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fsqrt_s(FloatRegister fd, FloatRegister fj) {
  spew("fsqrt_s %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_fsqrt_s, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fsqrt_d(FloatRegister fd, FloatRegister fj) {
  spew("fsqrt_d %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_fsqrt_d, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fcopysign_s(FloatRegister fd,
                                              FloatRegister fj,
                                              FloatRegister fk) {
  spew("fcopysign_s %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fcopysign_s, fk, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fcopysign_d(FloatRegister fd,
                                              FloatRegister fj,
                                              FloatRegister fk) {
  spew("fcopysign_d %3s,%3s,%3s", fd.name(), fj.name(), fk.name());
  return writeInst(InstReg(op_fcopysign_d, fk, fj, fd).encode());
}

// FP compare instructions
// fcmp.cond.s and fcmp.cond.d instructions
BufferOffset AssemblerLOONG64::as_fcmp_cor(FloatFormat fmt, FloatRegister fj,
                                           FloatRegister fk,
                                           FPConditionBit cd) {
  if (fmt == DoubleFloat) {
    spew("fcmp_cor_d FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_d, COR, fk, fj, cd).encode());
  } else {
    spew("fcmp_cor_s FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_s, COR, fk, fj, cd).encode());
  }
}

BufferOffset AssemblerLOONG64::as_fcmp_ceq(FloatFormat fmt, FloatRegister fj,
                                           FloatRegister fk,
                                           FPConditionBit cd) {
  if (fmt == DoubleFloat) {
    spew("fcmp_ceq_d FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_d, CEQ, fk, fj, cd).encode());
  } else {
    spew("fcmp_ceq_s FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_s, CEQ, fk, fj, cd).encode());
  }
}

BufferOffset AssemblerLOONG64::as_fcmp_cne(FloatFormat fmt, FloatRegister fj,
                                           FloatRegister fk,
                                           FPConditionBit cd) {
  if (fmt == DoubleFloat) {
    spew("fcmp_cne_d FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_d, CNE, fk, fj, cd).encode());
  } else {
    spew("fcmp_cne_s FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_s, CNE, fk, fj, cd).encode());
  }
}

BufferOffset AssemblerLOONG64::as_fcmp_cle(FloatFormat fmt, FloatRegister fj,
                                           FloatRegister fk,
                                           FPConditionBit cd) {
  if (fmt == DoubleFloat) {
    spew("fcmp_cle_d FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_d, CLE, fk, fj, cd).encode());
  } else {
    spew("fcmp_cle_s FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_s, CLE, fk, fj, cd).encode());
  }
}

BufferOffset AssemblerLOONG64::as_fcmp_clt(FloatFormat fmt, FloatRegister fj,
                                           FloatRegister fk,
                                           FPConditionBit cd) {
  if (fmt == DoubleFloat) {
    spew("fcmp_clt_d FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_d, CLT, fk, fj, cd).encode());
  } else {
    spew("fcmp_clt_s FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_s, CLT, fk, fj, cd).encode());
  }
}

BufferOffset AssemblerLOONG64::as_fcmp_cun(FloatFormat fmt, FloatRegister fj,
                                           FloatRegister fk,
                                           FPConditionBit cd) {
  if (fmt == DoubleFloat) {
    spew("fcmp_cun_d FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_d, CUN, fk, fj, cd).encode());
  } else {
    spew("fcmp_cun_s FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_s, CUN, fk, fj, cd).encode());
  }
}

BufferOffset AssemblerLOONG64::as_fcmp_cueq(FloatFormat fmt, FloatRegister fj,
                                            FloatRegister fk,
                                            FPConditionBit cd) {
  if (fmt == DoubleFloat) {
    spew("fcmp_cueq_d FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_d, CUEQ, fk, fj, cd).encode());
  } else {
    spew("fcmp_cueq_s FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_s, CUEQ, fk, fj, cd).encode());
  }
}

BufferOffset AssemblerLOONG64::as_fcmp_cune(FloatFormat fmt, FloatRegister fj,
                                            FloatRegister fk,
                                            FPConditionBit cd) {
  if (fmt == DoubleFloat) {
    spew("fcmp_cune_d FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_d, CUNE, fk, fj, cd).encode());
  } else {
    spew("fcmp_cune_s FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_s, CUNE, fk, fj, cd).encode());
  }
}

BufferOffset AssemblerLOONG64::as_fcmp_cule(FloatFormat fmt, FloatRegister fj,
                                            FloatRegister fk,
                                            FPConditionBit cd) {
  if (fmt == DoubleFloat) {
    spew("fcmp_cule_d FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_d, CULE, fk, fj, cd).encode());
  } else {
    spew("fcmp_cule_s FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_s, CULE, fk, fj, cd).encode());
  }
}

BufferOffset AssemblerLOONG64::as_fcmp_cult(FloatFormat fmt, FloatRegister fj,
                                            FloatRegister fk,
                                            FPConditionBit cd) {
  if (fmt == DoubleFloat) {
    spew("fcmp_cult_d FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_d, CULT, fk, fj, cd).encode());
  } else {
    spew("fcmp_cult_s FCC%d,%3s,%3s", cd, fj.name(), fk.name());
    return writeInst(InstReg(op_fcmp_cond_s, CULT, fk, fj, cd).encode());
  }
}

// FP conversion instructions
BufferOffset AssemblerLOONG64::as_fcvt_s_d(FloatRegister fd, FloatRegister fj) {
  spew("fcvt_s_d %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_fcvt_s_d, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_fcvt_d_s(FloatRegister fd, FloatRegister fj) {
  spew("fcvt_d_s %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_fcvt_d_s, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_ffint_s_w(FloatRegister fd,
                                            FloatRegister fj) {
  spew("ffint_s_w %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_ffint_s_w, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_ffint_s_l(FloatRegister fd,
                                            FloatRegister fj) {
  spew("ffint_s_l %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_ffint_s_l, fj, fd).encode());
}

BufferOffset AssemblerLOONG64::as_ffint_d_w(FloatRegister fd,
                                            FloatRegister fj) {
  spew("ffint_d_w %3s,%3s", fd.name(), fj.name());
  return writeInst(InstReg(op_ffint_d_w, fj, fd).encode());
}

--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=98 G=96

¤ Dauer der Verarbeitung: 0.50 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge