(** Memory accesses *)

(* Specifications: *)
Lemma indexed_memory_access_correct:
forall mk_instr base ofs k rs m,
base <> X31 ->
exists base' ofs' rs',
exec_straight_opt (indexed_memory_access mk_instr base ofs k) rs m
(mk_instr base' ofs' :: k) rs' m
/\ Val.offset_ptr rs'#base' (eval_offset ge ofs') = Val.offset_ptr rs#base ofs
/\ forall r, r <> PC -> r <> X31 -> rs'#r = rs#r.
Lemma indexed_load_access_correct:
forall chunk (mk_instr: ireg -> offset -> instruction) rd m,
(forall base ofs rs,
exec_instr ge fn (mk_instr base ofs) rs m = exec_load ge chunk rs m rd base ofs) ->
forall (base: ireg) ofs k (rs: regset) v,
Mem.loadv chunk m (Val.offset_ptr rs#base ofs) = Some v ->
base <> X31 -> rd <> PC ->
exists rs',
exec_straight ge fn (indexed_memory_access mk_instr base ofs k) rs m k rs' m
/\ rs'#rd = v
/\ forall r, r <> PC -> r <> X31 -> r <> rd -> rs'#r = rs#r.
Lemma indexed_store_access_correct:
forall chunk (mk_instr: ireg -> offset -> instruction) r1 m,
(forall base ofs rs,
exec_instr ge fn (mk_instr base ofs) rs m = exec_store ge chunk rs m r1 base ofs) ->
forall (base: ireg) ofs k (rs: regset) m',
Mem.storev chunk m (Val.offset_ptr rs#base ofs) (rs#r1) = Some m' ->
base <> X31 -> r1 <> X31 -> r1 <> PC ->
exists rs',
exec_straight ge fn (indexed_memory_access mk_instr base ofs k) rs m k rs' m'
/\ forall r, r <> PC -> r <> X31 -> rs'#r = rs#r.
Lemma loadind_correct:
forall (base: ireg) ofs ty dst k c (rs: regset) m v,
loadind base ofs ty dst k = OK c ->
Mem.loadv (chunk_of_type ty) m (Val.offset_ptr rs#base ofs) = Some v ->
base <> X31 ->
exists rs',
exec_straight ge fn c rs m k rs' m
/\ rs'#(preg_of dst) = v
/\ forall r, r <> PC -> r <> X31 -> r <> preg_of dst -> rs'#r = rs#r.
Lemma storeind_correct:
forall (base: ireg) ofs ty src k c (rs: regset) m m',
storeind src base ofs ty k = OK c ->
Mem.storev (chunk_of_type ty) m (Val.offset_ptr rs#base ofs) rs#(preg_of src) = Some m' ->
base <> X31 ->
exists rs',
exec_straight ge fn c rs m k rs' m'
/\ forall r, r <> PC -> r <> X31 -> rs'#r = rs#r.
Lemma loadind_ptr_correct:
forall (base: ireg) ofs (dst: ireg) k (rs: regset) m v,
Mem.loadv Mptr m (Val.offset_ptr rs#base ofs) = Some v ->
base <> X31 ->
exists rs',
exec_straight ge fn (loadind_ptr base ofs dst k) rs m k rs' m
/\ rs'#dst = v
/\ forall r, r <> PC -> r <> X31 -> r <> dst -> rs'#r = rs#r.
Lemma storeind_ptr_correct:
forall (base: ireg) ofs (src: ireg) k (rs: regset) m m',
Mem.storev Mptr m (Val.offset_ptr rs#base ofs) rs#src = Some m' ->
base <> X31 -> src <> X31 ->
exists rs',
exec_straight ge fn (storeind_ptr src base ofs k) rs m k rs' m'
/\ forall r, r <> PC -> r <> X31 -> rs'#r = rs#r.
Lemma transl_memory_access_correct:
forall mk_instr addr args k c (rs: regset) m v,
transl_memory_access mk_instr addr args k = OK c ->
eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some v ->
exists base ofs rs',
exec_straight_opt c rs m (mk_instr base ofs :: k) rs' m
/\ Val.offset_ptr rs'#base (eval_offset ge ofs) = v
/\ forall r, r <> PC -> r <> X31 -> rs'#r = rs#r.
Lemma transl_load_access_correct:
forall chunk (mk_instr: ireg -> offset -> instruction) addr args k c rd (rs: regset) m v v',
(forall base ofs rs,
exec_instr ge fn (mk_instr base ofs) rs m = exec_load ge chunk rs m rd base ofs) ->
transl_memory_access mk_instr addr args k = OK c ->
eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some v ->
Mem.loadv chunk m v = Some v' ->
rd <> PC ->
exists rs',
exec_straight ge fn c rs m k rs' m
/\ rs'#rd = v'
/\ forall r, r <> PC -> r <> X31 -> r <> rd -> rs'#r = rs#r.
Lemma transl_store_access_correct:
forall chunk (mk_instr: ireg -> offset -> instruction) addr args k c r1 (rs: regset) m v m',
(forall base ofs rs,
exec_instr ge fn (mk_instr base ofs) rs m = exec_store ge chunk rs m r1 base ofs) ->
transl_memory_access mk_instr addr args k = OK c ->
eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some v ->
Mem.storev chunk m v rs#r1 = Some m' ->
r1 <> PC -> r1 <> X31 ->
exists rs',
exec_straight ge fn c rs m k rs' m'
/\ forall r, r <> PC -> r <> X31 -> rs'#r = rs#r.
Lemma transl_load_correct:
forall chunk addr args dst k c (rs: regset) m a v,
transl_load chunk addr args dst k = OK c ->
eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
exists rs',
exec_straight ge fn c rs m k rs' m
/\ rs'#(preg_of dst) = v
/\ forall r, r <> PC -> r <> X31 -> r <> preg_of dst -> rs'#r = rs#r.
Lemma transl_store_correct:
forall chunk addr args src k c (rs: regset) m a m',
transl_store chunk addr args src k = OK c ->
eval_addressing ge rs#SP addr (map rs (map preg_of args)) = Some a ->
Mem.storev chunk m a rs#(preg_of src) = Some m' ->
exists rs',
exec_straight ge fn c rs m k rs' m'
/\ forall r, r <> PC -> r <> X31 -> rs'#r = rs#r.