Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/js/src/jit/mips64/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 32 kB image not shown  

Quelle  MacroAssembler-mips64-inl.h

  Sprache: C
 

/* 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/. */


#ifndef jit_mips64_MacroAssembler_mips64_inl_h
#define jit_mips64_MacroAssembler_mips64_inl_h

#include "jit/mips64/MacroAssembler-mips64.h"

#include "vm/BigIntType.h"  // JS::BigInt

#include "jit/mips-shared/MacroAssembler-mips-shared-inl.h"

namespace js {
namespace jit {

//{{{ check_macroassembler_style

void MacroAssembler::move64(Register64 src, Register64 dest) {
  movePtr(src.reg, dest.reg);
}

void MacroAssembler::move64(Imm64 imm, Register64 dest) {
  movePtr(ImmWord(imm.value), dest.reg);
}

void MacroAssembler::moveDoubleToGPR64(FloatRegister src, Register64 dest) {
  moveFromDouble(src, dest.reg);
}

void MacroAssembler::moveGPR64ToDouble(Register64 src, FloatRegister dest) {
  moveToDouble(src.reg, dest);
}

void MacroAssembler::move64To32(Register64 src, Register dest) {
  ma_sll(dest, src.reg, Imm32(0));
}

void MacroAssembler::move32To64ZeroExtend(Register src, Register64 dest) {
  ma_dext(dest.reg, src, Imm32(0), Imm32(32));
}

void MacroAssembler::move8To64SignExtend(Register src, Register64 dest) {
  move32To64SignExtend(src, dest);
  move8SignExtend(dest.reg, dest.reg);
}

void MacroAssembler::move16To64SignExtend(Register src, Register64 dest) {
  move32To64SignExtend(src, dest);
  move16SignExtend(dest.reg, dest.reg);
}

void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) {
  ma_sll(dest.reg, src, Imm32(0));
}

void MacroAssembler::move8SignExtendToPtr(Register src, Register dest) {
  move8To64SignExtend(src, Register64(dest));
}

void MacroAssembler::move16SignExtendToPtr(Register src, Register dest) {
  move16To64SignExtend(src, Register64(dest));
}

void MacroAssembler::move32SignExtendToPtr(Register src, Register dest) {
  ma_sll(dest, src, Imm32(0));
}

void MacroAssembler::move32ZeroExtendToPtr(Register src, Register dest) {
  ma_dext(dest, src, Imm32(0), Imm32(32));
}

// ===============================================================
// Load instructions

void MacroAssembler::load32SignExtendToPtr(const Address& src, Register dest) {
  load32(src, dest);
}

// ===============================================================
// Logical instructions

void MacroAssembler::notPtr(Register reg) { ma_not(reg, reg); }

void MacroAssembler::andPtr(Register src, Register dest) { ma_and(dest, src); }

void MacroAssembler::andPtr(Imm32 imm, Register dest) { ma_and(dest, imm); }

void MacroAssembler::andPtr(Imm32 imm, Register src, Register dest) {
  ma_and(dest, src, imm);
}

void MacroAssembler::and64(Imm64 imm, Register64 dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  ma_li(scratch, ImmWord(imm.value));
  ma_and(dest.reg, scratch);
}

void MacroAssembler::and64(Register64 src, Register64 dest) {
  ma_and(dest.reg, src.reg);
}

void MacroAssembler::or64(Imm64 imm, Register64 dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  ma_li(scratch, ImmWord(imm.value));
  ma_or(dest.reg, scratch);
}

void MacroAssembler::xor64(Imm64 imm, Register64 dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  ma_li(scratch, ImmWord(imm.value));
  ma_xor(dest.reg, scratch);
}

void MacroAssembler::orPtr(Register src, Register dest) { ma_or(dest, src); }

void MacroAssembler::orPtr(Imm32 imm, Register dest) { ma_or(dest, imm); }

void MacroAssembler::orPtr(Imm32 imm, Register src, Register dest) {
  ma_or(dest, src, imm);
}

void MacroAssembler::or64(Register64 src, Register64 dest) {
  ma_or(dest.reg, src.reg);
}

void MacroAssembler::xor64(Register64 src, Register64 dest) {
  ma_xor(dest.reg, src.reg);
}

void MacroAssembler::xorPtr(Register src, Register dest) { ma_xor(dest, src); }

void MacroAssembler::xorPtr(Imm32 imm, Register dest) { ma_xor(dest, imm); }

void MacroAssembler::xorPtr(Imm32 imm, Register src, Register dest) {
  ma_xor(dest, src, imm);
}

// ===============================================================
// Swap instructions

void MacroAssembler::byteSwap64(Register64 reg64) {
  Register reg = reg64.reg;
  ma_dsbh(reg, reg);
  ma_dshd(reg, reg);
}

// ===============================================================
// Arithmetic functions

void MacroAssembler::addPtr(Register src, Register dest) {
  ma_daddu(dest, src);
}

void MacroAssembler::addPtr(Imm32 imm, Register dest) { ma_daddu(dest, imm); }

void MacroAssembler::addPtr(ImmWord imm, Register dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  movePtr(imm, scratch);
  addPtr(scratch, dest);
}

void MacroAssembler::add64(Register64 src, Register64 dest) {
  addPtr(src.reg, dest.reg);
}

void MacroAssembler::add64(Imm32 imm, Register64 dest) {
  ma_daddu(dest.reg, imm);
}

void MacroAssembler::add64(Imm64 imm, Register64 dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  mov(ImmWord(imm.value), scratch);
  ma_daddu(dest.reg, scratch);
}

CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) {
  CodeOffset offset = CodeOffset(currentOffset());
  ma_liPatchable(dest, Imm32(0));
  as_dsubu(dest, StackPointer, dest);
  return offset;
}

void MacroAssembler::patchSub32FromStackPtr(CodeOffset offset, Imm32 imm) {
  Instruction* lui =
      (Instruction*)m_buffer.getInst(BufferOffset(offset.offset()));
  Instruction* ori =
      (Instruction*)m_buffer.getInst(BufferOffset(offset.offset() + 4));

  MOZ_ASSERT(lui->extractOpcode() == ((uint32_t)op_lui >> OpcodeShift));
  MOZ_ASSERT(ori->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));

  MacroAssemblerMIPSShared::UpdateLuiOriValue(lui, ori, imm.value);
}

void MacroAssembler::subPtr(Register src, Register dest) {
  as_dsubu(dest, dest, src);
}

void MacroAssembler::subPtr(Imm32 imm, Register dest) {
  ma_dsubu(dest, dest, imm);
}

void MacroAssembler::sub64(Register64 src, Register64 dest) {
  as_dsubu(dest.reg, dest.reg, src.reg);
}

void MacroAssembler::sub64(Imm64 imm, Register64 dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  mov(ImmWord(imm.value), scratch);
  as_dsubu(dest.reg, dest.reg, scratch);
}

void MacroAssembler::mulHighUnsigned32(Imm32 imm, Register src, Register dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  MOZ_ASSERT(src != scratch);
  move32(imm, scratch);
#ifdef MIPSR6
  as_muhu(dest, src, scratch);
#else
  as_multu(src, scratch);
  as_mfhi(dest);
#endif
}

void MacroAssembler::mulPtr(Register rhs, Register srcDest) {
#ifdef MIPSR6
  as_dmulu(srcDest, srcDest, rhs);
#else
  as_dmultu(srcDest, rhs);
  as_mflo(srcDest);
#endif
}

void MacroAssembler::mulPtr(ImmWord rhs, Register srcDest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  MOZ_ASSERT(srcDest != scratch);
  mov(rhs, scratch);
  mulPtr(scratch, srcDest);
}

void MacroAssembler::mul64(const Register64& rhs, const Register64& srcDest) {
  mul64(rhs, srcDest, InvalidReg);
}

