Inductive CMinSel_core: Type :=
  | CMinSel_State:                      (**r execution within a function *)
      forall (f: function)              (**r currently executing function  *)
             (s: stmt)                  (**r statement under consideration *)
             (k: cont)                  (**r its continuation -- what to do next *)
             (sp: val)                  (**r current stack pointer *)
             (e: Cminor.env),           (**r current local environment *)
      CMinSel_core
  | CMinSel_Callstate:                  (**r invocation of a fundef  *)
      forall (f: fundef)                (**r fundef to invoke *)
             (args: list val)           (**r arguments provided by caller *)
             (k: cont),                 (**r what to do next  *)
      CMinSel_core
  | CMinSel_Returnstate:
      forall (v: val)                   (**r return value *)
             (k: cont),                 (**r what to do next *)
      CMinSel_core.Inductive CMinSel_core: Type :=
  | CMinSel_State:                      (**r execution within a function *)
      forall (f: function)              (**r currently executing function  *)
             (s: stmt)                  (**r statement under consideration *)
             (k: cont)                  (**r its continuation -- what to do next *)
             (sp: val)                  (**r current stack pointer *)
             (e: Cminor.env),           (**r current local environment *)
      CMinSel_core
  | CMinSel_Callstate:                  (**r invocation of a fundef  *)
      forall (f: fundef)                (**r fundef to invoke *)
             (args: list val)           (**r arguments provided by caller *)
             (k: cont),                 (**r what to do next  *)
      CMinSel_core
  | CMinSel_Returnstate:
      forall (v: val)                   (**r return value *)
             (k: cont),                 (**r what to do next *)
      CMinSel_core.Inductive CMinSel_core: Type :=
  | CMinSel_State:                      (**r execution within a function *)
      forall (f: function)              (**r currently executing function  *)
             (s: stmt)                  (**r statement under consideration *)
             (k: cont)                  (**r its continuation -- what to do next *)
             (sp: val)                  (**r current stack pointer *)
             (e: Cminor.env),           (**r current local environment *)
      CMinSel_core
  | CMinSel_Callstate:                  (**r invocation of a fundef  *)
      forall (f: fundef)                (**r fundef to invoke *)
             (args: list val)           (**r arguments provided by caller *)
             (k: cont),                 (**r what to do next  *)
      CMinSel_core
  | CMinSel_Returnstate:
      forall (v: val)                   (**r return value *)
             (k: cont),                 (**r what to do next *)
      CMinSel_core.Inductive CMinSel_core: Type :=
  | CMinSel_State:                      (**r execution within a function *)
      forall (f: function)              (**r currently executing function  *)
             (s: stmt)                  (**r statement under consideration *)
             (k: cont)                  (**r its continuation -- what to do next *)
             (sp: val)                  (**r current stack pointer *)
             (e: Cminor.env),           (**r current local environment *)
      CMinSel_core
  | CMinSel_Callstate:                  (**r invocation of a fundef  *)
      forall (f: fundef)                (**r fundef to invoke *)
             (args: list val)           (**r arguments provided by caller *)
             (k: cont),                 (**r what to do next  *)
      CMinSel_core
  | CMinSel_Returnstate:
      forall (v: val)                   (**r return value *)
             (k: cont),                 (**r what to do next *)
      CMinSel_core.Definition ToState (q:CMinSel_core) (m:mem): CminorSel.state :=
  match q with
     CMinSel_State f s k sp e => State f s k sp e m
   | CMinSel_Callstate f args k => Callstate f args k m
   | CMinSel_Returnstate v k => Returnstate v k m
  end.Definition FromState (c: CminorSel.state) : CMinSel_core * mem :=
  match c with
     State f s k sp e m => (CMinSel_State f s k sp e, m)
   | Callstate f args k m => (CMinSel_Callstate f args k, m)
   | Returnstate v k m => (CMinSel_Returnstate v k, m)
  end.Definition CMinSel_at_external (c: CMinSel_core) : option (external_function * signature * list val) :=
  match c with
  | CMinSel_State _ _ _ _ _ => None
  | CMinSel_Callstate fd args k => match fd with
                                  Internal f => None
                                | External ef => Some (ef, ef_sig ef, args)
                              end
  | CMinSel_Returnstate v k => None
 end.Definition CMinSel_after_external (vret: option val) (c: CMinSel_core) : option CMinSel_core :=
  match c with
    CMinSel_Callstate fd args k =>
         match fd with
            Internal f => None
          | External ef => match vret with
                             None => Some (CMinSel_Returnstate Vundef k)
                           | Some v => Some (CMinSel_Returnstate v k)
                           end
         end
  | _ => None
  end.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.Inductive CMinSel_corestep (ge : genv) : CMinSel_core -> mem ->
                           CMinSel_core -> mem -> Prop:=

  | cminsel_corestep_skip_seq: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kseq s k) sp e) m
        (CMinSel_State f s k sp e) m
  | cminsel_corestep_skip_block: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f Sskip (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_skip_call: forall f k sp e m m',
      is_call_cont k ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f Sskip k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef k) m'

  | cminsel_corestep_assign: forall f id a k sp e m v,
      eval_expr ge sp e m nil a v ->
      CMinSel_corestep ge (CMinSel_State f (Sassign id a) k sp e) m
        (CMinSel_State f Sskip k sp (PTree.set id v e)) m

  | cminsel_corestep_store: forall f chunk addr al b k sp e m vl v vaddr m',
      eval_exprlist ge sp e m nil al vl ->
      eval_expr ge sp e m nil b v ->
      eval_addressing ge sp addr vl = Some vaddr ->
      Mem.storev chunk m vaddr v = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sstore chunk addr al b) k sp e) m
        (CMinSel_State f Sskip k sp e) m'

  | cminsel_corestep_call: forall f optid sig a bl k sp e m vf vargs fd,
      eval_expr_or_symbol ge sp e m nil a vf ->
      eval_exprlist ge sp e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      CMinSel_corestep ge (CMinSel_State f (Scall optid sig a bl) k sp e) m
        (CMinSel_Callstate fd vargs (Kcall optid f sp e k)) m

  | cminsel_corestep_tailcall: forall f sig a bl k sp e m vf vargs fd m',
      eval_expr_or_symbol ge (Vptr sp Int.zero) e m nil a vf ->
      eval_exprlist ge (Vptr sp Int.zero) e m nil bl vargs ->
      Genv.find_funct ge vf = Some fd ->
      funsig fd = sig ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Stailcall sig a bl) k (Vptr sp Int.zero) e) m
        (CMinSel_Callstate fd vargs (call_cont k)) m'

