Section CONSTRUCTORS.
Variable ge: genv.
Variable fn: function.
(** Decomposition of an integer constant *)
Remark decompose_int_arm_nil:
forall N n p, decompose_int_arm N n p = nil -> n = Int.zero.
Remark decompose_int_thumb_nil:
forall N n p, decompose_int_thumb N n p = nil -> n = Int.zero.
(** Loading a constant. *)
(** Add integer immediate. *)
(* And integer immediate *)
(** Reverse sub immediate *)
(** Or immediate *)
(** Xor immediate *)
(** Indexed memory loads. *)
(** Indexed memory stores. *)
(** Saving the link register *)
(** Translation of shift immediates *)
(** Translation of conditions *)
Ltac ArgsInv :=
repeat (match goal with
| [ H: Error _ = OK _ |- _ ] => discriminate
| [ H: match ?args with nil => _ | _ :: _ => _ end = OK _ |- _ ] => destruct args
| [ H: bind _ _ = OK _ |- _ ] => monadInv H
| [ H: match _ with left _ => _ | right _ => assertion_failed end = OK _ |- _ ] => monadInv H
| [ H: match _ with true => _ | false => assertion_failed end = OK _ |- _ ] => monadInv H
end);
subst;
repeat (match goal with
| [ H: ireg_of ?x = OK ?y |- _ ] => simpl in *; rewrite (ireg_of_eq _ _ H) in *
| [ H: freg_of ?x = OK ?y |- _ ] => simpl in *; rewrite (freg_of_eq _ _ H) in *
end).
(** Translation of arithmetic operations. *)
Ltac TranslOpSimpl :=
econstructor; split;
[ apply exec_straight_one; [simpl; eauto | reflexivity ]
| split; [try rewrite transl_shift_correct; repeat Simpl | intros; repeat Simpl] ].
(** 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).

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'.