Use atomic compare exchange in stdcx/stwcx (still under the global lock)

This commit is contained in:
Dr. Chat 2016-01-13 01:45:31 -06:00
parent 51dde62f09
commit f0802d75fa
4 changed files with 22 additions and 6 deletions

View File

@ -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;

View File

@ -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());

View File

@ -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

View File

@ -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);