(* WE DO NOT TREAT BUILTINS
  | cminsel_corestep_builtin: forall f optid ef al k sp e m vl t v m',
      eval_exprlist ge sp e m nil al vl ->
      external_call ef ge vl m t v m' ->
      CMinSel_corestep ge (CMinSel_State f (Sbuiltin optid ef al) k sp e) m
         (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m'
*)
  | cminsel_corestep_seq: forall f s1 s2 k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sseq s1 s2) k sp e) m
        (CMinSel_State f s1 (Kseq s2 k) sp e) m

  | cminsel_corestep_ifthenelse: forall f c s1 s2 k sp e m b,
      eval_condexpr ge sp e m nil c b ->
      CMinSel_corestep ge (CMinSel_State f (Sifthenelse c s1 s2) k sp e) m
        (CMinSel_State f (if b then s1 else s2) k sp e) m

  | cminsel_corestep_loop: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sloop s) k sp e) m
        (CMinSel_State f s (Kseq (Sloop s) k) sp e) m

  | cminsel_corestep_block: forall f s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sblock s) k sp e) m
        (CMinSel_State f s (Kblock k) sp e) m

  | cminsel_corestep_exit_seq: forall f n s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit n) (Kseq s k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m
  | cminsel_corestep_exit_block_0: forall f k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit O) (Kblock k) sp e) m
        (CMinSel_State f Sskip k sp e) m
  | cminsel_corestep_exit_block_S: forall f n k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Sexit (S n)) (Kblock k) sp e) m
        (CMinSel_State f (Sexit n) k sp e) m

  | cminsel_corestep_switch: forall f a cases default k sp e m n,
      eval_expr ge sp e m nil a (Vint n) ->
      CMinSel_corestep ge (CMinSel_State f (Sswitch a cases default) k sp e) m
        (CMinSel_State f (Sexit (switch_target n default cases)) k sp e) m

  | cminsel_corestep_return_0: forall f k sp e m m',
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn None) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate Vundef (call_cont k)) m'
  | cminsel_corestep_return_1: forall f a k sp e m v m',
      eval_expr ge (Vptr sp Int.zero) e m nil a v ->
      Mem.free m sp 0 f.(fn_stackspace) = Some m' ->
      CMinSel_corestep ge (CMinSel_State f (Sreturn (Some a)) k (Vptr sp Int.zero) e) m
        (CMinSel_Returnstate v (call_cont k)) m'

  | cminsel_corestep_label: forall f lbl s k sp e m,
      CMinSel_corestep ge (CMinSel_State f (Slabel lbl s) k sp e) m
        (CMinSel_State f s k sp e) m

  | cminsel_corestep_goto: forall f lbl k sp e m s' k',
      find_label lbl f.(fn_body) (call_cont k) = Some(s', k') ->
      CMinSel_corestep ge (CMinSel_State f (Sgoto lbl) k sp e) m
        (CMinSel_State f s' k' sp e) m

  | cminsel_corestep_internal_function: forall f vargs k m m' sp e,
      Mem.alloc m 0 f.(fn_stackspace) = (m', sp) ->
      Cminor.set_locals f.(fn_vars) (Cminor.set_params vargs f.(fn_params)) = e ->
      CMinSel_corestep ge (CMinSel_Callstate (Internal f) vargs k) m
        (CMinSel_State f f.(fn_body) k (Vptr sp Int.zero) e) m'
(*no external call
  | cminsel_corestep_external_function: forall ef vargs k m t vres m',
      external_call ef ge vargs m t vres m' ->
      step (Callstate (External ef) vargs k) m
         t (Returnstate vres k m')        *)

  | cminsel_corestep_return: forall v optid f sp e k m,
      CMinSel_corestep ge (CMinSel_Returnstate v (Kcall optid f sp e k)) m
        (CMinSel_State f Sskip k sp (Cminor.set_optvar optid v e)) m.

Lemma CMinSel_corestep_not_at_external: forall ge m q m' q', CMinSel_corestep ge q m q' m' -> CMinSel_at_external q = None.