Library multi_is_even_u_triple
From mathcomp Require Import ssreflect ssrbool eqtype ssrnat seq.
Require Import ZArith_ext uniq_tac machine_int multi_int.
Import MachineInt.
Require Import mips_seplog mips_contrib mips_tactics.
Require Import multi_is_even_u_prg.
Import expr_m.
Import assert_m.
Local Open Scope machine_int_scope.
Local Open Scope heap_scope.
Local Open Scope zarith_ext_scope.
Local Open Scope uniq_scope.
Local Open Scope mips_expr_scope.
Local Open Scope mips_assert_scope.
Local Open Scope mips_cmd_scope.
Local Open Scope mips_hoare_scope.
Local Open Scope multi_int_scope.
Lemma multi_is_even_u_triple k a ret : uniq(k, a, ret, r0) ->
forall nk A va, size A = nk ->
{{ fun s h => u2Z [ k ]_s = Z_of_nat nk /\ [a]_s = va /\ (var_e a |--> A) s h }}
multi_is_even_u k a ret
{{ fun s h =>
u2Z [ k ]_s = Z_of_nat nk /\ [a]_s = va /\ (var_e a |--> A) s h /\
(Zeven (\S_{ nk } A) -> [ret]_s = one32) /\ (Zodd (\S_{ nk } A) -> [ret]_s = zero32) }}.
Proof.
move=> Hset nk A va HlenA.
rewrite /multi_is_even_u.
Require Import ZArith_ext uniq_tac machine_int multi_int.
Import MachineInt.
Require Import mips_seplog mips_contrib mips_tactics.
Require Import multi_is_even_u_prg.
Import expr_m.
Import assert_m.
Local Open Scope machine_int_scope.
Local Open Scope heap_scope.
Local Open Scope zarith_ext_scope.
Local Open Scope uniq_scope.
Local Open Scope mips_expr_scope.
Local Open Scope mips_assert_scope.
Local Open Scope mips_cmd_scope.
Local Open Scope mips_hoare_scope.
Local Open Scope multi_int_scope.
Lemma multi_is_even_u_triple k a ret : uniq(k, a, ret, r0) ->
forall nk A va, size A = nk ->
{{ fun s h => u2Z [ k ]_s = Z_of_nat nk /\ [a]_s = va /\ (var_e a |--> A) s h }}
multi_is_even_u k a ret
{{ fun s h =>
u2Z [ k ]_s = Z_of_nat nk /\ [a]_s = va /\ (var_e a |--> A) s h /\
(Zeven (\S_{ nk } A) -> [ret]_s = one32) /\ (Zodd (\S_{ nk } A) -> [ret]_s = zero32) }}.
Proof.
move=> Hset nk A va HlenA.
rewrite /multi_is_even_u.
ifte_beq k, r0 thendo
apply while.hoare_ifte.
addiu ret r0 one16
apply hoare_addiu'.
rewrite /wp_addiu => s h [[Hk [Hva Hmem]] /= Hk'].
destruct nk; last by rewrite Hk store.get_r0 Z2uK in Hk'.
repeat Reg_upd; repeat (split => //).
by Assert_upd.
move=> _; by rewrite sext_Z2u // add0i.
lw ret zero16 a
apply hoare_lw_back_alt'' with (fun s h => u2Z [k ]_ s = Z_of_nat nk /\ [a ]_ s = va /\
(var_e a |--> A) s h /\ [ret]_s = head zero32 A).
move=> [s m] h [[Hk [Hva Hpre]] Hk'].
exists (List.hd zero32 A); split.
- rewrite sext_0.
destruct A as [|hdA tlA].
+ destruct nk => //.
by rewrite /= Hk Z2uK in Hk'.
+ rewrite /= in Hpre *.
case: Hpre => h1 [h2 [Hdisj [Hunion [Hh1 Hh2]]]].
exists h1, h2; split; first by done.
split; first by done.
split; last by done.
move: Hh1; apply mapsto_ext; last by done.
by rewrite /= addi0.
- rewrite /update_store_lw; repeat Reg_upd; repeat (split; trivial).
by Assert_upd.
andi ret ret one16
apply hoare_andi with (fun s h =>
u2Z [k ]_ s = Z_of_nat nk /\ [a ]_ s = va /\ (var_e a |--> A) s h /\
(Zeven (\S_{ nk } A) -> [ret]_s = zero32) /\ (Zodd (\S_{ nk } A) -> [ret]_s = one32)).
move => sm h [Hh [Hva [mem Hret]]].
rewrite /wp_andi; repeat Reg_upd.
repeat (split; trivial).
- by Assert_upd.
- move => Hparity.
have {}Hparity : Zeven (u2Z [ret]_sm).
destruct nk => //.
+ rewrite Hret.
destruct A => //.
by rewrite Z2uK.
+ apply Zeven_lSum in Hparity => //.
by rewrite Hret -nth0.
apply int_even_and_1 in Hparity.
by rewrite zext_Z2u.
- move=> Hparity.
have {}Hparity : Zodd (u2Z [ret]_sm).
apply Zodd_lSum in Hparity.
by rewrite Hret -nth0.
apply int_odd_and_1 in Hparity.
by rewrite zext_Z2u.
xori ret ret one16
apply hoare_xori'.
move=> sm h [Hk [Ha [mem [Hpre1 Hpre2]]]].
rewrite /wp_xori; repeat Reg_upd; repeat (split; trivial).
- by Assert_upd.
- move/Hpre1 => ->; by rewrite int_xorC int_xor_0 zext_Z2u.
- move/Hpre2 => ->; by rewrite zext_Z2u // int_xor_self.
Qed.