From 6d25b4f3fc23601b3a84b4a70aab40ba429ac4b9 Mon Sep 17 00:00:00 2001 From: xleroy Date: Tue, 30 Dec 2008 14:48:33 +0000 Subject: Reorganized the development, modularizing away machine-dependent parts. Started to merge the ARM code generator. Started to add support for PowerPC/EABI. Use ocamlbuild to construct executable from Caml files. git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@930 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e --- powerpc/Asmgenproof1.v | 1632 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1632 insertions(+) create mode 100644 powerpc/Asmgenproof1.v (limited to 'powerpc/Asmgenproof1.v') diff --git a/powerpc/Asmgenproof1.v b/powerpc/Asmgenproof1.v new file mode 100644 index 00000000..c17cb737 --- /dev/null +++ b/powerpc/Asmgenproof1.v @@ -0,0 +1,1632 @@ +(* *********************************************************************) +(* *) +(* The Compcert verified compiler *) +(* *) +(* Xavier Leroy, INRIA Paris-Rocquencourt *) +(* *) +(* Copyright Institut National de Recherche en Informatique et en *) +(* Automatique. All rights reserved. This file is distributed *) +(* under the terms of the INRIA Non-Commercial License Agreement. *) +(* *) +(* *********************************************************************) + +(** Correctness proof for PPC generation: auxiliary results. *) + +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 Machconcr. +Require Import Machtyping. +Require Import Asm. +Require Import Asmgen. +Require Conventions. + +(** * Properties of low half/high half decomposition *) + +Lemma high_half_zero: + forall v, Val.add (high_half v) Vzero = high_half v. +Proof. + intros. generalize (high_half_type v). + rewrite Val.add_commut. + case (high_half v); simpl; intros; try contradiction. + auto. + rewrite Int.add_commut; rewrite Int.add_zero; auto. + rewrite Int.add_zero; auto. +Qed. + +Lemma low_high_u: + forall n, Int.or (Int.shl (high_u n) (Int.repr 16)) (low_u n) = n. +Proof. + intros. unfold high_u, low_u. + rewrite Int.shl_rolm. rewrite Int.shru_rolm. + rewrite Int.rolm_rolm. + change (Int.modu (Int.add (Int.sub (Int.repr (Z_of_nat wordsize)) (Int.repr 16)) + (Int.repr 16)) + (Int.repr (Z_of_nat wordsize))) + with (Int.zero). + rewrite Int.rolm_zero. rewrite <- Int.and_or_distrib. + exact (Int.and_mone n). + reflexivity. reflexivity. +Qed. + +Lemma low_high_u_xor: + forall n, Int.xor (Int.shl (high_u n) (Int.repr 16)) (low_u n) = n. +Proof. + intros. unfold high_u, low_u. + rewrite Int.shl_rolm. rewrite Int.shru_rolm. + rewrite Int.rolm_rolm. + change (Int.modu (Int.add (Int.sub (Int.repr (Z_of_nat wordsize)) (Int.repr 16)) + (Int.repr 16)) + (Int.repr (Z_of_nat wordsize))) + with (Int.zero). + rewrite Int.rolm_zero. rewrite <- Int.and_xor_distrib. + exact (Int.and_mone n). + reflexivity. reflexivity. +Qed. + +Lemma low_high_s: + forall n, Int.add (Int.shl (high_s n) (Int.repr 16)) (low_s n) = n. +Proof. + intros. rewrite Int.shl_mul_two_p. + unfold high_s. + rewrite <- (Int.divu_pow2 (Int.sub n (low_s n)) (Int.repr 65536) (Int.repr 16)). + change (two_p (Int.unsigned (Int.repr 16))) with 65536. + + assert (forall x y, y > 0 -> (x - x mod y) mod y = 0). + intros. apply Zmod_unique with (x / y). + generalize (Z_div_mod_eq x y H). intro. rewrite Zmult_comm. omega. + omega. + + assert (Int.modu (Int.sub n (low_s n)) (Int.repr 65536) = Int.zero). + unfold Int.modu, Int.zero. decEq. + change (Int.unsigned (Int.repr 65536)) with 65536. + unfold Int.sub. + assert (forall a b, Int.eqm a b -> b mod 65536 = 0 -> a mod 65536 = 0). + intros a b [k EQ] H1. rewrite EQ. + change modulus with (65536 * 65536). + rewrite Zmult_assoc. rewrite Zplus_comm. rewrite Z_mod_plus. auto. + omega. + eapply H0. apply Int.eqm_sym. apply Int.eqm_unsigned_repr. + unfold low_s. unfold Int.sign_ext. + change (two_p 16) with 65536. change (two_p (16-1)) with 32768. + set (N := Int.unsigned n). + case (zlt (N mod 65536) 32768); intro. + apply H0 with (N - N mod 65536). auto with ints. + apply H. omega. + apply H0 with (N - (N mod 65536 - 65536)). auto with ints. + replace (N - (N mod 65536 - 65536)) + with ((N - N mod 65536) + 1 * 65536). + rewrite Z_mod_plus. apply H. omega. omega. ring. + + assert (Int.repr 65536 <> Int.zero). compute. congruence. + generalize (Int.modu_divu_Euclid (Int.sub n (low_s n)) (Int.repr 65536) H1). + rewrite H0. rewrite Int.add_zero. intro. rewrite <- H2. + rewrite Int.sub_add_opp. rewrite Int.add_assoc. + replace (Int.add (Int.neg (low_s n)) (low_s n)) with Int.zero. + apply Int.add_zero. symmetry. rewrite Int.add_commut. + rewrite <- Int.sub_add_opp. apply Int.sub_idem. + + reflexivity. +Qed. + +(** * Correspondence between Mach registers and PPC registers *) + +Hint Extern 2 (_ <> _) => discriminate: ppcgen. + +(** Mapping from Mach registers to PPC registers. *) + +Lemma preg_of_injective: + forall r1 r2, preg_of r1 = preg_of r2 -> r1 = r2. +Proof. + destruct r1; destruct r2; simpl; intros; reflexivity || discriminate. +Qed. + +(** Characterization of PPC registers that correspond to Mach registers. *) + +Definition is_data_reg (r: preg) : Prop := + match r with + | IR GPR12 => False + | FR FPR13 => False + | PC => False | LR => False | CTR => False + | CR0_0 => False | CR0_1 => False | CR0_2 => False | CR0_3 => False + | CARRY => False + | _ => True + end. + +Lemma ireg_of_is_data_reg: + forall (r: mreg), is_data_reg (ireg_of r). +Proof. + destruct r; exact I. +Qed. + +Lemma freg_of_is_data_reg: + forall (r: mreg), is_data_reg (ireg_of r). +Proof. + destruct r; exact I. +Qed. + +Lemma preg_of_is_data_reg: + forall (r: mreg), is_data_reg (preg_of r). +Proof. + destruct r; exact I. +Qed. + +Lemma ireg_of_not_GPR1: + forall r, ireg_of r <> GPR1. +Proof. + intro. case r; discriminate. +Qed. +Lemma ireg_of_not_GPR12: + forall r, ireg_of r <> GPR12. +Proof. + intro. case r; discriminate. +Qed. +Lemma freg_of_not_FPR13: + forall r, freg_of r <> FPR13. +Proof. + intro. case r; discriminate. +Qed. +Hint Resolve ireg_of_not_GPR1 ireg_of_not_GPR12 freg_of_not_FPR13: ppcgen. + +Lemma preg_of_not: + forall r1 r2, ~(is_data_reg r2) -> preg_of r1 <> r2. +Proof. + intros; red; intro. subst r2. elim H. apply preg_of_is_data_reg. +Qed. +Hint Resolve preg_of_not: ppcgen. + +Lemma preg_of_not_GPR1: + forall r, preg_of r <> GPR1. +Proof. + intro. case r; discriminate. +Qed. +Hint Resolve preg_of_not_GPR1: ppcgen. + +(** Agreement between Mach register sets and PPC register sets. *) + +Definition agree (ms: Mach.regset) (sp: val) (rs: Asm.regset) := + rs#GPR1 = sp /\ forall r: mreg, ms r = rs#(preg_of r). + +Lemma preg_val: + forall ms sp rs r, + agree ms sp rs -> ms r = rs#(preg_of r). +Proof. + intros. elim H. auto. +Qed. + +Lemma ireg_val: + forall ms sp rs r, + agree ms sp rs -> + mreg_type r = Tint -> + ms r = rs#(ireg_of r). +Proof. + intros. elim H; intros. + generalize (H2 r). unfold preg_of. rewrite H0. auto. +Qed. + +Lemma freg_val: + forall ms sp rs r, + agree ms sp rs -> + mreg_type r = Tfloat -> + ms r = rs#(freg_of r). +Proof. + intros. elim H; intros. + generalize (H2 r). unfold preg_of. rewrite H0. auto. +Qed. + +Lemma sp_val: + forall ms sp rs, + agree ms sp rs -> + sp = rs#GPR1. +Proof. + intros. elim H; auto. +Qed. + +Lemma agree_exten_1: + forall ms sp rs rs', + agree ms sp rs -> + (forall r, is_data_reg r -> rs'#r = rs#r) -> + agree ms sp rs'. +Proof. + unfold agree; intros. elim H; intros. + split. rewrite H0. auto. exact I. + intros. rewrite H0. auto. apply preg_of_is_data_reg. +Qed. + +Lemma agree_exten_2: + forall ms sp rs rs', + agree ms sp rs -> + (forall r, + r <> IR GPR12 -> r <> FR FPR13 -> + r <> PC -> r <> LR -> r <> CTR -> + r <> CR0_0 -> r <> CR0_1 -> r <> CR0_2 -> r <> CR0_3 -> + r <> CARRY -> + rs'#r = rs#r) -> + agree ms sp rs'. +Proof. + intros. apply agree_exten_1 with rs. auto. + intros. apply H0; (red; intro; subst r; elim H1). +Qed. + +(** Preservation of register agreement under various assignments. *) + +Lemma agree_set_mreg: + forall ms sp rs r v, + agree ms sp rs -> + agree (Regmap.set r v ms) sp (rs#(preg_of r) <- v). +Proof. + unfold agree; intros. elim H; intros; clear H. + split. rewrite Pregmap.gso. auto. apply sym_not_eq. apply preg_of_not_GPR1. + intros. unfold Regmap.set. case (RegEq.eq r0 r); intro. + subst r0. rewrite Pregmap.gss. auto. + rewrite Pregmap.gso. auto. red; intro. + elim n. apply preg_of_injective; auto. +Qed. +Hint Resolve agree_set_mreg: ppcgen. + +Lemma agree_set_mireg: + forall ms sp rs r v, + agree ms sp (rs#(preg_of r) <- v) -> + mreg_type r = Tint -> + agree ms sp (rs#(ireg_of r) <- v). +Proof. + intros. unfold preg_of in H. rewrite H0 in H. auto. +Qed. +Hint Resolve agree_set_mireg: ppcgen. + +Lemma agree_set_mfreg: + forall ms sp rs r v, + agree ms sp (rs#(preg_of r) <- v) -> + mreg_type r = Tfloat -> + agree ms sp (rs#(freg_of r) <- v). +Proof. + intros. unfold preg_of in H. rewrite H0 in H. auto. +Qed. +Hint Resolve agree_set_mfreg: ppcgen. + +Lemma agree_set_other: + forall ms sp rs r v, + agree ms sp rs -> + ~(is_data_reg r) -> + agree ms sp (rs#r <- v). +Proof. + intros. apply agree_exten_1 with rs. + auto. intros. apply Pregmap.gso. red; intro; subst r0; contradiction. +Qed. +Hint Resolve agree_set_other: ppcgen. + +Lemma agree_nextinstr: + forall ms sp rs, + agree ms sp rs -> agree ms sp (nextinstr rs). +Proof. + intros. unfold nextinstr. apply agree_set_other. auto. auto. +Qed. +Hint Resolve agree_nextinstr: ppcgen. + +Lemma agree_set_mireg_twice: + forall ms sp rs r v v', + agree ms sp rs -> + mreg_type r = Tint -> + agree (Regmap.set r v ms) sp (rs #(ireg_of r) <- v' #(ireg_of r) <- v). +Proof. + intros. replace (IR (ireg_of r)) with (preg_of r). elim H; intros. + split. repeat (rewrite Pregmap.gso; auto with ppcgen). + intros. case (mreg_eq r r0); intro. + subst r0. rewrite Regmap.gss. rewrite Pregmap.gss. auto. + assert (preg_of r <> preg_of r0). + red; intro. elim n. apply preg_of_injective. auto. + rewrite Regmap.gso; auto. + repeat (rewrite Pregmap.gso; auto). + unfold preg_of. rewrite H0. auto. +Qed. +Hint Resolve agree_set_mireg_twice: ppcgen. + +Lemma agree_set_twice_mireg: + forall ms sp rs r v v', + agree (Regmap.set r v' ms) sp rs -> + mreg_type r = Tint -> + agree (Regmap.set r v ms) sp (rs#(ireg_of r) <- v). +Proof. + intros. elim H; intros. + split. rewrite Pregmap.gso. auto. + generalize (ireg_of_not_GPR1 r); congruence. + intros. generalize (H2 r0). + case (mreg_eq r0 r); intro. + subst r0. repeat rewrite Regmap.gss. unfold preg_of; rewrite H0. + rewrite Pregmap.gss. auto. + repeat rewrite Regmap.gso; auto. + rewrite Pregmap.gso. auto. + replace (IR (ireg_of r)) with (preg_of r). + red; intros. elim n. apply preg_of_injective; auto. + unfold preg_of. rewrite H0. auto. +Qed. +Hint Resolve agree_set_twice_mireg: ppcgen. + +Lemma agree_set_commut: + forall ms sp rs r1 r2 v1 v2, + r1 <> r2 -> + agree ms sp ((rs#r2 <- v2)#r1 <- v1) -> + agree ms sp ((rs#r1 <- v1)#r2 <- v2). +Proof. + intros. apply agree_exten_1 with ((rs#r2 <- v2)#r1 <- v1). auto. + intros. + case (preg_eq r r1); intro. + subst r1. rewrite Pregmap.gss. rewrite Pregmap.gso. rewrite Pregmap.gss. + auto. auto. + case (preg_eq r r2); intro. + subst r2. rewrite Pregmap.gss. rewrite Pregmap.gso. rewrite Pregmap.gss. + auto. auto. + repeat (rewrite Pregmap.gso; auto). +Qed. +Hint Resolve agree_set_commut: ppcgen. + +Lemma agree_nextinstr_commut: + forall ms sp rs r v, + agree ms sp (rs#r <- v) -> + r <> PC -> + agree ms sp ((nextinstr rs)#r <- v). +Proof. + intros. unfold nextinstr. apply agree_set_commut. auto. + apply agree_set_other. auto. auto. +Qed. +Hint Resolve agree_nextinstr_commut: ppcgen. + +Lemma agree_set_mireg_exten: + forall ms sp rs r v (rs': regset), + agree ms sp rs -> + mreg_type r = Tint -> + rs'#(ireg_of r) = v -> + (forall r', + r' <> IR GPR12 -> r' <> FR FPR13 -> + r' <> PC -> r' <> LR -> r' <> CTR -> + r' <> CR0_0 -> r' <> CR0_1 -> r' <> CR0_2 -> r' <> CR0_3 -> + r' <> CARRY -> + r' <> IR (ireg_of r) -> rs'#r' = rs#r') -> + agree (Regmap.set r v ms) sp rs'. +Proof. + intros. apply agree_exten_2 with (rs#(ireg_of r) <- v). + auto with ppcgen. + intros. unfold Pregmap.set. case (PregEq.eq r0 (ireg_of r)); intro. + subst r0. auto. apply H2; auto. +Qed. + +(** Useful properties of the PC and GPR0 registers. *) + +Lemma nextinstr_inv: + forall r rs, r <> PC -> (nextinstr rs)#r = rs#r. +Proof. + intros. unfold nextinstr. apply Pregmap.gso. auto. +Qed. +Hint Resolve nextinstr_inv: ppcgen. + +Lemma nextinstr_set_preg: + forall rs m v, + (nextinstr (rs#(preg_of m) <- v))#PC = Val.add rs#PC Vone. +Proof. + intros. unfold nextinstr. rewrite Pregmap.gss. + rewrite Pregmap.gso. auto. apply sym_not_eq. auto with ppcgen. +Qed. +Hint Resolve nextinstr_set_preg: ppcgen. + +Lemma gpr_or_zero_not_zero: + forall rs r, r <> GPR0 -> gpr_or_zero rs r = rs#r. +Proof. + intros. unfold gpr_or_zero. case (ireg_eq r GPR0); tauto. +Qed. +Lemma gpr_or_zero_zero: + forall rs, gpr_or_zero rs GPR0 = Vzero. +Proof. + intros. reflexivity. +Qed. +Hint Resolve gpr_or_zero_not_zero gpr_or_zero_zero: ppcgen. + +(** Connection between Mach and Asm calling conventions for external + functions. *) + +Lemma extcall_arg_match: + forall ms sp rs m l v, + agree ms sp rs -> + Machconcr.extcall_arg ms m sp l v -> + Asm.extcall_arg rs m l v. +Proof. + intros. inv H0. + rewrite (preg_val _ _ _ r H). constructor. + rewrite (sp_val _ _ _ H) in H1. + destruct ty; unfold load_stack in H1. + econstructor. reflexivity. assumption. + econstructor. reflexivity. assumption. +Qed. + +Lemma extcall_args_match: + forall ms sp rs m, agree ms sp rs -> + forall ll vl, + Machconcr.extcall_args ms m sp ll vl -> + Asm.extcall_args rs m ll vl. +Proof. + induction 2; constructor; auto. eapply extcall_arg_match; eauto. +Qed. + +Lemma extcall_arguments_match: + forall ms m sp rs sg args, + agree ms sp rs -> + Machconcr.extcall_arguments ms m sp sg args -> + Asm.extcall_arguments rs m sg args. +Proof. + unfold Machconcr.extcall_arguments, Asm.extcall_arguments; intros. + eapply extcall_args_match; eauto. +Qed. + +(** * Execution of straight-line code *) + +Section STRAIGHTLINE. + +Variable ge: genv. +Variable fn: code. + +(** Straight-line code is composed of PPC instructions that execute + in sequence (no branches, no function calls and returns). + The following inductive predicate relates the machine states + before and after executing a straight-line sequence of instructions. + Instructions are taken from the first list instead of being fetched + from memory. *) + +Inductive exec_straight: code -> regset -> mem -> + code -> regset -> mem -> Prop := + | exec_straight_one: + forall i1 c rs1 m1 rs2 m2, + exec_instr ge fn i1 rs1 m1 = OK rs2 m2 -> + rs2#PC = Val.add rs1#PC Vone -> + exec_straight (i1 :: c) rs1 m1 c rs2 m2 + | exec_straight_step: + forall i c rs1 m1 rs2 m2 c' rs3 m3, + exec_instr ge fn i rs1 m1 = OK rs2 m2 -> + rs2#PC = Val.add rs1#PC Vone -> + exec_straight c rs2 m2 c' rs3 m3 -> + exec_straight (i :: c) rs1 m1 c' rs3 m3. + +Lemma exec_straight_trans: + forall c1 rs1 m1 c2 rs2 m2 c3 rs3 m3, + exec_straight c1 rs1 m1 c2 rs2 m2 -> + exec_straight c2 rs2 m2 c3 rs3 m3 -> + exec_straight c1 rs1 m1 c3 rs3 m3. +Proof. + induction 1; intros. + apply exec_straight_step with rs2 m2; auto. + apply exec_straight_step with rs2 m2; auto. +Qed. + +Lemma exec_straight_two: + forall i1 i2 c rs1 m1 rs2 m2 rs3 m3, + exec_instr ge fn i1 rs1 m1 = OK rs2 m2 -> + exec_instr ge fn i2 rs2 m2 = OK rs3 m3 -> + rs2#PC = Val.add rs1#PC Vone -> + rs3#PC = Val.add rs2#PC Vone -> + exec_straight (i1 :: i2 :: c) rs1 m1 c rs3 m3. +Proof. + intros. apply exec_straight_step with rs2 m2; auto. + apply exec_straight_one; auto. +Qed. + +Lemma exec_straight_three: + forall i1 i2 i3 c rs1 m1 rs2 m2 rs3 m3 rs4 m4, + exec_instr ge fn i1 rs1 m1 = OK rs2 m2 -> + exec_instr ge fn i2 rs2 m2 = OK rs3 m3 -> + exec_instr ge fn i3 rs3 m3 = OK rs4 m4 -> + rs2#PC = Val.add rs1#PC Vone -> + rs3#PC = Val.add rs2#PC Vone -> + rs4#PC = Val.add rs3#PC Vone -> + exec_straight (i1 :: i2 :: i3 :: c) rs1 m1 c rs4 m4. +Proof. + intros. apply exec_straight_step with rs2 m2; auto. + eapply exec_straight_two; eauto. +Qed. + +(** * Correctness of PowerPC constructor functions *) + +(** Properties of comparisons. *) + +Lemma compare_float_spec: + forall rs v1 v2, + let rs1 := nextinstr (compare_float rs v1 v2) in + rs1#CR0_0 = Val.cmpf Clt v1 v2 + /\ rs1#CR0_1 = Val.cmpf Cgt v1 v2 + /\ rs1#CR0_2 = Val.cmpf Ceq v1 v2 + /\ forall r', r' <> PC -> r' <> CR0_0 -> r' <> CR0_1 -> + r' <> CR0_2 -> r' <> CR0_3 -> rs1#r' = rs#r'. +Proof. + intros. unfold rs1. + split. reflexivity. + split. reflexivity. + split. reflexivity. + intros. rewrite nextinstr_inv; auto. + unfold compare_float. repeat (rewrite Pregmap.gso; auto). +Qed. + +Lemma compare_sint_spec: + forall rs v1 v2, + let rs1 := nextinstr (compare_sint rs v1 v2) in + rs1#CR0_0 = Val.cmp Clt v1 v2 + /\ rs1#CR0_1 = Val.cmp Cgt v1 v2 + /\ rs1#CR0_2 = Val.cmp Ceq v1 v2 + /\ forall r', r' <> PC -> r' <> CR0_0 -> r' <> CR0_1 -> + r' <> CR0_2 -> r' <> CR0_3 -> rs1#r' = rs#r'. +Proof. + intros. unfold rs1. + split. reflexivity. + split. reflexivity. + split. reflexivity. + intros. rewrite nextinstr_inv; auto. + unfold compare_sint. repeat (rewrite Pregmap.gso; auto). +Qed. + +Lemma compare_uint_spec: + forall rs v1 v2, + let rs1 := nextinstr (compare_uint rs v1 v2) in + rs1#CR0_0 = Val.cmpu Clt v1 v2 + /\ rs1#CR0_1 = Val.cmpu Cgt v1 v2 + /\ rs1#CR0_2 = Val.cmpu Ceq v1 v2 + /\ forall r', r' <> PC -> r' <> CR0_0 -> r' <> CR0_1 -> + r' <> CR0_2 -> r' <> CR0_3 -> rs1#r' = rs#r'. +Proof. + intros. unfold rs1. + split. reflexivity. + split. reflexivity. + split. reflexivity. + intros. rewrite nextinstr_inv; auto. + unfold compare_uint. repeat (rewrite Pregmap.gso; auto). +Qed. + +(** Loading a constant. *) + +Lemma loadimm_correct: + forall r n k rs m, + exists rs', + exec_straight (loadimm r n k) rs m k rs' m + /\ rs'#r = Vint n + /\ forall r': preg, r' <> r -> r' <> PC -> rs'#r' = rs#r'. +Proof. + intros. unfold loadimm. + case (Int.eq (high_s n) Int.zero). + (* addi *) + exists (nextinstr (rs#r <- (Vint n))). + split. apply exec_straight_one. + simpl. rewrite Int.add_commut. rewrite Int.add_zero. reflexivity. + reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. + apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. apply Pregmap.gso; auto. + (* addis *) + generalize (Int.eq_spec (low_s n) Int.zero); case (Int.eq (low_s n) Int.zero); intro. + exists (nextinstr (rs#r <- (Vint n))). + split. apply exec_straight_one. + simpl. rewrite Int.add_commut. + rewrite <- H. rewrite low_high_s. reflexivity. + reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. apply Pregmap.gso; auto. + (* addis + ori *) + pose (rs1 := nextinstr (rs#r <- (Vint (Int.shl (high_u n) (Int.repr 16))))). + exists (nextinstr (rs1#r <- (Vint n))). + split. eapply exec_straight_two. + simpl. rewrite Int.add_commut. rewrite Int.add_zero. reflexivity. + simpl. rewrite nextinstr_inv; auto with ppcgen. rewrite Pregmap.gss. + unfold Val.or. rewrite low_high_u. reflexivity. + reflexivity. reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. + unfold rs1. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. +Qed. + +(** Add integer immediate. *) + +Lemma addimm_1_correct: + forall r1 r2 n k rs m, + r1 <> GPR0 -> + r2 <> GPR0 -> + exists rs', + exec_straight (addimm_1 r1 r2 n k) rs m k rs' m + /\ rs'#r1 = Val.add rs#r2 (Vint n) + /\ forall r': preg, r' <> r1 -> r' <> PC -> rs'#r' = rs#r'. +Proof. + intros. unfold addimm_1. + (* addi *) + case (Int.eq (high_s n) Int.zero). + exists (nextinstr (rs#r1 <- (Val.add rs#r2 (Vint n)))). + split. apply exec_straight_one. + simpl. rewrite gpr_or_zero_not_zero; auto. + reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. apply Pregmap.gso; auto. + (* addis *) + generalize (Int.eq_spec (low_s n) Int.zero); case (Int.eq (low_s n) Int.zero); intro. + exists (nextinstr (rs#r1 <- (Val.add rs#r2 (Vint n)))). + split. apply exec_straight_one. + simpl. rewrite gpr_or_zero_not_zero; auto. + generalize (low_high_s n). rewrite H1. rewrite Int.add_zero. intro. + rewrite H2. auto. + reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. apply Pregmap.gso; auto. + (* addis + addi *) + pose (rs1 := nextinstr (rs#r1 <- (Val.add rs#r2 (Vint (Int.shl (high_s n) (Int.repr 16)))))). + exists (nextinstr (rs1#r1 <- (Val.add rs#r2 (Vint n)))). + split. apply exec_straight_two with rs1 m. + simpl. rewrite gpr_or_zero_not_zero; auto. + simpl. rewrite gpr_or_zero_not_zero; auto. + unfold rs1 at 1. rewrite nextinstr_inv; auto with ppcgen. rewrite Pregmap.gss. + rewrite Val.add_assoc. simpl. rewrite low_high_s. auto. + reflexivity. reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. + unfold rs1. rewrite nextinstr_inv; auto. apply Pregmap.gso; auto. +Qed. + +Lemma addimm_2_correct: + forall r1 r2 n k rs m, + r2 <> GPR12 -> + exists rs', + exec_straight (addimm_2 r1 r2 n k) rs m k rs' m + /\ rs'#r1 = Val.add rs#r2 (Vint n) + /\ forall r': preg, r' <> r1 -> r' <> GPR12 -> r' <> PC -> rs'#r' = rs#r'. +Proof. + intros. unfold addimm_2. + generalize (loadimm_correct GPR12 n (Padd r1 r2 GPR12 :: k) rs m). + intros [rs1 [EX [RES OTHER]]]. + exists (nextinstr (rs1#r1 <- (Val.add rs#r2 (Vint n)))). + split. eapply exec_straight_trans. eexact EX. + apply exec_straight_one. simpl. rewrite RES. rewrite OTHER. + auto. congruence. discriminate. + reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. +Qed. + +Lemma addimm_correct: + forall r1 r2 n k rs m, + r2 <> GPR12 -> + exists rs', + exec_straight (addimm r1 r2 n k) rs m k rs' m + /\ rs'#r1 = Val.add rs#r2 (Vint n) + /\ forall r': preg, r' <> r1 -> r' <> GPR12 -> r' <> PC -> rs'#r' = rs#r'. +Proof. + intros. unfold addimm. + case (ireg_eq r1 GPR0); intro. + apply addimm_2_correct; auto. + case (ireg_eq r2 GPR0); intro. + apply addimm_2_correct; auto. + generalize (addimm_1_correct r1 r2 n k rs m n0 n1). + intros [rs' [EX [RES OTH]]]. exists rs'. intuition. +Qed. + +(** And integer immediate. *) + +Lemma andimm_correct: + forall r1 r2 n k (rs : regset) m, + r2 <> GPR12 -> + let v := Val.and rs#r2 (Vint n) in + exists rs', + exec_straight (andimm r1 r2 n k) rs m k rs' m + /\ rs'#r1 = v + /\ rs'#CR0_2 = Val.cmp Ceq v Vzero + /\ forall r': preg, + r' <> r1 -> r' <> GPR12 -> r' <> PC -> + r' <> CR0_0 -> r' <> CR0_1 -> r' <> CR0_2 -> r' <> CR0_3 -> + rs'#r' = rs#r'. +Proof. + intros. unfold andimm. + case (Int.eq (high_u n) Int.zero). + (* andi *) + exists (nextinstr (compare_sint (rs#r1 <- v) v Vzero)). + generalize (compare_sint_spec (rs#r1 <- v) v Vzero). + intros [A [B [C D]]]. + split. apply exec_straight_one. reflexivity. reflexivity. + split. rewrite D; try discriminate. apply Pregmap.gss. + split. auto. + intros. rewrite D; auto. apply Pregmap.gso; auto. + (* andis *) + generalize (Int.eq_spec (low_u n) Int.zero); + case (Int.eq (low_u n) Int.zero); intro. + exists (nextinstr (compare_sint (rs#r1 <- v) v Vzero)). + generalize (compare_sint_spec (rs#r1 <- v) v Vzero). + intros [A [B [C D]]]. + split. apply exec_straight_one. simpl. + generalize (low_high_u n). rewrite H0. rewrite Int.or_zero. + intro. rewrite H1. reflexivity. reflexivity. + split. rewrite D; try discriminate. apply Pregmap.gss. + split. auto. + intros. rewrite D; auto. apply Pregmap.gso; auto. + (* loadimm + and *) + generalize (loadimm_correct GPR12 n (Pand_ r1 r2 GPR12 :: k) rs m). + intros [rs1 [EX1 [RES1 OTHER1]]]. + exists (nextinstr (compare_sint (rs1#r1 <- v) v Vzero)). + generalize (compare_sint_spec (rs1#r1 <- v) v Vzero). + intros [A [B [C D]]]. + split. eapply exec_straight_trans. eexact EX1. + apply exec_straight_one. simpl. rewrite RES1. + rewrite (OTHER1 r2). reflexivity. congruence. congruence. + reflexivity. + split. rewrite D; try discriminate. apply Pregmap.gss. + split. auto. + intros. rewrite D; auto. rewrite Pregmap.gso; auto. +Qed. + +(** Or integer immediate. *) + +Lemma orimm_correct: + forall r1 (r2: ireg) n k (rs : regset) m, + let v := Val.or rs#r2 (Vint n) in + exists rs', + exec_straight (orimm r1 r2 n k) rs m k rs' m + /\ rs'#r1 = v + /\ forall r': preg, r' <> r1 -> r' <> PC -> rs'#r' = rs#r'. +Proof. + intros. unfold orimm. + case (Int.eq (high_u n) Int.zero). + (* ori *) + exists (nextinstr (rs#r1 <- v)). + split. apply exec_straight_one. reflexivity. reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. apply Pregmap.gso; auto. + (* oris *) + generalize (Int.eq_spec (low_u n) Int.zero); + case (Int.eq (low_u n) Int.zero); intro. + exists (nextinstr (rs#r1 <- v)). + split. apply exec_straight_one. simpl. + generalize (low_high_u n). rewrite H. rewrite Int.or_zero. + intro. rewrite H0. reflexivity. reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. apply Pregmap.gso; auto. + (* oris + ori *) + pose (rs1 := nextinstr (rs#r1 <- (Val.or rs#r2 (Vint (Int.shl (high_u n) (Int.repr 16)))))). + exists (nextinstr (rs1#r1 <- v)). + split. apply exec_straight_two with rs1 m. + reflexivity. simpl. unfold rs1 at 1. + rewrite nextinstr_inv; auto with ppcgen. + rewrite Pregmap.gss. rewrite Val.or_assoc. simpl. + rewrite low_high_u. reflexivity. reflexivity. reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. + unfold rs1. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. +Qed. + +(** Xor integer immediate. *) + +Lemma xorimm_correct: + forall r1 (r2: ireg) n k (rs : regset) m, + let v := Val.xor rs#r2 (Vint n) in + exists rs', + exec_straight (xorimm r1 r2 n k) rs m k rs' m + /\ rs'#r1 = v + /\ forall r': preg, r' <> r1 -> r' <> PC -> rs'#r' = rs#r'. +Proof. + intros. unfold xorimm. + case (Int.eq (high_u n) Int.zero). + (* xori *) + exists (nextinstr (rs#r1 <- v)). + split. apply exec_straight_one. reflexivity. reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. apply Pregmap.gso; auto. + (* xoris *) + generalize (Int.eq_spec (low_u n) Int.zero); + case (Int.eq (low_u n) Int.zero); intro. + exists (nextinstr (rs#r1 <- v)). + split. apply exec_straight_one. simpl. + generalize (low_high_u_xor n). rewrite H. rewrite Int.xor_zero. + intro. rewrite H0. reflexivity. reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. apply Pregmap.gso; auto. + (* xoris + xori *) + pose (rs1 := nextinstr (rs#r1 <- (Val.xor rs#r2 (Vint (Int.shl (high_u n) (Int.repr 16)))))). + exists (nextinstr (rs1#r1 <- v)). + split. apply exec_straight_two with rs1 m. + reflexivity. simpl. unfold rs1 at 1. + rewrite nextinstr_inv; try discriminate. + rewrite Pregmap.gss. rewrite Val.xor_assoc. simpl. + rewrite low_high_u_xor. reflexivity. reflexivity. reflexivity. + split. rewrite nextinstr_inv; auto with ppcgen. + apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. + unfold rs1. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. +Qed. + +(** Indexed memory loads. *) + +Lemma loadind_aux_correct: + forall (base: ireg) ofs ty dst (rs: regset) m v, + Mem.loadv (chunk_of_type ty) m (Val.add rs#base (Vint ofs)) = Some v -> + mreg_type dst = ty -> + base <> GPR0 -> + exec_instr ge fn (loadind_aux base ofs ty dst) rs m = + OK (nextinstr (rs#(preg_of dst) <- v)) m. +Proof. + intros. unfold loadind_aux. unfold preg_of. rewrite H0. destruct ty. + simpl. unfold load1. rewrite gpr_or_zero_not_zero; auto. + unfold const_low. simpl in H. rewrite H. auto. + simpl. unfold load1. rewrite gpr_or_zero_not_zero; auto. + unfold const_low. simpl in H. rewrite H. auto. +Qed. + +Lemma loadind_correct: + forall (base: ireg) ofs ty dst k (rs: regset) m v, + Mem.loadv (chunk_of_type ty) m (Val.add rs#base (Vint ofs)) = Some v -> + mreg_type dst = ty -> + base <> GPR0 -> + exists rs', + exec_straight (loadind base ofs ty dst k) rs m k rs' m + /\ rs'#(preg_of dst) = v + /\ forall r, r <> PC -> r <> GPR12 -> r <> preg_of dst -> rs'#r = rs#r. +Proof. + intros. unfold loadind. + assert (preg_of dst <> PC). + unfold preg_of. case (mreg_type dst); discriminate. + (* short offset *) + case (Int.eq (high_s ofs) Int.zero). + exists (nextinstr (rs#(preg_of dst) <- v)). + split. apply exec_straight_one. apply loadind_aux_correct; auto. + unfold nextinstr. rewrite Pregmap.gss. rewrite Pregmap.gso. auto. auto. + split. rewrite nextinstr_inv; auto. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. apply Pregmap.gso; auto. + (* long offset *) + pose (rs1 := nextinstr (rs#GPR12 <- (Val.add rs#base (Vint (Int.shl (high_s ofs) (Int.repr 16)))))). + exists (nextinstr (rs1#(preg_of dst) <- v)). + split. apply exec_straight_two with rs1 m. + simpl. rewrite gpr_or_zero_not_zero; auto. + apply loadind_aux_correct. + unfold rs1. rewrite nextinstr_inv; auto with ppcgen. rewrite Pregmap.gss. + rewrite Val.add_assoc. simpl. rewrite low_high_s. assumption. + auto. discriminate. reflexivity. + unfold nextinstr. rewrite Pregmap.gss. rewrite Pregmap.gso. auto. auto. + split. rewrite nextinstr_inv; auto. apply Pregmap.gss. + intros. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. + unfold rs1. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. +Qed. + +(** Indexed memory stores. *) + +Lemma storeind_aux_correct: + forall (base: ireg) ofs ty src (rs: regset) m m', + Mem.storev (chunk_of_type ty) m (Val.add rs#base (Vint ofs)) (rs#(preg_of src)) = Some m' -> + mreg_type src = ty -> + base <> GPR0 -> + exec_instr ge fn (storeind_aux src base ofs ty) rs m = + OK (nextinstr rs) m'. +Proof. + intros. unfold storeind_aux. unfold preg_of in H. rewrite H0 in H. destruct ty. + simpl. unfold store1. rewrite gpr_or_zero_not_zero; auto. + unfold const_low. simpl in H. rewrite H. auto. + simpl. unfold store1. rewrite gpr_or_zero_not_zero; auto. + unfold const_low. simpl in H. rewrite H. auto. +Qed. + +Lemma storeind_correct: + forall (base: ireg) ofs ty src k (rs: regset) m m', + Mem.storev (chunk_of_type ty) m (Val.add rs#base (Vint ofs)) (rs#(preg_of src)) = Some m' -> + mreg_type src = ty -> + base <> GPR0 -> + exists rs', + exec_straight (storeind src base ofs ty k) rs m k rs' m' + /\ forall r, r <> PC -> r <> GPR12 -> rs'#r = rs#r. +Proof. + intros. unfold storeind. + (* short offset *) + case (Int.eq (high_s ofs) Int.zero). + exists (nextinstr rs). + split. apply exec_straight_one. apply storeind_aux_correct; auto. + reflexivity. + intros. rewrite nextinstr_inv; auto. + (* long offset *) + pose (rs1 := nextinstr (rs#GPR12 <- (Val.add rs#base (Vint (Int.shl (high_s ofs) (Int.repr 16)))))). + exists (nextinstr rs1). + split. apply exec_straight_two with rs1 m. + simpl. rewrite gpr_or_zero_not_zero; auto. + apply storeind_aux_correct; auto with ppcgen. + unfold rs1. rewrite nextinstr_inv; auto with ppcgen. rewrite Pregmap.gss. + rewrite nextinstr_inv; auto with ppcgen. + rewrite Pregmap.gso; auto with ppcgen. + rewrite Val.add_assoc. simpl. rewrite low_high_s. assumption. + reflexivity. reflexivity. + intros. rewrite nextinstr_inv; auto. + unfold rs1. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. +Qed. + +(** Float comparisons. *) + +Lemma floatcomp_correct: + forall cmp (r1 r2: freg) k rs m, + exists rs', + exec_straight (floatcomp cmp r1 r2 k) rs m k rs' m + /\ rs'#(reg_of_crbit (fst (crbit_for_fcmp cmp))) = + (if snd (crbit_for_fcmp cmp) + then Val.cmpf cmp rs#r1 rs#r2 + else Val.notbool (Val.cmpf cmp rs#r1 rs#r2)) + /\ forall r', + r' <> PC -> r' <> CR0_0 -> r' <> CR0_1 -> + r' <> CR0_2 -> r' <> CR0_3 -> rs'#r' = rs#r'. +Proof. + intros. + generalize (compare_float_spec rs rs#r1 rs#r2). + intros [A [B [C D]]]. + set (rs1 := nextinstr (compare_float rs rs#r1 rs#r2)) in *. + assert ((cmp = Ceq \/ cmp = Cne \/ cmp = Clt \/ cmp = Cgt) + \/ (cmp = Cle \/ cmp = Cge)). + case cmp; tauto. + unfold floatcomp. elim H; intro; clear H. + exists rs1. + split. generalize H0; intros [EQ|[EQ|[EQ|EQ]]]; subst cmp; + apply exec_straight_one; reflexivity. + split. + generalize H0; intros [EQ|[EQ|[EQ|EQ]]]; subst cmp; simpl; auto. + rewrite Val.negate_cmpf_eq. auto. + auto. + (* two instrs *) + exists (nextinstr (rs1#CR0_3 <- (Val.cmpf cmp rs#r1 rs#r2))). + split. elim H0; intro; subst cmp. + apply exec_straight_two with rs1 m. + reflexivity. simpl. + rewrite C; rewrite A. rewrite Val.or_commut. rewrite <- Val.cmpf_le. + reflexivity. reflexivity. reflexivity. + apply exec_straight_two with rs1 m. + reflexivity. simpl. + rewrite C; rewrite B. rewrite Val.or_commut. rewrite <- Val.cmpf_ge. + reflexivity. reflexivity. reflexivity. + split. elim H0; intro; subst cmp; simpl. + reflexivity. + reflexivity. + intros. rewrite nextinstr_inv; auto. rewrite Pregmap.gso; auto. +Qed. + +Ltac TypeInv := + match goal with + | H: (List.map ?f ?x = nil) |- _ => + destruct x; [clear H | simpl in H; discriminate] + | H: (List.map ?f ?x = ?hd :: ?tl) |- _ => + destruct x; simpl in H; + [ discriminate | + injection H; clear H; let T := fresh "T" in ( + intros H T; TypeInv) ] + | _ => idtac + end. + +(** Translation of conditions. *) + +Lemma transl_cond_correct_aux: + forall cond args k ms sp rs m, + map mreg_type args = type_of_condition cond -> + agree ms sp rs -> + exists rs', + exec_straight (transl_cond cond args k) rs m k rs' m + /\ rs'#(reg_of_crbit (fst (crbit_for_cond cond))) = + (if snd (crbit_for_cond cond) + then eval_condition_total cond (map ms args) + else Val.notbool (eval_condition_total cond (map ms args))) + /\ agree ms sp rs'. +Proof. + intros. destruct cond; simpl in H; TypeInv. + (* Ccomp *) + simpl. + generalize (compare_sint_spec rs ms#m0 ms#m1). + intros [A [B [C D]]]. + exists (nextinstr (compare_sint rs ms#m0 ms#m1)). + split. apply exec_straight_one. simpl. + repeat (rewrite <- (ireg_val ms sp rs); auto). + reflexivity. + split. + case c; simpl; auto; rewrite <- Val.negate_cmp; simpl; auto. + apply agree_exten_2 with rs; auto. + (* Ccompu *) + simpl. + generalize (compare_uint_spec rs ms#m0 ms#m1). + intros [A [B [C D]]]. + exists (nextinstr (compare_uint rs ms#m0 ms#m1)). + split. apply exec_straight_one. simpl. + repeat (rewrite <- (ireg_val ms sp rs); auto). + reflexivity. + split. + case c; simpl; auto; rewrite <- Val.negate_cmpu; simpl; auto. + apply agree_exten_2 with rs; auto. + (* Ccompimm *) + simpl. + case (Int.eq (high_s i) Int.zero). + generalize (compare_sint_spec rs ms#m0 (Vint i)). + intros [A [B [C D]]]. + exists (nextinstr (compare_sint rs ms#m0 (Vint i))). + split. apply exec_straight_one. simpl. + repeat (rewrite <- (ireg_val ms sp rs); auto). + reflexivity. + split. + case c; simpl; auto; rewrite <- Val.negate_cmp; simpl; auto. + apply agree_exten_2 with rs; auto. + generalize (loadimm_correct GPR12 i (Pcmpw (ireg_of m0) GPR12 :: k) rs m). + intros [rs1 [EX1 [RES1 OTH1]]]. + assert (agree ms sp rs1). apply agree_exten_2 with rs; auto. + generalize (compare_sint_spec rs1 ms#m0 (Vint i)). + intros [A [B [C D]]]. + exists (nextinstr (compare_sint rs1 ms#m0 (Vint i))). + split. eapply exec_straight_trans. eexact EX1. + apply exec_straight_one. simpl. + repeat (rewrite <- (ireg_val ms sp rs1); auto). rewrite RES1. + reflexivity. reflexivity. + split. + case c; simpl; auto; rewrite <- Val.negate_cmp; simpl; auto. + apply agree_exten_2 with rs1; auto. + (* Ccompuimm *) + simpl. + case (Int.eq (high_u i) Int.zero). + generalize (compare_uint_spec rs ms#m0 (Vint i)). + intros [A [B [C D]]]. + exists (nextinstr (compare_uint rs ms#m0 (Vint i))). + split. apply exec_straight_one. simpl. + repeat (rewrite <- (ireg_val ms sp rs); auto). + reflexivity. + split. + case c; simpl; auto; rewrite <- Val.negate_cmpu; simpl; auto. + apply agree_exten_2 with rs; auto. + generalize (loadimm_correct GPR12 i (Pcmplw (ireg_of m0) GPR12 :: k) rs m). + intros [rs1 [EX1 [RES1 OTH1]]]. + assert (agree ms sp rs1). apply agree_exten_2 with rs; auto. + generalize (compare_uint_spec rs1 ms#m0 (Vint i)). + intros [A [B [C D]]]. + exists (nextinstr (compare_uint rs1 ms#m0 (Vint i))). + split. eapply exec_straight_trans. eexact EX1. + apply exec_straight_one. simpl. + repeat (rewrite <- (ireg_val ms sp rs1); auto). rewrite RES1. + reflexivity. reflexivity. + split. + case c; simpl; auto; rewrite <- Val.negate_cmpu; simpl; auto. + apply agree_exten_2 with rs1; auto. + (* Ccompf *) + simpl. + generalize (floatcomp_correct c (freg_of m0) (freg_of m1) k rs m). + intros [rs' [EX [RES OTH]]]. + exists rs'. split. auto. + split. rewrite RES. repeat (rewrite <- (freg_val ms sp rs); auto). + apply agree_exten_2 with rs; auto. + (* Cnotcompf *) + simpl. + generalize (floatcomp_correct c (freg_of m0) (freg_of m1) k rs m). + intros [rs' [EX [RES OTH]]]. + exists rs'. split. auto. + split. rewrite RES. repeat (rewrite <- (freg_val ms sp rs); auto). + assert (forall v1 v2, Val.notbool (Val.notbool (Val.cmpf c v1 v2)) = Val.cmpf c v1 v2). + intros v1 v2; unfold Val.cmpf; destruct v1; destruct v2; auto. + apply Val.notbool_idem2. + rewrite H. + generalize RES. case (snd (crbit_for_fcmp c)); simpl; auto. + apply agree_exten_2 with rs; auto. + (* Cmaskzero *) + simpl. + generalize (andimm_correct GPR12 (ireg_of m0) i k rs m (ireg_of_not_GPR12 m0)). + intros [rs' [A [B [C D]]]]. + exists rs'. split. assumption. + split. rewrite C. rewrite <- (ireg_val ms sp rs); auto. + apply agree_exten_2 with rs; auto. + (* Cmasknotzero *) + simpl. + generalize (andimm_correct GPR12 (ireg_of m0) i k rs m (ireg_of_not_GPR12 m0)). + intros [rs' [A [B [C D]]]]. + exists rs'. split. assumption. + split. rewrite C. rewrite <- (ireg_val ms sp rs); auto. + rewrite Val.notbool_idem3. reflexivity. + apply agree_exten_2 with rs; auto. +Qed. + +Lemma transl_cond_correct: + forall cond args k ms sp rs m b, + map mreg_type args = type_of_condition cond -> + agree ms sp rs -> + eval_condition cond (map ms args) m = Some b -> + exists rs', + exec_straight (transl_cond cond args k) rs m k rs' m + /\ rs'#(reg_of_crbit (fst (crbit_for_cond cond))) = + (if snd (crbit_for_cond cond) + then Val.of_bool b + else Val.notbool (Val.of_bool b)) + /\ agree ms sp rs'. +Proof. + intros. rewrite <- (eval_condition_weaken _ _ _ H1). + apply transl_cond_correct_aux; auto. +Qed. + +(** Translation of arithmetic operations. *) + +Ltac TranslOpSimpl := + match goal with + | |- exists rs' : regset, + exec_straight ?c ?rs ?m ?k rs' ?m /\ + agree (Regmap.set ?res ?v ?ms) ?sp rs' => + (exists (nextinstr (rs#(ireg_of res) <- v)); + split; + [ apply exec_straight_one; + [ repeat (rewrite (ireg_val ms sp rs); auto); reflexivity + | reflexivity ] + | auto with ppcgen ]) + || + (exists (nextinstr (rs#(freg_of res) <- v)); + split; + [ apply exec_straight_one; + [ repeat (rewrite (freg_val ms sp rs); auto); reflexivity + | reflexivity ] + | auto with ppcgen ]) + end. + +Lemma transl_op_correct: + forall op args res k ms sp rs m v, + wt_instr (Mop op args res) -> + agree ms sp rs -> + eval_operation ge sp op (map ms args) m = Some v -> + exists rs', + exec_straight (transl_op op args res k) rs m k rs' m + /\ agree (Regmap.set res v ms) sp rs'. +Proof. + intros. rewrite <- (eval_operation_weaken _ _ _ _ _ H1). clear H1; clear v. + inversion H. + (* Omove *) + simpl. exists (nextinstr (rs#(preg_of res) <- (ms r1))). + split. caseEq (mreg_type r1); intro. + apply exec_straight_one. simpl. rewrite (ireg_val ms sp rs); auto. + simpl. unfold preg_of. rewrite <- H2. rewrite H5. reflexivity. + auto with ppcgen. + apply exec_straight_one. simpl. rewrite (freg_val ms sp rs); auto. + simpl. unfold preg_of. rewrite <- H2. rewrite H5. reflexivity. + auto with ppcgen. + auto with ppcgen. + (* Other instructions *) + clear H1; clear H2; clear H4. + destruct op; simpl in H5; injection H5; clear H5; intros; + TypeInv; simpl; try (TranslOpSimpl). + (* Omove again *) + congruence. + (* Ointconst *) + generalize (loadimm_correct (ireg_of res) i k rs m). + intros [rs' [A [B C]]]. + exists rs'. split. auto. + apply agree_set_mireg_exten with rs; auto. + (* Ofloatconst *) + exists (nextinstr (rs#(freg_of res) <- (Vfloat f) #GPR12 <- Vundef)). + split. apply exec_straight_one. reflexivity. reflexivity. + auto with ppcgen. + (* Oaddrsymbol *) + change (find_symbol_offset ge i i0) with (symbol_offset ge i i0). + set (v := symbol_offset ge i i0). + pose (rs1 := nextinstr (rs#GPR12 <- (high_half v))). + exists (nextinstr (rs1#(ireg_of res) <- v)). + split. apply exec_straight_two with rs1 m. + unfold exec_instr. rewrite gpr_or_zero_zero. + unfold const_high. rewrite Val.add_commut. + rewrite high_half_zero. reflexivity. + simpl. rewrite gpr_or_zero_not_zero. 2: congruence. + unfold rs1 at 1. rewrite nextinstr_inv; auto with ppcgen. + rewrite Pregmap.gss. + fold v. rewrite Val.add_commut. unfold v. rewrite low_high_half. + reflexivity. reflexivity. reflexivity. + unfold rs1. apply agree_nextinstr. apply agree_set_mireg; auto. + apply agree_set_mreg. apply agree_nextinstr. + apply agree_set_other. auto. simpl. tauto. + (* Oaddrstack *) + assert (GPR1 <> GPR12). discriminate. + generalize (addimm_correct (ireg_of res) GPR1 i k rs m H2). + intros [rs' [EX [RES OTH]]]. + exists rs'. split. auto. + apply agree_set_mireg_exten with rs; auto. + rewrite (sp_val ms sp rs). auto. auto. + (* Ocast8unsigned *) + exists (nextinstr (rs#(ireg_of res) <- (Val.rolm (ms m0) Int.zero (Int.repr 255)))). + split. apply exec_straight_one. repeat (rewrite (ireg_val ms sp rs)); auto. reflexivity. + replace (Val.zero_ext 8 (ms m0)) + with (Val.rolm (ms m0) Int.zero (Int.repr 255)). + auto with ppcgen. + unfold Val.rolm, Val.zero_ext. destruct (ms m0); auto. + rewrite Int.rolm_zero. rewrite Int.zero_ext_and. auto. compute; auto. + (* Ocast16unsigned *) + exists (nextinstr (rs#(ireg_of res) <- (Val.rolm (ms m0) Int.zero (Int.repr 65535)))). + split. apply exec_straight_one. repeat (rewrite (ireg_val ms sp rs)); auto. reflexivity. + replace (Val.zero_ext 16 (ms m0)) + with (Val.rolm (ms m0) Int.zero (Int.repr 65535)). + auto with ppcgen. + unfold Val.rolm, Val.zero_ext. destruct (ms m0); auto. + rewrite Int.rolm_zero. rewrite Int.zero_ext_and. auto. compute; auto. + (* Oaddimm *) + generalize (addimm_correct (ireg_of res) (ireg_of m0) i k rs m + (ireg_of_not_GPR12 m0)). + intros [rs' [A [B C]]]. + exists rs'. split. auto. + apply agree_set_mireg_exten with rs; auto. + rewrite (ireg_val ms sp rs); auto. + (* Osub *) + exists (nextinstr (rs#(ireg_of res) <- (Val.sub (ms m0) (ms m1)) #CARRY <- Vundef)). + split. apply exec_straight_one. repeat (rewrite (ireg_val ms sp rs); auto). + simpl. reflexivity. auto with ppcgen. + (* Osubimm *) + case (Int.eq (high_s i) Int.zero). + exists (nextinstr (rs#(ireg_of res) <- (Val.sub (Vint i) (ms m0)) #CARRY <- Vundef)). + split. apply exec_straight_one. rewrite (ireg_val ms sp rs); auto. + reflexivity. simpl. auto with ppcgen. + generalize (loadimm_correct GPR12 i (Psubfc (ireg_of res) (ireg_of m0) GPR12 :: k) rs m). + intros [rs1 [EX [RES OTH]]]. + assert (agree ms sp rs1). apply agree_exten_2 with rs; auto. + exists (nextinstr (rs1#(ireg_of res) <- (Val.sub (Vint i) (ms m0)) #CARRY <- Vundef)). + split. eapply exec_straight_trans. eexact EX. + apply exec_straight_one. repeat (rewrite (ireg_val ms sp rs); auto). + simpl. rewrite RES. rewrite OTH. reflexivity. + generalize (ireg_of_not_GPR12 m0); congruence. + discriminate. + reflexivity. simpl; auto with ppcgen. + (* Omulimm *) + case (Int.eq (high_s i) Int.zero). + exists (nextinstr (rs#(ireg_of res) <- (Val.mul (ms m0) (Vint i)))). + split. apply exec_straight_one. rewrite (ireg_val ms sp rs); auto. + reflexivity. auto with ppcgen. + generalize (loadimm_correct GPR12 i (Pmullw (ireg_of res) (ireg_of m0) GPR12 :: k) rs m). + intros [rs1 [EX [RES OTH]]]. + assert (agree ms sp rs1). apply agree_exten_2 with rs; auto. + exists (nextinstr (rs1#(ireg_of res) <- (Val.mul (ms m0) (Vint i)))). + split. eapply exec_straight_trans. eexact EX. + apply exec_straight_one. repeat (rewrite (ireg_val ms sp rs); auto). + simpl. rewrite RES. rewrite OTH. reflexivity. + generalize (ireg_of_not_GPR12 m0); congruence. + discriminate. + reflexivity. simpl; auto with ppcgen. + (* Oand *) + pose (v := Val.and (ms m0) (ms m1)). + pose (rs1 := rs#(ireg_of res) <- v). + generalize (compare_sint_spec rs1 v Vzero). + intros [A [B [C D]]]. + exists (nextinstr (compare_sint rs1 v Vzero)). + split. apply exec_straight_one. + unfold rs1, v. repeat (rewrite (ireg_val ms sp rs); auto). + reflexivity. + apply agree_exten_2 with rs1. unfold rs1, v; auto with ppcgen. + auto. + (* Oandimm *) + generalize (andimm_correct (ireg_of res) (ireg_of m0) i k rs m + (ireg_of_not_GPR12 m0)). + intros [rs' [A [B [C D]]]]. + exists rs'. split. auto. apply agree_set_mireg_exten with rs; auto. + rewrite (ireg_val ms sp rs); auto. + (* Oorimm *) + generalize (orimm_correct (ireg_of res) (ireg_of m0) i k rs m). + intros [rs' [A [B C]]]. + exists rs'. split. auto. apply agree_set_mireg_exten with rs; auto. + rewrite (ireg_val ms sp rs); auto. + (* Oxorimm *) + generalize (xorimm_correct (ireg_of res) (ireg_of m0) i k rs m). + intros [rs' [A [B C]]]. + exists rs'. split. auto. apply agree_set_mireg_exten with rs; auto. + rewrite (ireg_val ms sp rs); auto. + (* Oshr *) + exists (nextinstr (rs#(ireg_of res) <- (Val.shr (ms m0) (ms m1)) #CARRY <- (Val.shr_carry (ms m0) (ms m1)))). + split. apply exec_straight_one. repeat (rewrite (ireg_val ms sp rs); auto). + reflexivity. auto with ppcgen. + (* Oshrimm *) + exists (nextinstr (rs#(ireg_of res) <- (Val.shr (ms m0) (Vint i)) #CARRY <- (Val.shr_carry (ms m0) (Vint i)))). + split. apply exec_straight_one. repeat (rewrite (ireg_val ms sp rs); auto). + reflexivity. auto with ppcgen. + (* Oxhrximm *) + pose (rs1 := nextinstr (rs#(ireg_of res) <- (Val.shr (ms m0) (Vint i)) #CARRY <- (Val.shr_carry (ms m0) (Vint i)))). + exists (nextinstr (rs1#(ireg_of res) <- (Val.shrx (ms m0) (Vint i)))). + split. apply exec_straight_two with rs1 m. + unfold rs1; rewrite (ireg_val ms sp rs); auto. + simpl; unfold rs1; repeat rewrite <- (ireg_val ms sp rs); auto. + repeat (rewrite nextinstr_inv; try discriminate). + repeat rewrite Pregmap.gss. decEq. decEq. + apply (f_equal3 (@Pregmap.set val)); auto. + rewrite Pregmap.gso. rewrite Pregmap.gss. apply Val.shrx_carry. + discriminate. reflexivity. reflexivity. + apply agree_exten_2 with (rs#(ireg_of res) <- (Val.shrx (ms m0) (Vint i))). + auto with ppcgen. + intros. rewrite nextinstr_inv; auto. + case (preg_eq (ireg_of res) r); intro. + subst r. repeat rewrite Pregmap.gss. auto. + repeat rewrite Pregmap.gso; auto. + unfold rs1. rewrite nextinstr_inv; auto. + repeat rewrite Pregmap.gso; auto. + (* Ointoffloat *) + exists (nextinstr (rs#(ireg_of res) <- (Val.intoffloat (ms m0)) #FPR13 <- Vundef)). + split. apply exec_straight_one. + repeat (rewrite (freg_val ms sp rs); auto). + reflexivity. auto with ppcgen. + (* Ointuoffloat *) + exists (nextinstr (rs#(ireg_of res) <- (Val.intuoffloat (ms m0)) #FPR13 <- Vundef)). + split. apply exec_straight_one. + repeat (rewrite (freg_val ms sp rs); auto). + reflexivity. auto with ppcgen. + (* Ofloatofint *) + exists (nextinstr (rs#(freg_of res) <- (Val.floatofint (ms m0)) #GPR12 <- Vundef #FPR13 <- Vundef)). + split. apply exec_straight_one. + repeat (rewrite (ireg_val ms sp rs); auto). + reflexivity. auto 10 with ppcgen. + (* Ofloatofintu *) + exists (nextinstr (rs#(freg_of res) <- (Val.floatofintu (ms m0)) #GPR12 <- Vundef #FPR13 <- Vundef)). + split. apply exec_straight_one. + repeat (rewrite (ireg_val ms sp rs); auto). + reflexivity. auto 10 with ppcgen. + (* Ocmp *) + set (bit := fst (crbit_for_cond c)). + set (isset := snd (crbit_for_cond c)). + set (k1 := + Pmfcrbit (ireg_of res) bit :: + (if isset + then k + else Pxori (ireg_of res) (ireg_of res) (Cint Int.one) :: k)). + generalize (transl_cond_correct_aux c args k1 ms sp rs m H2 H0). + fold bit; fold isset. + intros [rs1 [EX1 [RES1 AG1]]]. + set (rs2 := nextinstr (rs1#(ireg_of res) <- (rs1#(reg_of_crbit bit)))). + destruct isset. + exists rs2. + split. apply exec_straight_trans with k1 rs1 m. assumption. + unfold k1. apply exec_straight_one. + reflexivity. reflexivity. + unfold rs2. rewrite RES1. auto with ppcgen. + exists (nextinstr (rs2#(ireg_of res) <- (eval_condition_total c ms##args))). + split. apply exec_straight_trans with k1 rs1 m. assumption. + unfold k1. apply exec_straight_two with rs2 m. + reflexivity. simpl. + replace (Val.xor (rs2 (ireg_of res)) (Vint Int.one)) + with (eval_condition_total c ms##args). + reflexivity. + unfold rs2. rewrite nextinstr_inv; auto with ppcgen. rewrite Pregmap.gss. + rewrite RES1. apply Val.notbool_xor. apply eval_condition_total_is_bool. + reflexivity. reflexivity. + unfold rs2. auto with ppcgen. +Qed. + +Lemma transl_load_store_correct: + forall (mk1: constant -> ireg -> instruction) (mk2: ireg -> ireg -> instruction) + addr args k ms sp rs m ms' m', + (forall cst (r1: ireg) (rs1: regset) k, + eval_addressing_total ge sp addr (map ms args) = Val.add rs1#r1 (const_low ge cst) -> + agree ms sp rs1 -> + r1 <> GPR0 -> + exists rs', + exec_straight (mk1 cst r1 :: k) rs1 m k rs' m' /\ + agree ms' sp rs') -> + (forall (r1 r2: ireg) (rs1: regset) k, + eval_addressing_total ge sp addr (map ms args) = Val.add rs1#r1 rs1#r2 -> + agree ms sp rs1 -> + exists rs', + exec_straight (mk2 r1 r2 :: k) rs1 m k rs' m' /\ + agree ms' sp rs') -> + agree ms sp rs -> + map mreg_type args = type_of_addressing addr -> + exists rs', + exec_straight (transl_load_store mk1 mk2 addr args k) rs m + k rs' m' + /\ agree ms' sp rs'. +Proof. + intros. destruct addr; simpl in H2; TypeInv; simpl. + (* Aindexed *) + case (ireg_eq (ireg_of t) GPR0); intro. + (* Aindexed from GPR0 *) + set (rs1 := nextinstr (rs#GPR12 <- (ms t))). + set (rs2 := nextinstr (rs1#GPR12 <- (Val.add (ms t) (Vint (Int.shl (high_s i) (Int.repr 16)))))). + assert (ADDR: eval_addressing_total ge sp (Aindexed i) ms##(t :: nil) = + Val.add rs2#GPR12 (const_low ge (Cint (low_s i)))). + simpl. unfold rs2. rewrite nextinstr_inv. rewrite Pregmap.gss. + rewrite Val.add_assoc. simpl. rewrite low_high_s. auto. + discriminate. + assert (AG: agree ms sp rs2). unfold rs2, rs1; auto 6 with ppcgen. + assert (NOT0: GPR12 <> GPR0). discriminate. + generalize (H _ _ _ k ADDR AG NOT0). + intros [rs' [EX' AG']]. + exists rs'. split. + apply exec_straight_trans with (mk1 (Cint (low_s i)) GPR12 :: k) rs2 m. + apply exec_straight_two with rs1 m. + unfold rs1. rewrite (ireg_val ms sp rs); auto. + unfold rs2. replace (ms t) with (rs1#GPR12). auto. + unfold rs1. rewrite nextinstr_inv. apply Pregmap.gss. discriminate. + reflexivity. reflexivity. + assumption. assumption. + (* Aindexed short *) + case (Int.eq (high_s i) Int.zero). + assert (ADDR: eval_addressing_total ge sp (Aindexed i) ms##(t :: nil) = + Val.add rs#(ireg_of t) (const_low ge (Cint i))). + simpl. rewrite (ireg_val ms sp rs); auto. + generalize (H _ _ _ k ADDR H1 n). intros [rs' [EX' AG']]. + exists rs'. split. auto. auto. + (* Aindexed long *) + set (rs1 := nextinstr (rs#GPR12 <- (Val.add (ms t) (Vint (Int.shl (high_s i) (Int.repr 16)))))). + assert (ADDR: eval_addressing_total ge sp (Aindexed i) ms##(t :: nil) = + Val.add rs1#GPR12 (const_low ge (Cint (low_s i)))). + simpl. unfold rs1. rewrite nextinstr_inv. rewrite Pregmap.gss. + rewrite Val.add_assoc. simpl. rewrite low_high_s. auto. + discriminate. + assert (AG: agree ms sp rs1). unfold rs1; auto with ppcgen. + assert (NOT0: GPR12 <> GPR0). discriminate. + generalize (H _ _ _ k ADDR AG NOT0). intros [rs' [EX' AG']]. + exists rs'. split. apply exec_straight_step with rs1 m. + simpl. rewrite gpr_or_zero_not_zero; auto. + rewrite <- (ireg_val ms sp rs); auto. reflexivity. + assumption. assumption. + (* Aindexed2 *) + apply H0. + simpl. repeat (rewrite (ireg_val ms sp rs); auto). auto. + (* Aglobal *) + set (rs1 := nextinstr (rs#GPR12 <- (const_high ge (Csymbol_high i i0)))). + assert (ADDR: eval_addressing_total ge sp (Aglobal i i0) ms##nil = + Val.add rs1#GPR12 (const_low ge (Csymbol_low i i0))). + simpl. unfold rs1. rewrite nextinstr_inv. rewrite Pregmap.gss. + unfold const_high, const_low. + set (v := symbol_offset ge i i0). + symmetry. rewrite Val.add_commut. unfold v. apply low_high_half. + discriminate. + assert (AG: agree ms sp rs1). unfold rs1; auto with ppcgen. + assert (NOT0: GPR12 <> GPR0). discriminate. + generalize (H _ _ _ k ADDR AG NOT0). intros [rs' [EX' AG']]. + exists rs'. split. apply exec_straight_step with rs1 m. + unfold exec_instr. rewrite gpr_or_zero_zero. + rewrite Val.add_commut. unfold const_high. + rewrite high_half_zero. + reflexivity. reflexivity. + assumption. assumption. + (* Abased *) + assert (COMMON: + forall (rs1: regset) r, + r <> GPR0 -> + ms t = rs1#r -> + agree ms sp rs1 -> + exists rs', + exec_straight + (Paddis GPR12 r (Csymbol_high i i0) + :: mk1 (Csymbol_low i i0) GPR12 :: k) rs1 m k rs' m' + /\ agree ms' sp rs'). + intros. + set (rs2 := nextinstr (rs1#GPR12 <- (Val.add (ms t) (const_high ge (Csymbol_high i i0))))). + assert (ADDR: eval_addressing_total ge sp (Abased i i0) ms##(t::nil) = + Val.add rs2#GPR12 (const_low ge (Csymbol_low i i0))). + simpl. unfold rs2. rewrite nextinstr_inv. rewrite Pregmap.gss. + unfold const_high. + set (v := symbol_offset ge i i0). + rewrite Val.add_assoc. + rewrite (Val.add_commut (high_half v)). + unfold v. rewrite low_high_half. apply Val.add_commut. + discriminate. + assert (AG: agree ms sp rs2). unfold rs2; auto with ppcgen. + assert (NOT0: GPR12 <> GPR0). discriminate. + generalize (H _ _ _ k ADDR AG NOT0). intros [rs' [EX' AG']]. + exists rs'. split. apply exec_straight_step with rs2 m. + unfold exec_instr. rewrite gpr_or_zero_not_zero; auto. + rewrite <- H3. reflexivity. reflexivity. + assumption. assumption. + case (ireg_eq (ireg_of t) GPR0); intro. + set (rs1 := nextinstr (rs#GPR12 <- (ms t))). + assert (R1: GPR12 <> GPR0). discriminate. + assert (R2: ms t = rs1 GPR12). + unfold rs1. rewrite nextinstr_inv. rewrite Pregmap.gss; auto. + discriminate. + assert (R3: agree ms sp rs1). unfold rs1; auto with ppcgen. + generalize (COMMON rs1 GPR12 R1 R2 R3). intros [rs' [EX' AG']]. + exists rs'. split. + apply exec_straight_step with rs1 m. + unfold rs1. rewrite (ireg_val ms sp rs); auto. reflexivity. + assumption. assumption. + apply COMMON; auto. eapply ireg_val; eauto. + (* Ainstack *) + case (Int.eq (high_s i) Int.zero). + apply H. simpl. rewrite (sp_val ms sp rs); auto. auto. + discriminate. + set (rs1 := nextinstr (rs#GPR12 <- (Val.add sp (Vint (Int.shl (high_s i) (Int.repr 16)))))). + assert (ADDR: eval_addressing_total ge sp (Ainstack i) ms##nil = + Val.add rs1#GPR12 (const_low ge (Cint (low_s i)))). + simpl. unfold rs1. rewrite nextinstr_inv. rewrite Pregmap.gss. + rewrite Val.add_assoc. decEq. simpl. rewrite low_high_s. auto. + discriminate. + assert (AG: agree ms sp rs1). unfold rs1; auto with ppcgen. + assert (NOT0: GPR12 <> GPR0). discriminate. + generalize (H _ _ _ k ADDR AG NOT0). intros [rs' [EX' AG']]. + exists rs'. split. apply exec_straight_step with rs1 m. + simpl. rewrite gpr_or_zero_not_zero. + unfold rs1. rewrite (sp_val ms sp rs). reflexivity. + auto. discriminate. reflexivity. assumption. assumption. +Qed. + +(** Translation of memory loads. *) + +Lemma transl_load_correct: + forall (mk1: constant -> ireg -> instruction) (mk2: ireg -> ireg -> instruction) + chunk addr args k ms sp rs m dst a v, + (forall cst (r1: ireg) (rs1: regset), + exec_instr ge fn (mk1 cst r1) rs1 m = + load1 ge chunk (preg_of dst) cst r1 rs1 m) -> + (forall (r1 r2: ireg) (rs1: regset), + exec_instr ge fn (mk2 r1 r2) rs1 m = + load2 chunk (preg_of dst) r1 r2 rs1 m) -> + agree ms sp rs -> + map mreg_type args = type_of_addressing addr -> + eval_addressing ge sp addr (map ms args) = Some a -> + Mem.loadv chunk m a = Some v -> + exists rs', + exec_straight (transl_load_store mk1 mk2 addr args k) rs m + k rs' m + /\ agree (Regmap.set dst v ms) sp rs'. +Proof. + intros. apply transl_load_store_correct with ms. + intros. exists (nextinstr (rs1#(preg_of dst) <- v)). + split. apply exec_straight_one. rewrite H. + unfold load1. rewrite gpr_or_zero_not_zero; auto. + rewrite <- (eval_addressing_weaken _ _ _ _ H3) in H4. + rewrite H5 in H4. rewrite H4. auto. + auto with ppcgen. auto with ppcgen. + intros. exists (nextinstr (rs1#(preg_of dst) <- v)). + split. apply exec_straight_one. rewrite H0. + unfold load2. + rewrite <- (eval_addressing_weaken _ _ _ _ H3) in H4. + rewrite H5 in H4. rewrite H4. auto. + auto with ppcgen. auto with ppcgen. + auto. auto. +Qed. + +(** Translation of memory stores. *) + +Lemma transl_store_correct: + forall (mk1: constant -> ireg -> instruction) (mk2: ireg -> ireg -> instruction) + chunk addr args k ms sp rs m src a m', + (forall cst (r1: ireg) (rs1: regset), + exec_instr ge fn (mk1 cst r1) rs1 m = + store1 ge chunk (preg_of src) cst r1 rs1 m) -> + (forall (r1 r2: ireg) (rs1: regset), + exec_instr ge fn (mk2 r1 r2) rs1 m = + store2 chunk (preg_of src) r1 r2 rs1 m) -> + agree ms sp rs -> + map mreg_type args = type_of_addressing addr -> + eval_addressing ge sp addr (map ms args) = Some a -> + Mem.storev chunk m a (ms src) = Some m' -> + exists rs', + exec_straight (transl_load_store mk1 mk2 addr args k) rs m + k rs' m' + /\ agree ms sp rs'. +Proof. + intros. apply transl_load_store_correct with ms. + intros. exists (nextinstr rs1). + split. apply exec_straight_one. rewrite H. + unfold store1. rewrite gpr_or_zero_not_zero; auto. + rewrite <- (eval_addressing_weaken _ _ _ _ H3) in H4. + rewrite H5 in H4. elim H6; intros. rewrite H9 in H4. + rewrite H4. auto. + auto with ppcgen. auto with ppcgen. + intros. exists (nextinstr rs1). + split. apply exec_straight_one. rewrite H0. + unfold store2. + rewrite <- (eval_addressing_weaken _ _ _ _ H3) in H4. + rewrite H5 in H4. elim H6; intros. rewrite H8 in H4. + rewrite H4. auto. + auto with ppcgen. auto with ppcgen. + auto. auto. +Qed. + +(** Translation of allocations *) + +Lemma transl_alloc_correct: + forall ms sp rs sz m m' blk k, + agree ms sp rs -> + ms Conventions.loc_alloc_argument = Vint sz -> + Mem.alloc m 0 (Int.signed sz) = (m', blk) -> + let ms' := Regmap.set Conventions.loc_alloc_result (Vptr blk Int.zero) ms in + exists rs', + exec_straight (Pallocblock :: k) rs m k rs' m' + /\ agree ms' sp rs'. +Proof. + intros. + pose (rs' := nextinstr (rs#GPR3 <- (Vptr blk Int.zero) #LR <- (Val.add rs#PC Vone))). + exists rs'; split. + apply exec_straight_one. unfold exec_instr. + generalize (preg_val _ _ _ Conventions.loc_alloc_argument H). + unfold preg_of; intro. simpl in H2. rewrite <- H2. rewrite H0. + rewrite H1. reflexivity. + reflexivity. + unfold ms', rs'. apply agree_nextinstr. apply agree_set_other. + change (IR GPR3) with (preg_of Conventions.loc_alloc_result). + apply agree_set_mreg. auto. + simpl. tauto. +Qed. + +End STRAIGHTLINE. + -- cgit