(*Lenb -- meminj_preserves_globales is new, and needed since this property is now
    required by the simulation realtions, rather than only at/efterexternal clauses*)
Inductive match_cores: core_data -> meminj -> CSharpMin_core -> mem -> CMin_core -> mem -> Prop :=
  | MC_states:
      forall d fn s k e le m tfn ts tk sp te tm cenv xenv j lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk  cenv xenv cs)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_State fn s k e le) m
                   (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm
  | MC_state_seq:
      forall d fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv j lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_State fn (Csharpminor.Sseq s1 s2) k e le) m
                   (CMin_State tfn ts1 tk (Vptr sp Int.zero) te) tm
  | MC_callstate:
      forall d fd args k m tfd targs tk tm j cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject j args targs)
      (PG: meminj_preserves_globals ge j),

      match_cores d j (CSharpMin_Callstate fd args k) m
                   (CMin_Callstate tfd targs tk) tm
  | MC_returnstate:
      forall d v k m tv tk tm j cs cenv
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject j v tv)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_Returnstate v k) m
                   (CMin_Returnstate tv tk) tm.(*Lenb -- meminj_preserves_globales is new, and needed since this property is now
    required by the simulation realtions, rather than only at/efterexternal clauses*)
Inductive match_cores: core_data -> meminj -> CSharpMin_core -> mem -> CMin_core -> mem -> Prop :=
  | MC_states:
      forall d fn s k e le m tfn ts tk sp te tm cenv xenv j lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk  cenv xenv cs)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_State fn s k e le) m
                   (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm
  | MC_state_seq:
      forall d fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv j lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_State fn (Csharpminor.Sseq s1 s2) k e le) m
                   (CMin_State tfn ts1 tk (Vptr sp Int.zero) te) tm
  | MC_callstate:
      forall d fd args k m tfd targs tk tm j cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject j args targs)
      (PG: meminj_preserves_globals ge j),

      match_cores d j (CSharpMin_Callstate fd args k) m
                   (CMin_Callstate tfd targs tk) tm
  | MC_returnstate:
      forall d v k m tv tk tm j cs cenv
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject j v tv)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_Returnstate v k) m
                   (CMin_Returnstate tv tk) tm.(*Lenb -- meminj_preserves_globales is new, and needed since this property is now
    required by the simulation realtions, rather than only at/efterexternal clauses*)
Inductive match_cores: core_data -> meminj -> CSharpMin_core -> mem -> CMin_core -> mem -> Prop :=
  | MC_states:
      forall d fn s k e le m tfn ts tk sp te tm cenv xenv j lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk  cenv xenv cs)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_State fn s k e le) m
                   (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm
  | MC_state_seq:
      forall d fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv j lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_State fn (Csharpminor.Sseq s1 s2) k e le) m
                   (CMin_State tfn ts1 tk (Vptr sp Int.zero) te) tm
  | MC_callstate:
      forall d fd args k m tfd targs tk tm j cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject j args targs)
      (PG: meminj_preserves_globals ge j),

      match_cores d j (CSharpMin_Callstate fd args k) m
                   (CMin_Callstate tfd targs tk) tm
  | MC_returnstate:
      forall d v k m tv tk tm j cs cenv
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject j v tv)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_Returnstate v k) m
                   (CMin_Returnstate tv tk) tm.(*Lenb -- meminj_preserves_globales is new, and needed since this property is now
    required by the simulation realtions, rather than only at/efterexternal clauses*)
Inductive match_cores: core_data -> meminj -> CSharpMin_core -> mem -> CMin_core -> mem -> Prop :=
  | MC_states:
      forall d fn s k e le m tfn ts tk sp te tm cenv xenv j lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk  cenv xenv cs)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_State fn s k e le) m
                   (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm
  | MC_state_seq:
      forall d fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv j lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_State fn (Csharpminor.Sseq s1 s2) k e le) m
                   (CMin_State tfn ts1 tk (Vptr sp Int.zero) te) tm
  | MC_callstate:
      forall d fd args k m tfd targs tk tm j cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject j args targs)
      (PG: meminj_preserves_globals ge j),

      match_cores d j (CSharpMin_Callstate fd args k) m
                   (CMin_Callstate tfd targs tk) tm
  | MC_returnstate:
      forall d v k m tv tk tm j cs cenv
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject j v tv)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_Returnstate v k) m
                   (CMin_Returnstate tv tk) tm.(*Lenb -- meminj_preserves_globales is new, and needed since this property is now
    required by the simulation realtions, rather than only at/efterexternal clauses*)
Inductive match_cores: core_data -> meminj -> CSharpMin_core -> mem -> CMin_core -> mem -> Prop :=
  | MC_states:
      forall d fn s k e le m tfn ts tk sp te tm cenv xenv j lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s = OK ts)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk  cenv xenv cs)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_State fn s k e le) m
                   (CMin_State tfn ts tk (Vptr sp Int.zero) te) tm
  | MC_state_seq:
      forall d fn s1 s2 k e le m tfn ts1 tk sp te tm cenv xenv j lo hi cs sz
      (TRF: transl_funbody cenv sz fn = OK tfn)
      (TR: transl_stmt cenv xenv s1 = OK ts1)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm
               (Frame cenv tfn e le te sp lo hi :: cs)
               (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont (Csharpminor.Kseq s2 k) tk cenv xenv cs)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_State fn (Csharpminor.Sseq s1 s2) k e le) m
                   (CMin_State tfn ts1 tk (Vptr sp Int.zero) te) tm
  | MC_callstate:
      forall d fd args k m tfd targs tk tm j cs cenv
      (TR: transl_fundef fd = OK tfd)
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (ISCC: Csharpminor.is_call_cont k)
      (ARGSINJ: val_list_inject j args targs)
      (PG: meminj_preserves_globals ge j),

      match_cores d j (CSharpMin_Callstate fd args k) m
                   (CMin_Callstate tfd targs tk) tm
  | MC_returnstate:
      forall d v k m tv tk tm j cs cenv
      (MINJ: Mem.inject j m tm)
      (MCS: match_callstack prog j m tm cs (Mem.nextblock m) (Mem.nextblock tm))
      (MK: match_cont k tk cenv nil cs)
      (RESINJ: val_inject j v tv)
      (PG: meminj_preserves_globals ge j),
      match_cores d j (CSharpMin_Returnstate v k) m
                   (CMin_Returnstate tv tk) tm.

