(****** Specific specs  ****************)
(* Memory predicates need to explicitly not capture any ghost state. *)
Definition VALspec : spec :=
fun (sh: Share.t) (l: address) =>
allp (jam (eq_dec l)
(fun l' => EX v: memval,
yesat NoneP (VAL v) sh l')
noat) && noghost.
Definition VALspec_range (n: Z) : spec :=
fun (sh: Share.t) (l: address) =>
andp (allp (jam (adr_range_dec l n)
(fun l' => EX v: memval,
yesat NoneP (VAL v) sh l')
noat)) noghost.
Definition nonlock_permission_bytes (sh: share) (a: address) (n: Z) : pred rmap :=
andp (allp (jam (adr_range_dec a n) (fun i => shareat i sh && nonlockat i) noat)) noghost.
Definition nthbyte (n: Z) (l: list memval) : memval :=
nth (nat_of_Z n) l Undef.
(*  Unfortunately address_mapsto_old, while a more elegant definition than address_mapsto, is not quite right.  For example, it doesn't uniquely determine v *)
Definition address_mapsto_old (ch: memory_chunk) (v: val) : spec :=
fun (sh: Share.t) (l: AV.address)  =>
allp (jam (adr_range_dec l (size_chunk ch))
(fun l' => yesat NoneP (VAL (nthbyte (snd l' - snd l) (encode_val ch v))) sh l')
noat).
Definition address_mapsto (ch: memory_chunk) (v: val) : spec :=
fun (sh: Share.t) (l: AV.address) =>
EX bl: list memval,
!! (length bl = size_chunk_nat ch  /\ decode_val ch bl = v /\ (align_chunk ch | snd l))  &&
(allp (jam (adr_range_dec l (size_chunk ch))
(fun loc => yesat NoneP (VAL (nth (nat_of_Z (snd loc - snd l)) bl Undef)) sh loc)
noat)) && noghost.

(* Specifications: *)
Lemma address_mapsto_align: forall ch v sh l,
address_mapsto ch v sh l = address_mapsto ch v sh l && !! (align_chunk ch | snd l).
Lemma address_mapsto_fun:
forall ch sh sh' l v v',
(address_mapsto ch v sh l * TT) && (address_mapsto ch v' sh' l * TT) |-- !!(v=v').