Commit 93169821 authored by Ivica Bogosavljevic's avatar Ivica Bogosavljevic Committed by Commit Bot

MIPS: Implement AtomicPairCompareExchange through runtime

MIPS32r2 doesn't have load-linked/store-conditional instructions
that work with 64-bit values and these are now implemented through
runtime.

TEST=mjsunit/wasm/compare-exchange64-stress

Change-Id: I70d8a454dcbbdac6f30e30ec3ac0eb4d429ef62e
Reviewed-on: https://chromium-review.googlesource.com/c/1296211
Commit-Queue: Ivica Bogosavljevic <ibogosavljevic@wavecomp.com>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57138}
parent bd39d922
...@@ -1772,8 +1772,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -1772,8 +1772,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ATOMIC64_BINOP_LOGIC_CASE(Xor, XorPair) ATOMIC64_BINOP_LOGIC_CASE(Xor, XorPair)
#undef ATOMIC64_BINOP_LOGIC_CASE #undef ATOMIC64_BINOP_LOGIC_CASE
case kMipsWord32AtomicPairExchange: case kMipsWord32AtomicPairExchange:
case kMipsWord32AtomicPairCompareExchange: UNREACHABLE();
break;
case kMipsWord32AtomicPairCompareExchange: {
FrameScope scope(tasm(), StackFrame::MANUAL);
__ PushCallerSaved(kDontSaveFPRegs, v0, v1);
__ PrepareCallCFunction(5, 0, kScratchReg);
__ addu(a0, i.InputRegister(0), i.InputRegister(1));
__ sw(i.InputRegister(5), MemOperand(sp, 16));
__ CallCFunction(
ExternalReference::atomic_pair_compare_exchange_function(), 5, 0);
__ PopCallerSaved(kDontSaveFPRegs, v0, v1);
break; break;
}
case kMipsS128Zero: { case kMipsS128Zero: {
CpuFeatureScope msa_scope(tasm(), MIPS_SIMD); CpuFeatureScope msa_scope(tasm(), MIPS_SIMD);
__ xor_v(i.OutputSimd128Register(), i.OutputSimd128Register(), __ xor_v(i.OutputSimd128Register(), i.OutputSimd128Register(),
......
...@@ -760,7 +760,32 @@ void InstructionSelector::VisitWord32AtomicPairExchange(Node* node) { ...@@ -760,7 +760,32 @@ void InstructionSelector::VisitWord32AtomicPairExchange(Node* node) {
} }
void InstructionSelector::VisitWord32AtomicPairCompareExchange(Node* node) { void InstructionSelector::VisitWord32AtomicPairCompareExchange(Node* node) {
VisitPairAtomicBinop(this, node, kMipsWord32AtomicPairCompareExchange); MipsOperandGenerator g(this);
InstructionOperand inputs[] = {
g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)),
g.UseFixed(node->InputAt(2), a1), g.UseFixed(node->InputAt(3), a2),
g.UseFixed(node->InputAt(4), a3), g.UseUniqueRegister(node->InputAt(5))};
InstructionCode code = kMipsWord32AtomicPairCompareExchange |
AddressingModeField::encode(kMode_MRI);
Node* projection0 = NodeProperties::FindProjection(node, 0);
Node* projection1 = NodeProperties::FindProjection(node, 1);
if (projection1) {
InstructionOperand outputs[] = {g.DefineAsFixed(projection0, v0),
g.DefineAsFixed(projection1, v1)};
InstructionOperand temps[] = {g.TempRegister(a0)};
Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs,
arraysize(temps), temps);
} else if (projection0) {
InstructionOperand outputs[] = {g.DefineAsFixed(projection0, v0)};
InstructionOperand temps[] = {g.TempRegister(a0), g.TempRegister(v1)};
Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs,
arraysize(temps), temps);
} else {
InstructionOperand temps[] = {g.TempRegister(a0), g.TempRegister(v0),
g.TempRegister(v1)};
Emit(code, 0, nullptr, arraysize(inputs), inputs, arraysize(temps), temps);
}
} }
void InstructionSelector::VisitWord32ReverseBits(Node* node) { UNREACHABLE(); } void InstructionSelector::VisitWord32ReverseBits(Node* node) { UNREACHABLE(); }
......
...@@ -975,6 +975,25 @@ ExternalReference ExternalReference::fixed_typed_array_base_data_offset() { ...@@ -975,6 +975,25 @@ ExternalReference ExternalReference::fixed_typed_array_base_data_offset() {
FixedTypedArrayBase::kDataOffset - kHeapObjectTag)); FixedTypedArrayBase::kDataOffset - kHeapObjectTag));
} }
static uint64_t atomic_pair_compare_exchange(intptr_t address,
int old_value_low,
int old_value_high,
int new_value_low,
int new_value_high) {
uint64_t old_value = static_cast<uint64_t>(old_value_high) << 32 |
(old_value_low & 0xFFFFFFFF);
uint64_t new_value = static_cast<uint64_t>(new_value_high) << 32 |
(new_value_low & 0xFFFFFFFF);
std::atomic_compare_exchange_strong(
reinterpret_cast<std::atomic<uint64_t>*>(address), &old_value, new_value);
return old_value;
}
ExternalReference ExternalReference::atomic_pair_compare_exchange_function() {
return ExternalReference(
Redirect(FUNCTION_ADDR(atomic_pair_compare_exchange)));
}
bool operator==(ExternalReference lhs, ExternalReference rhs) { bool operator==(ExternalReference lhs, ExternalReference rhs) {
return lhs.address() == rhs.address(); return lhs.address() == rhs.address();
} }
......
...@@ -177,6 +177,8 @@ class StatsCounter; ...@@ -177,6 +177,8 @@ class StatsCounter;
V(wasm_word32_ror, "wasm::word32_ror") \ V(wasm_word32_ror, "wasm::word32_ror") \
V(wasm_word64_ctz, "wasm::word64_ctz") \ V(wasm_word64_ctz, "wasm::word64_ctz") \
V(wasm_word64_popcnt, "wasm::word64_popcnt") \ V(wasm_word64_popcnt, "wasm::word64_popcnt") \
V(atomic_pair_compare_exchange_function, \
"atomic_pair_compare_exchange_function") \
EXTERNAL_REFERENCE_LIST_INTL(V) EXTERNAL_REFERENCE_LIST_INTL(V)
#ifndef V8_INTERPRETED_REGEXP #ifndef V8_INTERPRETED_REGEXP
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment