Section COMPARISONS.
Variable valid_ptr: block -> Z -> bool.
Let weak_valid_ptr (b: block) (ofs: Z) := valid_ptr b ofs || valid_ptr b (ofs - 1).
Definition cmp_bool (c: comparison) (v1 v2: val): option bool :=
match v1, v2 with
| Vint n1, Vint n2 => Some (Int.cmp c n1 n2)
| _, _ => None
end.
Definition cmp_different_blocks (c: comparison): option bool :=
match c with
| Ceq => Some false
| Cne => Some true
| _   => None
end.
Definition cmpu_bool (c: comparison) (v1 v2: val): option bool :=
match v1, v2 with
| Vint n1, Vint n2 =>
Some (Int.cmpu c n1 n2)
| Vint n1, Vptr b2 ofs2 =>
if Archi.ptr64 then None else
if Int.eq n1 Int.zero && weak_valid_ptr b2 (Ptrofs.unsigned ofs2)
then cmp_different_blocks c
else None
| Vptr b1 ofs1, Vptr b2 ofs2 =>
if Archi.ptr64 then None else
if eq_block b1 b2 then
if weak_valid_ptr b1 (Ptrofs.unsigned ofs1)
&& weak_valid_ptr b2 (Ptrofs.unsigned ofs2)
then Some (Ptrofs.cmpu c ofs1 ofs2)
else None
else
if valid_ptr b1 (Ptrofs.unsigned ofs1)
&& valid_ptr b2 (Ptrofs.unsigned ofs2)
then cmp_different_blocks c
else None
| Vptr b1 ofs1, Vint n2 =>
if Archi.ptr64 then None else
if Int.eq n2 Int.zero && weak_valid_ptr b1 (Ptrofs.unsigned ofs1)
then cmp_different_blocks c
else None
| _, _ => None
end.
Definition cmpf_bool (c: comparison) (v1 v2: val): option bool :=
match v1, v2 with
| Vfloat f1, Vfloat f2 => Some (Float.cmp c f1 f2)
| _, _ => None
end.
Definition cmpfs_bool (c: comparison) (v1 v2: val): option bool :=
match v1, v2 with
| Vsingle f1, Vsingle f2 => Some (Float32.cmp c f1 f2)
| _, _ => None
end.
Definition cmpl_bool (c: comparison) (v1 v2: val): option bool :=
match v1, v2 with
| Vlong n1, Vlong n2 => Some (Int64.cmp c n1 n2)
| _, _ => None
end.
Definition cmplu_bool (c: comparison) (v1 v2: val): option bool :=
match v1, v2 with
| Vlong n1, Vlong n2 => Some (Int64.cmpu c n1 n2)
| Vlong n1, Vptr b2 ofs2 =>
if negb Archi.ptr64 then None else
if Int64.eq n1 Int64.zero && weak_valid_ptr b2 (Ptrofs.unsigned ofs2)
then cmp_different_blocks c
else None
| Vptr b1 ofs1, Vptr b2 ofs2 =>
if negb Archi.ptr64 then None else
if eq_block b1 b2 then
if weak_valid_ptr b1 (Ptrofs.unsigned ofs1)
&& weak_valid_ptr b2 (Ptrofs.unsigned ofs2)
then Some (Ptrofs.cmpu c ofs1 ofs2)
else None
else
if valid_ptr b1 (Ptrofs.unsigned ofs1)
&& valid_ptr b2 (Ptrofs.unsigned ofs2)
then cmp_different_blocks c
else None
| Vptr b1 ofs1, Vlong n2 =>
if negb Archi.ptr64 then None else
if Int64.eq n2 Int64.zero && weak_valid_ptr b1 (Ptrofs.unsigned ofs1)
then cmp_different_blocks c
else None
| _, _ => None
end.
Definition of_optbool (ob: option bool): val :=
match ob with Some true => Vtrue | Some false => Vfalse | None => Vundef end.
Definition cmp (c: comparison) (v1 v2: val): val :=
of_optbool (cmp_bool c v1 v2).
Definition cmpu (c: comparison) (v1 v2: val): val :=
of_optbool (cmpu_bool c v1 v2).
Definition cmpf (c: comparison) (v1 v2: val): val :=
of_optbool (cmpf_bool c v1 v2).
Definition cmpfs (c: comparison) (v1 v2: val): val :=
of_optbool (cmpfs_bool c v1 v2).
Definition cmpl (c: comparison) (v1 v2: val): option val :=
option_map of_bool (cmpl_bool c v1 v2).
Definition cmplu (c: comparison) (v1 v2: val): option val :=
option_map of_bool (cmplu_bool c v1 v2).
Definition maskzero_bool (v: val) (mask: int): option bool :=
match v with
| Vint n => Some (Int.eq (Int.and n mask) Int.zero)
| _ => None
end.
End COMPARISONS.
(** Add the given offset to the given pointer. *)
Definition offset_ptr (v: val) (delta: ptrofs) : val :=
match v with
| Vptr b ofs => Vptr b (Ptrofs.add ofs delta)
| _ => Vundef
end.
(** Normalize a value to the given type, turning it into Vundef if it does not match the type. *)
Definition normalize (v: val) (ty: typ) : val :=
match v, ty with
| Vundef, _ => Vundef
| Vint _, Tint => v
| Vlong _, Tlong => v
| Vfloat _, Tfloat => v
| Vsingle _, Tsingle => v
| Vptr _ _, (Tint | Tany32) => if Archi.ptr64 then Vundef else v
| Vptr _ _, Tlong => if Archi.ptr64 then v else Vundef
| (Vint _ | Vsingle _), Tany32 => v
| _, Tany64 => v
| _, _ => Vundef
end.

Lemma normalize_idem:
forall v ty, has_type v ty -> normalize v ty = v.