diff options
Diffstat (limited to 'js/src/jit/mips64/MacroAssembler-mips64-inl.h')
-rw-r--r-- | js/src/jit/mips64/MacroAssembler-mips64-inl.h | 774 |
1 files changed, 774 insertions, 0 deletions
diff --git a/js/src/jit/mips64/MacroAssembler-mips64-inl.h b/js/src/jit/mips64/MacroAssembler-mips64-inl.h new file mode 100644 index 000000000..f5737748b --- /dev/null +++ b/js/src/jit/mips64/MacroAssembler-mips64-inl.h @@ -0,0 +1,774 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * 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 "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); +} + +// =============================================================== +// Logical instructions + +void +MacroAssembler::andPtr(Register src, Register dest) +{ + ma_and(dest, src); +} + +void +MacroAssembler::andPtr(Imm32 imm, Register dest) +{ + ma_and(dest, imm); +} + +void +MacroAssembler::and64(Imm64 imm, Register64 dest) +{ + ma_li(ScratchRegister, ImmWord(imm.value)); + ma_and(dest.reg, ScratchRegister); +} + +void +MacroAssembler::and64(Register64 src, Register64 dest) +{ + ma_and(dest.reg, src.reg); +} + +void +MacroAssembler::and64(const Operand& src, Register64 dest) +{ + if (src.getTag() == Operand::MEM) { + Register64 scratch(ScratchRegister); + + load64(src.toAddress(), scratch); + and64(scratch, dest); + } else { + and64(Register64(src.toReg()), dest); + } +} + +void +MacroAssembler::or64(Imm64 imm, Register64 dest) +{ + ma_li(ScratchRegister, ImmWord(imm.value)); + ma_or(dest.reg, ScratchRegister); +} + +void +MacroAssembler::xor64(Imm64 imm, Register64 dest) +{ + ma_li(ScratchRegister, ImmWord(imm.value)); + ma_xor(dest.reg, ScratchRegister); +} + +void +MacroAssembler::orPtr(Register src, Register dest) +{ + ma_or(dest, src); +} + +void +MacroAssembler::orPtr(Imm32 imm, Register dest) +{ + ma_or(dest, imm); +} + +void +MacroAssembler::or64(Register64 src, Register64 dest) +{ + ma_or(dest.reg, src.reg); +} + +void +MacroAssembler::or64(const Operand& src, Register64 dest) +{ + if (src.getTag() == Operand::MEM) { + Register64 scratch(ScratchRegister); + + load64(src.toAddress(), scratch); + or64(scratch, dest); + } else { + or64(Register64(src.toReg()), dest); + } +} + +void +MacroAssembler::xor64(Register64 src, Register64 dest) +{ + ma_xor(dest.reg, src.reg); +} + +void +MacroAssembler::xor64(const Operand& src, Register64 dest) +{ + if (src.getTag() == Operand::MEM) { + Register64 scratch(ScratchRegister); + + load64(src.toAddress(), scratch); + xor64(scratch, dest); + } else { + xor64(Register64(src.toReg()), dest); + } +} + +void +MacroAssembler::xorPtr(Register src, Register dest) +{ + ma_xor(dest, src); +} + +void +MacroAssembler::xorPtr(Imm32 imm, Register dest) +{ + ma_xor(dest, imm); +} + +// =============================================================== +// 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) +{ + movePtr(imm, ScratchRegister); + addPtr(ScratchRegister, dest); +} + +void +MacroAssembler::add64(Register64 src, Register64 dest) +{ + addPtr(src.reg, dest.reg); +} + +void +MacroAssembler::add64(const Operand& src, Register64 dest) +{ + if (src.getTag() == Operand::MEM) { + Register64 scratch(ScratchRegister); + + load64(src.toAddress(), scratch); + add64(scratch, dest); + } else { + add64(Register64(src.toReg()), dest); + } +} + +void +MacroAssembler::add64(Imm32 imm, Register64 dest) +{ + ma_daddu(dest.reg, imm); +} + +void +MacroAssembler::add64(Imm64 imm, Register64 dest) +{ + MOZ_ASSERT(dest.reg != ScratchRegister); + mov(ImmWord(imm.value), ScratchRegister); + ma_daddu(dest.reg, ScratchRegister); +} + +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(const Operand& src, Register64 dest) +{ + if (src.getTag() == Operand::MEM) { + Register64 scratch(ScratchRegister); + + load64(src.toAddress(), scratch); + sub64(scratch, dest); + } else { + sub64(Register64(src.toReg()), dest); + } +} + +void +MacroAssembler::sub64(Imm64 imm, Register64 dest) +{ + MOZ_ASSERT(dest.reg != ScratchRegister); + mov(ImmWord(imm.value), ScratchRegister); + as_dsubu(dest.reg, dest.reg, ScratchRegister); +} + +void +MacroAssembler::mul64(Imm64 imm, const Register64& dest) +{ + MOZ_ASSERT(dest.reg != ScratchRegister); + mov(ImmWord(imm.value), ScratchRegister); + as_dmultu(dest.reg, ScratchRegister); + as_mflo(dest.reg); +} + +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); + as_dmultu(dest.reg, src.reg); + as_mflo(dest.reg); +} + +void +MacroAssembler::mul64(const Operand& src, const Register64& dest, const Register temp) +{ + if (src.getTag() == Operand::MEM) { + Register64 scratch(ScratchRegister); + + load64(src.toAddress(), scratch); + mul64(scratch, dest, temp); + } else { + mul64(Register64(src.toReg()), dest, temp); + } +} + +void +MacroAssembler::mulBy3(Register src, Register dest) +{ + as_daddu(dest, src, src); + as_daddu(dest, dest, src); +} + +void +MacroAssembler::inc64(AbsoluteAddress dest) +{ + ma_li(ScratchRegister, ImmWord(uintptr_t(dest.addr))); + as_ld(SecondScratchReg, ScratchRegister, 0); + as_daddiu(SecondScratchReg, SecondScratchReg, 1); + as_sd(SecondScratchReg, ScratchRegister, 0); +} + +void +MacroAssembler::neg64(Register64 reg) +{ + as_dsubu(reg.reg, zero, reg.reg); +} + +// =============================================================== +// Shift functions + +void +MacroAssembler::lshiftPtr(Imm32 imm, Register dest) +{ + MOZ_ASSERT(0 <= imm.value && imm.value < 64); + ma_dsll(dest, dest, imm); +} + +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) +{ + MOZ_ASSERT(0 <= imm.value && imm.value < 64); + ma_dsrl(dest, dest, imm); +} + +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) +{ + MOZ_ASSERT(0 <= imm.value && imm.value < 64); + ma_dsra(dest, dest, imm); +} + +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); +} + +// =============================================================== +// Bit counting functions + +void +MacroAssembler::clz64(Register64 src, Register dest) +{ + as_dclz(dest, src.reg); +} + +void +MacroAssembler::ctz64(Register64 src, Register dest) +{ + ma_dctz(dest, src.reg); +} + +void +MacroAssembler::popcnt64(Register64 input, Register64 output, Register tmp) +{ + ma_move(output.reg, input.reg); + ma_dsra(tmp, input.reg, Imm32(1)); + ma_li(ScratchRegister, ImmWord(0x5555555555555555UL)); + ma_and(tmp, ScratchRegister); + ma_dsubu(output.reg, tmp); + ma_dsra(tmp, output.reg, Imm32(2)); + ma_li(ScratchRegister, ImmWord(0x3333333333333333UL)); + ma_and(output.reg, ScratchRegister); + ma_and(tmp, ScratchRegister); + ma_daddu(output.reg, tmp); + ma_dsrl(tmp, output.reg, Imm32(4)); + ma_daddu(output.reg, tmp); + ma_li(ScratchRegister, ImmWord(0xF0F0F0F0F0F0F0FUL)); + ma_and(output.reg, ScratchRegister); + 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* label) +{ + MOZ_ASSERT(cond == Assembler::NotEqual, + "other condition codes not supported"); + + branchPtr(cond, lhs, ImmWord(val.value), label); +} + +void +MacroAssembler::branch64(Condition cond, const Address& lhs, const Address& rhs, Register scratch, + Label* label) +{ + MOZ_ASSERT(cond == Assembler::NotEqual, + "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) +{ + if (rhs != ScratchRegister) + movePtr(rhs, ScratchRegister); + // Instead of unboxing lhs, box rhs and do direct comparison with lhs. + rshiftPtr(Imm32(1), ScratchRegister); + branchPtr(cond, lhs, ScratchRegister, label); +} + +template <class L> +void +MacroAssembler::branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, + L label) +{ + branchTestPtr(cond, lhs.reg, rhs.reg, label); +} + +void +MacroAssembler::branchTestUndefined(Condition cond, const ValueOperand& value, Label* label) +{ + SecondScratchRegisterScope scratch2(*this); + splitTag(value, scratch2); + branchTestUndefined(cond, scratch2, label); +} + +void +MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value, Label* label) +{ + SecondScratchRegisterScope scratch2(*this); + splitTag(value, scratch2); + branchTestInt32(cond, scratch2, label); +} + +void +MacroAssembler::branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label) +{ + ScratchRegisterScope scratch(*this); + 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) +{ + SecondScratchRegisterScope scratch2(*this); + splitTag(value, scratch2); + branchTestDouble(cond, scratch2, label); +} + +void +MacroAssembler::branchTestNumber(Condition cond, const ValueOperand& value, Label* label) +{ + SecondScratchRegisterScope scratch2(*this); + splitTag(value, scratch2); + branchTestNumber(cond, scratch2, label); +} + +void +MacroAssembler::branchTestBoolean(Condition cond, const ValueOperand& value, Label* label) +{ + SecondScratchRegisterScope scratch2(*this); + splitTag(value, scratch2); + branchTestBoolean(cond, scratch2, label); +} + +void +MacroAssembler::branchTestBooleanTruthy(bool b, const ValueOperand& value, Label* label) +{ + SecondScratchRegisterScope scratch2(*this); + unboxBoolean(value, scratch2); + ma_b(scratch2, scratch2, label, b ? NonZero : Zero); +} + +void +MacroAssembler::branchTestString(Condition cond, const ValueOperand& value, Label* label) +{ + SecondScratchRegisterScope scratch2(*this); + splitTag(value, scratch2); + branchTestString(cond, scratch2, label); +} + +void +MacroAssembler::branchTestStringTruthy(bool b, const ValueOperand& value, Label* label) +{ + SecondScratchRegisterScope scratch2(*this); + 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) +{ + SecondScratchRegisterScope scratch2(*this); + splitTag(value, scratch2); + branchTestSymbol(cond, scratch2, label); +} + +void +MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value, Label* label) +{ + SecondScratchRegisterScope scratch2(*this); + splitTag(value, scratch2); + branchTestNull(cond, scratch2, label); +} + +void +MacroAssembler::branchTestObject(Condition cond, const ValueOperand& value, Label* label) +{ + SecondScratchRegisterScope scratch2(*this); + splitTag(value, scratch2); + branchTestObject(cond, scratch2, label); +} + +void +MacroAssembler::branchTestPrimitive(Condition cond, const ValueOperand& value, Label* label) +{ + SecondScratchRegisterScope scratch2(*this); + splitTag(value, scratch2); + branchTestPrimitive(cond, scratch2, label); +} + +template <class L> +void +MacroAssembler::branchTestMagic(Condition cond, const ValueOperand& value, L label) +{ + SecondScratchRegisterScope scratch2(*this); + 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(); + ScratchRegisterScope scratch(*this); + loadPtr(valaddr, scratch); + ma_b(scratch, ImmWord(magic), label, cond); +} + +// ======================================================================== +// Memory access primitives. +void +MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const Address& addr) +{ + ma_sd(src, addr); +} +void +MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const BaseIndex& addr) +{ + MOZ_ASSERT(addr.offset == 0); + ma_sd(src, addr); +} + +void +MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const Address& addr) +{ + ma_ss(src, addr); +} +void +MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const BaseIndex& addr) +{ + MOZ_ASSERT(addr.offset == 0); + ma_ss(src, addr); +} + +// ======================================================================== +// wasm support + +template <class L> +void +MacroAssembler::wasmBoundsCheck(Condition cond, Register index, L label) +{ + BufferOffset bo = ma_BoundsCheck(ScratchRegister); + append(wasm::BoundsCheck(bo.getOffset())); + + ma_b(index, ScratchRegister, label, cond); +} + +void +MacroAssembler::wasmPatchBoundsCheck(uint8_t* patchAt, uint32_t limit) +{ + // Replace with new value + Assembler::UpdateLoad64Value((Instruction*) patchAt, limit); +} + +//}}} 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) +{ + loadPtr(lhs, ScratchRegister); + movePtr(rhs, SecondScratchReg); + cmpPtrSet(cond, ScratchRegister, SecondScratchReg, dest); +} + +template<> +inline void +MacroAssembler::cmpPtrSet(Assembler::Condition cond, Register lhs, Address rhs, + Register dest) +{ + loadPtr(rhs, ScratchRegister); + cmpPtrSet(cond, lhs, ScratchRegister, dest); +} + +template<> +inline void +MacroAssembler::cmp32Set(Assembler::Condition cond, Register lhs, Address rhs, + Register dest) +{ + load32(rhs, ScratchRegister); + cmp32Set(cond, lhs, ScratchRegister, dest); +} + +void +MacroAssemblerMIPS64Compat::incrementInt32Value(const Address& addr) +{ + asMasm().add32(Imm32(1), addr); +} + +void +MacroAssemblerMIPS64Compat::computeEffectiveAddress(const BaseIndex& address, Register dest) +{ + computeScaledAddress(address, dest); + if (address.offset) + asMasm().addPtr(Imm32(address.offset), dest); +} + +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 */ |