(** Translation of loads and stores. *)
Remark val_add_add_zero:
forall v1 v2, Val.add v1 v2 = Val.add (Val.add v1 v2) (Vint Int.zero).

(* Specifications: *)
Lemma transl_memory_access_correct:
forall (P: regset -> Prop) (mk_instr_imm: ireg -> int -> instruction)
(mk_instr_gen: option (ireg -> shift_op -> instruction))
(mk_immed: int -> int)
addr args k c (rs: regset) a m m',
transl_memory_access mk_instr_imm mk_instr_gen mk_immed addr args k = OK c ->
eval_addressing ge (rs#SP) addr (map rs (map preg_of args)) = Some a ->
match a with Vptr _ _ => True | _ => False end ->
(forall (r1: ireg) (rs1: regset) n k,
Val.add rs1#r1 (Vint n) = a ->
(forall (r: preg), if_preg r = true -> r <> IR14 -> rs1 r = rs r) ->
exists rs',
exec_straight ge fn (mk_instr_imm r1 n :: k) rs1 m k rs' m' /\ P rs') ->
match mk_instr_gen with
| None => True
| Some mk =>
(forall (r1: ireg) (sa: shift_op) k,
Val.add rs#r1 (eval_shift_op sa rs) = a ->
exists rs',
exec_straight ge fn (mk r1 sa :: k) rs m k rs' m' /\ P rs')
end ->
exists rs',
exec_straight ge fn c rs m k rs' m' /\ P rs'.
Lemma transl_load_int_correct:
forall mk_instr is_immed dst addr args k c (rs: regset) a chunk m v,
transl_memory_access_int mk_instr is_immed dst addr args k = OK c ->
eval_addressing ge (rs#SP) addr (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
(forall (r1 r2: ireg) (sa: shift_op) (rs1: regset),
exec_instr ge fn (mk_instr r1 r2 sa) rs1 m =
exec_load chunk (Val.add rs1#r2 (eval_shift_op sa rs1)) r1 rs1 m) ->
exists rs',
exec_straight ge fn c rs m k rs' m
/\ rs'#(preg_of dst) = v
/\ forall r, data_preg r = true -> r <> preg_of dst -> rs'#r = rs#r.
Lemma transl_load_float_correct:
forall mk_instr is_immed dst addr args k c (rs: regset) a chunk m v,
transl_memory_access_float mk_instr is_immed dst addr args k = OK c ->
eval_addressing ge (rs#SP) addr (map rs (map preg_of args)) = Some a ->
Mem.loadv chunk m a = Some v ->
(forall (r1: freg) (r2: ireg) (n: int) (rs1: regset),
exec_instr ge fn (mk_instr r1 r2 n) rs1 m =
exec_load chunk (Val.add rs1#r2 (Vint n)) r1 rs1 m) ->
exists rs',
exec_straight ge fn c rs m k rs' m
/\ rs'#(preg_of dst) = v
/\ forall r, data_preg r = true -> r <> preg_of dst -> rs'#r = rs#r.
Lemma transl_store_int_correct:
forall mr mk_instr is_immed src addr args k c (rs: regset) a chunk m m',
transl_memory_access_int mk_instr is_immed src addr args 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' ->
(forall (r1 r2: ireg) (sa: shift_op) (rs1: regset),
exec_instr ge fn (mk_instr r1 r2 sa) rs1 m =
exec_store chunk (Val.add rs1#r2 (eval_shift_op sa rs1)) r1 rs1 m) ->
exists rs',
exec_straight ge fn c rs m k rs' m'
/\ forall r, data_preg r = true -> preg_notin r mr -> rs'#r = rs#r.
Lemma transl_store_float_correct:
forall mr mk_instr is_immed src addr args k c (rs: regset) a chunk m m',
transl_memory_access_float mk_instr is_immed src addr args 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' ->
(forall (r1: freg) (r2: ireg) (n: int) (rs1: regset),
exec_instr ge fn (mk_instr r1 r2 n) rs1 m =
exec_store chunk (Val.add rs1#r2 (Vint n)) r1 rs1 m) ->
exists rs',
exec_straight ge fn c rs m k rs' m'
/\ forall r, data_preg r = true -> preg_notin r mr -> rs'#r = rs#r.
Lemma transl_load_correct:
forall chunk addr args dst k c (rs: regset) a m 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, data_preg r = true -> r <> preg_of dst -> rs'#r = rs#r.
Lemma transl_store_correct:
forall chunk addr args src k c (rs: regset) a m 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, data_preg r = true -> preg_notin r (destroyed_by_store chunk addr) -> rs'#r = rs#r.