(* *********************************************************************)
(*                                                                     *)
(*              The Compcert verified compiler                         *)
(*                                                                     *)
(*                  Xavier Leroy, INRIA Paris                          *)
(*                                                                     *)
(*  Copyright Institut National de Recherche en Informatique et en     *)
(*  Automatique.  All rights reserved.  This file is distributed       *)
(*  under the terms of the INRIA Non-Commercial License Agreement.     *)
(*                                                                     *)
(* *********************************************************************)

(** Correctness proof for x86-64 generation: auxiliary results. *)

Require Import Coqlib.
Require Import AST Errors Integers Floats Values Memory Globalenvs.
Require Import Op Locations Conventions Mach Asm.
Require Import Asmgen Asmgenproof0.

Local Open Scope error_monad_scope.

(** * Correspondence between Mach registers and x86 registers *)

Lemma agree_nextinstr_nf:
  forall ms sp rs,
  agree ms sp rs -> agree ms sp (nextinstr_nf rs).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold nextinstr_nf. apply agree_nextinstr.
(* Goal: agree ms sp (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs) *)
  apply agree_undef_nondata_regs. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  simpl; intros. intuition (subst r; auto).
Qed.

(** Useful properties of the PC register. *)

Lemma nextinstr_nf_inv:
  forall r rs,
  match r with PC => False | CR _ => False | _ => True end ->
  (nextinstr_nf rs)#r = rs#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold nextinstr_nf. rewrite nextinstr_inv.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. repeat rewrite Pregmap.gso; auto;
(* Goal: not (@eq preg r PC) *)
  red; intro; subst; contradiction.
(* Goal: not (@eq preg r PC) *)
  red; intro; subst; contradiction.
Qed.

Lemma nextinstr_nf_inv1:
  forall r rs,
  data_preg r = true -> (nextinstr_nf rs)#r = rs#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. apply nextinstr_nf_inv. destruct r; auto || discriminate.
Qed.

Lemma nextinstr_nf_set_preg:
  forall rs m v,
  (nextinstr_nf (rs#(preg_of m) <- v))#PC = Val.offset_ptr rs#PC Ptrofs.one.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold nextinstr_nf.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  transitivity (nextinstr (rs#(preg_of m) <- v) PC). auto.
(* Goal: @eq val (nextinstr (@Pregmap.set val (preg_of m) v rs) PC) (Val.offset_ptr (rs PC) Ptrofs.one) *)
  apply nextinstr_set_preg.
Qed.

(** Useful simplification tactic *)

Ltac Simplif :=
  match goal with
  | [ |- nextinstr_nf _ _ = _ ] =>
      ((rewrite nextinstr_nf_inv by auto with asmgen)
       || (rewrite nextinstr_nf_inv1 by auto with asmgen)); auto
  | [ |- nextinstr _ _ = _ ] =>
      ((rewrite nextinstr_inv by auto with asmgen)
       || (rewrite nextinstr_inv1 by auto with asmgen)); auto
  | [ |- Pregmap.get ?x (Pregmap.set ?x _ _) = _ ] =>
      rewrite Pregmap.gss; auto
  | [ |- Pregmap.set ?x _ _ ?x = _ ] =>
      rewrite Pregmap.gss; auto
  | [ |- Pregmap.get _ (Pregmap.set _ _ _) = _ ] =>
      rewrite Pregmap.gso by (auto with asmgen); auto
  | [ |- Pregmap.set _ _ _ _ = _ ] =>
      rewrite Pregmap.gso by (auto with asmgen); auto
  end.

Ltac Simplifs := repeat Simplif.

(** * Correctness of x86-64 constructor functions *)

Section CONSTRUCTORS.

Variable ge: genv.
Variable fn: function.

(** Smart constructor for moves. *)

Lemma mk_mov_correct:
  forall rd rs k c rs1 m,
  mk_mov rd rs k = OK c ->
  exists rs2,
     exec_straight ge fn c rs1 m k rs2 m
  /\ rs2#rd = rs1#rs
  /\ forall r, data_preg r = true -> r <> rd -> rs2#r = rs1#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold mk_mov; intros.
  destruct rd; try (monadInv H); destruct rs; monadInv H.
(* mov *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. simpl. eauto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. Simplifs. intros; Simplifs.
(* movsd *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. simpl. eauto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. Simplifs. intros; Simplifs.
Qed.

(** Properties of division *)

Lemma divu_modu_exists:
  forall v1 v2,
  Val.divu v1 v2 <> None \/ Val.modu v1 v2 <> None ->
  exists n d q r,
     v1 = Vint n /\ v2 = Vint d
  /\ Int.divmodu2 Int.zero n d = Some(q, r)
  /\ Val.divu v1 v2 = Some (Vint q) /\ Val.modu v1 v2 = Some (Vint r).
Proof.
(* Goal: forall (v1 v2 : val) (_ : or (not (@eq (option val) (Val.divu v1 v2) (@None val))) (not (@eq (option val) (Val.modu v1 v2) (@None val)))), @ex Int.int (fun n : Int.int => @ex Int.int (fun d : Int.int => @ex Int.int (fun q : Int.int => @ex Int.int (fun r : Int.int => and (@eq val v1 (Vint n)) (and (@eq val v2 (Vint d)) (and (@eq (option (prod Int.int Int.int)) (Int.divmodu2 Int.zero n d) (@Some (prod Int.int Int.int) (@pair Int.int Int.int q r))) (and (@eq (option val) (Val.divu v1 v2) (@Some val (Vint q))) (@eq (option val) (Val.modu v1 v2) (@Some val (Vint r)))))))))) *)
  intros v1 v2; unfold Val.divu, Val.modu.
(* Goal: forall _ : or (not (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))) (not (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl v1 (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val v1 (Vlong nl)) (and (@eq val v2 (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong q))) (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong r)))))))))))) *)
  destruct v1; try (intuition discriminate).
(* Goal: forall _ : or (not (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))) (not (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl (Vlong i) (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val (Vlong i) (Vlong nl)) (and (@eq val v2 (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong q))) (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong r)))))))))))) *)
  destruct v2; try (intuition discriminate).
(* Goal: forall _ : or (not (@eq (option val) (if Int.eq i0 Int.zero then @None val else @Some val (Vint (Int.divu i i0))) (@None val))) (not (@eq (option val) (if Int.eq i0 Int.zero then @None val else @Some val (Vint (Int.modu i i0))) (@None val))), @ex Int.int (fun n : Int.int => @ex Int.int (fun d : Int.int => @ex Int.int (fun q : Int.int => @ex Int.int (fun r : Int.int => and (@eq val (Vint i) (Vint n)) (and (@eq val (Vint i0) (Vint d)) (and (@eq (option (prod Int.int Int.int)) (Int.divmodu2 Int.zero n d) (@Some (prod Int.int Int.int) (@pair Int.int Int.int q r))) (and (@eq (option val) (if Int.eq i0 Int.zero then @None val else @Some val (Vint (Int.divu i i0))) (@Some val (Vint q))) (@eq (option val) (if Int.eq i0 Int.zero then @None val else @Some val (Vint (Int.modu i i0))) (@Some val (Vint r)))))))))) *)
  predSpec Int.eq Int.eq_spec i0 Int.zero ; try (intuition discriminate).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  intros _. exists i, i0, (Int.divu i i0), (Int.modu i i0); intuition auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply Int.divmodu2_divu_modu; auto.
Qed.

Lemma divs_mods_exists:
  forall v1 v2,
  Val.divs v1 v2 <> None \/ Val.mods v1 v2 <> None ->
  exists nh nl d q r,
     Val.shr v1 (Vint (Int.repr 31)) = Vint nh /\ v1 = Vint nl /\ v2 = Vint d
  /\ Int.divmods2 nh nl d = Some(q, r)
  /\ Val.divs v1 v2 = Some (Vint q) /\ Val.mods v1 v2 = Some (Vint r).
Proof.
(* Goal: forall (v1 v2 : val) (_ : or (not (@eq (option val) (Val.divs v1 v2) (@None val))) (not (@eq (option val) (Val.mods v1 v2) (@None val)))), @ex Int.int (fun nh : Int.int => @ex Int.int (fun nl : Int.int => @ex Int.int (fun d : Int.int => @ex Int.int (fun q : Int.int => @ex Int.int (fun r : Int.int => and (@eq val (Val.shr v1 (Vint (Int.repr (Zpos (xI (xI (xI (xI xH)))))))) (Vint nh)) (and (@eq val v1 (Vint nl)) (and (@eq val v2 (Vint d)) (and (@eq (option (prod Int.int Int.int)) (Int.divmods2 nh nl d) (@Some (prod Int.int Int.int) (@pair Int.int Int.int q r))) (and (@eq (option val) (Val.divs v1 v2) (@Some val (Vint q))) (@eq (option val) (Val.mods v1 v2) (@Some val (Vint r)))))))))))) *)
  intros v1 v2; unfold Val.divs, Val.mods.
(* Goal: forall _ : or (not (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))) (not (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl v1 (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val v1 (Vlong nl)) (and (@eq val v2 (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong q))) (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong r)))))))))))) *)
  destruct v1; try (intuition discriminate).
(* Goal: forall _ : or (not (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))) (not (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl (Vlong i) (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val (Vlong i) (Vlong nl)) (and (@eq val v2 (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong q))) (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong r)))))))))))) *)
  destruct v2; try (intuition discriminate).
  destruct (Int.eq i0 Int.zero
            || Int.eq i (Int.repr Int.min_signed) && Int.eq i0 Int.mone) eqn:OK;
  try (intuition discriminate).
(* Goal: forall _ : or (not (@eq (option val) (@Some val (Vlong (Int64.divs i i0))) (@None val))) (not (@eq (option val) (@Some val (Vlong (Int64.mods i i0))) (@None val))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl (Vlong i) (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val (Vlong i) (Vlong nl)) (and (@eq val (Vlong i0) (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) (@Some val (Vlong (Int64.divs i i0))) (@Some val (Vlong q))) (@eq (option val) (@Some val (Vlong (Int64.mods i i0))) (@Some val (Vlong r)))))))))))) *)
  intros _.
(* Goal: @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl (Vlong i) (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val (Vlong i) (Vlong nl)) (and (@eq val (Vlong i0) (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) (@Some val (Vlong (Int64.divs i i0))) (@Some val (Vlong q))) (@eq (option val) (@Some val (Vlong (Int64.mods i i0))) (@Some val (Vlong r)))))))))))) *)
  InvBooleans.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  exists (Int.shr i (Int.repr 31)), i, i0, (Int.divs i i0), (Int.mods i i0); intuition auto.
(* Goal: @eq (option (prod Int.int Int.int)) (Int.divmods2 (Int.shr i (Int.repr (Zpos (xI (xI (xI (xI xH))))))) i i0) (@Some (prod Int.int Int.int) (@pair Int.int Int.int (Int.divs i i0) (Int.mods i i0))) *)
  rewrite Int.shr_lt_zero. apply Int.divmods2_divs_mods.
(* Goal: not (@eq Int.int i0 Int.zero) *)
(* Goal: or (not (@eq Int.int i (Int.repr Int.min_signed))) (not (@eq Int.int i0 Int.mone)) *)
  red; intros; subst i0; rewrite Int.eq_true in H; discriminate.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  revert H0. predSpec Int.eq Int.eq_spec i (Int.repr Int.min_signed); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  predSpec Int.eq Int.eq_spec i0 Int.mone; auto.
(* Goal: forall _ : @eq bool (andb true true) false, or (not (@eq Int64.int i (Int64.repr Int64.min_signed))) (not (@eq Int64.int i0 Int64.mone)) *)
  discriminate.
Qed.

Lemma divlu_modlu_exists:
  forall v1 v2,
  Val.divlu v1 v2 <> None \/ Val.modlu v1 v2 <> None ->
  exists n d q r,
     v1 = Vlong n /\ v2 = Vlong d
  /\ Int64.divmodu2 Int64.zero n d = Some(q, r)
  /\ Val.divlu v1 v2 = Some (Vlong q) /\ Val.modlu v1 v2 = Some (Vlong r).
Proof.
(* Goal: forall (v1 v2 : val) (_ : or (not (@eq (option val) (Val.divlu v1 v2) (@None val))) (not (@eq (option val) (Val.modlu v1 v2) (@None val)))), @ex Int64.int (fun n : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val v1 (Vlong n)) (and (@eq val v2 (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmodu2 Int64.zero n d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) (Val.divlu v1 v2) (@Some val (Vlong q))) (@eq (option val) (Val.modlu v1 v2) (@Some val (Vlong r)))))))))) *)
  intros v1 v2; unfold Val.divlu, Val.modlu.
(* Goal: forall _ : or (not (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))) (not (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl v1 (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val v1 (Vlong nl)) (and (@eq val v2 (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong q))) (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong r)))))))))))) *)
  destruct v1; try (intuition discriminate).
(* Goal: forall _ : or (not (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))) (not (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl (Vlong i) (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val (Vlong i) (Vlong nl)) (and (@eq val v2 (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong q))) (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong r)))))))))))) *)
  destruct v2; try (intuition discriminate).
