Library multi_add_s_u_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_contrib mips_tactics mips_mint.
Import expr_m.
Import assert_m.
Require Import multi_add_s_u_prg pick_sign_prg copy_u_u_prg multi_add_u_u_prg.
Require Import multi_lt_prg multi_sub_u_u_prg multi_negate_prg multi_is_zero_u_prg.
Require Import pick_sign_triple multi_add_u_u_triple.
Require Import multi_lt_triple multi_sub_u_u_R_triple.
Require Import multi_sub_u_u_L_triple multi_negate_triple.
Require Import multi_is_zero_u_triple copy_u_u_triple.
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.
Local Open Scope multi_int_scope.
Lemma multi_add_s_u'_triple rk rx ry a0 a1 a2 a3 a4 a5 rX :
uniq(rk, rx, ry, a0, a1, a2, a3, a4, a5, rX, r0) ->
forall k vx vy ptr, k <> O -> Z_of_nat k < 2 ^^ 31 ->
u2Z ptr + 4 * Z_of_nat k < \B^1 ->
forall X Y, size X = k -> size Y = k -> 0 < \S_{ k } Y ->
forall slen, s2Z slen = sgZ (s2Z slen) * Z_of_nat k ->
{{ fun s h => [ rx ]_s = vx /\ [ ry ]_s = vy /\ u2Z [ rk ]_s = Z_of_nat k /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> X) ** var_e ry |--> Y) s h }}
multi_add_s_u0 rk rx ry a0 a1 a2 a3 a4 a5 rX
{{ fun s h => exists X' slen', size X' = k /\
[ rx ]_s = vx /\ [ ry ]_s = vy /\ s2Z slen' = sgZ (s2Z slen') * Z_of_nat k /\
sgZ (s2Z slen') = sgZ (sgZ (s2Z slen) * \S_{ k } X + \S_{ k } Y) /\
((var_e rx |--> slen' :: ptr :: nil ** int_e ptr |--> X') ** var_e ry |--> Y) s h /\
u2Z ([a3]_ s) <= 1 /\
sgZ (s2Z slen') * (\S_{ k } X' + u2Z ([a3]_ s) * \B^k) =
sgZ (s2Z slen) * \S_{ k } X + \S_{ k } Y }}.
Proof.
move=> Hregs nk va vb ptr Hnk Hnk' ptr_fit A B len_A len_B nk_B slen slen_no_weird.
rewrite /multi_add_s_u0.
Require Import ssrZ ZArith_ext seq_ext uniq_tac machine_int multi_int.
Import MachineInt.
Require Import mips_seplog mips_frame mips_contrib mips_tactics mips_mint.
Import expr_m.
Import assert_m.
Require Import multi_add_s_u_prg pick_sign_prg copy_u_u_prg multi_add_u_u_prg.
Require Import multi_lt_prg multi_sub_u_u_prg multi_negate_prg multi_is_zero_u_prg.
Require Import pick_sign_triple multi_add_u_u_triple.
Require Import multi_lt_triple multi_sub_u_u_R_triple.
Require Import multi_sub_u_u_L_triple multi_negate_triple.
Require Import multi_is_zero_u_triple copy_u_u_triple.
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.
Local Open Scope multi_int_scope.
Lemma multi_add_s_u'_triple rk rx ry a0 a1 a2 a3 a4 a5 rX :
uniq(rk, rx, ry, a0, a1, a2, a3, a4, a5, rX, r0) ->
forall k vx vy ptr, k <> O -> Z_of_nat k < 2 ^^ 31 ->
u2Z ptr + 4 * Z_of_nat k < \B^1 ->
forall X Y, size X = k -> size Y = k -> 0 < \S_{ k } Y ->
forall slen, s2Z slen = sgZ (s2Z slen) * Z_of_nat k ->
{{ fun s h => [ rx ]_s = vx /\ [ ry ]_s = vy /\ u2Z [ rk ]_s = Z_of_nat k /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> X) ** var_e ry |--> Y) s h }}
multi_add_s_u0 rk rx ry a0 a1 a2 a3 a4 a5 rX
{{ fun s h => exists X' slen', size X' = k /\
[ rx ]_s = vx /\ [ ry ]_s = vy /\ s2Z slen' = sgZ (s2Z slen') * Z_of_nat k /\
sgZ (s2Z slen') = sgZ (sgZ (s2Z slen) * \S_{ k } X + \S_{ k } Y) /\
((var_e rx |--> slen' :: ptr :: nil ** int_e ptr |--> X') ** var_e ry |--> Y) s h /\
u2Z ([a3]_ s) <= 1 /\
sgZ (s2Z slen') * (\S_{ k } X' + u2Z ([a3]_ s) * \B^k) =
sgZ (s2Z slen) * \S_{ k } X + \S_{ k } Y }}.
Proof.
move=> Hregs nk va vb ptr Hnk Hnk' ptr_fit A B len_A len_B nk_B slen slen_no_weird.
rewrite /multi_add_s_u0.
lw rX four16 rx
apply hoare_lw_back_alt'' with (fun s h => [ rx ]_ s = va /\ [ ry ]_ s = vb /\
u2Z ([ rk ]_ s) = Z_of_nat nk /\ [ rX ]_s = ptr /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A) ** var_e ry |--> B) s h).
rewrite /while.entails => s h [r_a [r_b [r_k Hmem]]].
exists ptr; split.
- rewrite conCE !conAE conCE !conAE
conCE !conAE in Hmem.
move: Hmem; apply monotony => // h'; apply mapsto_ext => //; by rewrite sext_Z2u.
- rewrite /update_store_lw.
repeat Reg_upd; repeat (split => //).
by Assert_upd.
pick_sign rx a0 a1
apply while.hoare_seq with (fun s h => [ rx ]_ s = va /\ [ ry ]_ s = vb /\
u2Z ([ rk ]_ s) = Z_of_nat nk /\ [ rX ]_s = ptr /\ [a0]_s = slen /\
sgZ (s2Z [a1]_s) = sgZ (s2Z slen) /\ (s2Z [a1]_s = 0 \/ s2Z [a1]_s = 1 \/ s2Z [a1]_s = -1 ) /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A) ** var_e ry |--> B) s h).
eapply while.hoare_conseq; last first.
apply (pick_sign_triple
(fun s h => [ ry ]_ s = vb /\ u2Z [ rk ]_ s = Z_of_nat nk /\ [ rX ]_ s = ptr)
(((var_e rx \+ int_e four32 |~> int_e ptr ** (fun st h0 =>
u2Z (([ rx ]_ st `+ four32) `+ four32) mod 4 = 0 /\
emp st h0)) ** int_e ptr |--> A) ** var_e ry |--> B) va slen).
by Uniq_uniq r0.
Inde.
move=> s h x v /= [].
move=> ?; subst a1; by Reg_upd.
case=> // ?; subst a0; by Reg_upd.
by Inde.
move=> s h /= [Ha [Hb [Hk [HX Hmem]]]].
by rewrite !conAE in Hmem *.
move=> s h /= [Ha [Ha0 [Ha1 [Ha1' [Hmem [Hb [Hk HX]]]]]]].
by rewrite !conAE in Hmem *.
If_bgez a1 Then
apply while.hoare_ifte.
If_beq a1, r0 Then
apply while.hoare_ifte.
apply while.hoare_seq with (fun s h => [ rx ]_ s = va /\ [ ry ]_ s = vb /\
u2Z [ rk ]_ s = Z_of_nat nk /\ [ rX ]_ s = ptr /\ [a0 ]_ s = slen /\
sgZ (s2Z slen) = 0 /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> B) ** var_e ry |--> B) s h).
copy_u_u rk rX ry a2 a3 a4
apply (before_frame
(fun s h => [ rx ]_ s = va /\ [ ry ]_ s = vb /\ [a0 ]_ s = slen /\
sgZ (s2Z slen) = 0 /\ (var_e rx |--> slen :: ptr :: nil) s h)
(fun s h => [ rX ]_s = ptr /\ u2Z [ rk ]_s = Z_of_nat nk /\
(var_e ry |--> B ** var_e rX |--> A) s h)
(fun s h => [ rX ]_s = ptr /\ u2Z [ rk ]_s = Z_of_nat nk /\
(var_e ry |--> B ** var_e rX |--> B) s h)).
apply frame_rule_R; last 2 first.
by Inde_frame.
move=> ?; by Inde_mult.
apply copy_u_u_triple => //; by Uniq_uniq r0.
move=> s h [ [[Ha [Hb [Hk [HX [Ha0 [a1_slen [Ha1' mem]]]]]]] _] Ha1].
rewrite conAE in mem.
case: mem => h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]].
exists h2, h1.
split; first by heap_tac_m.Disj.
split; first by heap_tac_m.Equal.
repeat (split => //).
rewrite conCE.
move: Hh2; apply monotony => // h'; exact: mapstos_ext.
rewrite /= in Ha1.
move/eqP/u2Z_inj in Ha1.
rewrite store.get_r0 in Ha1.
by rewrite -a1_slen Ha1 s2Z_u2Z_pos' // Z2uK.
move=> s h [h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]]].
case: Hh2 => [Ha [Hb [Ha0 [Ha1' Hh2]]]].
case: Hh1 => Hx [Hk Hh1].
repeat (split => //).
rewrite conAE.
exists h2, h1.
split; first by heap_tac_m.Disj.
split; first by heap_tac_m.Equal.
repeat (split => //).
rewrite conCE.
move: Hh1; apply monotony => h' //; exact: mapstos_ext.
addiu a3 r0 zero16
apply hoare_addiu with (fun s h =>
[ rx ]_ s = va /\ [ ry ]_ s = vb /\ u2Z [ rk ]_ s = Z_of_nat nk /\
[ rX ]_ s = ptr /\ [a0 ]_ s = slen /\ [a3]_s = zero32 /\
sgZ (s2Z slen) = 0 /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> B) ** var_e ry |--> B) s h).
move=> s h [Ha [Hb [Hk [HX [Ha0 [Ha1 mem]]]]]].
rewrite /wp_addiu.
repeat Reg_upd; repeat (split => //).
by rewrite add0i sext_Z2u.
by Assert_upd.
sw rk zero16 a
apply hoare_sw_back'.
move=> s h [Ha [Hb [Hk [HX [Ha0 [Ha3 [Hslen mem]]]]]]].
exists (int_e slen).
rewrite !conAE /= in mem.
move: mem; apply monotony => // h'.
apply mapsto_ext => //; by rewrite /= sext_Z2u // addi0.
apply currying => h'' Hh''.
exists B, (Z2s 32 (Z_of_nat nk)).
repeat (split => //).
rewrite Z2sK //; last lia.
rewrite (proj2 (Zsgn_pos (Z_of_nat nk))); lia.
rewrite Z2sK //; last lia.
rewrite Hslen /= (proj2 (Zsgn_pos (Z_of_nat nk))); last lia.
by rewrite (proj2 (Zsgn_pos (\S_{ nk } B))).
rewrite conCE in Hh''.
rewrite /= !conAE.
move: Hh''; apply monotony => // h'''.
apply mapsto_ext => /=.
by rewrite sext_Z2u // addi0.
apply u2Z_inj.
rewrite Hk u2Z_Z2s_pos //.
split; by [lia | apply: @ltZ_leZ_trans; [exact: Hnk' | ]].
by rewrite Ha3 Z2uK.
rewrite Z2sK //; last lia.
rewrite (proj2 (Zsgn_pos (Z_of_nat nk))); last lia.
by rewrite mul1Z Hslen /= Ha3 Z2uK // mul0Z addZ0.
addiu a3 r0 one16;
apply hoare_addiu with (fun s h => [ rx ]_ s = va /\ [ ry ]_ s = vb /\ u2Z [ rk ]_ s = Z_of_nat nk /\
[ rX ]_ s = ptr /\ [a0 ]_ s = slen /\ sgZ (s2Z [a1 ]_ s) = sgZ (s2Z slen) /\
s2Z [a1]_s = 1 /\ [a3]_s = one32 /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A) ** var_e ry |--> B) s h).
rewrite /wp_addiu => s h [[[Ha [Hb [Hk [HX [Ha0 [Ha1 [Ha1'' mem]]]]]]] Ha1'''] Ha1'].
repeat Reg_upd.
rewrite /= in Ha1' Ha1'''.
move/leZP in Ha1'''.
rewrite store.get_r0 Z2uK // in Ha1'.
move/eqP in Ha1'.
repeat (split => //).
case: Ha1'' => [Ha1'' | [ // | Ha1'']].
rewrite (_ : 0 = s2Z zero32) in Ha1''; last by rewrite s2Z_u2Z_pos' Z2uK.
move/s2Z_inj in Ha1''.
by rewrite Ha1'' Z2uK in Ha1'.
lia.
by rewrite add0i sext_Z2u.
by Assert_upd.
multi_add_u_u rk a3 ry rX rX a0 a1 a2
apply while.hoare_seq with (fun s h => exists A' slen', size A' = nk /\
[ rx ]_ s = va /\ [ ry ]_ s = vb /\ s2Z slen' = sgZ (s2Z slen') * Z_of_nat nk /\
((var_e rx |--> slen' :: ptr :: nil ** int_e ptr |--> A') ** var_e ry |--> B) s h /\
u2Z (store.lo s) <= 1 /\
sgZ (s2Z slen') = sgZ (sgZ (s2Z slen) * \S_{ nk } A + \S_{ nk } B) /\
sgZ (s2Z slen') * (\S_{ nk } A' + u2Z (store.lo s) * \B^nk) =
sgZ (s2Z slen) * \S_{ nk } A + \S_{ nk } B).
have : uniq(rk, a3, ry, rX, a0, a1, a2, r0) by Uniq_uniq r0.
move/multi_add_u_u_triple.
move/(_ nk vb ptr ptr_fit _ _ len_B len_A) => Htmp.
apply (before_frame
(fun s h => sgZ (s2Z slen) = 1 /\ [ rx ]_ s = va /\ (var_e rx |--> slen :: ptr :: nil) s h)
(fun s h =>
([a3]_s = one32 /\ [ ry ]_ s = vb /\ [ rX ]_ s = ptr /\ u2Z ([ rk ]_ s) = Z_of_nat nk /\
(var_e rX |--> A ** var_e ry |--> B) s h) /\
[ rx ]_ s = va /\ [a0 ]_ s = slen /\ 0 <= sgZ (s2Z slen) /\ eval_b (bgez a1) s)
(fun s h => exists A',
size A' = nk /\ [ ry ]_s = vb /\ [ rX ]_ s = ptr /\ (var_e ry |--> B ** var_e rX |--> A') s h /\
u2Z (store.lo s) <= 1 /\ \S_{ nk } A' + u2Z (store.lo s) * \B^nk = \S_{ nk } A + \S_{ nk } B)).
apply frame_rule_R; last 2 first.
by Inde_frame.
move=> ?; by Inde_mult.
eapply while.hoare_conseq; last exact: Htmp.
by rewrite addZC.
rewrite /while.entails => s h [[Hone [Hb [HX [Hk Hmem]]]] [Ha [Ha0 [HZsgn Ha1]]]].
move/leZP in Ha1.
by rewrite conCE in Hmem.
rewrite /while.entails => s h [Ha [Hb [Hk [HX [Ha0 [Hsgn [Hsgn' [Ha3 Hmem]]]]]]]].
rewrite conAE in Hmem.
case: Hmem => h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]].
exists h2, h1.
split; first by heap_tac_m.Disj.
split; first by heap_tac_m.Equal.
repeat (split => //).
move: Hh2; apply monotony => h' //; exact: mapstos_ext.
rewrite -Hsgn; by rewrite Hsgn'.
rewrite /=; apply/leZP; lia.
by rewrite -Hsgn Hsgn'.
rewrite /while.entails => s h [h1 [h2 [h1_d_h2 [h1_U_h2 [[A' [A'_nk [r_b [HX [Hh1 [Hlo Hsum]]]]]] [Hsgn [r_a Hh2]]]]]]].
exists A', slen.
repeat (split => //).
rewrite conAE.
exists h2, h1.
split; first by heap_tac_m.Disj.
split; first by heap_tac_m.Equal.
split; first by [].
rewrite conCE.
move: Hh1; apply monotony => h' //; exact: mapstos_ext.
rewrite Hsgn mul1Z (proj2 (Zsgn_pos (\S_{ nk } A + \S_{ nk } B))) //.
move: (min_lSum nk A) => ?; lia.
by rewrite Hsgn 2!mul1Z.
mflo a3
apply hoare_mflo'.
rewrite /while.entails => s h [A' [slen' [len_A' [r_a [r_b [slen'_nk [Hmem [Hlo [Hsgn Hsum]]]]]]]]].
rewrite /wp_mflo.
exists A', slen'.
repeat Reg_upd; repeat (split => //).
move: Hmem; apply inde_upd_store; by Inde.
multi_lt rk ry rX a0 a1 a5 a2 a3 a4 ;
apply while.hoare_seq with (fun s h =>
([ rx ]_ s = va /\ [ ry ]_ s = vb /\ u2Z ([ rk ]_ s) = Z_of_nat nk /\
[ rX ]_ s = ptr /\ sgZ (s2Z slen) = -1 /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A) ** var_e ry |--> B) s h) /\
((\S_{ nk } B < \S_{ nk } A /\ [a5]_s = one32 /\ [a2]_s = zero32 ) \/
(\S_{ nk } B > \S_{ nk } A /\ [a5]_s = zero32 /\ [a2]_s = one32 ) \/
(\S_{ nk } B = \S_{ nk } A /\ [a5]_s = zero32 /\ [a2]_s = zero32))).
apply (before_frame
(fun s h => [ rx ]_ s = va /\ sgZ (s2Z slen) = -1 /\ (var_e rx |--> slen :: ptr :: nil) s h)
(fun s h => u2Z [ rk ]_s = Z_of_nat nk /\
[ ry ]_s = vb /\ [ rX ]_s = ptr /\ (var_e ry |--> B ** var_e rX |--> A) s h)
(fun s h => u2Z ([ rk ]_ s) = Z_of_nat nk /\ [ ry ]_ s = vb /\ [ rX ]_ s = ptr /\
((\S_{ nk } B < \S_{ nk } A /\ ([a5 ]_ s) = one32 /\ [a2]_s = zero32) \/
(\S_{ nk } B > \S_{ nk } A /\ ([a5 ]_ s) = zero32 /\ [a2]_s = one32) \/
(\S_{ nk } B = \S_{ nk } A /\ ([a5 ]_ s) = zero32 /\ [a2]_s = zero32)) /\
(var_e ry |--> B ** var_e rX |--> A) s h)).
apply frame_rule_R; last 2 first.
by Inde_frame.
move=> ?; by Inde_mult.
apply multi_lt_triple => //; by Uniq_uniq r0.
rewrite /while.entails => s h [[Ha [Hb [Hk [HX [Ha0 [HZgn [Hsgn' Hmem]]]]]]] Ha1].
rewrite conAE in Hmem.
case : Hmem => h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]].
Compose_sepcon h2 h1.
repeat (split => //).
rewrite conCE.
move: Hh2; apply monotony => // h'; exact: mapstos_ext.
repeat (split => //).
rewrite /= in Ha1.
move/leZP in Ha1.
case: Hsgn' => Hsgn'; first lia.
case: Hsgn' => Hsgn'; first lia.
by rewrite -HZgn Hsgn'.
rewrite /while.entails => s h [h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]]].
case: Hh1 => Hk [Hb [hX [Hsum Hh1]]].
case: Hh2 => Ha [Hsgn Hh2].
split.
- repeat (split => //).
rewrite conAE.
Compose_sepcon h2 h1 => //.
rewrite conCE.
move: Hh1; apply monotony => // h'; exact: mapstos_ext.
- case: Hsum => Hsum.
left; tauto.
by right.
If_beq a5,r0 Then
apply while.hoare_ifte.
If_beq a2,r0 Then
apply while.hoare_ifte.
addiu a3 r0 zero16 ;
apply hoare_addiu with (fun s h => [ rx ]_ s = va /\ [ ry ]_ s = vb /\
u2Z [ rk ]_ s = Z_of_nat nk /\ [ rX ]_ s = ptr /\ [a3]_s = zero32 /\
sgZ (s2Z slen) = -1 /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A) ** var_e ry |--> B) s h /\
\S_{ nk } B = \S_{ nk } A).
move=> s h [ [[ [Ha [Hb [Hk [HX [Hslen mem]]] ]] Hsum] Ha5] Ha2].
rewrite /wp_addiu.
repeat Reg_upd; repeat (split => //).
by rewrite add0i sext_Z2u.
by Assert_upd.
rewrite /= in Ha5 Ha2.
move/eqP/u2Z_inj in Ha5.
move/eqP/u2Z_inj in Ha2.
case: Hsum => Hsum.
- rewrite Ha5 store.get_r0 in Hsum.
case: Hsum => _ [Hsum _].
by apply Z2u_dis in Hsum.
- case: Hsum => Hsum; last tauto.
case: Hsum => _ [_ Hsum].
rewrite Ha2 store.get_r0 in Hsum.
by apply Z2u_dis in Hsum.
sw r0 zero16 rx
apply hoare_sw_back'.
move=> s h [Ha [Hb [Hk [HX [Ha3 [Hslen [mem Hsum]]]]]]].
exists (int_e slen).
rewrite !conAE /= in mem.
move: mem; apply monotony => // h'.
apply mapsto_ext => //=; by rewrite sext_Z2u // addi0.
apply currying => h'' Hh''.
exists A , (Z2s 32 0).
repeat (split => //).
by rewrite Z2sK.
by rewrite Z2sK //= Hslen Hsum addZC mulN1Z addZN.
rewrite conCE in Hh''.
rewrite !conAE /=.
move: Hh''; apply monotony => // h'''.
apply mapsto_ext => /=.
by rewrite sext_Z2u // addi0.
rewrite store.get_r0.
apply u2Z_inj.
by rewrite Z2uK // u2Z_Z2s_pos.
by rewrite Ha3 Z2uK.
rewrite Z2sK //= Hslen Hsum; ring.
multi_sub_u_u rk ry rX rX a0 a1 a2 a3 a4 a5 ;
apply hoare_prop_m.hoare_stren with (fun s h => \S_{ nk } B > \S_{ nk } A /\
(([ rx ]_ s = va /\ [ ry ]_ s = vb /\ u2Z ([ rk ]_ s) = Z_of_nat nk /\
[ rX ]_ s = ptr /\ sgZ (s2Z slen) = -1 /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A) ** var_e ry |--> B) s h))).
rewrite /while.entails => s h [[[[Ha [Hb [Hk [HX [Hsgn Hmem]]]]] Hsum] Ha5] Ha2].
repeat (split => //).
rewrite /= store.get_r0 Z2uK // in Ha5.
move/eqP in Ha5.
case: Hsum => Hsum.
- case: Hsum => _ [Hsum _].
by rewrite Hsum Z2uK in Ha5.
- rewrite /= in Ha2.
move/eqP in Ha2.
case: Hsum => Hsum; first by tauto.
case: Hsum => _ [_ Hsum].
by rewrite Hsum Z2uK // store.get_r0 // Z2uK in Ha2.
apply (hoare_prop_m.pull_out_conjunction' hoare0_false) => HAB.
apply while.hoare_seq with (fun s h => exists A', size A' = nk /\
[ rx ]_ s = va /\ [ ry ]_ s = vb /\ s2Z slen = sgZ (s2Z slen) * Z_of_nat nk /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A') ** var_e ry |--> B) s h /\
[a3]_s = zero32 /\ sgZ (s2Z slen) = -1 /\
- sgZ (s2Z slen) * (\S_{ nk } A' - u2Z ([a3 ]_ s) * \B^nk) =
sgZ (s2Z slen) * \S_{ nk } A + \S_{ nk } B).
apply (before_frame
(fun s h => [ rx ]_ s = va /\ sgZ (s2Z slen) = -1 /\ (var_e rx |--> slen :: ptr :: nil) s h)
(fun s h => [ ry ]_s = vb /\ [ rX ]_ s = ptr /\ u2Z ([ rk ]_ s) = Z_of_nat nk /\
(var_e ry |--> B ** var_e rX |--> A) s h)
(fun s h => exists A', size A' = nk /\
[ ry ]_s = vb /\ [ rX ]_ s = ptr /\ u2Z ([ rk ]_ s) = Z_of_nat nk /\ [a3]_s = zero32 /\
(var_e ry |--> B ** var_e rX |--> A') s h /\ \S_{ nk } A' = \S_{ nk } B - \S_{ nk } A)).
apply frame_rule_R; last 2 first.
by Inde_frame.
move=> ?; by Inde_mult.
apply multi_sub_u_u_R_triple_B_le_A => //.
by Uniq_uniq r0.
lia.
rewrite /while.entails => s h [Ha [Hb [Hk [HX [Hsgn Hmem]]]]].
rewrite conAE in Hmem.
case: Hmem => h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]].
Compose_sepcon h2 h1; last by [].
repeat (split => //).
rewrite conCE.
move: Hh2; apply monotony => h' //; exact: mapstos_ext.
rewrite /while.entails => s h [h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 [Hva [Hsgn Hh2]]]]]]].
case: Hh1 => A' [len_A' [Hb [HX [Hk [Ha3 [Hh1 Hsum]]]]]].
exists A'.
repeat (split => //).
rewrite conAE.
Compose_sepcon h2 h1 => //.
rewrite conCE.
move: Hh1; apply monotony => // h'; exact: mapstos_ext.
rewrite Hsgn mulNZ mulN1Z oppZK Hsum Ha3 Z2uK // mul0Z subZ0; ring.
apply (hoare_prop_m.extract_exists extract_exists0) => A'.
multi_negate rx a0
apply (before_frame (fun s h => size A' = nk /\ [ rx ]_ s = va /\ [ ry ]_ s = vb /\
s2Z slen = sgZ (s2Z slen) * Z_of_nat nk /\
(var_e ry |--> B) s h /\ [a3 ]_ s = zero32 /\ sgZ (s2Z slen) = -1 /\
- sgZ (s2Z slen) * (\S_{ nk } A' - u2Z [a3 ]_ s * \B^nk) = sgZ (s2Z slen) * \S_{ nk } A + \S_{ nk } B)
(var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A')
(var_e rx |--> cplt2 slen :: ptr :: nil ** int_e ptr |--> A')).
apply frame_rule_R.
- apply multi_negate_triple; by Uniq_uniq r0.
- Inde_frame.
rewrite /inde => s h x v /= [] // ?; subst x; by Reg_upd.
- move=> ?; by Inde_mult.
rewrite /while.entails => s h [lenA' [r_a [r_b [slen'_nk [Hmem [Ha3 [Hsgn HSum]]]]]]].
move: Hmem; exact: monotony.
rewrite /while.entails => s h Hmem.
case: Hmem => h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]].
case: Hh2 => A'_nk [slen_nk_ [r_a [r_b [Hh2 [Ha3 [HZsgn HSum]]]]]].
exists (cplt2 slen).
rewrite s2Z_cplt2; last first.
rewrite weirdE2 slen_no_weird HZsgn; lia.
rewrite Ha3 Z2uK // mul0Z subZ0 in HSum.
rewrite Ha3 Z2uK // mul0Z addZ0 Zsgn_Zopp.
repeat (split => //).
have Htmp : - sgZ (s2Z slen) = 1 by rewrite HZsgn.
rewrite !Htmp HZsgn in HSum *.
rewrite r_b HZsgn; ring.
have Htmp : - sgZ (s2Z slen) = 1 by rewrite HZsgn.
rewrite !Htmp HZsgn in HSum *.
rewrite mul1Z in HSum.
rewrite -HSum (proj2 (Zsgn_pos (\S_{ nk } A'))) //.
move: (min_lSum nk A) => ?.
rewrite HSum mulN1Z; lia.
by Compose_sepcon h1 h2.
multi_sub_u_u k rX b rX a0 a1 a5 a3 a2 a4
apply hoare_prop_m.hoare_stren with (fun s h => \S_{ nk } B < \S_{ nk } A /\
([ rx ]_ s = va /\ [ ry ]_ s = vb /\ u2Z ([ rk ]_ s) = Z_of_nat nk /\ [ rX ]_ s = ptr /\
sgZ (s2Z slen) = -1 /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A) ** var_e ry |--> B) s h)).
rewrite /while.entails => s h [[[Ha [Hb [Hk [HX [Hslen Hmem]]]]] Hsum] Ha5].
case: Hsum => Hsum; first by tauto.
rewrite /= in Ha5.
move/eqP in Ha5.
rewrite store.get_r0 in Ha5.
case: Hsum.
case=> _ [Hsum _].
by rewrite Hsum Z2uK in Ha5.
case=> _ [Hsum _].
by rewrite Hsum Z2uK in Ha5.
apply (hoare_prop_m.pull_out_conjunction' hoare0_false) => HAB.
apply (before_frame
(fun s h => [ rx ]_ s = va /\ sgZ (s2Z slen) = -1 /\ (var_e rx |--> slen :: ptr :: nil) s h)
(fun s h => [ rX ]_s = ptr /\
[ ry ]_s = vb /\ u2Z ([ rk ]_ s) = Z_of_nat nk /\ (var_e rX |--> A ** var_e ry |--> B) s h)
(fun s h => exists A', size A' = nk /\
[ rX ]_s = ptr /\ [ ry ]_s = vb /\ u2Z ([ rk ]_ s) = Z_of_nat nk /\ [a3]_s = zero32 /\
(var_e rX |--> A' ** var_e ry |--> B) s h /\ \S_{ nk } A' = \S_{ nk } A - \S_{ nk } B)).
apply frame_rule_R; last 2 first.
by Inde_frame.
move=> ?; by Inde_mult.
apply multi_sub_u_u_L_triple_B_le_A => //.
by Uniq_uniq r0.
exact/ltZW.
rewrite /while.entails => s h [Ha [Hb [Hk [HX [Hslen Hmem]]]]].
rewrite conAE in Hmem.
case: Hmem => h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]].
Compose_sepcon h2 h1; last by [].
repeat (split => //).
move: Hh2; apply monotony => // h'; exact: mapstos_ext.
rewrite /while.entails => s h Hmem.
case: Hmem => h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]].
case: Hh1 => A' [len_A' [HX [Hb [Hk [Ha3 [Hh1 Hsum]]]]]].
case: Hh2 => Ha [Hsgn Hh2].
exists A', slen.
repeat (split => //).
rewrite Hsgn (proj2 (Zsgn_neg (-1 * \S_{ nk } A + \S_{ nk } B))) // addZC mulN1Z addZNE; lia.
rewrite conAE.
Compose_sepcon h2 h1; first by [].
move: Hh1; apply monotony => // h'.
exact: mapstos_ext.
by rewrite Ha3 Z2uK.
rewrite Hsgn 2!mulN1Z Hsum Ha3 Z2uK // mul0Z; ring.
Qed.
Lemma multi_add_s_u_triple_gen rk rx ry a0 a1 a2 a3 a4 a5 rX :
uniq(rk, rx, ry, a0, a1, a2, a3, a4, a5, rX, r0) ->
forall k va vb ptr, k <> O -> Z_of_nat k < 2 ^^ 31 ->
u2Z ptr + 4 * Z_of_nat k < \B^1 -> u2Z vb + 4 * Z_of_nat k < \B^1 ->
forall X Y, size X = k -> size Y = k ->
forall slen, s2Z slen = sgZ (s2Z slen) * Z_of_nat k ->
sgZ (s2Z slen) = sgZ (sgZ (s2Z slen) * \S_{ k } X) ->
{{ fun s h => [ rx ]_s = va /\ [ ry ]_s = vb /\
u2Z [ rk ]_s = Z_of_nat k /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> X) ** var_e ry |--> Y) s h }}
multi_add_s_u rk rx ry a0 a1 a2 a3 a4 a5 rX
{{ fun s h => exists X' slen', size X' = k /\
[ rx ]_s = va /\ [ ry ]_s = vb /\ s2Z slen' = sgZ (s2Z slen') * Z_of_nat k /\
sgZ (s2Z slen') = sgZ (sgZ (s2Z slen) * \S_{ k } X + \S_{ k } Y) /\
((var_e rx |--> slen' :: ptr :: nil ** int_e ptr |--> X') ** var_e ry |--> Y) s h /\
u2Z ([a3]_ s) <= 1 /\
sgZ (s2Z slen') * (\S_{ k } X' + u2Z ([a3]_ s) * \B^k) =
sgZ (s2Z slen) * \S_{ k } X + \S_{ k } Y }}.
Proof.
move=> Hregs nk va vb ptr Hnk Hnk' ptr_fit vb_fit A B
len_A len_B slen slen_no_weird slen_A.
rewrite /multi_add_s_u.
multi_is_zero_u rk ry a0 a1 a2 ;
apply while.hoare_seq with (fun s h => [ rx ]_s = va /\ [ ry ]_s = vb /\
u2Z [ rk ]_s = Z_of_nat nk /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A) ** var_e ry |--> B) s h /\
((0 = \S_{ nk } B -> [a2]_s = one32) /\ (0 < \S_{ nk } B -> [a2]_s = zero32))).
apply (before_frame(fun s h => [ rx ]_ s = va /\
(var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A) s h)
(fun s h => u2Z [ rk ]_s = Z_of_nat nk /\ [ ry ]_s = vb /\ (var_e ry |--> B) s h)
(fun s h => u2Z [ rk ]_s = Z_of_nat nk /\ [ ry ]_s = vb /\ (var_e ry |--> B) s h /\
((0 = \S_{ nk } B -> [a2]_s = one32) /\ (0 < \S_{ nk } B -> [a2]_s = zero32)))).
apply frame_rule_R; last 2 first.
by Inde_frame.
move=> ?; by Inde_mult.
apply multi_is_zero_u_triple => //.
by Uniq_uniq r0.
move=> s h [Ha [Hb [Hk mem]]].
case: mem => h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]].
Compose_sepcon h2 h1.
by repeat (split => //).
by repeat (split => //).
move => s h [h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]]].
repeat (split; first by tauto).
split; last by tauto.
Compose_sepcon h2 h1; tauto.
If_bne a2,r0 Then
apply while.hoare_ifte.
addiu a3 r0 zero16
apply hoare_addiu'.
move=> s h [ [Ha [Hb [Hk [mem Ha5]]]] Ha2].
rewrite /= in Ha2.
move/eqP in Ha2.
move: (min_lSum nk B).
case/Z_le_lt_eq_dec => Hsum.
apply (proj2 Ha5) in Hsum.
by rewrite Hsum Z2uK // store.get_r0 Z2uK in Ha2.
exists A, slen.
repeat Reg_upd; repeat (split => //).
rewrite -Hsum addZ0; exact slen_A.
by Assert_upd.
by rewrite sext_Z2u // addi0 Z2uK.
rewrite sext_Z2u // addi0 Z2uK // mul0Z addZ0 -Hsum; ring.
multi_add_s_u0 rk rx ry a0 a1 a2 a3 a4 a5 rX
apply hoare_prop_m.hoare_stren with
(!(fun s => 0 < \S_{ nk } B) **
(fun s h => [ rx ]_ s = va /\ [ ry ]_ s = vb /\ u2Z [ rk ]_ s = Z_of_nat nk /\
((var_e rx |--> slen :: ptr :: nil ** int_e ptr |--> A) ** var_e ry |--> B) s h)).
move=> s h [[Ha [Hb [Hk [mem Ha2']]]] Ha2].
rewrite /= negbK in Ha2.
move/eqP/u2Z_inj in Ha2.
move: (min_lSum nk B).
case/Z_le_lt_eq_dec => Hsum; last first.
apply (proj1 Ha2') in Hsum.
rewrite Hsum store.get_r0 in Ha2.
by apply Z2u_dis in Ha2.
by Compose_sepcon heap.emp h.
apply pull_out_bang => nk_B.
exact: multi_add_s_u'_triple.
Qed.
Lemma multi_add_s_u_triple rk rx ry a0 a1 a2 a3 a4 a5 rX :
uniq(rk, rx, ry, a0, a1, a2, a3, a4, a5, rX, r0) ->
forall k, 0 < Z_of_nat k < 2 ^^ 31 ->
forall vx vy X Y,
{{ fun s h => [rx]_s = vx /\ [ry]_s = vy /\
u2Z [rk]_s = Z_of_nat k /\
(var_signed k rx X ** var_unsign k ry Y) s h }}
multi_add_s_u rk rx ry a0 a1 a2 a3 a4 a5 rX
{{ fun s h => exists X' l' ptr, size X' = k /\
[rx]_s = vx /\ [ry]_s = vy /\ s2Z l' = sgZ (s2Z l') * Z_of_nat k /\
sgZ (s2Z l') = sgZ (X + Y) /\
((var_e rx |--> l' :: ptr :: List.nil ** int_e ptr |--> X') **
var_unsign k ry Y) s h /\
u2Z ([a3]_ s) <= 1 /\
sgZ (s2Z l') * (\S_{ k } X' + u2Z ([a3]_ s) * \B^k) = X + Y }}.
Proof.
move=> Hvars nk nk_0_max va vb A B.
apply hoare_prop_m.hoare_stren with (fun s h => exists slen ptr A0,
u2Z va + 4 * 2 < \B^1 /\
0 <= B < \B^nk /\
sgZ (s2Z slen) = sgZ A /\
u2Z ptr + 4 * Z_of_nat nk < \B^1 /\
u2Z vb + 4 * Z_of_nat nk < \B^1 /\
s2Z slen = sgZ (s2Z slen) * Z_of_nat nk /\
A = sgZ (s2Z slen) * \S_{ nk } A0 /\
size A0 = nk /\
[rx]_s = va /\ [ry]_s = vb /\
u2Z [rk ]_ s = Z_of_nat nk /\
((fun st h0 =>
((var_e rx |--> slen :: (ptr :: Datatypes.nil)%list **
int_e ptr |--> A0) st h0)) **
(fun st h0 =>
(var_e ry |--> Z2ints 32 nk B) st h0))
s h).
move=> s h H.
case: H => k_nk [a_va [b_vb [h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]]]]].
case: Hh1 => slen ptr A0 a_fit encodingA ptr_fit Hmem.
case: Hh2 => b_fit B_over G_mem.
exists slen, ptr, A0; repeat (split => //).
by subst va.
by case: encodingA => *.
by subst vb.
by case: encodingA => *.
by case: encodingA => *.
by case: encodingA => *.
by exists h1, h2.
apply mips_contrib.pull_out_exists => slen.
apply mips_contrib.pull_out_exists => ptr.
apply mips_contrib.pull_out_exists => A0.
apply (hoare_prop_m.pull_out_conjunction' mips_contrib.hoare0_false) => ?.
apply (hoare_prop_m.pull_out_conjunction' mips_contrib.hoare0_false) => ?.
apply (hoare_prop_m.pull_out_conjunction' mips_contrib.hoare0_false) => slen_A.
apply (hoare_prop_m.pull_out_conjunction' mips_contrib.hoare0_false) => ptr_fit.
apply (hoare_prop_m.pull_out_conjunction' mips_contrib.hoare0_false) => vb_fit.
apply (hoare_prop_m.pull_out_conjunction' mips_contrib.hoare0_false) => slen_nk.
apply (hoare_prop_m.pull_out_conjunction' mips_contrib.hoare0_false) => A_A0.
apply (hoare_prop_m.pull_out_conjunction' mips_contrib.hoare0_false) => A0_nk.
apply while.hoare_conseq with
(P' := fun s h => [rx]_s = va /\ [ry]_s = vb /\ u2Z [rk]_s = Z_of_nat nk /\
((var_e rx |--> slen :: ptr :: List.nil **
int_e ptr |--> A0) ** var_e ry |--> Z2ints 32 nk B) s h)
(Q':= fun s h => exists A' slen', size A' = nk /\
[rx]_s = va /\ [ry]_s = vb /\ s2Z slen' = sgZ (s2Z slen') * Z_of_nat nk /\
sgZ (s2Z slen') = sgZ (sgZ (s2Z slen) * \S_{ nk } A0 + \S_{ nk } (Z2ints 32 nk B)) /\
((var_e rx |--> slen' :: ptr :: List.nil ** int_e ptr |--> A') **
var_e ry |--> Z2ints 32 nk B) s h /\
u2Z ([a3]_ s) <= 1 /\
sgZ (s2Z slen') * (\S_{ nk } A' + u2Z ([a3]_ s) * \B^nk) =
sgZ (s2Z slen) * \S_{ nk } A0 + \S_{ nk } (Z2ints 32 nk B)).
- move=> s h H.
case: H => A' [slen' [A'_nk [a_va [b_vb [slen'_nk [slen'_A_B [Hmem [Ha3 HA']]]]]]]].
exists A', slen', ptr.
repeat (split => //).
+ rewrite slen'_A_B.
rewrite lSum_Z2ints; last by rewrite Z.abs_eq; tauto.
rewrite A_A0.
rewrite Z.abs_eq; tauto.
+ move: Hmem; apply assert_m.monotony => // h' Hh'.
apply mkVarUnsign => //.
congruence.
+ rewrite lSum_Z2ints in HA'; last by rewrite Z.abs_eq; tauto.
rewrite HA' -A_A0 Z.abs_eq; tauto.
- move=> s h [a_va [b_vb [k_nk H]]].
case: H => h1 [h2 [h1_d_h2 [h1_U_h2 [Hh1 Hh2]]]].
repeat (split; first by []).
by exists h1, h2.
- apply multi_add_s_u_triple_gen => //.
lia.
by case: nk_0_max.
by rewrite size_Z2ints.
by rewrite -A_A0.
Qed.