Local Open Scope logic.
Opaque Snuffle20. Opaque Snuffle.Snuffle. Opaque prepare_data.
Opaque fcore_result.
(* Lemma L32_spec_ok: semax_body SalsaVarSpecs SalsaFunSpecs f_L32 L32_spec.  Lemma lendian_nil: lendian [] = 0. Proof. reflexivity. Qed. Lemma lendian_singleton b: lendian [b] = Byte.unsigned b. Proof. simpl; omega. Qed.  Lemma lendian_app: forall l1 l2, lendian (l1++l2) = lendian l1 + 2^(8*Zlength l1) * lendian l2.  Lemma lendian_range: forall l, 0 <= lendian l < 2^(8*Zlength l).  Definition bendian l: Z := lendian (rev l). Lemma bendian_nil: bendian [] = 0. Proof. reflexivity. Qed. Lemma bendian_singleton b: bendian [b] = Byte.unsigned b. Proof. unfold bendian. simpl; omega. Qed.  Lemma bendian_app l1 l2: bendian (l1++l2) = bendian l2 + 2^(8*Zlength l2) * bendian l1.  Lemma Byte_unsigned_range_32 b: 0 <= Byte.unsigned b <= Int.max_unsigned.  Lemma dl64_spec_ok: semax_body SalsaVarSpecs SalsaFunSpecs f_dl64 dl64_spec.  Lemma div_bound u n (N:1<n): 0 <= Int.unsigned u / n <= Int.max_unsigned.  Lemma ST32_spec_ok: semax_body SalsaVarSpecs SalsaFunSpecs f_st32 st32_spec.  Lemma unsigned_repr' z (Q: 0 <= z < Byte.modulus): Byte.unsigned (Byte.repr z) = z. (* Lemma TS64_spec_ok: semax_body SalsaVarSpecs SalsaFunSpecs f_ts64 ts64_spec.   rewrite Int.repr_unsigned; trivial. rewrite ZW; omega. assert (0 <= ((Int.unsigned u mod Z.pow_pos 2 24) mod Z.pow_pos 2 16) mod Z.pow_pos 2 8 < Byte.modulus). apply Z_mod_lt. cbv; trivial. unfold Byte.max_unsigned. omega. } destruct (zeq i 6). { subst; simpl in *. unfold Znth; simpl. (*assert ((56 <= 56)%positive) by apply Pos.le_refl. specialize (B1 _ H); clear H. rewrite Z.pow_pos_fold in B1.*)
rewrite ! shru_shru, ADD48.
+ rewrite Int64.shru_div_two_p, (Int64.unsigned_repr 48), two_p_correct.
2: unfold Int64.max_unsigned; simpl; omega.
assert (QQ:= (UBND 48 16 (eq_refl _))%positive).
rewrite ! Z.pow_pos_fold in QQ.
rewrite Int64.unsigned_repr.
2:{ assert (2 ^ 16 < Int64.max_unsigned) by (cbv; trivial). omega. f_equal; f_equal. }
unfold bigendian64_invert in HeqU; inv HeqU. simpl.
destruct (Int64.unsigned_range u).
destruct (zlt (Int64.unsigned u) (Z.pow_pos 2 56)).
- rewrite Zmod_small by omega. rewrite ! Z.pow_pos_fold.
assert (0<= Int64.unsigned u / 2 ^ 48 < 2^8).
{ split; try omega. apply Zdiv_lt_upper_bound; trivial. }
(*rewrite Int.unsigned_repr. 2: change Byte.max_unsigned with (2^8-1) in UNS_B_I; omega.*)
rewrite Byte.unsigned_repr. 2: change Byte.max_unsigned with (2^8-1); omega.
rewrite zero_ext_inrange; trivial.
rewrite Int.unsigned_repr. 2: change Byte.max_unsigned with (2^8-1) in UNS_B_I; omega.
change (two_p 8) with (2^8); omega.
- specialize (Fcore_Zaux.Zdiv_mod_mult (Int64.unsigned u) (Z.pow_pos 2 48) (Z.pow_pos 2 8)); intros.
change ((Z.pow_pos 2 48 * Z.pow_pos 2 8)%Z) with (Z.pow_pos 2 56) in H1.
rewrite H1. rewrite Byte.unsigned_repr. 2:{ destruct (Z_mod_lt (Int64.unsigned u / Z.pow_pos 2 48) (Z.pow_pos 2 8)). cbv; trivial. }
change Byte.max_unsigned with (Z.pow_pos 2 8 -1). omega.
unfold Int.zero_ext.
clear - H1; rewrite int_max_unsigned_eq; split; try omega. specialize (Fcore_Zaux.Zpower_pos_gt_0 2 n); omega.
rewrite <- Zpower_pos_is_exp, H.
change Int64.modulus with (Z.pow_pos 2 64) in H1; trivial.
rewrite (Zdiv_small (Int64.unsigned u mod Z.pow_pos 2 56)).
2:{ specialize (Zmod_unique (Int64.unsigned u) (Z.pow_pos 2 56)); intros.
rewrite Int.unsigned_repr.
2:{ assert (2 ^ 16 < Int64.max_unsigned) by (cbv; trivial). omega. }
unfold Int.zero_ext. f_equal. f_equal. }
apply Byte.equal_same_bits; intros. rewrite Int.Zzero_ext_spec by omega.
unfold bigendian64_invert in HeqU; inv HeqU. simpl.
specialize (Zmod_recombine (Int64.unsigned u) (Z.pow_pos 2 8) (Z.pow_pos 2 48)). intros.
replace (Z.pow_pos 2 8 * Z.pow_pos 2 48)%Z with (Z.pow_pos 2 56) in H0.
rewrite H0.
destruct (zlt i 8).
rewrite <- (Byte.testbit_repr (Byte.unsigned b2)), Byte.repr_unsigned. unfold Byte.testbit.
rewrite if_true. by omega.
rewrite Int64.unsigned_repr.
unfold Int.zero_ext. rewrite Int.unsigned_repr.
unfold Int.zero_ext. f_equal. f_equal.
rewrite Int64.unsigned_repr by omega.
rewrite zero_ext_inrange. f_equal; f_equal.
- unfold bigendian64_invert in HeqU; inv HeqU.
rewrite Byte.unsigned_repr. reflexivity. rewrite Z.pow_pos_fold. omega.
- rewrite Int.unsigned_repr. apply B1. omega.
+ rewrite ADD48. rewrite 2 Int64.unsigned_repr; unfold Int64.max_unsigned; simpl; omega.
+ rewrite ADD40. rewrite 2 Int64.unsigned_repr; unfold Int64.max_unsigned; simpl; omega.
+ rewrite ADD32. rewrite 2 Int64.unsigned_repr; unfold Int64.max_unsigned; simpl; omega.
+ rewrite ADD24. rewrite 2 Int64.unsigned_repr; unfold Int64.max_unsigned; simpl; omega.
+ rewrite ADD16. rewrite 2 Int64.unsigned_repr; unfold Int64.max_unsigned; simpl; omega.
+ rewrite ! Int64.unsigned_repr; unfold Int64.max_unsigned; simpl; omega. }
+ rewrite ! Int64.add_unsigned. rewrite ! Int64.unsigned_repr; simpl; unfold Int64.max_unsigned; simpl; try omega.
+ }
rewrite two_p_correct. rewrite Z.pow_pos_fold in B1. omega.
unfold Int64.max_unsigned; simpl; omega.
rewrite Int64.shru_div_two_p.  UNSB_I64.  <- two_power_nat_two_p. omega. apply B1; apply  Pos.le_refl. cbv. omega. myadmit.  myadmit.  myadmit.  myadmit.  myadmit.
myadmit.  myadmit.  myadmit.  myadmit.  myadmit. }
destruct (zeq i 6).
{ subst; simpl in *. unfold Znth; simpl.
rewrite ! shru_shru.
replace (Int64.add (Int64.repr 8)
(Int64.add (Int64.repr 8)
(Int64.add (Int64.repr 8)
(Int64.add (Int64.repr 8) (Int64.add (Int64.repr 8) (Int64.repr 8))))))
with (Int64.repr 48) by reflexivity.
rewrite zero_ext_inrange. f_equal; f_equal.
unfold bigendian64_invert in HeqU; inv HeqU.
rewrite Int64.shru_div_two_p.
rewrite (Int64.unsigned_repr 48).
rewrite Int64.unsigned_repr.
rewrite Byte.unsigned_repr.x
specialize (Fcore_Zaux.Zdiv_mod_mult (Int64.unsigned u) (Z.pow_pos 2 8) (Z.pow_pos 2 48) ). intros.
replace (Z.pow_pos 2 8 * Z.pow_pos 2 48)%Z with (Z.pow_pos 2 56) in H by reflexivity.
rewrite H.
specialize (Fcore_Zaux.Zdiv_mod_mult). (Int64.unsigned u) (Z.pow_pos 2 40) (Z.pow_pos 2 8)). intros.
replace (Z.pow_pos 2 40 * Z.pow_pos 2 8)%Z with (Z.pow_pos 2 48) in H0 by reflexivity.
intros.
replace (Z.pow_pos 2 48 * Z.pow_pos 2 8)%Z with (Z.pow_pos 2 56) in H by reflexivity.
rewrite H.  reflexivity. myadmit.  myadmit.  myadmit.  myadmit.  myadmit.
myadmit.  myadmit.  myadmit.  myadmit.  myadmit. }
unfold Int64.shru.  simpl. ! Int64.add_unsigned. (Int64.unsigned_repr 8).
rewrite if_false by omega.
unfold Znth; simpl.
rewrite if_false by omega. destruct (Int64.unsigned_range_2 u).
unfold bigendian64_invert in HeqU. inv HeqU.
assert (BMU: Byte.max_unsigned = 255) by reflexivity.
assert (I64MU: Int64.max_unsigned = Z.pow 2 64 -1) by reflexivity.
rewrite iter64. 2: rewrite Z2Nat.id; omega.
unfold iter64Shr8'. rewrite Z2Nat.id; try omega.
rewrite Int64.mul_signed.
rewrite 2 Int64.signed_repr; try (unfold Int64.min_signed, Int64.max_signed; simpl; omega).
rewrite Int64.shru_div_two_p, (Int64.unsigned_repr (8 * i)). 2: unfold Int64.max_unsigned; simpl; omega.
assert (GT:= two_p_gt_ZERO (8*i)).
assert (BND1: 0 <= Int64.unsigned u / Z.pow_pos 2 56 < Byte.modulus).
{ split. apply Z_div_pos; trivial. cbv; trivial.
apply Z.div_lt_upper_bound. cbv; trivial. simpl in *. omega. }
(*  assert (BND1: 0 <= Int64.unsigned u / Z.pow_pos 2 56 < Byte.max_unsigned). { split. apply Z_div_pos; trivial. cbv; trivial. assert (Int64.unsigned u / Z.pow_pos 2 56 < Byte.modulus). 2: unfold Byte.max_unsigned; omega. apply Z.div_lt_upper_bound. cbv; trivial. simpl in *. omega. }*)
(*assert (BND1: 0 <= Int64.unsigned u / Z.pow_pos 2 56 < Byte.modulus). { split. apply Z_div_pos; trivial. cbv; trivial. apply Z.div_lt_upper_bound. cbv; trivial. simpl in *. omega. }*)
rewrite unsigned_repr'; trivial.
(*  rewrite Int64.unsigned_repr. 2:{ split. apply Z_div_pos; trivial. omega. apply Z.div_le_upper_bound. omega. eapply Z.le_trans; eauto. specialize (Zmult_le_compat_r 1 (two_p (8 * i)) Int64.max_unsigned). simpl. intros Q; apply Q; omega.*)
rewrite unsigned_repr'.
2:{ split.  apply Z_div_pos; trivial. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Z.div_lt_upper_bound. cbv; trivial.
eapply Z.lt_le_trans. apply Z_mod_lt. cbv; trivial. cbv; congruence.
rewrite unsigned_repr'.
2:{ split.  apply Z_div_pos; trivial. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Z.div_lt_upper_bound. cbv; trivial.
eapply Z.lt_le_trans. apply Z_mod_lt. cbv; trivial. cbv; congruence.
rewrite unsigned_repr'.
2:{ split.  apply Z_div_pos; trivial. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Z.div_lt_upper_bound. cbv; trivial.
eapply Z.lt_le_trans. apply Z_mod_lt. cbv; trivial. cbv; congruence.
rewrite unsigned_repr'.
2:{ split.  apply Z_div_pos; trivial. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Z.div_lt_upper_bound. cbv; trivial.
eapply Z.lt_le_trans. apply Z_mod_lt. cbv; trivial. cbv; congruence.
rewrite unsigned_repr'.
2:{ split.  apply Z_div_pos; trivial. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Z.div_lt_upper_bound. cbv; trivial.
eapply Z.lt_le_trans. apply Z_mod_lt. cbv; trivial. cbv; congruence.
rewrite unsigned_repr'.
2:{ split.  apply Z_div_pos; trivial. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Z.div_lt_upper_bound. cbv; trivial.
eapply Z.lt_le_trans. apply Z_mod_lt. cbv; trivial. cbv; congruence.
rewrite unsigned_repr'.
2:{ split.  apply Z_mod_lt. cbv; trivial. apply Z_mod_lt. cbv; trivial.
assert (BND: 0 <= Int64.unsigned u / Z.pow_pos 2 56 <= Byte.max_unsigned).
{ unfold Byte.max_unsigned; omega. }
assert (IMU: Int.max_unsigned = 4294967295) by reflexivity.
destruct (zeq i 7).
{ subst; simpl in *. rewrite two_power_pos_correct, zero_ext_inrange.
+ rewrite Int64.unsigned_repr; trivial.
split. apply Z_div_pos; trivial. cbv; trivial.
apply Z.div_le_upper_bound. cbv; trivial.
eapply Z.le_trans; eauto.
+ rewrite Int.unsigned_repr, Int64.unsigned_repr. apply BND. omega.
rewrite Int64.unsigned_repr. omega. omega. }
destruct (zeq i 6).
{ subst; simpl in *. rewrite two_power_pos_correct, zero_ext_inrange.
specialize (Fcore_Zaux.Zdiv_mod_mult (Int64.unsigned u) (Z.pow_pos 2 48) (Z.pow_pos 2 8)).
rewrite <- Zpower_pos_is_exp. intros Q.
replace (Z.pow_pos 2 (48 + 8)) with (Z.pow_pos 2 56) in Q by reflexivity.
rewrite Q. rewrite Zmod_small; trivial. f_equal. f_equal.  simpl. reflexivity.
rewrite Int.unsigned_repr; simpl in *; omega. }
omega.
replace Byte.modulus with (two_p 8) in BND1 unfold Byte.modulus in BND1. simpl in *. cbv. unfold Int.zero_ext. rewrite Int.unsigned_repr.
apply Z.div_lt_upper_bound. cbv; trivial.
eapply Z.lt_le_trans. apply Z_mod_lt. cbv; trivial. cbv; congruence.
. omega. cbv.
specialize (Zmult_le_compat_r 1 (two_p (8 * i)) Int64.max_unsigned). simpl.
intros Q; apply Q; omega.
rewrite zero_ext_inrange.
2:{ rewrite Int.unsigned_repr.
assert (Int64.unsigned u / two_p (8 * i) < two_p 8). 2: omega.
apply Z.div_lt_upper_bound. omega.
assert (Int64.max_unsigned < two_p (8 * i) * two_p 8). 2: omega.
rewrite 2 two_p_equiv, Z.pow_mul_r, I64MU; try omega.
specialize (Zpower_exp (2^8) i 1); rewrite Z.pow_1_r.
intros Q; rewrite <- Q. simpl. omega. simpl.
simpl in *. omega. split. apply Z_div_pos; trivial. cbv; trivial.
assert (Int64.unsigned u / Z.pow_pos 2 56 < Byte.modulus). 2: unfold Byte.max_unsigned; omega.
apply Z.div_lt_upper_bound. cbv; trivial. simpl in *. omega.
destruct (zeq i 7). { subst. simpl in *. rewrite zero_ext_inrange. rewrite Byte.unsigned_repr. reflexivity.
{ split. apply Z_div_pos; trivial. cbv; trivial.
assert (Int64.unsigned u / Z.pow_pos 2 56 < Byte.modulus). 2: unfold Byte.max_unsigned; omega.
apply Z.div_lt_upper_bound. cbv; trivial. simpl. omega. }
eapply Z.le_trans; eauto. rewrite I64MU. simpl. clear. cbv. omega.
unfold omega.  simpl. omega.  Zdiv_interval_2.
destruct (zeq i 0); subst; simpl. rewrite Byte.unsigned_repr. myadmit.
+ f_equal. rewrite iter64. 2: rewrite Z2Nat.id; omega.
unfold iter64Shr8'. rewrite Z2Nat.id; try omega.
unfold Int64.mul. rewrite 2 Int64.unsigned_repr.
2: unfold Int64.max_unsigned; simpl; omega.
2: unfold Int64.max_unsigned; simpl; omega.
rewrite Int64.shru_div_two_p.
rewrite (Int64.unsigned_repr (8 * i)), two_p_equiv.
2: unfold Int64.max_unsigned; simpl; omega.
assert (X: 0 < 2 ^ (8 * i)) by (apply Z.pow_pos_nonneg; omega).
destruct (Int64.unsigned_range_2 u).
assert (T: 0 <= Int64.unsigned u / 2 ^ (8 * i) <= 255).
{ split. apply Z_div_pos. omega. omega.
apply Zdiv_le_upper_bound; trivial. eapply Z.le_trans. apply H0.
unfold Int64.max_unsigned. rewrite Int64.modulus_power.
replace (two_p Int64.zwordsize) with (2^64) by reflexivity.
assert (2 ^ 64 < 255 * 2 ^ (8 * i)). 2: omega.
specialize (Zmult_le_compat_l 1 (2 ^ (8 * i)) Int64.max_unsigned).
rewrite Z.mul_1_r. intros Y; apply Y. omega. unfold Int64.max_unsigned; simpl; omega. }
assert (Q: 0 <= Int64.unsigned u / 2 ^ (8 * i) <= Int64.max_unsigned).
{ split. apply Z_div_pos. omega. omega.
apply Zdiv_le_upper_bound; trivial. eapply Z.le_trans. apply H0.
specialize (Zmult_le_compat_l 1 (2 ^ (8 * i)) Int64.max_unsigned).
rewrite Z.mul_1_r. intros Y; apply Y. omega. unfold Int64.max_unsigned; simpl; omega. }
rewrite Int64.unsigned_repr; trivial.
rewrite zero_ext_inrange. f_equal. myadmit.
rewrite Int.unsigned_repr. replace (two_p 8 - 1) with 255 by reflexivity.
replace (1 + (7 - i)) with (8-i) by omega. replace (i + (8 - i)) with 8 by omega.
destruct (zeq i 0).
{ subst; unfold sublist;  simpl. unfold littleendian64_invert in HeqU.
inv HeqU.
rewrite <- app_comm_cons. (sublist_app1 _ 0 i). 2: omega. 2: rewrite Zlength_sublist. omega.
rewrite <- app_assoc.
assert (ZW: Int.zwordsize = 32) by reflexivity.
assert (EIGHT: Int.unsigned (Int.repr 8) = 8). apply Int.unsigned_repr. rewrite int_max_unsigned_eq; omega.
inv HeqU. clear - ZW EIGHT I. simpl.
destruct (zeq i 0); subst; simpl. f_equal. f_equal.
{ rewrite Byte.unsigned_repr.
rewrite (Fcore_Zaux.Zmod_mod_mult _ (2^8) (2^8)). 2: cbv; trivial. 2: cbv; intros; discriminate.
rewrite (Fcore_Zaux.Zmod_mod_mult _ (2^16) (2^8)). 2: cbv; trivial. 2: cbv; intros; discriminate.
rewrite <- (Int.zero_ext_mod 8).
rewrite Int.repr_unsigned; trivial.
rewrite ZW; omega.
assert (0 <= ((Int.unsigned u mod Z.pow_pos 2 24) mod Z.pow_pos 2 16) mod Z.pow_pos 2 8 < Byte.modulus).
apply Z_mod_lt. cbv; trivial.
unfold Byte.max_unsigned. omega. }
destruct (zeq i 1); subst; simpl. f_equal. f_equal. f_equal.
{ rewrite Byte.unsigned_repr.
2:{ assert (0 <= (Int.unsigned u mod Z.pow_pos 2 24) mod Z.pow_pos 2 16 / Z.pow_pos 2 8 < Byte.modulus).
2:{ unfold Byte.max_unsigned. omega.
split. apply Z_div_pos. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Zdiv_lt_upper_bound. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Int.same_bits_eq. rewrite ZW; intros.
rewrite Int.bits_zero_ext, Int.testbit_repr; try apply H.
rewrite (Z.div_pow2_bits _ 8); try omega.
rewrite (Int.Ztestbit_mod_two_p 16); try omega.
rewrite (Int.Ztestbit_mod_two_p 24); try omega.
rewrite Int.bits_shru; try omega. rewrite EIGHT, ZW, Ztest_Inttest.
remember (zlt i 8).
destruct s. repeat rewrite zlt_true. trivial. omega. omega. omega.
rewrite zlt_false. trivial. omega. }
destruct (zeq i 2); subst; simpl. f_equal. f_equal. f_equal.
f_equal.
{ rewrite Byte.unsigned_repr.
2:{ assert (0 <= Int.unsigned u mod Z.pow_pos 2 24 / Z.pow_pos 2 16 < Byte.modulus).
2: unfold Byte.max_unsigned; omega.
split. apply Z_div_pos. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Zdiv_lt_upper_bound. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Int.same_bits_eq. rewrite ZW; intros.
rewrite Int.bits_zero_ext, Int.testbit_repr; try apply H.
rewrite Int.bits_shru; try omega. rewrite EIGHT, ZW.
rewrite (Z.div_pow2_bits _ 16); try omega.
rewrite (Int.Ztestbit_mod_two_p 24); try omega.
rewrite Ztest_Inttest.
remember (zlt i 8).
destruct s. repeat rewrite zlt_true. rewrite Int.bits_shru, EIGHT, ZW.
rewrite zlt_true. rewrite <- Z.add_assoc. reflexivity. omega. omega. omega. omega.
rewrite zlt_false. trivial. omega. }
destruct (zeq i 3); subst; simpl. f_equal. f_equal. f_equal. f_equal.
f_equal.
{ rewrite Byte.unsigned_repr.
2:{ assert (0 <= Int.unsigned u / Z.pow_pos 2 24 < Byte.modulus).
2: unfold Byte.max_unsigned; omega.
split. apply Z_div_pos. cbv; trivial. apply Int.unsigned_range.
apply Zdiv_lt_upper_bound. cbv; trivial. apply Int.unsigned_range.
apply Int.same_bits_eq. rewrite ZW; intros.
rewrite Int.bits_zero_ext, Int.testbit_repr; try apply H.
rewrite Int.bits_shru; try omega. rewrite EIGHT, ZW.
rewrite (Z.div_pow2_bits _ 24); try omega.
rewrite Ztest_Inttest.
remember (zlt i 8).
destruct s. rewrite zlt_true. rewrite Int.bits_shru, EIGHT, ZW.
rewrite zlt_true. rewrite Int.bits_shru, EIGHT, ZW.
rewrite zlt_true. repeat rewrite <- Z.add_assoc. reflexivity. omega. omega. omega. omega. omega.
rewrite Int.bits_above. trivial. omega. }
omega. }
Time forward. (*1.6*)
Time Qed. (*4.9*)
unfold data_at_, field_at_.
rewrite field_at_data_at.
rewrite field_address_offset by auto with field_compatible. simpl.
rewrite isptr_offset_val_zero. apply data_at_ext. unfold default_val. simpl. unfold tarray. simpl.   destruct tv. reflexivity. cancel. rewrite unfold field_address; simpl. normalize. cancel. }
forward_for (EX z:_,
(PROP (0<= z <= 7 )
LOCAL (temp _i (Vint (Int.repr z)); temp _x x;
temp _u (Vlong u))
SEP (data_at Tsh (tarray tuchar 8) (Data z) x))).
{ Exists 7. entailer!. myadmit. (*Data 7 = list_repeat 8 Vundef*) }
eapply semax_for with (A:=Z)(v:= fun a => Val.of_bool (negb (Int.lt (Int.repr a) (Int.repr 0)))).
solve [ reflexivity].
intros. solve [entailer!].
intros. entailer!.
{ intros i. simpl. normalize. rename H into I0. rename H0 into I7.
apply negb_true_iff in I0. (* apply lt_repr_false in I0.
2: red; unfold Int.min_signed, Int.max_signed; simpl. 2: split; try omega. 2:{
2: red; unfold Int.min_signed, Int.max_signed; simpl; omega.*)
forward.
{ apply andp_right. 2: solve [entailer].
apply andp_right. solve [entailer!].
entailer. myadmit. (*typecheck_error (invalid_cast_result tuchar tuchar)*) }
forward. entailer. simpl. myadmit. (*typecheck_error
(arg_type
(Ebinop Oshr (Etempvar _u tulong) (Econst_int (Int.repr 8) tint)
tulong))*)
unfold arg_type.
go_lower. entailer!. Search invalid_cast_result. unfold invalid_cast_result. typecheck_error. simpl.  simpl. destruct (zlt
{ apply extract_exists_pre. intros i. Intros. rename H into I.
cancel. 2:{ eapply semax_for with (A:=Z).
reflexivity.
Ltac forward_for_simple_bound n Pre ::=
check_Delta;
repeat match goal with |-
semax _ _ (Ssequence (Ssequence (Ssequence _ _) _) _) _ =>
apply -> seq_assoc; abbreviate_semax
end. (*
first [
match type of n with
?t => first [ unify t Z | elimtype (Type_of_bound_in_forward_for_should_be_Z_but_is t)]
end;
match type of Pre with
?t => first [unify t (environ -> mpred); fail 1 | elimtype (Type_of_invariant_in_forward_for_should_be_environ_arrow_mpred_but_is t)]
end
| simple eapply semax_seq';
[forward_for_simple_bound' n Pre
| cbv beta; simpl update_tycon; abbreviate_semax  ]
| eapply semax_post_flipped';
[forward_for_simple_bound' n Pre
| ]
].*)
Time forward_for_simple_bound 8 (EX i:Z,
(PROP  ()
LOCAL (temp _x x; temp _u (Vlong (iter64Shr8 u (Z.to_nat i))))
SEP (data_at Tsh (tarray tuchar 8)
(sublist 0 i (map Vint (map Int.repr (map Byte.unsigned ([w0;w1;w2;w3;u0;u1;u2;u3])))) ++
list_repeat (Z.to_nat(8-i)) Vundef)
x))).
{ entailer!. }
{ rename H into I.
Time assert_PROP (field_compatible (Tarray tuchar 4 noattr) [] x /\ isptr x)
as FC_ptrX by solve [entailer!]. (*2.3*)
destruct FC_ptrX as [FC ptrX].
Time forward. (*3.2*)
Time forward. (*0.8*)
rewrite Z.add_comm, Z2Nat.inj_add; try omega.
Time entailer!. (*1.5*)
unfold upd_Znth.
autorewrite with sublist.
rewrite field_at_data_at. simpl. unfold field_address. simpl.
if_tac. 2: solve [contradiction].
replace (4 - (1 + i)) with (4-i-1) by omega.
rewrite isptr_offset_val_zero; trivial. clear H.
apply data_at_ext. rewrite Zplus_comm.
assert (ZW: Int.zwordsize = 32) by reflexivity.
assert (EIGHT: Int.unsigned (Int.repr 8) = 8). apply Int.unsigned_repr. rewrite int_max_unsigned_eq; omega.
inv HeqU. clear - ZW EIGHT I.
destruct (zeq i 0); subst; simpl. f_equal. f_equal.
{ rewrite Byte.unsigned_repr.
rewrite (Fcore_Zaux.Zmod_mod_mult _ (2^8) (2^8)). 2: cbv; trivial. 2: cbv; intros; discriminate.
rewrite (Fcore_Zaux.Zmod_mod_mult _ (2^16) (2^8)). 2: cbv; trivial. 2: cbv; intros; discriminate.
rewrite <- (Int.zero_ext_mod 8).
rewrite Int.repr_unsigned; trivial.
rewrite ZW; omega.
assert (0 <= ((Int.unsigned u mod Z.pow_pos 2 24) mod Z.pow_pos 2 16) mod Z.pow_pos 2 8 < Byte.modulus).
apply Z_mod_lt. cbv; trivial.
unfold Byte.max_unsigned. omega. }
destruct (zeq i 1); subst; simpl. f_equal. f_equal. f_equal.
{ rewrite Byte.unsigned_repr.
2:{ assert (0 <= (Int.unsigned u mod Z.pow_pos 2 24) mod Z.pow_pos 2 16 / Z.pow_pos 2 8 < Byte.modulus).
2:{ unfold Byte.max_unsigned. omega.
split. apply Z_div_pos. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Zdiv_lt_upper_bound. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Int.same_bits_eq. rewrite ZW; intros.
rewrite Int.bits_zero_ext, Int.testbit_repr; try apply H.
rewrite (Z.div_pow2_bits _ 8); try omega.
rewrite (Int.Ztestbit_mod_two_p 16); try omega.
rewrite (Int.Ztestbit_mod_two_p 24); try omega.
rewrite Int.bits_shru; try omega. rewrite EIGHT, ZW, Ztest_Inttest.
remember (zlt i 8).
destruct s. repeat rewrite zlt_true. trivial. omega. omega. omega.
rewrite zlt_false. trivial. omega. }
destruct (zeq i 2); subst; simpl. f_equal. f_equal. f_equal.
f_equal.
{ rewrite Byte.unsigned_repr.
2:{ assert (0 <= Int.unsigned u mod Z.pow_pos 2 24 / Z.pow_pos 2 16 < Byte.modulus).
2: unfold Byte.max_unsigned; omega.
split. apply Z_div_pos. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Zdiv_lt_upper_bound. cbv; trivial. apply Z_mod_lt. cbv; trivial.
apply Int.same_bits_eq. rewrite ZW; intros.
rewrite Int.bits_zero_ext, Int.testbit_repr; try apply H.
rewrite Int.bits_shru; try omega. rewrite EIGHT, ZW.
rewrite (Z.div_pow2_bits _ 16); try omega.
rewrite (Int.Ztestbit_mod_two_p 24); try omega.
rewrite Ztest_Inttest.
remember (zlt i 8).
destruct s. repeat rewrite zlt_true. rewrite Int.bits_shru, EIGHT, ZW.
rewrite zlt_true. rewrite <- Z.add_assoc. reflexivity. omega. omega. omega. omega.
rewrite zlt_false. trivial. omega. }
destruct (zeq i 3); subst; simpl. f_equal. f_equal. f_equal. f_equal.
f_equal.
{ rewrite Byte.unsigned_repr.
2:{ assert (0 <= Int.unsigned u / Z.pow_pos 2 24 < Byte.modulus).
2: unfold Byte.max_unsigned; omega.
split. apply Z_div_pos. cbv; trivial. apply Int.unsigned_range.
apply Zdiv_lt_upper_bound. cbv; trivial. apply Int.unsigned_range.
apply Int.same_bits_eq. rewrite ZW; intros.
rewrite Int.bits_zero_ext, Int.testbit_repr; try apply H.
rewrite Int.bits_shru; try omega. rewrite EIGHT, ZW.
rewrite (Z.div_pow2_bits _ 24); try omega.
rewrite Ztest_Inttest.
remember (zlt i 8).
destruct s. rewrite zlt_true. rewrite Int.bits_shru, EIGHT, ZW.
rewrite zlt_true. rewrite Int.bits_shru, EIGHT, ZW.
rewrite zlt_true. repeat rewrite <- Z.add_assoc. reflexivity. omega. omega. omega. omega. omega.
rewrite Int.bits_above. trivial. omega. }
omega. }
Time forward. (*1.6*)
Time Qed. (*4.9*)
*)
(* Definition L32_specZ := DECLARE _L32 WITH x : int, c: int PRE [ _x OF tuint, _c OF tint ] PROP () (*c=Int.zero doesn't seem to satisfy spec???*)
LOCAL (temp _x (Vint x); temp _c (Vint Int.zero))
SEP ()
POST [ tuint ]
PROP (True)
LOCAL ()
SEP ().
Definition LDZFunSpecs : funspecs :=
L32_specZ::nil.

Lemma L32_specZ_ok: semax_body SalsaVarSpecs LDZFunSpecs
f_L32 L32_specZ.