Record unchanged_on (m_before m_after: mem) : Prop := mk_unchanged_on {
  unchanged_on_nextblock:
    Ple (nextblock m_before) (nextblock m_after);
  unchanged_on_perm:
    forall b ofs k p,
    P b ofs -> valid_block m_before b ->
    (perm m_before b ofs k p <-> perm m_after b ofs k p);
  unchanged_on_contents:
    forall b ofs,
    P b ofs -> perm m_before b ofs Cur Readable ->
    ZMap.get ofs (PMap.get b m_after.(mem_contents)) =
    ZMap.get ofs (PMap.get b m_before.(mem_contents))
}.Record unchanged_on (m_before m_after: mem) : Prop := mk_unchanged_on {
  unchanged_on_nextblock:
    Ple (nextblock m_before) (nextblock m_after);
  unchanged_on_perm:
    forall b ofs k p,
    P b ofs -> valid_block m_before b ->
    (perm m_before b ofs k p <-> perm m_after b ofs k p);
  unchanged_on_contents:
    forall b ofs,
    P b ofs -> perm m_before b ofs Cur Readable ->
    ZMap.get ofs (PMap.get b m_after.(mem_contents)) =
    ZMap.get ofs (PMap.get b m_before.(mem_contents))
}.Record unchanged_on (m_before m_after: mem) : Prop := mk_unchanged_on {
  unchanged_on_nextblock:
    Ple (nextblock m_before) (nextblock m_after);
  unchanged_on_perm:
    forall b ofs k p,
    P b ofs -> valid_block m_before b ->
    (perm m_before b ofs k p <-> perm m_after b ofs k p);
  unchanged_on_contents:
    forall b ofs,
    P b ofs -> perm m_before b ofs Cur Readable ->
    ZMap.get ofs (PMap.get b m_after.(mem_contents)) =
    ZMap.get ofs (PMap.get b m_before.(mem_contents))
}.Record unchanged_on (m_before m_after: mem) : Prop := mk_unchanged_on {
  unchanged_on_nextblock:
    Ple (nextblock m_before) (nextblock m_after);
  unchanged_on_perm:
    forall b ofs k p,
    P b ofs -> valid_block m_before b ->
    (perm m_before b ofs k p <-> perm m_after b ofs k p);
  unchanged_on_contents:
    forall b ofs,
    P b ofs -> perm m_before b ofs Cur Readable ->
    ZMap.get ofs (PMap.get b m_after.(mem_contents)) =
    ZMap.get ofs (PMap.get b m_before.(mem_contents))
}.Record unchanged_on (m_before m_after: mem) : Prop := mk_unchanged_on {
  unchanged_on_nextblock:
    Ple (nextblock m_before) (nextblock m_after);
  unchanged_on_perm:
    forall b ofs k p,
    P b ofs -> valid_block m_before b ->
    (perm m_before b ofs k p <-> perm m_after b ofs k p);
  unchanged_on_contents:
    forall b ofs,
    P b ofs -> perm m_before b ofs Cur Readable ->
    ZMap.get ofs (PMap.get b m_after.(mem_contents)) =
    ZMap.get ofs (PMap.get b m_before.(mem_contents))
}.

(* Specifications: *)
Lemma unchanged_on_refl: forall m, unchanged_on m m.
Lemma valid_block_unchanged_on: forall m m' b, unchanged_on m m' -> valid_block m b -> valid_block m' b.
Lemma perm_unchanged_on: forall m m' b ofs k p, unchanged_on m m' -> P b ofs -> perm m b ofs k p -> perm m' b ofs k p.
Lemma perm_unchanged_on_2: forall m m' b ofs k p, unchanged_on m m' -> P b ofs -> valid_block m b -> perm m' b ofs k p -> perm m b ofs k p.
Lemma unchanged_on_trans: forall m1 m2 m3, unchanged_on m1 m2 -> unchanged_on m2 m3 -> unchanged_on m1 m3.
Lemma loadbytes_unchanged_on_1: forall m m' b ofs n, unchanged_on m m' -> valid_block m b -> (forall i, ofs <= i < ofs + n -> P b i) -> loadbytes m' b ofs n = loadbytes m b ofs n.
Lemma loadbytes_unchanged_on: forall m m' b ofs n bytes, unchanged_on m m' -> (forall i, ofs <= i < ofs + n -> P b i) -> loadbytes m b ofs n = Some bytes -> loadbytes m' b ofs n = Some bytes.
Lemma load_unchanged_on_1: forall m m' chunk b ofs, unchanged_on m m' -> valid_block m b -> (forall i, ofs <= i < ofs + size_chunk chunk -> P b i) -> load chunk m' b ofs = load chunk m b ofs.
Lemma load_unchanged_on: forall m m' chunk b ofs v, unchanged_on m m' -> (forall i, ofs <= i < ofs + size_chunk chunk -> P b i) -> load chunk m b ofs = Some v -> load chunk m' b ofs = Some v.
Lemma store_unchanged_on: forall chunk m b ofs v m', store chunk m b ofs v = Some m' -> (forall i, ofs <= i < ofs + size_chunk chunk -> ~ P b i) -> unchanged_on m m'.
Lemma storebytes_unchanged_on: forall m b ofs bytes m', storebytes m b ofs bytes = Some m' -> (forall i, ofs <= i < ofs + Z.of_nat (length bytes) -> ~ P b i) -> unchanged_on m m'.
Lemma alloc_unchanged_on: forall m lo hi m' b, alloc m lo hi = (m', b) -> unchanged_on m m'.
Lemma free_unchanged_on: forall m b lo hi m', free m b lo hi = Some m' -> (forall i, lo <= i < hi -> ~ P b i) -> unchanged_on m m'.
Lemma drop_perm_unchanged_on: forall m b lo hi p m', drop_perm m b lo hi p = Some m' -> (forall i, lo <= i < hi -> ~ P b i) -> unchanged_on m m'.
Lemma unchanged_on_implies: forall (P Q: block -> Z -> Prop) m m', unchanged_on P m m' -> (forall b ofs, Q b ofs -> valid_block m b -> P b ofs) -> unchanged_on Q m m'.