diff --git a/js/src/jit/loongarch64/Architecture-loongarch64.cpp b/js/src/jit/loongarch64/Architecture-loongarch64.cpp index 41321265b8..f0c1a59f09 100644 --- a/js/src/jit/loongarch64/Architecture-loongarch64.cpp +++ b/js/src/jit/loongarch64/Architecture-loongarch64.cpp @@ -73,7 +73,7 @@ uint32_t FloatRegister::getRegisterDumpOffsetInBytes() { } bool CPUFlagsHaveBeenComputed() { - // TODO(loongarch64): Add CPU flags support. + // No optional LoongArch64 CPU feature bits are consumed by this backend yet. return true; } diff --git a/js/src/jit/loongarch64/Architecture-loongarch64.h b/js/src/jit/loongarch64/Architecture-loongarch64.h index 4fab3cfcf5..8792c9adac 100644 --- a/js/src/jit/loongarch64/Architecture-loongarch64.h +++ b/js/src/jit/loongarch64/Architecture-loongarch64.h @@ -293,7 +293,8 @@ class FloatRegisters { static const SetType AllDoubleMask = AllPhysMask * SpreadDouble; static const SetType NoneMask = SetType(0); - // TODO(loongarch64): Much less than ARM64 here. + // LoongArch64 only tracks the scalar callee-saved fp registers here; there + // are no SIMD aliases to account for in this backend yet. static const SetType NonVolatileMask = SetType((1 << FloatRegisters::f24) | (1 << FloatRegisters::f25) | (1 << FloatRegisters::f26) | (1 << FloatRegisters::f27) | diff --git a/js/src/jit/loongarch64/Assembler-loongarch64.cpp b/js/src/jit/loongarch64/Assembler-loongarch64.cpp index b8d33f2ef1..7b65a9e277 100644 --- a/js/src/jit/loongarch64/Assembler-loongarch64.cpp +++ b/js/src/jit/loongarch64/Assembler-loongarch64.cpp @@ -49,11 +49,10 @@ void js::jit::PatchJump(CodeLocationJump& jump_, CodeLocationLabel label, // Note this is used for inter-wasm calls and may pass arguments and results // in floating point registers even if the system ABI does not. -// TODO(loongarch64): Inconsistent with LoongArch's calling convention. -// LoongArch floating-point parameters calling convention: -// The first eight floating-point parameters should be passed in f0-f7, and -// the other floating point parameters will be passed like integer parameters. -// But we just pass the other floating-point parameters on stack here. +// For the internal JIT ABI we spill floating-point arguments beyond f0-f7 to +// the stack instead of recycling integer argument registers. Caller and callee +// both use this discipline, so it remains self-consistent even though the +// native LoongArch C ABI would next use integer argument slots. ABIArg ABIArgGenerator::next(MIRType type) { switch (type) { case MIRType::Int32: @@ -335,7 +334,8 @@ void AssemblerLOONGARCH64::WriteInstStatic(uint32_t x, uint32_t* dest) { } BufferOffset AssemblerLOONGARCH64::haltingAlign(int alignment) { - // TODO(loongarch64): Implement a proper halting align. + // Like ARM64, we currently pad with nops because there is no dedicated + // backend-specific halting fill sequence here yet. return nopAlign(alignment); } diff --git a/js/src/jit/loongarch64/Assembler-loongarch64.h b/js/src/jit/loongarch64/Assembler-loongarch64.h index 1428dc9161..2eacbf3da5 100644 --- a/js/src/jit/loongarch64/Assembler-loongarch64.h +++ b/js/src/jit/loongarch64/Assembler-loongarch64.h @@ -237,8 +237,8 @@ static_assert(JitStackAlignment % sizeof(Value) == 0 && JitStackValueAlignment >= 1, "Stack alignment should be a non-zero multiple of sizeof(Value)"); -// TODO(loongarch64): this is just a filler to prevent a build failure. The -// LoongArch SIMD alignment requirements still need to be explored. +// The backend does not expose LSX/LASX registers yet, but wasm/JIT constant +// pools still assume 16-byte alignment for SIMD-sized data blobs. static constexpr uint32_t SimdMemoryAlignment = 16; static_assert(CodeAlignment % SimdMemoryAlignment == 0, @@ -258,9 +258,7 @@ static constexpr uint32_t WasmCheckedTailEntryOffset = 16u; static constexpr Scale ScalePointer = TimesEight; -// TODO(loongarch64): Add LoongArch instruction types description. - -// LoongArch instruction encoding constants. +// LoongArch instruction encoding constants and operand field positions. static const uint32_t RJShift = 5; static const uint32_t RJBits = 5; static const uint32_t RKShift = 10; @@ -342,11 +340,11 @@ static const uint32_t BOffImm21Mask = ((1 << Imm21Bits) - 1) << Imm21Shift; static const uint32_t BOffImm26Mask = ((1 << Imm26Bits) - 1) << Imm26Shift; static const uint32_t RegMask = Registers::Total - 1; -// TODO(loongarch64) Change to syscall? +// LoongArch break encodes a 10-bit immediate trap code. static const uint32_t MAX_BREAK_CODE = 1024 - 1; static const uint32_t WASM_TRAP = 6; // BRK_OVERFLOW -// TODO(loongarch64) Change to LoongArch instruction type. +// Forward declarations for decoded instruction wrappers. class Instruction; class InstReg; class InstImm; @@ -864,7 +862,7 @@ class LOONGBufferWithExecutableCopy : public LOONGBuffer { class AssemblerLOONGARCH64 : public AssemblerShared { public: - // TODO(loongarch64): Should we remove these conditions here? + // Keep these aligned with the shared MacroAssembler condition space. enum Condition { Equal, NotEqual, diff --git a/js/src/jit/loongarch64/MacroAssembler-loongarch64.cpp b/js/src/jit/loongarch64/MacroAssembler-loongarch64.cpp index 3d961c9e35..0c44060c8c 100644 --- a/js/src/jit/loongarch64/MacroAssembler-loongarch64.cpp +++ b/js/src/jit/loongarch64/MacroAssembler-loongarch64.cpp @@ -859,7 +859,6 @@ void MacroAssemblerLOONGARCH64::ma_subPtrTestOverflow(Register rd, Register rj, void MacroAssemblerLOONGARCH64::ma_subPtrTestOverflow(Register rd, Register rj, Imm32 imm, Label* overflow) { - // TODO(loongarch64): Check subPtrTestOverflow MOZ_ASSERT(imm.value != INT32_MIN); ma_addPtrTestOverflow(rd, rj, Imm32(-imm.value), overflow); } @@ -907,77 +906,37 @@ void MacroAssemblerLOONGARCH64::ma_mulPtrTestOverflow(Register rd, Register rj, void MacroAssemblerLOONGARCH64::ma_load(Register dest, Address address, LoadStoreSize size, LoadStoreExtension extension) { - int32_t encodedOffset; - Register base; - - // TODO: use as_ldx_b/h/w/d, could decrease as_add_d instr. switch (size) { case SizeByte: - case SizeHalfWord: - if (!is_intN(address.offset, 12)) { - ma_li(ScratchRegister, Imm32(address.offset)); - as_add_d(ScratchRegister, address.base, ScratchRegister); - base = ScratchRegister; - encodedOffset = 0; + if (ZeroExtend == extension) { + ma_ld_bu(dest, address); } else { - encodedOffset = address.offset; - base = address.base; + ma_ld_b(dest, address); } - - if (size == SizeByte) { - if (ZeroExtend == extension) { - as_ld_bu(dest, base, encodedOffset); - } else { - as_ld_b(dest, base, encodedOffset); - } + break; + case SizeHalfWord: + if (ZeroExtend == extension) { + ma_ld_hu(dest, address); } else { - if (ZeroExtend == extension) { - as_ld_hu(dest, base, encodedOffset); - } else { - as_ld_h(dest, base, encodedOffset); - } + ma_ld_h(dest, address); } break; case SizeWord: + if ((address.offset & 0x3) == 0 && SignExtend == extension && + Imm16::IsInSignedRange(address.offset)) { + as_ldptr_w(dest, address.base, address.offset); + } else if (ZeroExtend == extension) { + ma_ld_wu(dest, address); + } else { + ma_ld_w(dest, address); + } + break; case SizeDouble: if ((address.offset & 0x3) == 0 && - (size == SizeDouble || - (size == SizeWord && SignExtend == extension))) { - if (!Imm16::IsInSignedRange(address.offset)) { - ma_li(ScratchRegister, Imm32(address.offset)); - as_add_d(ScratchRegister, address.base, ScratchRegister); - base = ScratchRegister; - encodedOffset = 0; - } else { - encodedOffset = address.offset; - base = address.base; - } - - if (size == SizeWord) { - as_ldptr_w(dest, base, encodedOffset); - } else { - as_ldptr_d(dest, base, encodedOffset); - } + Imm16::IsInSignedRange(address.offset)) { + as_ldptr_d(dest, address.base, address.offset); } else { - if (!is_intN(address.offset, 12)) { - ma_li(ScratchRegister, Imm32(address.offset)); - as_add_d(ScratchRegister, address.base, ScratchRegister); - base = ScratchRegister; - encodedOffset = 0; - } else { - encodedOffset = address.offset; - base = address.base; - } - - if (size == SizeWord) { - if (ZeroExtend == extension) { - as_ld_wu(dest, base, encodedOffset); - } else { - as_ld_w(dest, base, encodedOffset); - } - } else { - as_ld_d(dest, base, encodedOffset); - } + ma_ld_d(dest, address); } break; default: @@ -988,63 +947,27 @@ void MacroAssemblerLOONGARCH64::ma_load(Register dest, Address address, void MacroAssemblerLOONGARCH64::ma_store(Register data, Address address, LoadStoreSize size, LoadStoreExtension extension) { - int32_t encodedOffset; - Register base; - - // TODO: use as_stx_b/h/w/d, could decrease as_add_d instr. switch (size) { case SizeByte: + ma_st_b(data, address); + break; case SizeHalfWord: - if (!is_intN(address.offset, 12)) { - ma_li(ScratchRegister, Imm32(address.offset)); - as_add_d(ScratchRegister, address.base, ScratchRegister); - base = ScratchRegister; - encodedOffset = 0; - } else { - encodedOffset = address.offset; - base = address.base; - } - - if (size == SizeByte) { - as_st_b(data, base, encodedOffset); - } else { - as_st_h(data, base, encodedOffset); - } + ma_st_h(data, address); break; case SizeWord: - case SizeDouble: - if ((address.offset & 0x3) == 0) { - if (!Imm16::IsInSignedRange(address.offset)) { - ma_li(ScratchRegister, Imm32(address.offset)); - as_add_d(ScratchRegister, address.base, ScratchRegister); - base = ScratchRegister; - encodedOffset = 0; - } else { - encodedOffset = address.offset; - base = address.base; - } - - if (size == SizeWord) { - as_stptr_w(data, base, encodedOffset); - } else { - as_stptr_d(data, base, encodedOffset); - } + if ((address.offset & 0x3) == 0 && + Imm16::IsInSignedRange(address.offset)) { + as_stptr_w(data, address.base, address.offset); } else { - if (!is_intN(address.offset, 12)) { - ma_li(ScratchRegister, Imm32(address.offset)); - as_add_d(ScratchRegister, address.base, ScratchRegister); - base = ScratchRegister; - encodedOffset = 0; - } else { - encodedOffset = address.offset; - base = address.base; - } - - if (size == SizeWord) { - as_st_w(data, base, encodedOffset); - } else { - as_st_d(data, base, encodedOffset); - } + ma_st_w(data, address); + } + break; + case SizeDouble: + if ((address.offset & 0x3) == 0 && + Imm16::IsInSignedRange(address.offset)) { + as_stptr_d(data, address.base, address.offset); + } else { + ma_st_d(data, address); } break; default: @@ -1274,8 +1197,8 @@ void MacroAssemblerLOONGARCH64::ma_cmp_set(Register rd, Register rj, ImmPtr imm, void MacroAssemblerLOONGARCH64::ma_cmp_set(Register rd, Address address, Imm32 imm, Condition c) { - // TODO(loongarch64): 32-bit ma_cmp_set? SecondScratchRegisterScope scratch2(asMasm()); + // Match the register/Imm32 helper by comparing a sign-extended 32-bit value. ma_ld_w(scratch2, address); ma_cmp_set(rd, Register(scratch2), imm, c); } @@ -1818,8 +1741,7 @@ void MacroAssemblerLOONGARCH64::storeUnalignedFloat32( append(access, store.getOffset(), asMasm().framePushed()); } -// Branches when done from within loongarch-specific code. -// TODO(loongarch64) Optimize ma_b +// Branches emitted from loongarch64-specific code paths. void MacroAssemblerLOONGARCH64::ma_b(Register lhs, Register rhs, Label* label, Condition c, JumpKind jumpKind) { switch (c) { @@ -2488,7 +2410,7 @@ void MacroAssemblerLOONGARCH64Compat::wasmLoadI64Impl( as_ldx_w(output.reg, memoryBase, ptr); break; case Scalar::Uint32: - // TODO(loongarch64): Why need zero-extension here? + // Register64 consumers expect the upper half to be cleared for Uint32. as_ldx_wu(output.reg, memoryBase, ptr); break; case Scalar::Int64: