Definition unary_constructor_sound (cstr: expr -> expr) (sem: val -> val) : Prop :=
  forall le a x,
  eval_expr ge sp e m le a x ->
  exists v, eval_expr ge sp e m le (cstr a) v /\ Val.lessdef (sem x) v.Definition binary_constructor_sound (cstr: expr -> expr -> expr) (sem: val -> val -> val) : Prop :=
  forall le a x b y,
  eval_expr ge sp e m le a x ->
  eval_expr ge sp e m le b y ->
  exists v, eval_expr ge sp e m le (cstr a b) v /\ Val.lessdef (sem x y) v.

(* Specifications: *)
Lemma eval_splitlong: forall le a f v sem, (forall le a b x y, eval_expr ge sp e m le a x -> eval_expr ge sp e m le b y -> exists v, eval_expr ge sp e m le (f a b) v /\ (forall p q, x = Vint p -> y = Vint q -> v = sem (Vlong (Int64.ofwords p q)))) -> match v with Vlong _ => True | _ => sem v = Vundef end -> eval_expr ge sp e m le a v -> exists v', eval_expr ge sp e m le (splitlong a f) v' /\ Val.lessdef (sem v) v'.
Lemma eval_splitlong_strict: forall le a f va v, eval_expr ge sp e m le a (Vlong va) -> (forall le a1 a2, eval_expr ge sp e m le a1 (Vint (Int64.hiword va)) -> eval_expr ge sp e m le a2 (Vint (Int64.loword va)) -> eval_expr ge sp e m le (f a1 a2) v) -> eval_expr ge sp e m le (splitlong a f) v.
Lemma eval_splitlong2: forall le a b f va vb sem, (forall le a1 a2 b1 b2 x1 x2 y1 y2, eval_expr ge sp e m le a1 x1 -> eval_expr ge sp e m le a2 x2 -> eval_expr ge sp e m le b1 y1 -> eval_expr ge sp e m le b2 y2 -> exists v, eval_expr ge sp e m le (f a1 a2 b1 b2) v /\ (forall p1 p2 q1 q2, x1 = Vint p1 -> x2 = Vint p2 -> y1 = Vint q1 -> y2 = Vint q2 -> v = sem (Vlong (Int64.ofwords p1 p2)) (Vlong (Int64.ofwords q1 q2)))) -> match va, vb with Vlong _, Vlong _ => True | _, _ => sem va vb = Vundef end -> eval_expr ge sp e m le a va -> eval_expr ge sp e m le b vb -> exists v, eval_expr ge sp e m le (splitlong2 a b f) v /\ Val.lessdef (sem va vb) v.
Lemma eval_splitlong2_strict: forall le a b f va vb v, eval_expr ge sp e m le a (Vlong va) -> eval_expr ge sp e m le b (Vlong vb) -> (forall le a1 a2 b1 b2, eval_expr ge sp e m le a1 (Vint (Int64.hiword va)) -> eval_expr ge sp e m le a2 (Vint (Int64.loword va)) -> eval_expr ge sp e m le b1 (Vint (Int64.hiword vb)) -> eval_expr ge sp e m le b2 (Vint (Int64.loword vb)) -> eval_expr ge sp e m le (f a1 a2 b1 b2) v) -> eval_expr ge sp e m le (splitlong2 a b f) v.
Lemma is_longconst_sound: forall le a x n, is_longconst a = Some n -> eval_expr ge sp e m le a x -> x = Vlong n.
Lemma is_longconst_zero_sound: forall le a x, is_longconst_zero a = true -> eval_expr ge sp e m le a x -> x = Vlong Int64.zero.
Lemma eval_lowlong: unary_constructor_sound lowlong Val.loword.
Lemma eval_highlong: unary_constructor_sound highlong Val.hiword.
Lemma eval_longconst: forall le n, eval_expr ge sp e m le (longconst n) (Vlong n).
Theorem eval_intoflong: unary_constructor_sound intoflong Val.loword.
Theorem eval_longofintu: unary_constructor_sound longofintu Val.longofintu.
Theorem eval_longofint: unary_constructor_sound longofint Val.longofint.
Theorem eval_negl: unary_constructor_sound negl Val.negl.
Theorem eval_notl: unary_constructor_sound notl Val.notl.
Theorem eval_longoffloat: forall le a x y, eval_expr ge sp e m le a x -> Val.longoffloat x = Some y -> exists v, eval_expr ge sp e m le (longoffloat a) v /\ Val.lessdef y v.
Theorem eval_longuoffloat: forall le a x y, eval_expr ge sp e m le a x -> Val.longuoffloat x = Some y -> exists v, eval_expr ge sp e m le (longuoffloat a) v /\ Val.lessdef y v.
Theorem eval_floatoflong: forall le a x y, eval_expr ge sp e m le a x -> Val.floatoflong x = Some y -> exists v, eval_expr ge sp e m le (floatoflong a) v /\ Val.lessdef y v.
Theorem eval_floatoflongu: forall le a x y, eval_expr ge sp e m le a x -> Val.floatoflongu x = Some y -> exists v, eval_expr ge sp e m le (floatoflongu a) v /\ Val.lessdef y v.
Theorem eval_longofsingle: forall le a x y, eval_expr ge sp e m le a x -> Val.longofsingle x = Some y -> exists v, eval_expr ge sp e m le (longofsingle a) v /\ Val.lessdef y v.
Theorem eval_longuofsingle: forall le a x y, eval_expr ge sp e m le a x -> Val.longuofsingle x = Some y -> exists v, eval_expr ge sp e m le (longuofsingle a) v /\ Val.lessdef y v.
Theorem eval_singleoflong: forall le a x y, eval_expr ge sp e m le a x -> Val.singleoflong x = Some y -> exists v, eval_expr ge sp e m le (singleoflong a) v /\ Val.lessdef y v.
Theorem eval_singleoflongu: forall le a x y, eval_expr ge sp e m le a x -> Val.singleoflongu x = Some y -> exists v, eval_expr ge sp e m le (singleoflongu a) v /\ Val.lessdef y v.
Theorem eval_andl: binary_constructor_sound andl Val.andl.
Theorem eval_orl: binary_constructor_sound orl Val.orl.
Theorem eval_xorl: binary_constructor_sound xorl Val.xorl.
Lemma is_intconst_sound: forall le a x n, is_intconst a = Some n -> eval_expr ge sp e m le a x -> x = Vint n.