Source code

Revision control

Other Tools

/* -*- 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/. */
#ifndef jit_mips_shared_MacroAssembler_mips_shared_h
#define jit_mips_shared_MacroAssembler_mips_shared_h
#if defined(JS_CODEGEN_MIPS32)
# include "jit/mips32/Assembler-mips32.h"
#elif defined(JS_CODEGEN_MIPS64)
# include "jit/mips64/Assembler-mips64.h"
#endif
#include "jit/AtomicOp.h"
namespace js {
namespace jit {
enum LoadStoreSize {
SizeByte = 8,
SizeHalfWord = 16,
SizeWord = 32,
SizeDouble = 64
};
enum LoadStoreExtension { ZeroExtend = 0, SignExtend = 1 };
enum JumpKind { LongJump = 0, ShortJump = 1 };
enum DelaySlotFill { DontFillDelaySlot = 0, FillDelaySlot = 1 };
static Register CallReg = t9;
class MacroAssemblerMIPSShared : public Assembler {
protected:
// Perform a downcast. Should be removed by Bug 996602.
MacroAssembler& asMasm();
const MacroAssembler& asMasm() const;
Condition ma_cmp(Register rd, Register lhs, Register rhs, Condition c);
Condition ma_cmp(Register rd, Register lhs, Imm32 imm, Condition c);
void compareFloatingPoint(FloatFormat fmt, FloatRegister lhs,
FloatRegister rhs, DoubleCondition c,
FloatTestKind* testKind, FPConditionBit fcc = FCC0);
public:
void ma_move(Register rd, Register rs);
void ma_li(Register dest, ImmGCPtr ptr);
void ma_li(Register dest, Imm32 imm);
void ma_liPatchable(Register dest, Imm32 imm);
// Shift operations
void ma_sll(Register rd, Register rt, Imm32 shift);
void ma_srl(Register rd, Register rt, Imm32 shift);
void ma_sra(Register rd, Register rt, Imm32 shift);
void ma_ror(Register rd, Register rt, Imm32 shift);
void ma_rol(Register rd, Register rt, Imm32 shift);
void ma_sll(Register rd, Register rt, Register shift);
void ma_srl(Register rd, Register rt, Register shift);
void ma_sra(Register rd, Register rt, Register shift);
void ma_ror(Register rd, Register rt, Register shift);
void ma_rol(Register rd, Register rt, Register shift);
// Negate
void ma_negu(Register rd, Register rs);
void ma_not(Register rd, Register rs);
// Bit extract/insert
void ma_ext(Register rt, Register rs, uint16_t pos, uint16_t size);
void ma_ins(Register rt, Register rs, uint16_t pos, uint16_t size);
// Sign extend
void ma_seb(Register rd, Register rt);
void ma_seh(Register rd, Register rt);
// and
void ma_and(Register rd, Register rs);
void ma_and(Register rd, Imm32 imm);
void ma_and(Register rd, Register rs, Imm32 imm);
// or
void ma_or(Register rd, Register rs);
void ma_or(Register rd, Imm32 imm);
void ma_or(Register rd, Register rs, Imm32 imm);
// xor
void ma_xor(Register rd, Register rs);
void ma_xor(Register rd, Imm32 imm);
void ma_xor(Register rd, Register rs, Imm32 imm);
// word swap byte within halfwords
void ma_wsbh(Register rd, Register rt);
void ma_ctz(Register rd, Register rs);
// load
void ma_load(Register dest, const BaseIndex& src,
LoadStoreSize size = SizeWord,
LoadStoreExtension extension = SignExtend);
void ma_load_unaligned(Register dest, const BaseIndex& src,
LoadStoreSize size = SizeWord,
LoadStoreExtension extension = SignExtend);
void ma_load_unaligned(Register dest, const Address& address,
LoadStoreSize size = SizeWord,
LoadStoreExtension extension = SignExtend);
void ma_load_unaligned(const wasm::MemoryAccessDesc& access, Register dest,
const BaseIndex& src, Register temp,
LoadStoreSize size, LoadStoreExtension extension);
// store
void ma_store(Register data, const BaseIndex& dest,
LoadStoreSize size = SizeWord,
LoadStoreExtension extension = SignExtend);
void ma_store(Imm32 imm, const BaseIndex& dest, LoadStoreSize size = SizeWord,
LoadStoreExtension extension = SignExtend);
void ma_store_unaligned(Register data, const Address& dest,
LoadStoreSize size = SizeWord);
void ma_store_unaligned(Register data, const BaseIndex& dest,
LoadStoreSize size = SizeWord);
void ma_store_unaligned(const wasm::MemoryAccessDesc& access, Register data,
const BaseIndex& dest, Register temp,
LoadStoreSize size, LoadStoreExtension extension);
// arithmetic based ops
// add
void ma_addu(Register rd, Register rs, Imm32 imm);
void ma_addu(Register rd, Register rs);
void ma_addu(Register rd, Imm32 imm);
void ma_add32TestCarry(Condition cond, Register rd, Register rs, Register rt,
Label* overflow);
void ma_add32TestCarry(Condition cond, Register rd, Register rs, Imm32 imm,
Label* overflow);
// subtract
void ma_subu(Register rd, Register rs, Imm32 imm);
void ma_subu(Register rd, Register rs);
void ma_subu(Register rd, Imm32 imm);
void ma_sub32TestOverflow(Register rd, Register rs, Imm32 imm,
Label* overflow);
// multiplies. For now, there are only few that we care about.
void ma_mul(Register rd, Register rs, Imm32 imm);
void ma_mul32TestOverflow(Register rd, Register rs, Register rt,
Label* overflow);
void ma_mul32TestOverflow(Register rd, Register rs, Imm32 imm,
Label* overflow);
// divisions
void ma_div_branch_overflow(Register rd, Register rs, Register rt,
Label* overflow);
void ma_div_branch_overflow(Register rd, Register rs, Imm32 imm,
Label* overflow);
// fast mod, uses scratch registers, and thus needs to be in the assembler
// implicitly assumes that we can overwrite dest at the beginning of the
// sequence
void ma_mod_mask(Register src, Register dest, Register hold, Register remain,
int32_t shift, Label* negZero = nullptr);
// branches when done from within mips-specific code
void ma_b(Register lhs, Register rhs, Label* l, Condition c,
JumpKind jumpKind = LongJump);
void ma_b(Register lhs, Imm32 imm, Label* l, Condition c,
JumpKind jumpKind = LongJump);
void ma_b(Register lhs, ImmPtr imm, Label* l, Condition c,
JumpKind jumpKind = LongJump);
void ma_b(Register lhs, ImmGCPtr imm, Label* l, Condition c,
JumpKind jumpKind = LongJump) {
MOZ_ASSERT(lhs != ScratchRegister);
ma_li(ScratchRegister, imm);
ma_b(lhs, ScratchRegister, l, c, jumpKind);
}
void ma_b(Label* l, JumpKind jumpKind = LongJump);
// fp instructions
void ma_lis(FloatRegister dest, float value);
void ma_sd(FloatRegister src, BaseIndex address);
void ma_ss(FloatRegister src, BaseIndex address);
void ma_ld(FloatRegister dest, const BaseIndex& src);
void ma_ls(FloatRegister dest, const BaseIndex& src);
// FP branches
void ma_bc1s(FloatRegister lhs, FloatRegister rhs, Label* label,
DoubleCondition c, JumpKind jumpKind = LongJump,
FPConditionBit fcc = FCC0);
void ma_bc1d(FloatRegister lhs, FloatRegister rhs, Label* label,
DoubleCondition c, JumpKind jumpKind = LongJump,
FPConditionBit fcc = FCC0);
void ma_call(ImmPtr dest);
void ma_jump(ImmPtr dest);
void ma_cmp_set(Register dst, Register lhs, Register rhs, Condition c);
void ma_cmp_set(Register dst, Register lhs, Imm32 imm, Condition c);
// void ma_cmp_set(Register dst, Address address, Imm32 imm, Condition c);
void ma_cmp_set_double(Register dst, FloatRegister lhs, FloatRegister rhs,
DoubleCondition c);
void ma_cmp_set_float32(Register dst, FloatRegister lhs, FloatRegister rhs,
DoubleCondition c);
void moveToDoubleLo(Register src, FloatRegister dest) { as_mtc1(src, dest); }
void moveFromDoubleLo(FloatRegister src, Register dest) {
as_mfc1(dest, src);
}
void moveToFloat32(Register src, FloatRegister dest) { as_mtc1(src, dest); }
void moveFromFloat32(FloatRegister src, Register dest) { as_mfc1(dest, src); }
// Evaluate srcDest = minmax<isMax>{Float32,Double}(srcDest, other).
// Handle NaN specially if handleNaN is true.
void minMaxDouble(FloatRegister srcDest, FloatRegister other, bool handleNaN,
bool isMax);
void minMaxFloat32(FloatRegister srcDest, FloatRegister other, bool handleNaN,
bool isMax);
void loadDouble(const Address& addr, FloatRegister dest);
void loadDouble(const BaseIndex& src, FloatRegister dest);
// Load a float value into a register, then expand it to a double.
void loadFloatAsDouble(const Address& addr, FloatRegister dest);
void loadFloatAsDouble(const BaseIndex& src, FloatRegister dest);
void loadFloat32(const Address& addr, FloatRegister dest);
void loadFloat32(const BaseIndex& src, FloatRegister dest);
void outOfLineWasmTruncateToInt32Check(FloatRegister input, Register output,
MIRType fromType, TruncFlags flags,
Label* rejoin,
wasm::BytecodeOffset trapOffset);
void outOfLineWasmTruncateToInt64Check(FloatRegister input, Register64 output,
MIRType fromType, TruncFlags flags,
Label* rejoin,
wasm::BytecodeOffset trapOffset);
protected:
void wasmLoadImpl(const wasm::MemoryAccessDesc& access, Register memoryBase,
Register ptr, Register ptrScratch, AnyRegister output,
Register tmp);
void wasmStoreImpl(const wasm::MemoryAccessDesc& access, AnyRegister value,
Register memoryBase, Register ptr, Register ptrScratch,
Register tmp);
};
} // namespace jit
} // namespace js
#endif /* jit_mips_shared_MacroAssembler_mips_shared_h */