mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 15:28:39 +09:00
Issue #3049 - Enable loongarch64 JIT atomics
This commit is contained in:
parent
bb16a45039
commit
4c58aa2724
3 changed files with 699 additions and 16 deletions
|
|
@ -306,58 +306,307 @@ CodeGeneratorLoongArch64::visitWasmAddOffset(LWasmAddOffset* lir)
|
|||
masm.branchPtr(Assembler::Below, out, limitBase, trap(mir, wasm::Trap::OutOfBounds));
|
||||
}
|
||||
|
||||
template <typename S, typename T>
|
||||
static void
|
||||
AtomicBinopToTypedIntArray(MacroAssemblerLOONGARCH64Compat& masm, AtomicOp op,
|
||||
Scalar::Type arrayType, const S& value,
|
||||
const T& mem, Register outTemp,
|
||||
Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, AnyRegister output)
|
||||
{
|
||||
switch (arrayType) {
|
||||
case Scalar::Int8:
|
||||
masm.atomicFetchOp(1, true, op, value, mem, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Uint8:
|
||||
masm.atomicFetchOp(1, false, op, value, mem, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Int16:
|
||||
masm.atomicFetchOp(2, true, op, value, mem, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Uint16:
|
||||
masm.atomicFetchOp(2, false, op, value, mem, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Int32:
|
||||
masm.atomicFetchOp(4, false, op, value, mem, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Uint32:
|
||||
MOZ_ASSERT(output.isFloat());
|
||||
MOZ_ASSERT(outTemp != InvalidReg);
|
||||
masm.atomicFetchOp(4, false, op, value, mem, valueTemp, offsetTemp,
|
||||
maskTemp, outTemp);
|
||||
masm.convertUInt32ToDouble(outTemp, output.fpu());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid typed array type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename S, typename T>
|
||||
static void
|
||||
AtomicBinopToTypedIntArray(MacroAssemblerLOONGARCH64Compat& masm, AtomicOp op,
|
||||
Scalar::Type arrayType, const S& value,
|
||||
const T& mem, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp)
|
||||
{
|
||||
switch (arrayType) {
|
||||
case Scalar::Int8:
|
||||
case Scalar::Uint8:
|
||||
masm.atomicEffectOp(1, op, value, mem, valueTemp, offsetTemp,
|
||||
maskTemp);
|
||||
break;
|
||||
case Scalar::Int16:
|
||||
case Scalar::Uint16:
|
||||
masm.atomicEffectOp(2, op, value, mem, valueTemp, offsetTemp,
|
||||
maskTemp);
|
||||
break;
|
||||
case Scalar::Int32:
|
||||
case Scalar::Uint32:
|
||||
masm.atomicEffectOp(4, op, value, mem, valueTemp, offsetTemp,
|
||||
maskTemp);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid typed array type");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void
|
||||
AtomicBinopToTypedArray(MacroAssemblerLOONGARCH64Compat& masm, AtomicOp op,
|
||||
Scalar::Type arrayType, const LAllocation* value,
|
||||
const T& mem, Register outTemp, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp,
|
||||
AnyRegister output)
|
||||
{
|
||||
if (value->isConstant()) {
|
||||
AtomicBinopToTypedIntArray(masm, op, arrayType, Imm32(ToInt32(value)),
|
||||
mem, outTemp, valueTemp, offsetTemp,
|
||||
maskTemp, output);
|
||||
} else {
|
||||
AtomicBinopToTypedIntArray(masm, op, arrayType, ToRegister(value),
|
||||
mem, outTemp, valueTemp, offsetTemp,
|
||||
maskTemp, output);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void
|
||||
AtomicBinopToTypedArray(MacroAssemblerLOONGARCH64Compat& masm, AtomicOp op,
|
||||
Scalar::Type arrayType, const LAllocation* value,
|
||||
const T& mem, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp)
|
||||
{
|
||||
if (value->isConstant()) {
|
||||
AtomicBinopToTypedIntArray(masm, op, arrayType, Imm32(ToInt32(value)),
|
||||
mem, valueTemp, offsetTemp, maskTemp);
|
||||
} else {
|
||||
AtomicBinopToTypedIntArray(masm, op, arrayType, ToRegister(value),
|
||||
mem, valueTemp, offsetTemp, maskTemp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorLoongArch64::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins)
|
||||
{
|
||||
(void)ins;
|
||||
MOZ_CRASH("asm.js atomics are not supported on loongarch64 yet");
|
||||
MAsmJSCompareExchangeHeap* mir = ins->mir();
|
||||
Scalar::Type vt = mir->access().type();
|
||||
Register ptrReg = ToRegister(ins->ptr());
|
||||
BaseIndex srcAddr(HeapReg, ptrReg, TimesOne);
|
||||
MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
|
||||
|
||||
Register oldval = ToRegister(ins->oldValue());
|
||||
Register newval = ToRegister(ins->newValue());
|
||||
Register valueTemp = ToRegister(ins->valueTemp());
|
||||
Register offsetTemp = ToRegister(ins->offsetTemp());
|
||||
Register maskTemp = ToRegister(ins->maskTemp());
|
||||
|
||||
masm.compareExchangeToTypedIntArray(
|
||||
vt == Scalar::Uint32 ? Scalar::Int32 : vt, srcAddr, oldval, newval,
|
||||
InvalidReg, valueTemp, offsetTemp, maskTemp,
|
||||
ToAnyRegister(ins->output()));
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorLoongArch64::visitAsmJSAtomicExchangeHeap(LAsmJSAtomicExchangeHeap* ins)
|
||||
{
|
||||
(void)ins;
|
||||
MOZ_CRASH("asm.js atomics are not supported on loongarch64 yet");
|
||||
MAsmJSAtomicExchangeHeap* mir = ins->mir();
|
||||
Scalar::Type vt = mir->access().type();
|
||||
Register ptrReg = ToRegister(ins->ptr());
|
||||
Register value = ToRegister(ins->value());
|
||||
BaseIndex srcAddr(HeapReg, ptrReg, TimesOne);
|
||||
MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
|
||||
|
||||
Register valueTemp = ToRegister(ins->valueTemp());
|
||||
Register offsetTemp = ToRegister(ins->offsetTemp());
|
||||
Register maskTemp = ToRegister(ins->maskTemp());
|
||||
|
||||
masm.atomicExchangeToTypedIntArray(
|
||||
vt == Scalar::Uint32 ? Scalar::Int32 : vt, srcAddr, value, InvalidReg,
|
||||
valueTemp, offsetTemp, maskTemp, ToAnyRegister(ins->output()));
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorLoongArch64::visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap* ins)
|
||||
{
|
||||
(void)ins;
|
||||
MOZ_CRASH("asm.js atomics are not supported on loongarch64 yet");
|
||||
MOZ_ASSERT(ins->mir()->hasUses());
|
||||
MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
|
||||
|
||||
MAsmJSAtomicBinopHeap* mir = ins->mir();
|
||||
Scalar::Type vt = mir->access().type();
|
||||
Register ptrReg = ToRegister(ins->ptr());
|
||||
Register valueTemp = ToRegister(ins->valueTemp());
|
||||
Register offsetTemp = ToRegister(ins->offsetTemp());
|
||||
Register maskTemp = ToRegister(ins->maskTemp());
|
||||
const LAllocation* value = ins->value();
|
||||
AtomicOp op = mir->operation();
|
||||
|
||||
BaseIndex srcAddr(HeapReg, ptrReg, TimesOne);
|
||||
|
||||
AtomicBinopToTypedArray(masm, op,
|
||||
vt == Scalar::Uint32 ? Scalar::Int32 : vt, value,
|
||||
srcAddr, InvalidReg, valueTemp, offsetTemp,
|
||||
maskTemp, ToAnyRegister(ins->output()));
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorLoongArch64::visitAsmJSAtomicBinopHeapForEffect(LAsmJSAtomicBinopHeapForEffect* ins)
|
||||
{
|
||||
(void)ins;
|
||||
MOZ_CRASH("asm.js atomics are not supported on loongarch64 yet");
|
||||
MOZ_ASSERT(!ins->mir()->hasUses());
|
||||
MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
|
||||
|
||||
MAsmJSAtomicBinopHeap* mir = ins->mir();
|
||||
Scalar::Type vt = mir->access().type();
|
||||
Register ptrReg = ToRegister(ins->ptr());
|
||||
Register valueTemp = ToRegister(ins->valueTemp());
|
||||
Register offsetTemp = ToRegister(ins->offsetTemp());
|
||||
Register maskTemp = ToRegister(ins->maskTemp());
|
||||
const LAllocation* value = ins->value();
|
||||
AtomicOp op = mir->operation();
|
||||
|
||||
BaseIndex srcAddr(HeapReg, ptrReg, TimesOne);
|
||||
|
||||
AtomicBinopToTypedArray(masm, op, vt, value, srcAddr, valueTemp,
|
||||
offsetTemp, maskTemp);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorLoongArch64::visitAtomicTypedArrayElementBinop(LAtomicTypedArrayElementBinop* lir)
|
||||
{
|
||||
(void)lir;
|
||||
MOZ_CRASH("atomics are not supported on loongarch64 Ion yet");
|
||||
MOZ_ASSERT(lir->mir()->hasUses());
|
||||
|
||||
AnyRegister output = ToAnyRegister(lir->output());
|
||||
Register elements = ToRegister(lir->elements());
|
||||
Register outTemp = lir->temp2()->isBogusTemp() ? InvalidReg
|
||||
: ToRegister(lir->temp2());
|
||||
Register valueTemp = ToRegister(lir->valueTemp());
|
||||
Register offsetTemp = ToRegister(lir->offsetTemp());
|
||||
Register maskTemp = ToRegister(lir->maskTemp());
|
||||
const LAllocation* value = lir->value();
|
||||
|
||||
Scalar::Type arrayType = lir->mir()->arrayType();
|
||||
int width = Scalar::byteSize(arrayType);
|
||||
|
||||
if (lir->index()->isConstant()) {
|
||||
Address mem(elements, ToInt32(lir->index()) * width);
|
||||
AtomicBinopToTypedArray(masm, lir->mir()->operation(), arrayType, value,
|
||||
mem, outTemp, valueTemp, offsetTemp, maskTemp,
|
||||
output);
|
||||
} else {
|
||||
BaseIndex mem(elements, ToRegister(lir->index()),
|
||||
ScaleFromElemWidth(width));
|
||||
AtomicBinopToTypedArray(masm, lir->mir()->operation(), arrayType, value,
|
||||
mem, outTemp, valueTemp, offsetTemp, maskTemp,
|
||||
output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorLoongArch64::visitAtomicTypedArrayElementBinopForEffect(LAtomicTypedArrayElementBinopForEffect* lir)
|
||||
{
|
||||
(void)lir;
|
||||
MOZ_CRASH("atomics are not supported on loongarch64 Ion yet");
|
||||
MOZ_ASSERT(!lir->mir()->hasUses());
|
||||
|
||||
Register elements = ToRegister(lir->elements());
|
||||
Register valueTemp = ToRegister(lir->valueTemp());
|
||||
Register offsetTemp = ToRegister(lir->offsetTemp());
|
||||
Register maskTemp = ToRegister(lir->maskTemp());
|
||||
const LAllocation* value = lir->value();
|
||||
Scalar::Type arrayType = lir->mir()->arrayType();
|
||||
int width = Scalar::byteSize(arrayType);
|
||||
|
||||
if (lir->index()->isConstant()) {
|
||||
Address mem(elements, ToInt32(lir->index()) * width);
|
||||
AtomicBinopToTypedArray(masm, lir->mir()->operation(), arrayType, value,
|
||||
mem, valueTemp, offsetTemp, maskTemp);
|
||||
} else {
|
||||
BaseIndex mem(elements, ToRegister(lir->index()),
|
||||
ScaleFromElemWidth(width));
|
||||
AtomicBinopToTypedArray(masm, lir->mir()->operation(), arrayType, value,
|
||||
mem, valueTemp, offsetTemp, maskTemp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorLoongArch64::visitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement* lir)
|
||||
{
|
||||
(void)lir;
|
||||
MOZ_CRASH("atomics are not supported on loongarch64 Ion yet");
|
||||
Register elements = ToRegister(lir->elements());
|
||||
AnyRegister output = ToAnyRegister(lir->output());
|
||||
Register temp = lir->temp()->isBogusTemp() ? InvalidReg
|
||||
: ToRegister(lir->temp());
|
||||
|
||||
Register oldval = ToRegister(lir->oldval());
|
||||
Register newval = ToRegister(lir->newval());
|
||||
Register valueTemp = ToRegister(lir->valueTemp());
|
||||
Register offsetTemp = ToRegister(lir->offsetTemp());
|
||||
Register maskTemp = ToRegister(lir->maskTemp());
|
||||
|
||||
Scalar::Type arrayType = lir->mir()->arrayType();
|
||||
int width = Scalar::byteSize(arrayType);
|
||||
|
||||
if (lir->index()->isConstant()) {
|
||||
Address dest(elements, ToInt32(lir->index()) * width);
|
||||
masm.compareExchangeToTypedIntArray(arrayType, dest, oldval, newval,
|
||||
temp, valueTemp, offsetTemp,
|
||||
maskTemp, output);
|
||||
} else {
|
||||
BaseIndex dest(elements, ToRegister(lir->index()),
|
||||
ScaleFromElemWidth(width));
|
||||
masm.compareExchangeToTypedIntArray(arrayType, dest, oldval, newval,
|
||||
temp, valueTemp, offsetTemp,
|
||||
maskTemp, output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorLoongArch64::visitAtomicExchangeTypedArrayElement(LAtomicExchangeTypedArrayElement* lir)
|
||||
{
|
||||
(void)lir;
|
||||
MOZ_CRASH("atomics are not supported on loongarch64 Ion yet");
|
||||
Register elements = ToRegister(lir->elements());
|
||||
AnyRegister output = ToAnyRegister(lir->output());
|
||||
Register temp = lir->temp()->isBogusTemp() ? InvalidReg
|
||||
: ToRegister(lir->temp());
|
||||
|
||||
Register value = ToRegister(lir->value());
|
||||
Register valueTemp = ToRegister(lir->valueTemp());
|
||||
Register offsetTemp = ToRegister(lir->offsetTemp());
|
||||
Register maskTemp = ToRegister(lir->maskTemp());
|
||||
|
||||
Scalar::Type arrayType = lir->mir()->arrayType();
|
||||
int width = Scalar::byteSize(arrayType);
|
||||
|
||||
if (lir->index()->isConstant()) {
|
||||
Address dest(elements, ToInt32(lir->index()) * width);
|
||||
masm.atomicExchangeToTypedIntArray(arrayType, dest, value, temp,
|
||||
valueTemp, offsetTemp, maskTemp,
|
||||
output);
|
||||
} else {
|
||||
BaseIndex dest(elements, ToRegister(lir->index()),
|
||||
ScaleFromElemWidth(width));
|
||||
masm.atomicExchangeToTypedIntArray(arrayType, dest, value, temp,
|
||||
valueTemp, offsetTemp, maskTemp,
|
||||
output);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,140 @@
|
|||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
namespace {
|
||||
|
||||
static inline void MoveAtomicValue(MacroAssemblerLOONGARCH64Compat& masm,
|
||||
Imm32 value, Register dest) {
|
||||
masm.move32(value, dest);
|
||||
}
|
||||
|
||||
static inline void MoveAtomicValue(MacroAssemblerLOONGARCH64Compat& masm,
|
||||
Register value, Register dest) {
|
||||
masm.move32(value, dest);
|
||||
}
|
||||
|
||||
static inline void SignExtendAtomicResult(MacroAssemblerLOONGARCH64Compat& masm,
|
||||
int nbytes, Register output) {
|
||||
switch (nbytes) {
|
||||
case 1:
|
||||
masm.as_ext_w_b(output, output);
|
||||
break;
|
||||
case 2:
|
||||
masm.as_ext_w_h(output, output);
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("unexpected atomic width");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline void PrepareAtomicAddress(
|
||||
MacroAssemblerLOONGARCH64Compat& masm, int nbytes, const T& address,
|
||||
Register offsetTemp, Register maskTemp) {
|
||||
masm.computeEffectiveAddress(address, ScratchRegister);
|
||||
masm.as_andi(offsetTemp, ScratchRegister, 3);
|
||||
masm.as_sub_d(ScratchRegister, ScratchRegister, offsetTemp);
|
||||
masm.as_slli_w(offsetTemp, offsetTemp, 3);
|
||||
masm.ma_li(maskTemp, Imm32(int32_t(UINT32_MAX >> ((4 - nbytes) * 8))));
|
||||
masm.as_sll_w(maskTemp, maskTemp, offsetTemp);
|
||||
}
|
||||
|
||||
template <typename S, typename T>
|
||||
static void AtomicFetchOpLoongArch64(MacroAssemblerLOONGARCH64Compat& masm,
|
||||
int nbytes, bool signExtend, AtomicOp op,
|
||||
const S& value, const T& address,
|
||||
Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, Register output) {
|
||||
Label again;
|
||||
|
||||
PrepareAtomicAddress(masm, nbytes, address, offsetTemp, maskTemp);
|
||||
|
||||
masm.bind(&again);
|
||||
masm.as_dbar(0);
|
||||
masm.as_ll_w(SecondScratchReg, ScratchRegister, 0);
|
||||
|
||||
if (output != InvalidReg) {
|
||||
masm.as_and(output, SecondScratchReg, maskTemp);
|
||||
masm.as_srl_w(output, output, offsetTemp);
|
||||
if (signExtend) {
|
||||
SignExtendAtomicResult(masm, nbytes, output);
|
||||
}
|
||||
}
|
||||
|
||||
MoveAtomicValue(masm, value, valueTemp);
|
||||
masm.as_sll_w(valueTemp, valueTemp, offsetTemp);
|
||||
|
||||
switch (op) {
|
||||
case AtomicFetchAddOp:
|
||||
masm.as_add_w(valueTemp, SecondScratchReg, valueTemp);
|
||||
break;
|
||||
case AtomicFetchSubOp:
|
||||
masm.as_sub_w(valueTemp, SecondScratchReg, valueTemp);
|
||||
break;
|
||||
case AtomicFetchAndOp:
|
||||
masm.as_and(valueTemp, SecondScratchReg, valueTemp);
|
||||
break;
|
||||
case AtomicFetchOrOp:
|
||||
masm.as_or(valueTemp, SecondScratchReg, valueTemp);
|
||||
break;
|
||||
case AtomicFetchXorOp:
|
||||
masm.as_xor(valueTemp, SecondScratchReg, valueTemp);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("unexpected atomic op");
|
||||
}
|
||||
|
||||
masm.as_and(valueTemp, valueTemp, maskTemp);
|
||||
masm.as_or(SecondScratchReg, SecondScratchReg, maskTemp);
|
||||
masm.as_xor(SecondScratchReg, SecondScratchReg, maskTemp);
|
||||
masm.as_or(SecondScratchReg, SecondScratchReg, valueTemp);
|
||||
masm.as_sc_w(SecondScratchReg, ScratchRegister, 0);
|
||||
masm.ma_b(SecondScratchReg, SecondScratchReg, &again, Assembler::Zero,
|
||||
ShortJump);
|
||||
masm.as_dbar(0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void CompareExchangeLoongArch64(
|
||||
MacroAssemblerLOONGARCH64Compat& masm, int nbytes, bool signExtend,
|
||||
const T& address, Register oldval, Register newval, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp, Register output) {
|
||||
Label again, done;
|
||||
|
||||
PrepareAtomicAddress(masm, nbytes, address, offsetTemp, maskTemp);
|
||||
|
||||
masm.bind(&again);
|
||||
masm.as_dbar(0);
|
||||
masm.as_ll_w(SecondScratchReg, ScratchRegister, 0);
|
||||
|
||||
masm.as_and(output, SecondScratchReg, maskTemp);
|
||||
masm.as_srl_w(output, output, offsetTemp);
|
||||
if (signExtend) {
|
||||
SignExtendAtomicResult(masm, nbytes, output);
|
||||
}
|
||||
|
||||
if (oldval != InvalidReg) {
|
||||
masm.ma_b(output, oldval, &done, Assembler::NotEqual, ShortJump);
|
||||
}
|
||||
|
||||
masm.move32(newval, valueTemp);
|
||||
masm.as_sll_w(valueTemp, valueTemp, offsetTemp);
|
||||
masm.as_and(valueTemp, valueTemp, maskTemp);
|
||||
masm.as_or(SecondScratchReg, SecondScratchReg, maskTemp);
|
||||
masm.as_xor(SecondScratchReg, SecondScratchReg, maskTemp);
|
||||
masm.as_or(SecondScratchReg, SecondScratchReg, valueTemp);
|
||||
masm.as_sc_w(SecondScratchReg, ScratchRegister, 0);
|
||||
masm.ma_b(SecondScratchReg, SecondScratchReg, &again, Assembler::Zero,
|
||||
ShortJump);
|
||||
masm.as_dbar(0);
|
||||
|
||||
masm.bind(&done);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void MacroAssembler::alignFrameForICArguments(AfterICSaveLive& aic) {
|
||||
if (framePushed() % ABIStackAlignment != 0) {
|
||||
aic.alignmentPadding = ABIStackAlignment - (framePushed() % ABIStackAlignment);
|
||||
|
|
@ -3244,6 +3378,246 @@ void MacroAssemblerLOONGARCH64Compat::storePtr(Register src, AbsoluteAddress des
|
|||
storePtr(src, Address(scratch, 0));
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicEffectOp(
|
||||
int nbytes, AtomicOp op, Imm32 value, const Address& address,
|
||||
Register valueTemp, Register offsetTemp, Register maskTemp) {
|
||||
AtomicFetchOpLoongArch64(*this, nbytes, false, op, value, address, valueTemp,
|
||||
offsetTemp, maskTemp, InvalidReg);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicEffectOp(
|
||||
int nbytes, AtomicOp op, Imm32 value, const BaseIndex& address,
|
||||
Register valueTemp, Register offsetTemp, Register maskTemp) {
|
||||
AtomicFetchOpLoongArch64(*this, nbytes, false, op, value, address, valueTemp,
|
||||
offsetTemp, maskTemp, InvalidReg);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicEffectOp(
|
||||
int nbytes, AtomicOp op, Register value, const Address& address,
|
||||
Register valueTemp, Register offsetTemp, Register maskTemp) {
|
||||
AtomicFetchOpLoongArch64(*this, nbytes, false, op, value, address, valueTemp,
|
||||
offsetTemp, maskTemp, InvalidReg);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicEffectOp(
|
||||
int nbytes, AtomicOp op, Register value, const BaseIndex& address,
|
||||
Register valueTemp, Register offsetTemp, Register maskTemp) {
|
||||
AtomicFetchOpLoongArch64(*this, nbytes, false, op, value, address, valueTemp,
|
||||
offsetTemp, maskTemp, InvalidReg);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicFetchOp(
|
||||
int nbytes, bool signExtend, AtomicOp op, Imm32 value,
|
||||
const Address& address, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, Register output) {
|
||||
AtomicFetchOpLoongArch64(*this, nbytes, signExtend, op, value, address,
|
||||
valueTemp, offsetTemp, maskTemp, output);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicFetchOp(
|
||||
int nbytes, bool signExtend, AtomicOp op, Imm32 value,
|
||||
const BaseIndex& address, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, Register output) {
|
||||
AtomicFetchOpLoongArch64(*this, nbytes, signExtend, op, value, address,
|
||||
valueTemp, offsetTemp, maskTemp, output);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicFetchOp(
|
||||
int nbytes, bool signExtend, AtomicOp op, Register value,
|
||||
const Address& address, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, Register output) {
|
||||
AtomicFetchOpLoongArch64(*this, nbytes, signExtend, op, value, address,
|
||||
valueTemp, offsetTemp, maskTemp, output);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicFetchOp(
|
||||
int nbytes, bool signExtend, AtomicOp op, Register value,
|
||||
const BaseIndex& address, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, Register output) {
|
||||
AtomicFetchOpLoongArch64(*this, nbytes, signExtend, op, value, address,
|
||||
valueTemp, offsetTemp, maskTemp, output);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::compareExchange(
|
||||
int nbytes, bool signExtend, const Address& address, Register oldval,
|
||||
Register newval, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, Register output) {
|
||||
CompareExchangeLoongArch64(*this, nbytes, signExtend, address, oldval,
|
||||
newval, valueTemp, offsetTemp, maskTemp, output);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::compareExchange(
|
||||
int nbytes, bool signExtend, const BaseIndex& address, Register oldval,
|
||||
Register newval, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, Register output) {
|
||||
CompareExchangeLoongArch64(*this, nbytes, signExtend, address, oldval,
|
||||
newval, valueTemp, offsetTemp, maskTemp, output);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::compareExchangeToTypedIntArray(
|
||||
Scalar::Type arrayType, const Address& mem, Register oldval,
|
||||
Register newval, Register temp, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, AnyRegister output) {
|
||||
switch (arrayType) {
|
||||
case Scalar::Int8:
|
||||
compareExchange(1, true, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Uint8:
|
||||
compareExchange(1, false, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Int16:
|
||||
compareExchange(2, true, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Uint16:
|
||||
compareExchange(2, false, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Int32:
|
||||
compareExchange(4, false, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Uint32:
|
||||
MOZ_ASSERT(output.isFloat());
|
||||
MOZ_ASSERT(temp != InvalidReg);
|
||||
compareExchange(4, false, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, temp);
|
||||
convertUInt32ToDouble(temp, output.fpu());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid typed array type");
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::compareExchangeToTypedIntArray(
|
||||
Scalar::Type arrayType, const BaseIndex& mem, Register oldval,
|
||||
Register newval, Register temp, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, AnyRegister output) {
|
||||
switch (arrayType) {
|
||||
case Scalar::Int8:
|
||||
compareExchange(1, true, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Uint8:
|
||||
compareExchange(1, false, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Int16:
|
||||
compareExchange(2, true, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Uint16:
|
||||
compareExchange(2, false, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Int32:
|
||||
compareExchange(4, false, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, output.gpr());
|
||||
break;
|
||||
case Scalar::Uint32:
|
||||
MOZ_ASSERT(output.isFloat());
|
||||
MOZ_ASSERT(temp != InvalidReg);
|
||||
compareExchange(4, false, mem, oldval, newval, valueTemp, offsetTemp,
|
||||
maskTemp, temp);
|
||||
convertUInt32ToDouble(temp, output.fpu());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid typed array type");
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicExchange(
|
||||
int nbytes, bool signExtend, const Address& address, Register value,
|
||||
Register valueTemp, Register offsetTemp, Register maskTemp,
|
||||
Register output) {
|
||||
CompareExchangeLoongArch64(*this, nbytes, signExtend, address, InvalidReg,
|
||||
value, valueTemp, offsetTemp, maskTemp, output);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicExchange(
|
||||
int nbytes, bool signExtend, const BaseIndex& address, Register value,
|
||||
Register valueTemp, Register offsetTemp, Register maskTemp,
|
||||
Register output) {
|
||||
CompareExchangeLoongArch64(*this, nbytes, signExtend, address, InvalidReg,
|
||||
value, valueTemp, offsetTemp, maskTemp, output);
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicExchangeToTypedIntArray(
|
||||
Scalar::Type arrayType, const Address& mem, Register value, Register temp,
|
||||
Register valueTemp, Register offsetTemp, Register maskTemp,
|
||||
AnyRegister output) {
|
||||
switch (arrayType) {
|
||||
case Scalar::Int8:
|
||||
atomicExchange(1, true, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
output.gpr());
|
||||
break;
|
||||
case Scalar::Uint8:
|
||||
atomicExchange(1, false, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
output.gpr());
|
||||
break;
|
||||
case Scalar::Int16:
|
||||
atomicExchange(2, true, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
output.gpr());
|
||||
break;
|
||||
case Scalar::Uint16:
|
||||
atomicExchange(2, false, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
output.gpr());
|
||||
break;
|
||||
case Scalar::Int32:
|
||||
atomicExchange(4, false, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
output.gpr());
|
||||
break;
|
||||
case Scalar::Uint32:
|
||||
MOZ_ASSERT(output.isFloat());
|
||||
MOZ_ASSERT(temp != InvalidReg);
|
||||
atomicExchange(4, false, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
temp);
|
||||
convertUInt32ToDouble(temp, output.fpu());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid typed array type");
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::atomicExchangeToTypedIntArray(
|
||||
Scalar::Type arrayType, const BaseIndex& mem, Register value,
|
||||
Register temp, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, AnyRegister output) {
|
||||
switch (arrayType) {
|
||||
case Scalar::Int8:
|
||||
atomicExchange(1, true, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
output.gpr());
|
||||
break;
|
||||
case Scalar::Uint8:
|
||||
atomicExchange(1, false, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
output.gpr());
|
||||
break;
|
||||
case Scalar::Int16:
|
||||
atomicExchange(2, true, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
output.gpr());
|
||||
break;
|
||||
case Scalar::Uint16:
|
||||
atomicExchange(2, false, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
output.gpr());
|
||||
break;
|
||||
case Scalar::Int32:
|
||||
atomicExchange(4, false, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
output.gpr());
|
||||
break;
|
||||
case Scalar::Uint32:
|
||||
MOZ_ASSERT(output.isFloat());
|
||||
MOZ_ASSERT(temp != InvalidReg);
|
||||
atomicExchange(4, false, mem, value, valueTemp, offsetTemp, maskTemp,
|
||||
temp);
|
||||
convertUInt32ToDouble(temp, output.fpu());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid typed array type");
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssemblerLOONGARCH64Compat::testNullSet(Condition cond,
|
||||
const ValueOperand& value,
|
||||
Register dest) {
|
||||
|
|
|
|||
|
|
@ -1272,6 +1272,66 @@ class MacroAssemblerLOONGARCH64Compat : public MacroAssemblerLOONGARCH64 {
|
|||
void storePtr(Register src, const BaseIndex& address);
|
||||
void storePtr(Register src, AbsoluteAddress dest);
|
||||
|
||||
void atomicEffectOp(int nbytes, AtomicOp op, Imm32 value,
|
||||
const Address& address, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp);
|
||||
void atomicEffectOp(int nbytes, AtomicOp op, Imm32 value,
|
||||
const BaseIndex& address, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp);
|
||||
void atomicEffectOp(int nbytes, AtomicOp op, Register value,
|
||||
const Address& address, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp);
|
||||
void atomicEffectOp(int nbytes, AtomicOp op, Register value,
|
||||
const BaseIndex& address, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp);
|
||||
|
||||
void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, Imm32 value,
|
||||
const Address& address, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp, Register output);
|
||||
void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, Imm32 value,
|
||||
const BaseIndex& address, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp, Register output);
|
||||
void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, Register value,
|
||||
const Address& address, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp, Register output);
|
||||
void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, Register value,
|
||||
const BaseIndex& address, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp, Register output);
|
||||
|
||||
void compareExchange(int nbytes, bool signExtend, const Address& address,
|
||||
Register oldval, Register newval, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp, Register output);
|
||||
void compareExchange(int nbytes, bool signExtend, const BaseIndex& address,
|
||||
Register oldval, Register newval, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp, Register output);
|
||||
void compareExchangeToTypedIntArray(Scalar::Type arrayType,
|
||||
const Address& mem, Register oldval,
|
||||
Register newval, Register temp,
|
||||
Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, AnyRegister output);
|
||||
void compareExchangeToTypedIntArray(Scalar::Type arrayType,
|
||||
const BaseIndex& mem, Register oldval,
|
||||
Register newval, Register temp,
|
||||
Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, AnyRegister output);
|
||||
|
||||
void atomicExchange(int nbytes, bool signExtend, const Address& address,
|
||||
Register value, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, Register output);
|
||||
void atomicExchange(int nbytes, bool signExtend, const BaseIndex& address,
|
||||
Register value, Register valueTemp, Register offsetTemp,
|
||||
Register maskTemp, Register output);
|
||||
void atomicExchangeToTypedIntArray(Scalar::Type arrayType,
|
||||
const Address& mem, Register value,
|
||||
Register temp, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp,
|
||||
AnyRegister output);
|
||||
void atomicExchangeToTypedIntArray(Scalar::Type arrayType,
|
||||
const BaseIndex& mem, Register value,
|
||||
Register temp, Register valueTemp,
|
||||
Register offsetTemp, Register maskTemp,
|
||||
AnyRegister output);
|
||||
|
||||
void moveDouble(FloatRegister src, FloatRegister dest) {
|
||||
as_fmov_d(dest, src);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue