Inductive individual_match ocd i:
      meminj -> ctl -> mem -> ctl -> mem -> Prop:= 
    |individual_mtch_source:
       (i > hb)%nat ->
       forall j s1 m1 s2 m2,
         match_thread_source j s1 m1 s2 m2 ->
         individual_match ocd i j s1 m1 s2 m2
    |individual_mtch_target:
       (i < hb)%nat ->
       forall j s1 m1 s2 m2,
         match_thread_target j s1 m1 s2 m2 ->
         individual_match ocd i j s1 m1 s2 m2
    | individual_mtch_compiled:
        (i = hb)%nat ->
        forall cd j s1 m1 s2 m2,
          ocd = Some cd ->
          match_thread_compiled cd j s1 m1 s2 m2 ->
          individual_match ocd i j s1 m1 s2 m2.Inductive individual_match ocd i:
      meminj -> ctl -> mem -> ctl -> mem -> Prop:= 
    |individual_mtch_source:
       (i > hb)%nat ->
       forall j s1 m1 s2 m2,
         match_thread_source j s1 m1 s2 m2 ->
         individual_match ocd i j s1 m1 s2 m2
    |individual_mtch_target:
       (i < hb)%nat ->
       forall j s1 m1 s2 m2,
         match_thread_target j s1 m1 s2 m2 ->
         individual_match ocd i j s1 m1 s2 m2
    | individual_mtch_compiled:
        (i = hb)%nat ->
        forall cd j s1 m1 s2 m2,
          ocd = Some cd ->
          match_thread_compiled cd j s1 m1 s2 m2 ->
          individual_match ocd i j s1 m1 s2 m2.Inductive individual_match ocd i:
      meminj -> ctl -> mem -> ctl -> mem -> Prop:= 
    |individual_mtch_source:
       (i > hb)%nat ->
       forall j s1 m1 s2 m2,
         match_thread_source j s1 m1 s2 m2 ->
         individual_match ocd i j s1 m1 s2 m2
    |individual_mtch_target:
       (i < hb)%nat ->
       forall j s1 m1 s2 m2,
         match_thread_target j s1 m1 s2 m2 ->
         individual_match ocd i j s1 m1 s2 m2
    | individual_mtch_compiled:
        (i = hb)%nat ->
        forall cd j s1 m1 s2 m2,
          ocd = Some cd ->
          match_thread_compiled cd j s1 m1 s2 m2 ->
          individual_match ocd i j s1 m1 s2 m2.Inductive individual_match ocd i:
      meminj -> ctl -> mem -> ctl -> mem -> Prop:= 
    |individual_mtch_source:
       (i > hb)%nat ->
       forall j s1 m1 s2 m2,
         match_thread_source j s1 m1 s2 m2 ->
         individual_match ocd i j s1 m1 s2 m2
    |individual_mtch_target:
       (i < hb)%nat ->
       forall j s1 m1 s2 m2,
         match_thread_target j s1 m1 s2 m2 ->
         individual_match ocd i j s1 m1 s2 m2
    | individual_mtch_compiled:
        (i = hb)%nat ->
        forall cd j s1 m1 s2 m2,
          ocd = Some cd ->
          match_thread_compiled cd j s1 m1 s2 m2 ->
          individual_match ocd i j s1 m1 s2 m2.

(* Specifications: *)
Lemma simulation_equivlanence: forall s3 t s2 cd cd0, (Smallstep.plus (Asm.step (Genv.globalenv Asm_program)) s3 t s2 \/ Smallstep.star (Asm.step (Genv.globalenv Asm_program)) s3 t s2 /\ Injorder compiler_sim cd cd0) -> Smallstep.plus (Asm.step (Genv.globalenv Asm_program)) s3 t s2 \/ t = Events.E0 /\ s2 = s3 /\ Injorder compiler_sim cd cd0.
Lemma Concur_update: forall (st1: ThreadPool.t) (m1 m1' : mem) (tid : nat) (Htid : ThreadPool.containsThread st1 tid) c1 (cd cd' : option compiler_index) (st2 : ThreadPool.t) (mu : meminj) (m2 : mem) c2 (f' : meminj) (m2' : mem) (Htid' : ThreadPool.containsThread st2 tid) (mcompat1: mem_compatible st1 m1) (mcompat2: mem_compatible st2 m2), semantics.mem_step (restrPermMap (proj1 (mcompat1 tid Htid))) m1' -> semantics.mem_step (restrPermMap (proj1 (mcompat2 tid Htid'))) m2' -> invariant st1 -> invariant st2 -> concur_match cd mu st1 m1 st2 m2 -> individual_match cd' tid f' c1 m1' c2 m2' -> self_simulation.is_ext mu (Mem.nextblock m1) f' (Mem.nextblock m2) -> concur_match cd' f' (updThread Htid c1 (getCurPerm m1', snd (getThreadR Htid))) m1' (updThread Htid' c2 (getCurPerm m2', snd (getThreadR Htid'))) m2'.
Lemma Concur_update_compiled: forall (st1 : ThreadPool.t) (m1 m1' : mem) (Htid : ThreadPool.containsThread st1 hb) (st2 : ThreadPool.t) (mu : meminj) (m2 : mem) (cd0 : compiler_index), concur_match (Some cd0) mu st1 m1 st2 m2 -> forall (s' : Clight.state) (j1' : meminj) (cd' : Injindex compiler_sim) (j2' : meminj) (s4' : Asm.state) (j3' : meminj) (m2' : mem) (Htid' : containsThread st2 hb) (mcompat1: mem_compatible st1 m1) (mcompat2: mem_compatible st2 m2), semantics.mem_step (restrPermMap (proj1 (mcompat1 hb Htid))) m1' -> semantics.mem_step (restrPermMap (proj1 (mcompat2 hb Htid'))) m2' -> invariant st1 -> invariant st2 -> match_thread_compiled cd' (compose_meminj (compose_meminj j1' j2') j3') (Krun (SState Clight.state Asm.state s')) m1' (Krun (TState Clight.state Asm.state s4')) m2' -> concur_match (Some cd') (compose_meminj (compose_meminj j1' j2') j3') (updThread Htid (Krun (SState Clight.state Asm.state s')) (getCurPerm m1', snd (getThreadR Htid))) m1' (updThread Htid' (Krun (TState Clight.state Asm.state s4')) (getCurPerm m2', snd (getThreadR Htid'))) m2'.
Lemma Concur_update_compiled': forall (st1 : ThreadPool.t) (m1 m1' : mem) (Htid : ThreadPool.containsThread st1 hb) (st2 : ThreadPool.t) (mu : meminj) (m2 : mem) (cd0 : compiler_index), concur_match (Some cd0) mu st1 m1 st2 m2 -> forall (s' : Clight.state) (j1' : meminj) (cd' : Injindex compiler_sim) (j2' : meminj) (s4 : Asm.state) (j3' : meminj) (Htid' : containsThread st2 hb) (mcompat1: mem_compatible st1 m1) (mcompat2: mem_compatible st2 m2), semantics.mem_step (restrPermMap (proj1 (mcompat1 hb Htid))) m1' -> invariant st1 -> invariant st2 -> match_thread_compiled cd' (compose_meminj (compose_meminj j1' j2') j3') (Krun (SState Clight.state Asm.state s')) m1' (Krun (TState Clight.state Asm.state s4)) (restrPermMap (proj1 (mcompat2 hb Htid'))) -> concur_match (Some cd') (compose_meminj (compose_meminj j1' j2') j3') (updThread Htid (Krun (SState Clight.state Asm.state s')) (getCurPerm m1', snd (getThreadR Htid))) m1' st2 m2.