void MacroAssembler::mul64(Imm64 imm, const Register64& dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  mov(ImmWord(imm.value), scratch);
#ifdef MIPSR6
  as_dmulu(dest.reg, scratch, dest.reg);
#else
  as_dmultu(dest.reg, scratch);
  as_mflo(dest.reg);
#endif
}

void MacroAssembler::mul64(Imm64 imm, const Register64& dest,
                           const Register temp) {
  MOZ_ASSERT(temp == InvalidReg);
  mul64(imm, dest);
}

void MacroAssembler::mul64(const Register64& src, const Register64& dest,
                           const Register temp) {
  MOZ_ASSERT(temp == InvalidReg);
#ifdef MIPSR6
  as_dmulu(dest.reg, src.reg, dest.reg);
#else
  as_dmultu(dest.reg, src.reg);
  as_mflo(dest.reg);
#endif
}

void MacroAssembler::mulBy3(Register src, Register dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  MOZ_ASSERT(src != scratch);
  as_daddu(scratch, src, src);
  as_daddu(dest, scratch, src);
}

void MacroAssembler::inc64(AbsoluteAddress dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  Register scratch2 = temps.Acquire();
  ma_li(scratch, ImmWord(uintptr_t(dest.addr)));
  as_ld(scratch2, scratch, 0);
  as_daddiu(scratch2, scratch2, 1);
  as_sd(scratch2, scratch, 0);
}

void MacroAssembler::quotient64(Register lhs, Register rhs, Register dest,
                                bool isUnsigned) {
#ifdef MIPSR6
  if (isUnsigned) {
    as_ddivu(dest, lhs, rhs);
  } else {
    as_ddiv(dest, lhs, rhs);
  }
#else
  if (isUnsigned) {
    as_ddivu(lhs, rhs);
  } else {
    as_ddiv(lhs, rhs);
  }
  as_mflo(dest);
#endif
}

void MacroAssembler::remainder64(Register lhs, Register rhs, Register dest,
                                 bool isUnsigned) {
#ifdef MIPSR6
  if (isUnsigned) {
    as_dmodu(dest, lhs, rhs);
  } else {
    as_dmod(dest, lhs, rhs);
  }
#else
  if (isUnsigned) {
    as_ddivu(lhs, rhs);
  } else {
    as_ddiv(lhs, rhs);
  }
  as_mfhi(dest);
#endif
}

void MacroAssembler::neg64(Register64 reg) { as_dsubu(reg.reg, zero, reg.reg); }

void MacroAssembler::negPtr(Register reg) { as_dsubu(reg, zero, reg); }

// ===============================================================
// Shift functions

void MacroAssembler::lshiftPtr(Imm32 imm, Register dest) {
  lshiftPtr(imm, dest, dest);
}

void MacroAssembler::lshiftPtr(Imm32 imm, Register src, Register dest) {
  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
  ma_dsll(dest, src, imm);
}

void MacroAssembler::lshiftPtr(Register shift, Register dest) {
  ma_dsll(dest, dest, shift);
}

void MacroAssembler::lshift64(Imm32 imm, Register64 dest) {
  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
  ma_dsll(dest.reg, dest.reg, imm);
}

void MacroAssembler::lshift64(Register shift, Register64 dest) {
  ma_dsll(dest.reg, dest.reg, shift);
}

void MacroAssembler::rshiftPtr(Imm32 imm, Register dest) {
  rshiftPtr(imm, dest, dest);
}

void MacroAssembler::rshiftPtr(Imm32 imm, Register src, Register dest) {
  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
  ma_dsrl(dest, src, imm);
}

void MacroAssembler::rshiftPtr(Register shift, Register dest) {
  ma_dsrl(dest, dest, shift);
}

void MacroAssembler::rshift64(Imm32 imm, Register64 dest) {
  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
  ma_dsrl(dest.reg, dest.reg, imm);
}

