(** Offset an addressing mode [addr] by a quantity [delta], so that
  it designates the pointer [delta] bytes past the pointer designated
  by [addr].  This may be undefined if an offset overflows, in which case
  [None] is returned.  *)

Definition offset_addressing_total (addr: addressing) (delta: Z) : addressing :=
  match addr with
  | Aindexed n => Aindexed (n + delta)
  | Aindexed2 n => Aindexed2 (n + delta)
  | Ascaled sc n => Ascaled sc (n + delta)
  | Aindexed2scaled sc n => Aindexed2scaled sc (n + delta)
  | Aglobal s n => Aglobal s (Ptrofs.add n (Ptrofs.repr delta))
  | Abased s n => Abased s (Ptrofs.add n (Ptrofs.repr delta))
  | Abasedscaled sc s n => Abasedscaled sc s (Ptrofs.add n (Ptrofs.repr delta))
  | Ainstack n => Ainstack (Ptrofs.add n (Ptrofs.repr delta))
  end.Definition offset_addressing (addr: addressing) (delta: Z) : option addressing :=
  let addr' := offset_addressing_total addr delta in
  if addressing_valid addr' then Some addr' else None.

Lemma eval_offset_addressing: forall (F V: Type) (ge: Genv.t F V) sp addr args delta addr' v, offset_addressing addr delta = Some addr' -> eval_addressing ge sp addr args = Some v -> Archi.ptr64 = false -> eval_addressing ge sp addr' args = Some(Val.add v (Vint (Int.repr delta))).