(** Indexed memory loads. *)

(* Specifications: *)
Lemma accessind_load_correct:
forall (A: Type) (inj: A -> preg)
(instr1: A -> constant -> ireg -> instruction)
(instr2: A -> ireg -> ireg -> instruction)
(base: ireg) ofs rx chunk v (rs: regset) m k,
(forall rs m r1 cst r2,
exec_instr ge fn (instr1 r1 cst r2) rs m = load1 ge chunk (inj r1) cst r2 rs m) ->
(forall rs m r1 r2 r3,
exec_instr ge fn (instr2 r1 r2 r3) rs m = load2 chunk (inj r1) r2 r3 rs m) ->
Mem.loadv chunk m (Val.offset_ptr rs#base ofs) = Some v ->
base <> GPR0 -> inj rx <> PC ->
exists rs',
exec_straight ge fn (accessind instr1 instr2 base ofs rx k) rs m k rs' m
/\ rs'#(inj rx) = v
/\ forall r, r <> PC -> r <> inj rx -> r <> GPR0 -> rs'#r = rs#r.
Lemma loadind_correct:
forall (base: ireg) ofs ty dst k (rs: regset) m v c,
loadind base ofs ty dst k = OK c ->
Mem.loadv (chunk_of_type ty) m (Val.offset_ptr rs#base ofs) = Some v ->
base <> GPR0 ->
exists rs',
exec_straight ge fn c rs m k rs' m
/\ rs'#(preg_of dst) = v
/\ forall r, r <> PC -> r <> preg_of dst -> r <> GPR0 -> rs'#r = rs#r.
Lemma indexed_memory_access_correct:
forall (P: regset -> Prop) (mk_instr: ireg -> int -> instruction)
(mk_immed: int -> int) (base: ireg) n k (rs: regset) m m',
(forall (r1: ireg) (rs1: regset) n1 k,
Val.add rs1#r1 (Vint n1) = Val.add rs#base (Vint n) ->
(forall (r: preg), if_preg r = true -> r <> IR14 -> rs1 r = rs r) ->
exists rs',
exec_straight ge fn (mk_instr r1 n1 :: k) rs1 m k rs' m' /\ P rs') ->
exists rs',
exec_straight ge fn
(indexed_memory_access mk_instr mk_immed base n k) rs m
k rs' m'
/\ P rs'.
Lemma loadind_int_correct:
forall (base: ireg) ofs dst (rs: regset) m v k,
Mem.loadv Mint32 m (Val.offset_ptr rs#base ofs) = Some v ->
exists rs',
exec_straight ge fn (loadind_int base ofs dst k) rs m k rs' m
/\ rs'#dst = v
/\ forall r, if_preg r = true -> r <> IR14 -> r <> dst -> 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 ->
exists rs',
exec_straight ge fn c rs m k rs' m
/\ rs'#(preg_of dst) = v
/\ forall r, if_preg r = true -> r <> IR14 -> r <> preg_of dst -> rs'#r = rs#r.