[a64] Implement armv8.0 atomic operations

Uses LSE when available, but provides an armv8.0 baseline implementation.
This commit is contained in:
Wunkolo 2024-05-29 10:54:31 -07:00
parent 4655bc1633
commit 151700d830
1 changed files with 54 additions and 10 deletions

View File

@ -195,15 +195,37 @@ struct ATOMIC_COMPARE_EXCHANGE_I32
}
e.ADD(X1, e.GetMembaseReg(), X1);
const XReg address = X1;
const WReg expected = i.src2;
const WReg desired = i.src3;
const WReg status = W0;
e.MOV(status, expected);
// if([C] == A) [C] = B
// else A = [C]
e.CASAL(status, desired, X1);
e.CMP(status, expected);
if (e.IsFeatureEnabled(kA64EmitLSE)) {
e.MOV(status, expected);
// if([C] == A) [C] = B
// else A = [C]
e.CASAL(status, desired, address);
e.CMP(status, expected);
e.CSET(i.dest, Cond::EQ);
return;
}
oaknut::Label success, fail, retry;
e.l(retry);
e.LDAXR(W4, address);
e.CMP(W4, expected);
e.B(Cond::NE, fail);
e.STLXR(status.toW(), desired, address);
e.CBNZ(status, retry);
e.B(success);
e.l(fail);
e.CLREX();
e.l(success);
e.CSET(i.dest, Cond::EQ);
}
};
@ -223,15 +245,37 @@ struct ATOMIC_COMPARE_EXCHANGE_I64
}
e.ADD(X1, e.GetMembaseReg(), X1);
const XReg address = X1;
const XReg expected = i.src2;
const XReg desired = i.src3;
const XReg status = X0;
e.MOV(status, expected);
// if([C] == A) [C] = B
// else A = [C]
e.CASAL(status, desired, X1);
e.CMP(status, expected);
if (e.IsFeatureEnabled(kA64EmitLSE)) {
e.MOV(status, expected);
// if([C] == A) [C] = B
// else A = [C]
e.CASAL(status, desired, address);
e.CMP(status, expected);
e.CSET(i.dest, Cond::EQ);
return;
}
oaknut::Label success, fail, retry;
e.l(retry);
e.LDAXR(X4, address);
e.CMP(X4, expected);
e.B(Cond::NE, fail);
e.STLXR(status.toW(), desired, address);
e.CBNZ(status, retry);
e.B(success);
e.l(fail);
e.CLREX();
e.l(success);
e.CSET(i.dest, Cond::EQ);
}
};