Ltac address_ordered_auto :=
      auto; repeat match goal with
                   | H: AddressOrdered.eq ?A ?A |- _ => clear H
                   | H: AddressOrdered.eq ?A ?B |- _ => hnf in H; subst A
                   | H: ?A <> ?A |- _ => contradiction H; reflexivity
                   | H: AddressOrdered.lt ?A ?A |- _ =>
                     apply AddressOrdered.lt_not_eq in H; contradiction H; reflexivity
                   | H: AddressOrdered.lt ?A ?B, H': AddressOrdered.lt ?B ?A |- _ =>
                     contradiction (AddressOrdered.lt_not_eq (AddressOrdered.lt_trans H H')); reflexivity
                   end.

(* Specifications: *)
Lemma gsolockResUpdLock: forall js loc a res, loc <> a -> lockRes (updLockSet js loc res) a = lockRes js a.
Lemma gsslockResRemLock: forall js a, lockRes (remLockSet js a) a = None.
Lemma gsolockResRemLock: forall js loc a, loc <> a -> lockRes (remLockSet js loc) a = lockRes js a.
Lemma gsoThreadLock: forall {i tp} c p (cnti: containsThread tp i), lockSet (updThread cnti c p) = lockSet tp.
Lemma gsoThreadCLock: forall {i tp} c (cnti: containsThread tp i), lockSet (updThreadC cnti c) = lockSet tp.
Lemma gsoThreadRLock: forall {i tp} p (cnti: containsThread tp i), lockSet (updThreadR cnti p) = lockSet tp.
Lemma gsoAddLock: forall tp vf arg p, lockSet (addThread tp vf arg p) = lockSet tp.
Lemma PX_in_rev: forall elt a m, AMap.Raw.PX.In (elt:=elt) a m <-> AMap.Raw.PX.In a (rev m).
Lemma lockRes_range_dec: forall tp b ofs, { (exists z, z <= ofs < z+LKSIZE /\ lockRes tp (b,z) )%Z } + {(forall z, z <= ofs < z+LKSIZE -> lockRes tp (b,z) = None)%Z }.
Lemma gssThreadCode {tid tp} (cnt: containsThread tp tid) c' p' (cnt': containsThread (updThread cnt c' p') tid) : getThreadC cnt' = c'.
Lemma eq_op_false: forall A i j, i <>j -> @eq_op A i j = false.
Lemma gsoThreadCode: forall {i j tp} (Hneq: i <> j) (cnti: containsThread tp i) (cntj: containsThread tp j) c' p' (cntj': containsThread (updThread cnti c' p') j), getThreadC cntj' = getThreadC cntj.
Lemma gssThreadRes {tid tp} (cnt: containsThread tp tid) c' p' (cnt': containsThread (updThread cnt c' p') tid) : getThreadR cnt' = p'.
Lemma gsoThreadRes {i j tp} (cnti: containsThread tp i) (cntj: containsThread tp j) (Hneq: i <> j) c' p' (cntj': containsThread (updThread cnti c' p') j) : getThreadR cntj' = getThreadR cntj.
Lemma gssThreadCC {tid tp} (cnt: containsThread tp tid) c' (cnt': containsThread (updThreadC cnt c') tid) : getThreadC cnt' = c'.
Lemma gsoThreadCC {i j tp} (Hneq: i <> j) (cnti: containsThread tp i) (cntj: containsThread tp j) c' (cntj': containsThread (updThreadC cnti c') j) : getThreadC cntj = getThreadC cntj'.
Lemma getThreadCC {tp} i j (cnti : containsThread tp i) (cntj : containsThread tp j) c' (cntj' : containsThread (updThreadC cnti c') j): getThreadC cntj' = if eq_nat_dec i j then c' else getThreadC cntj.
Lemma gssThreadRR {tid tp} (cnt: containsThread tp tid) p' (cnt': containsThread (updThreadR cnt p') tid) : getThreadR cnt' = p'.
Lemma gsoThreadRR {i j tp} (Hneq: i <> j) (cnti: containsThread tp i) (cntj: containsThread tp j) p' (cntj': containsThread (updThreadR cnti p') j) : getThreadR cntj = getThreadR cntj'.
Lemma gThreadCR {i j tp} (cnti: containsThread tp i) (cntj: containsThread tp j) c' (cntj': containsThread (updThreadC cnti c') j) : getThreadR cntj' = getThreadR cntj.
Lemma gThreadRC {i j tp} (cnti: containsThread tp i) (cntj: containsThread tp j) p (cntj': containsThread (updThreadR cnti p) j) : getThreadC cntj' = getThreadC cntj.
Lemma gssAddRes: forall {tp} vf arg pmap j (Heq: j = latestThread tp) (cnt': containsThread (addThread tp vf arg pmap) j), getThreadR cnt' = pmap.
Lemma gsoAddRes: forall {tp} vf arg pmap j (cntj: containsThread tp j) (cntj': containsThread (addThread tp vf arg pmap) j), getThreadR cntj' = getThreadR cntj.
Lemma gssAddCode: forall {tp} vf arg pmap j (Heq: j = latestThread tp) (cnt': containsThread (addThread tp vf arg pmap) j), getThreadC cnt' = Kinit vf arg.
Lemma gsoAddCode: forall {tp} vf arg pmap j (cntj: containsThread tp j) (cntj': containsThread (addThread tp vf arg pmap) j), getThreadC cntj' = getThreadC cntj.
Lemma add_update_comm: forall tp i vf arg pmap c' pmap' (cnti: containsThread tp i) (cnti': containsThread (addThread tp vf arg pmap) i), addThread (updThread cnti c' pmap') vf arg pmap = updThread cnti' c' pmap'.
Lemma add_updateC_comm: forall tp i vf arg pmap c' (cnti: containsThread tp i) (cnti': containsThread (addThread tp vf arg pmap) i), addThread (updThreadC cnti c') vf arg pmap = updThreadC cnti' c'.
Lemma updThread_comm : forall tp i j c pmap c' pmap' (Hneq: i <> j) (cnti : containsThread tp i) (cntj : containsThread tp j) (cnti': containsThread (updThread cntj c' pmap') i) (cntj': containsThread (updThread cnti c pmap) j), updThread cnti' c pmap = updThread cntj' c' pmap'.
Lemma updThread_updThreadC_comm : forall tp i j c pmap' c' (Hneq: i <> j) (cnti : containsThread tp i) (cntj : containsThread tp j) (cnti': containsThread (updThread cntj c' pmap') i) (cntj': containsThread (updThreadC cnti c) j), updThreadC cnti' c = updThread cntj' c' pmap'.
Lemma updThread_same : forall tp i (cnti : containsThread tp i), updThread cnti (getThreadC cnti) (getThreadR cnti) = tp.
Lemma updThread_twice : forall tp i (cnti : containsThread tp i) c c' r r' (cnti' : containsThread (updThread cnti c r) i), updThread cnti' c' r' = updThread cnti c' r'.
Lemma updThreadRC : forall tp i (cnti : containsThread tp i) c, updThread cnti c (getThreadR cnti) = updThreadC cnti c.
Lemma gsoThreadCLPool: forall {i tp} c (cnti: containsThread tp i) addr, lockRes (updThreadC cnti c) addr = lockRes tp addr.
Lemma gsoThreadLPool: forall {i tp} c p (cnti: containsThread tp i) addr, lockRes (updThread cnti c p) addr = lockRes tp addr.
Lemma gsoAddLPool: forall tp vf arg p (addr : address), lockRes (addThread tp vf arg p) addr = lockRes tp addr.
Lemma gLockSetRes: forall {i tp} addr (res : lock_info) (cnti: containsThread tp i) (cnti': containsThread (updLockSet tp addr res) i), getThreadR cnti' = getThreadR cnti.
Lemma gLockSetCode: forall {i tp} addr (res : lock_info) (cnti: containsThread tp i) (cnti': containsThread (updLockSet tp addr res) i), getThreadC cnti' = getThreadC cnti.
Lemma gRemLockSetCode: forall {i tp} addr (cnti: containsThread tp i) (cnti': containsThread (remLockSet tp addr) i), getThreadC cnti' = getThreadC cnti.
Lemma gRemLockSetRes: forall {i tp} addr (cnti: containsThread tp i) (cnti': containsThread (remLockSet tp addr) i), getThreadR cnti' = getThreadR cnti.
Lemma gssLockRes: forall tp addr pmap, lockRes (updLockSet tp addr pmap) addr = Some pmap.
Lemma gsoLockRes: forall tp addr addr' pmap (Hneq: addr <> addr'), lockRes (updLockSet tp addr pmap) addr' = lockRes tp addr'.
Lemma gssLockSet: forall tp b ofs rmap ofs', (ofs <= ofs' < ofs + Z.of_nat lksize.LKSIZE_nat)%Z -> (Maps.PMap.get b (lockSet (updLockSet tp (b, ofs) rmap)) ofs') = Some Memtype.Writable.
Lemma gsoLockSet_12 : forall tp b b' ofs ofs' pmap, ~ adr_range (b,ofs) LKSIZE (b',ofs') -> (Maps.PMap.get b' (lockSet (updLockSet tp (b,ofs) pmap))) ofs' = (Maps.PMap.get b' (lockSet tp)) ofs'.
Lemma gsoLockSet_1: forall tp b ofs ofs' pmap (Hofs: (ofs' < ofs)%Z \/ (ofs' >= ofs + (Z.of_nat lksize.LKSIZE_nat))%Z), (Maps.PMap.get b (lockSet (updLockSet tp (b,ofs) pmap))) ofs' = (Maps.PMap.get b (lockSet tp)) ofs'.
Lemma gsoLockSet_2 : forall tp b b' ofs ofs' pmap, b <> b' -> (Maps.PMap.get b' (lockSet (updLockSet tp (b,ofs) pmap))) ofs' = (Maps.PMap.get b' (lockSet tp)) ofs'.
Lemma lockSet_updLockSet: forall tp i (pf: containsThread tp i) c pmap addr rmap, lockSet (updLockSet tp addr rmap) = lockSet (updLockSet (updThread pf c pmap) addr rmap).
Lemma updThread_lr_valid: forall tp i (cnti: containsThread tp i) c' m', lr_valid (lockRes tp) -> lr_valid (lockRes (updThread cnti c' m')).
Lemma contains_iff_num: forall tp tp' (Hcnt: forall i, containsThread tp i <-> containsThread tp' i), num_threads tp = num_threads tp'.
Lemma leq_stepdown: forall {m n}, S n <= m -> n <= m.
Lemma lt_sub: forall {m n}, S n <= m -> m - (S n) < m.