Use atomic compare exchange in stdcx/stwcx (still under the global lock)
This commit is contained in:
parent
51dde62f09
commit
f0802d75fa
|
@ -423,8 +423,8 @@ typedef struct PPCContext_s {
|
|||
|
||||
uint8_t* physical_membase;
|
||||
|
||||
// Keep the struct padded out to 64b total.
|
||||
uint8_t _padding[8];
|
||||
// Value of last reserved load
|
||||
uint64_t reserved_val;
|
||||
|
||||
static std::string GetRegisterName(PPCRegister reg);
|
||||
std::string GetStringFromValue(PPCRegister reg) const;
|
||||
|
|
|
@ -658,6 +658,7 @@ int InstrEmit_ldarx(PPCHIRBuilder& f, const InstrData& i) {
|
|||
|
||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||
Value* rt = f.ByteSwap(f.Load(ea, INT64_TYPE));
|
||||
f.StoreReserved(rt);
|
||||
f.StoreGPR(i.X.RT, rt);
|
||||
return 0;
|
||||
}
|
||||
|
@ -682,6 +683,7 @@ int InstrEmit_lwarx(PPCHIRBuilder& f, const InstrData& i) {
|
|||
|
||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||
Value* rt = f.ZeroExtend(f.ByteSwap(f.Load(ea, INT32_TYPE)), INT64_TYPE);
|
||||
f.StoreReserved(rt);
|
||||
f.StoreGPR(i.X.RT, rt);
|
||||
return 0;
|
||||
}
|
||||
|
@ -703,8 +705,9 @@ int InstrEmit_stdcx(PPCHIRBuilder& f, const InstrData& i) {
|
|||
|
||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||
Value* rt = f.ByteSwap(f.LoadGPR(i.X.RT));
|
||||
f.Store(ea, rt);
|
||||
f.StoreContext(offsetof(PPCContext, cr0.cr0_eq), f.LoadConstantInt8(1));
|
||||
Value* res = f.ByteSwap(f.LoadReserved());
|
||||
Value* v = f.AtomicCompareExchange(ea, res, rt);
|
||||
f.StoreContext(offsetof(PPCContext, cr0.cr0_eq), v);
|
||||
f.StoreContext(offsetof(PPCContext, cr0.cr0_lt), f.LoadZeroInt8());
|
||||
f.StoreContext(offsetof(PPCContext, cr0.cr0_gt), f.LoadZeroInt8());
|
||||
|
||||
|
@ -732,8 +735,9 @@ int InstrEmit_stwcx(PPCHIRBuilder& f, const InstrData& i) {
|
|||
|
||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||
Value* rt = f.ByteSwap(f.Truncate(f.LoadGPR(i.X.RT), INT32_TYPE));
|
||||
f.Store(ea, rt);
|
||||
f.StoreContext(offsetof(PPCContext, cr0.cr0_eq), f.LoadConstantInt8(1));
|
||||
Value* res = f.ByteSwap(f.Truncate(f.LoadReserved(), INT32_TYPE));
|
||||
Value* v = f.AtomicCompareExchange(ea, res, rt);
|
||||
f.StoreContext(offsetof(PPCContext, cr0.cr0_eq), v);
|
||||
f.StoreContext(offsetof(PPCContext, cr0.cr0_lt), f.LoadZeroInt8());
|
||||
f.StoreContext(offsetof(PPCContext, cr0.cr0_gt), f.LoadZeroInt8());
|
||||
|
||||
|
|
|
@ -511,6 +511,15 @@ void PPCHIRBuilder::StoreVR(uint32_t reg, Value* value) {
|
|||
trace_reg.value = value;
|
||||
}
|
||||
|
||||
void PPCHIRBuilder::StoreReserved(Value* val) {
|
||||
assert_true(val->type == INT64_TYPE);
|
||||
StoreContext(offsetof(PPCContext, reserved_val), val);
|
||||
}
|
||||
|
||||
Value* PPCHIRBuilder::LoadReserved() {
|
||||
return LoadContext(offsetof(PPCContext, reserved_val), INT64_TYPE);
|
||||
}
|
||||
|
||||
} // namespace ppc
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
|
|
@ -78,6 +78,9 @@ class PPCHIRBuilder : public hir::HIRBuilder {
|
|||
Value* LoadVR(uint32_t reg);
|
||||
void StoreVR(uint32_t reg, Value* value);
|
||||
|
||||
void StoreReserved(Value* val);
|
||||
Value* LoadReserved();
|
||||
|
||||
private:
|
||||
void AnnotateLabel(uint32_t address, Label* label);
|
||||
|
||||
|
|
Loading…
Reference in New Issue