Ltac TrivialExists :=
match goal with
| [ |- exists v2, Some ?v1 = Some v2 /\ Val.inject _ _ v2 ] =>
exists v1; split; auto
| _ => idtac
end.

(* Specifications: *)
Lemma eval_operation_inj:
forall op sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_operation op) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_operation ge1 sp1 op vl1 m1 = Some v1 ->
exists v2, eval_operation ge2 sp2 op vl2 m2 = Some v2 /\ Val.inject f v1 v2.
Lemma eval_addressing_inj:
forall addr sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_addressing addr) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_addressing ge1 sp1 addr vl1 = Some v1 ->
exists v2, eval_addressing ge2 sp2 addr vl2 = Some v2 /\ Val.inject f v1 v2.
Lemma eval_addressing32_inj:
forall addr sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_addressing addr) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_addressing32 ge1 sp1 addr vl1 = Some v1 ->
exists v2, eval_addressing32 ge2 sp2 addr vl2 = Some v2 /\ Val.inject f v1 v2.
Lemma eval_addressing64_inj:
forall addr sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_addressing addr) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_addressing64 ge1 sp1 addr vl1 = Some v1 ->
exists v2, eval_addressing64 ge2 sp2 addr vl2 = Some v2 /\ Val.inject f v1 v2.
Lemma eval_addressing_inj:
forall addr sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_addressing addr) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_addressing ge1 sp1 addr vl1 = Some v1 ->
exists v2, eval_addressing ge2 sp2 addr vl2 = Some v2 /\ Val.inject f v1 v2.
Lemma eval_operation_inj:
forall op sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_operation op) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_operation ge1 sp1 op vl1 m1 = Some v1 ->
exists v2, eval_operation ge2 sp2 op vl2 m2 = Some v2 /\ Val.inject f v1 v2.
Lemma eval_operation_inj:
forall op sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_operation op) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_operation ge1 sp1 op vl1 m1 = Some v1 ->
exists v2, eval_operation ge2 sp2 op vl2 m2 = Some v2 /\ Val.inject f v1 v2.
Lemma eval_addressing_inj:
forall addr sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_addressing addr) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_addressing ge1 sp1 addr vl1 = Some v1 ->
exists v2, eval_addressing ge2 sp2 addr vl2 = Some v2 /\ Val.inject f v1 v2.
Lemma eval_operation_inj:
forall op sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_operation op) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_operation ge1 sp1 op vl1 m1 = Some v1 ->
exists v2, eval_operation ge2 sp2 op vl2 m2 = Some v2 /\ Val.inject f v1 v2.
Lemma eval_addressing_inj:
forall addr sp1 vl1 sp2 vl2 v1,
(forall id ofs,
In id (globals_addressing addr) ->
Val.inject f (Genv.symbol_address ge1 id ofs) (Genv.symbol_address ge2 id ofs)) ->
Val.inject f sp1 sp2 ->
Val.inject_list f vl1 vl2 ->
eval_addressing ge1 sp1 addr vl1 = Some v1 ->
exists v2, eval_addressing ge2 sp2 addr vl2 = Some v2 /\ Val.inject f v1 v2.