diff --git a/js/src/jit/loongarch64/Assembler-loongarch64.cpp b/js/src/jit/loongarch64/Assembler-loongarch64.cpp index 9612d62362..77e7c734ce 100644 --- a/js/src/jit/loongarch64/Assembler-loongarch64.cpp +++ b/js/src/jit/loongarch64/Assembler-loongarch64.cpp @@ -22,20 +22,13 @@ void js::jit::PatchJump(CodeLocationJump& jump_, CodeLocationLabel label, ReprotectCode reprotect) { Instruction* inst = reinterpret_cast(jump_.raw()); - // jumpWithPatch() reserves four instructions: - // beq zero, zero, 0 - // INVALID_OFFSET - // nop - // nop - // Patch that block into the long-jump form used elsewhere in the backend: - // load64 scratch, target - // jirl zero, scratch, 0 - MaybeAutoWritableJitCode awjc(inst, 4 * sizeof(uint32_t), reprotect); - Assembler::WriteLoad64Instructions(inst, ScratchRegister, - uintptr_t(label.raw())); - inst[3] = InstImm(op_jirl, BOffImm16(0), ScratchRegister, zero); + // jumpWithPatch() emits a long-jump template up front so patching only + // updates the embedded target pointer and never mutates live control-flow + // opcodes in place. + MaybeAutoWritableJitCode awjc(inst, 3 * sizeof(uint32_t), reprotect); + Assembler::UpdateLoad64Value(inst, uintptr_t(label.raw())); - AutoFlushICache::flush(uintptr_t(inst), 4 * sizeof(uint32_t)); + AutoFlushICache::flush(uintptr_t(inst), 3 * sizeof(uint32_t)); } // Note this is used for inter-wasm calls and may pass arguments and results @@ -2337,7 +2330,12 @@ void Assembler::bind(RepatchLabel* label) { if (label->used() && !oom()) { BufferOffset branch(label->offset()); InstImm* inst = reinterpret_cast(editSrc(branch)); - bind(inst, branch.getOffset(), dest.getOffset()); + if ((inst[0].extractBitField(31, 25)) == + ((uint32_t)op_lu12i_w >> 25)) { + addLongJump(branch, dest); + } else { + bind(inst, branch.getOffset(), dest.getOffset()); + } } label->bind(dest.getOffset()); } diff --git a/js/src/jit/loongarch64/MacroAssembler-loongarch64.cpp b/js/src/jit/loongarch64/MacroAssembler-loongarch64.cpp index 938783b93a..75efcab752 100644 --- a/js/src/jit/loongarch64/MacroAssembler-loongarch64.cpp +++ b/js/src/jit/loongarch64/MacroAssembler-loongarch64.cpp @@ -1547,6 +1547,145 @@ void MacroAssemblerLOONGARCH64::ma_store(Imm32 imm, const BaseIndex& dest, asMasm().ma_store(scratch, Address(scratch2, 0), size, extension); } +void MacroAssemblerLOONGARCH64::ma_load_unaligned( + const wasm::MemoryAccessDesc& access, Register dest, const BaseIndex& src, + Register temp, LoadStoreSize size, LoadStoreExtension extension) { + MOZ_ASSERT(dest != temp); + + asMasm().computeEffectiveAddress(src, temp); + + BufferOffset load = as_ld_bu(dest, temp, 0); + if (size != SizeByte) { + ScratchRegisterScope scratch(asMasm()); + const size_t byteSize = size / 8; + for (size_t i = 1; i < byteSize; i++) { + as_ld_bu(scratch, temp, i); + as_slli_d(scratch, scratch, 8 * i); + as_or(dest, dest, scratch); + } + } + + switch (size) { + case SizeByte: + if (extension == SignExtend) { + as_ext_w_b(dest, dest); + } + break; + case SizeHalfWord: + if (extension == SignExtend) { + as_ext_w_h(dest, dest); + } + break; + case SizeWord: + if (extension == SignExtend) { + as_addi_w(dest, dest, 0); + } + break; + case SizeDouble: + break; + default: + MOZ_CRASH("Invalid argument for ma_load_unaligned"); + } + + append(access, load.getOffset(), asMasm().framePushed()); +} + +void MacroAssemblerLOONGARCH64::ma_store_unaligned( + const wasm::MemoryAccessDesc& access, Register data, const BaseIndex& dest, + Register temp, LoadStoreSize size, LoadStoreExtension extension) { + (void)extension; + + MOZ_ASSERT(data != temp); + + asMasm().computeEffectiveAddress(dest, temp); + + BufferOffset store = as_st_b(data, temp, 0); + if (size != SizeByte) { + ScratchRegisterScope scratch(asMasm()); + const size_t byteSize = size / 8; + for (size_t i = 1; i < byteSize; i++) { + as_srli_d(scratch, data, 8 * i); + as_st_b(scratch, temp, i); + } + } + + append(access, store.getOffset(), asMasm().framePushed()); +} + +void MacroAssemblerLOONGARCH64::loadUnalignedDouble( + const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, + FloatRegister dest) { + asMasm().computeEffectiveAddress(src, temp); + + ScratchRegisterScope scratch(asMasm()); + SecondScratchRegisterScope scratch2(asMasm()); + + BufferOffset load = as_ld_bu(scratch, temp, 0); + for (size_t i = 1; i < sizeof(double); i++) { + as_ld_bu(scratch2, temp, i); + as_slli_d(scratch2, scratch2, 8 * i); + as_or(scratch, scratch, scratch2); + } + + append(access, load.getOffset(), asMasm().framePushed()); + moveToDouble(scratch, dest); +} + +void MacroAssemblerLOONGARCH64::loadUnalignedFloat32( + const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, + FloatRegister dest) { + asMasm().computeEffectiveAddress(src, temp); + + ScratchRegisterScope scratch(asMasm()); + SecondScratchRegisterScope scratch2(asMasm()); + + BufferOffset load = as_ld_bu(scratch, temp, 0); + for (size_t i = 1; i < sizeof(float); i++) { + as_ld_bu(scratch2, temp, i); + as_slli_d(scratch2, scratch2, 8 * i); + as_or(scratch, scratch, scratch2); + } + + append(access, load.getOffset(), asMasm().framePushed()); + moveToFloat32(scratch, dest); +} + +void MacroAssemblerLOONGARCH64::storeUnalignedDouble( + const wasm::MemoryAccessDesc& access, FloatRegister src, Register temp, + const BaseIndex& dest) { + asMasm().computeEffectiveAddress(dest, temp); + + ScratchRegisterScope scratch(asMasm()); + SecondScratchRegisterScope scratch2(asMasm()); + moveFromDouble(src, scratch); + + BufferOffset store = as_st_b(scratch, temp, 0); + for (size_t i = 1; i < sizeof(double); i++) { + as_srli_d(scratch2, scratch, 8 * i); + as_st_b(scratch2, temp, i); + } + + append(access, store.getOffset(), asMasm().framePushed()); +} + +void MacroAssemblerLOONGARCH64::storeUnalignedFloat32( + const wasm::MemoryAccessDesc& access, FloatRegister src, Register temp, + const BaseIndex& dest) { + asMasm().computeEffectiveAddress(dest, temp); + + ScratchRegisterScope scratch(asMasm()); + SecondScratchRegisterScope scratch2(asMasm()); + moveFromFloat32(src, scratch); + + BufferOffset store = as_st_b(scratch, temp, 0); + for (size_t i = 1; i < sizeof(float); i++) { + as_srli_d(scratch2, scratch, 8 * i); + as_st_b(scratch2, temp, i); + } + + append(access, store.getOffset(), asMasm().framePushed()); +} + // Branches when done from within loongarch-specific code. // TODO(loongarch64) Optimize ma_b void MacroAssemblerLOONGARCH64::ma_b(Register lhs, Register rhs, Label* label, @@ -2512,16 +2651,18 @@ CodeOffsetJump MacroAssemblerLOONGARCH64Compat::backedgeJump( CodeOffsetJump MacroAssemblerLOONGARCH64Compat::jumpWithPatch( RepatchLabel* label, Label* documentation) { + (void)documentation; MOZ_ASSERT(!label->used()); BufferOffset bo = nextOffset(); label->use(bo.getOffset()); m_buffer.ensureSpace(4 * sizeof(uint32_t)); - writeInst(InstImm(op_beq, BOffImm16(0), zero, zero).encode()); - writeInst(LabelBase::INVALID_OFFSET); - as_nop(); - as_nop(); + if (label->bound()) { + addLongJump(bo, BufferOffset(label->offset())); + } + ma_liPatchable(ScratchRegister, ImmWord(LabelBase::INVALID_OFFSET)); + as_jirl(zero, ScratchRegister, BOffImm16(0)); return CodeOffsetJump(bo.getOffset()); } diff --git a/js/src/jit/loongarch64/MacroAssembler-loongarch64.h b/js/src/jit/loongarch64/MacroAssembler-loongarch64.h index 31ed3777d3..0c70e3968a 100644 --- a/js/src/jit/loongarch64/MacroAssembler-loongarch64.h +++ b/js/src/jit/loongarch64/MacroAssembler-loongarch64.h @@ -559,62 +559,22 @@ class MacroAssemblerLOONGARCH64 : public Assembler { } void ma_load_unaligned(const wasm::MemoryAccessDesc& access, Register dest, const BaseIndex& src, Register temp, - LoadStoreSize size, LoadStoreExtension extension) { - (void)access; - (void)dest; - (void)src; - (void)temp; - (void)size; - (void)extension; - MOZ_CRASH("wasm unaligned integer loads are not supported on loongarch64 yet"); - } + LoadStoreSize size, LoadStoreExtension extension); void ma_store_unaligned(const wasm::MemoryAccessDesc& access, Register data, const BaseIndex& dest, Register temp, - LoadStoreSize size, LoadStoreExtension extension) { - (void)access; - (void)data; - (void)dest; - (void)temp; - (void)size; - (void)extension; - MOZ_CRASH("wasm unaligned integer stores are not supported on loongarch64 yet"); - } + LoadStoreSize size, LoadStoreExtension extension); void loadUnalignedDouble(const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, - FloatRegister dest) { - (void)access; - (void)src; - (void)temp; - (void)dest; - MOZ_CRASH("wasm unaligned double loads are not supported on loongarch64 yet"); - } + FloatRegister dest); void loadUnalignedFloat32(const wasm::MemoryAccessDesc& access, const BaseIndex& src, Register temp, - FloatRegister dest) { - (void)access; - (void)src; - (void)temp; - (void)dest; - MOZ_CRASH("wasm unaligned float loads are not supported on loongarch64 yet"); - } + FloatRegister dest); void storeUnalignedDouble(const wasm::MemoryAccessDesc& access, FloatRegister src, Register temp, - const BaseIndex& dest) { - (void)access; - (void)src; - (void)temp; - (void)dest; - MOZ_CRASH("wasm unaligned double stores are not supported on loongarch64 yet"); - } + const BaseIndex& dest); void storeUnalignedFloat32(const wasm::MemoryAccessDesc& access, FloatRegister src, Register temp, - const BaseIndex& dest) { - (void)access; - (void)src; - (void)temp; - (void)dest; - MOZ_CRASH("wasm unaligned float stores are not supported on loongarch64 yet"); - } + const BaseIndex& 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);