Section MM2_CM2.
Variable (P: list mm2_instr). (* MM2 program *)
Variables (a0 b0: nat). (* MM2 initial counters *)
Definition mm2_config : Set := (nat*(nat*nat)).
(* instruction index map *)
Definition fs (i: nat) : CM2.State :=
if i is S i then i + a0 + b0 else (length P) + a0 + b0.
(* encode instruction mmi at position i using index map fs for current cm2 state p *)
Definition encode_instruction (mmi: mm2_instr) : CM2.Instruction :=
match mmi with
| mm2_inc_a => CM2.inc false
| mm2_inc_b => CM2.inc true
| mm2_dec_a j => CM2.dec false (fs j)
| mm2_dec_b j => CM2.dec true (fs j)
end.
(* two counter machine encoding P in start cofiguration (0, (0, 0)) *)
Definition M : list CM2.Instruction :=
(repeat (CM2.inc false) a0) ++ (repeat (CM2.inc true) b0) ++ map encode_instruction P.
(* encode mm2 config as cm2 config *)
Definition encode_config (x: mm2_config) : CM2.Config :=
let: (i, (a, b)) := x in {| CM2.state := fs i; CM2.value1 := a; CM2.value2 := b |}.

Lemma init_M_a0 (n: nat) : n <= a0 -> Nat.iter n (CM2.step M) {| CM2.state := 0; CM2.value1 := 0; CM2.value2 := 0 |} =
{| CM2.state := n; CM2.value1 := n; CM2.value2 := 0 |}.