apply Z.mul_nonneg_nonneg; omega.
Qed.
(* Lemma data_at_ext {cs} sh t v v' p: v=v' -> @data_at cs sh t v p |-- @data_at cs sh t v' p.  Lemma split2_data_at_Tarray_at_tuchar_unfold {cs} sh n n1 v p: 0 <= n1 <= n -> @data_at cs sh (Tarray tuchar n noattr) v p |-- (@data_at cs sh (Tarray tuchar n1 noattr) (sublist 0 n1 v) p * at_offset (@data_at cs sh (Tarray tuchar (n - n1) noattr) (sublist n1 (Zlength v) v)) n1 p)%logic. Lemma split2_data_at_Tarray_at_tuchar_unfold_with_fc {cs} sh n n1 v p: 0 <= n1 <= n -> @data_at cs sh (Tarray tuchar n noattr) v p |-- !!(field_compatible (Tarray tuchar n noattr) [] p) && (@data_at cs sh (Tarray tuchar n1 noattr) (sublist 0 n1 v) p * at_offset (@data_at cs sh (Tarray tuchar (n - n1) noattr) (sublist n1 (Zlength v) v)) n1 p)%logic.  Lemma array_at_data_at1 {cs} : forall sh t gfs lo hi v p, field_compatible0 t (gfs SUB lo) p -> field_compatible0 t (gfs SUB hi) p -> @array_at cs sh t gfs lo hi v p = at_offset (@data_at cs sh (nested_field_array_type t gfs lo hi) (@fold_reptype _ (nested_field_array_type t gfs lo hi)  v)) (nested_field_offset2 t (ArraySubsc lo :: gfs)) p.  Lemma split2_data_at_Tarray_at_tuchar_fold {cs} sh n n1 v p: 0 <= n1 <= n -> n = Zlength v -> n < Int.modulus -> field_compatible (Tarray tuchar n noattr) [] p -> (@data_at cs sh (Tarray tuchar n1 noattr) (sublist 0 n1 v) p * at_offset (@data_at cs sh (Tarray tuchar (n - n1) noattr) (sublist n1 (Zlength v) v)) n1 p)%logic |-- @data_at cs sh (Tarray tuchar n noattr) v p.  Lemma split2_data_at_Tarray_at_tuchar {cs} sh n n1 v p: 0 <= n1 <= n -> n = Zlength v -> n < Int.modulus -> field_compatible (Tarray tuchar n noattr) [] p -> @data_at cs sh (Tarray tuchar n noattr) v p = (@data_at cs sh (Tarray tuchar n1 noattr) (sublist 0 n1 v) p * at_offset (@data_at cs sh (Tarray tuchar (n - n1) noattr) (sublist n1 (Zlength v) v)) n1 p)%logic.  Lemma append_split2_data_at_Tarray_at_tuchar {cs} sh n data1 data2 p: Zlength (data1++data2) < Int.modulus -> n = Zlength (data1++data2) -> field_compatible (Tarray tuchar n noattr) [] p -> @data_at cs sh (Tarray tuchar n noattr) (data1++data2) p = (@data_at cs sh (Tarray tuchar (Zlength data1) noattr) data1 p * at_offset (@data_at cs sh (Tarray tuchar (Zlength data2) noattr) data2) (Zlength data1) p)%logic.  (* Lemma split_offset_Tarray_at cs: forall n sh t len (contents: reptype (Tarray t len noattr)) v, legal_alignas_type t = true -> (Z.of_nat n <= Zlength contents)%Z -> (Z.of_nat n <= len)%Z -> @data_at cs sh (Tarray t len noattr) contents v = (!! (offset_in_range (sizeof t * 0) v) && !! (offset_in_range (sizeof t * len) v) && (data_at sh (Tarray t (Z.of_nat n) noattr) (firstn n contents) v * data_at sh (Tarray t (len- Z.of_nat n) noattr) (skipn n contents) (offset_val (Int.repr (sizeof t * Z.of_nat n)) v)))%logic. Lemma split3_data_at_Tarray_at_tuchar_unfold' {cs} sh n n1 n2 v p: n2 + n1 <= n <= Zlength v-> 0<= n1 -> 0<= n2 -> @data_at cs sh (Tarray tuchar n noattr) v p |-- (@data_at cs sh (Tarray tuchar n1 noattr) (sublist 0 n1 v) p * at_offset (@data_at cs sh (Tarray tuchar n2 noattr) (sublist n1 (n2 + n1) v)) n1 p * at_offset (@data_at cs sh (Tarray tuchar (Zlength v - (n2 + n1)) noattr) (sublist (n2 + n1) (Zlength v) v)) (n2 + n1)  p)%logic.  Lemma split3_data_at_Tarray_at_tuchar_fold {cs} sh n lo hi v p: 0 <= lo <= hi -> hi <= n -> n = Zlength v -> n < Int.modulus -> field_compatible (Tarray tuchar n noattr) [] p -> (@data_at cs sh (Tarray tuchar lo noattr) (sublist 0 lo v) p * at_offset (@data_at cs sh (Tarray tuchar (hi - lo) noattr) (sublist lo hi v)) lo p * at_offset (@data_at cs sh (Tarray tuchar (n - hi) noattr) (sublist hi (Zlength v) v)) hi p)%logic |-- @data_at cs sh (Tarray tuchar n noattr) v p. Lemma split3_data_at_Tarray_at_tuchar_fold' {cs} sh n n1 n2 v p: n2 + n1 <= n -> 0<= n1 -> 0<= n2 -> n=Zlength v -> n < Int.modulus -> field_compatible (Tarray tuchar n noattr) [] p -> (@data_at cs sh (Tarray tuchar n1 noattr) (sublist 0 n1 v) p * at_offset (@data_at cs sh (Tarray tuchar n2 noattr) (sublist n1 (n2 + n1) v)) n1 p * at_offset (@data_at cs sh (Tarray tuchar (Zlength v - (n2 + n1)) noattr) (sublist (n2+n1) (Zlength v) v)) (n2+n1) p)%logic |-- @data_at cs sh (Tarray tuchar n noattr) v p.  Lemma split3_data_at_Tarray_at_tuchar {cs} sh n n1 n2 v p: n2 + n1 <= n -> 0<= n1 -> 0<= n2 -> n=Zlength v -> n < Int.modulus -> field_compatible (Tarray tuchar n noattr) [] p -> @data_at cs sh (Tarray tuchar n noattr) v p = (@data_at cs sh (Tarray tuchar n1 noattr) (sublist 0 n1 v) p * at_offset (@data_at cs sh (Tarray tuchar n2 noattr) (sublist n1 (n2 + n1) v)) n1 p * at_offset (@data_at cs sh (Tarray tuchar (Zlength v - (n2 + n1)) noattr) (sublist (n2+n1) (Zlength v) v)) (n2+n1) p)%logic.  Lemma append_split3_data_at_Tarray_at_tuchar {cs} sh n data1 data2 data3 p: n = Zlength (data1++data2++data3) -> n < Int.modulus -> field_compatible (Tarray tuchar n noattr) [] p -> @data_at cs sh (Tarray tuchar n noattr) (data1++data2++data3) p = (@data_at cs sh (Tarray tuchar (Zlength data1) noattr) data1 p * at_offset (@data_at cs sh (Tarray tuchar (Zlength data2) noattr) data2) (Zlength data1) p * at_offset (@data_at cs sh (Tarray tuchar (Zlength data3) noattr) data3) (Zlength data2 + Zlength data1) p)%logic.  Lemma append_split3_data_at_Tarray_at_tuchar' {cs} sh data data1 data2 data3 p: data = data1++data2++data3 -> Zlength data < Int.modulus -> field_compatible (Tarray tuchar (Zlength data) noattr) [] p -> @data_at cs sh (Tarray tuchar (Zlength data) noattr) data p = (@data_at cs sh (Tarray tuchar (Zlength data1) noattr) data1 p * at_offset (@data_at cs sh (Tarray tuchar (Zlength data2) noattr) data2) (Zlength data1) p * at_offset (@data_at cs sh (Tarray tuchar (Zlength data3) noattr) data3) (Zlength data2 + Zlength data1) p)%logic. *)
(* Lemma split3_data_at_Tarray_at_tuchar: lo n sh data d (N: (lo+n <= length data)%nat): data_at sh (Tarray tuchar n noattr) data d = (* (!! offset_in_range 0 d && !! offset_in_range (sizeof t * Zlength data) d &&*)
(data_at sh (tarray t (Z.of_nat lo)) (firstn lo data) d *
data_at sh (tarray t (Z.of_nat n)) (firstn n (skipn lo data)) (offset_val (Int.repr (sizeof t * Z.of_nat lo)) d) *
data_at sh (tarray t (Zlength data - Z.of_nat (lo+n)))
(skipn (lo+n) data)  (offset_val (Int.repr (sizeof t * Z.of_nat (lo+n))) d)))%logic.

Lemma split3_offset_array_at
t (A: legal_alignas_type t = true)
lo n sh data d
(N: (lo+n <= length data)%nat):
data_at sh (tarray t (Zlength data)) data d =
(!! offset_in_range 0 d &&
!! offset_in_range (sizeof t * Zlength data) d &&
(data_at sh (tarray t (Z.of_nat lo)) (firstn lo data) d *
data_at sh (tarray t (Z.of_nat n)) (firstn n (skipn lo data)) (offset_val (Int.repr (sizeof t * Z.of_nat lo)) d) *
data_at sh (tarray t (Zlength data - Z.of_nat (lo+n)))
(skipn (lo+n) data)  (offset_val (Int.repr (sizeof t * Z.of_nat (lo+n))) d)))%logic.