diff options
Diffstat (limited to 'js/src/jit/mips-shared/MacroAssembler-mips-shared.h')
-rw-r--r-- | js/src/jit/mips-shared/MacroAssembler-mips-shared.h | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/js/src/jit/mips-shared/MacroAssembler-mips-shared.h b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h new file mode 100644 index 0000000000..88238accbb --- /dev/null +++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.h @@ -0,0 +1,258 @@ +/* -*- 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 */ |