Library pick_sign_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_contrib mips_tactics.
Import expr_m.
Import assert_m.
Require Import pick_sign_prg.
Local Open Scope mips_expr_scope.
Local Open Scope mips_assert_scope.
Local Open Scope mips_hoare_scope.
Local Open Scope uniq_scope.
Local Open Scope zarith_ext_scope.
Local Open Scope machine_int_scope.
Lemma pick_sign_triple P Q va slen a a0 a1 : uniq(a, a0, a1, r0) ->
inde (a1 :: a0 :: nil) Q -> inde (a1 :: a0 :: nil) P ->
{{ fun s h => [a ]_ s = va /\ (var_e a |~> int_e slen ** Q) s h /\
P s h}}
pick_sign a a0 a1
{{ fun s h => [a ]_ s = va /\ [a0 ]_ s = slen /\
sgZ (s2Z [a1 ]_ s) = sgZ (s2Z slen) /\
(s2Z [ a1 ]_ s = 0 \/ s2Z [ a1 ]_ s = 1 \/ s2Z [ a1 ]_s = - 1) /\
(var_e a |~> int_e slen ** Q) s h /\ P s h }}.
Proof.
move=> Hregs inde_Q inde_P.
rewrite /pick_sign.
Require Import ssrZ ZArith_ext seq_ext uniq_tac machine_int multi_int.
Import MachineInt.
Require Import mips_seplog mips_contrib mips_tactics.
Import expr_m.
Import assert_m.
Require Import pick_sign_prg.
Local Open Scope mips_expr_scope.
Local Open Scope mips_assert_scope.
Local Open Scope mips_hoare_scope.
Local Open Scope uniq_scope.
Local Open Scope zarith_ext_scope.
Local Open Scope machine_int_scope.
Lemma pick_sign_triple P Q va slen a a0 a1 : uniq(a, a0, a1, r0) ->
inde (a1 :: a0 :: nil) Q -> inde (a1 :: a0 :: nil) P ->
{{ fun s h => [a ]_ s = va /\ (var_e a |~> int_e slen ** Q) s h /\
P s h}}
pick_sign a a0 a1
{{ fun s h => [a ]_ s = va /\ [a0 ]_ s = slen /\
sgZ (s2Z [a1 ]_ s) = sgZ (s2Z slen) /\
(s2Z [ a1 ]_ s = 0 \/ s2Z [ a1 ]_ s = 1 \/ s2Z [ a1 ]_s = - 1) /\
(var_e a |~> int_e slen ** Q) s h /\ P s h }}.
Proof.
move=> Hregs inde_Q inde_P.
rewrite /pick_sign.
lw a0 zero16 a ;
apply hoare_lw_back_alt'' with (fun s h => [a ]_ s = va /\ [a0]_s = slen /\
(var_e a |~> int_e slen ** Q) s h /\ P s h).
rewrite /while.entails => s h [r_a [Hmem HP]].
exists slen; split.
- move: Hmem; apply assert_m.monotony => // h'.
apply assert_m.mapsto_ext => //=.
by rewrite sext_Z2u // addi0.
- rewrite /mips_contrib.update_store_lw.
repeat Reg_upd; repeat (split => //).
Assert_upd; apply (incl_inde _ _ _ inde_Q); by intuition.
Assert_upd; apply (incl_inde _ _ _ inde_P); by intuition.
If_beq a0,r0 Then
apply while.hoare_ifte.
addiu a1 r0 zero16
apply hoare_addiu' => s h [[a_va [a0_slen [mem HP]]]].
move/eqP/u2Z_inj => /=.
rewrite store.get_r0 => a0_0.
rewrite /wp_addiu.
repeat Reg_upd; repeat (split => //).
- rewrite add0i -a0_slen a0_0; by rewrite sext_Z2u.
- left; rewrite add0i sext_Z2u // s2Z_u2Z_pos'; by rewrite Z2uK.
- Assert_upd. apply (incl_inde _ _ _ inde_Q); by intuition.
- rewrite /inde in inde_P.
rewrite -(incl_inde _ _ _ inde_P) //.
+ by apply List.incl_refl.
+ In_tac.
srl a1 a0 (Z2u 5 31) ;
apply mips_contrib.hoare_srl with (fun s h => [a ]_ s = va /\ [a0 ]_ s = slen /\
bZsgn (u2Z [a1]_s) = sgZ (s2Z slen) /\ (var_e a |~> int_e slen ** Q) s h /\
P s h).
rewrite /while.entails => s h [[r_a [r_a0 [Hmem HP]]] a0_0].
rewrite /mips_seplog.wp_srl.
repeat Reg_upd; repeat (split => //).
- rewrite r_a0 Z2uK // (_ : '|31| = 2 ^ 5 - 1)%nat //.
apply (@bZsgn_Zsgn_s2Z 5 slen).
rewrite -r_a0.
rewrite /= in a0_0.
move/eqP : a0_0.
by rewrite store.get_r0 Z2uK.
- Assert_upd. apply (incl_inde _ _ _ inde_Q); by intuition.
- rewrite /inde in inde_P.
rewrite -(incl_inde _ _ _ inde_P) //.
+ by apply List.incl_refl.
+ In_tac.
If_beq a1,r0 Then
apply while.hoare_ifte.
addiu a1 r0 one16
apply hoare_addiu' => s h [[a_va [a0_slen [sgn_a1 [mem HP]]]] Ha1].
rewrite /wp_addiu.
repeat Reg_upd; repeat (split => //).
- rewrite add0i sext_Z2u // s2Z_u2Z_pos'; last by rewrite Z2uK.
rewrite Z2uK //=.
rewrite /= in Ha1.
move/eqP : Ha1.
by rewrite store.get_r0 Z2uK // => Ha1; rewrite Ha1 /bZsgn /= in sgn_a1.
- right; left.
by rewrite add0i sext_Z2u // s2Z_u2Z_pos' Z2uK.
- Assert_upd. apply (incl_inde _ _ _ inde_Q); by intuition.
- rewrite /inde in inde_P.
rewrite -(incl_inde _ _ _ inde_P) //.
+ by apply List.incl_refl.
+ In_tac.
addiu a1 r0 mone16
apply hoare_addiu' => s h [[a_va [a0_slen [sgn_a1 [mem HP]]]] Ha1].
rewrite /wp_addiu.
repeat Reg_upd; repeat (split => //).
- rewrite add0i sext_Z2s //.
rewrite /= in Ha1.
move/eqP : Ha1; rewrite store.get_r0 Z2uK //; move/eqP => Ha1.
by rewrite -sgn_a1 /bZsgn (negbTE Ha1) Z2sK.
- right; right.
by rewrite add0i sext_Z2s // Z2sK.
- Assert_upd. apply (incl_inde _ _ _ inde_Q); by intuition.
- rewrite /inde in inde_P.
rewrite -(incl_inde _ _ _ inde_P) //.
+ exact: List.incl_refl.
+ In_tac.
Qed.