Section STRAIGHTLINE.
Variable ge: genv.
Variable fn: function.
(** Straight-line code is composed of processor instructions that execute in sequence (no branches, no function calls and returns). The following inductive predicate relates the machine states before and after executing a straight-line sequence of instructions. Instructions are taken from the first list instead of being fetched from memory. *)
Inductive exec_straight: code -> regset -> mem ->
code -> regset -> mem -> Prop :=
| exec_straight_one:
forall i1 c rs1 m1 rs2 m2,
exec_instr ge fn i1 rs1 m1 = Next rs2 m2 ->
rs2#PC = Val.offset_ptr rs1#PC Ptrofs.one ->
exec_straight (i1 :: c) rs1 m1 c rs2 m2
| exec_straight_step:
forall i c rs1 m1 rs2 m2 c' rs3 m3,
exec_instr ge fn i rs1 m1 = Next rs2 m2 ->
rs2#PC = Val.offset_ptr rs1#PC Ptrofs.one ->
exec_straight c rs2 m2 c' rs3 m3 ->
exec_straight (i :: c) rs1 m1 c' rs3 m3.
(** The following lemmas show that straight-line executions (predicate [exec_straight]) correspond to correct Asm executions. *)
(** A variant that supports zero steps of execution *)
Inductive exec_straight_opt: code -> regset -> mem -> code -> regset -> mem -> Prop :=
| exec_straight_opt_refl: forall c rs m,
exec_straight_opt c rs m c rs m
| exec_straight_opt_intro: forall c1 rs1 m1 c2 rs2 m2,
exec_straight c1 rs1 m1 c2 rs2 m2 ->
exec_straight_opt c1 rs1 m1 c2 rs2 m2.

Lemma exec_straight_opt_step_opt:
forall i c rs1 m1 rs2 m2 c' rs3 m3,
exec_instr ge fn i rs1 m1 = Next rs2 m2 ->
rs2#PC = Val.offset_ptr rs1#PC Ptrofs.one ->
exec_straight_opt c rs2 m2 c' rs3 m3 ->
exec_straight_opt (i :: c) rs1 m1 c' rs3 m3.