(*Construction used in make_initial_core: put incoming injection into foreign/unknown component as specified, initialize local_of, locBlocksSrc/Tgt, and pubBlocksSrc/Tgt as empty*)
Definition initial_SM (extS extT frgnS frgnT: block->bool)
(extern:meminj): SM_Injection :=
Build_SM_Injection
(*locBlocksSrc/Tgt:*) (fun b => false) (fun b => false) (*pubBlocksSrc/Tgt:*)(fun b => false) (fun b => false) (*local:*)(fun b => None) (*extBlocksSrc/Tgt:*) extS extT (*frgnBlocksSrc/Tgt:*) frgnS frgnT extern.  Lemma initial_SM_wd: forall extS extT frgnS frgnT extern (EXT: forall b1 b2 d, extern b1 =Some(b2,d) -> extS b1 = true /\ extT b2 = true) (F: forall b1, frgnS b1 = true -> exists b2 z, extern b1 = Some (b2, z) /\ frgnT b2 = true) (FS: forall b, frgnS b = true -> extS b = true) (FT: forall b, frgnT b = true -> extT b = true), SM_wd (initial_SM extS extT frgnS frgnT extern).  Lemma initial_SM_as_inj: forall extS extT frgnS frgnT j, as_inj (initial_SM extS extT frgnS frgnT j) = j.  Definition restrict (j: meminj) (X:block -> bool) : meminj := fun b => if X b then j b else None.  Lemma restrictD_Some: forall j X b1 b2 d (R:restrict j X b1 = Some(b2,d)), j b1 = Some(b2,d) /\ X b1 = true. Lemma restrictI_Some: forall j X b b2 d (J:j b = Some(b2,d)) (Hb: X b = true), restrict j X b = Some(b2,d). Lemma restrictD_None: forall j X b1 b2 d (R:restrict j X b1 = None) (J: j b1 = Some(b2,d)), X b1 = false. Lemma restrictD_None': forall j X b1 (R:restrict j X b1 = None), j b1 = None \/ (exists b2 d, j b1 =Some(b2,d) /\ X b1 = false). Lemma restrictI_None: forall j X b (Hb: j b = None \/ X b = false), restrict j X b = None.  Lemma join_restrict: forall j k X, join (restrict j X) (restrict k X) = restrict (join j k) X.  Lemma restrict_outside: forall j X (HX: forall b1 b2 d, j b1 = Some(b2, d) -> X b1 = true), restrict j X = j.  Lemma restrict_incr: forall j X, inject_incr (restrict j X) j.  Lemma restrict_nest: forall j X Y (HXY: forall b, Y b = true -> X b = true), restrict (restrict j X) Y = restrict j Y. Lemma restrict_nest': forall j X Y (HXY: forall b, Y b = true -> X b = true), restrict (restrict j Y) X = restrict j Y.  Lemma val_inject_restrictD: forall j v v' X (V: val_inject (restrict j X) v v'), val_inject j v v'.  Lemma forall_vals_inject_restrictD: forall j vals1 vals2 X (Inj : Forall2 (val_inject (restrict j X)) vals1 vals2), Forall2 (val_inject j) vals1 vals2.  Definition reestablish (mu0 mu: SM_Injection): SM_Injection := match mu0, mu with Build_SM_Injection locBSrc0 locBTgt0 pSrc0 pTgt0 local0 extBSrc0 extBTgt0 fSrc0 fTgt0 extern0, Build_SM_Injection locBSrc locBTgt pSrc pTgt local extBSrc extBTgt fSrc fTgt extern => Build_SM_Injection locBSrc0 locBTgt0 pSrc0 pTgt0 local0 (fun b => if locBSrc0 b then false else locBSrc b || extBSrc b) (fun b => if locBTgt0 b then false else locBTgt b || extBTgt b) fSrc0 fTgt0 (*We have not YET learned about additional blocks - that's done by replace_externs in AfterEtxernal!*)
(fun b => if locBSrc0 b then None else join extern local b)
end.

(* Specifications: *)
Lemma reestablish_DomSrc: forall mu0 mu
(D: forall b, locBlocksSrc mu0 b = true -> DomSrc mu b = true),
DomSrc (reestablish mu0 mu) = DomSrc mu.
Lemma reestablish_DomTgt: forall mu0 mu
(D: forall b, locBlocksTgt mu0 b = true -> DomTgt mu b = true),
DomTgt (reestablish mu0 mu) = DomTgt mu.
Lemma reestablish_wd: forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(REST: restrict (as_inj mu) (DomSrc mu0) = as_inj mu0)
(SEP: forall b1 b2 d, as_inj mu0 b1 = None -> as_inj mu b1 = Some(b2,d) ->
(DomSrc mu0 b1 = false /\ DomTgt mu0 b2 = false))
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true),
SM_wd (reestablish mu0 mu).
Lemma reestablish_wd': forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(INC: inject_incr (as_inj mu0) (as_inj mu))
(Hmu: forall b1 b2 z (A:as_inj mu b1 = Some(b2,z)),
locBlocksSrc mu0 b1 = locBlocksTgt mu0 b2 /\
extBlocksSrc mu0 b1 = extBlocksTgt mu0 b2)
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true),
SM_wd (reestablish mu0 mu).
Lemma reestablish_extern_incr': forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(INC: inject_incr (as_inj mu0) (as_inj mu))
(ExtSrc: forall b, extBlocksSrc mu0 b = true -> DomSrc mu b = true)
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true),
extern_incr mu0 (reestablish mu0 mu).
Lemma reestablish_extern_incr: forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(REST: restrict (as_inj mu) (DomSrc mu0) = as_inj mu0)
(ExtSrc: forall b, extBlocksSrc mu0 b = true -> DomSrc mu b = true)
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true),
extern_incr mu0 (reestablish mu0 mu).
Lemma reestablish_internstep': forall mu0 mu mu' (WD0:SM_wd mu0) (WD:SM_wd mu) (WD:SM_wd mu')
(INC: inject_incr (as_inj mu0) (as_inj mu))
(ExtSrc: forall b, extBlocksSrc mu0 b = true -> DomSrc mu b = true)
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true)
(II: intern_incr mu mu'),
extern_incr mu0 (reestablish mu0 mu').
Lemma reestablish_internstep: forall mu0 mu mu' (WD0:SM_wd mu0) (WD:SM_wd mu) (WD:SM_wd mu')
(REST: restrict (as_inj mu) (DomSrc mu0) = as_inj mu0)
(ExtSrc: forall b, extBlocksSrc mu0 b = true -> DomSrc mu b = true)
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true)
(II: intern_incr mu mu'),
extern_incr mu0 (reestablish mu0 mu').
Lemma reestablish_as_inj: forall mu0 mu (WD0:SM_wd mu0)
(REST: restrict (as_inj mu) (DomSrc mu0) = as_inj mu0),
as_inj (reestablish mu0 mu) = as_inj mu.
Lemma reestablish_as_inj': forall mu0 mu (WD0:SM_wd mu0)
(HINC: inject_incr (as_inj mu0) (as_inj mu))
(H: forall b, locBlocksSrc mu0 b = true -> local_of mu0 b = None ->
as_inj mu b = None),
as_inj (reestablish mu0 mu) = as_inj mu.
Lemma reestablish_sm_injsep: forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(REST: restrict (as_inj mu) (DomSrc mu0) = as_inj mu0)
(LocSrc: forall b, locBlocksSrc mu0 b = true -> DomSrc mu b = true)
(LocTgt: forall b, locBlocksTgt mu0 b = true -> DomTgt mu b = true)
m1 m2 (SEP: sm_inject_separated mu0 mu m1 m2),
sm_inject_separated mu0 (reestablish mu0 mu) m1 m2.
Lemma reestablish_sm_valid: forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(LocSrc: forall b, locBlocksSrc mu0 b = true -> DomSrc mu b = true)
(DomTgt: forall b, locBlocksTgt mu0 b = true -> DomTgt mu b = true)
m1 m2 (VAL: sm_valid mu m1 m2),
sm_valid (reestablish mu0 mu) m1 m2.
Lemma as_inj_locBlocks mu b1 b2 delta: forall (WD: SM_wd mu)
(A: as_inj mu b1 = Some(b2,delta)),
locBlocksSrc mu b1 = locBlocksTgt mu b2.
Lemma as_inj_extBlocks mu b1 b2 delta: forall (WD: SM_wd mu)
(A: as_inj mu b1 = Some(b2,delta)),
extBlocksSrc mu b1 = extBlocksTgt mu b2.
Lemma locBlocksSrc_as_inj_local mu b: forall (WD: SM_wd mu)
(L: locBlocksSrc mu b = true),
as_inj mu b = local_of mu b.
Lemma frgnBlocksSrc_false_foreign_None mu b: forall
(F: frgnBlocksSrc mu b = false),
foreign_of mu b = None.
Lemma foreign_None_frgnBlocksSrc_false mu b: forall (WD: SM_wd mu)
(F: foreign_of mu b = None),
as_inj mu b = None \/ frgnBlocksSrc mu b = false.
Lemma locBlocksSrc_false_local_None mu b: forall (WD: SM_wd mu)
(L: locBlocksSrc mu b = false),
local_of mu b = None.
Lemma reestablish_DomSrc: forall mu0 mu
(D: forall b, locBlocksSrc mu0 b = true -> DomSrc mu b = true),
DomSrc (reestablish mu0 mu) = DomSrc mu.
Lemma reestablish_DomTgt: forall mu0 mu
(D: forall b, locBlocksTgt mu0 b = true -> DomTgt mu b = true),
DomTgt (reestablish mu0 mu) = DomTgt mu.
Lemma reestablish_wd: forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(REST: restrict (as_inj mu) (DomSrc mu0) = as_inj mu0)
(SEP: forall b1 b2 d, as_inj mu0 b1 = None -> as_inj mu b1 = Some(b2,d) ->
(DomSrc mu0 b1 = false /\ DomTgt mu0 b2 = false))
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true),
SM_wd (reestablish mu0 mu).
Lemma reestablish_wd': forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(INC: inject_incr (as_inj mu0) (as_inj mu))
(Hmu: forall b1 b2 z (A:as_inj mu b1 = Some(b2,z)),
locBlocksSrc mu0 b1 = locBlocksTgt mu0 b2 /\
extBlocksSrc mu0 b1 = extBlocksTgt mu0 b2)
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true),
SM_wd (reestablish mu0 mu).
Lemma reestablish_extern_incr': forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(INC: inject_incr (as_inj mu0) (as_inj mu))
(ExtSrc: forall b, extBlocksSrc mu0 b = true -> DomSrc mu b = true)
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true),
extern_incr mu0 (reestablish mu0 mu).
Lemma reestablish_extern_incr: forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(REST: restrict (as_inj mu) (DomSrc mu0) = as_inj mu0)
(ExtSrc: forall b, extBlocksSrc mu0 b = true -> DomSrc mu b = true)
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true),
extern_incr mu0 (reestablish mu0 mu).
Lemma reestablish_internstep': forall mu0 mu mu' (WD0:SM_wd mu0) (WD:SM_wd mu) (WD:SM_wd mu')
(INC: inject_incr (as_inj mu0) (as_inj mu))
(ExtSrc: forall b, extBlocksSrc mu0 b = true -> DomSrc mu b = true)
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true)
(II: intern_incr mu mu'),
extern_incr mu0 (reestablish mu0 mu').
Lemma reestablish_internstep: forall mu0 mu mu' (WD0:SM_wd mu0) (WD:SM_wd mu) (WD:SM_wd mu')
(REST: restrict (as_inj mu) (DomSrc mu0) = as_inj mu0)
(ExtSrc: forall b, extBlocksSrc mu0 b = true -> DomSrc mu b = true)
(ExtTgt: forall b, extBlocksTgt mu0 b = true -> DomTgt mu b = true)
(II: intern_incr mu mu'),
extern_incr mu0 (reestablish mu0 mu').
Lemma reestablish_as_inj: forall mu0 mu (WD0:SM_wd mu0)
(REST: restrict (as_inj mu) (DomSrc mu0) = as_inj mu0),
as_inj (reestablish mu0 mu) = as_inj mu.
Lemma reestablish_as_inj': forall mu0 mu (WD0:SM_wd mu0)
(HINC: inject_incr (as_inj mu0) (as_inj mu))
(H: forall b, locBlocksSrc mu0 b = true -> local_of mu0 b = None ->
as_inj mu b = None),
as_inj (reestablish mu0 mu) = as_inj mu.
Lemma reestablish_sm_injsep: forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(REST: restrict (as_inj mu) (DomSrc mu0) = as_inj mu0)
(LocSrc: forall b, locBlocksSrc mu0 b = true -> DomSrc mu b = true)
(LocTgt: forall b, locBlocksTgt mu0 b = true -> DomTgt mu b = true)
m1 m2 (SEP: sm_inject_separated mu0 mu m1 m2),
sm_inject_separated mu0 (reestablish mu0 mu) m1 m2.
Lemma reestablish_sm_valid: forall mu0 mu (WD0:SM_wd mu0) (WD:SM_wd mu)
(LocSrc: forall b, locBlocksSrc mu0 b = true -> DomSrc mu b = true)
(DomTgt: forall b, locBlocksTgt mu0 b = true -> DomTgt mu b = true)
m1 m2 (VAL: sm_valid mu m1 m2),
sm_valid (reestablish mu0 mu) m1 m2.