void MacroAssembler::rshift64(Register shift, Register64 dest) {
  ma_dsrl(dest.reg, dest.reg, shift);
}

void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest) {
  rshiftPtrArithmetic(imm, dest, dest);
}

void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register src,
                                         Register dest) {
  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
  ma_dsra(dest, src, imm);
}

void MacroAssembler::rshiftPtrArithmetic(Register shift, Register dest) {
  ma_dsra(dest, dest, shift);
}

void MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest) {
  MOZ_ASSERT(0 <= imm.value && imm.value < 64);
  ma_dsra(dest.reg, dest.reg, imm);
}

void MacroAssembler::rshift64Arithmetic(Register shift, Register64 dest) {
  ma_dsra(dest.reg, dest.reg, shift);
}

// ===============================================================
// Rotation functions

void MacroAssembler::rotateLeft64(Imm32 count, Register64 src, Register64 dest,
                                  Register temp) {
  MOZ_ASSERT(temp == InvalidReg);

  if (count.value) {
    ma_drol(dest.reg, src.reg, count);
  } else {
    ma_move(dest.reg, src.reg);
  }
}

void MacroAssembler::rotateLeft64(Register count, Register64 src,
                                  Register64 dest, Register temp) {
  MOZ_ASSERT(temp == InvalidReg);
  ma_drol(dest.reg, src.reg, count);
}

void MacroAssembler::rotateRight64(Imm32 count, Register64 src, Register64 dest,
                                   Register temp) {
  MOZ_ASSERT(temp == InvalidReg);

  if (count.value) {
    ma_dror(dest.reg, src.reg, count);
  } else {
    ma_move(dest.reg, src.reg);
  }
}

void MacroAssembler::rotateRight64(Register count, Register64 src,
                                   Register64 dest, Register temp) {
  MOZ_ASSERT(temp == InvalidReg);
  ma_dror(dest.reg, src.reg, count);
}

// ===============================================================
// Condition functions

template <typename T1, typename T2>
void MacroAssembler::cmpPtrSet(Condition cond, T1 lhs, T2 rhs, Register dest) {
  ma_cmp_set(dest, lhs, rhs, cond);
}

// Also see below for specializations of cmpPtrSet.

template <typename T1, typename T2>
void MacroAssembler::cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest) {
  ma_cmp_set(dest, lhs, rhs, cond);
}

void MacroAssembler::cmp64Set(Condition cond, Register64 lhs, Register64 rhs,
                              Register dest) {
  ma_cmp_set(dest, lhs.reg, rhs.reg, cond);
}

void MacroAssembler::cmp64Set(Condition cond, Register64 lhs, Imm64 rhs,
                              Register dest) {
  ma_cmp_set(dest, lhs.reg, ImmWord(uint64_t(rhs.value)), cond);
}

void MacroAssembler::cmp64Set(Condition cond, Address lhs, Register64 rhs,
                              Register dest) {
  ma_cmp_set(dest, lhs, rhs.reg, cond);
}

void MacroAssembler::cmp64Set(Condition cond, Address lhs, Imm64 rhs,
                              Register dest) {
  ma_cmp_set(dest, lhs, ImmWord(uint64_t(rhs.value)), cond);
}

// ===============================================================
// Bit counting functions

void MacroAssembler::clz64(Register64 src, Register64 dest) {
  as_dclz(dest.reg, src.reg);
}

void MacroAssembler::ctz64(Register64 src, Register64 dest) {
  ma_dctz(dest.reg, src.reg);
}

