Library multi_one_s_triple
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.
Require Import ssrZ ZArith_ext seq_ext uniq_tac machine_int multi_int.
Import MachineInt.
Require Import mips_seplog mips_frame mips_tactics mips_contrib mapstos.
Import expr_m.
Import assert_m.
Require Import multi_zero_s_prg multi_zero_s_triple multi_one_s_prg.
Local Open Scope heap_scope.
Local Open Scope mips_expr_scope.
Local Open Scope mips_assert_scope.
Local Open Scope mips_hoare_scope.
Local Open Scope machine_int_scope.
Local Open Scope zarith_ext_scope.
Local Open Scope uniq_scope.
Lemma multi_zero_s'_triple_bang rx a0 a1 a2 a3 : uniq(rx, a0, a1, a2, a3, r0) ->
forall nk X vx ptr, size X = nk ->
u2Z vx + 4 * 2 < \B^1 ->
u2Z ptr + 4 * Z_of_nat nk < \B^1 ->
{{ !(fun s => [ rx ]_s = vx) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil ** int_e ptr |--> X }}
multi_zero_s' rx a0 a1 a2 a3
{{ !(fun s => [ rx ]_s = vx) ** !(fun s => [ a0 ]_s = Z2u 32 (Z_of_nat nk)) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil ** int_e ptr |--> nseq nk zero32 }}.
Proof.
move=> Hregs nk X vx ptr X_nk vx_fit ptr_fit.
eapply while.hoare_conseq; last first.
have : uniq(rx, a0, a1, a2, a3, r0) by Uniq_uniq r0.
move/multi_zero_s'_triple.
move/(_ nk X vx ptr X_nk vx_fit ptr_fit)=> hoare_triple.
exact: hoare_triple.
move=> s h H.
apply con_and_bang_inv_L in H.
by case: H.
move=> s h [Hrx [Ha0 H]].
apply con_and_bang_L => //; exact: con_and_bang_L.
Qed.
Lemma multi_one_s_triple_bang rx rk a0 a1 a2 a3 : uniq(rx, rk, a0, a1, a2, a3, r0) ->
forall nk X vx ptr, 0 < Z_of_nat nk < 2 ^^ 31 -> size X = nk ->
u2Z vx + 4 * 2 < \B^1 ->
u2Z ptr + 4 * Z_of_nat nk < \B^1 ->
forall slen, s2Z slen = sgZ (s2Z slen) * Z_of_nat nk ->
{{ !(fun s => [ rx ]_ s = vx) **
!(fun s => u2Z [ rk ]_s = Z_of_nat nk) **
var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> X}}
multi_one_s rx rk a0 a1 a2 a3
{{ !(fun s => [ rx ]_ s = vx) **
!(fun s => u2Z [ rk ]_s = Z_of_nat nk) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil ** int_e ptr |--> one32 :: nseq (nk - 1) zero32 }}.
Proof.
move=> Hnodup nk X vx ptr Hnk X_nk vx_fit ptr_fit slen Hslen.
rewrite /multi_one_s.
Require Import ssrZ ZArith_ext seq_ext uniq_tac machine_int multi_int.
Import MachineInt.
Require Import mips_seplog mips_frame mips_tactics mips_contrib mapstos.
Import expr_m.
Import assert_m.
Require Import multi_zero_s_prg multi_zero_s_triple multi_one_s_prg.
Local Open Scope heap_scope.
Local Open Scope mips_expr_scope.
Local Open Scope mips_assert_scope.
Local Open Scope mips_hoare_scope.
Local Open Scope machine_int_scope.
Local Open Scope zarith_ext_scope.
Local Open Scope uniq_scope.
Lemma multi_zero_s'_triple_bang rx a0 a1 a2 a3 : uniq(rx, a0, a1, a2, a3, r0) ->
forall nk X vx ptr, size X = nk ->
u2Z vx + 4 * 2 < \B^1 ->
u2Z ptr + 4 * Z_of_nat nk < \B^1 ->
{{ !(fun s => [ rx ]_s = vx) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil ** int_e ptr |--> X }}
multi_zero_s' rx a0 a1 a2 a3
{{ !(fun s => [ rx ]_s = vx) ** !(fun s => [ a0 ]_s = Z2u 32 (Z_of_nat nk)) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil ** int_e ptr |--> nseq nk zero32 }}.
Proof.
move=> Hregs nk X vx ptr X_nk vx_fit ptr_fit.
eapply while.hoare_conseq; last first.
have : uniq(rx, a0, a1, a2, a3, r0) by Uniq_uniq r0.
move/multi_zero_s'_triple.
move/(_ nk X vx ptr X_nk vx_fit ptr_fit)=> hoare_triple.
exact: hoare_triple.
move=> s h H.
apply con_and_bang_inv_L in H.
by case: H.
move=> s h [Hrx [Ha0 H]].
apply con_and_bang_L => //; exact: con_and_bang_L.
Qed.
Lemma multi_one_s_triple_bang rx rk a0 a1 a2 a3 : uniq(rx, rk, a0, a1, a2, a3, r0) ->
forall nk X vx ptr, 0 < Z_of_nat nk < 2 ^^ 31 -> size X = nk ->
u2Z vx + 4 * 2 < \B^1 ->
u2Z ptr + 4 * Z_of_nat nk < \B^1 ->
forall slen, s2Z slen = sgZ (s2Z slen) * Z_of_nat nk ->
{{ !(fun s => [ rx ]_ s = vx) **
!(fun s => u2Z [ rk ]_s = Z_of_nat nk) **
var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> X}}
multi_one_s rx rk a0 a1 a2 a3
{{ !(fun s => [ rx ]_ s = vx) **
!(fun s => u2Z [ rk ]_s = Z_of_nat nk) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil ** int_e ptr |--> one32 :: nseq (nk - 1) zero32 }}.
Proof.
move=> Hnodup nk X vx ptr Hnk X_nk vx_fit ptr_fit slen Hslen.
rewrite /multi_one_s.
lw a0 zero16 rx
apply mips_contrib.hoare_lw_back_alt'' with (
!(fun s => [rx ]_ s = vx) **
!(fun s => u2Z [ rk ]_s = Z_of_nat nk) **
var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> X **
!(fun s => [ a0 ]_ s = slen)).
move=> s h Hmem.
exists slen; split.
move: Hmem.
rewrite !assert_m.conAE.
do 2 rewrite assert_m.conCE !assert_m.conAE.
apply monotony => // h1.
apply mapsto_ext => //.
by rewrite /= sext_Z2u // addi0.
rewrite [assert_m.mapstos]lock -!assert_m.conAE -lock.
apply con_and_bang_R.
apply inde_upd_store => //.
by rewrite /bang; Inde.
by rewrite [assert_m.mapstos]lock !assert_m.conAE -lock.
by Reg_upd.
ifte_beq a0, r0 thendo
apply while.hoare_seq with (!(fun s => [rx ]_ s = vx) **
!(fun s => u2Z [rk ]_ s = Z_of_nat nk) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil ** int_e ptr |--> X).
apply hoare_ifte_bang.
- apply hoare_sw_back' => s h H.
exists (int_e slen).
rewrite -mapsto2_mapstos in H.
do 4 rewrite assert_m.conCE !assert_m.conAE in H.
move: H; apply monotony => h1 //.
apply mapsto_ext => //=.
by rewrite sext_Z2u // addi0.
apply currying => {}h1 H.
rewrite !assert_m.conAE in H.
do 5 rewrite assert_m.conCE !assert_m.conAE in H.
rewrite -mapsto2_mapstos.
do 1 rewrite assert_m.conCE !assert_m.conAE.
move: H.
apply con_bang_L_pull_out => rk_nk H.
move: H; apply monotony => // h2.
apply mapsto_ext => //.
by rewrite /= sext_Z2u // addi0.
by rewrite /= -rk_nk Z2u_u2Z.
apply monotony => // h3.
apply monotony => // h4 H.
rewrite -assert_m.conAE in H.
rewrite con_bangE in H.
by apply con_and_bang_inv_L in H; case: H.
ifte_bltz a0 thendo
apply hoare_ifte_bang.
- set pre := _ ** _.
apply mips_seplog.hoare_prop_m.hoare_stren with (fun s h => s2Z slen < 0 /\ pre s h).
move=> s h H /=.
split; last by [].
rewrite /pre {pre} in H.
rewrite [assert_m.mapstos]lock -!assert_m.conAE -lock in H.
apply con_and_bang_inv_R in H; case: H => H /=.
move/ltZP => Ha0.
apply con_and_bang_inv_R in H; case: H => H _.
apply con_and_bang_inv_R in H; case: H => _ H.
by subst slen.
apply (hoare_prop_m.pull_out_conjunction' hoare0_false) => slen_neq.
rewrite /pre.
move/Zsgn_neg in slen_neq.
have <- : cplt2 slen = Z2u 32 (Z_of_nat nk).
apply s2Z_inj.
rewrite [X in _ = X]s2Z_u2Z_pos'; last first.
rewrite Z2uK //; clear -Hnk; simpl in *; lia.
rewrite Z2uK; last by clear -Hnk; simpl in *; lia.
rewrite s2Z_cplt2; last first.
move/weirdE2; rewrite Hslen slen_neq mulN1Z eqZ_opp.
move=> /ltZ_eqF; apply; by case: Hnk.
rewrite Hslen slen_neq mulN1Z; ring.
have : uniq(rx, a0, r0) by Uniq_uniq r0.
move/(multi_negate_triple.multi_negate_triple rx a0 slen ptr X) => Htmp.
apply hoare_prop_m.hoare_stren with (
(var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> X) **
(!(fun s : store.t => [rx ]_ s = vx) **
!(fun s : store.t => u2Z [rk ]_ s = Z_of_nat nk))).
move=> s h.
rewrite [mapstos]lock.
rewrite !assert_m.conAE.
do 2 rewrite assert_m.conCE !assert_m.conAE.
apply monotony => // h1.
apply monotony => // h2.
do 3 rewrite assert_m.conCE !assert_m.conAE.
apply monotony => // h3.
rewrite con_bangE.
rewrite con_bangE.
by move/con_bang_L.
rewrite [mapstos]lock.
do 2 rewrite [X in WMIPS_Hoare.hoare _ _ X]assert_m.conCE ![X in WMIPS_Hoare.hoare _ _ X]assert_m.conAE.
rewrite -[X in WMIPS_Hoare.hoare _ _ X]assert_m.conAE.
rewrite -lock.
apply frame_rule_R.
by [].
rewrite [modified_regs _]/=; rewrite /bang; by Inde.
rewrite /bang; by Inde.
nop
apply hoare_nop' => s h H.
rewrite [assert_m.mapstos]lock in H.
rewrite assert_m.conCE !assert_m.conAE in H.
apply con_and_bang_inv_L in H; case: H => H1 H.
do 4 rewrite assert_m.conCE !assert_m.conAE in H.
apply con_and_bang_inv_L in H; case: H => H H2.
apply con_and_bang_inv_L in H2; case: H2 => H2 H3.
rewrite -lock in H3.
suff : slen = Z2u 32 (Z_of_nat nk) by move=> <-.
apply s2Z_inj.
rewrite Hslen.
move/ltZP in H1.
move/eqP in H2.
rewrite store.get_r0 Z2uK // in H2.
have {H2} {}H1 : 0 < s2Z slen.
have {}H2 : s2Z [ a0 ]_ s <> 0.
contradict H2.
rewrite (_ : 0 = s2Z (Z2u 32 0)) in H2; last by rewrite s2Z_u2Z_pos' // Z2uK.
by rewrite (s2Z_inj H2) Z2uK.
subst slen; lia.
move/Zsgn_pos in H1.
rewrite H1 s2Z_u2Z_pos'; last first.
rewrite Z2uK //; clear -Hnk; simpl in *; lia.
rewrite Z2uK //; last by clear -Hnk; simpl in *; lia.
ring.
multi_zero_signed' rx rk a1 a2 a3 ;
apply while.hoare_seq with (!(fun s => [rx ]_ s = vx) **
!(fun s => [ rk ]_ s = Z2u 32 (Z_of_nat nk)) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil **
int_e ptr |--> nseq nk zero32).
apply hoare_prop_m.hoare_stren with (
!(fun s => [rk ]_ s = Z2u 32 (Z_of_nat nk)) **
!(fun s => [rx ]_ s = vx) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil **
int_e ptr |--> X).
move=> s h H.
rewrite [mapstos]lock.
do 1 rewrite assert_m.conCE !assert_m.conAE.
rewrite -lock.
move: H; apply monotony => // {}h H.
rewrite [mapstos]lock.
do 2 rewrite assert_m.conCE !assert_m.conAE.
rewrite -lock.
move: H; apply monotony => // {}h.
apply bangify => <-.
by rewrite Z2u_u2Z.
apply hoare_prop_m.hoare_weak with (
!(fun s => [rk ]_ s = Z2u 32 (Z_of_nat nk)) **
!(fun s => [rx ]_ s = vx) **
!(fun s => [a0 ]_ s = Z2u 32 (Z_of_nat nk)) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil **
int_e ptr |--> nseq nk zero32).
move=> s h H.
rewrite [mapstos]lock in H.
do 2 rewrite assert_m.conCE !assert_m.conAE in H.
rewrite -lock in H.
apply con_and_bang_inv_L in H; case: H => _ H.
rewrite [mapstos]lock.
do 2 rewrite assert_m.conCE !assert_m.conAE.
rewrite -lock.
move: H; apply monotony => {}h //.
apply monotony => {}h //.
by rewrite assert_m.conCE.
apply frame_rule_L; last 2 first.
rewrite [modified_regs _]/=; rewrite /bang; by Inde.
rewrite /bang; by Inde.
apply multi_zero_s'_triple_bang => //.
by Uniq_uniq r0.
lw a0 four16 rx;
apply mips_contrib.hoare_lw_back_alt'' with
(!(fun s => [rx ]_ s = vx) **
!(fun s => [rk ]_ s = Z2u 32 (Z_of_nat nk)) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil **
int_e ptr |--> nseq nk zero32 **
!(fun s => [ a0 ]_s = ptr)).
move=> s h H.
exists ptr; split.
rewrite -mapsto2_mapstos in H.
do 3 rewrite assert_m.conCE 3!assert_m.conAE in H.
move: H; apply monotony => // {}h.
by rewrite sext_Z2u.
rewrite /update_store_lw.
rewrite -mapsto2_mapstos.
rewrite -!assert_m.conAE.
apply con_and_bang_R; last by Reg_upd.
apply inde_upd_store.
rewrite /bang; by Inde.
rewrite !assert_m.conAE.
rewrite -mapsto2_mapstos in H.
rewrite !assert_m.conAE in H.
by [].
addiu a1 r0 one16;
apply hoare_addiu with (
!(fun s => [rx ]_ s = vx) **
!(fun s => [rk ]_ s = Z2u 32 (Z_of_nat nk)) **
var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil **
int_e ptr |--> nseq nk zero32 ** !(fun s : store.t => [a0 ]_ s = ptr) **
!(fun s => [ a1 ]_s = one32)).
move=> s h H.
rewrite /wp_addiu -mapsto2_mapstos -!assert_m.conAE.
apply con_and_bang_R; last first.
Reg_upd.
by rewrite store.get_r0 add0i sext_Z2u.
apply inde_upd_store => //.
rewrite /bang; by Inde.
rewrite !assert_m.conAE.
by rewrite -mapsto2_mapstos !assert_m.conAE in H.
sw a1 zero16 a0
apply hoare_sw_back' => s h H.
exists (int_e zero32).
rewrite sext_Z2u //.
destruct nk.
by case: Hnk.
rewrite subn1.
rewrite [nseq (S nk) zero32]/= in H.
have a0_ptr : [a0]_s = ptr.
do 4 rewrite assert_m.conCE 3!assert_m.conAE in H.
apply con_and_bang_inv_L in H.
tauto.
rewrite -mapsto2_mapstos [_ |--> _]/= in H.
do 4 rewrite assert_m.conCE 4!assert_m.conAE in H.
move: H; apply monotony => // {}h.
apply mapsto_ext => //=.
by rewrite addi0.
apply currying => {}h H.
rewrite !assert_m.conAE in H.
rewrite -mapsto2_mapstos [_ |--> _]/=.
rewrite -!assert_m.conAE.
do 1 rewrite assert_m.conCE !assert_m.conAE.
move: H; apply monotony => {}h // H.
do 4 rewrite assert_m.conCE !assert_m.conAE in H.
do 2 rewrite assert_m.conCE !assert_m.conAE.
move: H; apply monotony => {}h // H.
move: H; apply monotony => {}h // H.
do 2 rewrite assert_m.conCE !assert_m.conAE in H.
apply con_and_bang_inv_L in H.
case: H => H' H.
do 2 rewrite assert_m.conCE !assert_m.conAE in H.
move: H; apply monotony => {}h //.
apply mapsto_ext => //.
by rewrite /= addi0.
move=> H.
apply con_and_bang_inv_L in H.
case: H => H'' H.
move: H.
apply monotony=> // h3.
apply bangify => ->.
rewrite Z2uK //.
clear -Hnk; simpl in *; lia.
Qed.
Lemma multi_one_s_triple rx rk a0 a1 a2 a3 : uniq(rx, rk, a0, a1, a2, a3, r0) ->
forall nk X vx ptr, 0 < Z_of_nat nk < 2 ^^ 31 -> size X = nk ->
u2Z vx + 4 * 2 < \B^1 ->
u2Z ptr + 4 * Z_of_nat nk < \B^1 ->
forall slen, s2Z slen = sgZ (s2Z slen) * Z_of_nat nk ->
{{ fun s h => [ rx ]_s = vx /\ u2Z [ rk ]_s = Z_of_nat nk /\
(var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> X) s h }}
multi_one_s rx rk a0 a1 a2 a3
{{ fun s h => [ rx ]_s = vx /\ u2Z [ rk ]_s = Z_of_nat nk /\
(var_e rx |--> Z2u 32 (Z_of_nat nk) :: ptr :: nil **
int_e ptr |--> one32 :: nseq (nk - 1) zero32) s h }}.
Proof.
move=> Hnodup nk X vx ptr Hnk X_nk vx_fit ptr_fit slen slen_nk.
move: (multi_one_s_triple_bang _ _ _ _ _ _ Hnodup _ _ _ _ Hnk X_nk vx_fit ptr_fit _ slen_nk) => Htmp.
eapply while.hoare_conseq; last exact: Htmp.
move=> s h H.
apply con_and_bang_inv_L in H; case: H => Hrx H.
split; first by [].
apply con_and_bang_inv_L in H; case: H => Hrk H.
by [].
move=> s h [Hrx [Hrk H]].
apply con_and_bang_L => //.
exact/con_and_bang_L.
Qed.