[a64] Implement armv8.0 atomic operations
Uses LSE when available, but provides an armv8.0 baseline implementation.
This commit is contained in:
parent
4655bc1633
commit
151700d830
|
@ -195,16 +195,38 @@ struct ATOMIC_COMPARE_EXCHANGE_I32
|
||||||
}
|
}
|
||||||
e.ADD(X1, e.GetMembaseReg(), X1);
|
e.ADD(X1, e.GetMembaseReg(), X1);
|
||||||
|
|
||||||
|
const XReg address = X1;
|
||||||
const WReg expected = i.src2;
|
const WReg expected = i.src2;
|
||||||
const WReg desired = i.src3;
|
const WReg desired = i.src3;
|
||||||
const WReg status = W0;
|
const WReg status = W0;
|
||||||
|
|
||||||
|
if (e.IsFeatureEnabled(kA64EmitLSE)) {
|
||||||
e.MOV(status, expected);
|
e.MOV(status, expected);
|
||||||
|
|
||||||
// if([C] == A) [C] = B
|
// if([C] == A) [C] = B
|
||||||
// else A = [C]
|
// else A = [C]
|
||||||
e.CASAL(status, desired, X1);
|
e.CASAL(status, desired, address);
|
||||||
e.CMP(status, expected);
|
e.CMP(status, expected);
|
||||||
e.CSET(i.dest, Cond::EQ);
|
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct ATOMIC_COMPARE_EXCHANGE_I64
|
struct ATOMIC_COMPARE_EXCHANGE_I64
|
||||||
|
@ -223,16 +245,38 @@ struct ATOMIC_COMPARE_EXCHANGE_I64
|
||||||
}
|
}
|
||||||
e.ADD(X1, e.GetMembaseReg(), X1);
|
e.ADD(X1, e.GetMembaseReg(), X1);
|
||||||
|
|
||||||
|
const XReg address = X1;
|
||||||
const XReg expected = i.src2;
|
const XReg expected = i.src2;
|
||||||
const XReg desired = i.src3;
|
const XReg desired = i.src3;
|
||||||
const XReg status = X0;
|
const XReg status = X0;
|
||||||
|
|
||||||
|
if (e.IsFeatureEnabled(kA64EmitLSE)) {
|
||||||
e.MOV(status, expected);
|
e.MOV(status, expected);
|
||||||
|
|
||||||
// if([C] == A) [C] = B
|
// if([C] == A) [C] = B
|
||||||
// else A = [C]
|
// else A = [C]
|
||||||
e.CASAL(status, desired, X1);
|
e.CASAL(status, desired, address);
|
||||||
e.CMP(status, expected);
|
e.CMP(status, expected);
|
||||||
e.CSET(i.dest, Cond::EQ);
|
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
EMITTER_OPCODE_TABLE(OPCODE_ATOMIC_COMPARE_EXCHANGE,
|
EMITTER_OPCODE_TABLE(OPCODE_ATOMIC_COMPARE_EXCHANGE,
|
||||||
|
|
Loading…
Reference in New Issue