x64: port atomic_cas to ISLE (#4223)
This commit is contained in:
@@ -1058,6 +1058,11 @@
|
|||||||
(decl encode_fcmp_imm (FcmpImm) u8)
|
(decl encode_fcmp_imm (FcmpImm) u8)
|
||||||
(extern constructor encode_fcmp_imm encode_fcmp_imm)
|
(extern constructor encode_fcmp_imm encode_fcmp_imm)
|
||||||
|
|
||||||
|
;;;; Registers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(decl rax () WritableGpr)
|
||||||
|
(extern constructor rax rax)
|
||||||
|
|
||||||
;;;; Newtypes for Different Register Classes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;; Newtypes for Different Register Classes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(type Gpr (primitive Gpr))
|
(type Gpr (primitive Gpr))
|
||||||
@@ -2876,6 +2881,11 @@
|
|||||||
(rule (x64_mfence)
|
(rule (x64_mfence)
|
||||||
(SideEffectNoResult.Inst (MInst.Fence (FenceKind.MFence))))
|
(SideEffectNoResult.Inst (MInst.Fence (FenceKind.MFence))))
|
||||||
|
|
||||||
|
(decl x64_cmpxchg (Type Gpr Gpr SyntheticAmode) Gpr)
|
||||||
|
(rule (x64_cmpxchg ty expected replacement addr)
|
||||||
|
(let ((_ Unit (emit (MInst.LockCmpxchg ty replacement expected addr (rax)))))
|
||||||
|
(rax)))
|
||||||
|
|
||||||
;;;; Automatic conversions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;; Automatic conversions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(convert Gpr InstOutput output_gpr)
|
(convert Gpr InstOutput output_gpr)
|
||||||
|
|||||||
@@ -2812,3 +2812,9 @@
|
|||||||
(side_effect (side_effect_concat
|
(side_effect (side_effect_concat
|
||||||
(x64_movrm ty (to_amode flags address (zero_offset)) value)
|
(x64_movrm ty (to_amode flags address (zero_offset)) value)
|
||||||
(x64_mfence))))
|
(x64_mfence))))
|
||||||
|
|
||||||
|
;; Rules for `atomic_cas` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
(rule (lower (has_type (and (fits_in_64 ty) (ty_int _))
|
||||||
|
(atomic_cas flags address expected replacement)))
|
||||||
|
(x64_cmpxchg ty expected replacement (to_amode flags address (zero_offset))))
|
||||||
|
|||||||
@@ -2205,32 +2205,7 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Opcode::AtomicCas => {
|
Opcode::AtomicCas => {
|
||||||
// This is very similar to, but not identical to, the `AtomicRmw` case. As with
|
implemented_in_isle(ctx);
|
||||||
// `AtomicRmw`, there's no need to zero-extend narrow values here.
|
|
||||||
let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
|
|
||||||
let addr = lower_to_amode(ctx, inputs[0], 0);
|
|
||||||
let expected = put_input_in_reg(ctx, inputs[1]);
|
|
||||||
let replacement = put_input_in_reg(ctx, inputs[2]);
|
|
||||||
let ty_access = ty.unwrap();
|
|
||||||
assert!(is_valid_atomic_transaction_ty(ty_access));
|
|
||||||
|
|
||||||
// Move the expected value into %rax. Because there's only one fixed register on
|
|
||||||
// the input side, we don't have to use `ensure_in_vreg`, as is necessary in the
|
|
||||||
// `AtomicRmw` case.
|
|
||||||
ctx.emit(Inst::gen_move(
|
|
||||||
Writable::from_reg(regs::rax()),
|
|
||||||
expected,
|
|
||||||
types::I64,
|
|
||||||
));
|
|
||||||
ctx.emit(Inst::LockCmpxchg {
|
|
||||||
ty: ty_access,
|
|
||||||
mem: addr.into(),
|
|
||||||
replacement,
|
|
||||||
expected: regs::rax(),
|
|
||||||
dst_old: Writable::from_reg(regs::rax()),
|
|
||||||
});
|
|
||||||
// And finally, copy the old value at the location to its destination reg.
|
|
||||||
ctx.emit(Inst::gen_move(dst, regs::rax(), types::I64));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Opcode::AtomicLoad => {
|
Opcode::AtomicLoad => {
|
||||||
|
|||||||
@@ -547,6 +547,12 @@ where
|
|||||||
fn zero_offset(&mut self) -> Offset32 {
|
fn zero_offset(&mut self) -> Offset32 {
|
||||||
Offset32::new(0)
|
Offset32::new(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rax(&mut self) -> WritableGpr {
|
||||||
|
let gpr = Gpr::new(regs::rax()).unwrap();
|
||||||
|
WritableGpr::from_reg(gpr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since x64 doesn't have 8x16 shifts and we must use a 16x8 shift instead, we
|
// Since x64 doesn't have 8x16 shifts and we must use a 16x8 shift instead, we
|
||||||
|
|||||||
Reference in New Issue
Block a user