(*Lenb: moved to mpred Definition assert := environ -> mpred.  (* Unfortunately can't export this abbreviation through SeparationLogic.v because it confuses the Lift system *)
*)
Definition writable_block (id: ident) (n: Z): assert :=
fun rho =>
EX b: block,  EX sh: Share.t,
!! (writable_share sh /\ ge_of rho id = Some b) && VALspec_range n sh (b, 0).
Fixpoint writable_blocks (bl : list (ident*Z)) : assert :=
match bl with
| nil =>  fun rho => emp
| (b,n)::bl' =>  fun rho => writable_block b n rho * writable_blocks bl' rho
end.
Fixpoint address_mapsto_zeros (sh: share) (n: nat) (adr: address) : mpred :=
match n with
| O => emp
| S n' => address_mapsto Mint8unsigned (Vint Int.zero) sh adr
* address_mapsto_zeros sh n' (fst adr, Z.succ (snd adr))
end.
Definition address_mapsto_zeros' (n: Z) : spec :=
fun (sh: Share.t) (l: address) =>
allp (jam (adr_range_dec l (Z.max n 0))
(fun l' => yesat NoneP (VAL (Byte Byte.zero)) sh l')
noat) && noghost.
Definition mapsto_zeros (n: Z) (sh: share) (a: val) : mpred :=
match a with
| Vptr b z =>
!! (0 <= Ptrofs.unsigned z  /\ n + Ptrofs.unsigned z < Ptrofs.modulus)%Z &&
address_mapsto_zeros sh (Z.to_nat n) (b, Ptrofs.unsigned z)
| _ => FF
end.
Fixpoint memory_block' (sh: share) (n: nat) (b: block) (i: Z) : mpred :=
match n with
| O => emp
| S n' => mapsto_ sh (Tint I8 Unsigned noattr) (Vptr b (Ptrofs.repr i))
* memory_block' sh n' b (i+1)
end.
Definition memory_block'_alt (sh: share) (n: nat) (b: block) (ofs: Z) : mpred :=
if readable_share_dec sh
then VALspec_range (Z_of_nat n) sh (b, ofs)
else nonlock_permission_bytes sh (b,ofs) (Z.of_nat n).
Definition memory_block (sh: share) (n: Z) (v: val) : mpred :=
match v with
| Vptr b ofs => (!!(Ptrofs.unsigned ofs + n < Ptrofs.modulus)) && memory_block' sh (Z.to_nat n) b (Ptrofs.unsigned ofs)
| _ => FF
end.

Lemma memory_block_share_join:
forall sh1 sh2 sh n p,
sepalg.join sh1 sh2 sh ->
memory_block sh1 n p * memory_block sh2 n p = memory_block sh n p.