Issue #3049 - Enable loongarch64 wasm baseline compiler

This commit is contained in:
Basilisk-Dev 2026-04-25 02:13:28 -04:00 • committed by wuggy
commit dfc6a844c6

View file

@ -109,6 +109,9 @@
#if defined(JS_CODEGEN_ARM) #if defined(JS_CODEGEN_ARM)
# include "jit/arm/Assembler-arm.h" # include "jit/arm/Assembler-arm.h"
#endif #endif
#if defined(JS_CODEGEN_LOONGARCH64)
# include "jit/loongarch64/Assembler-loongarch64.h"
#endif
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
# include "jit/x86-shared/Architecture-x86-shared.h" # include "jit/x86-shared/Architecture-x86-shared.h"
# include "jit/x86-shared/Assembler-x86-shared.h" # include "jit/x86-shared/Assembler-x86-shared.h"
@ -218,7 +221,8 @@ class BaseCompiler
// We define our own ScratchRegister abstractions, deferring to // We define our own ScratchRegister abstractions, deferring to
// the platform's when possible. // the platform's when possible.
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || \
defined(JS_CODEGEN_LOONGARCH64)
typedef ScratchDoubleScope ScratchF64; typedef ScratchDoubleScope ScratchF64;
#else #else
class ScratchF64 class ScratchF64
@ -231,7 +235,8 @@ class BaseCompiler
}; };
#endif #endif
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || \
defined(JS_CODEGEN_LOONGARCH64)
typedef ScratchFloat32Scope ScratchF32; typedef ScratchFloat32Scope ScratchF32;
#else #else
class ScratchF32 class ScratchF32
@ -246,7 +251,7 @@ class BaseCompiler
#if defined(JS_CODEGEN_X64) #if defined(JS_CODEGEN_X64)
typedef ScratchRegisterScope ScratchI32; typedef ScratchRegisterScope ScratchI32;
#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_LOONGARCH64)
class ScratchI32 class ScratchI32
{ {
# ifdef DEBUG # ifdef DEBUG
@ -267,8 +272,10 @@ class BaseCompiler
operator Register() const { operator Register() const {
# ifdef JS_CODEGEN_X86 # ifdef JS_CODEGEN_X86
return ScratchRegX86; return ScratchRegX86;
# else # elif defined(JS_CODEGEN_ARM)
return ScratchRegARM; return ScratchRegARM;
# else
return ScratchRegister;
# endif # endif
} }
}; };
@ -1822,21 +1829,24 @@ class BaseCompiler
Stk& v = stk_[i]; Stk& v = stk_[i];
switch (v.kind()) { switch (v.kind()) {
case Stk::MemI32: case Stk::MemI32:
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || \
defined(JS_CODEGEN_LOONGARCH64)
size += sizeof(intptr_t); size += sizeof(intptr_t);
#else #else
MOZ_CRASH("BaseCompiler platform hook: stackConsumed I32"); MOZ_CRASH("BaseCompiler platform hook: stackConsumed I32");
#endif #endif
break; break;
case Stk::MemI64: case Stk::MemI64:
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || \
defined(JS_CODEGEN_LOONGARCH64)
size += sizeof(int64_t); size += sizeof(int64_t);
#else #else
MOZ_CRASH("BaseCompiler platform hook: stackConsumed I64"); MOZ_CRASH("BaseCompiler platform hook: stackConsumed I64");
#endif #endif
break; break;
case Stk::MemF64: case Stk::MemF64:
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || \
defined(JS_CODEGEN_LOONGARCH64)
size += sizeof(double); size += sizeof(double);
#else #else
MOZ_CRASH("BaseCompiler platform hook: stackConsumed F64"); MOZ_CRASH("BaseCompiler platform hook: stackConsumed F64");
@ -1845,7 +1855,7 @@ class BaseCompiler
case Stk::MemF32: case Stk::MemF32:
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86)
size += sizeof(double); size += sizeof(double);
#elif defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_LOONGARCH64)
size += sizeof(float); size += sizeof(float);
#else #else
MOZ_CRASH("BaseCompiler platform hook: stackConsumed F32"); MOZ_CRASH("BaseCompiler platform hook: stackConsumed F32");
@ -2241,6 +2251,9 @@ class BaseCompiler
masm.store32(scratch, Address(StackPointer, argLoc.offsetFromArgBase() + INT64LOW_OFFSET)); masm.store32(scratch, Address(StackPointer, argLoc.offsetFromArgBase() + INT64LOW_OFFSET));
loadI64High(scratch, arg); loadI64High(scratch, arg);
masm.store32(scratch, Address(StackPointer, argLoc.offsetFromArgBase() + INT64HIGH_OFFSET)); masm.store32(scratch, Address(StackPointer, argLoc.offsetFromArgBase() + INT64HIGH_OFFSET));
#elif defined(JS_CODEGEN_LOONGARCH64)
loadI64(Register64(scratch), arg);
masm.store64(Register64(scratch), Address(StackPointer, argLoc.offsetFromArgBase()));
#else #else
MOZ_CRASH("BaseCompiler platform hook: passArg I64"); MOZ_CRASH("BaseCompiler platform hook: passArg I64");
#endif #endif
@ -2387,7 +2400,8 @@ class BaseCompiler
} }
void jumpTable(LabelVector& labels) { void jumpTable(LabelVector& labels) {
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || \
defined(JS_CODEGEN_LOONGARCH64)
for (uint32_t i = 0; i < labels.length(); i++) { for (uint32_t i = 0; i < labels.length(); i++) {
CodeLabel cl; CodeLabel cl;
masm.writeCodePointer(cl.patchAt()); masm.writeCodePointer(cl.patchAt());
@ -2430,6 +2444,18 @@ class BaseCompiler
// Jump indirect via table element // Jump indirect via table element
masm.ma_ldr(DTRAddr(scratch, DtrRegImmShift(switchValue.reg, LSL, 2)), pc, Offset, masm.ma_ldr(DTRAddr(scratch, DtrRegImmShift(switchValue.reg, LSL, 2)), pc, Offset,
Assembler::Always); Assembler::Always);
#elif defined(JS_CODEGEN_LOONGARCH64)
ScratchI32 scratch(*this);
SecondScratchRegisterScope target(masm);
CodeLabel tableCl;
masm.mov(tableCl.patchAt(), scratch);
tableCl.target()->bind(theTable->offset());
masm.addCodeLabel(tableCl);
masm.computeEffectiveAddress(BaseIndex(scratch, switchValue.reg, ScalePointer), scratch);
masm.loadPtr(Address(scratch, 0), target);
masm.jump(target);
#else #else
MOZ_CRASH("BaseCompiler platform hook: tableSwitch"); MOZ_CRASH("BaseCompiler platform hook: tableSwitch");
#endif #endif
@ -2585,6 +2611,11 @@ class BaseCompiler
masm.cqo(); masm.cqo();
masm.idivq(rhs.reg.reg); masm.idivq(rhs.reg.reg);
} }
# elif defined(JS_CODEGEN_LOONGARCH64)
if (isUnsigned)
masm.as_div_du(srcDest.reg.reg, srcDest.reg.reg, rhs.reg.reg);
else
masm.as_div_d(srcDest.reg.reg, srcDest.reg.reg, rhs.reg.reg);
# else # else
MOZ_CRASH("BaseCompiler platform hook: quotientI64"); MOZ_CRASH("BaseCompiler platform hook: quotientI64");
# endif # endif
@ -2612,6 +2643,11 @@ class BaseCompiler
masm.idivq(rhs.reg.reg); masm.idivq(rhs.reg.reg);
} }
masm.movq(rdx, rax); masm.movq(rdx, rax);
# elif defined(JS_CODEGEN_LOONGARCH64)
if (isUnsigned)
masm.as_mod_du(srcDest.reg.reg, srcDest.reg.reg, rhs.reg.reg);
else
masm.as_mod_d(srcDest.reg.reg, srcDest.reg.reg, rhs.reg.reg);
# else # else
MOZ_CRASH("BaseCompiler platform hook: remainderI64"); MOZ_CRASH("BaseCompiler platform hook: remainderI64");
# endif # endif
@ -2648,7 +2684,7 @@ class BaseCompiler
bool popcnt32NeedsTemp() const { bool popcnt32NeedsTemp() const {
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
return !AssemblerX86Shared::HasPOPCNT(); return !AssemblerX86Shared::HasPOPCNT();
#elif defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_LOONGARCH64)
return true; return true;
#else #else
MOZ_CRASH("BaseCompiler platform hook: popcnt32NeedsTemp"); MOZ_CRASH("BaseCompiler platform hook: popcnt32NeedsTemp");
@ -2658,7 +2694,7 @@ class BaseCompiler
bool popcnt64NeedsTemp() const { bool popcnt64NeedsTemp() const {
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
return !AssemblerX86Shared::HasPOPCNT(); return !AssemblerX86Shared::HasPOPCNT();
#elif defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_LOONGARCH64)
return true; return true;
#else #else
MOZ_CRASH("BaseCompiler platform hook: popcnt64NeedsTemp"); MOZ_CRASH("BaseCompiler platform hook: popcnt64NeedsTemp");
@ -2675,6 +2711,8 @@ class BaseCompiler
masm.freeStack(sizeof(uint64_t)); masm.freeStack(sizeof(uint64_t));
#elif defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_ARM)
masm.ma_vxfer(src.reg.low, src.reg.high, dest.reg); masm.ma_vxfer(src.reg.low, src.reg.high, dest.reg);
#elif defined(JS_CODEGEN_LOONGARCH64)
masm.moveToDouble(src.reg.reg, dest.reg);
#else #else
MOZ_CRASH("BaseCompiler platform hook: reinterpretI64AsF64"); MOZ_CRASH("BaseCompiler platform hook: reinterpretI64AsF64");
#endif #endif
@ -2690,6 +2728,8 @@ class BaseCompiler
masm.Pop(dest.reg.high); masm.Pop(dest.reg.high);
#elif defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_ARM)
masm.ma_vxfer(src.reg, dest.reg.low, dest.reg.high); masm.ma_vxfer(src.reg, dest.reg.low, dest.reg.high);
#elif defined(JS_CODEGEN_LOONGARCH64)
masm.moveFromDouble(src.reg, dest.reg.reg);
#else #else
MOZ_CRASH("BaseCompiler platform hook: reinterpretF64AsI64"); MOZ_CRASH("BaseCompiler platform hook: reinterpretF64AsI64");
#endif #endif
@ -2701,6 +2741,8 @@ class BaseCompiler
masm.movl(src.reg.reg, dest.reg); masm.movl(src.reg.reg, dest.reg);
#elif defined(JS_NUNBOX32) #elif defined(JS_NUNBOX32)
masm.move32(src.reg.low, dest.reg); masm.move32(src.reg.low, dest.reg);
#elif defined(JS_CODEGEN_LOONGARCH64)
masm.move32(src.reg.reg, dest.reg);
#else #else
MOZ_CRASH("BaseCompiler platform hook: wrapI64ToI32"); MOZ_CRASH("BaseCompiler platform hook: wrapI64ToI32");
#endif #endif
@ -2735,6 +2777,8 @@ class BaseCompiler
#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
masm.move8SignExtend(r.reg.low, r.reg.low); masm.move8SignExtend(r.reg.low, r.reg.low);
signExtendI32ToI64(RegI32(r.reg.low), r); signExtendI32ToI64(RegI32(r.reg.low), r);
#elif defined(JS_CODEGEN_LOONGARCH64)
masm.move8SignExtend(r.reg.reg, r.reg.reg);
#else #else
MOZ_CRASH("Basecompiler platform hook: signExtendI64_8"); MOZ_CRASH("Basecompiler platform hook: signExtendI64_8");
#endif #endif
@ -2746,6 +2790,8 @@ class BaseCompiler
#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
masm.move16SignExtend(r.reg.low, r.reg.low); masm.move16SignExtend(r.reg.low, r.reg.low);
signExtendI32ToI64(RegI32(r.reg.low), r); signExtendI32ToI64(RegI32(r.reg.low), r);
#elif defined(JS_CODEGEN_LOONGARCH64)
masm.move16SignExtend(r.reg.reg, r.reg.reg);
#else #else
MOZ_CRASH("Basecompiler platform hook: signExtendI64_16"); MOZ_CRASH("Basecompiler platform hook: signExtendI64_16");
#endif #endif
@ -2762,6 +2808,8 @@ class BaseCompiler
#elif defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_ARM)
masm.ma_mov(src.reg, dest.reg.low); masm.ma_mov(src.reg, dest.reg.low);
masm.ma_asr(Imm32(31), src.reg, dest.reg.high); masm.ma_asr(Imm32(31), src.reg, dest.reg.high);
#elif defined(JS_CODEGEN_LOONGARCH64)
masm.move32(src.reg, dest.reg.reg);
#else #else
MOZ_CRASH("BaseCompiler platform hook: signExtendI32ToI64"); MOZ_CRASH("BaseCompiler platform hook: signExtendI32ToI64");
#endif #endif
@ -2773,6 +2821,8 @@ class BaseCompiler
#elif defined(JS_NUNBOX32) #elif defined(JS_NUNBOX32)
masm.move32(src.reg, dest.reg.low); masm.move32(src.reg, dest.reg.low);
masm.move32(Imm32(0), dest.reg.high); masm.move32(Imm32(0), dest.reg.high);
#elif defined(JS_CODEGEN_LOONGARCH64)
masm.as_bstrpick_d(dest.reg.reg, src.reg, 31, 0);
#else #else
MOZ_CRASH("BaseCompiler platform hook: extendU32ToI64"); MOZ_CRASH("BaseCompiler platform hook: extendU32ToI64");
#endif #endif
@ -2845,6 +2895,30 @@ class BaseCompiler
masm.wasmTruncateFloat32ToUInt32(src.reg, dest.reg, ool->entry()); masm.wasmTruncateFloat32ToUInt32(src.reg, dest.reg, ool->entry());
else else
masm.wasmTruncateFloat32ToInt32(src.reg, dest.reg, ool->entry()); masm.wasmTruncateFloat32ToInt32(src.reg, dest.reg, ool->entry());
#elif defined(JS_CODEGEN_LOONGARCH64)
RegF64 doubleInput = needF64();
ScratchF64 scratch(*this);
masm.convertFloat32ToDouble(src.reg, doubleInput.reg);
masm.branchDouble(Assembler::DoubleUnordered, doubleInput.reg, doubleInput.reg,
trap(Trap::InvalidConversionToInteger));
masm.loadConstantDouble(isUnsigned ? -1.0 : double(INT32_MIN), scratch);
masm.branchDouble(isUnsigned ? Assembler::DoubleLessThanOrEqual
: Assembler::DoubleLessThan,
doubleInput.reg, scratch, trap(Trap::IntegerOverflow));
masm.loadConstantDouble(isUnsigned ? double(UINT32_MAX) + 1.0
: double(INT32_MAX) + 1.0,
scratch);
masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, doubleInput.reg, scratch,
trap(Trap::IntegerOverflow));
sync();
RegI32 temp = needI32();
masm.setupUnalignedABICall(temp.reg);
masm.passABIArg(doubleInput.reg, MoveOp::DOUBLE);
masm.callWithABI(SymbolicAddress::ToInt32);
masm.storeCallInt32Result(dest.reg);
freeI32(temp);
freeF64(doubleInput);
#else #else
MOZ_CRASH("BaseCompiler platform hook: truncateF32ToI32 wasm"); MOZ_CRASH("BaseCompiler platform hook: truncateF32ToI32 wasm");
#endif #endif
@ -2873,6 +2947,27 @@ class BaseCompiler
masm.wasmTruncateDoubleToUInt32(src.reg, dest.reg, ool->entry()); masm.wasmTruncateDoubleToUInt32(src.reg, dest.reg, ool->entry());
else else
masm.wasmTruncateDoubleToInt32(src.reg, dest.reg, ool->entry()); masm.wasmTruncateDoubleToInt32(src.reg, dest.reg, ool->entry());
#elif defined(JS_CODEGEN_LOONGARCH64)
ScratchF64 scratch(*this);
masm.branchDouble(Assembler::DoubleUnordered, src.reg, src.reg,
trap(Trap::InvalidConversionToInteger));
masm.loadConstantDouble(isUnsigned ? -1.0 : double(INT32_MIN), scratch);
masm.branchDouble(isUnsigned ? Assembler::DoubleLessThanOrEqual
: Assembler::DoubleLessThan,
src.reg, scratch, trap(Trap::IntegerOverflow));
masm.loadConstantDouble(isUnsigned ? double(UINT32_MAX) + 1.0
: double(INT32_MAX) + 1.0,
scratch);
masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, src.reg, scratch,
trap(Trap::IntegerOverflow));
sync();
RegI32 temp = needI32();
masm.setupUnalignedABICall(temp.reg);
masm.passABIArg(src.reg, MoveOp::DOUBLE);
masm.callWithABI(SymbolicAddress::ToInt32);
masm.storeCallInt32Result(dest.reg);
freeI32(temp);
#else #else
MOZ_CRASH("BaseCompiler platform hook: truncateF64ToI32 wasm"); MOZ_CRASH("BaseCompiler platform hook: truncateF64ToI32 wasm");
#endif #endif
@ -2937,6 +3032,30 @@ class BaseCompiler
else else
masm.wasmTruncateFloat32ToInt64(src.reg, dest.reg, ool->entry(), masm.wasmTruncateFloat32ToInt64(src.reg, dest.reg, ool->entry(),
ool->rejoin(), temp.reg); ool->rejoin(), temp.reg);
# elif defined(JS_CODEGEN_LOONGARCH64)
RegF64 doubleInput = needF64();
ScratchF64 scratch(*this);
masm.convertFloat32ToDouble(src.reg, doubleInput.reg);
masm.branchDouble(Assembler::DoubleUnordered, doubleInput.reg, doubleInput.reg,
trap(Trap::InvalidConversionToInteger));
masm.loadConstantDouble(isUnsigned ? -1.0 : double(INT64_MIN), scratch);
masm.branchDouble(isUnsigned ? Assembler::DoubleLessThanOrEqual
: Assembler::DoubleLessThan,
doubleInput.reg, scratch, trap(Trap::IntegerOverflow));
masm.loadConstantDouble(isUnsigned ? double(UINT64_MAX) : double(INT64_MAX), scratch);
masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, doubleInput.reg, scratch,
trap(Trap::IntegerOverflow));
sync();
RegI32 callTemp = needI32();
masm.setupUnalignedABICall(callTemp.reg);
masm.passABIArg(doubleInput.reg, MoveOp::DOUBLE);
masm.callWithABI(isUnsigned ? SymbolicAddress::TruncateDoubleToUint64
: SymbolicAddress::TruncateDoubleToInt64);
if (dest.reg.reg != ReturnReg64.reg)
masm.movePtr(ReturnReg64.reg, dest.reg.reg);
freeI32(callTemp);
freeF64(doubleInput);
# else # else
MOZ_CRASH("BaseCompiler platform hook: truncateF32ToI64"); MOZ_CRASH("BaseCompiler platform hook: truncateF32ToI64");
# endif # endif
@ -2957,6 +3076,27 @@ class BaseCompiler
else else
masm.wasmTruncateDoubleToInt64(src.reg, dest.reg, ool->entry(), masm.wasmTruncateDoubleToInt64(src.reg, dest.reg, ool->entry(),
ool->rejoin(), temp.reg); ool->rejoin(), temp.reg);
# elif defined(JS_CODEGEN_LOONGARCH64)
ScratchF64 scratch(*this);
masm.branchDouble(Assembler::DoubleUnordered, src.reg, src.reg,
trap(Trap::InvalidConversionToInteger));
masm.loadConstantDouble(isUnsigned ? -1.0 : double(INT64_MIN), scratch);
masm.branchDouble(isUnsigned ? Assembler::DoubleLessThanOrEqual
: Assembler::DoubleLessThan,
src.reg, scratch, trap(Trap::IntegerOverflow));
masm.loadConstantDouble(isUnsigned ? double(UINT64_MAX) : double(INT64_MAX), scratch);
masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, src.reg, scratch,
trap(Trap::IntegerOverflow));
sync();
RegI32 callTemp = needI32();
masm.setupUnalignedABICall(callTemp.reg);
masm.passABIArg(src.reg, MoveOp::DOUBLE);
masm.callWithABI(isUnsigned ? SymbolicAddress::TruncateDoubleToUint64
: SymbolicAddress::TruncateDoubleToInt64);
if (dest.reg.reg != ReturnReg64.reg)
masm.movePtr(ReturnReg64.reg, dest.reg.reg);
freeI32(callTemp);
# else # else
MOZ_CRASH("BaseCompiler platform hook: truncateF64ToI64"); MOZ_CRASH("BaseCompiler platform hook: truncateF64ToI64");
# endif # endif
@ -2979,6 +3119,11 @@ class BaseCompiler
masm.convertUInt64ToFloat32(src.reg, dest.reg, temp.reg); masm.convertUInt64ToFloat32(src.reg, dest.reg, temp.reg);
else else
masm.convertInt64ToFloat32(src.reg, dest.reg); masm.convertInt64ToFloat32(src.reg, dest.reg);
# elif defined(JS_CODEGEN_LOONGARCH64)
if (isUnsigned)
masm.convertUInt64ToFloat32(src.reg.reg, dest.reg);
else
masm.convertInt64ToFloat32(src.reg.reg, dest.reg);
# else # else
MOZ_CRASH("BaseCompiler platform hook: convertI64ToF32"); MOZ_CRASH("BaseCompiler platform hook: convertI64ToF32");
# endif # endif
@ -2990,6 +3135,11 @@ class BaseCompiler
masm.convertUInt64ToDouble(src.reg, dest.reg, temp.reg); masm.convertUInt64ToDouble(src.reg, dest.reg, temp.reg);
else else
masm.convertInt64ToDouble(src.reg, dest.reg); masm.convertInt64ToDouble(src.reg, dest.reg);
# elif defined(JS_CODEGEN_LOONGARCH64)
if (isUnsigned)
masm.convertUInt64ToDouble(src.reg, dest.reg, temp.reg);
else
masm.convertInt64ToDouble(src.reg.reg, dest.reg);
# else # else
MOZ_CRASH("BaseCompiler platform hook: convertI64ToF64"); MOZ_CRASH("BaseCompiler platform hook: convertI64ToF64");
# endif # endif
@ -3000,7 +3150,7 @@ class BaseCompiler
#if defined(JS_CODEGEN_X64) #if defined(JS_CODEGEN_X64)
masm.cmpq(rhs.reg.reg, lhs.reg.reg); masm.cmpq(rhs.reg.reg, lhs.reg.reg);
masm.emitSet(cond, dest.reg); masm.emitSet(cond, dest.reg);
#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_LOONGARCH64)
// TODO / OPTIMIZE (Bug 1316822): This is pretty branchy, we should be // TODO / OPTIMIZE (Bug 1316822): This is pretty branchy, we should be
// able to do better. // able to do better.
Label done, condTrue; Label done, condTrue;
@ -3041,6 +3191,9 @@ class BaseCompiler
ScratchRegisterScope scratch(*this); // Really must be the ARM scratchreg ScratchRegisterScope scratch(*this); // Really must be the ARM scratchreg
unsigned addr = globalDataOffset - WasmGlobalRegBias; unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.ma_dtr(js::jit::IsLoad, GlobalReg, Imm32(addr), r.reg, scratch); masm.ma_dtr(js::jit::IsLoad, GlobalReg, Imm32(addr), r.reg, scratch);
#elif defined(JS_CODEGEN_LOONGARCH64)
unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.load32(Address(GlobalReg, addr), r.reg);
#else #else
MOZ_CRASH("BaseCompiler platform hook: loadGlobalVarI32"); MOZ_CRASH("BaseCompiler platform hook: loadGlobalVarI32");
#endif #endif
@ -3062,6 +3215,9 @@ class BaseCompiler
masm.ma_dtr(js::jit::IsLoad, GlobalReg, Imm32(addr + INT64LOW_OFFSET), r.reg.low, scratch); masm.ma_dtr(js::jit::IsLoad, GlobalReg, Imm32(addr + INT64LOW_OFFSET), r.reg.low, scratch);
masm.ma_dtr(js::jit::IsLoad, GlobalReg, Imm32(addr + INT64HIGH_OFFSET), r.reg.high, masm.ma_dtr(js::jit::IsLoad, GlobalReg, Imm32(addr + INT64HIGH_OFFSET), r.reg.high,
scratch); scratch);
#elif defined(JS_CODEGEN_LOONGARCH64)
unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.load64(Address(GlobalReg, addr), r.reg);
#else #else
MOZ_CRASH("BaseCompiler platform hook: loadGlobalVarI64"); MOZ_CRASH("BaseCompiler platform hook: loadGlobalVarI64");
#endif #endif
@ -3079,6 +3235,9 @@ class BaseCompiler
unsigned addr = globalDataOffset - WasmGlobalRegBias; unsigned addr = globalDataOffset - WasmGlobalRegBias;
VFPRegister vd(r.reg); VFPRegister vd(r.reg);
masm.ma_vldr(VFPAddr(GlobalReg, VFPOffImm(addr)), vd.singleOverlay()); masm.ma_vldr(VFPAddr(GlobalReg, VFPOffImm(addr)), vd.singleOverlay());
#elif defined(JS_CODEGEN_LOONGARCH64)
unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.loadFloat32(Address(GlobalReg, addr), r.reg);
#else #else
MOZ_CRASH("BaseCompiler platform hook: loadGlobalVarF32"); MOZ_CRASH("BaseCompiler platform hook: loadGlobalVarF32");
#endif #endif
@ -3095,6 +3254,9 @@ class BaseCompiler
#elif defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_ARM)
unsigned addr = globalDataOffset - WasmGlobalRegBias; unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.ma_vldr(VFPAddr(GlobalReg, VFPOffImm(addr)), r.reg); masm.ma_vldr(VFPAddr(GlobalReg, VFPOffImm(addr)), r.reg);
#elif defined(JS_CODEGEN_LOONGARCH64)
unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.loadDouble(Address(GlobalReg, addr), r.reg);
#else #else
MOZ_CRASH("BaseCompiler platform hook: loadGlobalVarF64"); MOZ_CRASH("BaseCompiler platform hook: loadGlobalVarF64");
#endif #endif
@ -3114,6 +3276,9 @@ class BaseCompiler
ScratchRegisterScope scratch(*this); // Really must be the ARM scratchreg ScratchRegisterScope scratch(*this); // Really must be the ARM scratchreg
unsigned addr = globalDataOffset - WasmGlobalRegBias; unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.ma_dtr(js::jit::IsStore, GlobalReg, Imm32(addr), r.reg, scratch); masm.ma_dtr(js::jit::IsStore, GlobalReg, Imm32(addr), r.reg, scratch);
#elif defined(JS_CODEGEN_LOONGARCH64)
unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.store32(r.reg, Address(GlobalReg, addr));
#else #else
MOZ_CRASH("BaseCompiler platform hook: storeGlobalVarI32"); MOZ_CRASH("BaseCompiler platform hook: storeGlobalVarI32");
#endif #endif
@ -3135,6 +3300,9 @@ class BaseCompiler
masm.ma_dtr(js::jit::IsStore, GlobalReg, Imm32(addr + INT64LOW_OFFSET), r.reg.low, scratch); masm.ma_dtr(js::jit::IsStore, GlobalReg, Imm32(addr + INT64LOW_OFFSET), r.reg.low, scratch);
masm.ma_dtr(js::jit::IsStore, GlobalReg, Imm32(addr + INT64HIGH_OFFSET), r.reg.high, masm.ma_dtr(js::jit::IsStore, GlobalReg, Imm32(addr + INT64HIGH_OFFSET), r.reg.high,
scratch); scratch);
#elif defined(JS_CODEGEN_LOONGARCH64)
unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.store64(r.reg, Address(GlobalReg, addr));
#else #else
MOZ_CRASH("BaseCompiler platform hook: storeGlobalVarI64"); MOZ_CRASH("BaseCompiler platform hook: storeGlobalVarI64");
#endif #endif
@ -3152,6 +3320,9 @@ class BaseCompiler
unsigned addr = globalDataOffset - WasmGlobalRegBias; unsigned addr = globalDataOffset - WasmGlobalRegBias;
VFPRegister vd(r.reg); VFPRegister vd(r.reg);
masm.ma_vstr(vd.singleOverlay(), VFPAddr(GlobalReg, VFPOffImm(addr))); masm.ma_vstr(vd.singleOverlay(), VFPAddr(GlobalReg, VFPOffImm(addr)));
#elif defined(JS_CODEGEN_LOONGARCH64)
unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.storeFloat32(r.reg, Address(GlobalReg, addr));
#else #else
MOZ_CRASH("BaseCompiler platform hook: storeGlobalVarF32"); MOZ_CRASH("BaseCompiler platform hook: storeGlobalVarF32");
#endif #endif
@ -3168,6 +3339,9 @@ class BaseCompiler
#elif defined(JS_CODEGEN_ARM) #elif defined(JS_CODEGEN_ARM)
unsigned addr = globalDataOffset - WasmGlobalRegBias; unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.ma_vstr(r.reg, VFPAddr(GlobalReg, VFPOffImm(addr))); masm.ma_vstr(r.reg, VFPAddr(GlobalReg, VFPOffImm(addr)));
#elif defined(JS_CODEGEN_LOONGARCH64)
unsigned addr = globalDataOffset - WasmGlobalRegBias;
masm.storeDouble(r.reg, Address(GlobalReg, addr));
#else #else
MOZ_CRASH("BaseCompiler platform hook: storeGlobalVarF64"); MOZ_CRASH("BaseCompiler platform hook: storeGlobalVarF64");
#endif #endif
@ -3190,7 +3364,7 @@ class BaseCompiler
{} {}
void generate(MacroAssembler& masm) { void generate(MacroAssembler& masm) {
# if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) # if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_LOONGARCH64)
switch (viewType) { switch (viewType) {
case Scalar::MaxTypedArrayViewType: case Scalar::MaxTypedArrayViewType:
MOZ_CRASH("unexpected array type"); MOZ_CRASH("unexpected array type");
@ -3244,6 +3418,8 @@ class BaseCompiler
} }
} }
return 0; return 0;
#elif defined(JS_CODEGEN_LOONGARCH64)
return IsUnaligned(access) && access.byteSize() > 1 ? 1 : 0;
#else #else
return 0; return 0;
#endif #endif
@ -3326,6 +3502,64 @@ class BaseCompiler
default: default:
MOZ_CRASH("Compiler bug: unexpected array type"); MOZ_CRASH("Compiler bug: unexpected array type");
} }
#elif defined(JS_CODEGEN_LOONGARCH64)
switch (access.type()) {
case Scalar::Uint8:
case Scalar::Uint16:
case Scalar::Uint32:
case Scalar::Int8:
case Scalar::Int16:
case Scalar::Int32: {
BaseIndex srcAddr(HeapReg, ptr.reg, TimesOne, access.offset());
LoadStoreSize size = static_cast<LoadStoreSize>(access.byteSize() * 8);
LoadStoreExtension ext = (access.type() == Scalar::Uint8 ||
access.type() == Scalar::Uint16 ||
access.type() == Scalar::Uint32)
? ZeroExtend
: SignExtend;
Register out = dest.tag == AnyReg::I64 ? dest.i64().reg.reg : dest.i32().reg;
if (IsUnaligned(access) && access.byteSize() > 1) {
masm.ma_load_unaligned(access, out, srcAddr, tmp1.reg, size, ext);
} else {
masm.ma_load(out, srcAddr, size, ext);
masm.append(access, masm.size() - 4, masm.framePushed());
}
break;
}
case Scalar::Int64: {
BaseIndex srcAddr(HeapReg, ptr.reg, TimesOne, access.offset());
if (IsUnaligned(access))
masm.ma_load_unaligned(access, dest.i64().reg.reg, srcAddr, tmp1.reg,
SizeDouble, SignExtend);
else {
masm.load64(srcAddr, dest.i64().reg);
masm.append(access, masm.size() - 4, masm.framePushed());
}
break;
}
case Scalar::Float32: {
BaseIndex srcAddr(HeapReg, ptr.reg, TimesOne, access.offset());
if (IsUnaligned(access))
masm.loadUnalignedFloat32(access, srcAddr, tmp1.reg, dest.f32().reg);
else {
masm.loadFloat32(srcAddr, dest.f32().reg);
masm.append(access, masm.size() - 4, masm.framePushed());
}
break;
}
case Scalar::Float64: {
BaseIndex srcAddr(HeapReg, ptr.reg, TimesOne, access.offset());
if (IsUnaligned(access))
masm.loadUnalignedDouble(access, srcAddr, tmp1.reg, dest.f64().reg);
else {
masm.loadDouble(srcAddr, dest.f64().reg);
masm.append(access, masm.size() - 4, masm.framePushed());
}
break;
}
default:
MOZ_CRASH("Compiler bug: unexpected array type");
}
#else #else
MOZ_CRASH("BaseCompiler platform hook: load"); MOZ_CRASH("BaseCompiler platform hook: load");
#endif #endif
@ -3405,6 +3639,59 @@ class BaseCompiler
default: default:
MOZ_CRASH("Compiler bug: unexpected array type"); MOZ_CRASH("Compiler bug: unexpected array type");
} }
#elif defined(JS_CODEGEN_LOONGARCH64)
switch (access.type()) {
case Scalar::Uint8:
case Scalar::Uint16:
case Scalar::Uint32:
case Scalar::Int8:
case Scalar::Int16:
case Scalar::Int32: {
Register rt = src.tag == AnyReg::I64 ? src.i64().reg.reg : src.i32().reg;
BaseIndex dstAddr(HeapReg, ptr.reg, TimesOne, access.offset());
LoadStoreSize size = static_cast<LoadStoreSize>(access.byteSize() * 8);
if (IsUnaligned(access) && access.byteSize() > 1)
masm.ma_store_unaligned(access, rt, dstAddr, tmp1.reg, size, SignExtend);
else {
masm.ma_store(rt, dstAddr, size, SignExtend);
masm.append(access, masm.size() - 4, masm.framePushed());
}
break;
}
case Scalar::Int64: {
BaseIndex dstAddr(HeapReg, ptr.reg, TimesOne, access.offset());
if (IsUnaligned(access))
masm.ma_store_unaligned(access, src.i64().reg.reg, dstAddr, tmp1.reg,
SizeDouble, SignExtend);
else {
masm.store64(src.i64().reg, dstAddr);
masm.append(access, masm.size() - 4, masm.framePushed());
}
break;
}
case Scalar::Float32: {
BaseIndex dstAddr(HeapReg, ptr.reg, TimesOne, access.offset());
if (IsUnaligned(access))
masm.storeUnalignedFloat32(access, src.f32().reg, tmp1.reg, dstAddr);
else {
masm.storeFloat32(src.f32().reg, dstAddr);
masm.append(access, masm.size() - 4, masm.framePushed());
}
break;
}
case Scalar::Float64: {
BaseIndex dstAddr(HeapReg, ptr.reg, TimesOne, access.offset());
if (IsUnaligned(access))
masm.storeUnalignedDouble(access, src.f64().reg, tmp1.reg, dstAddr);
else {
masm.storeDouble(src.f64().reg, dstAddr);
masm.append(access, masm.size() - 4, masm.framePushed());
}
break;
}
default:
MOZ_CRASH("Compiler bug: unexpected array type");
}
#else #else
MOZ_CRASH("BaseCompiler platform hook: store"); MOZ_CRASH("BaseCompiler platform hook: store");
#endif #endif
@ -7593,7 +7880,8 @@ js::wasm::BaselineCanCompile(const FunctionGenerator* fg)
return false; return false;
#endif #endif
#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) #if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM) || \
defined(JS_CODEGEN_LOONGARCH64)
if (fg->usesAtomics()) if (fg->usesAtomics())
return false; return false;