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.
(* This lemma is only used when updating non compiled threads *)
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'.