Section bsm_sim.
Variable (iP : nat) (cP : list (bsm_instr m)).
Let lnk_Q_pair := @gen_compiler_correction _ _ _ _ bsm_instr_compile_length_eq _ _ _ _  (@bsm_sss_total' _)
(@mm_sss_fun _) _ bsm_instr_compile_sound (iP,cP) 1.
Let lnk := projT1 lnk_Q_pair.
Let Q := proj1_sig (projT2 lnk_Q_pair).
Let Hlnk : fst Q = 1 /\ lnk iP = 1 /\ forall i, out_code i (iP,cP) -> lnk i = code_end Q.
Infix "⋈" := bsm_state_enc (at level 70, no associativity).
Let HQ1 : forall i1 v1 w1 i2 v2, v1 ⋈ w1 /\ (iP,cP) /BSM/ (i1,v1) ~~> (i2,v2)
-> exists w2,    v2 ⋈ w2 /\ Q /MM/ (lnk i1,w1) ~~> (lnk i2,w2).
(* (iQ,cQ) simulates termination of (iP,cP) while ensuring tmp1 and tmp2 stay void when it terminates *)
Let Q_spec1 : (iP,cP) /BSM/ (iP,v) ↓ -> exists w', Q /MM/ (1,w) ~~> (code_end Q, w') /\ w'#>tmp1 = 0 /\ w'#>tmp2 = 0.
Let Q_spec2 : Q /MM/ (1,w) ↓ -> (iP,cP) /BSM/ (iP,v) ↓.
Definition bsm_mm_sim := snd Q.
Let iE := code_end Q.
(* We complete (iQ,cQ) with some code nullifying all variables except tmp1 & tmp2 *)
Let cN := mm_nullify tmp1 iE (map (fun p => pos_nxt (pos_nxt p)) (pos_list m)).
Let cE := cN ++ DEC tmp1 0 :: nil.
Let E_spec w' : w'#>tmp1 = 0 -> w'#>tmp2 = 0 -> (iE,cE) /MM/ (iE,w') -+> (0,vec_zero).
Definition bsm_mm := snd Q ++ cE.
Let cQ_sim : Q <sc (1,bsm_mm).
Let cE_sim : (iE,cE) <sc (1,bsm_mm).
(* (1,bsm_sim) is a simulator for (iP,cP) *)
End bsm_sim.
End simulator.

Theorem bsm_mm_compiler_1 n i (P : list (bsm_instr n)) :
{ Q : list (mm_instr (pos (2+n))) | forall v, (i,P) /BSM/ (i,v) ↓ <-> (1,Q) /MM/ (1,0##0##vec_map stack_enc v) ↓ }.