Library mips_frame
From mathcomp Require Import ssreflect ssrbool ssrnat eqtype seq.
Require Import ZArith_ext machine_int.
Import MachineInt.
Require Import mips_seplog.
Local Close Scope positive_scope.
Local Open Scope heap_scope.
Import expr_m.
Local Open Scope mips_expr_scope.
Local Open Scope mips_cmd_scope.
Import assert_m.
Local Open Scope mips_assert_scope.
Local Open Scope mips_hoare_scope.
Require Import ZArith_ext machine_int.
Import MachineInt.
Require Import mips_seplog.
Local Close Scope positive_scope.
Local Open Scope heap_scope.
Import expr_m.
Local Open Scope mips_expr_scope.
Local Open Scope mips_cmd_scope.
Import assert_m.
Local Open Scope mips_assert_scope.
Local Open Scope mips_hoare_scope.
Definition modified_regs0 (c : cmd0) : seq store.var :=
match c with
| nop => nil
| add rd _ _ => rd :: nil
| addi rt _ _ => rt :: nil
| addiu rt _ _ => rt :: nil
| addu rd _ _ => rd :: nil
| cmd_and rd _ _ => rd :: nil
| andi rt _ _ => rt :: nil
| lw rt _ _ => rt :: nil
| lwxs rt _ _ => rt :: nil
| maddu _ _ => nil
| mflo rd => rd :: nil
| movn rd _ _ => rd :: nil
| movz rd _ _ => rd :: nil
| mfhi rd => rd :: nil
| mflhxu rd => rd :: nil
| msubu _ _ => nil
| mthi _ => nil
| mtlo _ => nil
| multu _ _ => nil
| nor rd _ _ => rd :: nil
| cmd_or rd _ _ => rd :: nil
| sll rx _ _ => rx :: nil
| sllv rd _ _ => rd :: nil
| sra rd _ _ => rd :: nil
| srl rd _ _ => rd :: nil
| srlv rd _ _ => rd :: nil
| sltu rd _ _ => rd :: nil
| sw _ _ _ => nil
| subu rd _ _ => rd :: nil
| xor rd _ _ => rd :: nil
| xori rt _ _ => rt :: nil
end.
Fixpoint modified_regs (c : @while.cmd cmd0 expr_b) : seq store.var :=
match c with
| while.cmd_cmd0 c0 => modified_regs0 c0
| while.while _ c => modified_regs c
| c1 ; c2 => modified_regs c1 ++ modified_regs c2
| while.ifte t c1 c2 => modified_regs c1 ++ modified_regs c2
end.
Lemma inde_seq R c d : inde (modified_regs (c ; d)) R ->
inde (modified_regs c) R /\ inde (modified_regs d) R.
Proof.
move=> H; split => s h x v H'; split => H''.
- rewrite -H //=; apply List.in_or_app; by left.
- rewrite (H _ _ x v) //=; apply List.in_or_app; by left.
- rewrite -H //=; apply List.in_or_app; by right.
- rewrite (H _ _ x v) //=; apply List.in_or_app; by right.
Qed.
Lemma inde_ifte R t c d : inde (modified_regs (while.ifte t c d)) R ->
inde (modified_regs c) R /\ inde (modified_regs d) R.
Proof.
move=> H; split => s h x v H'; split => H''.
- rewrite -H //=; apply: List.in_or_app; by left.
- rewrite (H _ _ x v) //=; apply: List.in_or_app; by left.
- rewrite -H //=; apply List.in_or_app; by right.
- rewrite (H _ _ x v) //=; apply List.in_or_app; by right.
Qed.
Definition modifies_mult0 (c : cmd0) :=
match c with
| nop => false
| add _ _ _ => false
| addi _ _ _ => false
| addiu _ _ _ => false
| addu _ _ _ => false
| cmd_and _ _ _ => false
| andi _ _ _ => false
| lw _ _ _ => false
| lwxs _ _ _ => false
| maddu _ _ => true
| mfhi _ => false
| mflhxu _ => true
| mflo _ => false
| movn _ _ _ => false
| movz _ _ _ => false
| msubu _ _ => true
| mtlo _ => true
| mthi _ => true
| multu _ _ => true
| nor _ _ _ => false
| cmd_or _ _ _ => false
| sll _ _ _ => false
| sllv _ _ _ => false
| sltu _ _ _ => false
| sra _ _ _ => false
| srl _ _ _ => false
| srlv _ _ _ => false
| subu _ _ _ => false
| sw _ _ _ => false
| xor _ _ _ => false
| xori _ _ _ => false
end.
Fixpoint modifies_mult (c : @while.cmd cmd0 expr_b) : bool :=
match c with
| while.cmd_cmd0 c => modifies_mult0 c
| while.while _ c' => modifies_mult c'
| c1 ; c2 => modifies_mult c1 || modifies_mult c2
| while.ifte t c1 c2 => modifies_mult c1 || modifies_mult c2
end.
an assert that is independent of the execution of a command modifying the multiplier
Definition inde_cmd_mult c (P : assert) := modifies_mult c -> inde_mult P.
Lemma inde_cmd_mult_TT : forall l, inde_cmd_mult l TT. Proof. by []. Qed.
Lemma inde_cmd_mult_seq R c d : inde_cmd_mult (c; d) R ->
inde_cmd_mult c R /\ inde_cmd_mult d R.
Proof.
move=> H; split => H' s h m m'; split => H''.
- by rewrite -(H _ _ _ m) //= H'.
- by rewrite -(H _ _ _ m') //= H'.
- by rewrite -(H _ _ _ m) //= H' orbC.
- by rewrite -(H _ _ _ m') //= H' orbC.
Qed.
Lemma inde_cmd_mult_ifte R t c d : inde_cmd_mult (while.ifte t c d) R ->
inde_cmd_mult c R /\ inde_cmd_mult d R.
Proof.
move=> H; split => H' s h m m'; split => H''.
- by rewrite -(H _ _ _ m) //= H'.
- by rewrite -(H _ _ _ m') //= H'.
- by rewrite -(H _ _ _ m) //= H' orbC.
- by rewrite -(H _ _ _ m') //= H' orbC.
Qed.
Lemma frame_rule0 (P Q : assert) (c : cmd0) : {{[ P ]}} c {{[ Q ]}} ->
forall (R : assert), inde (modified_regs c) R ->
inde_cmd_mult c R -> {{ P ** R }} c {{ Q ** R }}.
Proof.
elim; clear P Q c.
- move=> P R H1 H2; by do 2 constructor.
- move=> Q rs rt rd R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_add rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [H3 [H4 [ [H5 H7] H6] ] ] ] ].
split => //.
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
-
move=> Q rt rs imm R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_addi rt rs imm (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [ [H5 H7] H6] ] ] ] ].
split => //.
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rt rs imm R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_addiu rt rs imm (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [ H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rs rt rd R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_addu rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> P rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_and rd rs rt (P ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> P rt rs imm R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_andi rt rs imm (P ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rt offset base R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_lw rt offset base (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [H3 [H4 [ [p [H7 [z [H8 H9] ] ] ] H6] ] ] ] ].
exists p; split => //.
exists z; split => //.
rewrite H4.
by apply heap.get_union_L.
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> rt index base P0 R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_lwxs rt index base (P0 ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [H3 [H4 [ [p [H7 [z [H8 H9] ] ] ] H6] ] ] ] ].
exists p; split => //.
exists z; split => //.
rewrite H4.
by apply heap.get_union_L.
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_maddu rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by rewrite -(H2 _ s h2 m).
- move=> Q rd R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_mfhi rd (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> rd Q R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_mflhxu rd (Q ** R))); last by do 2 constructor.
move=> [s [a [hi lo]]] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
rewrite /=.
case: ifP => [/eqP ? | X].
+ rewrite -(H2 _ _ _) //; by apply H6.
+ have : List.In rd (modified_regs (mflhxu rd)) by rewrite /=; auto.
move/(H1 (s, (a, (hi, lo))) h2 rd lo).
rewrite /store.upd X => {}H1.
rewrite -(H2 _ _ _ (a, (hi, lo))) //; tauto.
- move=> Q rd R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_mflo rd (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_movn rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
split => H7.
exists h1, h2; repeat (split => //).
by apply (proj1 H5).
by apply inde_upd_store.
exists h1, h2; repeat (split => //).
by apply (proj2 H5).
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_movz rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
split => H7.
exists h1, h2; repeat (split => //).
by apply (proj1 H5).
by apply inde_upd_store.
exists h1, h2; repeat (split => //).
by apply (proj2 H5).
- move=> Q rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_msubu rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by rewrite -(H2 _ s h2 m).
- move=> Q rs R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_mthi rs (Q ** R))); last by do 2 constructor.
move=> [s [a [hi lo]]] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
rewrite /= -(H2 _ _ _) //.
by apply H6.
- move=> Q rs R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_mtlo rs (Q ** R))); last by do 2 constructor.
move=> [s [a [hi lo]]] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
rewrite /= -(H2 _ s h2) //.
by apply H6.
- move=> Q rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_multu rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by rewrite /= -(H2 _ s h2 m).
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_nor rd rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_or rd rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rx ry sa R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_sll rx ry sa (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_sllv rd rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_sltu rd rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rt sa R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_sra rd rt sa (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rt sa R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_srl rd rt sa (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rt rs R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_srlv rd rt rs (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rs rt rd R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_subu rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> rt off b Q R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_sw rt off b (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [ [p [H7 [ [z H8] H9]]] H6]]]]].
exists p; split => //.
split.
exists z.
rewrite H4.
by apply heap.get_union_L.
exists (heap.upd p [rt]_s h1), h2; split.
by apply heap.disj_upd.
split => //.
rewrite H4.
by apply heap.upd_union_L with z.
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_xor rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6]]]]].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rt rs imm R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_xori rt rs imm (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6]]]]].
exists h1, h2; repeat (split=> //).
by apply inde_upd_store.
Qed.
Lemma frame_rule_R (P : assert) c (Q : assert) : {{ P }} c {{ Q }} ->
forall (R : assert), inde (modified_regs c) R -> inde_cmd_mult c R ->
{{ P ** R }} c {{ Q ** R }}.
Proof.
elim; clear P c Q.
- exact frame_rule0.
- move=> Q P R c d H IHhoare1 H0 IHhoare2 U.
case/inde_seq => H11 H12.
case/inde_cmd_mult_seq => H21 H22.
apply (while.hoare_seq _ _ _ _ _ _ (Q ** U)); by [apply IHhoare1 | apply IHhoare2].
- move=> P P' Q Q' c H H0 H1 IHhoare R H2 H3.
move: (IHhoare _ H2 H3) => H4.
apply (hoare_prop_m.hoare_stren (P' ** R)).
move=> s h [h1 [h2 [H5 [H6 [H7 H8]]]]]; by exists h1, h2; auto.
apply (hoare_prop_m.hoare_weak (Q' ** R)) => //.
move=> s h [h1 [h2 [ H5 [H6 [H7 H8]]]]]; by exists h1, h2; auto.
- move=> P t c H IHhoare R H1 H2.
apply (hoare_prop_m.hoare_weak (fun s h => (P ** R) s h /\ ~~ eval_b t s)).
move=> s h [[h1 [h2 [H3 [H4 [H5 H6]]]]] H7]; by exists h1, h2.
apply (hoare_prop_m.hoare_stren (P ** R)) => //.
apply while.hoare_while with (P := P ** R).
move: (IHhoare _ H1 H2) => H3.
apply (hoare_prop_m.hoare_stren (fun s h => ((fun s0 h0 => P s0 h0 /\ eval_b t s) ** R) s h)) => //.
move=> s h [ [h1 [h2 [ H4 [H5 [H6 H7] ] ] ] ] H8 ]; by exists h1, h2.
- move=> P Q t c d H1 IHhoare1 H3 IHhoare2 R.
case/inde_ifte => H51 H52.
case/inde_cmd_mult_ifte => H61 H62.
apply while.hoare_ifte.
+ apply (hoare_prop_m.hoare_stren ((fun s h => P s h /\ eval_b t s) ** R)).
move=> s h [ [h1 [h2 [H8 [H9 [H10 H11] ] ] ] ] H12 ]; by exists h1, h2.
by apply IHhoare1.
+ apply (hoare_prop_m.hoare_stren ((fun s h => P s h /\ ~~ eval_b t s) ** R)).
move=> s h [ [h1 [h2 [H8 [H9 [H10 H11] ] ] ] ] H12 ]; by exists h1, h2.
by apply IHhoare2.
Qed.
Lemma frame_rule_L (P : assert) (c : while.cmd) (Q : _assert) : {{P}}c {{Q}} ->
forall R : assert, inde (modified_regs c) R ->
inde_cmd_mult c R -> {{R ** P}}c {{R ** Q}}.
Proof.
move=> P_c_Q R H1 H2.
apply (while.hoare_conseq _ _ _ _ _ _ _ (P ** R) _ (Q ** R)).
by rewrite assert_m.conCE.
by rewrite assert_m.conCE.
by apply frame_rule_R.
Qed.
Lemma before_frame R P' Q' P c Q : {{ P' ** R }} c {{ Q' ** R }} ->
P ===> P' ** R -> Q' ** R ===> Q -> {{ P }} c {{ Q }}.
Proof. move=> H1 H2 H3; by eapply while.hoare_conseq; eauto. Qed.
Lemma inde_cmd_mult_TT : forall l, inde_cmd_mult l TT. Proof. by []. Qed.
Lemma inde_cmd_mult_seq R c d : inde_cmd_mult (c; d) R ->
inde_cmd_mult c R /\ inde_cmd_mult d R.
Proof.
move=> H; split => H' s h m m'; split => H''.
- by rewrite -(H _ _ _ m) //= H'.
- by rewrite -(H _ _ _ m') //= H'.
- by rewrite -(H _ _ _ m) //= H' orbC.
- by rewrite -(H _ _ _ m') //= H' orbC.
Qed.
Lemma inde_cmd_mult_ifte R t c d : inde_cmd_mult (while.ifte t c d) R ->
inde_cmd_mult c R /\ inde_cmd_mult d R.
Proof.
move=> H; split => H' s h m m'; split => H''.
- by rewrite -(H _ _ _ m) //= H'.
- by rewrite -(H _ _ _ m') //= H'.
- by rewrite -(H _ _ _ m) //= H' orbC.
- by rewrite -(H _ _ _ m') //= H' orbC.
Qed.
Lemma frame_rule0 (P Q : assert) (c : cmd0) : {{[ P ]}} c {{[ Q ]}} ->
forall (R : assert), inde (modified_regs c) R ->
inde_cmd_mult c R -> {{ P ** R }} c {{ Q ** R }}.
Proof.
elim; clear P Q c.
- move=> P R H1 H2; by do 2 constructor.
- move=> Q rs rt rd R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_add rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [H3 [H4 [ [H5 H7] H6] ] ] ] ].
split => //.
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
-
move=> Q rt rs imm R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_addi rt rs imm (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [ [H5 H7] H6] ] ] ] ].
split => //.
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rt rs imm R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_addiu rt rs imm (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [ H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rs rt rd R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_addu rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> P rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_and rd rs rt (P ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> P rt rs imm R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_andi rt rs imm (P ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rt offset base R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_lw rt offset base (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [H3 [H4 [ [p [H7 [z [H8 H9] ] ] ] H6] ] ] ] ].
exists p; split => //.
exists z; split => //.
rewrite H4.
by apply heap.get_union_L.
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> rt index base P0 R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_lwxs rt index base (P0 ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [H3 [H4 [ [p [H7 [z [H8 H9] ] ] ] H6] ] ] ] ].
exists p; split => //.
exists z; split => //.
rewrite H4.
by apply heap.get_union_L.
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_maddu rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by rewrite -(H2 _ s h2 m).
- move=> Q rd R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_mfhi rd (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> rd Q R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_mflhxu rd (Q ** R))); last by do 2 constructor.
move=> [s [a [hi lo]]] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
rewrite /=.
case: ifP => [/eqP ? | X].
+ rewrite -(H2 _ _ _) //; by apply H6.
+ have : List.In rd (modified_regs (mflhxu rd)) by rewrite /=; auto.
move/(H1 (s, (a, (hi, lo))) h2 rd lo).
rewrite /store.upd X => {}H1.
rewrite -(H2 _ _ _ (a, (hi, lo))) //; tauto.
- move=> Q rd R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_mflo rd (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_movn rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
split => H7.
exists h1, h2; repeat (split => //).
by apply (proj1 H5).
by apply inde_upd_store.
exists h1, h2; repeat (split => //).
by apply (proj2 H5).
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_movz rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
split => H7.
exists h1, h2; repeat (split => //).
by apply (proj1 H5).
by apply inde_upd_store.
exists h1, h2; repeat (split => //).
by apply (proj2 H5).
- move=> Q rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_msubu rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by rewrite -(H2 _ s h2 m).
- move=> Q rs R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_mthi rs (Q ** R))); last by do 2 constructor.
move=> [s [a [hi lo]]] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
rewrite /= -(H2 _ _ _) //.
by apply H6.
- move=> Q rs R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_mtlo rs (Q ** R))); last by do 2 constructor.
move=> [s [a [hi lo]]] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
rewrite /= -(H2 _ s h2) //.
by apply H6.
- move=> Q rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_multu rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by rewrite /= -(H2 _ s h2 m).
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_nor rd rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_or rd rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rx ry sa R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_sll rx ry sa (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_sllv rd rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_sltu rd rs rt (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rt sa R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_sra rd rt sa (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rt sa R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_srl rd rt sa (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [ H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rd rt rs R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_srlv rd rt rs (Q ** R))); last by do 2 constructor.
move=> [s m] h [h1 [h2 [H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rs rt rd R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_subu rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [H3 [H4 [H5 H6] ] ] ] ].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> rt off b Q R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_sw rt off b (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [ [p [H7 [ [z H8] H9]]] H6]]]]].
exists p; split => //.
split.
exists z.
rewrite H4.
by apply heap.get_union_L.
exists (heap.upd p [rt]_s h1), h2; split.
by apply heap.disj_upd.
split => //.
rewrite H4.
by apply heap.upd_union_L with z.
- move=> Q rd rs rt R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_xor rd rs rt (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6]]]]].
exists h1, h2; repeat (split => //).
by apply inde_upd_store.
- move=> Q rt rs imm R H1 H2.
apply (hoare_prop_m.hoare_stren (wp_xori rt rs imm (Q ** R))); last by do 2 constructor.
move=> s h [h1 [h2 [ H3 [H4 [H5 H6]]]]].
exists h1, h2; repeat (split=> //).
by apply inde_upd_store.
Qed.
Lemma frame_rule_R (P : assert) c (Q : assert) : {{ P }} c {{ Q }} ->
forall (R : assert), inde (modified_regs c) R -> inde_cmd_mult c R ->
{{ P ** R }} c {{ Q ** R }}.
Proof.
elim; clear P c Q.
- exact frame_rule0.
- move=> Q P R c d H IHhoare1 H0 IHhoare2 U.
case/inde_seq => H11 H12.
case/inde_cmd_mult_seq => H21 H22.
apply (while.hoare_seq _ _ _ _ _ _ (Q ** U)); by [apply IHhoare1 | apply IHhoare2].
- move=> P P' Q Q' c H H0 H1 IHhoare R H2 H3.
move: (IHhoare _ H2 H3) => H4.
apply (hoare_prop_m.hoare_stren (P' ** R)).
move=> s h [h1 [h2 [H5 [H6 [H7 H8]]]]]; by exists h1, h2; auto.
apply (hoare_prop_m.hoare_weak (Q' ** R)) => //.
move=> s h [h1 [h2 [ H5 [H6 [H7 H8]]]]]; by exists h1, h2; auto.
- move=> P t c H IHhoare R H1 H2.
apply (hoare_prop_m.hoare_weak (fun s h => (P ** R) s h /\ ~~ eval_b t s)).
move=> s h [[h1 [h2 [H3 [H4 [H5 H6]]]]] H7]; by exists h1, h2.
apply (hoare_prop_m.hoare_stren (P ** R)) => //.
apply while.hoare_while with (P := P ** R).
move: (IHhoare _ H1 H2) => H3.
apply (hoare_prop_m.hoare_stren (fun s h => ((fun s0 h0 => P s0 h0 /\ eval_b t s) ** R) s h)) => //.
move=> s h [ [h1 [h2 [ H4 [H5 [H6 H7] ] ] ] ] H8 ]; by exists h1, h2.
- move=> P Q t c d H1 IHhoare1 H3 IHhoare2 R.
case/inde_ifte => H51 H52.
case/inde_cmd_mult_ifte => H61 H62.
apply while.hoare_ifte.
+ apply (hoare_prop_m.hoare_stren ((fun s h => P s h /\ eval_b t s) ** R)).
move=> s h [ [h1 [h2 [H8 [H9 [H10 H11] ] ] ] ] H12 ]; by exists h1, h2.
by apply IHhoare1.
+ apply (hoare_prop_m.hoare_stren ((fun s h => P s h /\ ~~ eval_b t s) ** R)).
move=> s h [ [h1 [h2 [H8 [H9 [H10 H11] ] ] ] ] H12 ]; by exists h1, h2.
by apply IHhoare2.
Qed.
Lemma frame_rule_L (P : assert) (c : while.cmd) (Q : _assert) : {{P}}c {{Q}} ->
forall R : assert, inde (modified_regs c) R ->
inde_cmd_mult c R -> {{R ** P}}c {{R ** Q}}.
Proof.
move=> P_c_Q R H1 H2.
apply (while.hoare_conseq _ _ _ _ _ _ _ (P ** R) _ (Q ** R)).
by rewrite assert_m.conCE.
by rewrite assert_m.conCE.
by apply frame_rule_R.
Qed.
Lemma before_frame R P' Q' P c Q : {{ P' ** R }} c {{ Q' ** R }} ->
P ===> P' ** R -> Q' ** R ===> Q -> {{ P }} c {{ Q }}.
Proof. move=> H1 H2 H3; by eapply while.hoare_conseq; eauto. Qed.