void MacroAssembler::popcnt64(Register64 input, Register64 output,
                              Register tmp) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  ma_move(output.reg, input.reg);
  ma_dsra(tmp, input.reg, Imm32(1));
  ma_li(scratch, ImmWord(0x5555555555555555UL));
  ma_and(tmp, scratch);
  ma_dsubu(output.reg, tmp);
  ma_dsra(tmp, output.reg, Imm32(2));
  ma_li(scratch, ImmWord(0x3333333333333333UL));
  ma_and(output.reg, scratch);
  ma_and(tmp, scratch);
  ma_daddu(output.reg, tmp);
  ma_dsrl(tmp, output.reg, Imm32(4));
  ma_daddu(output.reg, tmp);
  ma_li(scratch, ImmWord(0xF0F0F0F0F0F0F0FUL));
  ma_and(output.reg, scratch);
  ma_dsll(tmp, output.reg, Imm32(8));
  ma_daddu(output.reg, tmp);
  ma_dsll(tmp, output.reg, Imm32(16));
  ma_daddu(output.reg, tmp);
  ma_dsll(tmp, output.reg, Imm32(32));
  ma_daddu(output.reg, tmp);
  ma_dsra(output.reg, output.reg, Imm32(56));
}

// ===============================================================
// Branch functions

void MacroAssembler::branch64(Condition cond, Register64 lhs, Imm64 val,
                              Label* success, Label* fail) {
  MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal ||
                 cond == Assembler::LessThan ||
                 cond == Assembler::LessThanOrEqual ||
                 cond == Assembler::GreaterThan ||
                 cond == Assembler::GreaterThanOrEqual ||
                 cond == Assembler::Below || cond == Assembler::BelowOrEqual ||
                 cond == Assembler::Above || cond == Assembler::AboveOrEqual,
             "other condition codes not supported");

  branchPtr(cond, lhs.reg, ImmWord(val.value), success);
  if (fail) {
    jump(fail);
  }
}

void MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs,
                              Label* success, Label* fail) {
  MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal ||
                 cond == Assembler::LessThan ||
                 cond == Assembler::LessThanOrEqual ||
                 cond == Assembler::GreaterThan ||
                 cond == Assembler::GreaterThanOrEqual ||
                 cond == Assembler::Below || cond == Assembler::BelowOrEqual ||
                 cond == Assembler::Above || cond == Assembler::AboveOrEqual,
             "other condition codes not supported");

  branchPtr(cond, lhs.reg, rhs.reg, success);
  if (fail) {
    jump(fail);
  }
}

void MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val,
                              Label* success, Label* fail) {
  MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal ||
                 cond == Assembler::LessThan ||
                 cond == Assembler::LessThanOrEqual ||
                 cond == Assembler::GreaterThan ||
                 cond == Assembler::GreaterThanOrEqual ||
                 cond == Assembler::Below || cond == Assembler::BelowOrEqual ||
                 cond == Assembler::Above || cond == Assembler::AboveOrEqual,
             "other condition codes not supported");

  branchPtr(cond, lhs, ImmWord(val.value), success);
  if (fail) {
    jump(fail);
  }
}

void MacroAssembler::branch64(Condition cond, const Address& lhs,
                              Register64 rhs, Label* success, Label* fail) {
  MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal ||
                 cond == Assembler::LessThan ||
                 cond == Assembler::LessThanOrEqual ||
                 cond == Assembler::GreaterThan ||
                 cond == Assembler::GreaterThanOrEqual ||
                 cond == Assembler::Below || cond == Assembler::BelowOrEqual ||
                 cond == Assembler::Above || cond == Assembler::AboveOrEqual,
             "other condition codes not supported");

  branchPtr(cond, lhs, rhs.reg, success);
  if (fail) {
    jump(fail);
  }
}

void MacroAssembler::branch64(Condition cond, const Address& lhs,
                              const Address& rhs, Register scratch,
                              Label* label) {
  MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal,
             "other condition codes not supported");
  MOZ_ASSERT(lhs.base != scratch);
  MOZ_ASSERT(rhs.base != scratch);

  loadPtr(rhs, scratch);
  branchPtr(cond, lhs, scratch, label);
}

void MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs,
                                      Register rhs, Label* label) {
  branchPtr(cond, lhs, rhs, label);
}

void MacroAssembler::branchTest64(Condition cond, Register64 lhs,
                                  Register64 rhs, Register temp, Label* success,
                                  Label* fail) {
  branchTestPtr(cond, lhs.reg, rhs.reg, success);
  if (fail) {
    jump(fail);
  }
}

void MacroAssembler::branchTest64(Condition cond, Register64 lhs, Imm64 rhs,
                                  Label* success, Label* fail) {
  branchTestPtr(cond, lhs.reg, ImmWord(rhs.value), success);
  if (fail) {
    jump(fail);
  }
}

void MacroAssembler::branchTestUndefined(Condition cond,
                                         const ValueOperand& value,
                                         Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestUndefined(cond, scratch2, label);
}

void MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value,
                                     Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestInt32(cond, scratch2, label);
}

void MacroAssembler::branchTestInt32Truthy(bool b, const ValueOperand& value,
                                           Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  ma_dext(scratch, value.valueReg(), Imm32(0), Imm32(32));
  ma_b(scratch, scratch, label, b ? NonZero : Zero);
}

void MacroAssembler::branchTestDouble(Condition cond, Register tag,
                                      Label* label) {
  MOZ_ASSERT(cond == Equal || cond == NotEqual);
  Condition actual = (cond == Equal) ? BelowOrEqual : Above;
  ma_b(tag, ImmTag(JSVAL_TAG_MAX_DOUBLE), label, actual);
}

void MacroAssembler::branchTestDouble(Condition cond, const ValueOperand& value,
                                      Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestDouble(cond, scratch2, label);
}

void MacroAssembler::branchTestNumber(Condition cond, const ValueOperand& value,
                                      Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestNumber(cond, scratch2, label);
}

void MacroAssembler::branchTestBoolean(Condition cond,
                                       const ValueOperand& value,
                                       Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestBoolean(cond, scratch2, label);
}

void MacroAssembler::branchTestBooleanTruthy(bool b, const ValueOperand& value,
                                             Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  unboxBoolean(value, scratch2);
  ma_b(scratch2, scratch2, label, b ? NonZero : Zero);
}

void MacroAssembler::branchTestString(Condition cond, const ValueOperand& value,
                                      Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestString(cond, scratch2, label);
}

void MacroAssembler::branchTestStringTruthy(bool b, const ValueOperand& value,
                                            Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  unboxString(value, scratch2);
  load32(Address(scratch2, JSString::offsetOfLength()), scratch2);
  ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal);
}

void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value,
                                      Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestSymbol(cond, scratch2, label);
}

void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address,
                                      Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  computeEffectiveAddress(address, scratch2);
  splitTag(scratch2, scratch2);
  branchTestBigInt(cond, scratch2, label);
}

void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value,
                                      Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestBigInt(cond, scratch2, label);
}

void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value,
                                            Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  unboxBigInt(value, scratch2);
  load32(Address(scratch2, BigInt::offsetOfDigitLength()), scratch2);
  ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal);
}

void MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value,
                                    Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestNull(cond, scratch2, label);
}

void MacroAssembler::branchTestObject(Condition cond, const ValueOperand& value,
                                      Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestObject(cond, scratch2, label);
}

void MacroAssembler::branchTestPrimitive(Condition cond,
                                         const ValueOperand& value,
                                         Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  branchTestPrimitive(cond, scratch2, label);
}

void MacroAssembler::branchTestMagic(Condition cond, const ValueOperand& value,
                                     Label* label) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  splitTag(value, scratch2);
  ma_b(scratch2, ImmTag(JSVAL_TAG_MAGIC), label, cond);
}

void MacroAssembler::branchTestMagic(Condition cond, const Address& valaddr,
                                     JSWhyMagic why, Label* label) {
  uint64_t magic = MagicValue(why).asRawBits();
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  loadPtr(valaddr, scratch);
  ma_b(scratch, ImmWord(magic), label, cond);
}

void MacroAssembler::branchTestMagic(Condition cond, const BaseIndex& valaddr,
                                     JSWhyMagic why, Label* label) {
  uint64_t magic = MagicValue(why).asRawBits();
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  loadPtr(valaddr, scratch);
  ma_b(scratch, ImmWord(magic), label, cond);
}

