Section mma_sim.
Variable (iP : nat) (cP : list (mm_instr (pos n))).
Let lnk_Q_pair := @gen_compiler_correction _ _ _ _ mma_instr_compile_length_eq _ _ _ _  (@mma_sss_total_ni _)
(@mma_sss_fun _) _ mma_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 "⋈" := (@eq (vec nat n)) (at level 70, no associativity).
Let HQ1 : forall i1 v1 w1 i2 v2, v1 ⋈ w1 /\ (iP,cP) // (i1,v1) ~~> (i2,v2)
-> exists w2,    v2 ⋈ w2 /\ Q // (lnk i1,w1) ~~> (lnk i2,w2).
Let HQ2 : forall i1 v1 w1 j2 w2, v1 ⋈ w1 /\ Q // (lnk i1,w1) ~~> (j2,w2)
-> exists i2 v2, v2 ⋈ w2 /\ (iP,cP) // (i1,v1) ~~> (i2,v2) /\ j2 = lnk i2.
Variable v : vec nat n.
(* Q simulates termination of (iP,cP) while ensuring tmp1 and tmp2 stay void when it terminates *)
Let Q_spec1 : (iP,cP) // (iP,v) ↓ -> exists w', Q // (1,v) ~~> (code_end Q, w').
Let Q_spec2 : Q // (1,v) ↓ -> (iP,cP) // (iP,v) ↓.
Definition mma_sim := snd Q.
Definition mma_sim_end := code_end Q.

Theorem mma_sim_spec : ((iP,cP) // (iP,v) ↓ -> exists w', (1,mma_sim) // (1,v) ~~> (1+length mma_sim, w'))
/\ ((1,mma_sim) // (1,v) ↓ -> (iP,cP) // (iP,v) ↓).