(* Goal: forall _ : or (not (@eq (option val) (if Int64.eq i0 Int64.zero then @None val else @Some val (Vlong (Int64.divu i i0))) (@None val))) (not (@eq (option val) (if Int64.eq i0 Int64.zero then @None val else @Some val (Vlong (Int64.modu i i0))) (@None val))), @ex Int64.int (fun n : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Vlong i) (Vlong n)) (and (@eq val (Vlong i0) (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmodu2 Int64.zero n d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) (if Int64.eq i0 Int64.zero then @None val else @Some val (Vlong (Int64.divu i i0))) (@Some val (Vlong q))) (@eq (option val) (if Int64.eq i0 Int64.zero then @None val else @Some val (Vlong (Int64.modu i i0))) (@Some val (Vlong r)))))))))) *)
  predSpec Int64.eq Int64.eq_spec i0 Int64.zero ; try (intuition discriminate).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  intros _. exists i, i0, (Int64.divu i i0), (Int64.modu i i0); intuition auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply Int64.divmodu2_divu_modu; auto.
Qed.

Lemma divls_modls_exists:
  forall v1 v2,
  Val.divls v1 v2 <> None \/ Val.modls v1 v2 <> None ->
  exists nh nl d q r,
     Val.shrl v1 (Vint (Int.repr 63)) = Vlong nh /\ v1 = Vlong nl /\ v2 = Vlong d
  /\ Int64.divmods2 nh nl d = Some(q, r)
  /\ Val.divls v1 v2 = Some (Vlong q) /\ Val.modls v1 v2 = Some (Vlong r).
Proof.
(* Goal: forall (v1 v2 : val) (_ : or (not (@eq (option val) (Val.divls v1 v2) (@None val))) (not (@eq (option val) (Val.modls v1 v2) (@None val)))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl v1 (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val v1 (Vlong nl)) (and (@eq val v2 (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) (Val.divls v1 v2) (@Some val (Vlong q))) (@eq (option val) (Val.modls v1 v2) (@Some val (Vlong r)))))))))))) *)
  intros v1 v2; unfold Val.divls, Val.modls.
(* Goal: forall _ : or (not (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))) (not (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl v1 (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val v1 (Vlong nl)) (and (@eq val v2 (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong q))) (@eq (option val) match v1 with | Vundef => @None val | Vint i => @None val | Vlong n1 => match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq n1 (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods n1 n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong r)))))))))))) *)
  destruct v1; try (intuition discriminate).
(* Goal: forall _ : or (not (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))) (not (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@None val))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl (Vlong i) (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val (Vlong i) (Vlong nl)) (and (@eq val v2 (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.divs i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong q))) (@eq (option val) match v2 with | Vundef => @None val | Vint i => @None val | Vlong n2 => if orb (Int64.eq n2 Int64.zero) (andb (Int64.eq i (Int64.repr Int64.min_signed)) (Int64.eq n2 Int64.mone)) then @None val else @Some val (Vlong (Int64.mods i n2)) | Vfloat f => @None val | Vsingle f => @None val | Vptr b i => @None val end (@Some val (Vlong r)))))))))))) *)
  destruct v2; try (intuition discriminate).
  destruct (Int64.eq i0 Int64.zero
            || Int64.eq i (Int64.repr Int64.min_signed) && Int64.eq i0 Int64.mone) eqn:OK;
  try (intuition discriminate).
(* Goal: forall _ : or (not (@eq (option val) (@Some val (Vlong (Int64.divs i i0))) (@None val))) (not (@eq (option val) (@Some val (Vlong (Int64.mods i i0))) (@None val))), @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl (Vlong i) (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val (Vlong i) (Vlong nl)) (and (@eq val (Vlong i0) (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) (@Some val (Vlong (Int64.divs i i0))) (@Some val (Vlong q))) (@eq (option val) (@Some val (Vlong (Int64.mods i i0))) (@Some val (Vlong r)))))))))))) *)
  intros _.
(* Goal: @ex Int64.int (fun nh : Int64.int => @ex Int64.int (fun nl : Int64.int => @ex Int64.int (fun d : Int64.int => @ex Int64.int (fun q : Int64.int => @ex Int64.int (fun r : Int64.int => and (@eq val (Val.shrl (Vlong i) (Vint (Int.repr (Zpos (xI (xI (xI (xI (xI xH))))))))) (Vlong nh)) (and (@eq val (Vlong i) (Vlong nl)) (and (@eq val (Vlong i0) (Vlong d)) (and (@eq (option (prod Int64.int Int64.int)) (Int64.divmods2 nh nl d) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int q r))) (and (@eq (option val) (@Some val (Vlong (Int64.divs i i0))) (@Some val (Vlong q))) (@eq (option val) (@Some val (Vlong (Int64.mods i i0))) (@Some val (Vlong r)))))))))))) *)
  InvBooleans.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  exists (Int64.shr i (Int64.repr 63)), i, i0, (Int64.divs i i0), (Int64.mods i i0); intuition auto.
(* Goal: @eq (option (prod Int64.int Int64.int)) (Int64.divmods2 (Int64.shr i (Int64.repr (Zpos (xI (xI (xI (xI (xI xH)))))))) i i0) (@Some (prod Int64.int Int64.int) (@pair Int64.int Int64.int (Int64.divs i i0) (Int64.mods i i0))) *)
  rewrite Int64.shr_lt_zero. apply Int64.divmods2_divs_mods.
(* Goal: forall _ : @eq bool (andb true true) false, or (not (@eq Int64.int i (Int64.repr Int64.min_signed))) (not (@eq Int64.int i0 Int64.mone)) *)
  red; intros; subst i0; rewrite Int64.eq_true in H; discriminate.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  revert H0. predSpec Int64.eq Int64.eq_spec i (Int64.repr Int64.min_signed); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  predSpec Int64.eq Int64.eq_spec i0 Int64.mone; auto.
(* Goal: forall _ : @eq bool (andb true true) false, or (not (@eq Int64.int i (Int64.repr Int64.min_signed))) (not (@eq Int64.int i0 Int64.mone)) *)
  discriminate.
Qed.

(** Smart constructor for [shrx] *)

Lemma mk_shrximm_correct:
  forall n k c (rs1: regset) v m,
  mk_shrximm n k = OK c ->
  Val.shrx (rs1#RAX) (Vint n) = Some v ->
  exists rs2,
     exec_straight ge fn c rs1 m k rs2 m
  /\ rs2#RAX = v
  /\ forall r, data_preg r = true -> r <> RAX -> r <> RCX -> rs2#r = rs1#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold mk_shrximm; intros. inv H.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  exploit Val.shrx_shr; eauto. intros [x [y [A [B C]]]].
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn (@cons instruction (Ptestl_rr RAX RAX) (@cons instruction (Pleal RCX (Addrmode (@Some ireg RAX) (@None (prod ireg Z)) (@inl Z (prod ident Ptrofs.int) (Int.unsigned (Int.sub (Int.shl Int.one n) Int.one))))) (@cons instruction (Pcmov Cond_l RAX RCX) (@cons instruction (Psarl_ri RAX n) k)))) rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
  inversion B; clear B; subst y; subst v; clear H0.
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn (@cons instruction (Ptestl_rr RAX RAX) (@cons instruction (Pleal RCX (Addrmode (@Some ireg RAX) (@None (prod ireg Z)) (@inl Z (prod ident Ptrofs.int) (Int.unsigned (Int.sub (Int.shl Int.one n) Int.one))))) (@cons instruction (Pcmov Cond_l RAX RCX) (@cons instruction (Psarl_ri RAX n) k)))) rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) (Val.shr (if Int.lt x Int.zero then Val.add (rs1 (IR RAX)) (Vint (Int.sub (Int.shl Int.one n) Int.one)) else rs1 (IR RAX)) (Vint n))) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
  set (tnm1 := Int.sub (Int.shl Int.one n) Int.one).
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn (@cons instruction (Ptestl_rr RAX RAX) (@cons instruction (Pleal RCX (Addrmode (@Some ireg RAX) (@None (prod ireg Z)) (@inl Z (prod ident Ptrofs.int) (Int.unsigned tnm1)))) (@cons instruction (Pcmov Cond_l RAX RCX) (@cons instruction (Psarl_ri RAX n) k)))) rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) (Val.shr (if Int.lt x Int.zero then Val.add (rs1 (IR RAX)) (Vint tnm1) else rs1 (IR RAX)) (Vint n))) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
  set (x' := Int.add x tnm1).
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn (@cons instruction (Ptestl_rr RAX RAX) (@cons instruction (Pleal RCX (Addrmode (@Some ireg RAX) (@None (prod ireg Z)) (@inl Z (prod ident Ptrofs.int) (Int.unsigned tnm1)))) (@cons instruction (Pcmov Cond_l RAX RCX) (@cons instruction (Psarl_ri RAX n) k)))) rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) (Val.shr (if Int.lt x Int.zero then Val.add (rs1 (IR RAX)) (Vint tnm1) else rs1 (IR RAX)) (Vint n))) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
  set (rs2 := nextinstr (compare_ints (Vint x) (Vint Int.zero) rs1 m)).
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn (@cons instruction (Ptestl_rr RAX RAX) (@cons instruction (Pleal RCX (Addrmode (@Some ireg RAX) (@None (prod ireg Z)) (@inl Z (prod ident Ptrofs.int) (Int.unsigned tnm1)))) (@cons instruction (Pcmov Cond_l RAX RCX) (@cons instruction (Psarl_ri RAX n) k)))) rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) (Val.shr (if Int.lt x Int.zero then Val.add (rs1 (IR RAX)) (Vint tnm1) else rs1 (IR RAX)) (Vint n))) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
  set (rs3 := nextinstr (rs2#RCX <- (Vint x'))).
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn (@cons instruction (Ptestl_rr RAX RAX) (@cons instruction (Pleal RCX (Addrmode (@Some ireg RAX) (@None (prod ireg Z)) (@inl Z (prod ident Ptrofs.int) (Int.unsigned tnm1)))) (@cons instruction (Pcmov Cond_l RAX RCX) (@cons instruction (Psarl_ri RAX n) k)))) rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) (Val.shr (if Int.lt x Int.zero then Val.add (rs1 (IR RAX)) (Vint tnm1) else rs1 (IR RAX)) (Vint n))) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
  set (rs4 := nextinstr (if Int.lt x Int.zero then rs3#RAX <- (Vint x') else rs3)).
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn (@cons instruction (Ptestl_rr RAX RAX) (@cons instruction (Pleal RCX (Addrmode (@Some ireg RAX) (@None (prod ireg Z)) (@inl Z (prod ident Ptrofs.int) (Int.unsigned tnm1)))) (@cons instruction (Pcmov Cond_l RAX RCX) (@cons instruction (Psarl_ri RAX n) k)))) rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) (Val.shr (if Int.lt x Int.zero then Val.add (rs1 (IR RAX)) (Vint tnm1) else rs1 (IR RAX)) (Vint n))) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
  set (rs5 := nextinstr_nf (rs4#RAX <- (Val.shr rs4#RAX (Vint n)))).
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  assert (rs3#RAX = Vint x). unfold rs3. Simplifs.
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  assert (rs3#RCX = Vint x'). unfold rs3. Simplifs.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  exists rs5. split.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply exec_straight_step with rs2 m. simpl. rewrite A. simpl. rewrite Int.and_idem. auto. auto.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  apply exec_straight_step with rs3 m. simpl.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  change (rs2 RAX) with (rs1 RAX). rewrite A. simpl.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite Int.repr_unsigned. rewrite Int.add_zero_l. auto. auto.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  apply exec_straight_step with rs4 m. simpl.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite Int.lt_sub_overflow. unfold rs4. destruct (Int.lt x Int.zero); simpl; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  unfold rs4. destruct (Int.lt x Int.zero); simpl; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply exec_straight_one. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. unfold rs5. Simplifs. unfold rs4. rewrite nextinstr_inv; auto with asmgen.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int.lt x Int.zero). rewrite Pregmap.gss. rewrite A; auto. rewrite A; rewrite H; auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold rs5. Simplifs. unfold rs4. Simplifs.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  transitivity (rs3#r). destruct (Int.lt x Int.zero). Simplifs. auto.
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  unfold rs3. Simplifs. unfold rs2. Simplifs.
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  unfold compare_ints. Simplifs.
Qed.

(** Smart constructor for [shrxl] *)

Lemma mk_shrxlimm_correct:
  forall n k c (rs1: regset) v m,
  mk_shrxlimm n k = OK c ->
  Val.shrxl (rs1#RAX) (Vint n) = Some v ->
  exists rs2,
     exec_straight ge fn c rs1 m k rs2 m
  /\ rs2#RAX = v
  /\ forall r, data_preg r = true -> r <> RAX -> r <> RDX -> rs2#r = rs1#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold mk_shrxlimm; intros. exploit Val.shrxl_shrl_2; eauto. intros EQ.
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn c rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
  destruct (Int.eq n Int.zero); inv H.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- econstructor; split. apply exec_straight_one. simpl; reflexivity. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. Simplifs. intros; Simplifs.
- set (v1 := Val.shrl (rs1 RAX) (Vint (Int.repr 63))) in *.
  set (v2 := Val.shrlu v1 (Vint (Int.sub (Int.repr 64) n))) in *.
  set (v3 := Val.addl (rs1 RAX) v2) in *.
  set (v4 := Val.shrl v3 (Vint n)) in *.
  set (rs2 := nextinstr_nf (rs1#RDX <- v1)).
  set (rs3 := nextinstr_nf (rs2#RDX <- v2)).
  set (rs4 := nextinstr (rs3#RAX <- v3)).
  set (rs5 := nextinstr_nf (rs4#RAX <- v4)).
  assert (X: forall v1 v2,
             Val.addl v1 (Val.addl v2 (Vlong Int64.zero)) = Val.addl v1 v2).
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  { intros. unfold Val.addl; destruct Archi.ptr64 eqn:SF, v0; auto; destruct v5; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    rewrite Int64.add_zero; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    rewrite Ptrofs.add_zero; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    rewrite Int64.add_zero; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    rewrite Int64.add_zero; auto. }
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  exists rs5; split.
  eapply exec_straight_trans with (rs2 := rs3).
  eapply exec_straight_two with (rs2 := rs2); reflexivity.
  eapply exec_straight_two with (rs2 := rs4).
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite X. reflexivity. reflexivity. reflexivity. reflexivity.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. unfold rs5; Simplifs.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold rs5; Simplifs. unfold rs4; Simplifs. unfold rs3; Simplifs. unfold rs2; Simplifs.
Qed.

(** Smart constructor for integer conversions *)

Lemma mk_intconv_correct:
  forall mk sem rd rs k c rs1 m,
  mk_intconv mk rd rs k = OK c ->
  (forall c rd rs r m,
   exec_instr ge c (mk rd rs) r m = Next (nextinstr (r#rd <- (sem r#rs))) m) ->
  exists rs2,
     exec_straight ge fn c rs1 m k rs2 m
  /\ rs2#rd = sem rs1#rs
  /\ forall r, data_preg r = true -> r <> rd -> r <> RAX -> rs2#r = rs1#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold mk_intconv; intros. destruct (Archi.ptr64 || low_ireg rs); monadInv H.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. rewrite H0. eauto. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  split. Simplifs. intros. Simplifs.
  econstructor. split. eapply exec_straight_two.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. eauto. apply H0. auto. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  split. Simplifs. intros. Simplifs.
Qed.

(** Smart constructor for small stores *)

Lemma addressing_mentions_correct:
  forall a r (rs1 rs2: regset),
  (forall (r': ireg), r' <> r -> rs1 r' = rs2 r') ->
  addressing_mentions a r = false ->
  eval_addrmode32 ge a rs1 = eval_addrmode32 ge a rs2.
Proof.
(* Goal: forall (a : addrmode) (r : ireg) (rs1 rs2 : regset) (_ : forall (r' : ireg) (_ : not (@eq ireg r' r)), @eq val (rs1 (IR r')) (rs2 (IR r'))) (_ : @eq bool (addressing_mentions a r) false), @eq val (eval_addrmode32 ge a rs1) (eval_addrmode32 ge a rs2) *)
  intros until rs2; intro AG. unfold addressing_mentions, eval_addrmode32.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  destruct a. intros. destruct (orb_false_elim _ _ H). unfold proj_sumbool in *.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  decEq. destruct base; auto. apply AG. destruct (ireg_eq r i); congruence.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  decEq. destruct ofs as [[r' sc] | ]; auto. rewrite AG; auto. destruct (ireg_eq r r'); congruence.
Qed.

Lemma mk_storebyte_correct:
  forall addr r k c rs1 m1 m2,
  mk_storebyte addr r k = OK c ->
  Mem.storev Mint8unsigned m1 (eval_addrmode ge addr rs1) (rs1 r) = Some m2 ->
  exists rs2,
     exec_straight ge fn c rs1 m1 k rs2 m2
  /\ forall r, data_preg r = true -> preg_notin r (if Archi.ptr64 then nil else AX :: CX :: nil) -> rs2#r = rs1#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold mk_storebyte; intros.
  destruct (Archi.ptr64 || low_ireg r) eqn:E.
(* low reg *)
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  monadInv H. econstructor; split. apply exec_straight_one.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. unfold exec_store. rewrite H0. eauto. auto.
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  intros; Simplifs.
(* high reg *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  InvBooleans. rewrite H1; simpl. destruct (addressing_mentions addr RAX) eqn:E; monadInv H.
(* RAX is mentioned. *)
(* Goal: forall (v : val) (i : Z), Val.lessdef (Val.mull v (Vlong (Int64.repr i))) (if zeq i (Zpos xH) then v else Val.mull v (Vlong (Int64.repr i))) *)
(* Goal: forall (addr : addressing) (args : list mreg) (am : addrmode) (rs : regset) (v : val) (_ : @eq (res addrmode) (transl_addressing addr args) (@OK addrmode am)) (_ : @eq (option val) (@eval_addressing64 fundef unit ge (rs (IR RSP)) addr (@map PregEq.t val rs (@map mreg preg preg_of args))) (@Some val v)), Val.lessdef v (eval_addrmode64 ge am rs) *)
  assert (r <> RCX). { red; intros; subst r; discriminate H2. }
  set (rs2 := nextinstr (rs1#RCX <- (eval_addrmode32 ge addr rs1))).
  set (rs3 := nextinstr (rs2#RAX <- (rs1 r))).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
  apply exec_straight_three with rs2 m1 rs3 m1.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. replace (rs2 r) with (rs1 r). auto. symmetry. unfold rs2; Simplifs.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. unfold exec_store. unfold eval_addrmode; rewrite H1; simpl. rewrite Int.add_zero.
  change (rs3 RAX) with (rs1 r).
  change (rs3 RCX) with (eval_addrmode32 ge addr rs1).
  replace (Val.add (eval_addrmode32 ge addr rs1) (Vint Int.zero))
     with (eval_addrmode ge addr rs1).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite H0. eauto.
  unfold eval_addrmode in *; rewrite H1 in *.
  destruct (eval_addrmode32 ge addr rs1); simpl in H0; try discriminate H0.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. rewrite H1. rewrite Ptrofs.add_zero; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  auto. auto. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. destruct H4. Simplifs. unfold rs3; Simplifs. unfold rs2; Simplifs.
(* RAX is not mentioned *)
  set (rs2 := nextinstr (rs1#RAX <- (rs1 r))).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
  apply exec_straight_two with rs2 m1.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. auto.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. unfold exec_store. unfold eval_addrmode in *; rewrite H1 in *.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite (addressing_mentions_correct addr RAX rs2 rs1); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  change (rs2 RAX) with (rs1 r). rewrite H0. eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold rs2; Simplifs.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  auto. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. destruct H3. simpl. Simplifs. unfold rs2; Simplifs.
Qed.

(** Accessing slots in the stack frame *)

Remark eval_addrmode_indexed:
  forall (base: ireg) ofs (rs: regset),
  match rs#base with Vptr _ _ => True | _ => False end ->
  eval_addrmode ge (Addrmode (Some base) None (inl _ (Ptrofs.unsigned ofs))) rs = Val.offset_ptr rs#base ofs.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. destruct (rs#base) eqn:BASE; try contradiction.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  intros; unfold eval_addrmode; destruct Archi.ptr64 eqn:SF; simpl; rewrite BASE; simpl; rewrite SF; simpl.
- apply f_equal. apply f_equal. rewrite Int64.add_zero_l. rewrite <- (Ptrofs.repr_unsigned ofs) at 2. auto with ptrofs.
(* Goal: Val.lessdef (Vptr b (Ptrofs.add i0 i)) (Vptr b (Ptrofs.add i0 (Ptrofs.of_int (Int.add Int.zero (Int.repr (Ptrofs.signed i)))))) *)
-  apply f_equal. apply f_equal. rewrite Int.add_zero_l. rewrite <- (Ptrofs.repr_unsigned ofs) at 2. auto with ptrofs.
Qed.

Ltac loadind_correct_solve :=
  match goal with
  | H: Error _ = OK _ |- _ => discriminate H
  | H: OK _ = OK _ |- _ => inv H
  | H: match ?x with _ => _ end = OK _ |- _ => destruct x eqn:?; loadind_correct_solve
  | _ => idtac
  end.

Lemma loadind_correct:
  forall (base: ireg) ofs ty dst k (rs: regset) c m v,
  loadind base ofs ty dst k = OK c ->
  Mem.loadv (chunk_of_type ty) m (Val.offset_ptr rs#base ofs) = Some v ->
  exists rs',
     exec_straight ge fn c rs m k rs' m
  /\ rs'#(preg_of dst) = v
  /\ forall r, data_preg r = true -> r <> preg_of dst -> rs'#r = rs#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold loadind; intros.
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m') (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : preg_notin r (destroyed_by_setstack ty)), @eq val (rs' r) (rs r))) *)
  set (addr := Addrmode (Some base) None (inl (ident * ptrofs) (Ptrofs.unsigned ofs))) in *.
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m') (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : preg_notin r (destroyed_by_setstack ty)), @eq val (rs' r) (rs r))) *)
  assert (eval_addrmode ge addr rs = Val.offset_ptr rs#base ofs).
(* Goal: forall _ : @eq bool (andb true true) false, or (not (@eq Int64.int i (Int64.repr Int64.min_signed))) (not (@eq Int64.int i0 Int64.mone)) *)
  { apply eval_addrmode_indexed. destruct (rs base); auto || discriminate. }
  rewrite <- H1 in H0.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  exists (nextinstr_nf (rs#(preg_of dst) <- v)); split.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- loadind_correct_solve; apply exec_straight_one; auto; simpl in *; unfold exec_load; rewrite ?Heqb, ?H0; auto.
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
- intuition Simplifs.
Qed.

Lemma storeind_correct:
  forall (base: ireg) ofs ty src k (rs: regset) c m m',
  storeind src base ofs ty k = OK c ->
  Mem.storev (chunk_of_type ty) m (Val.offset_ptr rs#base ofs) (rs#(preg_of src)) = Some m' ->
  exists rs',
     exec_straight ge fn c rs m k rs' m'
  /\ forall r, data_preg r = true -> preg_notin r (destroyed_by_setstack ty) -> rs'#r = rs#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold storeind; intros.
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m') (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : preg_notin r (destroyed_by_setstack ty)), @eq val (rs' r) (rs r))) *)
  set (addr := Addrmode (Some base) None (inl (ident * ptrofs) (Ptrofs.unsigned ofs))) in *.
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m') (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : preg_notin r (destroyed_by_setstack ty)), @eq val (rs' r) (rs r))) *)
  assert (eval_addrmode ge addr rs = Val.offset_ptr rs#base ofs).
(* Goal: forall _ : @eq bool (andb true true) false, or (not (@eq Int64.int i (Int64.repr Int64.min_signed))) (not (@eq Int64.int i0 Int64.mone)) *)
  { apply eval_addrmode_indexed. destruct (rs base); auto || discriminate. }
  rewrite <- H1 in H0.
  loadind_correct_solve; simpl in H0;
  (econstructor; split;
  [apply exec_straight_one; [simpl; unfold exec_store; rewrite ?Heqb, H0;eauto|auto]
  |simpl; intros; unfold undef_regs; repeat Simplifs]).
Qed.

(** Translation of addressing modes *)

Lemma transl_addressing_mode_32_correct:
  forall addr args am (rs: regset) v,
  transl_addressing addr args = OK am ->
  eval_addressing32 ge (rs RSP) addr (List.map rs (List.map preg_of args)) = Some v ->
  Val.lessdef v (eval_addrmode32 ge am rs).
Proof.
  assert (A: forall id ofs, Archi.ptr64 = false ->
          Val.add (Vint Int.zero) (Genv.symbol_address ge id ofs) = Genv.symbol_address ge id ofs).
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  { intros. unfold Val.add; rewrite H. unfold Genv.symbol_address.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    destruct (Genv.find_symbol ge id); auto. rewrite Ptrofs.add_zero; auto. }
  assert (C: forall v i,
    Val.lessdef (Val.mul v (Vint (Int.repr i)))
               (if zeq i 1 then v else Val.mul v (Vint (Int.repr i)))).
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  { intros. destruct (zeq i 1); subst; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    destruct v; simpl; auto. rewrite Int.mul_one; auto. }
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold transl_addressing; intros.
  destruct addr; repeat (destruct args; try discriminate H); simpl in H0; FuncInv;
  monadInv H; try (erewrite ! ireg_of_eq by eauto); unfold eval_addrmode32.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- simpl; rewrite Int.add_zero_l; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- rewrite Val.add_assoc. apply Val.add_lessdef; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- rewrite Val.add_permut. apply Val.add_lessdef; auto. simpl; rewrite Int.add_zero_l; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- apply Val.add_lessdef; auto. apply Val.add_lessdef; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- rewrite ! A by auto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- rewrite Val.add_commut. rewrite A by auto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- rewrite Val.add_permut. rewrite Val.add_commut. apply Val.add_lessdef; auto. rewrite A; auto.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
- simpl. unfold Val.add; rewrite Heqb.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (rs RSP); simpl; auto.
(* Goal: Val.lessdef (Vptr b (Ptrofs.add i0 i)) (Vptr b (Ptrofs.add i0 (Ptrofs.of_int (Int.add Int.zero (Int.repr (Ptrofs.signed i)))))) *)
  rewrite Int.add_zero_l. apply Val.lessdef_same; f_equal; f_equal.
(* Goal: @eq Ptrofs.int i (Ptrofs.of_int64 (Int64.repr (Ptrofs.signed i))) *)
  symmetry. transitivity (Ptrofs.repr (Ptrofs.signed i)). auto with ptrofs. auto with ints.
Qed.

Lemma transl_addressing_mode_64_correct:
  forall addr args am (rs: regset) v,
  transl_addressing addr args = OK am ->
  eval_addressing64 ge (rs RSP) addr (List.map rs (List.map preg_of args)) = Some v ->
  Val.lessdef v (eval_addrmode64 ge am rs).
Proof.
  assert (A: forall id ofs, Archi.ptr64 = true ->
          Val.addl (Vlong Int64.zero) (Genv.symbol_address ge id ofs) = Genv.symbol_address ge id ofs).
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  { intros. unfold Val.addl; rewrite H. unfold Genv.symbol_address.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    destruct (Genv.find_symbol ge id); auto. rewrite Ptrofs.add_zero; auto. }
  assert (C: forall v i,
    Val.lessdef (Val.mull v (Vlong (Int64.repr i)))
               (if zeq i 1 then v else Val.mull v (Vlong (Int64.repr i)))).
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  { intros. destruct (zeq i 1); subst; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    destruct v; simpl; auto. rewrite Int64.mul_one; auto. }
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold transl_addressing; intros.
  destruct addr; repeat (destruct args; try discriminate H); simpl in H0; FuncInv;
  monadInv H; try (erewrite ! ireg_of_eq by eauto); unfold eval_addrmode64.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- simpl; rewrite Int64.add_zero_l; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- rewrite Val.addl_assoc. apply Val.addl_lessdef; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- rewrite Val.addl_permut. apply Val.addl_lessdef; auto. simpl; rewrite Int64.add_zero_l; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- apply Val.addl_lessdef; auto. apply Val.addl_lessdef; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- rewrite ! A by auto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
- unfold Val.addl; rewrite Heqb. destruct (rs RSP); auto. simpl.
(* Goal: Val.lessdef (Vptr b (Ptrofs.add i0 i)) (Vptr b (Ptrofs.add i0 (Ptrofs.of_int64 (Int64.add Int64.zero (Int64.repr (Ptrofs.signed i)))))) *)
  rewrite Int64.add_zero_l. apply Val.lessdef_same; f_equal; f_equal.
(* Goal: @eq Ptrofs.int i (Ptrofs.of_int64 (Int64.repr (Ptrofs.signed i))) *)
  symmetry. transitivity (Ptrofs.repr (Ptrofs.signed i)). auto with ptrofs. auto with ints.
Qed.

Lemma transl_addressing_mode_correct:
  forall addr args am (rs: regset) v,
  transl_addressing addr args = OK am ->
  eval_addressing ge (rs RSP) addr (List.map rs (List.map preg_of args)) = Some v ->
  Val.lessdef v (eval_addrmode ge am rs).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold eval_addressing, eval_addrmode; intros. destruct Archi.ptr64.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply transl_addressing_mode_64_correct; eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply transl_addressing_mode_32_correct; eauto.
Qed.

Lemma normalize_addrmode_32_correct:
  forall am rs, eval_addrmode32 ge (normalize_addrmode_32 am) rs = eval_addrmode32 ge am rs.
Proof.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  intros; destruct am as [base ofs [n|r]]; simpl; auto. rewrite Int.repr_signed. auto.
Qed.

Lemma normalize_addrmode_64_correct:
  forall am rs,
  eval_addrmode64 ge am rs =
  match normalize_addrmode_64 am with
  | (am', None) => eval_addrmode64 ge am' rs
  | (am', Some delta) => Val.addl (eval_addrmode64 ge am' rs) (Vlong delta)
  end.
Proof.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  intros; destruct am as [base ofs [n|[id delta]]]; simpl.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
- destruct (offset_in_range n); auto; simpl.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite ! Val.addl_assoc. apply f_equal. apply f_equal. simpl. rewrite Int64.add_zero_l; auto.
- destruct Archi.ptr64 eqn:SF; auto; simpl;
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (ptroffset_in_range delta); auto. simpl.
(* Goal: @eq val (Val.addl match ofs with | Some (pair r sc as p) => if zeq sc (Zpos xH) then rs (IR r) else Val.mull (rs (IR r)) (Vlong (Int64.repr sc)) | None => Vlong Int64.zero end (@Genv.symbol_address fundef unit ge id delta)) (Val.addl match ofs with | Some (pair r sc as p) => if zeq sc (Zpos xH) then rs (IR r) else Val.mull (rs (IR r)) (Vlong (Int64.repr sc)) | None => Vlong Int64.zero end (Val.addl (@Genv.symbol_address fundef unit ge id Ptrofs.zero) (Vlong (Ptrofs.to_int64 delta)))) *)
  rewrite ! Val.addl_assoc. apply f_equal. apply f_equal.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite <- Genv.shift_symbol_address_64 by auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  f_equal. rewrite Ptrofs.add_zero_l, Ptrofs.of_int64_to_int64 by auto. auto.
Qed.

(** Processor conditions and comparisons *)

Lemma compare_ints_spec:
  forall rs v1 v2 m,
  let rs' := nextinstr (compare_ints v1 v2 rs m) in
     rs'#ZF = Val.cmpu (Mem.valid_pointer m) Ceq v1 v2
  /\ rs'#CF = Val.cmpu (Mem.valid_pointer m) Clt v1 v2
  /\ rs'#SF = Val.negative (Val.sub v1 v2)
  /\ rs'#OF = Val.sub_overflow v1 v2
  /\ (forall r, data_preg r = true -> rs'#r = rs#r).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold rs'; unfold compare_ints.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs.
Qed.

Lemma testcond_for_signed_comparison_32_correct:
  forall c v1 v2 rs m b,
  Val.cmp_bool c v1 v2 = Some b ->
  eval_testcond (testcond_for_signed_comparison c)
                (nextinstr (compare_ints v1 v2 rs m)) = Some b.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. generalize (compare_ints_spec rs v1 v2 m).
(* Goal: forall _ : let rs' := nextinstr (compare_ints v1 v2 rs m) in and (@eq val (rs' (CR ZF)) (Val.cmpu (Mem.valid_pointer m) Ceq v1 v2)) (and (@eq val (rs' (CR CF)) (Val.cmpu (Mem.valid_pointer m) Clt v1 v2)) (and (@eq val (rs' (CR SF)) (Val.negative (Val.sub v1 v2))) (and (@eq val (rs' (CR OF)) (Val.sub_overflow v1 v2)) (forall (r : preg) (_ : @eq bool (data_preg r) true), @eq val (rs' r) (rs r))))), @eq (option bool) (eval_testcond (testcond_for_unsigned_comparison c) (nextinstr (compare_ints v1 v2 rs m))) (@Some bool b) *)
  set (rs' := nextinstr (compare_ints v1 v2 rs m)).
(* Goal: forall _ : let rs' := rs' in and (@eq val (rs' (CR ZF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2))) (and (@eq val (rs' (CR CF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2))) (and (@eq val (rs' (CR SF)) (Val.negativel (Val.subl v1 v2))) (and (@eq val (rs' (CR OF)) (Val.subl_overflow v1 v2)) (forall (r : preg) (_ : @eq bool (data_preg r) true), @eq val (rs' r) (rs r))))), @eq (option bool) (eval_testcond (testcond_for_unsigned_comparison c) rs') (@Some bool b) *)
  intros [A [B [C [D E]]]].
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn c rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
  destruct v1; destruct v2; simpl in H; inv H.
(* Goal: @eq (option bool) (eval_testcond c (@Pregmap.set val (IR r) v rs)) (eval_testcond c rs) *)
  unfold eval_testcond. rewrite A; rewrite B; rewrite C; rewrite D.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. unfold Val.cmp, Val.cmpu.
(* Goal: @eq (option bool) match testcond_for_signed_comparison c with | Cond_e => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vint i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vint i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vint i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vint i) (Vint i0)) with | Vundef => @None bool | Vint c => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vint i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vint i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vint i) (Vint i0)) with | Vundef => @None bool | Vint c => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vint i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => @Some bool (Int.eq (Int.xor (Int.sub_overflow i i0 Int.zero) (Int.negative (Int.sub i i0))) Int.one) | Cond_le => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vint i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq (Int.xor (Int.sub_overflow i i0 Int.zero) (Int.negative (Int.sub i i0))) Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ge => @Some bool (Int.eq (Int.xor (Int.sub_overflow i i0 Int.zero) (Int.negative (Int.sub i i0))) Int.zero) | Cond_g => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vint i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq (Int.xor (Int.sub_overflow i i0 Int.zero) (Int.negative (Int.sub i i0))) Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_p => @None bool | Cond_np => @None bool end (@Some bool (Int.cmp c i i0)) *)
  rewrite Int.lt_sub_overflow.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  destruct c; simpl.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int.eq i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int.eq i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int.lt i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite Int.not_lt. destruct (Int.lt i i0); simpl; destruct (Int.eq i i0); auto.
  rewrite (Int.lt_not i i0). destruct (Int.lt i i0); destruct (Int.eq i i0); reflexivity.
  destruct (Int.lt i i0); reflexivity.
Qed.

Lemma testcond_for_unsigned_comparison_32_correct:
  forall c v1 v2 rs m b,
  Val.cmpu_bool (Mem.valid_pointer m) c v1 v2 = Some b ->
  eval_testcond (testcond_for_unsigned_comparison c)
                (nextinstr (compare_ints v1 v2 rs m)) = Some b.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. generalize (compare_ints_spec rs v1 v2 m).
(* Goal: forall _ : let rs' := nextinstr (compare_ints v1 v2 rs m) in and (@eq val (rs' (CR ZF)) (Val.cmpu (Mem.valid_pointer m) Ceq v1 v2)) (and (@eq val (rs' (CR CF)) (Val.cmpu (Mem.valid_pointer m) Clt v1 v2)) (and (@eq val (rs' (CR SF)) (Val.negative (Val.sub v1 v2))) (and (@eq val (rs' (CR OF)) (Val.sub_overflow v1 v2)) (forall (r : preg) (_ : @eq bool (data_preg r) true), @eq val (rs' r) (rs r))))), @eq (option bool) (eval_testcond (testcond_for_unsigned_comparison c) (nextinstr (compare_ints v1 v2 rs m))) (@Some bool b) *)
  set (rs' := nextinstr (compare_ints v1 v2 rs m)).
(* Goal: forall _ : let rs' := rs' in and (@eq val (rs' (CR ZF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2))) (and (@eq val (rs' (CR CF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2))) (and (@eq val (rs' (CR SF)) (Val.negativel (Val.subl v1 v2))) (and (@eq val (rs' (CR OF)) (Val.subl_overflow v1 v2)) (forall (r : preg) (_ : @eq bool (data_preg r) true), @eq val (rs' r) (rs r))))), @eq (option bool) (eval_testcond (testcond_for_unsigned_comparison c) rs') (@Some bool b) *)
  intros [A [B [C [D E]]]].
(* Goal: @eq (option bool) (eval_testcond c (@Pregmap.set val (IR r) v rs)) (eval_testcond c rs) *)
  unfold eval_testcond. rewrite A; rewrite B. unfold Val.cmpu, Val.cmp.
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2) with | Vundef => @None bool | Vint c => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2) with | Vundef => @None bool | Vint c => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_le => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq (Int.xor o s) Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ge => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_g => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq (Int.xor o s) Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_p => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_np => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end end (@Some bool b) *)
  destruct v1; destruct v2; simpl in H; FuncInv; subst.
- (* int int *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct c; simpl; auto.
  destruct (Int.eq i i0); reflexivity.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int.eq i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int.ltu i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite Int.not_ltu. destruct (Int.ltu i i0); simpl; destruct (Int.eq i i0); auto.
  rewrite (Int.ltu_not i i0). destruct (Int.ltu i i0); destruct (Int.eq i i0); reflexivity.
  destruct (Int.ltu i i0); reflexivity.
- (* int ptr *)
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint c => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint c => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_le => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq (Int.xor o s) Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ge => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_g => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq (Int.xor o s) Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_p => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_np => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end end (@Some bool b) *)
  unfold Val.cmpu_bool; rewrite Heqb1.
  destruct (Int.eq i Int.zero &&
    (Mem.valid_pointer m b0 (Ptrofs.unsigned i0) || Mem.valid_pointer m b0 (Ptrofs.unsigned i0 - 1))); try discriminate H.
  destruct c; simpl in *; inv H; reflexivity.
- (* ptr int *)
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint c => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint c => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_le => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq (Int.xor o s) Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ge => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_g => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vint i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq (Int.xor o s) Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_p => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_np => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end end (@Some bool b) *)
  unfold Val.cmpu_bool; rewrite Heqb1.
  destruct (Int.eq i0 Int.zero &&
    (Mem.valid_pointer m b0 (Ptrofs.unsigned i) || Mem.valid_pointer m b0 (Ptrofs.unsigned i - 1))); try discriminate H.
  destruct c; simpl in *; inv H; reflexivity.
- (* ptr ptr *)
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint c => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Clt (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint c => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_le => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq (Int.xor o s) Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ge => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_g => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.of_optbool (Val.cmpu_bool (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq (Int.xor o s) Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_p => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_np => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end end (@Some bool b) *)
  unfold Val.cmpu_bool; rewrite Heqb2.
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => @None bool | Cond_le => @None bool | Cond_ge => @None bool | Cond_g => @None bool | Cond_p => @None bool | Cond_np => @None bool end (@Some bool b) *)
  fold (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) in *.
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => @None bool | Cond_le => @None bool | Cond_ge => @None bool | Cond_g => @None bool | Cond_p => @None bool | Cond_np => @None bool end (@Some bool b) *)
  fold (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) in *.
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => @None bool | Cond_le => @None bool | Cond_ge => @None bool | Cond_g => @None bool | Cond_p => @None bool | Cond_np => @None bool end (@Some bool b) *)
  destruct (eq_block b0 b1).
  destruct (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i) &&
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn c rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
            Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)); inv H.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct c; simpl; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Ptrofs.eq i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Ptrofs.eq i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Ptrofs.ltu i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite Ptrofs.not_ltu. destruct (Ptrofs.ltu i i0); simpl; destruct (Ptrofs.eq i i0); auto.
  rewrite (Ptrofs.ltu_not i i0). destruct (Ptrofs.ltu i i0); destruct (Ptrofs.eq i i0); reflexivity.
  destruct (Ptrofs.ltu i i0); reflexivity.
  destruct (Mem.valid_pointer m b0 (Ptrofs.unsigned i) &&
            Mem.valid_pointer m b1 (Ptrofs.unsigned i0)); try discriminate H.
  destruct c; simpl in *; inv H; reflexivity.
Qed.

Lemma compare_longs_spec:
  forall rs v1 v2 m,
  let rs' := nextinstr (compare_longs v1 v2 rs m) in
     rs'#ZF = Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2)
  /\ rs'#CF = Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2)
  /\ rs'#SF = Val.negativel (Val.subl v1 v2)
  /\ rs'#OF = Val.subl_overflow v1 v2
  /\ (forall r, data_preg r = true -> rs'#r = rs#r).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold rs'; unfold compare_longs.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs.
Qed.

Lemma int64_sub_overflow:
  forall x y,
  Int.xor (Int.repr (Int64.unsigned (Int64.sub_overflow x y Int64.zero)))
          (Int.repr (Int64.unsigned (Int64.negative (Int64.sub x y)))) =
  (if Int64.lt x y then Int.one else Int.zero).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros.
(* Goal: @eq Int.int (Int.xor (Int.repr (Int64.unsigned (Int64.sub_overflow x y Int64.zero))) (Int.repr (Int64.unsigned (Int64.negative (Int64.sub x y))))) (if Int64.lt x y then Int.one else Int.zero) *)
  transitivity (Int.repr (Int64.unsigned (if Int64.lt x y then Int64.one else Int64.zero))).
  rewrite <- (Int64.lt_sub_overflow x y).
(* Goal: @eq Int.int (Int.xor (Int.repr (Int64.unsigned (Int64.sub_overflow x y Int64.zero))) (Int.repr (Int64.unsigned (Int64.negative (Int64.sub x y))))) (Int.repr (Int64.unsigned (Int64.xor (Int64.sub_overflow x y Int64.zero) (Int64.negative (Int64.sub x y))))) *)
(* Goal: @eq Int.int (Int.repr (Int64.unsigned (if Int64.lt x y then Int64.one else Int64.zero))) (if Int64.lt x y then Int.one else Int.zero) *)
  unfold Int64.sub_overflow, Int64.negative.
  set (s := Int64.signed x - Int64.signed y - Int64.signed Int64.zero).
  destruct (zle Int64.min_signed s && zle s Int64.max_signed);
  destruct (Int64.lt (Int64.sub x y) Int64.zero);
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int64.lt x y); auto.
Qed.

Lemma testcond_for_signed_comparison_64_correct:
  forall c v1 v2 rs m b,
  Val.cmpl_bool c v1 v2 = Some b ->
  eval_testcond (testcond_for_signed_comparison c)
                (nextinstr (compare_longs v1 v2 rs m)) = Some b.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. generalize (compare_longs_spec rs v1 v2 m).
(* Goal: forall _ : let rs' := nextinstr (compare_longs v1 v2 rs m) in and (@eq val (rs' (CR ZF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2))) (and (@eq val (rs' (CR CF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2))) (and (@eq val (rs' (CR SF)) (Val.negativel (Val.subl v1 v2))) (and (@eq val (rs' (CR OF)) (Val.subl_overflow v1 v2)) (forall (r : preg) (_ : @eq bool (data_preg r) true), @eq val (rs' r) (rs r))))), @eq (option bool) (eval_testcond (testcond_for_unsigned_comparison c) (nextinstr (compare_longs v1 v2 rs m))) (@Some bool b) *)
  set (rs' := nextinstr (compare_longs v1 v2 rs m)).
(* Goal: forall _ : let rs' := rs' in and (@eq val (rs' (CR ZF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2))) (and (@eq val (rs' (CR CF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2))) (and (@eq val (rs' (CR SF)) (Val.negativel (Val.subl v1 v2))) (and (@eq val (rs' (CR OF)) (Val.subl_overflow v1 v2)) (forall (r : preg) (_ : @eq bool (data_preg r) true), @eq val (rs' r) (rs r))))), @eq (option bool) (eval_testcond (testcond_for_unsigned_comparison c) rs') (@Some bool b) *)
  intros [A [B [C [D E]]]].
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn c rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
  destruct v1; destruct v2; simpl in H; inv H.
(* Goal: @eq (option bool) (eval_testcond c (@Pregmap.set val (IR r) v rs)) (eval_testcond c rs) *)
  unfold eval_testcond. rewrite A; rewrite B; rewrite C; rewrite D.
(* Goal: @eq (option bool) match testcond_for_signed_comparison c with | Cond_e => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint c => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint c => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => match Val.subl_overflow (Vlong i) (Vlong i0) with | Vundef => @None bool | Vint o => match Val.negativel (Val.subl (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_le => match Val.subl_overflow (Vlong i) (Vlong i0) with | Vundef => @None bool | Vint o => match Val.negativel (Val.subl (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint s => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq (Int.xor o s) Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ge => match Val.subl_overflow (Vlong i) (Vlong i0) with | Vundef => @None bool | Vint o => match Val.negativel (Val.subl (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_g => match Val.subl_overflow (Vlong i) (Vlong i0) with | Vundef => @None bool | Vint o => match Val.negativel (Val.subl (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint s => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vlong i) (Vlong i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq (Int.xor o s) Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_p => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_np => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end end (@Some bool (Int64.cmp c i i0)) *)
  simpl; rewrite int64_sub_overflow.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  destruct c; simpl.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int64.eq i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int64.eq i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int64.lt i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite Int64.not_lt. destruct (Int64.lt i i0); simpl; destruct (Int64.eq i i0); auto.
  rewrite (Int64.lt_not i i0). destruct (Int64.lt i i0); destruct (Int64.eq i i0); reflexivity.
  destruct (Int64.lt i i0); reflexivity.
Qed.

Lemma testcond_for_unsigned_comparison_64_correct:
  forall c v1 v2 rs m b,
  Val.cmplu_bool (Mem.valid_pointer m) c v1 v2 = Some b ->
  eval_testcond (testcond_for_unsigned_comparison c)
                (nextinstr (compare_longs v1 v2 rs m)) = Some b.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. generalize (compare_longs_spec rs v1 v2 m).
(* Goal: forall _ : let rs' := nextinstr (compare_longs v1 v2 rs m) in and (@eq val (rs' (CR ZF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2))) (and (@eq val (rs' (CR CF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2))) (and (@eq val (rs' (CR SF)) (Val.negativel (Val.subl v1 v2))) (and (@eq val (rs' (CR OF)) (Val.subl_overflow v1 v2)) (forall (r : preg) (_ : @eq bool (data_preg r) true), @eq val (rs' r) (rs r))))), @eq (option bool) (eval_testcond (testcond_for_unsigned_comparison c) (nextinstr (compare_longs v1 v2 rs m))) (@Some bool b) *)
  set (rs' := nextinstr (compare_longs v1 v2 rs m)).
(* Goal: forall _ : let rs' := rs' in and (@eq val (rs' (CR ZF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2))) (and (@eq val (rs' (CR CF)) (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2))) (and (@eq val (rs' (CR SF)) (Val.negativel (Val.subl v1 v2))) (and (@eq val (rs' (CR OF)) (Val.subl_overflow v1 v2)) (forall (r : preg) (_ : @eq bool (data_preg r) true), @eq val (rs' r) (rs r))))), @eq (option bool) (eval_testcond (testcond_for_unsigned_comparison c) rs') (@Some bool b) *)
  intros [A [B [C [D E]]]].
(* Goal: @eq (option bool) (eval_testcond c (@Pregmap.set val (IR r) v rs)) (eval_testcond c rs) *)
  unfold eval_testcond. rewrite A; rewrite B.
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2) with | Vundef => @None bool | Vint c => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt v1 v2) with | Vundef => @None bool | Vint c => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_le => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq (Int.xor o s) Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ge => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_g => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq (Int.xor o s) Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_p => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_np => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end end (@Some bool b) *)
  destruct v1; destruct v2; simpl in H; FuncInv; subst.
- (* int int *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct c; simpl; auto.
  destruct (Int64.eq i i0); reflexivity.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int64.eq i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Int64.ltu i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite Int64.not_ltu. destruct (Int64.ltu i i0); simpl; destruct (Int64.eq i i0); auto.
  rewrite (Int64.ltu_not i i0). destruct (Int64.ltu i i0); destruct (Int64.eq i i0); reflexivity.
  destruct (Int64.ltu i i0); reflexivity.
- (* int ptr *)
(* Goal: forall _ : @eq bool (andb true true) false, or (not (@eq Int64.int i (Int64.repr Int64.min_signed))) (not (@eq Int64.int i0 Int64.mone)) *)
  unfold Val.cmplu; simpl; destruct Archi.ptr64; try discriminate.
  destruct (Int64.eq i Int64.zero &&
    (Mem.valid_pointer m b0 (Ptrofs.unsigned i0) || Mem.valid_pointer m b0 (Ptrofs.unsigned i0 - 1))) eqn:?; try discriminate H.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct c; simpl in *; inv H; auto.
- (* ptr int *)
(* Goal: forall _ : @eq bool (andb true true) false, or (not (@eq Int64.int i (Int64.repr Int64.min_signed))) (not (@eq Int64.int i0 Int64.mone)) *)
  unfold Val.cmplu; simpl; destruct Archi.ptr64; try discriminate.
  destruct (Int64.eq i0 Int64.zero &&
    (Mem.valid_pointer m b0 (Ptrofs.unsigned i) || Mem.valid_pointer m b0 (Ptrofs.unsigned i - 1))) eqn:?; try discriminate H.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct c; simpl in *; inv H; auto.
- (* ptr ptr *)
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint c => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint c => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_le => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq (Int.xor o s) Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ge => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => @Some bool (Int.eq (Int.xor o s) Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_g => match rs' (CR OF) with | Vundef => @None bool | Vint o => match rs' (CR SF) with | Vundef => @None bool | Vint s => match Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq (Vptr b0 i) (Vptr b1 i0)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq (Int.xor o s) Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_p => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_np => match rs' (CR PF) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end end (@Some bool b) *)
  unfold Val.cmplu; simpl; destruct Archi.ptr64; try discriminate H.
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (orb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b0 (Z.sub (Ptrofs.unsigned i) (Zpos xH)))) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => @None bool | Cond_le => @None bool | Cond_ge => @None bool | Cond_g => @None bool | Cond_p => @None bool | Cond_np => @None bool end (@Some bool b) *)
  fold (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) in *.
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (orb (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) (Mem.valid_pointer m b1 (Z.sub (Ptrofs.unsigned i0) (Zpos xH)))) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => @None bool | Cond_le => @None bool | Cond_ge => @None bool | Cond_g => @None bool | Cond_p => @None bool | Cond_np => @None bool end (@Some bool b) *)
  fold (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) in *.
(* Goal: @eq (option bool) match testcond_for_unsigned_comparison c with | Cond_e => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ne => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_b => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.one) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_be => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (orb (Int.eq c Int.one) (Int.eq z Int.one)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_ae => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint n => @Some bool (Int.eq n Int.zero) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_a => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.ltu i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @None bool else @None bool)) with | Vundef => @None bool | Vint c => match Val.maketotal (@option_map bool val Val.of_bool (if negb true then @None bool else if eq_block b0 b1 then if andb (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool (Ptrofs.eq i i0) else @None bool else if andb (Mem.valid_pointer m b0 (Ptrofs.unsigned i)) (Mem.valid_pointer m b1 (Ptrofs.unsigned i0)) then @Some bool false else @None bool)) with | Vundef => @None bool | Vint z => @Some bool (andb (Int.eq c Int.zero) (Int.eq z Int.zero)) | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Vlong i => @None bool | Vfloat f => @None bool | Vsingle f => @None bool | Vptr b i => @None bool end | Cond_l => @None bool | Cond_le => @None bool | Cond_ge => @None bool | Cond_g => @None bool | Cond_p => @None bool | Cond_np => @None bool end (@Some bool b) *)
  destruct (eq_block b0 b1).
  destruct (Mem.weak_valid_pointer m b0 (Ptrofs.unsigned i) &&
(* Goal: @ex regset (fun rs2 : regset => and (exec_straight ge fn c rs1 m k rs2 m) (and (@eq val (rs2 (IR RAX)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs2 r) (rs1 r)))) *)
            Mem.weak_valid_pointer m b1 (Ptrofs.unsigned i0)); inv H.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct c; simpl; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Ptrofs.eq i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Ptrofs.eq i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Ptrofs.ltu i i0); auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite Ptrofs.not_ltu. destruct (Ptrofs.ltu i i0); simpl; destruct (Ptrofs.eq i i0); auto.
  rewrite (Ptrofs.ltu_not i i0). destruct (Ptrofs.ltu i i0); destruct (Ptrofs.eq i i0); reflexivity.
  destruct (Ptrofs.ltu i i0); reflexivity.
  destruct (Mem.valid_pointer m b0 (Ptrofs.unsigned i) &&
            Mem.valid_pointer m b1 (Ptrofs.unsigned i0)); try discriminate H.
  destruct c; simpl in *; inv H; reflexivity.
Qed.

Lemma compare_floats_spec:
  forall rs n1 n2,
  let rs' := nextinstr (compare_floats (Vfloat n1) (Vfloat n2) rs) in
     rs'#ZF = Val.of_bool (Float.cmp Ceq n1 n2 || negb (Float.ordered n1 n2))
  /\ rs'#CF = Val.of_bool (negb (Float.cmp Cge n1 n2))
  /\ rs'#PF = Val.of_bool (negb (Float.ordered n1 n2))
  /\ (forall r, data_preg r = true -> rs'#r = rs#r).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold rs'; unfold compare_floats.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs.
Qed.

Lemma compare_floats32_spec:
  forall rs n1 n2,
  let rs' := nextinstr (compare_floats32 (Vsingle n1) (Vsingle n2) rs) in
     rs'#ZF = Val.of_bool (Float32.cmp Ceq n1 n2 || negb (Float32.ordered n1 n2))
  /\ rs'#CF = Val.of_bool (negb (Float32.cmp Cge n1 n2))
  /\ rs'#PF = Val.of_bool (negb (Float32.ordered n1 n2))
  /\ (forall r, data_preg r = true -> rs'#r = rs#r).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold rs'; unfold compare_floats32.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs.
Qed.

Definition eval_extcond (xc: extcond) (rs: regset) : option bool :=
  match xc with
  | Cond_base c =>
      eval_testcond c rs
  | Cond_and c1 c2 =>
      match eval_testcond c1 rs, eval_testcond c2 rs with
      | Some b1, Some b2 => Some (b1 && b2)
      | _, _ => None
      end
  | Cond_or c1 c2 =>
      match eval_testcond c1 rs, eval_testcond c2 rs with
      | Some b1, Some b2 => Some (b1 || b2)
      | _, _ => None
      end
  end.

(* Goal: forall (v : val) (i : Z), Val.lessdef (Val.mull v (Vlong (Int64.repr i))) (if zeq i (Zpos xH) then v else Val.mull v (Vlong (Int64.repr i))) *)
(* Goal: forall (addr : addressing) (args : list mreg) (am : addrmode) (rs : regset) (v : val) (_ : @eq (res addrmode) (transl_addressing addr args) (@OK addrmode am)) (_ : @eq (option val) (@eval_addressing64 fundef unit ge (rs (IR RSP)) addr (@map PregEq.t val rs (@map mreg preg preg_of args))) (@Some val v)), Val.lessdef v (eval_addrmode64 ge am rs) *)
Definition swap_floats {A: Type} (c: comparison) (n1 n2: A) : A :=
  match c with
  | Clt | Cle => n2
  | Ceq | Cne | Cgt | Cge => n1
  end.

Lemma testcond_for_float_comparison_correct:
  forall c n1 n2 rs,
  eval_extcond (testcond_for_condition (Ccompf c))
               (nextinstr (compare_floats (Vfloat (swap_floats c n1 n2))
                                          (Vfloat (swap_floats c n2 n1)) rs)) =
  Some(Float.cmp c n1 n2).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros.
  generalize (compare_floats_spec rs (swap_floats c n1 n2) (swap_floats c n2 n1)).
  set (rs' := nextinstr (compare_floats (Vfloat (swap_floats c n1 n2))
                                        (Vfloat (swap_floats c n2 n1)) rs)).
  intros [A [B [C D]]].
  unfold eval_extcond, eval_testcond. rewrite A; rewrite B; rewrite C.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  destruct c; simpl.
- (* eq *)
Transparent Float.cmp Float.ordered.
  unfold Float.ordered, Float.cmp; destruct (Float.compare n1 n2) as [[]|]; reflexivity.
- (* ne *)
  unfold Float.ordered, Float.cmp; destruct (Float.compare n1 n2) as [[]|]; reflexivity.
- (* lt *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  rewrite <- (Float.cmp_swap Clt n2 n1). simpl. unfold Float.ordered. 
  destruct (Float.compare n2 n1) as [[]|]; reflexivity.
- (* le *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  rewrite <- (Float.cmp_swap Cge n1 n2). simpl.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Float.compare n1 n2) as [[]|]; auto.
- (* gt *)
 unfold Float.ordered, Float.cmp; destruct (Float.compare n1 n2) as [[]|]; reflexivity.
- (* ge *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Float.cmp Cge n1 n2); auto.
Opaque Float.cmp Float.ordered.
Qed.

Lemma testcond_for_neg_float_comparison_correct:
  forall c n1 n2 rs,
  eval_extcond (testcond_for_condition (Cnotcompf c))
               (nextinstr (compare_floats (Vfloat (swap_floats c n1 n2))
                                          (Vfloat (swap_floats c n2 n1)) rs)) =
  Some(negb(Float.cmp c n1 n2)).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros.
  generalize (compare_floats_spec rs (swap_floats c n1 n2) (swap_floats c n2 n1)).
  set (rs' := nextinstr (compare_floats (Vfloat (swap_floats c n1 n2))
                                        (Vfloat (swap_floats c n2 n1)) rs)).
  intros [A [B [C D]]].
  unfold eval_extcond, eval_testcond. rewrite A; rewrite B; rewrite C.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  destruct c; simpl.
- (* eq *)
Transparent Float.cmp Float.ordered.
  unfold Float.ordered, Float.cmp; destruct (Float.compare n1 n2) as [[]|]; reflexivity.
- (* ne *)
  unfold Float.ordered, Float.cmp; destruct (Float.compare n1 n2) as [[]|]; reflexivity.
- (* lt *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  rewrite <- (Float.cmp_swap Clt n2 n1). simpl. unfold Float.ordered. 
  destruct (Float.compare n2 n1) as [[]|]; reflexivity.
- (* le *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  rewrite <- (Float.cmp_swap Cge n1 n2). simpl.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Float.compare n1 n2) as [[]|]; auto.
- (* gt *)
 unfold Float.ordered, Float.cmp; destruct (Float.compare n1 n2) as [[]|]; reflexivity.
- (* ge *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Float.cmp Cge n1 n2); auto.
Opaque Float.cmp Float.ordered.
Qed.

Lemma testcond_for_float32_comparison_correct:
  forall c n1 n2 rs,
  eval_extcond (testcond_for_condition (Ccompfs c))
               (nextinstr (compare_floats32 (Vsingle (swap_floats c n1 n2))
                                            (Vsingle (swap_floats c n2 n1)) rs)) =
  Some(Float32.cmp c n1 n2).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros.
  generalize (compare_floats32_spec rs (swap_floats c n1 n2) (swap_floats c n2 n1)).
  set (rs' := nextinstr (compare_floats32 (Vsingle (swap_floats c n1 n2))
                                        (Vsingle (swap_floats c n2 n1)) rs)).
  intros [A [B [C D]]].
  unfold eval_extcond, eval_testcond. rewrite A; rewrite B; rewrite C.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  destruct c; simpl.
- (* eq *)
Transparent Float32.cmp Float32.ordered.
  unfold Float32.ordered, Float32.cmp; destruct (Float32.compare n1 n2) as [[]|]; reflexivity.
- (* ne *)
  unfold Float32.ordered, Float32.cmp; destruct (Float32.compare n1 n2) as [[]|]; reflexivity.
- (* lt *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  rewrite <- (Float32.cmp_swap Clt n2 n1). simpl. unfold Float32.ordered. 
  destruct (Float32.compare n2 n1) as [[]|]; reflexivity.
- (* le *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  rewrite <- (Float32.cmp_swap Cge n1 n2). simpl.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Float32.compare n1 n2) as [[]|]; auto.
- (* gt *)
 unfold Float32.ordered, Float32.cmp; destruct (Float32.compare n1 n2) as [[]|]; reflexivity.
- (* ge *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Float32.cmp Cge n1 n2); auto.
Opaque Float32.cmp Float32.ordered.
Qed.

Lemma testcond_for_neg_float32_comparison_correct:
  forall c n1 n2 rs,
  eval_extcond (testcond_for_condition (Cnotcompfs c))
               (nextinstr (compare_floats32 (Vsingle (swap_floats c n1 n2))
                                            (Vsingle (swap_floats c n2 n1)) rs)) =
  Some(negb(Float32.cmp c n1 n2)).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros.
  generalize (compare_floats32_spec rs (swap_floats c n1 n2) (swap_floats c n2 n1)).
  set (rs' := nextinstr (compare_floats32 (Vsingle (swap_floats c n1 n2))
                                          (Vsingle (swap_floats c n2 n1)) rs)).
  intros [A [B [C D]]].
  unfold eval_extcond, eval_testcond. rewrite A; rewrite B; rewrite C.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  destruct c; simpl.
- (* eq *)
Transparent Float32.cmp Float32.ordered.
  unfold Float32.ordered, Float32.cmp; destruct (Float32.compare n1 n2) as [[]|]; reflexivity.
- (* ne *)
  unfold Float32.ordered, Float32.cmp; destruct (Float32.compare n1 n2) as [[]|]; reflexivity.
- (* lt *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  rewrite <- (Float32.cmp_swap Clt n2 n1). simpl. unfold Float32.ordered. 
  destruct (Float32.compare n2 n1) as [[]|]; reflexivity.
- (* le *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  rewrite <- (Float32.cmp_swap Cge n1 n2). simpl.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Float32.compare n1 n2) as [[]|]; auto.
- (* gt *)
 unfold Float32.ordered, Float32.cmp; destruct (Float32.compare n1 n2) as [[]|]; reflexivity.
- (* ge *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (Float32.cmp Cge n1 n2); auto.
Opaque Float32.cmp Float32.ordered.
Qed.

Remark swap_floats_commut:
  forall (A B: Type) c (f: A -> B) x y, swap_floats c (f x) (f y) = f (swap_floats c x y).
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. destruct c; auto.
Qed.

Remark compare_floats_inv:
  forall vx vy rs r,
  r <> CR ZF -> r <> CR CF -> r <> CR PF -> r <> CR SF -> r <> CR OF ->
  compare_floats vx vy rs r = rs r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros.
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  assert (DFL: undef_regs (CR ZF :: CR CF :: CR PF :: CR SF :: CR OF :: nil) rs r = rs r).
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
    simpl. Simplifs.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  unfold compare_floats; destruct vx; destruct vy; auto. Simplifs.
Qed.

Remark compare_floats32_inv:
  forall vx vy rs r,
  r <> CR ZF -> r <> CR CF -> r <> CR PF -> r <> CR SF -> r <> CR OF ->
  compare_floats32 vx vy rs r = rs r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros.
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  assert (DFL: undef_regs (CR ZF :: CR CF :: CR PF :: CR SF :: CR OF :: nil) rs r = rs r).
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
    simpl. Simplifs.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  unfold compare_floats32; destruct vx; destruct vy; auto. Simplifs.
Qed.

Lemma transl_cond_correct:
  forall cond args k c rs m,
  transl_cond cond args k = OK c ->
  exists rs',
     exec_straight ge fn c rs m k rs' m
  /\ match eval_condition cond (map rs (map preg_of args)) m with
     | None => True
     | Some b => eval_extcond (testcond_for_condition cond) rs' = Some b
     end
  /\ forall r, data_preg r = true -> rs'#r = rs r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold transl_cond; intros.
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct cond; repeat (destruct args; try discriminate); monadInv H.
- (* comp *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (ireg_of_eq _ _ EQ). rewrite (ireg_of_eq _ _ EQ1).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. simpl. eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (Val.cmp_bool c0 (rs x) (rs x0)) eqn:?; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply testcond_for_signed_comparison_32_correct; eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_ints. Simplifs.
- (* compu *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (ireg_of_eq _ _ EQ). rewrite (ireg_of_eq _ _ EQ1).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. simpl. eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (Val.cmpu_bool (Mem.valid_pointer m) c0 (rs x) (rs x0)) eqn:?; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply testcond_for_unsigned_comparison_32_correct; eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_ints. Simplifs.
- (* compimm *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (ireg_of_eq _ _ EQ). destruct (Int.eq_dec n Int.zero).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor; split. apply exec_straight_one. simpl; eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (rs x); simpl; auto. subst. rewrite Int.and_idem.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply testcond_for_signed_comparison_32_correct; eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_ints. Simplifs.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor; split. apply exec_straight_one. simpl; eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (Val.cmp_bool c0 (rs x) (Vint n)) eqn:?; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply testcond_for_signed_comparison_32_correct; eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_ints. Simplifs.
- (* compuimm *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (ireg_of_eq _ _ EQ).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. simpl. eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (Val.cmpu_bool (Mem.valid_pointer m) c0 (rs x) (Vint n)) eqn:?; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply testcond_for_unsigned_comparison_32_correct; eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_ints. Simplifs.
- (* compl *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (ireg_of_eq _ _ EQ). rewrite (ireg_of_eq _ _ EQ1).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. simpl. eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (Val.cmpl_bool c0 (rs x) (rs x0)) eqn:?; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply testcond_for_signed_comparison_64_correct; eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_longs. Simplifs.
- (* complu *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (ireg_of_eq _ _ EQ). rewrite (ireg_of_eq _ _ EQ1).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. simpl. eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (Val.cmplu_bool (Mem.valid_pointer m) c0 (rs x) (rs x0)) eqn:?; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply testcond_for_unsigned_comparison_64_correct; eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_longs. Simplifs.
- (* compimm *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (ireg_of_eq _ _ EQ). destruct (Int64.eq_dec n Int64.zero).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor; split. apply exec_straight_one. simpl; eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (rs x); simpl; auto. subst. rewrite Int64.and_idem.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply testcond_for_signed_comparison_64_correct; eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_longs. Simplifs.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor; split. apply exec_straight_one. simpl; eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (Val.cmpl_bool c0 (rs x) (Vlong n)) eqn:?; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply testcond_for_signed_comparison_64_correct; eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_longs. Simplifs.
- (* compuimm *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (ireg_of_eq _ _ EQ).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. simpl. eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (Val.cmplu_bool (Mem.valid_pointer m) c0 (rs x) (Vlong n)) eqn:?; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply testcond_for_unsigned_comparison_64_correct; eauto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_longs. Simplifs.
- (* compf *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (freg_of_eq _ _ EQ). rewrite (freg_of_eq _ _ EQ1).
  exists (nextinstr (compare_floats (swap_floats c0 (rs x) (rs x0)) (swap_floats c0 (rs x0) (rs x)) rs)).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. apply exec_straight_one.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct c0; simpl; auto.
(* Goal: @eq val (Val.shr (@Pregmap.set val (IR RAX) (Vint x') rs3 (IR RAX)) (Vint n)) (Val.shr (Val.add (rs1 (IR RAX)) (Vint tnm1)) (Vint n)) *)
(* Goal: @eq val (Val.shr (rs3 (IR RAX)) (Vint n)) (Val.shr (rs1 (IR RAX)) (Vint n)) *)
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs5 r) (rs1 r) *)
  unfold nextinstr. rewrite Pregmap.gss. rewrite compare_floats_inv; auto with asmgen.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (rs x); destruct (rs x0); simpl; auto.
  repeat rewrite swap_floats_commut. apply testcond_for_float_comparison_correct.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs. apply compare_floats_inv; auto with asmgen.
- (* notcompf *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (freg_of_eq _ _ EQ). rewrite (freg_of_eq _ _ EQ1).
  exists (nextinstr (compare_floats (swap_floats c0 (rs x) (rs x0)) (swap_floats c0 (rs x0) (rs x)) rs)).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. apply exec_straight_one.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct c0; simpl; auto.
(* Goal: @eq val (Val.shr (@Pregmap.set val (IR RAX) (Vint x') rs3 (IR RAX)) (Vint n)) (Val.shr (Val.add (rs1 (IR RAX)) (Vint tnm1)) (Vint n)) *)
(* Goal: @eq val (Val.shr (rs3 (IR RAX)) (Vint n)) (Val.shr (rs1 (IR RAX)) (Vint n)) *)
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs5 r) (rs1 r) *)
  unfold nextinstr. rewrite Pregmap.gss. rewrite compare_floats_inv; auto with asmgen.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (rs x); destruct (rs x0); simpl; auto.
  repeat rewrite swap_floats_commut. apply testcond_for_neg_float_comparison_correct.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs. apply compare_floats_inv; auto with asmgen.
- (* compfs *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (freg_of_eq _ _ EQ). rewrite (freg_of_eq _ _ EQ1).
  exists (nextinstr (compare_floats32 (swap_floats c0 (rs x) (rs x0)) (swap_floats c0 (rs x0) (rs x)) rs)).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. apply exec_straight_one.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct c0; simpl; auto.
(* Goal: @eq val (Val.shr (@Pregmap.set val (IR RAX) (Vint x') rs3 (IR RAX)) (Vint n)) (Val.shr (Val.add (rs1 (IR RAX)) (Vint tnm1)) (Vint n)) *)
(* Goal: @eq val (Val.shr (rs3 (IR RAX)) (Vint n)) (Val.shr (rs1 (IR RAX)) (Vint n)) *)
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs5 r) (rs1 r) *)
  unfold nextinstr. rewrite Pregmap.gss. rewrite compare_floats32_inv; auto with asmgen.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (rs x); destruct (rs x0); simpl; auto.
  repeat rewrite swap_floats_commut. apply testcond_for_float32_comparison_correct.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs. apply compare_floats32_inv; auto with asmgen.
- (* notcompfs *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (freg_of_eq _ _ EQ). rewrite (freg_of_eq _ _ EQ1).
  exists (nextinstr (compare_floats32 (swap_floats c0 (rs x) (rs x0)) (swap_floats c0 (rs x0) (rs x)) rs)).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. apply exec_straight_one.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct c0; simpl; auto.
(* Goal: @eq val (Val.shr (@Pregmap.set val (IR RAX) (Vint x') rs3 (IR RAX)) (Vint n)) (Val.shr (Val.add (rs1 (IR RAX)) (Vint tnm1)) (Vint n)) *)
(* Goal: @eq val (Val.shr (rs3 (IR RAX)) (Vint n)) (Val.shr (rs1 (IR RAX)) (Vint n)) *)
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (IR RAX))) (_ : not (@eq preg r (IR RCX))), @eq val (rs5 r) (rs1 r) *)
  unfold nextinstr. rewrite Pregmap.gss. rewrite compare_floats32_inv; auto with asmgen.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (rs x); destruct (rs x0); simpl; auto.
  repeat rewrite swap_floats_commut. apply testcond_for_neg_float32_comparison_correct.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs. apply compare_floats32_inv; auto with asmgen.
- (* maskzero *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (ireg_of_eq _ _ EQ).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. simpl; eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (rs x); simpl; auto.
  generalize (compare_ints_spec rs (Vint (Int.and i n)) Vzero m).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  intros [A B]. rewrite A. unfold Val.cmpu; simpl. destruct (Int.eq (Int.and i n) Int.zero); auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_ints. Simplifs.
- (* masknotzero *)
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. rewrite (ireg_of_eq _ _ EQ).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  econstructor. split. apply exec_straight_one. simpl; eauto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. destruct (rs x); simpl; auto.
  generalize (compare_ints_spec rs (Vint (Int.and i n)) Vzero m).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  intros [A B]. rewrite A. unfold Val.cmpu; simpl. destruct (Int.eq (Int.and i n) Int.zero); auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold compare_ints. Simplifs.
Qed.

Remark eval_testcond_nextinstr:
  forall c rs, eval_testcond c (nextinstr rs) = eval_testcond c rs.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold eval_testcond. repeat rewrite nextinstr_inv; auto with asmgen.
Qed.

Remark eval_testcond_set_ireg:
  forall c rs r v, eval_testcond c (rs#(IR r) <- v) = eval_testcond c rs.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold eval_testcond. repeat rewrite Pregmap.gso; auto with asmgen.
Qed.

Lemma mk_setcc_base_correct:
  forall cond rd k rs1 m,
  exists rs2,
  exec_straight ge fn (mk_setcc_base cond rd k) rs1 m k rs2 m
  /\ rs2#rd = Val.of_optbool(eval_extcond cond rs1)
  /\ forall r, data_preg r = true -> r <> RAX /\ r <> RCX -> r <> rd -> rs2#r = rs1#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. destruct cond; simpl in *.
- (* base *)
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply exec_straight_one. simpl; eauto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. Simplifs. intros; Simplifs.
- (* or *)
  assert (Val.of_optbool
    match eval_testcond c1 rs1 with
    | Some b1 =>
        match eval_testcond c2 rs1 with
        | Some b2 => Some (b1 || b2)
        | None => None
        end
    | None => None
    end =
    Val.or (Val.of_optbool (eval_testcond c1 rs1)) (Val.of_optbool (eval_testcond c2 rs1))).
  destruct (eval_testcond c1 rs1). destruct (eval_testcond c2 rs1).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct b; destruct b0; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct b; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  auto.
  rewrite H; clear H.
  destruct (ireg_eq rd RAX).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  subst rd. econstructor; split.
  eapply exec_straight_three.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl; eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. rewrite eval_testcond_nextinstr. repeat rewrite eval_testcond_set_ireg. eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl; eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  auto. auto. auto.
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  intuition Simplifs.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
  eapply exec_straight_three.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl; eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. rewrite eval_testcond_nextinstr. repeat rewrite eval_testcond_set_ireg. eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  auto. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. Simplifs. rewrite Val.or_commut. decEq; Simplifs.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. destruct H0; Simplifs.
- (* and *)
  assert (Val.of_optbool
    match eval_testcond c1 rs1 with
    | Some b1 =>
        match eval_testcond c2 rs1 with
        | Some b2 => Some (b1 && b2)
        | None => None
        end
    | None => None
    end =
    Val.and (Val.of_optbool (eval_testcond c1 rs1)) (Val.of_optbool (eval_testcond c2 rs1))).
(* Goal: forall (v : val) (i : Z), Val.lessdef (Val.mull v (Vlong (Int64.repr i))) (if zeq i (Zpos xH) then v else Val.mull v (Vlong (Int64.repr i))) *)
(* Goal: forall (addr : addressing) (args : list mreg) (am : addrmode) (rs : regset) (v : val) (_ : @eq (res addrmode) (transl_addressing addr args) (@OK addrmode am)) (_ : @eq (option val) (@eval_addressing64 fundef unit ge (rs (IR RSP)) addr (@map PregEq.t val rs (@map mreg preg preg_of args))) (@Some val v)), Val.lessdef v (eval_addrmode64 ge am rs) *)
  {
    destruct (eval_testcond c1 rs1). destruct (eval_testcond c2 rs1).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    destruct b; destruct b0; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    destruct b; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    auto.
  }
  rewrite H; clear H.
  destruct (ireg_eq rd RAX).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  subst rd. econstructor; split.
  eapply exec_straight_three.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl; eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. rewrite eval_testcond_nextinstr. repeat rewrite eval_testcond_set_ireg. eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl; eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  auto. auto. auto.
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  intuition Simplifs.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
  eapply exec_straight_three.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl; eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. rewrite eval_testcond_nextinstr. repeat rewrite eval_testcond_set_ireg. eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  auto. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. Simplifs. rewrite Val.and_commut. decEq; Simplifs.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. destruct H0; Simplifs.
Qed.

Lemma mk_setcc_correct:
  forall cond rd k rs1 m,
  exists rs2,
  exec_straight ge fn (mk_setcc cond rd k) rs1 m k rs2 m
  /\ rs2#rd = Val.of_optbool(eval_extcond cond rs1)
  /\ forall r, data_preg r = true -> r <> RAX /\ r <> RCX -> r <> rd -> rs2#r = rs1#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold mk_setcc. destruct (Archi.ptr64 || low_ireg rd).
- apply mk_setcc_base_correct.
- exploit mk_setcc_base_correct. intros [rs2 [A [B C]]].
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split. eapply exec_straight_trans. eexact A. apply exec_straight_one.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    simpl. eauto. simpl. auto.
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  intuition Simplifs.
Qed.

(** Translation of arithmetic operations. *)

Ltac ArgsInv :=
  match goal with
  | [ H: Error _ = OK _ |- _ ] => discriminate
  | [ H: match ?args with nil => _ | _ :: _ => _ end = OK _ |- _ ] => destruct args; ArgsInv
  | [ H: bind _ _ = OK _ |- _ ] => monadInv H; ArgsInv
  | [ H: match _ with left _ => _ | right _ => assertion_failed end = OK _ |- _ ] => monadInv H; ArgsInv
  | [ H: match _ with true => _ | false => assertion_failed end = OK _ |- _ ] => monadInv H; ArgsInv
  | [ H: ireg_of _ = OK _ |- _ ] => simpl in *; rewrite (ireg_of_eq _ _ H) in *; clear H; ArgsInv
  | [ H: freg_of _ = OK _ |- _ ] => simpl in *; rewrite (freg_of_eq _ _ H) in *; clear H; ArgsInv
  | _ => idtac
  end.

Ltac TranslOp :=
  econstructor; split;
  [ apply exec_straight_one; [ simpl; eauto | auto ]
  | split; [ Simplifs | intros; Simplifs ]].

Lemma transl_op_correct:
  forall op args res k c (rs: regset) m v,
  transl_op op args res k = OK c ->
  eval_operation ge (rs#RSP) op (map rs (map preg_of args)) m = Some v ->
  exists rs',
     exec_straight ge fn c rs m k rs' m
  /\ Val.lessdef v rs'#(preg_of res)
  /\ forall r, data_preg r = true -> r <> preg_of res -> preg_notin r (destroyed_by_op op) -> rs' r = rs r.
Proof.
Transparent destroyed_by_op.
  intros until v; intros TR EV.
  assert (SAME:
  (exists rs',
     exec_straight ge fn c rs m k rs' m
  /\ rs'#(preg_of res) = v
  /\ forall r, data_preg r = true -> r <> preg_of res -> preg_notin r (destroyed_by_op op) -> rs' r = rs r) ->
  exists rs',
     exec_straight ge fn c rs m k rs' m
  /\ Val.lessdef v rs'#(preg_of res)
  /\ forall r, data_preg r = true -> r <> preg_of res -> preg_notin r (destroyed_by_op op) -> rs' r = rs r).
(* Goal: forall (v : val) (i : Z), Val.lessdef (Val.mull v (Vlong (Int64.repr i))) (if zeq i (Zpos xH) then v else Val.mull v (Vlong (Int64.repr i))) *)
(* Goal: forall (addr : addressing) (args : list mreg) (am : addrmode) (rs : regset) (v : val) (_ : @eq (res addrmode) (transl_addressing addr args) (@OK addrmode am)) (_ : @eq (option val) (@eval_addressing64 fundef unit ge (rs (IR RSP)) addr (@map PregEq.t val rs (@map mreg preg preg_of args))) (@Some val v)), Val.lessdef v (eval_addrmode64 ge am rs) *)
  {
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    intros [rs' [A [B C]]]. subst v. exists rs'; auto.
  }

  destruct op; simpl in TR; ArgsInv; simpl in EV; try (inv EV); try (apply SAME; TranslOp; fail).
(* move *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  exploit mk_mov_correct; eauto. intros [rs2 [A [B C]]].
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. exists rs2. eauto.
(* intconst *)
  apply SAME. destruct (Int.eq_dec n Int.zero). subst n. TranslOp. TranslOp.
(* longconst *)
  apply SAME. destruct (Int64.eq_dec n Int64.zero). subst n. TranslOp. TranslOp.
(* floatconst *)
  apply SAME. destruct (Float.eq_dec n Float.zero). subst n. TranslOp. TranslOp.
(* singleconst *)
  apply SAME. destruct (Float32.eq_dec n Float32.zero). subst n. TranslOp. TranslOp.
(* cast8signed *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. eapply mk_intconv_correct; eauto.
(* cast8unsigned *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. eapply mk_intconv_correct; eauto.
(* mulhs *)
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  apply SAME. TranslOp. destruct H1. Simplifs.
(* mulhu *)
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  apply SAME. TranslOp. destruct H1. Simplifs.
(* div *)
  apply SAME.
  exploit (divs_mods_exists (rs RAX) (rs RCX)). left; congruence.
  intros (nh & nl & d & q & r & A & B & C & D & E & F).
  set (rs1 := nextinstr_nf (rs#RDX <- (Vint nh))).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  eapply exec_straight_two with (rs2 := rs1). simpl. rewrite A. reflexivity.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. change (rs1 RAX) with (rs RAX); rewrite B.
  change (rs1 RCX) with (rs RCX); rewrite C.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite D. reflexivity. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. change (Vint q = v). congruence.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  simpl; intros. destruct H2. unfold rs1; Simplifs.
(* divu *)
  apply SAME.
  exploit (divu_modu_exists (rs RAX) (rs RCX)). left; congruence.
  intros (n & d & q & r & B & C & D & E & F).
  set (rs1 := nextinstr_nf (rs#RDX <- Vzero)).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
  eapply exec_straight_two with (rs2 := rs1). reflexivity.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. change (rs1 RAX) with (rs RAX); rewrite B.
  change (rs1 RCX) with (rs RCX); rewrite C.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite D. reflexivity. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. change (Vint q = v). congruence.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  simpl; intros. destruct H2. unfold rs1; Simplifs.
(* mod *)
  apply SAME.
  exploit (divs_mods_exists (rs RAX) (rs RCX)). right; congruence.
  intros (nh & nl & d & q & r & A & B & C & D & E & F).
  set (rs1 := nextinstr_nf (rs#RDX <- (Vint nh))).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  eapply exec_straight_two with (rs2 := rs1). simpl. rewrite A. reflexivity.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. change (rs1 RAX) with (rs RAX); rewrite B.
  change (rs1 RCX) with (rs RCX); rewrite C.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite D. reflexivity. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. change (Vint r = v). congruence.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  simpl; intros. destruct H2. unfold rs1; Simplifs.
(* modu *)
  apply SAME.
  exploit (divu_modu_exists (rs RAX) (rs RCX)). right; congruence.
  intros (n & d & q & r & B & C & D & E & F).
  set (rs1 := nextinstr_nf (rs#RDX <- Vzero)).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
  eapply exec_straight_two with (rs2 := rs1). reflexivity.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. change (rs1 RAX) with (rs RAX); rewrite B.
  change (rs1 RCX) with (rs RCX); rewrite C.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite D. reflexivity. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. change (Vint r = v). congruence.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  simpl; intros. destruct H2. unfold rs1; Simplifs.
(* shrximm *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. eapply mk_shrximm_correct; eauto.
(* lea *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  exploit transl_addressing_mode_32_correct; eauto. intros EA.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  TranslOp. rewrite nextinstr_inv; auto with asmgen. rewrite Pregmap.gss. rewrite normalize_addrmode_32_correct; auto.
(* mullhs *)
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  apply SAME. TranslOp. destruct H1. Simplifs.
(* mullhu *)
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  apply SAME. TranslOp. destruct H1. Simplifs.
(* divl *)
  apply SAME.
  exploit (divls_modls_exists (rs RAX) (rs RCX)). left; congruence.
  intros (nh & nl & d & q & r & A & B & C & D & E & F).
  set (rs1 := nextinstr_nf (rs#RDX <- (Vlong nh))).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  eapply exec_straight_two with (rs2 := rs1). simpl. rewrite A. reflexivity.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. change (rs1 RAX) with (rs RAX); rewrite B.
  change (rs1 RCX) with (rs RCX); rewrite C.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite D. reflexivity. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. change (Vlong q = v). congruence.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  simpl; intros. destruct H2. unfold rs1; Simplifs.
(* divlu *)
  apply SAME.
  exploit (divlu_modlu_exists (rs RAX) (rs RCX)). left; congruence.
  intros (n & d & q & r & B & C & D & E & F).
  set (rs1 := nextinstr_nf (rs#RDX <- (Vlong Int64.zero))).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
  eapply exec_straight_two with (rs2 := rs1). reflexivity.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. change (rs1 RAX) with (rs RAX); rewrite B.
  change (rs1 RCX) with (rs RCX); rewrite C.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite D. reflexivity. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. change (Vlong q = v). congruence.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  simpl; intros. destruct H2. unfold rs1; Simplifs.
(* modl *)
  apply SAME.
  exploit (divls_modls_exists (rs RAX) (rs RCX)). right; congruence.
  intros (nh & nl & d & q & r & A & B & C & D & E & F).
  set (rs1 := nextinstr_nf (rs#RDX <- (Vlong nh))).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  eapply exec_straight_two with (rs2 := rs1). simpl. rewrite A. reflexivity.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. change (rs1 RAX) with (rs RAX); rewrite B.
  change (rs1 RCX) with (rs RCX); rewrite C.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite D. reflexivity. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. change (Vlong r = v). congruence.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  simpl; intros. destruct H2. unfold rs1; Simplifs.
(* modlu *)
  apply SAME.
  exploit (divlu_modlu_exists (rs RAX) (rs RCX)). right; congruence.
  intros (n & d & q & r & B & C & D & E & F).
  set (rs1 := nextinstr_nf (rs#RDX <- (Vlong Int64.zero))).
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
  eapply exec_straight_two with (rs2 := rs1). reflexivity.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  simpl. change (rs1 RAX) with (rs RAX); rewrite B.
  change (rs1 RCX) with (rs RCX); rewrite C.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite D. reflexivity. auto. auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. change (Vlong r = v). congruence.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  simpl; intros. destruct H2. unfold rs1; Simplifs.
(* shrxlimm *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. eapply mk_shrxlimm_correct; eauto.
(* leal *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  exploit transl_addressing_mode_64_correct; eauto. intros EA.
  generalize (normalize_addrmode_64_correct x rs). destruct (normalize_addrmode_64 x) as [am' [delta|]]; intros EV.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split. eapply exec_straight_two.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl. reflexivity.  simpl. reflexivity. auto. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  split. rewrite nextinstr_nf_inv by auto. rewrite Pregmap.gss. rewrite nextinstr_inv by auto with asmgen.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite Pregmap.gss. rewrite <- EV; auto.
(* Goal: @eq val (nextinstr_nf (@Pregmap.set val (preg_of dest) v rs) r) (rs r) *)
  intros; Simplifs.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  TranslOp. rewrite nextinstr_inv; auto with asmgen. rewrite Pregmap.gss; auto. rewrite <- EV; auto.
(* intoffloat *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. TranslOp. rewrite H0; auto.
(* floatofint *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. TranslOp. rewrite H0; auto.
(* intofsingle *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. TranslOp. rewrite H0; auto.
(* singleofint *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. TranslOp. rewrite H0; auto.
(* longoffloat *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. TranslOp. rewrite H0; auto.
(* floatoflong *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. TranslOp. rewrite H0; auto.
(* longofsingle *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. TranslOp. rewrite H0; auto.
(* singleoflong *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply SAME. TranslOp. rewrite H0; auto.
(* condition *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  exploit transl_cond_correct; eauto. intros [rs2 [P [Q R]]].
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  exploit mk_setcc_correct; eauto. intros [rs3 [S [T U]]].
  exists rs3.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. eapply exec_straight_trans. eexact P. eexact S.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. rewrite T. destruct (eval_condition cond rs ## (preg_of ## args) m).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite Q. auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  simpl; auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. transitivity (rs2 r); auto.
Qed.

(** Translation of memory loads. *)

Lemma transl_load_correct:
  forall chunk addr args dest k c (rs: regset) m a v,
  transl_load chunk addr args dest k = OK c ->
  eval_addressing ge (rs#RSP) addr (map rs (map preg_of args)) = Some a ->
  Mem.loadv chunk m a = Some v ->
  exists rs',
     exec_straight ge fn c rs m k rs' m
  /\ rs'#(preg_of dest) = v
  /\ forall r, data_preg r = true -> r <> preg_of dest -> rs'#r = rs#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold transl_load; intros. monadInv H.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  exploit transl_addressing_mode_correct; eauto. intro EA.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  assert (EA': eval_addrmode ge x rs = a). destruct a; simpl in H1; try discriminate; inv EA; auto.
  set (rs2 := nextinstr_nf (rs#(preg_of dest) <- v)).
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  assert (exec_load ge chunk m x rs (preg_of dest) = Next rs2 m).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    unfold exec_load. rewrite EA'. rewrite H1. auto.
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  assert (rs2 PC = Val.offset_ptr (rs PC) Ptrofs.one).
    transitivity (Val.offset_ptr ((rs#(preg_of dest) <- v) PC) Ptrofs.one).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
    auto. decEq. apply Pregmap.gso; auto with asmgen.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  exists rs2. split.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct chunk; ArgsInv; apply exec_straight_one; auto.
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  split. unfold rs2. rewrite nextinstr_nf_inv1. Simplifs. apply preg_of_data.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. unfold rs2. Simplifs.
Qed.

Lemma transl_store_correct:
  forall chunk addr args src k c (rs: regset) m a m',
  transl_store chunk addr args src k = OK c ->
  eval_addressing ge (rs#RSP) addr (map rs (map preg_of args)) = Some a ->
  Mem.storev chunk m a (rs (preg_of src)) = Some m' ->
  exists rs',
     exec_straight ge fn c rs m k rs' m'
  /\ forall r, data_preg r = true -> preg_notin r (destroyed_by_store chunk addr) -> rs'#r = rs#r.
Proof.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  unfold transl_store; intros. monadInv H.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  exploit transl_addressing_mode_correct; eauto. intro EA.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  assert (EA': eval_addrmode ge x rs = a). destruct a; simpl in H1; try discriminate; inv EA; auto.
  rewrite <- EA' in H1. destruct chunk; ArgsInv.
(* int8signed *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply mk_storebyte_correct; eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (eval_addrmode ge x rs); simpl; auto. rewrite <- Mem.store_signed_unsigned_8; auto.
(* int8unsigned *)
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  eapply mk_storebyte_correct; eauto.
(* int16signed *)
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (undef_regs (@cons preg (CR ZF) (@cons preg (CR CF) (@cons preg (CR PF) (@cons preg (CR SF) (@cons preg (CR OF) (@nil preg)))))) rs r) (rs r) *)
(* Goal: @eq val (compare_floats32 vx vy rs r) (rs r) *)
  apply exec_straight_one. simpl. unfold exec_store.
  replace (Mem.storev Mint16unsigned m (eval_addrmode ge x rs) (rs x0))
     with (Mem.storev Mint16signed m (eval_addrmode ge x rs) (rs x0)).
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  rewrite H1. eauto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  destruct (eval_addrmode ge x rs); simpl; auto. rewrite Mem.store_signed_unsigned_16; auto.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs.
(* int16unsigned *)
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply exec_straight_one. simpl. unfold exec_store. rewrite H1. eauto. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs.
(* int32 *)
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply exec_straight_one. simpl. unfold exec_store. rewrite H1. eauto. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs.
(* int64 *)
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply exec_straight_one. simpl. unfold exec_store. rewrite H1. eauto. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs.
(* float32 *)
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply exec_straight_one. simpl. unfold exec_store. rewrite H1. eauto. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Transparent destroyed_by_store. simpl in H2. simpl. Simplifs.
(* float64 *)
(* Goal: and (@eq val (rs2 (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r)) *)
  econstructor; split.
(* Goal: @eq val (rs2 PC) (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) *)
(* Goal: @eq val (Val.offset_ptr (@Pregmap.set val (preg_of dest) v rs PC) Ptrofs.one) (Val.offset_ptr (rs PC) Ptrofs.one) *)
(* Goal: @ex regset (fun rs' : regset => and (exec_straight ge fn c rs m k rs' m) (and (@eq val (rs' (preg_of dest)) v) (forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs' r) (rs r)))) *)
  apply exec_straight_one. simpl. unfold exec_store. rewrite H1. eauto. auto.
(* Goal: forall (r : preg) (_ : @eq bool (data_preg r) true) (_ : not (@eq preg r (preg_of dest))), @eq val (rs2 r) (rs r) *)
  intros. Simplifs.
Qed.

End CONSTRUCTORS.
