Library multi_add_s_u_termination
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.
Require Import ZArith_ext seq_ext uniq_tac machine_int.
Import MachineInt.
Require Import mips_cmd mips_tactics mips_contrib.
Import expr_m.
Require Import multi_add_s_u_prg multi_is_zero_u_termination pick_sign_prg.
Require Import pick_sign_termination copy_u_u_termination multi_add_u_u_termination.
Require Import multi_negate_termination multi_lt_termination multi_sub_u_u_termination.
Local Open Scope machine_int_scope.
Local Open Scope mips_expr_scope.
Local Open Scope mips_cmd_scope.
Local Open Scope uniq_scope.
Lemma multi_add_s_u0_termination st h rk rx ry a0 a1 a2 a3 a4 a5 rX :
uniq(rk, rx, ry, a0, a1, a2, a3, a4, a5, rX, r0) ->
{ s' | Some (st, h) -- multi_add_s_u0 rk rx ry a0 a1 a2 a3 a4 a5 rX ---> s' }%mips_cmd.
Proof.
move=> Hregs.
set c := multi_add_s_u0 _ _ _ _ _ _ _ _ _ _.
have : {s' | Some (st, h) -- c ---> s' /\ forall s, s' = Some s -> True}.
rewrite /c {c} /multi_add_s_u0.
exists_lw l Hl z Hz.
set s0 := store.upd _ _ _.
have : uniq(rx,a0,a1,r0) by Uniq_uniq r0.
case/(pick_sign_termination s0 h rx a0 a1) => s1 Hs1.
apply exists_seq_P with (fun s' => forall st0 : store.t * heap.t, s' = Some st0 -> True).
by exists s1.
move=> [[s1' h1']|] Hs1'; last first.
exists None; split => //.
by apply while.exec_none.
apply exists_ifte_P.
apply exists_ifte_P.
have : uniq(rk, rX, ry, a2, a3, a4, r0) by Uniq_uniq r0.
case/(copy_u_u_termination s1' h1') => s2 Hs2.
apply exists_seq_P with (fun s' => forall st0 : store.t * heap.t, s' = Some st0 -> True).
by exists s2.
move=> [[s2' h2']|] Hs2'; last first.
exists None; split => //.
by apply while.exec_none.
apply exists_addiu_seq_P.
by exists_sw1 k Hk z' Hz'.
apply exists_addiu_seq_P.
repeat Reg_upd.
rewrite add0i.
have : uniq(rk, a3, ry, rX, a0, a1, a2, r0) by Uniq_uniq r0.
move/(multi_add_u_u_termination) => H.
set s2 := store.upd _ _ _.
case: {H}(H s2 h1' rX) => si Hsi.
destruct si as [[si hi]|]; last first.
exists None; split => //.
apply while.exec_seq with None => //.
by apply while.exec_none.
apply exists_seq_P with (fun si => True).
by exists (Some (si, hi)).
case.
case=> si0 hi0 _.
by apply exists_mflo_P.
move=> _.
exists None; split => //.
by apply while.exec_none.
have : uniq(rk, ry, rX, a0, a1, a5, a2, a3, a4, r0) by Uniq_uniq r0.
move/multi_lt_termination.
case/(_ s1' h1').
case; last first.
move=> Hsi.
exists None; split => //.
apply while.exec_seq with None => //.
by apply while.exec_none.
case=> s2 h2 s2h2.
apply exists_seq_P with (fun s' => forall s, s' = Some s -> True).
by exists (Some (s2, h2)).
case=> [[s2' h2']|] => //; last first.
move=> _.
exists None; split => //.
by apply while.exec_none.
move=> ?.
apply exists_ifte_P.
apply exists_ifte_P.
apply exists_addiu_seq_P.
by exists_sw1 a b c d.
have : uniq(rk, rX, ry, a0, a1, a2, a3, a4, a5, r0) by Uniq_uniq r0.
move/multi_sub_u_u_termination.
move/(_ s2' h2' rX) => H2'.
apply exists_seq_P with (fun si => True).
case: H2' => si H2'.
by exists si.
move=> [[si hi]|]; last first.
move=> _.
exists None; split => //.
by apply while.exec_none.
move=> _.
have : uniq(rx, a0, r0) by Uniq_uniq r0.
move/multi_negate_termination.
case/(_ si hi) => x.
by exists x.
have : uniq(rk, ry, rX, a0, a1, a5, a3, a2, a4, r0) by Uniq_uniq r0.
move/multi_sub_u_u_termination.
case/(_ s2' h2' rX) => x.
by exists x.
case=> x [] Hx _.
by exists x.
Qed.
Lemma multi_add_s_u_termination st h rk rx ry a0 a1 a2 a3 a4 a5 rX :
uniq(rk, rx, ry, a0, a1, a2, a3, a4, a5, rX, r0) ->
{ s' | Some (st, h) -- multi_add_s_u rk rx ry a0 a1 a2 a3 a4 a5 rX ---> s' }%mips_cmd.
Proof.
move=> Hregs.
have : {s' : option (store.t * heap.t) |
(Some (st, h) -- multi_add_s_u rk rx ry a0 a1 a2 a3 a4 a5 rX ---> s')%mips_cmd /\
(forall s, s' = Some s -> True)}.
rewrite /multi_add_s_u.
apply exists_seq_P with (fun s => forall s', s = Some s' -> True).
have : uniq(rk, ry, a0, a1, a2, r0) by Uniq_uniq r0.
case/(multi_is_zero_u_termination st h) => si Hsi.
by exists si.
move=> [[si hi]|] Hsi; last first.
exists None; split => //.
by apply while.exec_none.
apply exists_ifte_P.
by apply exists_addiu_P.
have : uniq(rk,rx,ry,a0,a1,a2,a3,a4,a5,rX,r0) by Uniq_uniq r0.
move/(multi_add_s_u0_termination si hi).
case=> si' Hsi'.
exists si'; tauto.
case=> si Hsi.
exists si; tauto.
Qed.
Require Import ZArith_ext seq_ext uniq_tac machine_int.
Import MachineInt.
Require Import mips_cmd mips_tactics mips_contrib.
Import expr_m.
Require Import multi_add_s_u_prg multi_is_zero_u_termination pick_sign_prg.
Require Import pick_sign_termination copy_u_u_termination multi_add_u_u_termination.
Require Import multi_negate_termination multi_lt_termination multi_sub_u_u_termination.
Local Open Scope machine_int_scope.
Local Open Scope mips_expr_scope.
Local Open Scope mips_cmd_scope.
Local Open Scope uniq_scope.
Lemma multi_add_s_u0_termination st h rk rx ry a0 a1 a2 a3 a4 a5 rX :
uniq(rk, rx, ry, a0, a1, a2, a3, a4, a5, rX, r0) ->
{ s' | Some (st, h) -- multi_add_s_u0 rk rx ry a0 a1 a2 a3 a4 a5 rX ---> s' }%mips_cmd.
Proof.
move=> Hregs.
set c := multi_add_s_u0 _ _ _ _ _ _ _ _ _ _.
have : {s' | Some (st, h) -- c ---> s' /\ forall s, s' = Some s -> True}.
rewrite /c {c} /multi_add_s_u0.
exists_lw l Hl z Hz.
set s0 := store.upd _ _ _.
have : uniq(rx,a0,a1,r0) by Uniq_uniq r0.
case/(pick_sign_termination s0 h rx a0 a1) => s1 Hs1.
apply exists_seq_P with (fun s' => forall st0 : store.t * heap.t, s' = Some st0 -> True).
by exists s1.
move=> [[s1' h1']|] Hs1'; last first.
exists None; split => //.
by apply while.exec_none.
apply exists_ifte_P.
apply exists_ifte_P.
have : uniq(rk, rX, ry, a2, a3, a4, r0) by Uniq_uniq r0.
case/(copy_u_u_termination s1' h1') => s2 Hs2.
apply exists_seq_P with (fun s' => forall st0 : store.t * heap.t, s' = Some st0 -> True).
by exists s2.
move=> [[s2' h2']|] Hs2'; last first.
exists None; split => //.
by apply while.exec_none.
apply exists_addiu_seq_P.
by exists_sw1 k Hk z' Hz'.
apply exists_addiu_seq_P.
repeat Reg_upd.
rewrite add0i.
have : uniq(rk, a3, ry, rX, a0, a1, a2, r0) by Uniq_uniq r0.
move/(multi_add_u_u_termination) => H.
set s2 := store.upd _ _ _.
case: {H}(H s2 h1' rX) => si Hsi.
destruct si as [[si hi]|]; last first.
exists None; split => //.
apply while.exec_seq with None => //.
by apply while.exec_none.
apply exists_seq_P with (fun si => True).
by exists (Some (si, hi)).
case.
case=> si0 hi0 _.
by apply exists_mflo_P.
move=> _.
exists None; split => //.
by apply while.exec_none.
have : uniq(rk, ry, rX, a0, a1, a5, a2, a3, a4, r0) by Uniq_uniq r0.
move/multi_lt_termination.
case/(_ s1' h1').
case; last first.
move=> Hsi.
exists None; split => //.
apply while.exec_seq with None => //.
by apply while.exec_none.
case=> s2 h2 s2h2.
apply exists_seq_P with (fun s' => forall s, s' = Some s -> True).
by exists (Some (s2, h2)).
case=> [[s2' h2']|] => //; last first.
move=> _.
exists None; split => //.
by apply while.exec_none.
move=> ?.
apply exists_ifte_P.
apply exists_ifte_P.
apply exists_addiu_seq_P.
by exists_sw1 a b c d.
have : uniq(rk, rX, ry, a0, a1, a2, a3, a4, a5, r0) by Uniq_uniq r0.
move/multi_sub_u_u_termination.
move/(_ s2' h2' rX) => H2'.
apply exists_seq_P with (fun si => True).
case: H2' => si H2'.
by exists si.
move=> [[si hi]|]; last first.
move=> _.
exists None; split => //.
by apply while.exec_none.
move=> _.
have : uniq(rx, a0, r0) by Uniq_uniq r0.
move/multi_negate_termination.
case/(_ si hi) => x.
by exists x.
have : uniq(rk, ry, rX, a0, a1, a5, a3, a2, a4, r0) by Uniq_uniq r0.
move/multi_sub_u_u_termination.
case/(_ s2' h2' rX) => x.
by exists x.
case=> x [] Hx _.
by exists x.
Qed.
Lemma multi_add_s_u_termination st h rk rx ry a0 a1 a2 a3 a4 a5 rX :
uniq(rk, rx, ry, a0, a1, a2, a3, a4, a5, rX, r0) ->
{ s' | Some (st, h) -- multi_add_s_u rk rx ry a0 a1 a2 a3 a4 a5 rX ---> s' }%mips_cmd.
Proof.
move=> Hregs.
have : {s' : option (store.t * heap.t) |
(Some (st, h) -- multi_add_s_u rk rx ry a0 a1 a2 a3 a4 a5 rX ---> s')%mips_cmd /\
(forall s, s' = Some s -> True)}.
rewrite /multi_add_s_u.
apply exists_seq_P with (fun s => forall s', s = Some s' -> True).
have : uniq(rk, ry, a0, a1, a2, r0) by Uniq_uniq r0.
case/(multi_is_zero_u_termination st h) => si Hsi.
by exists si.
move=> [[si hi]|] Hsi; last first.
exists None; split => //.
by apply while.exec_none.
apply exists_ifte_P.
by apply exists_addiu_P.
have : uniq(rk,rx,ry,a0,a1,a2,a3,a4,a5,rX,r0) by Uniq_uniq r0.
move/(multi_add_s_u0_termination si hi).
case=> si' Hsi'.
exists si'; tauto.
case=> si Hsi.
exists si; tauto.
Qed.