template <typename T>
void MacroAssembler::branchTestValue(Condition cond, const T& lhs,
                                     const ValueOperand& rhs, Label* label) {
  MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
  branchPtr(cond, lhs, rhs.valueReg(), label);
}

void MacroAssembler::branchTruncateDoubleMaybeModUint32(FloatRegister src,
                                                        Register dest,
                                                        Label* fail) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  as_truncld(ScratchDoubleReg, src);
  as_cfc1(scratch, Assembler::FCSR);
  moveFromDouble(ScratchDoubleReg, dest);
  ma_ext(scratch, scratch, Assembler::CauseV, 1);
  ma_b(scratch, Imm32(0), fail, Assembler::NotEqual);

  as_sll(dest, dest, 0);
}

void MacroAssembler::branchTruncateFloat32MaybeModUint32(FloatRegister src,
                                                         Register dest,
                                                         Label* fail) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  as_truncls(ScratchDoubleReg, src);
  as_cfc1(scratch, Assembler::FCSR);
  moveFromDouble(ScratchDoubleReg, dest);
  ma_ext(scratch, scratch, Assembler::CauseV, 1);
  ma_b(scratch, Imm32(0), fail, Assembler::NotEqual);

  as_sll(dest, dest, 0);
}

void MacroAssembler::branchTruncateDoubleToInt32(FloatRegister src,
                                                 Register dest, Label* fail) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  ScratchDoubleScope fpscratch(asMasm());

  // Convert scalar to signed 64-bit fixed-point, rounding toward zero.
  // In the case of -0, the output is zero.
  // In the case of overflow, the output is:
  //   - MIPS64R2: 2^63-1
  //   - MIPS64R6: saturated
  // In the case of NaN, the output is:
  //   - MIPS64R2: 2^63-1
  //   - MIPS64R6: 0
  as_truncld(fpscratch, src);
  moveFromDouble(fpscratch, dest);

  // Fail on overflow cases, besides MIPS64R2 will also fail here on NaN cases.
  as_sll(scratch, dest, 0);
  ma_b(dest, scratch, fail, Assembler::NotEqual);
}

void MacroAssembler::branchInt64NotInPtrRange(Register64 src, Label* label) {
  // No-op on 64-bit platforms.
}

void MacroAssembler::branchUInt64NotInPtrRange(Register64 src, Label* label) {
  branchTest64(Assembler::Signed, src, src, label);
}

void MacroAssembler::fallibleUnboxPtr(const ValueOperand& src, Register dest,
                                      JSValueType type, Label* fail) {
  MOZ_ASSERT(type == JSVAL_TYPE_OBJECT || type == JSVAL_TYPE_STRING ||
             type == JSVAL_TYPE_SYMBOL || type == JSVAL_TYPE_BIGINT);
  // dest := src XOR mask
  // scratch := dest >> JSVAL_TAG_SHIFT
  // fail if scratch != 0
  //
  // Note: src and dest can be the same register
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  mov(ImmShiftedTag(type), scratch);
  ma_xor(scratch, src.valueReg());
  ma_move(dest, scratch);
  ma_dsrl(scratch, scratch, Imm32(JSVAL_TAG_SHIFT));
  ma_b(scratch, Imm32(0), fail, Assembler::NotEqual);
}

void MacroAssembler::fallibleUnboxPtr(const Address& src, Register dest,
                                      JSValueType type, Label* fail) {
  loadValue(src, ValueOperand(dest));
  fallibleUnboxPtr(ValueOperand(dest), dest, type, fail);
}

void MacroAssembler::fallibleUnboxPtr(const BaseIndex& src, Register dest,
                                      JSValueType type, Label* fail) {
  loadValue(src, ValueOperand(dest));
  fallibleUnboxPtr(ValueOperand(dest), dest, type, fail);
}

// ===============================================================
// 128-bit arithmetic

