summaryrefslogtreecommitdiff
path: root/backend/PPCgenproof.v
diff options
context:
space:
mode:
Diffstat (limited to 'backend/PPCgenproof.v')
-rw-r--r--backend/PPCgenproof.v1242
1 files changed, 1242 insertions, 0 deletions
diff --git a/backend/PPCgenproof.v b/backend/PPCgenproof.v
new file mode 100644
index 0000000..d89046f
--- /dev/null
+++ b/backend/PPCgenproof.v
@@ -0,0 +1,1242 @@
+(** Correctness proof for PPC generation: main proof. *)
+
+Require Import Coqlib.
+Require Import Maps.
+Require Import AST.
+Require Import Integers.
+Require Import Floats.
+Require Import Values.
+Require Import Mem.
+Require Import Globalenvs.
+Require Import Op.
+Require Import Locations.
+Require Import Mach.
+Require Import Machtyping.
+Require Import PPC.
+Require Import PPCgen.
+Require Import PPCgenproof1.
+
+Section PRESERVATION.
+
+Variable prog: Mach.program.
+Variable tprog: PPC.program.
+Hypothesis TRANSF: transf_program prog = Some tprog.
+
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Lemma symbols_preserved:
+ forall id, Genv.find_symbol tge id = Genv.find_symbol ge id.
+Proof.
+ intros. unfold ge, tge.
+ apply Genv.find_symbol_transf_partial with transf_function.
+ exact TRANSF.
+Qed.
+
+Lemma functions_translated:
+ forall f b,
+ Genv.find_funct_ptr ge b = Some f ->
+ Genv.find_funct_ptr tge b = Some (transl_function f).
+Proof.
+ intros.
+ generalize (Genv.find_funct_ptr_transf_partial
+ transf_function TRANSF H).
+ intros [A B].
+ unfold tge. change code with (list instruction). rewrite A.
+ generalize B. unfold transf_function.
+ case (zlt Int.max_unsigned (code_size (transl_function f))); intro.
+ tauto. auto.
+Qed.
+
+Lemma functions_translated_2:
+ forall f v,
+ Genv.find_funct ge v = Some f ->
+ Genv.find_funct tge v = Some (transl_function f).
+Proof.
+ intros.
+ generalize (Genv.find_funct_transf_partial
+ transf_function TRANSF H).
+ intros [A B].
+ unfold tge. change code with (list instruction). rewrite A.
+ generalize B. unfold transf_function.
+ case (zlt Int.max_unsigned (code_size (transl_function f))); intro.
+ tauto. auto.
+Qed.
+
+Lemma functions_translated_no_overflow:
+ forall b f,
+ Genv.find_funct_ptr ge b = Some f ->
+ code_size (transl_function f) <= Int.max_unsigned.
+Proof.
+ intros.
+ generalize (Genv.find_funct_ptr_transf_partial
+ transf_function TRANSF H).
+ intros [A B].
+ generalize B.
+ unfold transf_function.
+ case (zlt Int.max_unsigned (code_size (transl_function f))); intro.
+ tauto. intro. omega.
+Qed.
+
+(** * Properties of control flow *)
+
+Lemma find_instr_in:
+ forall c pos i,
+ find_instr pos c = Some i -> In i c.
+Proof.
+ induction c; simpl. intros; discriminate.
+ intros until i. case (zeq pos 0); intros.
+ left; congruence. right; eauto.
+Qed.
+
+(** The ``code tail'' of an instruction list [c] is the list of instructions
+ starting at PC [pos]. *)
+
+Fixpoint code_tail (pos: Z) (c: code) {struct c} : code :=
+ match c with
+ | nil => nil
+ | i :: il => if zeq pos 0 then c else code_tail (pos - 1) il
+ end.
+Proof.
+
+Lemma find_instr_tail:
+ forall c pos,
+ find_instr pos c =
+ match code_tail pos c with nil => None | i1 :: il => Some i1 end.
+Proof.
+ induction c; simpl; intros.
+ auto.
+ case (zeq pos 0); auto.
+Qed.
+
+Remark code_size_pos:
+ forall fn, code_size fn >= 0.
+Proof.
+ induction fn; simpl; omega.
+Qed.
+
+Remark code_tail_bounds:
+ forall fn ofs i c,
+ code_tail ofs fn = i :: c -> 0 <= ofs < code_size fn.
+Proof.
+ induction fn; simpl.
+ intros; discriminate.
+ intros until c. case (zeq ofs 0); intros.
+ generalize (code_size_pos fn). omega.
+ generalize (IHfn _ _ _ H). omega.
+Qed.
+
+Remark code_tail_unfold:
+ forall ofs i c,
+ ofs >= 0 ->
+ code_tail (ofs + 1) (i :: c) = code_tail ofs c.
+Proof.
+ intros. simpl. case (zeq (ofs + 1) 0); intros.
+ omegaContradiction.
+ replace (ofs + 1 - 1) with ofs. auto. omega.
+Qed.
+
+Remark code_tail_zero:
+ forall fn, code_tail 0 fn = fn.
+Proof.
+ intros. destruct fn; simpl. auto. auto.
+Qed.
+
+Lemma code_tail_next:
+ forall fn ofs i c,
+ code_tail ofs fn = i :: c ->
+ code_tail (ofs + 1) fn = c.
+Proof.
+ induction fn.
+ simpl; intros; discriminate.
+ intros until c. case (zeq ofs 0); intro.
+ subst ofs. intros. rewrite code_tail_zero in H. injection H.
+ intros. subst c. rewrite code_tail_unfold. apply code_tail_zero.
+ omega.
+ intro; generalize (code_tail_bounds _ _ _ _ H); intros [A B].
+ assert (ofs = (ofs - 1) + 1). omega.
+ rewrite H0 in H. rewrite code_tail_unfold in H.
+ rewrite code_tail_unfold. rewrite H0. eauto.
+ omega. omega.
+Qed.
+
+Lemma code_tail_next_int:
+ forall fn ofs i c,
+ code_size fn <= Int.max_unsigned ->
+ code_tail (Int.unsigned ofs) fn = i :: c ->
+ code_tail (Int.unsigned (Int.add ofs Int.one)) fn = c.
+Proof.
+ intros. rewrite Int.add_unsigned. unfold Int.one.
+ repeat rewrite Int.unsigned_repr. apply code_tail_next with i; auto.
+ compute; intuition congruence.
+ generalize (code_tail_bounds _ _ _ _ H0). omega.
+ compute; intuition congruence.
+Qed.
+
+(** [transl_code_at_pc pc fn c] holds if the code pointer [pc] points
+ within the PPC code generated by translating Mach function [fn],
+ and [c] is the tail of the generated code at the position corresponding
+ to the code pointer [pc]. *)
+
+Inductive transl_code_at_pc: val -> Mach.function -> Mach.code -> Prop :=
+ transl_code_at_pc_intro:
+ forall b ofs f c,
+ Genv.find_funct_ptr ge b = Some f ->
+ code_tail (Int.unsigned ofs) (transl_function f) = transl_code c ->
+ transl_code_at_pc (Vptr b ofs) f c.
+
+(** The following lemmas show that straight-line executions
+ (predicate [exec_straight]) correspond to correct PPC executions
+ (predicate [exec_steps]) under adequate [transl_code_at_pc] hypotheses. *)
+
+Lemma exec_straight_steps_1:
+ forall fn c rs m c' rs' m',
+ exec_straight tge fn c rs m c' rs' m' ->
+ code_size fn <= Int.max_unsigned ->
+ forall b ofs,
+ rs#PC = Vptr b ofs ->
+ Genv.find_funct_ptr tge b = Some fn ->
+ code_tail (Int.unsigned ofs) fn = c ->
+ exec_steps tge rs m rs' m'.
+Proof.
+ induction 1.
+ intros. apply exec_refl.
+ intros. apply exec_trans with rs2 m2.
+ apply exec_one; econstructor; eauto.
+ rewrite find_instr_tail. rewrite H5. auto.
+ apply IHexec_straight with b (Int.add ofs Int.one).
+ auto. rewrite H0. rewrite H3. reflexivity.
+ auto.
+ apply code_tail_next_int with i; auto.
+Qed.
+
+Lemma exec_straight_steps_2:
+ forall fn c rs m c' rs' m',
+ exec_straight tge fn c rs m c' rs' m' ->
+ code_size fn <= Int.max_unsigned ->
+ forall b ofs,
+ rs#PC = Vptr b ofs ->
+ Genv.find_funct_ptr tge b = Some fn ->
+ code_tail (Int.unsigned ofs) fn = c ->
+ exists ofs',
+ rs'#PC = Vptr b ofs'
+ /\ code_tail (Int.unsigned ofs') fn = c'.
+Proof.
+ induction 1; intros.
+ exists ofs. split. auto. auto.
+ apply IHexec_straight with (Int.add ofs Int.one).
+ auto. rewrite H0. rewrite H3. reflexivity. auto.
+ apply code_tail_next_int with i; auto.
+Qed.
+
+Lemma exec_straight_steps:
+ forall f c c' rs m rs' m',
+ transl_code_at_pc (rs PC) f c ->
+ exec_straight tge (transl_function f)
+ (transl_code c) rs m (transl_code c') rs' m' ->
+ exec_steps tge rs m rs' m' /\ transl_code_at_pc (rs' PC) f c'.
+Proof.
+ intros. inversion H.
+ generalize (functions_translated_no_overflow _ _ H2). intro.
+ generalize (functions_translated _ _ H2). intro.
+ split. eapply exec_straight_steps_1; eauto.
+ generalize (exec_straight_steps_2 _ _ _ _ _ _ _
+ H0 H6 _ _ (sym_equal H1) H7 H3).
+ intros [ofs' [PC' CT']].
+ rewrite PC'. constructor; auto.
+Qed.
+
+(** The [find_label] function returns the code tail starting at the
+ given label. A connection with [code_tail] is then established. *)
+
+Fixpoint find_label (lbl: label) (c: code) {struct c} : option code :=
+ match c with
+ | nil => None
+ | instr :: c' =>
+ if is_label lbl instr then Some c' else find_label lbl c'
+ end.
+
+Lemma label_pos_code_tail:
+ forall lbl c pos c',
+ find_label lbl c = Some c' ->
+ exists pos',
+ label_pos lbl pos c = Some pos'
+ /\ code_tail (pos' - pos) c = c'
+ /\ pos < pos' <= pos + code_size c.
+Proof.
+ induction c.
+ simpl; intros. discriminate.
+ simpl; intros until c'.
+ case (is_label lbl a).
+ intro EQ; injection EQ; intro; subst c'.
+ exists (pos + 1). split. auto. split.
+ rewrite zeq_false. replace (pos + 1 - pos - 1) with 0.
+ apply code_tail_zero. omega. omega.
+ generalize (code_size_pos c). omega.
+ intros. generalize (IHc (pos + 1) c' H). intros [pos' [A [B C]]].
+ exists pos'. split. auto. split.
+ rewrite zeq_false. replace (pos' - pos - 1) with (pos' - (pos + 1)).
+ auto. omega. omega. omega.
+Qed.
+
+(** The following lemmas show that the translation from Mach to PPC
+ preserves labels, in the sense that the following diagram commutes:
+<<
+ translation
+ Mach code ------------------------ PPC instr sequence
+ | |
+ | Mach.find_label lbl find_label lbl |
+ | |
+ v v
+ Mach code tail ------------------- PPC instr seq tail
+ translation
+>>
+ The proof demands many boring lemmas showing that PPC constructor
+ functions do not introduce new labels.
+*)
+
+Section TRANSL_LABEL.
+
+Variable lbl: label.
+
+Remark loadimm_label:
+ forall r n k, find_label lbl (loadimm r n k) = find_label lbl k.
+Proof.
+ intros. unfold loadimm.
+ case (Int.eq (high_s n) Int.zero). reflexivity.
+ case (Int.eq (low_s n) Int.zero). reflexivity.
+ reflexivity.
+Qed.
+Hint Rewrite loadimm_label: labels.
+
+Remark addimm_1_label:
+ forall r1 r2 n k, find_label lbl (addimm_1 r1 r2 n k) = find_label lbl k.
+Proof.
+ intros; unfold addimm_1.
+ case (Int.eq (high_s n) Int.zero). reflexivity.
+ case (Int.eq (low_s n) Int.zero). reflexivity. reflexivity.
+Qed.
+Remark addimm_2_label:
+ forall r1 r2 n k, find_label lbl (addimm_2 r1 r2 n k) = find_label lbl k.
+Proof.
+ intros; unfold addimm_2. autorewrite with labels. reflexivity.
+Qed.
+Remark addimm_label:
+ forall r1 r2 n k, find_label lbl (addimm r1 r2 n k) = find_label lbl k.
+Proof.
+ intros; unfold addimm.
+ case (ireg_eq r1 GPR0); intro. apply addimm_2_label.
+ case (ireg_eq r2 GPR0); intro. apply addimm_2_label.
+ apply addimm_1_label.
+Qed.
+Hint Rewrite addimm_label: labels.
+
+Remark andimm_label:
+ forall r1 r2 n k, find_label lbl (andimm r1 r2 n k) = find_label lbl k.
+Proof.
+ intros; unfold andimm.
+ case (Int.eq (high_u n) Int.zero). reflexivity.
+ case (Int.eq (low_u n) Int.zero). reflexivity.
+ autorewrite with labels. reflexivity.
+Qed.
+Hint Rewrite andimm_label: labels.
+
+Remark orimm_label:
+ forall r1 r2 n k, find_label lbl (orimm r1 r2 n k) = find_label lbl k.
+Proof.
+ intros; unfold orimm.
+ case (Int.eq (high_u n) Int.zero). reflexivity.
+ case (Int.eq (low_u n) Int.zero). reflexivity. reflexivity.
+Qed.
+Hint Rewrite orimm_label: labels.
+
+Remark xorimm_label:
+ forall r1 r2 n k, find_label lbl (xorimm r1 r2 n k) = find_label lbl k.
+Proof.
+ intros; unfold xorimm.
+ case (Int.eq (high_u n) Int.zero). reflexivity.
+ case (Int.eq (low_u n) Int.zero). reflexivity. reflexivity.
+Qed.
+Hint Rewrite xorimm_label: labels.
+
+Remark loadind_aux_label:
+ forall base ofs ty dst k, find_label lbl (loadind_aux base ofs ty dst :: k) = find_label lbl k.
+Proof.
+ intros; unfold loadind_aux.
+ case ty; reflexivity.
+Qed.
+Remark loadind_label:
+ forall base ofs ty dst k, find_label lbl (loadind base ofs ty dst k) = find_label lbl k.
+Proof.
+ intros; unfold loadind.
+ case (Int.eq (high_s ofs) Int.zero). apply loadind_aux_label.
+ transitivity (find_label lbl (loadind_aux GPR2 (low_s ofs) ty dst :: k)).
+ reflexivity. apply loadind_aux_label.
+Qed.
+Hint Rewrite loadind_label: labels.
+Remark storeind_aux_label:
+ forall base ofs ty dst k, find_label lbl (storeind_aux base ofs ty dst :: k) = find_label lbl k.
+Proof.
+ intros; unfold storeind_aux.
+ case dst; reflexivity.
+Qed.
+Remark storeind_label:
+ forall base ofs ty src k, find_label lbl (storeind base src ofs ty k) = find_label lbl k.
+Proof.
+ intros; unfold storeind.
+ case (Int.eq (high_s ofs) Int.zero). apply storeind_aux_label.
+ transitivity (find_label lbl (storeind_aux base GPR2 (low_s ofs) ty :: k)).
+ reflexivity. apply storeind_aux_label.
+Qed.
+Hint Rewrite storeind_label: labels.
+Remark floatcomp_label:
+ forall cmp r1 r2 k, find_label lbl (floatcomp cmp r1 r2 k) = find_label lbl k.
+Proof.
+ intros; unfold floatcomp. destruct cmp; reflexivity.
+Qed.
+
+Remark transl_cond_label:
+ forall cond args k, find_label lbl (transl_cond cond args k) = find_label lbl k.
+Proof.
+ intros; unfold transl_cond.
+ destruct cond; (destruct args;
+ [try reflexivity | destruct args;
+ [try reflexivity | destruct args; try reflexivity]]).
+ case (Int.eq (high_s i) Int.zero). reflexivity.
+ autorewrite with labels; reflexivity.
+ case (Int.eq (high_u i) Int.zero). reflexivity.
+ autorewrite with labels; reflexivity.
+ apply floatcomp_label. apply floatcomp_label.
+ apply andimm_label. apply andimm_label.
+Qed.
+Hint Rewrite transl_cond_label: labels.
+Remark transl_op_label:
+ forall op args r k, find_label lbl (transl_op op args r k) = find_label lbl k.
+Proof.
+ intros; unfold transl_op;
+ destruct op; destruct args; try (destruct args); try (destruct args); try (destruct args);
+ try reflexivity; autorewrite with labels; try reflexivity.
+ case (mreg_type m); reflexivity.
+ case (mreg_type r); reflexivity.
+ case (Int.eq (high_s i) Int.zero); autorewrite with labels; reflexivity.
+ case (Int.eq (high_s i) Int.zero); autorewrite with labels; reflexivity.
+ case (snd (crbit_for_cond c)); reflexivity.
+ case (snd (crbit_for_cond c)); reflexivity.
+ case (snd (crbit_for_cond c)); reflexivity.
+ case (snd (crbit_for_cond c)); reflexivity.
+ case (snd (crbit_for_cond c)); reflexivity.
+Qed.
+Hint Rewrite transl_op_label: labels.
+
+Remark transl_load_store_label:
+ forall (mk1: constant -> ireg -> instruction) (mk2: ireg -> ireg -> instruction)
+ addr args k,
+ (forall c r, is_label lbl (mk1 c r) = false) ->
+ (forall r1 r2, is_label lbl (mk2 r1 r2) = false) ->
+ find_label lbl (transl_load_store mk1 mk2 addr args k) = find_label lbl k.
+Proof.
+ intros; unfold transl_load_store.
+ destruct addr; destruct args; try (destruct args); try (destruct args);
+ try reflexivity.
+ case (ireg_eq (ireg_of m) GPR0); intro.
+ simpl. rewrite H. auto.
+ case (Int.eq (high_s i) Int.zero). simpl; rewrite H; auto.
+ simpl; rewrite H; auto.
+ simpl; rewrite H0; auto.
+ simpl; rewrite H; auto.
+ case (ireg_eq (ireg_of m) GPR0); intro; simpl; rewrite H; auto.
+ case (Int.eq (high_s i) Int.zero); simpl; rewrite H; auto.
+Qed.
+Hint Rewrite transl_load_store_label: labels.
+
+Lemma transl_instr_label:
+ forall i k,
+ find_label lbl (transl_instr i k) =
+ if Mach.is_label lbl i then Some k else find_label lbl k.
+Proof.
+ intros. generalize (Mach.is_label_correct lbl i).
+ case (Mach.is_label lbl i); intro.
+ subst i. simpl. rewrite peq_true. auto.
+ destruct i; simpl; autorewrite with labels; try reflexivity.
+ destruct m; rewrite transl_load_store_label; intros; reflexivity.
+ destruct m; rewrite transl_load_store_label; intros; reflexivity.
+ destruct s0; reflexivity.
+ rewrite peq_false. auto. congruence.
+ case (snd (crbit_for_cond c)); reflexivity.
+Qed.
+
+Lemma transl_code_label:
+ forall c,
+ find_label lbl (transl_code c) =
+ option_map transl_code (Mach.find_label lbl c).
+Proof.
+ induction c; simpl; intros.
+ auto. rewrite transl_instr_label.
+ case (Mach.is_label lbl a). reflexivity.
+ auto.
+Qed.
+
+Lemma transl_find_label:
+ forall f,
+ find_label lbl (transl_function f) =
+ option_map transl_code (Mach.find_label lbl f.(fn_code)).
+Proof.
+ intros. unfold transl_function. simpl. apply transl_code_label.
+Qed.
+
+End TRANSL_LABEL.
+
+(** A valid branch in a piece of Mach code translates to a valid ``go to''
+ transition in the generated PPC code. *)
+
+Lemma find_label_goto_label:
+ forall f lbl rs m c' b ofs,
+ Genv.find_funct_ptr ge b = Some f ->
+ rs PC = Vptr b ofs ->
+ Mach.find_label lbl f.(fn_code) = Some c' ->
+ exists rs',
+ goto_label (transl_function f) lbl rs m = OK rs' m
+ /\ transl_code_at_pc (rs' PC) f c'
+ /\ forall r, r <> PC -> rs'#r = rs#r.
+Proof.
+ intros.
+ generalize (transl_find_label lbl f).
+ rewrite H1; simpl. intro.
+ generalize (label_pos_code_tail lbl (transl_function f) 0
+ (transl_code c') H2).
+ intros [pos' [A [B C]]].
+ exists (rs#PC <- (Vptr b (Int.repr pos'))).
+ split. unfold goto_label. rewrite A. rewrite H0. auto.
+ split. rewrite Pregmap.gss. constructor. auto.
+ rewrite Int.unsigned_repr. replace (pos' - 0) with pos' in B.
+ auto. omega.
+ generalize (functions_translated_no_overflow _ _ H).
+ omega.
+ intros. apply Pregmap.gso; auto.
+Qed.
+
+(** * Memory properties *)
+
+(** The PowerPC has no instruction for ``load 8-bit signed integer''.
+ We show that it can be synthesized as a ``load 8-bit unsigned integer''
+ followed by a sign extension. *)
+
+Lemma loadv_8_signed_unsigned:
+ forall m a,
+ Mem.loadv Mint8signed m a =
+ option_map Val.cast8signed (Mem.loadv Mint8unsigned m a).
+Proof.
+ intros. unfold Mem.loadv. destruct a; try reflexivity.
+ unfold load. case (zlt b (nextblock m)); intro.
+ change (in_bounds Mint8unsigned (Int.signed i) (blocks m b))
+ with (in_bounds Mint8signed (Int.signed i) (blocks m b)).
+ case (in_bounds Mint8signed (Int.signed i) (blocks m b)).
+ change (mem_chunk Mint8unsigned) with (mem_chunk Mint8signed).
+ set (v := (load_contents (mem_chunk Mint8signed)
+ (contents (blocks m b)) (Int.signed i))).
+ unfold Val.load_result. destruct v; try reflexivity.
+ simpl. rewrite Int.cast8_signed_unsigned. auto.
+ reflexivity. reflexivity.
+Qed.
+
+(** Similarly, we show that signed 8- and 16-bit stores can be performed
+ like unsigned stores. *)
+
+Lemma storev_8_signed_unsigned:
+ forall m a v,
+ Mem.storev Mint8signed m a v = Mem.storev Mint8unsigned m a v.
+Proof.
+ intros. reflexivity.
+Qed.
+
+Lemma storev_16_signed_unsigned:
+ forall m a v,
+ Mem.storev Mint16signed m a v = Mem.storev Mint16unsigned m a v.
+Proof.
+ intros. reflexivity.
+Qed.
+
+(** * Proof of semantic preservation *)
+
+(** The invariants for the inductive proof of simulation are as follows.
+ The simulation diagrams are of the form:
+<<
+ c1, ms1, m1 --------------------- rs1, m1
+ | |
+ | |
+ v v
+ c2, ms2, m2 --------------------- rs2, m2
+>>
+ Left: execution of one Mach instruction. Right: execution of zero, one
+ or several instructions. Precondition (top): agreement between
+ the Mach register set [ms1] and the PPC register set [rs1]; moreover,
+ [rs1 PC] points to the translation of code [c1]. Postcondition (bottom):
+ similar.
+*)
+
+Definition exec_instr_prop
+ (f: Mach.function) (sp: val)
+ (c1: Mach.code) (ms1: Mach.regset) (m1: mem)
+ (c2: Mach.code) (ms2: Mach.regset) (m2: mem) :=
+ forall rs1
+ (WTF: wt_function f)
+ (INCL: incl c1 f.(fn_code))
+ (AT: transl_code_at_pc (rs1 PC) f c1)
+ (AG: agree ms1 sp rs1),
+ exists rs2,
+ agree ms2 sp rs2
+ /\ exec_steps tge rs1 m1 rs2 m2
+ /\ transl_code_at_pc (rs2 PC) f c2.
+
+Definition exec_function_body_prop
+ (f: Mach.function) (parent: val) (ra: val)
+ (ms1: Mach.regset) (m1: mem)
+ (ms2: Mach.regset) (m2: mem) :=
+ forall rs1
+ (WTRA: Val.has_type ra Tint)
+ (RALR: rs1 LR = ra)
+ (WTF: wt_function f)
+ (AT: Genv.find_funct ge (rs1 PC) = Some f)
+ (AG: agree ms1 parent rs1),
+ exists rs2,
+ agree ms2 parent rs2
+ /\ exec_steps tge rs1 m1 rs2 m2
+ /\ rs2 PC = rs1 LR.
+
+Definition exec_function_prop
+ (f: Mach.function) (parent: val)
+ (ms1: Mach.regset) (m1: mem)
+ (ms2: Mach.regset) (m2: mem) :=
+ forall rs1
+ (WTF: wt_function f)
+ (AT: Genv.find_funct ge (rs1 PC) = Some f)
+ (AG: agree ms1 parent rs1)
+ (WTRA: Val.has_type (rs1 LR) Tint),
+ exists rs2,
+ agree ms2 parent rs2
+ /\ exec_steps tge rs1 m1 rs2 m2
+ /\ rs2 PC = rs1 LR.
+
+(** We show each case of the inductive proof of simulation as a separate
+ lemma. *)
+
+Lemma exec_Mlabel_prop:
+ forall (f : function) (sp : val) (lbl : Mach.label)
+ (c : list Mach.instruction) (rs : Mach.regset) (m : mem),
+ exec_instr_prop f sp (Mlabel lbl :: c) rs m c rs m.
+Proof.
+ intros; red; intros.
+ assert (exec_straight tge (transl_function f)
+ (transl_code (Mlabel lbl :: c)) rs1 m
+ (transl_code c) (nextinstr rs1) m).
+ simpl. apply exec_straight_one. reflexivity. reflexivity.
+ exists (nextinstr rs1). split. apply agree_nextinstr; auto.
+ eapply exec_straight_steps; eauto.
+Qed.
+
+Lemma exec_Mgetstack_prop:
+ forall (f : function) (sp : val) (ofs : int) (ty : typ) (dst : mreg)
+ (c : list Mach.instruction) (ms : Mach.regset) (m : mem) (v : val),
+ load_stack m sp ty ofs = Some v ->
+ exec_instr_prop f sp (Mgetstack ofs ty dst :: c) ms m c (Regmap.set dst v ms) m.
+Proof.
+ intros; red; intros.
+ unfold load_stack in H.
+ generalize (wt_function_instrs _ WTF _ (INCL _ (in_eq _ _))).
+ intro WTI. inversion WTI.
+ rewrite (sp_val _ _ _ AG) in H.
+ assert (NOTE: GPR1 <> GPR0). congruence.
+ generalize (loadind_correct tge (transl_function f) GPR1 ofs ty
+ dst (transl_code c) rs1 m v H H1 NOTE).
+ intros [rs2 [EX [RES OTH]]].
+ exists rs2. split.
+ apply agree_exten_2 with (rs1#(preg_of dst) <- v).
+ auto with ppcgen.
+ intros. case (preg_eq r0 (preg_of dst)); intro.
+ subst r0. rewrite Pregmap.gss. auto.
+ rewrite Pregmap.gso; auto.
+ eapply exec_straight_steps; eauto.
+Qed.
+
+Lemma exec_Msetstack_prop:
+ forall (f : function) (sp : val) (src : mreg) (ofs : int) (ty : typ)
+ (c : list Mach.instruction) (ms : mreg -> val) (m m' : mem),
+ store_stack m sp ty ofs (ms src) = Some m' ->
+ exec_instr_prop f sp (Msetstack src ofs ty :: c) ms m c ms m'.
+Proof.
+ intros; red; intros.
+ unfold store_stack in H.
+ generalize (wt_function_instrs _ WTF _ (INCL _ (in_eq _ _))).
+ intro WTI. inversion WTI.
+ rewrite (sp_val _ _ _ AG) in H.
+ rewrite (preg_val ms sp rs1) in H; auto.
+ assert (NOTE: GPR1 <> GPR0). congruence.
+ generalize (storeind_correct tge (transl_function f) GPR1 ofs ty
+ src (transl_code c) rs1 m m' H H2 NOTE).
+ intros [rs2 [EX OTH]].
+ exists rs2. split.
+ apply agree_exten_2 with rs1; auto.
+ eapply exec_straight_steps; eauto.
+Qed.
+
+Lemma exec_Mgetparam_prop:
+ forall (f : function) (sp parent : val) (ofs : int) (ty : typ)
+ (dst : mreg) (c : list Mach.instruction) (ms : Mach.regset)
+ (m : mem) (v : val),
+ load_stack m sp Tint (Int.repr 0) = Some parent ->
+ load_stack m parent ty ofs = Some v ->
+ exec_instr_prop f sp (Mgetparam ofs ty dst :: c) ms m c (Regmap.set dst v ms) m.
+Proof.
+ intros; red; intros.
+ set (rs2 := nextinstr (rs1#GPR2 <- parent)).
+ assert (EX1: exec_straight tge (transl_function f)
+ (transl_code (Mgetparam ofs ty dst :: c)) rs1 m
+ (loadind GPR2 ofs ty dst (transl_code c)) rs2 m).
+ simpl. apply exec_straight_one.
+ simpl. unfold load1. rewrite gpr_or_zero_not_zero; auto with ppcgen.
+ unfold const_low. rewrite <- (sp_val ms sp rs1); auto.
+ unfold load_stack in H. simpl chunk_of_type in H.
+ rewrite H. reflexivity. reflexivity.
+ generalize (wt_function_instrs _ WTF _ (INCL _ (in_eq _ _))).
+ intro WTI. inversion WTI.
+ unfold load_stack in H0. change parent with rs2#GPR2 in H0.
+ assert (NOTE: GPR2 <> GPR0). congruence.
+ generalize (loadind_correct tge (transl_function f) GPR2 ofs ty
+ dst (transl_code c) rs2 m v H0 H2 NOTE).
+ intros [rs3 [EX2 [RES OTH]]].
+ exists rs3. split.
+ apply agree_exten_2 with (rs2#(preg_of dst) <- v).
+ unfold rs2; auto with ppcgen.
+ intros. case (preg_eq r0 (preg_of dst)); intro.
+ subst r0. rewrite Pregmap.gss. auto.
+ rewrite Pregmap.gso; auto.
+ eapply exec_straight_steps; eauto.
+ eapply exec_straight_trans; eauto.
+Qed.
+
+Lemma exec_straight_exec_prop:
+ forall f sp c1 rs1 m1 c2 m2 ms',
+ transl_code_at_pc (rs1 PC) f c1 ->
+ (exists rs2,
+ exec_straight tge (transl_function f)
+ (transl_code c1) rs1 m1
+ (transl_code c2) rs2 m2
+ /\ agree ms' sp rs2) ->
+ (exists rs2,
+ agree ms' sp rs2
+ /\ exec_steps tge rs1 m1 rs2 m2
+ /\ transl_code_at_pc (rs2 PC) f c2).
+Proof.
+ intros until ms'. intros TRANS1 [rs2 [EX AG]].
+ exists rs2. split. assumption.
+ eapply exec_straight_steps; eauto.
+Qed.
+
+Lemma exec_Mop_prop:
+ forall (f : function) (sp : val) (op : operation) (args : list mreg)
+ (res : mreg) (c : list Mach.instruction) (ms: Mach.regset)
+ (m : mem) (v: val),
+ eval_operation ge sp op ms ## args = Some v ->
+ exec_instr_prop f sp (Mop op args res :: c) ms m c (Regmap.set res v ms) m.
+Proof.
+ intros; red; intros.
+ generalize (wt_function_instrs _ WTF _ (INCL _ (in_eq _ _))).
+ intro WTI.
+ eapply exec_straight_exec_prop; eauto.
+ simpl. eapply transl_op_correct; auto.
+ rewrite <- H. apply eval_operation_preserved. exact symbols_preserved.
+Qed.
+
+Lemma exec_Mload_prop:
+ forall (f : function) (sp : val) (chunk : memory_chunk)
+ (addr : addressing) (args : list mreg) (dst : mreg)
+ (c : list Mach.instruction) (ms: Mach.regset) (m : mem)
+ (a v : val),
+ eval_addressing ge sp addr ms ## args = Some a ->
+ loadv chunk m a = Some v ->
+ exec_instr_prop f sp (Mload chunk addr args dst :: c) ms m c (Regmap.set dst v ms) m.
+Proof.
+ intros; red; intros.
+ generalize (wt_function_instrs _ WTF _ (INCL _ (in_eq _ _))).
+ intro WTI; inversion WTI.
+ assert (eval_addressing tge sp addr ms##args = Some a).
+ rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved.
+ eapply exec_straight_exec_prop; eauto.
+ destruct chunk; simpl; simpl in H6;
+ (* all cases but Mint8signed *)
+ try (eapply transl_load_correct; eauto;
+ intros; simpl; unfold preg_of; rewrite H6; auto).
+ (* Mint8signed *)
+ generalize (loadv_8_signed_unsigned m a).
+ rewrite H0.
+ caseEq (loadv Mint8unsigned m a);
+ [idtac | simpl;intros;discriminate].
+ intros v' LOAD' EQ. simpl in EQ. injection EQ. intro EQ1. clear EQ.
+ assert (X1: forall (cst : constant) (r1 : ireg) (rs1 : regset),
+ exec_instr tge (transl_function f) (Plbz (ireg_of dst) cst r1) rs1 m =
+ load1 tge Mint8unsigned (preg_of dst) cst r1 rs1 m).
+ intros. unfold preg_of; rewrite H6. reflexivity.
+ assert (X2: forall (r1 r2 : ireg) (rs1 : regset),
+ exec_instr tge (transl_function f) (Plbzx (ireg_of dst) r1 r2) rs1 m =
+ load2 Mint8unsigned (preg_of dst) r1 r2 rs1 m).
+ intros. unfold preg_of; rewrite H6. reflexivity.
+ generalize (transl_load_correct tge (transl_function f)
+ (Plbz (ireg_of dst)) (Plbzx (ireg_of dst))
+ Mint8unsigned addr args
+ (Pextsb (ireg_of dst) (ireg_of dst) :: transl_code c)
+ ms sp rs1 m dst a v'
+ X1 X2 AG H3 H7 LOAD').
+ intros [rs2 [EX1 AG1]].
+ exists (nextinstr (rs2#(ireg_of dst) <- v)).
+ split. eapply exec_straight_trans. eexact EX1.
+ apply exec_straight_one. simpl.
+ rewrite <- (ireg_val _ _ _ dst AG1);auto. rewrite Regmap.gss.
+ rewrite EQ1. reflexivity. reflexivity.
+ eauto with ppcgen.
+Qed.
+
+Lemma exec_Mstore_prop:
+ forall (f : function) (sp : val) (chunk : memory_chunk)
+ (addr : addressing) (args : list mreg) (src : mreg)
+ (c : list Mach.instruction) (ms: Mach.regset) (m m' : mem)
+ (a : val),
+ eval_addressing ge sp addr ms ## args = Some a ->
+ storev chunk m a (ms src) = Some m' ->
+ exec_instr_prop f sp (Mstore chunk addr args src :: c) ms m c ms m'.
+Proof.
+ intros; red; intros.
+ generalize (wt_function_instrs _ WTF _ (INCL _ (in_eq _ _))).
+ intro WTI; inversion WTI.
+ rewrite <- (eval_addressing_preserved symbols_preserved) in H.
+ eapply exec_straight_exec_prop; eauto.
+ destruct chunk; simpl; simpl in H6;
+ try (rewrite storev_8_signed_unsigned in H);
+ try (rewrite storev_16_signed_unsigned in H);
+ simpl; eapply transl_store_correct; eauto;
+ intros; unfold preg_of; rewrite H6; reflexivity.
+Qed.
+
+Hypothesis wt_prog: wt_program prog.
+
+Lemma exec_Mcall_prop:
+ forall (f : function) (sp : val) (sig : signature)
+ (mos : mreg + ident) (c : list Mach.instruction) (ms : Mach.regset)
+ (m : mem) (f' : function) (ms' : Mach.regset) (m' : mem),
+ find_function ge mos ms = Some f' ->
+ exec_function ge f' sp ms m ms' m' ->
+ exec_function_prop f' sp ms m ms' m' ->
+ exec_instr_prop f sp (Mcall sig mos :: c) ms m c ms' m'.
+Proof.
+ intros; red; intros.
+ generalize (wt_function_instrs _ WTF _ (INCL _ (in_eq _ _))).
+ intro WTI. inversion WTI.
+ inversion AT.
+ assert (WTF': wt_function f').
+ destruct mos; simpl in H.
+ apply (Genv.find_funct_prop wt_function wt_prog H).
+ destruct (Genv.find_symbol ge i); try discriminate.
+ apply (Genv.find_funct_ptr_prop wt_function wt_prog H).
+ assert (NOOV: code_size (transl_function f) <= Int.max_unsigned).
+ eapply functions_translated_no_overflow; eauto.
+ destruct mos; simpl in H; simpl transl_code in H7.
+ (* Indirect call *)
+ generalize (code_tail_next_int _ _ _ _ NOOV H7). intro CT1.
+ generalize (code_tail_next_int _ _ _ _ NOOV CT1). intro CT2.
+ set (rs2 := nextinstr (rs1#CTR <- (ms m0))).
+ set (rs3 := rs2 #LR <- (Val.add rs2#PC Vone) #PC <- (ms m0)).
+ assert (TFIND: Genv.find_funct ge (rs3#PC) = Some f').
+ unfold rs3. rewrite Pregmap.gss. auto.
+ assert (AG3: agree ms sp rs3).
+ unfold rs3, rs2; auto 8 with ppcgen.
+ assert (WTRA: Val.has_type rs3#LR Tint).
+ change rs3#LR with (Val.add (Val.add rs1#PC Vone) Vone).
+ rewrite <- H5. exact I.
+ generalize (H1 rs3 WTF' TFIND AG3 WTRA).
+ intros [rs4 [AG4 [EXF' PC4]]].
+ exists rs4. split. auto. split.
+ apply exec_trans with rs2 m. apply exec_one. econstructor.
+ eauto. apply functions_translated. eexact H6.
+ rewrite find_instr_tail. rewrite H7. reflexivity.
+ simpl. rewrite <- (ireg_val ms sp rs1); auto.
+ apply exec_trans with rs3 m. apply exec_one. econstructor.
+ unfold rs2, nextinstr. rewrite Pregmap.gss.
+ rewrite Pregmap.gso. rewrite <- H5. simpl. reflexivity.
+ discriminate. apply functions_translated. eexact H6.
+ rewrite find_instr_tail. rewrite CT1. reflexivity.
+ simpl. replace (rs2 CTR) with (ms m0). reflexivity.
+ unfold rs2. rewrite nextinstr_inv. rewrite Pregmap.gss.
+ auto. discriminate.
+ exact EXF'.
+ rewrite PC4. unfold rs3. rewrite Pregmap.gso. rewrite Pregmap.gss.
+ unfold rs2, nextinstr. rewrite Pregmap.gss. rewrite Pregmap.gso.
+ rewrite <- H5. simpl. constructor. auto. auto.
+ discriminate. discriminate.
+ (* Direct call *)
+ caseEq (Genv.find_symbol ge i). intros fblock FINDS.
+ rewrite FINDS in H.
+ generalize (code_tail_next_int _ _ _ _ NOOV H7). intro CT1.
+ set (rs2 := rs1 #LR <- (Val.add rs1#PC Vone) #PC <- (symbol_offset tge i Int.zero)).
+ assert (TFIND: Genv.find_funct ge (rs2#PC) = Some f').
+ unfold rs2. rewrite Pregmap.gss.
+ unfold symbol_offset. rewrite symbols_preserved.
+ rewrite FINDS.
+ rewrite Genv.find_funct_find_funct_ptr. assumption.
+ assert (AG2: agree ms sp rs2).
+ unfold rs2; auto 8 with ppcgen.
+ assert (WTRA: Val.has_type rs2#LR Tint).
+ change rs2#LR with (Val.add rs1#PC Vone).
+ rewrite <- H5. exact I.
+ generalize (H1 rs2 WTF' TFIND AG2 WTRA).
+ intros [rs3 [AG3 [EXF' PC3]]].
+ exists rs3. split. auto. split.
+ apply exec_trans with rs2 m. apply exec_one. econstructor.
+ eauto. apply functions_translated. eexact H6.
+ rewrite find_instr_tail. rewrite H7. reflexivity.
+ simpl. reflexivity.
+ exact EXF'.
+ rewrite PC3. unfold rs2. rewrite Pregmap.gso. rewrite Pregmap.gss.
+ rewrite <- H5. simpl. constructor. auto. auto.
+ discriminate.
+ intro FINDS. rewrite FINDS in H. discriminate.
+Qed.
+
+Lemma exec_Mgoto_prop:
+ forall (f : function) (sp : val) (lbl : Mach.label)
+ (c : list Mach.instruction) (ms : Mach.regset) (m : mem)
+ (c' : Mach.code),
+ Mach.find_label lbl (fn_code f) = Some c' ->
+ exec_instr_prop f sp (Mgoto lbl :: c) ms m c' ms m.
+Proof.
+ intros; red; intros.
+ inversion AT.
+ generalize (find_label_goto_label f lbl rs1 m _ _ _ H1 (sym_equal H0) H).
+ intros [rs2 [GOTO [AT2 INV]]].
+ exists rs2. split. apply agree_exten_2 with rs1; auto.
+ split. inversion AT. apply exec_one. econstructor; eauto.
+ apply functions_translated; eauto.
+ rewrite find_instr_tail. rewrite H7. simpl. reflexivity.
+ simpl. rewrite GOTO. auto. auto.
+Qed.
+
+Lemma exec_Mcond_true_prop:
+ forall (f : function) (sp : val) (cond : condition)
+ (args : list mreg) (lbl : Mach.label) (c : list Mach.instruction)
+ (ms: Mach.regset) (m : mem) (c' : Mach.code),
+ eval_condition cond ms ## args = Some true ->
+ Mach.find_label lbl (fn_code f) = Some c' ->
+ exec_instr_prop f sp (Mcond cond args lbl :: c) ms m c' ms m.
+Proof.
+ intros; red; intros.
+ generalize (wt_function_instrs _ WTF _ (INCL _ (in_eq _ _))).
+ intro WTI. inversion WTI.
+ pose (k1 :=
+ if snd (crbit_for_cond cond)
+ then Pbt (fst (crbit_for_cond cond)) lbl :: transl_code c
+ else Pbf (fst (crbit_for_cond cond)) lbl :: transl_code c).
+ generalize (transl_cond_correct tge (transl_function f)
+ cond args k1 ms sp rs1 m true H2 AG H).
+ simpl. intros [rs2 [EX [RES AG2]]].
+ inversion AT.
+ generalize (functions_translated _ _ H6); intro FN.
+ generalize (functions_translated_no_overflow _ _ H6); intro NOOV.
+ simpl in H7.
+ generalize (exec_straight_steps_2 _ _ _ _ _ _ _ EX
+ NOOV _ _ (sym_equal H5) FN H7).
+ intros [ofs' [PC2 CT2]].
+ generalize (find_label_goto_label f lbl rs2 m _ _ _ H6 PC2 H0).
+ intros [rs3 [GOTO [AT3 INV3]]].
+ exists rs3. split.
+ apply agree_exten_2 with rs2; auto.
+ split. eapply exec_trans.
+ eapply exec_straight_steps_1; eauto.
+ caseEq (snd (crbit_for_cond cond)); intro ISSET; rewrite ISSET in RES.
+ apply exec_one. econstructor; eauto.
+ rewrite find_instr_tail. rewrite CT2. unfold k1. rewrite ISSET. reflexivity.
+ simpl. rewrite RES. simpl. auto.
+ apply exec_one. econstructor; eauto.
+ rewrite find_instr_tail. rewrite CT2. unfold k1. rewrite ISSET. reflexivity.
+ simpl. rewrite RES. simpl. auto.
+ auto.
+Qed.
+
+Lemma exec_Mcond_false_prop:
+ forall (f : function) (sp : val) (cond : condition)
+ (args : list mreg) (lbl : Mach.label) (c : list Mach.instruction)
+ (ms : Mach.regset) (m : mem),
+ eval_condition cond ms ## args = Some false ->
+ exec_instr_prop f sp (Mcond cond args lbl :: c) ms m c ms m.
+Proof.
+ intros; red; intros.
+ generalize (wt_function_instrs _ WTF _ (INCL _ (in_eq _ _))).
+ intro WTI. inversion WTI.
+ pose (k1 :=
+ if snd (crbit_for_cond cond)
+ then Pbt (fst (crbit_for_cond cond)) lbl :: transl_code c
+ else Pbf (fst (crbit_for_cond cond)) lbl :: transl_code c).
+ generalize (transl_cond_correct tge (transl_function f)
+ cond args k1 ms sp rs1 m false H1 AG H).
+ simpl. intros [rs2 [EX [RES AG2]]].
+ exists (nextinstr rs2).
+ split. auto with ppcgen.
+ eapply exec_straight_steps; eauto.
+ eapply exec_straight_trans. eexact EX.
+ caseEq (snd (crbit_for_cond cond)); intro ISSET; rewrite ISSET in RES.
+ unfold k1; rewrite ISSET; apply exec_straight_one.
+ simpl. rewrite RES. reflexivity.
+ reflexivity.
+ unfold k1; rewrite ISSET; apply exec_straight_one.
+ simpl. rewrite RES. reflexivity.
+ reflexivity.
+Qed.
+
+Lemma exec_instr_incl:
+ forall f sp c rs m c' rs' m',
+ Mach.exec_instr ge f sp c rs m c' rs' m' ->
+ incl c f.(fn_code) -> incl c' f.(fn_code).
+Proof.
+ induction 1; intros; eauto with coqlib.
+ eapply incl_find_label; eauto.
+ eapply incl_find_label; eauto.
+Qed.
+
+Lemma exec_instrs_incl:
+ forall f sp c rs m c' rs' m',
+ Mach.exec_instrs ge f sp c rs m c' rs' m' ->
+ incl c f.(fn_code) -> incl c' f.(fn_code).
+Proof.
+ induction 1; intros.
+ auto.
+ eapply exec_instr_incl; eauto.
+ eauto.
+Qed.
+
+Lemma exec_refl_prop:
+ forall (f : function) (sp : val) (c : Mach.code) (ms : Mach.regset)
+ (m : mem), exec_instr_prop f sp c ms m c ms m.
+Proof.
+ intros; red; intros.
+ exists rs1. split. auto. split. apply exec_refl. auto.
+Qed.
+
+Lemma exec_one_prop:
+ forall (f : function) (sp : val) (c : Mach.code) (ms : Mach.regset)
+ (m : mem) (c' : Mach.code) (ms' : Mach.regset) (m' : mem),
+ Mach.exec_instr ge f sp c ms m c' ms' m' ->
+ exec_instr_prop f sp c ms m c' ms' m' ->
+ exec_instr_prop f sp c ms m c' ms' m'.
+Proof.
+ auto.
+Qed.
+
+Lemma exec_trans_prop:
+ forall (f : function) (sp : val) (c1 : Mach.code) (ms1 : Mach.regset)
+ (m1 : mem) (c2 : Mach.code) (ms2 : Mach.regset) (m2 : mem)
+ (c3 : Mach.code) (ms3 : Mach.regset) (m3 : mem),
+ exec_instrs ge f sp c1 ms1 m1 c2 ms2 m2 ->
+ exec_instr_prop f sp c1 ms1 m1 c2 ms2 m2 ->
+ exec_instrs ge f sp c2 ms2 m2 c3 ms3 m3 ->
+ exec_instr_prop f sp c2 ms2 m2 c3 ms3 m3 ->
+ exec_instr_prop f sp c1 ms1 m1 c3 ms3 m3.
+Proof.
+ intros; red; intros.
+ generalize (H0 rs1 WTF INCL AT AG).
+ intros [rs2 [AG2 [EX2 AT2]]].
+ generalize (exec_instrs_incl _ _ _ _ _ _ _ _ H INCL). intro INCL2.
+ generalize (H2 rs2 WTF INCL2 AT2 AG2).
+ intros [rs3 [AG3 [EX3 AT3]]].
+ exists rs3. split. auto. split. eapply exec_trans; eauto. auto.
+Qed.
+
+Lemma exec_function_body_prop_:
+ forall (f : function) (parent ra : val) (ms : Mach.regset) (m : mem)
+ (ms' : Mach.regset) (m1 m2 m3 m4 : mem) (stk : block)
+ (c : list Mach.instruction),
+ alloc m (- fn_framesize f)
+ (align_16_top (- fn_framesize f) (fn_stacksize f)) = (m1, stk) ->
+ let sp := Vptr stk (Int.repr (- fn_framesize f)) in
+ store_stack m1 sp Tint (Int.repr 0) parent = Some m2 ->
+ store_stack m2 sp Tint (Int.repr 4) ra = Some m3 ->
+ exec_instrs ge f sp (fn_code f) ms m3 (Mreturn :: c) ms' m4 ->
+ exec_instr_prop f sp (fn_code f) ms m3 (Mreturn :: c) ms' m4 ->
+ load_stack m4 sp Tint (Int.repr 0) = Some parent ->
+ load_stack m4 sp Tint (Int.repr 4) = Some ra ->
+ exec_function_body_prop f parent ra ms m ms' (free m4 stk).
+Proof.
+ intros; red; intros.
+ generalize (Genv.find_funct_inv AT). intros [b EQPC].
+ generalize AT. rewrite EQPC. rewrite Genv.find_funct_find_funct_ptr. intro FN.
+ generalize (functions_translated_no_overflow _ _ FN); intro NOOV.
+ set (rs2 := nextinstr (rs1#GPR1 <- sp #GPR2 <- Vundef)).
+ set (rs3 := nextinstr (rs2#GPR2 <- ra)).
+ set (rs4 := nextinstr rs3).
+ assert (exec_straight tge (transl_function f)
+ (transl_function f) rs1 m
+ (transl_code (fn_code f)) rs4 m3).
+ unfold transl_function at 2.
+ apply exec_straight_three with rs2 m2 rs3 m2.
+ unfold exec_instr. rewrite H. fold sp.
+ generalize H0. unfold store_stack. change (Vint (Int.repr 0)) with Vzero.
+ replace (Val.add sp Vzero) with sp. simpl chunk_of_type.
+ rewrite (sp_val _ _ _ AG). intro. rewrite H6. clear H6.
+ reflexivity. unfold sp. simpl. rewrite Int.add_zero. reflexivity.
+ simpl. replace (rs2 LR) with ra. reflexivity.
+ simpl. unfold store1. rewrite gpr_or_zero_not_zero.
+ unfold const_low. replace (rs3 GPR1) with sp. replace (rs3 GPR2) with ra.
+ unfold store_stack in H1. simpl chunk_of_type in H1. rewrite H1. reflexivity.
+ reflexivity. reflexivity. discriminate.
+ reflexivity. reflexivity. reflexivity.
+ assert (AT2: transl_code_at_pc rs4#PC f f.(fn_code)).
+ change (rs4 PC) with (Val.add (Val.add (Val.add (rs1 PC) Vone) Vone) Vone).
+ rewrite EQPC. simpl. constructor. auto.
+ eapply code_tail_next_int; auto.
+ eapply code_tail_next_int; auto.
+ eapply code_tail_next_int; auto.
+ unfold Int.zero. rewrite Int.unsigned_repr.
+ rewrite code_tail_zero. unfold transl_function. reflexivity.
+ compute. intuition congruence.
+ assert (AG2: agree ms sp rs2).
+ split. reflexivity.
+ intros. unfold rs2. rewrite nextinstr_inv.
+ repeat (rewrite Pregmap.gso). elim AG; auto.
+ auto with ppcgen. auto with ppcgen. auto with ppcgen.
+ assert (AG4: agree ms sp rs4).
+ unfold rs4, rs3; auto with ppcgen.
+ generalize (H3 rs4 WTF (incl_refl _) AT2 AG4).
+ intros [rs5 [AG5 [EXB AT5]]].
+ set (rs6 := nextinstr (rs5#GPR2 <- ra)).
+ set (rs7 := nextinstr (rs6#LR <- ra)).
+ set (rs8 := nextinstr (rs7#GPR1 <- parent)).
+ set (rs9 := rs8#PC <- ra).
+ assert (exec_straight tge (transl_function f)
+ (transl_code (Mreturn :: c)) rs5 m4
+ (Pblr :: transl_code c) rs8 (free m4 stk)).
+ simpl. apply exec_straight_three with rs6 m4 rs7 m4.
+ simpl. unfold load1. rewrite gpr_or_zero_not_zero. unfold const_low.
+ unfold load_stack in H5. simpl in H5.
+ rewrite <- (sp_val _ _ _ AG5). simpl. rewrite H5.
+ reflexivity. discriminate.
+ unfold rs7. change ra with rs6#GPR2. reflexivity.
+ unfold exec_instr. generalize H4. unfold load_stack.
+ replace (Val.add sp (Vint (Int.repr 0))) with sp.
+ simpl chunk_of_type. intro. change rs7#GPR1 with rs5#GPR1.
+ rewrite <- (sp_val _ _ _ AG5). rewrite H7.
+ unfold sp. reflexivity.
+ unfold sp. simpl. rewrite Int.add_zero. reflexivity.
+ reflexivity. reflexivity. reflexivity.
+ exists rs9. split.
+ (* agreement *)
+ assert (AG7: agree ms' sp rs7).
+ unfold rs7, rs6; auto 10 with ppcgen.
+ assert (AG8: agree ms' parent rs8).
+ split. reflexivity. intros. unfold rs8.
+ rewrite nextinstr_inv. rewrite Pregmap.gso.
+ elim AG7; auto. auto with ppcgen. auto with ppcgen.
+ unfold rs9; auto with ppcgen.
+ (* execution *)
+ split. apply exec_trans with rs4 m3.
+ eapply exec_straight_steps_1; eauto.
+ apply functions_translated; auto.
+ apply exec_trans with rs5 m4. assumption.
+ inversion AT5.
+ apply exec_trans with rs8 (free m4 stk).
+ eapply exec_straight_steps_1; eauto.
+ apply functions_translated; auto.
+ apply exec_one. econstructor.
+ change rs8#PC with (Val.add (Val.add (Val.add rs5#PC Vone) Vone) Vone).
+ rewrite <- H8. simpl. reflexivity.
+ apply functions_translated; eauto.
+ assert (code_tail (Int.unsigned (Int.add (Int.add (Int.add ofs Int.one) Int.one) Int.one))
+ (transl_function f) = Pblr :: transl_code c).
+ eapply code_tail_next_int; auto.
+ eapply code_tail_next_int; auto.
+ eapply code_tail_next_int; auto.
+ rewrite H10. simpl. reflexivity.
+ rewrite find_instr_tail. rewrite H13.
+ reflexivity.
+ reflexivity.
+ (* LR preservation *)
+ change rs9#PC with ra. auto.
+Qed.
+
+Lemma exec_function_prop_:
+ forall (f : function) (parent : val) (ms : Mach.regset) (m : mem)
+ (ms' : Mach.regset) (m' : mem),
+ (forall ra : val,
+ Val.has_type ra Tint ->
+ exec_function_body ge f parent ra ms m ms' m') ->
+ (forall ra : val, Val.has_type ra Tint ->
+ exec_function_body_prop f parent ra ms m ms' m') ->
+ exec_function_prop f parent ms m ms' m'.
+Proof.
+ intros; red; intros.
+ apply (H0 rs1#LR WTRA rs1 WTRA (refl_equal _) WTF AT AG).
+Qed.
+
+(** We then conclude by induction on the structure of the Mach
+execution derivation. *)
+
+Theorem transf_function_correct:
+ forall f parent ms m ms' m',
+ Mach.exec_function ge f parent ms m ms' m' ->
+ exec_function_prop f parent ms m ms' m'.
+Proof
+ (Mach.exec_function_ind4 ge
+ exec_instr_prop exec_instr_prop
+ exec_function_body_prop exec_function_prop
+
+ exec_Mlabel_prop
+ exec_Mgetstack_prop
+ exec_Msetstack_prop
+ exec_Mgetparam_prop
+ exec_Mop_prop
+ exec_Mload_prop
+ exec_Mstore_prop
+ exec_Mcall_prop
+ exec_Mgoto_prop
+ exec_Mcond_true_prop
+ exec_Mcond_false_prop
+ exec_refl_prop
+ exec_one_prop
+ exec_trans_prop
+ exec_function_body_prop_
+ exec_function_prop_).
+
+End PRESERVATION.
+
+Theorem transf_program_correct:
+ forall (p: Mach.program) (tp: PPC.program) (r: val),
+ wt_program p ->
+ transf_program p = Some tp ->
+ Mach.exec_program p r ->
+ PPC.exec_program tp r.
+Proof.
+ intros.
+ destruct H1 as [fptr [f [ms [m [FINDS [FINDF [EX RES]]]]]]].
+ assert (WTF: wt_function f).
+ apply (Genv.find_funct_ptr_prop wt_function H FINDF).
+ set (ge := Genv.globalenv p) in *.
+ set (ms0 := Regmap.init Vundef) in *.
+ set (tge := Genv.globalenv tp).
+ set (rs0 :=
+ (Pregmap.init Vundef) # PC <- (symbol_offset tge tp.(prog_main) Int.zero)
+ # LR <- Vzero
+ # GPR1 <- (Vptr Mem.nullptr Int.zero)).
+ assert (AT: Genv.find_funct ge (rs0 PC) = Some f).
+ change (rs0 PC) with (symbol_offset tge tp.(prog_main) Int.zero).
+ rewrite (transform_partial_program_main _ _ H0).
+ unfold symbol_offset. rewrite (symbols_preserved p tp H0).
+ fold ge. rewrite FINDS.
+ rewrite Genv.find_funct_find_funct_ptr. exact FINDF.
+ assert (AG: agree ms0 (Vptr Mem.nullptr Int.zero) rs0).
+ split. reflexivity. intros. unfold rs0.
+ repeat (rewrite Pregmap.gso; auto with ppcgen).
+ assert (WTRA: Val.has_type (rs0 LR) Tint).
+ exact I.
+ generalize (transf_function_correct p tp H0 H
+ _ _ _ _ _ _ EX rs0 WTF AT AG WTRA).
+ intros [rs [AG' [EX' RPC]]].
+ red. exists rs; exists m.
+ split. rewrite (Genv.init_mem_transf_partial _ _ H0). exact EX'.
+ split. rewrite RPC. reflexivity. rewrite <- RES.
+ change (IR GPR3) with (preg_of R3). elim AG'; auto.
+Qed.