Ltac const_equation x :=
  let y := eval compute in x
   in exact (x = y).Ltac Zground X :=
  match X with
  | Z0 => idtac
  | Zpos ?y => Zground y
  | Zneg ?y => Zground y 
  | xH => idtac
  | xO ?y => Zground y
  | xI ?y => Zground y
 end.Ltac natground X :=
  match X with O => idtac | S ?Y => natground Y end.Ltac compute_Z_of_nat :=
 repeat
  match goal with
  | H: context [Z.of_nat ?n] |- _ => 
          natground n; 
          let z := constr:(Z.of_nat n) in let y := eval hnf in z 
           in change z with y in *
  | |- context [Z.of_nat ?n] => 
          natground n; 
          let z := constr:(Z.of_nat n) in let y := eval hnf in z 
           in change z with y in *
   end.(*
Ltac pose_const_equation X :=
 match goal with
 | H: X = ?Y |- _ => Zground Y
 | _ => let z := eval compute in X in assert (X = z) by reflexivity
 end.
*)

Ltac pose_const_equation X :=
 match goal with
 | H: X = ?Y |- _ => Zground Y
 | _ => let z := eval compute in X in 
            match z with context C [Archi.ptr64] =>
                       first [
                           unify Archi.ptr64 false; let u := context C [false] in let u := eval compute in u in change X with u in *
                          |unify Archi.ptr64 true; let u := context C [true] in let u := eval compute in u in change X with u in *
                      ]
              | _ => change X with z in *
            end
 end.Ltac perhaps_post_const_equation X :=
 lazymatch goal with 
 | H: context [X] |- _ => pose_const_equation X
(* | H:= context [X] |- _ => pose_const_equation X *)
 | |- context [X] => pose_const_equation X
 | |- _ => idtac
 end.Ltac pose_const_equations L :=
 match L with
 | ?X :: ?Y => perhaps_post_const_equation X; pose_const_equations Y
 | nil => idtac
 end.Ltac pose_standard_const_equations :=
pose_const_equations
  [
  Int.zwordsize; Int.modulus; Int.half_modulus; Int.max_unsigned; Int.max_signed; Int.min_signed;
  Int64.zwordsize; Int64.modulus; Int64.half_modulus; Int64.max_unsigned; Int64.max_signed; Int64.min_signed;
  Ptrofs.zwordsize; Ptrofs.modulus; Ptrofs.half_modulus; Ptrofs.max_unsigned; Ptrofs.max_signed; Ptrofs.min_signed;
  Byte.min_signed; Byte.max_signed; Byte.max_unsigned; Byte.modulus
  ];
 pose_const_equations [Int.wordsize; Int64.wordsize; Ptrofs.wordsize].Ltac pose_lemma F A L :=
  match type of (L A) with ?T =>
     lazymatch goal with
      | H:  T |- _ => fail
      | H:  T /\ _ |- _ => fail
      | |- _ => pose proof (L A)
     end
  end.Ltac pose_lemmas F L :=
 repeat
  match goal with
  | |- context [F ?A] => pose_lemma F A L
  | H: context [F ?A] |- _ => pose_lemma F A L
 end.Ltac rep_omega_setup := 
 repeat match goal with
            |  x:= _ : Z |- _ => subst x
            |  x:= _ : nat |- _ => subst x
            |  x:= _ |- _ => clearbody x
            end;
  try autorewrite with rep_omega in *;
  unfold repable_signed in *;
  compute_Z_of_nat;
  pose_Zlength_nonneg;
  pose_lemmas Byte.unsigned Byte.unsigned_range;
  pose_lemmas Byte.signed Byte.signed_range;
  pose_lemmas Int.unsigned Int.unsigned_range;
  pose_lemmas Int.signed Int.signed_range;
  pose_lemmas Int64.unsigned Int64.unsigned_range;
  pose_lemmas Int64.signed Int64.signed_range;
  pose_lemmas Ptrofs.unsigned Ptrofs.unsigned_range;
  pose_standard_const_equations.Ltac rep_omega_setup2 := idtac.Ltac rep_omega2 := 
 repeat  match goal with
  | |- _ /\ _ => match goal with
                        | |- context [Z.of_nat] => split
                        | |- context [Z.to_nat] => split
                        end
            end;
  match goal with
  | |- (_ >= _)%nat => apply <- Nat2Z.inj_ge
  | |- (_ > _)%nat => apply <- Nat2Z.inj_gt
  | |- (_ <= _)%nat => apply <- Nat2Z.inj_le
  | |- (_ < _)%nat => apply <- Nat2Z.inj_lt
  | |- @eq nat _ _ => apply Nat2Z.inj
  | |- _ => idtac
  end;
  repeat rewrite ?Nat2Z.id, ?Nat2Z.inj_add, ?Nat2Z.inj_mul, 
         ?Z2Nat.id, ?Nat2Z.inj_sub, ?Z2Nat.inj_sub,
         ?Z2Nat.inj_add by rep_omega2;
(*    simpl; *)
   omega.Ltac rep_omega :=
   rep_omega_setup;
   rep_omega_setup2;
   rep_omega2.

(* Specifications: *)
Lemma Vubyte_injective i j (H: Vubyte i = Vubyte j): i=j.
Lemma map_Vubyte_injective: forall l m, map Vubyte l = map Vubyte m -> l=m.
Lemma Vbyte_injective a b (H: Vbyte a = Vbyte b): a=b.
Lemma Znth_map_Vbyte: forall (i : Z) (l : list byte), 0 <= i < Zlength l -> Znth i (map Vbyte l) = Vbyte (Znth i l).