summaryrefslogtreecommitdiff
path: root/ia32
diff options
context:
space:
mode:
authorGravatar xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>2011-08-05 17:29:06 +0000
committerGravatar xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>2011-08-05 17:29:06 +0000
commit5d1c52555bb166430402103afe9540cc4c296487 (patch)
tree2a23a9acb86dca39f1b04c46f3913ec35e30be79 /ia32
parenta80483e9f8ec927bfd1f32a117c56c8167cecc4f (diff)
Cleaned up handling of composite conditions
git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@1699 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
Diffstat (limited to 'ia32')
-rw-r--r--ia32/Asm.v16
-rw-r--r--ia32/Asmgen.v69
-rw-r--r--ia32/Asmgenproof.v126
-rw-r--r--ia32/Asmgenproof1.v134
-rw-r--r--ia32/Asmgenretaddr.v18
-rw-r--r--ia32/PrintAsm.ml47
6 files changed, 311 insertions, 99 deletions
diff --git a/ia32/Asm.v b/ia32/Asm.v
index ebb22a6..1870d69 100644
--- a/ia32/Asm.v
+++ b/ia32/Asm.v
@@ -85,9 +85,7 @@ Inductive testcond: Type :=
| Cond_e | Cond_ne
| Cond_b | Cond_be | Cond_ae | Cond_a
| Cond_l | Cond_le | Cond_ge | Cond_g
- | Cond_p | Cond_np
- | Cond_nep (**r synthetic: P or (not Z) *)
- | Cond_enp. (**r synthetic: (not P) and Z *)
+ | Cond_p | Cond_np.
(** Instructions. IA32 instructions accept many combinations of
registers, memory references and immediate constants as arguments.
@@ -178,6 +176,7 @@ Inductive instruction: Type :=
| Pjmp_s (symb: ident)
| Pjmp_r (r: ireg)
| Pjcc (c: testcond)(l: label)
+ | Pjcc2 (c1 c2: testcond)(l: label)
| Pjmptbl (r: ireg) (tbl: list label) (**r pseudo *)
| Pcall_s (symb: ident)
| Pcall_r (r: ireg)
@@ -381,6 +380,7 @@ Definition eval_testcond (c: testcond) (rs: regset) : option bool :=
| Vint n => Some (Int.eq n Int.zero)
| _ => None
end
+(*
| Cond_nep =>
match rs PF, rs ZF with
| Vint p, Vint z => Some (Int.eq p Int.one || Int.eq z Int.zero)
@@ -391,6 +391,7 @@ Definition eval_testcond (c: testcond) (rs: regset) : option bool :=
| Vint p, Vint z => Some (Int.eq p Int.zero && Int.eq z Int.one)
| _, _ => None
end
+*)
end.
(** The semantics is purely small-step and defined as a function
@@ -580,8 +581,7 @@ Definition exec_instr (c: code) (i: instruction) (rs: regset) (m: mem) : outcome
end
| Psetcc c rd =>
match eval_testcond c rs with
- | Some true => Next (nextinstr (rs#ECX <- Vundef #EDX <- Vundef #rd <- Vtrue)) m
- | Some false => Next (nextinstr (rs#ECX <- Vundef #EDX <- Vundef #rd <- Vfalse)) m
+ | Some b => Next (nextinstr (rs#ECX <- Vundef #rd <- (Val.of_bool b))) m
| None => Stuck
end
(** Arithmetic operations over floats *)
@@ -612,6 +612,12 @@ Definition exec_instr (c: code) (i: instruction) (rs: regset) (m: mem) : outcome
| Some false => Next (nextinstr rs) m
| None => Stuck
end
+ | Pjcc2 cond1 cond2 lbl =>
+ match eval_testcond cond1 rs, eval_testcond cond2 rs with
+ | Some true, Some true => goto_label c lbl rs m
+ | Some _, Some _ => Next (nextinstr rs) m
+ | _, _ => Stuck
+ end
| Pjmptbl r tbl =>
match rs#r with
| Vint n =>
diff --git a/ia32/Asmgen.v b/ia32/Asmgen.v
index c87167b..452f2e7 100644
--- a/ia32/Asmgen.v
+++ b/ia32/Asmgen.v
@@ -253,32 +253,59 @@ Definition testcond_for_unsigned_comparison (cmp: comparison) :=
| Cge => Cond_ae
end.
-Definition testcond_for_condition (cond: condition) : testcond :=
+Inductive extcond: Type :=
+ | Cond_base (c: testcond)
+ | Cond_or (c1 c2: testcond)
+ | Cond_and (c1 c2: testcond).
+
+Definition testcond_for_condition (cond: condition) : extcond :=
match cond with
- | Ccomp c => testcond_for_signed_comparison c
- | Ccompu c => testcond_for_unsigned_comparison c
- | Ccompimm c n => testcond_for_signed_comparison c
- | Ccompuimm c n => testcond_for_unsigned_comparison c
+ | Ccomp c => Cond_base(testcond_for_signed_comparison c)
+ | Ccompu c => Cond_base(testcond_for_unsigned_comparison c)
+ | Ccompimm c n => Cond_base(testcond_for_signed_comparison c)
+ | Ccompuimm c n => Cond_base(testcond_for_unsigned_comparison c)
| Ccompf c =>
match c with
- | Ceq => Cond_enp
- | Cne => Cond_nep
- | Clt => Cond_a
- | Cle => Cond_ae
- | Cgt => Cond_a
- | Cge => Cond_ae
+ | Ceq => Cond_and Cond_np Cond_e
+ | Cne => Cond_or Cond_p Cond_ne
+ | Clt => Cond_base Cond_a
+ | Cle => Cond_base Cond_ae
+ | Cgt => Cond_base Cond_a
+ | Cge => Cond_base Cond_ae
end
| Cnotcompf c =>
match c with
- | Ceq => Cond_nep
- | Cne => Cond_enp
- | Clt => Cond_be
- | Cle => Cond_b
- | Cgt => Cond_be
- | Cge => Cond_b
+ | Ceq => Cond_or Cond_p Cond_ne
+ | Cne => Cond_and Cond_np Cond_e
+ | Clt => Cond_base Cond_be
+ | Cle => Cond_base Cond_b
+ | Cgt => Cond_base Cond_be
+ | Cge => Cond_base Cond_b
end
- | Cmaskzero n => Cond_e
- | Cmasknotzero n => Cond_ne
+ | Cmaskzero n => Cond_base Cond_e
+ | Cmasknotzero n => Cond_base Cond_ne
+ end.
+
+(** Acting upon extended conditions. *)
+
+Definition mk_setcc (cond: extcond) (rd: ireg) (k: code) :=
+ match cond with
+ | Cond_base c => Psetcc c rd :: k
+ | Cond_and c1 c2 =>
+ if ireg_eq rd EDX
+ then Psetcc c1 EDX :: Psetcc c2 ECX :: Pand_rr EDX ECX :: k
+ else Psetcc c1 EDX :: Psetcc c2 rd :: Pand_rr rd EDX :: k
+ | Cond_or c1 c2 =>
+ if ireg_eq rd EDX
+ then Psetcc c1 EDX :: Psetcc c2 ECX :: Por_rr EDX ECX :: k
+ else Psetcc c1 EDX :: Psetcc c2 rd :: Por_rr rd EDX :: k
+ end.
+
+Definition mk_jcc (cond: extcond) (lbl: label) (k: code) :=
+ match cond with
+ | Cond_base c => Pjcc c lbl :: k
+ | Cond_and c1 c2 => Pjcc2 c1 c2 lbl :: k
+ | Cond_or c1 c2 => Pjcc c1 lbl :: Pjcc c2 lbl :: k
end.
(** Translation of the arithmetic operation [r <- op(args)].
@@ -396,7 +423,7 @@ Definition transl_op
do r <- freg_of res; do r1 <- ireg_of a1; OK (Pcvtsi2sd_fr r r1 :: k)
| Ocmp c, args =>
do r <- ireg_of res;
- transl_cond c args (Psetcc (testcond_for_condition c) r :: k)
+ transl_cond c args (mk_setcc (testcond_for_condition c) r k)
| _, _ =>
Error(msg "Asmgen.transl_op")
end.
@@ -486,7 +513,7 @@ Definition transl_instr (f: Mach.function) (i: Mach.instruction)
| Mgoto lbl =>
OK(Pjmp_l lbl :: k)
| Mcond cond args lbl =>
- transl_cond cond args (Pjcc (testcond_for_condition cond) lbl :: k)
+ transl_cond cond args (mk_jcc (testcond_for_condition cond) lbl k)
| Mjumptable arg tbl =>
do r <- ireg_of arg; OK (Pjmptbl r tbl :: k)
| Mreturn =>
diff --git a/ia32/Asmgenproof.v b/ia32/Asmgenproof.v
index d049737..45ac48d 100644
--- a/ia32/Asmgenproof.v
+++ b/ia32/Asmgenproof.v
@@ -401,6 +401,20 @@ Proof.
destruct (preg_of src); inv H; auto.
Qed.
+Remark mk_setcc_label:
+ forall xc rd k,
+ find_label lbl (mk_setcc xc rd k) = find_label lbl k.
+Proof.
+ intros. destruct xc; simpl; auto; destruct (ireg_eq rd EDX); auto.
+Qed.
+
+Remark mk_jcc_label:
+ forall xc lbl' k,
+ find_label lbl (mk_jcc xc lbl' k) = find_label lbl k.
+Proof.
+ intros. destruct xc; auto.
+Qed.
+
Ltac ArgsInv :=
match goal with
| [ H: Error _ = OK _ |- _ ] => discriminate
@@ -441,7 +455,7 @@ Proof.
eapply mk_shift_label; eauto.
eapply mk_shrximm_label; eauto.
eapply mk_shift_label; eauto.
- eapply trans_eq. eapply transl_cond_label; eauto. auto.
+ eapply trans_eq. eapply transl_cond_label; eauto. apply mk_setcc_label.
Qed.
Remark transl_load_label:
@@ -482,7 +496,7 @@ Opaque loadind.
monadInv H; auto.
inv H; simpl. destruct (peq lbl l). congruence. auto.
monadInv H; auto.
- eapply trans_eq. eapply transl_cond_label; eauto. auto.
+ eapply trans_eq. eapply transl_cond_label; eauto. apply mk_jcc_label.
monadInv H; auto.
monadInv H; auto.
Qed.
@@ -624,6 +638,43 @@ Proof.
econstructor; eauto. eapply exec_straight_at; eauto.
Qed.
+Lemma exec_straight_steps_goto:
+ forall s fb f rs1 i c ep tf tc m1' m2 m2' sp ms2 lbl c',
+ match_stack s ->
+ Mem.extends m2 m2' ->
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ Mach.find_label lbl f.(fn_code) = Some c' ->
+ transl_code_at_pc (rs1 PC) fb f (i :: c) ep tf tc ->
+ edx_preserved ep i = false ->
+ (forall k c, transl_instr f i ep k = OK c ->
+ exists jmp, exists k', exists rs2,
+ exec_straight tge tf c rs1 m1' (jmp :: k') rs2 m2'
+ /\ agree ms2 sp rs2
+ /\ exec_instr tge tf jmp rs2 m2' = goto_label tf lbl rs2 m2') ->
+ exists st',
+ plus step tge (State rs1 m1') E0 st' /\
+ match_states (Machsem.State s fb sp c' ms2 m2) st'.
+Proof.
+ intros. inversion H3. subst. monadInv H9.
+ exploit H5; eauto. intros [jmp [k' [rs2 [A [B C]]]]].
+ generalize (functions_transl _ _ _ H7 H8); intro FN.
+ generalize (transf_function_no_overflow _ _ H8); intro NOOV.
+ exploit exec_straight_steps_2; eauto.
+ intros [ofs' [PC2 CT2]].
+ exploit find_label_goto_label; eauto.
+ intros [tc' [rs3 [GOTO [AT' OTH]]]].
+ exists (State rs3 m2'); split.
+ eapply plus_right'.
+ eapply exec_straight_steps_1; eauto.
+ econstructor; eauto.
+ eapply find_instr_tail. eauto.
+ rewrite C. eexact GOTO.
+ traceEq.
+ econstructor; eauto.
+ apply agree_exten with rs2; auto with ppcgen.
+ congruence.
+Qed.
+
Lemma parent_sp_def: forall s, match_stack s -> parent_sp s <> Vundef.
Proof. induction 1; simpl. congruence. auto. Qed.
@@ -1053,22 +1104,40 @@ Lemma exec_Mcond_true_prop:
Proof.
intros; red; intros; inv MS. assert (f0 = f) by congruence. subst f0.
exploit eval_condition_lessdef. eapply preg_vals; eauto. eauto. eauto. intros EC.
- inv AT. monadInv H5.
+ left; eapply exec_straight_steps_goto; eauto.
+ intros. simpl in H2.
exploit transl_cond_correct; eauto. intros [rs' [A [B C]]].
- generalize (functions_transl _ _ _ FIND H4); intro FN.
- generalize (transf_function_no_overflow _ _ H4); intro NOOV.
- exploit exec_straight_steps_2; eauto.
- intros [ofs' [PC2 CT2]].
- exploit find_label_goto_label; eauto.
- intros [tc' [rs3 [GOTO [AT3 INV3]]]].
- left; exists (State rs3 m'); split.
- eapply plus_right'.
- eapply exec_straight_steps_1; eauto.
- econstructor; eauto.
- eapply find_instr_tail. eauto. simpl. rewrite B. eauto. traceEq.
- econstructor; eauto.
- eapply agree_exten_temps; eauto. intros. rewrite INV3; auto with ppcgen.
- congruence.
+ destruct (testcond_for_condition cond); simpl in *.
+(* simple jcc *)
+ exists (Pjcc c1 lbl); exists k; exists rs'.
+ split. eexact A.
+ split. eapply agree_exten_temps; eauto.
+ simpl. rewrite B. auto.
+(* jcc; jcc *)
+ destruct (eval_testcond c1 rs') as [b1|]_eqn;
+ destruct (eval_testcond c2 rs') as [b2|]_eqn; inv B.
+ destruct b1.
+ (* first jcc jumps *)
+ exists (Pjcc c1 lbl); exists (Pjcc c2 lbl :: k); exists rs'.
+ split. eexact A.
+ split. eapply agree_exten_temps; eauto.
+ simpl. rewrite Heqo. auto.
+ (* second jcc jumps *)
+ exists (Pjcc c2 lbl); exists k; exists (nextinstr rs').
+ split. eapply exec_straight_trans. eexact A.
+ eapply exec_straight_one. simpl. rewrite Heqo. auto. auto.
+ split. eapply agree_exten_temps; eauto.
+ intros. rewrite nextinstr_inv; auto with ppcgen.
+ simpl. rewrite eval_testcond_nextinstr. rewrite Heqo0.
+ destruct b2; auto || discriminate.
+(* jcc2 *)
+ destruct (eval_testcond c1 rs') as [b1|]_eqn;
+ destruct (eval_testcond c2 rs') as [b2|]_eqn; inv B.
+ destruct (andb_prop _ _ H4). subst.
+ exists (Pjcc2 c1 c2 lbl); exists k; exists rs'.
+ split. eexact A.
+ split. eapply agree_exten_temps; eauto.
+ simpl. rewrite Heqo; rewrite Heqo0; auto.
Qed.
Lemma exec_Mcond_false_prop:
@@ -1083,11 +1152,34 @@ Proof.
exploit eval_condition_lessdef. eapply preg_vals; eauto. eauto. eauto. intros EC.
left; eapply exec_straight_steps; eauto. intros. simpl in H0.
exploit transl_cond_correct; eauto. intros [rs' [A [B C]]].
+ destruct (testcond_for_condition cond); simpl in *.
+(* simple jcc *)
econstructor; split.
eapply exec_straight_trans. eexact A.
apply exec_straight_one. simpl. rewrite B. eauto. auto.
split. apply agree_nextinstr. eapply agree_exten_temps; eauto.
simpl; congruence.
+(* jcc ; jcc *)
+ destruct (eval_testcond c1 rs') as [b1|]_eqn;
+ destruct (eval_testcond c2 rs') as [b2|]_eqn; inv B.
+ destruct (orb_false_elim _ _ H2); subst.
+ econstructor; split.
+ eapply exec_straight_trans. eexact A.
+ eapply exec_straight_two. simpl. rewrite Heqo. eauto. auto.
+ simpl. rewrite eval_testcond_nextinstr. rewrite Heqo0. eauto. auto. auto.
+ split. apply agree_nextinstr. apply agree_nextinstr. eapply agree_exten_temps; eauto.
+ simpl; congruence.
+(* jcc2 *)
+ destruct (eval_testcond c1 rs') as [b1|]_eqn;
+ destruct (eval_testcond c2 rs') as [b2|]_eqn; inv B.
+ exists (nextinstr rs'); split.
+ eapply exec_straight_trans. eexact A.
+ apply exec_straight_one. simpl.
+ rewrite Heqo; rewrite Heqo0.
+ destruct b1. simpl in *. subst b2. auto. auto.
+ auto.
+ split. apply agree_nextinstr. eapply agree_exten_temps; eauto.
+ rewrite H2; congruence.
Qed.
Lemma exec_Mjumptable_prop:
diff --git a/ia32/Asmgenproof1.v b/ia32/Asmgenproof1.v
index b3e7aaa..3a91ac5 100644
--- a/ia32/Asmgenproof1.v
+++ b/ia32/Asmgenproof1.v
@@ -1147,6 +1147,22 @@ Proof.
intros. repeat SOther.
Qed.
+Definition eval_extcond (xc: extcond) (rs: regset) : option bool :=
+ match xc with
+ | Cond_base c =>
+ eval_testcond c rs
+ | Cond_and c1 c2 =>
+ match eval_testcond c1 rs, eval_testcond c2 rs with
+ | Some b1, Some b2 => Some (b1 && b2)
+ | _, _ => None
+ end
+ | Cond_or c1 c2 =>
+ match eval_testcond c1 rs, eval_testcond c2 rs with
+ | Some b1, Some b2 => Some (b1 || b2)
+ | _, _ => None
+ end
+ end.
+
Definition swap_floats (c: comparison) (n1 n2: float) : float :=
match c with
| Clt | Cle => n2
@@ -1155,9 +1171,9 @@ Definition swap_floats (c: comparison) (n1 n2: float) : float :=
Lemma testcond_for_float_comparison_correct:
forall c n1 n2 rs,
- eval_testcond (testcond_for_condition (Ccompf c))
- (nextinstr (compare_floats (Vfloat (swap_floats c n1 n2))
- (Vfloat (swap_floats c n2 n1)) rs)) =
+ eval_extcond (testcond_for_condition (Ccompf c))
+ (nextinstr (compare_floats (Vfloat (swap_floats c n1 n2))
+ (Vfloat (swap_floats c n2 n1)) rs)) =
Some(Float.cmp c n1 n2).
Proof.
intros.
@@ -1165,7 +1181,7 @@ Proof.
set (rs' := nextinstr (compare_floats (Vfloat (swap_floats c n1 n2))
(Vfloat (swap_floats c n2 n1)) rs)).
intros [A [B [C D]]].
- unfold eval_testcond. rewrite A; rewrite B; rewrite C.
+ unfold eval_extcond, eval_testcond. rewrite A; rewrite B; rewrite C.
destruct c; simpl.
(* eq *)
rewrite Float.cmp_ne_eq.
@@ -1203,9 +1219,9 @@ Qed.
Lemma testcond_for_neg_float_comparison_correct:
forall c n1 n2 rs,
- eval_testcond (testcond_for_condition (Cnotcompf c))
- (nextinstr (compare_floats (Vfloat (swap_floats c n1 n2))
- (Vfloat (swap_floats c n2 n1)) rs)) =
+ eval_extcond (testcond_for_condition (Cnotcompf c))
+ (nextinstr (compare_floats (Vfloat (swap_floats c n1 n2))
+ (Vfloat (swap_floats c n2 n1)) rs)) =
Some(negb(Float.cmp c n1 n2)).
Proof.
intros.
@@ -1213,7 +1229,7 @@ Proof.
set (rs' := nextinstr (compare_floats (Vfloat (swap_floats c n1 n2))
(Vfloat (swap_floats c n2 n1)) rs)).
intros [A [B [C D]]].
- unfold eval_testcond. rewrite A; rewrite B; rewrite C.
+ unfold eval_extcond, eval_testcond. rewrite A; rewrite B; rewrite C.
destruct c; simpl.
(* eq *)
rewrite Float.cmp_ne_eq.
@@ -1255,7 +1271,7 @@ Lemma transl_cond_correct:
eval_condition cond (map rs (map preg_of args)) m = Some b ->
exists rs',
exec_straight c rs m k rs' m
- /\ eval_testcond (testcond_for_condition cond) rs' = Some b
+ /\ eval_extcond (testcond_for_condition cond) rs' = Some b
/\ forall r, nontemp_preg r = true -> rs'#r = rs r.
Proof.
unfold transl_cond; intros.
@@ -1264,17 +1280,17 @@ Proof.
simpl map in H0. rewrite (ireg_of_eq _ _ EQ) in H0. rewrite (ireg_of_eq _ _ EQ1) in H0.
econstructor. split. apply exec_straight_one. simpl. eauto. auto.
split. simpl in H0. FuncInv.
- subst b. apply testcond_for_signed_comparison_correct_ii.
+ subst b. simpl. apply testcond_for_signed_comparison_correct_ii.
intros. unfold compare_ints. repeat SOther.
(* compu *)
simpl map in H0.
rewrite (ireg_of_eq _ _ EQ) in H0. rewrite (ireg_of_eq _ _ EQ1) in H0.
econstructor. split. apply exec_straight_one. simpl. eauto. auto.
split. simpl in H0. FuncInv.
- subst b. apply testcond_for_unsigned_comparison_correct_ii.
- apply testcond_for_unsigned_comparison_correct_ip; auto.
- apply testcond_for_unsigned_comparison_correct_pi; auto.
- eapply testcond_for_unsigned_comparison_correct_pp; eauto.
+ subst b. simpl; apply testcond_for_unsigned_comparison_correct_ii.
+ simpl; apply testcond_for_unsigned_comparison_correct_ip; auto.
+ simpl; apply testcond_for_unsigned_comparison_correct_pi; auto.
+ simpl; eapply testcond_for_unsigned_comparison_correct_pp; eauto.
intros. unfold compare_ints. repeat SOther.
(* compimm *)
simpl map in H0. rewrite (ireg_of_eq _ _ EQ) in H0.
@@ -1284,14 +1300,14 @@ Proof.
simpl in H0. FuncInv. simpl. rewrite Int.and_idem. auto. auto.
apply exec_straight_one; auto.
split. simpl in H0. FuncInv.
- subst b. apply testcond_for_signed_comparison_correct_ii.
+ subst b. simpl; apply testcond_for_signed_comparison_correct_ii.
intros. unfold compare_ints. repeat SOther.
(* compuimm *)
simpl map in H0. rewrite (ireg_of_eq _ _ EQ) in H0.
econstructor. split. apply exec_straight_one. simpl; eauto. auto.
split. simpl in H0. FuncInv.
- subst b. apply testcond_for_unsigned_comparison_correct_ii.
- apply testcond_for_unsigned_comparison_correct_pi; auto.
+ subst b. simpl; apply testcond_for_unsigned_comparison_correct_ii.
+ simpl; apply testcond_for_unsigned_comparison_correct_pi; auto.
intros. unfold compare_ints. repeat SOther.
(* compf *)
simpl map in H0. rewrite (freg_of_eq _ _ EQ) in H0. rewrite (freg_of_eq _ _ EQ1) in H0.
@@ -1327,6 +1343,78 @@ Proof.
intros. unfold compare_ints. repeat SOther.
Qed.
+Remark eval_testcond_nextinstr:
+ forall c rs, eval_testcond c (nextinstr rs) = eval_testcond c rs.
+Proof.
+ intros. unfold eval_testcond. repeat rewrite nextinstr_inv; auto with ppcgen.
+Qed.
+
+Remark eval_testcond_set_ireg:
+ forall c rs r v, eval_testcond c (rs#(IR r) <- v) = eval_testcond c rs.
+Proof.
+ intros. unfold eval_testcond. repeat rewrite Pregmap.gso; auto with ppcgen.
+Qed.
+
+Lemma mk_setcc_correct:
+ forall cond rd k rs1 m b,
+ eval_extcond cond rs1 = Some b ->
+ exists rs2,
+ exec_straight (mk_setcc cond rd k) rs1 m k rs2 m
+ /\ rs2#rd = Val.of_bool b
+ /\ forall r, nontemp_preg r = true -> r <> rd -> rs2#r = rs1#r.
+Proof.
+ intros. destruct cond; simpl in *.
+(* base *)
+ econstructor; split.
+ apply exec_straight_one. simpl; rewrite H. eauto. auto.
+ split. repeat SRes.
+ intros. repeat SOther.
+(* or *)
+ destruct (eval_testcond c1 rs1) as [b1|]_eqn;
+ destruct (eval_testcond c2 rs1) as [b2|]_eqn; inv H.
+ assert (D: Val.or (Val.of_bool b1) (Val.of_bool b2) = Val.of_bool (b1 || b2)).
+ destruct b1; destruct b2; auto.
+ destruct (ireg_eq rd EDX).
+ subst rd. econstructor; split.
+ eapply exec_straight_three.
+ simpl; rewrite Heqo; eauto.
+ simpl. rewrite eval_testcond_nextinstr. repeat rewrite eval_testcond_set_ireg. rewrite Heqo0. eauto.
+ simpl. eauto.
+ auto. auto. auto.
+ split. SRes.
+ intros. repeat SOther.
+ econstructor; split.
+ eapply exec_straight_three.
+ simpl; rewrite Heqo; eauto.
+ simpl. rewrite eval_testcond_nextinstr. repeat rewrite eval_testcond_set_ireg. rewrite Heqo0. eauto.
+ simpl. eauto.
+ auto. auto. auto.
+ split. repeat SRes. rewrite <- D. rewrite Val.or_commut. decEq; repeat SRes.
+ intros. repeat SOther.
+(* and *)
+ destruct (eval_testcond c1 rs1) as [b1|]_eqn;
+ destruct (eval_testcond c2 rs1) as [b2|]_eqn; inv H.
+ assert (D: Val.and (Val.of_bool b1) (Val.of_bool b2) = Val.of_bool (b1 && b2)).
+ destruct b1; destruct b2; auto.
+ destruct (ireg_eq rd EDX).
+ subst rd. econstructor; split.
+ eapply exec_straight_three.
+ simpl; rewrite Heqo; eauto.
+ simpl. rewrite eval_testcond_nextinstr. repeat rewrite eval_testcond_set_ireg. rewrite Heqo0. eauto.
+ simpl. eauto.
+ auto. auto. auto.
+ split. SRes.
+ intros. repeat SOther.
+ econstructor; split.
+ eapply exec_straight_three.
+ simpl; rewrite Heqo; eauto.
+ simpl. rewrite eval_testcond_nextinstr. repeat rewrite eval_testcond_set_ireg. rewrite Heqo0. eauto.
+ simpl. eauto.
+ auto. auto. auto.
+ split. repeat SRes. rewrite <- D. rewrite Val.and_commut. decEq; repeat SRes.
+ intros. repeat SOther.
+Qed.
+
(** Translation of arithmetic operations. *)
(*
@@ -1367,8 +1455,6 @@ Ltac TranslOp :=
[ apply exec_straight_one; [ simpl; eauto | auto ]
| split; [ repeat SRes | intros; repeat SOther ]].
-(* Move elsewhere *)
-
Lemma transl_op_correct:
forall op args res k c (rs: regset) m v,
transl_op op args res k = OK c ->
@@ -1425,11 +1511,11 @@ Proof.
remember (eval_condition c0 rs ## (preg_of ## args) m) as ob. destruct ob; inv EV.
rewrite (eval_condition_weaken _ _ _ (sym_equal Heqob)).
exploit transl_cond_correct; eauto. intros [rs2 [P [Q R]]].
- exists (nextinstr (rs2#ECX <- Vundef #EDX <- Vundef #x <- v)).
- split. eapply exec_straight_trans. eauto.
- apply exec_straight_one. simpl. rewrite Q. destruct b; inv H0; auto. auto.
- split. repeat SRes. destruct b; inv H0; auto.
- intros. repeat SOther.
+ exploit mk_setcc_correct; eauto. intros [rs3 [S [T U]]].
+ exists rs3.
+ split. eapply exec_straight_trans. eexact P. eexact S.
+ split. auto.
+ intros. transitivity (rs2 r); auto.
Qed.
(** Translation of memory loads. *)
diff --git a/ia32/Asmgenretaddr.v b/ia32/Asmgenretaddr.v
index 674a73e..e0787d7 100644
--- a/ia32/Asmgenretaddr.v
+++ b/ia32/Asmgenretaddr.v
@@ -173,8 +173,24 @@ Proof.
unfold storeind; intros. destruct ty; IsTail. destruct (preg_of src); IsTail.
Qed.
+Lemma mk_setcc_tail:
+ forall cond rd k, is_tail k (mk_setcc cond rd k).
+Proof.
+ unfold mk_setcc; intros. destruct cond.
+ IsTail.
+ destruct (ireg_eq rd EDX); IsTail.
+ destruct (ireg_eq rd EDX); IsTail.
+Qed.
+
+Lemma mk_jcc_tail:
+ forall cond lbl k, is_tail k (mk_jcc cond lbl k).
+Proof.
+ unfold mk_jcc; intros. destruct cond; IsTail.
+Qed.
+
Hint Resolve mk_mov_tail mk_shift_tail mk_div_tail mk_mod_tail mk_shrximm_tail
- mk_intconv_tail mk_smallstore_tail loadind_tail storeind_tail : ppcretaddr.
+ mk_intconv_tail mk_smallstore_tail loadind_tail storeind_tail
+ mk_setcc_tail mk_jcc_tail : ppcretaddr.
Lemma transl_cond_tail:
forall cond args k c, transl_cond cond args k = OK c -> is_tail k c.
diff --git a/ia32/PrintAsm.ml b/ia32/PrintAsm.ml
index 6f02a8a..a6369c4 100644
--- a/ia32/PrintAsm.ml
+++ b/ia32/PrintAsm.ml
@@ -132,7 +132,12 @@ let name_of_condition = function
| Cond_b -> "b" | Cond_be -> "be" | Cond_ae -> "ae" | Cond_a -> "a"
| Cond_l -> "l" | Cond_le -> "le" | Cond_ge -> "ge" | Cond_g -> "g"
| Cond_p -> "p" | Cond_np -> "np"
- | Cond_nep | Cond_enp -> assert false (* treated specially *)
+
+let name_of_neg_condition = function
+ | Cond_e -> "ne" | Cond_ne -> "e"
+ | Cond_b -> "ae" | Cond_be -> "a" | Cond_ae -> "b" | Cond_a -> "be"
+ | Cond_l -> "ge" | Cond_le -> "g" | Cond_ge -> "l" | Cond_g -> "le"
+ | Cond_p -> "np" | Cond_np -> "p"
let section oc name =
fprintf oc " %s\n" name
@@ -218,14 +223,11 @@ let need_masks = ref false
(* Built-in functions *)
-(* Built-ins. They come in three flavors:
+(* Built-ins. They come in two flavors:
- annotation statements: take their arguments in registers or stack
locations; generate no code;
- inlined by the compiler: take their arguments in arbitrary
- registers; preserve all registers except ECX, EDX, XMM6 and XMM7
- - inlined while printing asm code; take their arguments in
- locations dictated by the calling conventions; preserve
- callee-save regs only. *)
+ registers; preserve all registers except ECX, EDX, XMM6 and XMM7. *)
(* Handling of annotations *)
@@ -588,21 +590,9 @@ let print_instruction oc = function
| Ptest_ri(r1, n) ->
fprintf oc " testl $%a, %a\n" coqint n ireg r1
| Pcmov(c, rd, r1) ->
- assert (c <> Cond_nep && c <> Cond_enp);
fprintf oc " cmov%s %a, %a\n" (name_of_condition c) ireg r1 ireg rd
| Psetcc(c, rd) ->
- begin match c with
- | Cond_nep ->
- fprintf oc " setne %%cl\n";
- fprintf oc " setp %%dl\n";
- fprintf oc " orb %%dl, %%cl\n"
- | Cond_enp ->
- fprintf oc " sete %%cl\n";
- fprintf oc " setnp %%dl\n";
- fprintf oc " andb %%dl, %%cl\n"
- | _ ->
- fprintf oc " set%s %%cl\n" (name_of_condition c)
- end;
+ fprintf oc " set%s %%cl\n" (name_of_condition c);
fprintf oc " movzbl %%cl, %a\n" ireg rd
(** Arithmetic operations over floats *)
| Paddd_ff(rd, r1) ->
@@ -630,18 +620,13 @@ let print_instruction oc = function
fprintf oc " jmp *%a\n" ireg r
| Pjcc(c, l) ->
let l = transl_label l in
- begin match c with
- | Cond_nep ->
- fprintf oc " jp %a\n" label l;
- fprintf oc " jne %a\n" label l
- | Cond_enp ->
- let l' = new_label() in
- fprintf oc " jp %a\n" label l';
- fprintf oc " je %a\n" label l;
- fprintf oc "%a:\n" label l'
- | _ ->
- fprintf oc " j%s %a\n" (name_of_condition c) label l
- end
+ fprintf oc " j%s %a\n" (name_of_condition c) label l
+ | Pjcc2(c1, c2, l) ->
+ let l = transl_label l in
+ let l' = new_label() in
+ fprintf oc " j%s %a\n" (name_of_neg_condition c1) label l';
+ fprintf oc " j%s %a\n" (name_of_condition c2) label l;
+ fprintf oc "%a:\n" label l'
| Pjmptbl(r, tbl) ->
let l = new_label() in
fprintf oc " jmp *%a(, %a, 4)\n" label l ireg r;