(* Specifications: *)
Lemma match_cores_valid: forall d j c1 m1 c2 m2, match_cores d j c1 m1 c2 m2 -> forall b1 b2 ofs, j b1 = Some(b2,ofs) -> (Mem.valid_block m1 b1 /\ Mem.valid_block m2 b2).
Lemma match_cores_genvs: forall d j c1 m1 c2 m2, match_cores d j c1 m1 c2 m2 -> meminj_preserves_globals ge j.
Lemma valid_init_is_global : forall (R: list_norepet (map fst (prog_defs prog))) m (G: Genv.init_mem prog = Some m) b (VB: Mem.valid_block m b), exists id, Genv.find_symbol (Genv.globalenv prog) id = Some b.
Lemma match_globalenvs_init': forall (R: list_norepet (map fst (prog_defs prog))) m j, Genv.init_mem prog = Some m -> meminj_preserves_globals ge j -> match_globalenvs prog j (Mem.nextblock m).
Lemma init_cores: forall (v1 v2 : val) (sig : signature) entrypoints (EP: In (v1, v2, sig) entrypoints) (entry_points_ok : forall v1 v2 sig, In (v1, v2, sig) entrypoints -> exists b f1 f2, v1 = Vptr b Int.zero /\ v2 = Vptr b Int.zero /\ Genv.find_funct_ptr ge b = Some f1 /\ Genv.find_funct_ptr tge b = Some f2) (vals1 : list val) (c1 : core_data) (m1 : mem) (j : meminj) (vals2 : list val) (m2 : mem) (CSM_Ini : initial_core CSharpMin_core_sem ge v1 vals1 = Some c1) (Inj : Mem.inject j m1 m2) (VI: Forall2 (val_inject j) vals1 vals2) (PG: meminj_preserves_globals ge j) (R: list_norepet (map fst (prog_defs prog))) (INIT_MEM: exists m0, Genv.init_mem prog = Some m0 /\ Ple (Mem.nextblock m0) (Mem.nextblock m1) /\ Ple (Mem.nextblock m0) (Mem.nextblock m2)), exists c2 : CMin_core, initial_core CMin_core_sem tge v2 vals2 = Some c2 /\ match_cores c1 j c1 m1 c2 m2.
Lemma MC_safely_halted: forall (cd : core_data) (j : meminj) (c1 : CSharpMin_core) (m1 : mem) (c2 : CMin_core) (m2 : mem) (v1 : val), match_cores cd j c1 m1 c2 m2 -> halted CSharpMin_core_sem c1 = Some v1 -> exists v2, halted CMin_core_sem c2 = Some v2 /\ Mem.inject j m1 m2 /\ val_inject j v1 v2.
Lemma MC_at_external: forall (cd : core_data) (j : meminj) (st1 : CSharpMin_core) (m1 : mem) (st2 : CMin_core) (m2 : mem) (e : external_function) (vals1 : list val) sig, (cd = st1 /\ match_cores cd j st1 m1 st2 m2) -> at_external CSharpMin_core_sem st1 = Some (e, sig, vals1) -> Mem.inject j m1 m2 /\ Events.meminj_preserves_globals ge j /\ (exists vals2 : list val, Forall2 (val_inject j) vals1 vals2 /\ at_external CMin_core_sem st2 = Some (e, sig, vals2)).
Lemma MC_after_external:forall (d : core_data) (j j' : meminj) (st1 : core_data) (st2 : CMin_core) (m1 : mem) (e : external_function) (vals1 : list val) (ret1 : val) (m1' m2 m2' : mem) (ret2 : val) (sig : signature), d = st1 /\ match_cores d j st1 m1 st2 m2 -> at_external CSharpMin_core_sem st1 = Some (e, sig, vals1) -> Events.meminj_preserves_globals ge j -> inject_incr j j' -> Events.inject_separated j j' m1 m2 -> Mem.inject j' m1' m2' -> val_inject j' ret1 ret2 -> mem_forward m1 m1' -> Mem.unchanged_on (Events.loc_unmapped j) m1 m1' -> mem_forward m2 m2' -> Mem.unchanged_on (Events.loc_out_of_reach j m1) m2 m2' -> exists st1' : core_data, exists st2' : CMin_core, exists d' : core_data, after_external CSharpMin_core_sem (Some ret1) st1 = Some st1' /\ after_external CMin_core_sem (Some ret2) st2 = Some st2' /\ d' = st1' /\ match_cores d' j' st1' m1' st2' m2'.
Lemma MC_MSI: forall d j q m q' m', match_cores d j q m q' m' -> match_statesInj prog j (ToState q m) (Cminor_coop.ToState q' m').
Lemma MSI_MC: forall j q m q' m' d (*NEW:*) (PG: meminj_preserves_globals ge j), match_statesInj prog j (ToState q m) (Cminor_coop.ToState q' m') -> match_cores d j q m q' m'.
Lemma MSI_atExt: forall j c1 m1 c2 m2 (H: match_statesInj prog j (ToState c1 m1) (Cminor_coop.ToState c2 m2) ), (CSharpMin_at_external c1 = None) = (CMin_at_external c2 = None).