void MacroAssembler::wasmAddSubI128HI64(Register lhsLo, Register lhsHi,
                                        Register rhsLo, Register rhsHi,
                                        Register output, bool isAdd) {
  // Require: the output is not the same as any of the inputs.
  MOZ_RELEASE_ASSERT(output != lhsLo && output != lhsHi && output != rhsLo &&
                     output != rhsHi);
  // We use `output` as a temp to hold the carry or borrow.
  if (isAdd) {
    as_daddu(output, lhsLo, rhsLo);   // output = lhsLo + rhsLo
    as_sltu(output, output, lhsLo);   // output = carry from `lhsLo + rhsLo`
    as_daddu(output, output, lhsHi);  // output = carry + lhsHi
    as_daddu(output, output, rhsHi);  // output = carry + lhsHi + rhsHi
  } else {
    as_sltu(output, lhsLo, rhsLo);    // output = borrow from `lhsLo - rhsLo`
    as_dsubu(output, lhsHi, output);  // output = lhsHi - borrow
    as_dsubu(output, output, rhsHi);  // output = lhsHi - borrow - rhsHi
  }
}

void MacroAssembler::wasmMulI64WideHI64(Register lhs, Register rhs,
                                        Register output, bool isSigned) {
  if (isSigned) {
#ifdef MIPSR6
    as_dmuh(output, lhs, rhs);
#else
    as_dmult(lhs, rhs);
    as_mfhi(output);
#endif
  } else {
#ifdef MIPSR6
    as_dmuhu(output, lhs, rhs);
#else
    as_dmultu(lhs, rhs);
    as_mfhi(output);
#endif
  }
}

//}}} check_macroassembler_style
// ===============================================================

// The specializations for cmpPtrSet are outside the braces because
// check_macroassembler_style can't yet deal with specializations.

template <>
inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs,
                                      ImmPtr rhs, Register dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch2 = temps.Acquire();
  loadPtr(lhs, scratch2);
  cmpPtrSet(cond, scratch2, rhs, dest);
}

template <>
inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Register lhs,
                                      Address rhs, Register dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  loadPtr(rhs, scratch);
  cmpPtrSet(cond, lhs, scratch, dest);
}

template <>
inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs,
                                      Register rhs, Register dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  loadPtr(lhs, scratch);
  cmpPtrSet(cond, scratch, rhs, dest);
}

template <>
inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Register lhs,
                                     Address rhs, Register dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  load32(rhs, scratch);
  cmp32Set(cond, lhs, scratch, dest);
}

template <>
inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Address lhs,
                                     Register rhs, Register dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  load32(lhs, scratch);
  cmp32Set(cond, scratch, rhs, dest);
}

void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, Register rhs,
                                   Register src, Register dest) {
  UseScratchRegisterScope temps(*this);
  Register scratch = temps.Acquire();
  MOZ_ASSERT(src != scratch && dest != scratch);
  cmpPtrSet(cond, lhs, rhs, scratch);
#ifdef MIPSR6
  as_selnez(src, src, scratch);
  as_seleqz(dest, dest, scratch);
  as_or(dest, dest, src);
#else
  as_movn(dest, src, scratch);
#endif
}

void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs,
                                   const Address& rhs, Register src,
                                   Register dest) {
  MOZ_CRASH("NYI");
}

void MacroAssemblerMIPS64Compat::incrementInt32Value(const Address& addr) {
  asMasm().add32(Imm32(1), addr);
}

void MacroAssemblerMIPS64Compat::retn(Imm32 n) {
  // pc <- [sp]; sp += n
  loadPtr(Address(StackPointer, 0), ra);
  asMasm().addPtr(n, StackPointer);
  as_jr(ra);
  as_nop();
}

}  // namespace jit
}  // namespace js

#endif /* jit_mips64_MacroAssembler_mips64_inl_h */

Messung V0.5 in Prozent
C=95 H=100 G=97

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet am  2026-08-26) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

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.