Record t : Type :=
  mk { pre_mem  : mem
     ; post_mem : mem
     ; args : list val
     ; rv   : option val }.Record t : Type :=
  mk { pre_mem  : mem
     ; post_mem : mem
     ; args : list val
     ; rv   : option val }.Record t : Type :=
  mk { pre_mem  : mem
     ; post_mem : mem
     ; args : list val
     ; rv   : option val }.Record t : Type :=
  mk { pre_mem  : mem
     ; post_mem : mem
     ; args : list val
     ; rv   : option val }.Record t : Type :=
  mk { pre_mem  : mem
     ; post_mem : mem
     ; args : list val
     ; rv   : option val }.Record t : Type :=
  mk { pre_mem  : mem
     ; post_mem : mem
     ; args : list val
     ; rv   : option val }.Definition yielded c :=
  (exists ef sig args, at_external sem c = Some (ef, sig, args))
  \/ exists rv, halted sem c = Some rv.Inductive step
: G -> (Z*list Event.t*C) -> mem -> (Z*list Event.t*C) -> mem -> Prop :=
| trace_step :
  forall ge tr z c m c' m',
  corestep sem ge c m c' m' ->
  step ge (z,tr,c) m (z,tr,c') m'
| trace_extern :
  forall ge tr z c m z' c' m' ef sig args rv x,
  at_external sem c = Some (ef, sig, args) ->
  Mem.unchanged_on (fun b ofs => REACH m (getBlocks args) b=false) m m' ->
  mem_forward m m' ->
  ext_spec_pre spec ef x (sig_args sig) args z m ->
  ext_spec_post spec ef x (sig_res sig) (Some rv) z' m' ->
  after_external sem (Some rv) c = Some c' ->
  step ge (z,tr,c) m (z',Event.mk m m' args (Some rv) :: tr,c') m'.Inductive step
: G -> (Z*list Event.t*C) -> mem -> (Z*list Event.t*C) -> mem -> Prop :=
| trace_step :
  forall ge tr z c m c' m',
  corestep sem ge c m c' m' ->
  step ge (z,tr,c) m (z,tr,c') m'
| trace_extern :
  forall ge tr z c m z' c' m' ef sig args rv x,
  at_external sem c = Some (ef, sig, args) ->
  Mem.unchanged_on (fun b ofs => REACH m (getBlocks args) b=false) m m' ->
  mem_forward m m' ->
  ext_spec_pre spec ef x (sig_args sig) args z m ->
  ext_spec_post spec ef x (sig_res sig) (Some rv) z' m' ->
  after_external sem (Some rv) c = Some c' ->
  step ge (z,tr,c) m (z',Event.mk m m' args (Some rv) :: tr,c') m'.Inductive step
: G -> (Z*list Event.t*C) -> mem -> (Z*list Event.t*C) -> mem -> Prop :=
| trace_step :
  forall ge tr z c m c' m',
  corestep sem ge c m c' m' ->
  step ge (z,tr,c) m (z,tr,c') m'
| trace_extern :
  forall ge tr z c m z' c' m' ef sig args rv x,
  at_external sem c = Some (ef, sig, args) ->
  Mem.unchanged_on (fun b ofs => REACH m (getBlocks args) b=false) m m' ->
  mem_forward m m' ->
  ext_spec_pre spec ef x (sig_args sig) args z m ->
  ext_spec_post spec ef x (sig_res sig) (Some rv) z' m' ->
  after_external sem (Some rv) c = Some c' ->
  step ge (z,tr,c) m (z',Event.mk m m' args (Some rv) :: tr,c') m'.Definition initial_core (ge : G) (v : val) (vs : list val)
  : option (Z*list Event.t*C) :=
  match initial_core sem ge v vs with
    | Some c => Some (z_init, nil, c)
    | None => None
  end.Definition halted (c : Z*list Event.t*C) := halted sem (snd c).Program Definition coresem : CoreSemantics G (Z*list Event.t*C) mem :=
  @Build_CoreSemantics G (Z*list Event.t*C) mem
  initial_core
  (fun _ => None)
  (fun _ _ => None)
  halted
  step
  _ _ _ _.Program Definition coopsem : CoopCoreSem G (Z*list Event.t*C) :=
  @Build_CoopCoreSem G (Z*list Event.t*C) coresem _.

Lemma corestepN_geq ge c m c' m' c'' m'' z tr z' tr' n1 n2 : corestep_fun sem -> corestepN sem ge n1 c m c' m' -> corestepN coopsem ge n2 (z,tr,c) m (z',tr',c'') m'' -> (n1 >= n2)%nat -> z=z' /\ tr=tr'.