aboutsummaryrefslogtreecommitdiffstats
path: root/powerpc/Asmgenproof1.v
diff options
context:
space:
mode:
Diffstat (limited to 'powerpc/Asmgenproof1.v')
-rw-r--r--powerpc/Asmgenproof1.v232
1 files changed, 191 insertions, 41 deletions
diff --git a/powerpc/Asmgenproof1.v b/powerpc/Asmgenproof1.v
index c18757b2..20cf9c1d 100644
--- a/powerpc/Asmgenproof1.v
+++ b/powerpc/Asmgenproof1.v
@@ -16,6 +16,7 @@ Require Import Coqlib.
Require Import Errors.
Require Import Maps.
Require Import AST.
+Require Import Zbits.
Require Import Integers.
Require Import Floats.
Require Import Values.
@@ -80,13 +81,13 @@ Proof.
unfold Int.modu, Int.zero. decEq.
change 0 with (0 mod 65536).
change (Int.unsigned (Int.repr 65536)) with 65536.
- apply Int.eqmod_mod_eq. omega.
- unfold x, low_s. eapply Int.eqmod_trans.
- apply Int.eqmod_divides with Int.modulus.
+ apply eqmod_mod_eq. omega.
+ unfold x, low_s. eapply eqmod_trans.
+ apply eqmod_divides with Int.modulus.
unfold Int.sub. apply Int.eqm_unsigned_repr_l. apply Int.eqm_refl.
exists 65536. compute; auto.
replace 0 with (Int.unsigned n - Int.unsigned n) by omega.
- apply Int.eqmod_sub. apply Int.eqmod_refl. apply Int.eqmod_sign_ext'.
+ apply eqmod_sub. apply eqmod_refl. apply Int.eqmod_sign_ext'.
compute; auto.
rewrite H0 in H. rewrite Int.add_zero in H.
rewrite <- H. unfold x. rewrite Int.sub_add_opp. rewrite Int.add_assoc.
@@ -531,6 +532,40 @@ Qed.
(** Load int64 constant. *)
+Lemma loadimm64_32s_correct:
+ forall r n k rs m,
+ exists rs',
+ exec_straight ge fn (loadimm64_32s r n k) rs m k rs' m
+ /\ rs'#r = Vlong (Int64.sign_ext 32 n)
+ /\ forall r': preg, r' <> r -> r' <> PC -> rs'#r' = rs#r'.
+Proof.
+ unfold loadimm64_32s; intros. predSpec Int64.eq Int64.eq_spec n (low64_s n).
+ - econstructor; split; [|split].
+ + apply exec_straight_one. simpl; eauto. auto.
+ + Simpl. rewrite Int64.add_zero_l. rewrite H. unfold low64_s.
+ rewrite Int64.sign_ext_widen by omega. auto.
+ + intros; Simpl.
+ - econstructor; split; [|split].
+ + eapply exec_straight_two. simpl; eauto. simpl; eauto. auto. auto.
+ + Simpl. simpl. f_equal. rewrite Int64.add_zero_l.
+ apply Int64.same_bits_eq; intros. assert (Int64.zwordsize = 64) by auto.
+ rewrite Int64.bits_or, Int64.bits_shl by auto.
+ unfold low64_s, low64_u.
+ rewrite Int64.bits_zero_ext by omega.
+ change (Int64.unsigned (Int64.repr 16)) with 16.
+ destruct (zlt i 16).
+ * rewrite Int64.bits_sign_ext by omega. rewrite zlt_true by omega. auto.
+ * rewrite ! Int64.bits_sign_ext by omega. rewrite orb_false_r.
+ destruct (zlt i 32).
+ ** rewrite zlt_true by omega. rewrite Int64.bits_shr by omega.
+ change (Int64.unsigned (Int64.repr 16)) with 16.
+ rewrite zlt_true by omega. f_equal; omega.
+ ** rewrite zlt_false by omega. rewrite Int64.bits_shr by omega.
+ change (Int64.unsigned (Int64.repr 16)) with 16.
+ reflexivity.
+ + intros; Simpl.
+Qed.
+
Lemma loadimm64_correct:
forall r n k rs m,
exists rs',
@@ -539,20 +574,78 @@ Lemma loadimm64_correct:
/\ forall r': preg, r' <> r -> r' <> GPR12 -> r' <> PC -> rs'#r' = rs#r'.
Proof.
intros. unfold loadimm64.
- set (hi_s := Int64.sign_ext 16 (Int64.shr n (Int64.repr 16))).
- set (hi' := Int64.shl hi_s (Int64.repr 16)).
- destruct (Int64.eq n (low64_s n)).
- (* addi *)
- econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- rewrite Int64.add_zero_l. intuition Simpl.
- (* addis + ori *)
- predSpec Int64.eq Int64.eq_spec n (Int64.or hi' (low64_u n)).
- econstructor; split. eapply exec_straight_two. simpl; eauto. simpl; eauto. auto. auto.
- split. Simpl. rewrite Int64.add_zero_l. simpl; f_equal; auto.
- intros. Simpl.
- (* ldi *)
- econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- intuition Simpl.
+ predSpec Int64.eq Int64.eq_spec n (Int64.sign_ext 32 n).
+ - destruct (loadimm64_32s_correct r n k rs m) as (rs' & A & B & C).
+ exists rs'; intuition auto. congruence.
+ - econstructor; split. apply exec_straight_one. simpl; eauto. auto.
+ intuition Simpl.
+Qed.
+
+(** Alternate load int64 immediate *)
+
+Lemma loadimm64_notemp_correct:
+ forall r n k rs m,
+ exists rs',
+ exec_straight ge fn (loadimm64_notemp r n k) rs m k rs' m
+ /\ rs'#r = Vlong n
+ /\ forall r': preg, r' <> r -> r' <> PC -> rs'#r' = rs#r'.
+Proof.
+ intros. unfold loadimm64_notemp.
+ predSpec Int64.eq Int64.eq_spec n (Int64.sign_ext 32 n).
+- destruct (loadimm64_32s_correct r n k rs m) as (rs' & A & B & C).
+ exists rs'; intuition auto. congruence.
+- set (n2 := Int64.shru n (Int64.repr 32)).
+ set (n1 := Int64.zero_ext 16 (Int64.shru n (Int64.repr 16))).
+ set (n0 := Int64.zero_ext 16 n).
+ set (mi := Int64.shl n1 (Int64.repr 16)).
+ set (hi := Int64.shl (Int64.sign_ext 32 n2) (Int64.repr 32)).
+ assert (HI: forall i, 0 <= i < Int64.zwordsize ->
+ Int64.testbit hi i = if zlt i 32 then false else Int64.testbit n i).
+ { intros. unfold hi. assert (Int64.zwordsize = 64) by auto.
+ rewrite Int64.bits_shl by auto.
+ change (Int64.unsigned (Int64.repr 32)) with 32.
+ destruct (zlt i 32); auto.
+ rewrite Int64.bits_sign_ext by omega.
+ rewrite zlt_true by omega.
+ unfold n2. rewrite Int64.bits_shru by omega.
+ change (Int64.unsigned (Int64.repr 32)) with 32.
+ rewrite zlt_true by omega. f_equal; omega.
+ }
+ assert (MI: forall i, 0 <= i < Int64.zwordsize ->
+ Int64.testbit mi i =
+ if zlt i 16 then false
+ else if zlt i 32 then Int64.testbit n i else false).
+ { intros. unfold mi. assert (Int64.zwordsize = 64) by auto.
+ rewrite Int64.bits_shl by auto.
+ change (Int64.unsigned (Int64.repr 16)) with 16.
+ destruct (zlt i 16); auto.
+ unfold n1. rewrite Int64.bits_zero_ext by omega.
+ rewrite Int64.bits_shru by omega.
+ destruct (zlt i 32).
+ rewrite zlt_true by omega.
+ change (Int64.unsigned (Int64.repr 16)) with 16.
+ rewrite zlt_true by omega. f_equal; omega.
+ rewrite zlt_false by omega. auto.
+ }
+ assert (EQ: Int64.or (Int64.or hi mi) n0 = n).
+ { apply Int64.same_bits_eq; intros.
+ rewrite ! Int64.bits_or by auto.
+ unfold n0; rewrite Int64.bits_zero_ext by omega.
+ rewrite HI, MI by auto.
+ destruct (zlt i 16).
+ rewrite zlt_true by omega. auto.
+ destruct (zlt i 32); rewrite ! orb_false_r; auto.
+ }
+ edestruct (loadimm64_32s_correct r n2) as (rs' & A & B & C).
+ econstructor; split; [|split].
+ + eapply exec_straight_trans. eexact A.
+ eapply exec_straight_three.
+ simpl. rewrite B. simpl; auto.
+ simpl; auto.
+ simpl; auto.
+ reflexivity. reflexivity. reflexivity.
+ + Simpl. simpl. f_equal. rewrite <- Int64.shl_rolm by auto. exact EQ.
+ + intros; Simpl.
Qed.
(** Add int64 immediate. *)
@@ -889,7 +982,7 @@ Lemma transl_cond_correct_1:
(if snd (crbit_for_cond cond)
then Val.of_optbool (eval_condition cond (map rs (map preg_of args)) m)
else Val.notbool (Val.of_optbool (eval_condition cond (map rs (map preg_of args)) m)))
- /\ forall r, important_preg r = true -> preg_notin r (destroyed_by_cond cond) -> rs'#r = rs#r.
+ /\ forall r, important_preg r = true -> rs'#r = rs#r.
Proof.
intros.
Opaque Int.eq.
@@ -991,20 +1084,12 @@ Opaque Int.eq.
auto with asmgen.
- (* Ccomplimm *)
rewrite <- Val.notbool_negb_3. rewrite <- Val.negate_cmpl_bool.
- destruct (Int64.eq i (low64_s i)); [|destruct (ireg_eq x GPR12)]; inv EQ0.
+ destruct (Int64.eq i (low64_s i)); inv EQ0.
+ destruct (compare_slong_spec rs (rs x) (Vlong i)) as [A [B [C D]]].
econstructor; split.
apply exec_straight_one. simpl; reflexivity. reflexivity.
split. case c0; simpl; auto. auto with asmgen.
-+ destruct (loadimm64_correct GPR12 i (Pcmpd GPR0 GPR12 :: k) (nextinstr (rs#GPR0 <- (rs#GPR12))) m) as [rs1 [EX1 [RES1 OTH1]]].
- destruct (compare_slong_spec rs1 (rs GPR12) (Vlong i)) as [A [B [C D]]].
- assert (SAME: rs1 GPR0 = rs GPR12) by (apply OTH1; eauto with asmgen).
- econstructor; split.
- eapply exec_straight_step. simpl;reflexivity. reflexivity.
- eapply exec_straight_trans. eexact EX1. eapply exec_straight_one. simpl;reflexivity. reflexivity.
- split. rewrite RES1, SAME. destruct c0; simpl; auto.
- simpl; intros. rewrite RES1, SAME. rewrite D by eauto with asmgen. rewrite OTH1 by eauto with asmgen. Simpl.
-+ destruct (loadimm64_correct GPR0 i (Pcmpd x GPR0 :: k) rs m) as [rs1 [EX1 [RES1 OTH1]]].
++ destruct (loadimm64_notemp_correct GPR0 i (Pcmpd x GPR0 :: k) rs m) as [rs1 [EX1 [RES1 OTH1]]].
destruct (compare_slong_spec rs1 (rs x) (Vlong i)) as [A [B [C D]]].
assert (SAME: rs1 x = rs x) by (apply OTH1; eauto with asmgen).
econstructor; split.
@@ -1013,20 +1098,12 @@ Opaque Int.eq.
simpl; intros. rewrite RES1, SAME. rewrite D; eauto with asmgen.
- (* Ccompluimm *)
rewrite <- Val.notbool_negb_3. rewrite <- Val.negate_cmplu_bool.
- destruct (Int64.eq i (low64_u i)); [|destruct (ireg_eq x GPR12)]; inv EQ0.
+ destruct (Int64.eq i (low64_u i)); inv EQ0.
+ destruct (compare_ulong_spec rs m (rs x) (Vlong i)) as [A [B [C D]]].
econstructor; split.
apply exec_straight_one. simpl; reflexivity. reflexivity.
split. case c0; simpl; auto. auto with asmgen.
-+ destruct (loadimm64_correct GPR12 i (Pcmpld GPR0 GPR12 :: k) (nextinstr (rs#GPR0 <- (rs#GPR12))) m) as [rs1 [EX1 [RES1 OTH1]]].
- destruct (compare_ulong_spec rs1 m (rs GPR12) (Vlong i)) as [A [B [C D]]].
- assert (SAME: rs1 GPR0 = rs GPR12) by (apply OTH1; eauto with asmgen).
- econstructor; split.
- eapply exec_straight_step. simpl;reflexivity. reflexivity.
- eapply exec_straight_trans. eexact EX1. eapply exec_straight_one. simpl;reflexivity. reflexivity.
- split. rewrite RES1, SAME. destruct c0; simpl; auto.
- simpl; intros. rewrite RES1, SAME. rewrite D by eauto with asmgen. rewrite OTH1 by eauto with asmgen. Simpl.
-+ destruct (loadimm64_correct GPR0 i (Pcmpld x GPR0 :: k) rs m) as [rs1 [EX1 [RES1 OTH1]]].
++ destruct (loadimm64_notemp_correct GPR0 i (Pcmpld x GPR0 :: k) rs m) as [rs1 [EX1 [RES1 OTH1]]].
destruct (compare_ulong_spec rs1 m (rs x) (Vlong i)) as [A [B [C D]]].
assert (SAME: rs1 x = rs x) by (apply OTH1; eauto with asmgen).
econstructor; split.
@@ -1045,7 +1122,7 @@ Lemma transl_cond_correct_2:
(if snd (crbit_for_cond cond)
then Val.of_bool b
else Val.notbool (Val.of_bool b))
- /\ forall r, important_preg r = true -> preg_notin r (destroyed_by_cond cond) -> rs'#r = rs#r.
+ /\ forall r, important_preg r = true -> rs'#r = rs#r.
Proof.
intros.
replace (Val.of_bool b)
@@ -1072,7 +1149,8 @@ Proof.
exploit transl_cond_correct_2. eauto.
eapply eval_condition_lessdef. eapply preg_vals; eauto. eauto. eauto.
intros [rs' [A [B C]]].
- exists rs'; split. eauto. split. auto. apply agree_undef_regs with rs; auto. intros r D.
+ exists rs'; split. eauto. split. auto.
+ apply agree_undef_regs with rs; auto. intros r D E.
apply C. apply important_data_preg_1; auto.
Qed.
@@ -1180,6 +1258,66 @@ Proof.
intuition Simpl.
rewrite RES1. destruct (eval_condition c rs ## (preg_of ## rl) m). destruct b; auto. auto.
Qed.
+
+Lemma transl_select_op_correct:
+ forall cond args ty r1 r2 rd k rs m c,
+ transl_select_op cond args r1 r2 rd k = OK c ->
+ important_preg rd = true -> important_preg r1 = true -> important_preg r2 = true ->
+ exists rs',
+ exec_straight ge fn c rs m k rs' m
+ /\ Val.lessdef (Val.select (eval_condition cond (map rs (map preg_of args)) m) rs#r1 rs#r2 ty) rs'#rd
+ /\ forall r, important_preg r = true -> r <> rd -> rs'#r = rs#r.
+Proof.
+ intros until c. intros TR IMP1 IMP2 IMP3.
+ unfold transl_select_op in TR.
+ destruct (ireg_eq r1 r2).
+ - inv TR. econstructor; split; [|split].
+ + apply exec_straight_one. simpl; eauto. auto.
+ + Simpl. destruct (eval_condition cond rs ## (preg_of ## args) m) as [[]|]; simpl; auto using Val.lessdef_normalize.
+ + intros; Simpl.
+ - destruct (transl_cond_correct_1 cond args _ rs m _ TR) as (rs1 & A & B & C).
+ set (bit := fst (crbit_for_cond cond)) in *.
+ set (dir := snd (crbit_for_cond cond)) in *.
+ set (ob := eval_condition cond rs##(preg_of##args) m) in *.
+ econstructor; split; [|split].
+ + eapply exec_straight_trans. eexact A. apply exec_straight_one. simpl; eauto.
+ reflexivity.
+ + Simpl.
+ rewrite <- (C r1), <- (C r2) by auto.
+ rewrite B, gpr_or_zero_not_zero.
+ destruct dir; destruct ob as [[]|]; simpl; auto using Val.lessdef_normalize.
+ destruct dir; intros e; subst; discriminate.
+ + intros. Simpl.
+Qed.
+
+Lemma transl_fselect_op_correct:
+ forall cond args ty r1 r2 rd k rs m c,
+ transl_fselect_op cond args r1 r2 rd k = OK c ->
+ important_preg rd = true -> important_preg r1 = true -> important_preg r2 = true ->
+ exists rs',
+ exec_straight ge fn c rs m k rs' m
+ /\ Val.lessdef (Val.select (eval_condition cond (map rs (map preg_of args)) m) rs#r1 rs#r2 ty) rs'#rd
+ /\ forall r, important_preg r = true -> r <> rd -> rs'#r = rs#r.
+Proof.
+ intros until c. intros TR IMP1 IMP2 IMP3.
+ unfold transl_fselect_op in TR.
+ destruct (freg_eq r1 r2).
+ - inv TR. econstructor; split; [|split].
+ + apply exec_straight_one. simpl; eauto. auto.
+ + Simpl. destruct (eval_condition cond rs ## (preg_of ## args) m) as [[]|]; simpl; auto using Val.lessdef_normalize.
+ + intros; Simpl.
+ - destruct (transl_cond_correct_1 cond args _ rs m _ TR) as (rs1 & A & B & C).
+ set (bit := fst (crbit_for_cond cond)) in *.
+ set (dir := snd (crbit_for_cond cond)) in *.
+ set (ob := eval_condition cond rs##(preg_of##args) m) in *.
+ econstructor; split; [|split].
+ + eapply exec_straight_trans. eexact A. apply exec_straight_one. simpl; eauto.
+ reflexivity.
+ + Simpl.
+ rewrite <- (C r1), <- (C r2) by auto.
+ rewrite B. destruct dir; destruct ob as [[]|]; simpl; auto using Val.lessdef_normalize.
+ + intros. Simpl.
+Qed.
(** Translation of arithmetic operations. *)
@@ -1377,6 +1515,18 @@ Opaque Val.add.
(* Ocmp *)
- destruct (transl_cond_op_correct c0 args res k rs m c) as [rs' [A [B C]]]; auto.
exists rs'; auto with asmgen.
+ (* Osel *)
+- assert (X: forall mr r, ireg_of mr = OK r -> important_preg r = true).
+ { intros. apply ireg_of_eq in H0. apply important_data_preg_1. rewrite <- H0.
+ auto with asmgen. }
+ assert (Y: forall mr r, freg_of mr = OK r -> important_preg r = true).
+ { intros. apply freg_of_eq in H0. apply important_data_preg_1. rewrite <- H0.
+ auto with asmgen. }
+ destruct (preg_of res) eqn:RES; monadInv H; rewrite <- RES.
+ + rewrite (ireg_of_eq _ _ EQ), (ireg_of_eq _ _ EQ0), (ireg_of_eq _ _ EQ1) in *.
+ destruct (transl_select_op_correct _ _ t _ _ _ _ rs m _ EQ3) as (rs' & A & B & C); eauto.
+ + rewrite (freg_of_eq _ _ EQ), (freg_of_eq _ _ EQ0), (freg_of_eq _ _ EQ1) in *.
+ destruct (transl_fselect_op_correct _ _ t _ _ _ _ rs m _ EQ3) as (rs' & A & B & C); eauto.
Qed.
Lemma transl_op_correct: