(** * Memory values *)

(** A ``memory value'' is a byte-sized quantity that describes the current
  content of a memory cell.  It can be either:
- a concrete 8-bit integer;
- a byte-sized fragment of an opaque value;
- the special constant [Undef] that represents uninitialized memory.
*)

(** Values stored in memory cells. *)

Inductive memval: Type :=
  | Undef: memval
  | Byte: byte -> memval
  | Fragment: val -> quantity -> nat -> memval.(** * Memory values *)

(** A ``memory value'' is a byte-sized quantity that describes the current
  content of a memory cell.  It can be either:
- a concrete 8-bit integer;
- a byte-sized fragment of an opaque value;
- the special constant [Undef] that represents uninitialized memory.
*)

(** Values stored in memory cells. *)

Inductive memval: Type :=
  | Undef: memval
  | Byte: byte -> memval
  | Fragment: val -> quantity -> nat -> memval.(** * Memory values *)

(** A ``memory value'' is a byte-sized quantity that describes the current
  content of a memory cell.  It can be either:
- a concrete 8-bit integer;
- a byte-sized fragment of an opaque value;
- the special constant [Undef] that represents uninitialized memory.
*)

(** Values stored in memory cells. *)

Inductive memval: Type :=
  | Undef: memval
  | Byte: byte -> memval
  | Fragment: val -> quantity -> nat -> memval.(** * Memory values *)

(** A ``memory value'' is a byte-sized quantity that describes the current
  content of a memory cell.  It can be either:
- a concrete 8-bit integer;
- a byte-sized fragment of an opaque value;
- the special constant [Undef] that represents uninitialized memory.
*)

(** Values stored in memory cells. *)

Inductive memval: Type :=
  | Undef: memval
  | Byte: byte -> memval
  | Fragment: val -> quantity -> nat -> memval.(** * Encoding and decoding integers *)

(** We define functions to convert between integers and lists of bytes
  of a given length *)

Fixpoint bytes_of_int (n: nat) (x: Z) {struct n}: list byte :=
  match n with
  | O => nil
  | S m => Byte.repr x :: bytes_of_int m (x / 256)
  end.Fixpoint int_of_bytes (l: list byte): Z :=
  match l with
  | nil => 0
  | b :: l' => Byte.unsigned b + int_of_bytes l' * 256
  end.Definition rev_if_be (l: list byte) : list byte :=
  if Archi.big_endian then List.rev l else l.Definition encode_int (sz: nat) (x: Z) : list byte :=
  rev_if_be (bytes_of_int sz x).Definition decode_int (b: list byte) : Z :=
  int_of_bytes (rev_if_be b).

(* Specifications: *)
Lemma length_bytes_of_int: forall n x, length (bytes_of_int n x) = n.
Lemma rev_if_be_length: forall l, length (rev_if_be l) = length l.
Lemma encode_int_length: forall sz x, length(encode_int sz x) = sz.
Lemma int_of_bytes_of_int: forall n x, int_of_bytes (bytes_of_int n x) = x mod (two_p (Z.of_nat n * 8)).
Lemma rev_if_be_involutive: forall l, rev_if_be (rev_if_be l) = l.
Lemma decode_encode_int: forall n x, decode_int (encode_int n x) = x mod (two_p (Z.of_nat n * 8)).
Lemma decode_encode_int_1: forall x, Int.repr (decode_int (encode_int 1 (Int.unsigned x))) = Int.zero_ext 8 x.
Lemma decode_encode_int_2: forall x, Int.repr (decode_int (encode_int 2 (Int.unsigned x))) = Int.zero_ext 16 x.
Lemma decode_encode_int_4: forall x, Int.repr (decode_int (encode_int 4 (Int.unsigned x))) = x.
Lemma decode_encode_int_8: forall x, Int64.repr (decode_int (encode_int 8 (Int64.unsigned x))) = x.
Lemma bytes_of_int_mod: forall n x y, Int.eqmod (two_p (Z.of_nat n * 8)) x y -> bytes_of_int n x = bytes_of_int n y.
Lemma encode_int_8_mod: forall x y, Int.eqmod (two_p 8) x y -> encode_int 1%nat x = encode_int 1%nat y.
Lemma encode_int_16_mod: forall x y, Int.eqmod (two_p 16) x y -> encode_int 2%nat x = encode_int 2%nat y.
Lemma length_bytes_of_int: forall n x, length (bytes_of_int n x) = n.
Lemma rev_if_be_length: forall l, length (rev_if_be l) = length l.
Lemma encode_int_length: forall sz x, length(encode_int sz x) = sz.
Lemma int_of_bytes_of_int: forall n x, int_of_bytes (bytes_of_int n x) = x mod (two_p (Z.of_nat n * 8)).
Lemma rev_if_be_involutive: forall l, rev_if_be (rev_if_be l) = l.
Lemma decode_encode_int: forall n x, decode_int (encode_int n x) = x mod (two_p (Z.of_nat n * 8)).
Lemma decode_encode_int_1: forall x, Int.repr (decode_int (encode_int 1 (Int.unsigned x))) = Int.zero_ext 8 x.
Lemma decode_encode_int_2: forall x, Int.repr (decode_int (encode_int 2 (Int.unsigned x))) = Int.zero_ext 16 x.
Lemma decode_encode_int_4: forall x, Int.repr (decode_int (encode_int 4 (Int.unsigned x))) = x.
Lemma decode_encode_int_8: forall x, Int64.repr (decode_int (encode_int 8 (Int64.unsigned x))) = x.
Lemma bytes_of_int_mod: forall n x y, Int.eqmod (two_p (Z.of_nat n * 8)) x y -> bytes_of_int n x = bytes_of_int n y.
Lemma encode_int_8_mod: forall x y, Int.eqmod (two_p 8) x y -> encode_int 1%nat x = encode_int 1%nat y.
Lemma encode_int_16_mod: forall x y, Int.eqmod (two_p 16) x y -> encode_int 2%nat x = encode_int 2%nat y.