Require Coq.funind.Recdef.
Ltac inv_int i :=
let ofs := fresh "ofs" in
let H := fresh "H" in
let H0 := fresh "H" in
let H1 := fresh "H" in
match type of i with
| int =>
pose proof Int.repr_unsigned i as H;
pose proof Int.unsigned_range i as H0;
remember (Int.unsigned i) as ofs eqn:H1;
rewrite <- H in *;
clear H H1; try clear i
| ptrofs =>
pose proof Ptrofs.repr_unsigned i as H;
pose proof Ptrofs.unsigned_range i as H0;
remember (Ptrofs.unsigned i) as ofs eqn:H1;
rewrite <- H in *;
clear H H1; try clear i
end.
(**************************************************  Solve_mod_modulus  **************************************************)
Definition int_modm x := x mod Int.modulus.
Definition int_reprm := Int.repr.
Ltac int_simpl_mod A H :=
let H0 := fresh "H" in
let H1 := fresh "H" in
match A with
| (?B + ?C)%Z =>
int_simpl_mod B H0; int_simpl_mod C H1;
pose proof Zbits.eqmod_add Int.modulus _ _ _ _ H0 H1 as H;
clear H1 H0
| (?B - ?C)%Z =>
int_simpl_mod B H0; int_simpl_mod C H1;
pose proof Zbits.eqmod_sub Int.modulus _ _ _ _ H0 H1 as H;
clear H1 H0
| (?B * ?C)%Z =>
int_simpl_mod B H0; int_simpl_mod C H1;
pose proof Zbits.eqmod_mult Int.modulus _ _ _ _ H0 H1 as H;
clear H1 H0
| (- ?B)%Z =>
int_simpl_mod B H0;
pose proof Zbits.eqmod_neg Int.modulus _ _ H0 as H;
clear H0
| ?B mod Int.modulus =>
int_simpl_mod B H0;
pose proof int_modm_mod_elim B _ H0 as H;
clear H0
| int_modm ?B =>
int_simpl_mod B H0;
pose proof int_modm_mod_elim B _ H0 as H;
clear H0
| _ =>
pose proof Zbits.eqmod_refl Int.modulus A as H
end.
Definition ptrofs_modm x := x mod Ptrofs.modulus.
Definition ptrofs_reprm := Ptrofs.repr.
Ltac ptrofs_simpl_mod A H :=
let H0 := fresh "H" in
let H1 := fresh "H" in
match A with
| (?B + ?C)%Z =>
ptrofs_simpl_mod B H0; ptrofs_simpl_mod C H1;
pose proof Zbits.eqmod_add Ptrofs.modulus _ _ _ _ H0 H1 as H;
clear H1 H0
| (?B - ?C)%Z =>
ptrofs_simpl_mod B H0; ptrofs_simpl_mod C H1;
pose proof Zbits.eqmod_sub Ptrofs.modulus _ _ _ _ H0 H1 as H;
clear H1 H0
| (?B * ?C)%Z =>
ptrofs_simpl_mod B H0; ptrofs_simpl_mod C H1;
pose proof Zbits.eqmod_mult Ptrofs.modulus _ _ _ _ H0 H1 as H;
clear H1 H0
| (- ?B)%Z =>
ptrofs_simpl_mod B H0;
pose proof Zbits.eqmod_neg Ptrofs.modulus _ _ H0 as H;
clear H0
| ?B mod Ptrofs.modulus =>
ptrofs_simpl_mod B H0;
pose proof ptrofs_modm_mod_elim B _ H0 as H;
clear H0
| ptrofs_modm ?B =>
ptrofs_simpl_mod B H0;
pose proof ptrofs_modm_mod_elim B _ H0 as H;
clear H0
| _ =>
pose proof Zbits.eqmod_refl Ptrofs.modulus A as H
end.
Ltac solve_mod_modulus :=
unfold Int.add; rewrite ?Int.unsigned_repr_eq;
unfold Ptrofs.add; rewrite ?Ptrofs.unsigned_repr_eq;
repeat
match goal with
| |- context [?A mod Int.modulus] =>
let H := fresh "H" in int_simpl_mod A H;
rewrite (int_modm_mod_eq A _ H);
clear H
| |- context [Int.repr ?A] =>
let H := fresh "H" in int_simpl_mod A H;
rewrite (int_modm_repr_eq A _ H);
clear H
| |- context [?A mod Ptrofs.modulus] =>
let H := fresh "H" in int_simpl_mod A H;
rewrite (int_modm_mod_eq A _ H);
clear H
| |- context [Int.repr ?A] =>
let H := fresh "H" in int_simpl_mod A H;
rewrite (int_modm_repr_eq A _ H);
clear H
| |- context [?A mod Ptrofs.modulus] =>
let H := fresh "H" in ptrofs_simpl_mod A H;
rewrite (ptrofs_modm_mod_eq A _ H);
clear H
| |- context [Ptrofs.repr ?A] =>
let H := fresh "H" in ptrofs_simpl_mod A H;
rewrite (ptrofs_modm_repr_eq A _ H);
clear H
| |- context [?A mod Ptrofs.modulus] =>
let H := fresh "H" in ptrofs_simpl_mod A H;
rewrite (ptrofs_modm_mod_eq A _ H);
clear H
| |- context [Ptrofs.repr ?A] =>
let H := fresh "H" in ptrofs_simpl_mod A H;
rewrite (ptrofs_modm_repr_eq A _ H);
clear H
end;
unfold int_modm, int_reprm, ptrofs_modm, ptrofs_reprm in *.
(**************************************************  List lemmas  **************************************************)

Lemma mul64_repr:
forall x y, Int64.mul (Int64.repr x) (Int64.repr y) = Int64.repr (x * y).