aboutsummaryrefslogtreecommitdiff
path: root/src/Assembly/WordizeUtil.v
diff options
context:
space:
mode:
authorGravatar Robert Sloan <varomodt@gmail.com>2016-08-23 15:31:19 -0700
committerGravatar Robert Sloan <varomodt@gmail.com>2016-08-23 15:31:19 -0700
commit3d722dcf238e0788ae2fb3ac1a81e4fa8b1aa844 (patch)
tree2f7062dcd01df4e333dea2aec337ad535a14350d /src/Assembly/WordizeUtil.v
parent9658c50670ca7907954a08a63ba543eb427ebde5 (diff)
Experimental requirements for rsloan-phoas
Diffstat (limited to 'src/Assembly/WordizeUtil.v')
-rw-r--r--src/Assembly/WordizeUtil.v905
1 files changed, 905 insertions, 0 deletions
diff --git a/src/Assembly/WordizeUtil.v b/src/Assembly/WordizeUtil.v
new file mode 100644
index 000000000..b3358ae54
--- /dev/null
+++ b/src/Assembly/WordizeUtil.v
@@ -0,0 +1,905 @@
+Require Import Bedrock.Word Bedrock.Nomega.
+Require Import NArith PArith Ndigits Nnat NPow NPeano Ndec.
+Require Import List Omega NArith Nnat BoolEq Compare_dec.
+Require Import SetoidTactics.
+Require Import ProofIrrelevance FunctionalExtensionality.
+Require Import QhasmUtil QhasmEvalCommon.
+
+(* Custom replace-at wrapper for 8.4pl3 compatibility *)
+Definition ltac_nat_from_int (x:BinInt.Z) : nat :=
+ match x with
+ | BinInt.Z0 => 0%nat
+ | BinInt.Zpos p => BinPos.nat_of_P p
+ | BinInt.Zneg p => 0%nat
+ end.
+
+Ltac nat_from_number N :=
+ match type of N with
+ | nat => constr:(N)
+ | BinInt.Z => let N' := constr:(ltac_nat_from_int N) in eval compute in N'
+ end.
+
+Tactic Notation "replace'" constr(x) "with" constr(y) "at" constr(n) "by" tactic(tac) :=
+ let tmp := fresh in (
+ match nat_from_number n with
+ | 1 => set (tmp := x) at 1
+ | 2 => set (tmp := x) at 2
+ | 3 => set (tmp := x) at 3
+ | 4 => set (tmp := x) at 4
+ | 5 => set (tmp := x) at 5
+ end;
+ replace tmp with y by (unfold tmp; tac);
+ clear tmp).
+
+(* Word-shattering tactic *)
+Ltac shatter a :=
+ let H := fresh in
+ pose proof (shatter_word a) as H; simpl in H;
+ try rewrite H in *; clear H.
+
+Section Misc.
+ Local Open Scope nword_scope.
+
+ Lemma word_replace: forall n m, n = m -> word n = word m.
+ Proof. intros; subst; intuition. Qed.
+
+ Lemma of_nat_lt: forall x b, (x < b)%nat <-> (N.of_nat x < N.of_nat b)%N.
+ Proof.
+ intros x b; split; intro H.
+
+ - unfold N.lt; rewrite N2Nat.inj_compare.
+ repeat rewrite Nat2N.id.
+ apply nat_compare_lt in H.
+ intuition.
+
+ - unfold N.lt in H; rewrite N2Nat.inj_compare in H.
+ repeat rewrite Nat2N.id in H.
+ apply nat_compare_lt in H.
+ intuition.
+ Qed.
+
+ Lemma to_nat_lt: forall x b, (x < b)%N <-> (N.to_nat x < N.to_nat b)%nat.
+ Proof.
+ intros x b; split; intro H.
+
+ - unfold N.lt in H; rewrite N2Nat.inj_compare in H.
+ apply nat_compare_lt in H.
+ intuition.
+
+ - unfold N.lt; rewrite N2Nat.inj_compare.
+ apply nat_compare_lt.
+ intuition.
+ Qed.
+
+ Lemma word_size_bound : forall {n} (w: word n), (&w < Npow2 n)%N.
+ Proof.
+ intros; pose proof (wordToNat_bound w) as B;
+ rewrite of_nat_lt in B;
+ rewrite <- Npow2_nat in B;
+ rewrite N2Nat.id in B;
+ rewrite <- wordToN_nat in B;
+ assumption.
+ Qed.
+
+ Lemma ge_to_le: forall (x y: N), (x >= y)%N <-> (y <= x)%N.
+ Proof.
+ intros x y; split; intro H;
+ unfold N.ge, N.le in *;
+ intro H0; contradict H;
+ rewrite N.compare_antisym;
+ rewrite H0; simpl; intuition.
+ Qed.
+
+ Lemma N_ge_0: forall x: N, (0 <= x)%N.
+ Proof.
+ intro x0; unfold N.le.
+ pose proof (N.compare_0_r x0) as H.
+ rewrite N.compare_antisym in H.
+ induction x0; simpl in *;
+ intro V; inversion V.
+ Qed.
+
+ Lemma Pos_ge_1: forall p, (1 <= N.pos p)%N.
+ Proof.
+ intro.
+ replace (N.pos p) with (N.succ (N.pos p - 1)%N) by (
+ induction p; simpl;
+ try rewrite Pos.succ_pred_double;
+ try reflexivity).
+ unfold N.succ.
+ apply N.le_pred_le_succ.
+ replace (N.pred 1%N) with 0%N by (simpl; intuition).
+ apply N_ge_0.
+ Qed.
+
+ Lemma testbit_wones_false: forall n k,
+ (k >= N.of_nat n)%N
+ -> false = N.testbit (& wones n) k.
+ Proof.
+ induction n; try abstract (simpl; intuition).
+ induction k; try abstract (
+ intro H; destruct H; simpl; intuition).
+
+ intro H.
+ assert (N.pos p - 1 >= N.of_nat n)%N as Z.
+ apply ge_to_le;
+ apply ge_to_le in H;
+ apply (N.add_le_mono_r _ _ 1%N);
+ replace (N.of_nat n + 1)%N with (N.of_nat (S n));
+ replace (N.pos p - 1 + 1)%N with (N.pos p);
+ try rewrite N.sub_add;
+ try assumption;
+ try nomega;
+ apply Pos_ge_1.
+
+ rewrite (IHn (N.pos p - 1)%N Z) at 1.
+
+ assert (N.pos p = N.succ (N.pos p - 1)) as Hp by (
+ rewrite <- N.pred_sub;
+ rewrite N.succ_pred;
+ try abstract intuition;
+ intro H0; inversion H0).
+
+ symmetry.
+ rewrite Hp at 1.
+ rewrite Hp in H.
+
+ revert H; clear IHn Hp Z;
+ generalize (N.pos p - 1)%N as x;
+ intros x H.
+
+ replace (& wones (S n)) with (2 * & (wones n) + N.b2n true)%N
+ by (simpl; nomega).
+
+ rewrite N.testbit_succ_r; reflexivity.
+ Qed.
+
+ Lemma testbit_wones_true: forall n k,
+ (k < N.of_nat n)%N
+ -> true = N.testbit (& wones n) k.
+ Proof.
+ induction n; intros k H; try nomega.
+ destruct (N.eq_dec k (N.of_nat n)).
+
+ - clear IHn H; subst.
+ induction n.
+
+ + simpl; intuition.
+
+ + replace (& (wones (S (S n))))
+ with (2 * (& (wones (S n))) + N.b2n true)%N
+ by (simpl; nomega).
+ rewrite Nat2N.inj_succ.
+ rewrite N.testbit_succ_r.
+ assumption.
+
+ - induction k.
+
+ + replace (& (wones (S n))) with (2 * (& (wones n)) + N.b2n true)%N
+ by (simpl; nomega).
+ rewrite N.testbit_0_r.
+ reflexivity.
+
+ + assert (N.pos p < N.of_nat n)%N as IH by (
+ rewrite Nat2N.inj_succ in H;
+ nomega).
+ apply N.lt_lt_pred in IH.
+ apply IHn in IH.
+ replace (N.pos p) with (N.succ (N.pred (N.pos p))) by (
+ induction p; simpl;
+ try rewrite Pos.succ_pred_double;
+ intuition).
+ replace (& (wones (S n))) with (2 * (& (wones n)) + N.b2n true)%N
+ by (simpl; nomega).
+ rewrite N.testbit_succ_r.
+ assumption.
+ Qed.
+
+
+ Lemma plus_le: forall {n} (x y: word n),
+ (& (x ^+ y) <= &x + &y)%N.
+ Proof.
+ intros.
+ unfold wplus, wordBin.
+ rewrite wordToN_nat.
+ rewrite NToWord_nat.
+ pose proof (wordToNat_natToWord n (N.to_nat (& x + & y))) as H.
+ destruct H as [k H].
+ destruct H as [Heq Hk].
+ rewrite Heq.
+ rewrite Nat2N.inj_sub.
+ rewrite N2Nat.id.
+ generalize (&x + &y)%N; intro a.
+ generalize (N.of_nat (k * pow2 n))%N; intro b.
+ clear Heq Hk; clear x y k; clear n.
+ replace a with (a - 0)%N by nomega.
+ replace' (a - 0)%N with a at 1 by nomega.
+ apply N.sub_le_mono_l.
+ apply N_ge_0.
+ Qed.
+
+ Lemma mult_le: forall {n} (x y: word n),
+ (& (x ^* y) <= &x * &y)%N.
+ Proof.
+ intros.
+ unfold wmult, wordBin.
+ rewrite wordToN_nat.
+ rewrite NToWord_nat.
+ pose proof (wordToNat_natToWord n (N.to_nat (& x * & y))) as H.
+ destruct H as [k H].
+ destruct H as [Heq Hk].
+ rewrite Heq.
+ rewrite Nat2N.inj_sub.
+ rewrite N2Nat.id.
+ generalize (&x * &y)%N; intro a.
+ generalize (N.of_nat (k * pow2 n))%N; intro b.
+ clear Heq Hk; clear x y k; clear n.
+ replace a with (a - 0)%N by nomega.
+ replace' (a - 0)%N with a at 1 by nomega.
+ apply N.sub_le_mono_l.
+ apply N_ge_0.
+ Qed.
+End Misc.
+
+Section Exp.
+ Local Open Scope nword_scope.
+
+ Lemma pow2_inv : forall n m, pow2 n = pow2 m -> n = m.
+ Proof.
+ induction n; intros; simpl in *;
+ induction m; simpl in *; try omega.
+ f_equal; apply IHn.
+ omega.
+ Qed.
+
+ Lemma pow2_gt0 : forall n, (pow2 n > O)%nat.
+ Proof. induction n; simpl; omega. Qed.
+
+ Lemma pow2_N_bound: forall n j,
+ (j < pow2 n)%nat -> (N.of_nat j < Npow2 n)%N.
+ Proof.
+ intros.
+ rewrite <- Npow2_nat in H.
+ unfold N.lt.
+ rewrite N2Nat.inj_compare.
+ rewrite Nat2N.id.
+ apply nat_compare_lt in H.
+ assumption.
+ Qed.
+
+ Lemma Npow2_gt0 : forall x, (0 < Npow2 x)%N.
+ Proof.
+ intros; induction x.
+
+ - simpl; apply N.lt_1_r; intuition.
+
+ - replace (Npow2 (S x)) with (2 * (Npow2 x))%N by intuition.
+ apply (N.lt_0_mul 2 (Npow2 x)); left; split; apply N.neq_0_lt_0.
+
+ + intuition; inversion H.
+
+ + apply N.neq_0_lt_0 in IHx; intuition.
+ Qed.
+
+ Lemma Npow2_ge1 : forall x, (1 <= Npow2 x)%N.
+ Proof.
+ intro x.
+ pose proof (Npow2_gt0 x) as Z.
+ apply N.lt_pred_le; simpl.
+ assumption.
+ Qed.
+
+ Lemma Npow2_split: forall a b,
+ (Npow2 (a + b) = (Npow2 a) * (Npow2 b))%N.
+ Proof.
+ intros; revert a.
+ induction b.
+
+ - intros; simpl; replace (a + 0) with a; try nomega.
+ rewrite N.mul_1_r; intuition.
+
+ - intros.
+ replace (a + S b) with (S a + b) by omega.
+ rewrite (IHb (S a)); simpl; clear IHb.
+ induction (Npow2 a), (Npow2 b); simpl; intuition.
+ rewrite Pos.mul_xO_r; intuition.
+ Qed.
+
+ Lemma Npow2_N: forall n, Npow2 n = (2 ^ N.of_nat n)%N.
+ Proof.
+ induction n.
+
+ - simpl; intuition.
+
+ - rewrite Nat2N.inj_succ.
+ rewrite N.pow_succ_r; try apply N_ge_0.
+ rewrite <- IHn.
+ simpl; intuition.
+ Qed.
+
+ Lemma Npow2_succ: forall n, (Npow2 (S n) = 2 * (Npow2 n))%N.
+ Proof. intros; simpl; induction (Npow2 n); intuition. Qed.
+
+ Lemma Npow2_ordered: forall n m, (n <= m)%nat -> (Npow2 n <= Npow2 m)%N.
+ Proof.
+ induction n; intros m H; try rewrite Npow2_succ.
+
+ - simpl; apply Npow2_ge1.
+
+ - induction m; try rewrite Npow2_succ.
+
+ + inversion H.
+
+ + assert (n <= m)%nat as H0 by omega.
+ apply IHn in H0.
+ apply N.mul_le_mono_l.
+ assumption.
+ Qed.
+
+End Exp.
+
+Section Conversions.
+ Local Open Scope nword_scope.
+
+ Lemma NToWord_wordToN: forall sz x, NToWord sz (wordToN x) = x.
+ Proof.
+ intros.
+ rewrite NToWord_nat.
+ rewrite wordToN_nat.
+ rewrite Nat2N.id.
+ rewrite natToWord_wordToNat.
+ intuition.
+ Qed.
+
+ Lemma NToWord_equal: forall n (x y: word n),
+ wordToN x = wordToN y -> x = y.
+ Proof.
+ intros.
+ rewrite <- (NToWord_wordToN _ x).
+ rewrite <- (NToWord_wordToN _ y).
+ rewrite H; reflexivity.
+ Qed.
+
+ Lemma wordToN_NToWord: forall sz x, (x < Npow2 sz)%N -> wordToN (NToWord sz x) = x.
+ Proof.
+ intros.
+ rewrite NToWord_nat.
+ rewrite wordToN_nat.
+ rewrite <- (N2Nat.id x).
+ apply Nat2N.inj_iff.
+ rewrite Nat2N.id.
+ apply natToWord_inj with (sz:=sz);
+ try rewrite natToWord_wordToNat;
+ intuition.
+
+ - apply wordToNat_bound.
+ - rewrite <- Npow2_nat; apply to_nat_lt; assumption.
+ Qed.
+
+ Lemma Npow2_ignore: forall {n} (x: word n),
+ x = NToWord _ (& x + Npow2 n).
+ Proof.
+ intros.
+ rewrite <- (NToWord_wordToN n x) at 1.
+ repeat rewrite NToWord_nat.
+ rewrite N2Nat.inj_add.
+ rewrite Npow2_nat.
+ replace' (N.to_nat (&x))
+ with ((N.to_nat (&x) + pow2 n) - 1 * pow2 n)
+ at 1 by omega.
+ rewrite drop_sub; [intuition|omega].
+ Qed.
+End Conversions.
+
+Section SpecialFunctions.
+ Local Open Scope nword_scope.
+
+ Lemma convS_id: forall n x p, (@convS n n x p) = x.
+ Proof.
+ intros; unfold convS; vm_compute.
+ replace (convS_subproof n n x p)
+ with (eq_refl (word n)) by (apply proof_irrelevance).
+ reflexivity.
+ Qed.
+
+ Lemma wordToN_convS: forall {n m} x p,
+ wordToN (@convS n m x p) = wordToN x.
+ Proof.
+ intros.
+ revert x.
+ rewrite p.
+ intro x.
+ rewrite convS_id.
+ reflexivity.
+ Qed.
+
+ Lemma wordToN_zext: forall {n m} (x: word n),
+ wordToN (@zext n x m) = wordToN x.
+ Proof.
+ intros; induction x; simpl; intuition.
+
+ - unfold zext, Word.combine.
+ rewrite wordToN_nat.
+ unfold wzero.
+ rewrite (@wordToNat_natToWord_idempotent m 0); simpl; intuition.
+ apply Npow2_gt0.
+
+ - unfold zext in IHx; rewrite IHx; clear IHx;
+ destruct b; intuition.
+ Qed.
+
+ Lemma wordToN_div2: forall {n} (x: word (S n)),
+ N.div2 (&x) = & (wtl x).
+ Proof.
+ intros.
+ pose proof (shatter_word x) as Hx; simpl in Hx; rewrite Hx; simpl.
+ destruct (whd x).
+ replace (match & wtl x with
+ | 0%N => 0%N
+ | N.pos q => N.pos (xO q)
+ end)
+ with (N.double (& (wtl x)))
+ by (induction (& (wtl x)); simpl; intuition).
+
+ - rewrite N.double_spec.
+ replace (N.succ (2 * & wtl x))
+ with ((2 * (& wtl x)) + 1)%N
+ by nomega.
+ rewrite <- N.succ_double_spec.
+ rewrite N.div2_succ_double.
+ reflexivity.
+
+ - induction (& (wtl x)); simpl; intuition.
+ Qed.
+
+ Fixpoint wbit {n} (x: word n) (k: nat): bool :=
+ match n as n' return word n' -> bool with
+ | O => fun _ => false
+ | S m => fun x' =>
+ match k with
+ | O => (whd x')
+ | S k' => wbit (wtl x') k'
+ end
+ end x.
+
+ Lemma wbit_wtl: forall {n} (x: word (S n)) k,
+ wbit x (S k) = wbit (wtl x) k.
+ Proof.
+ intros.
+ pose proof (shatter_word x) as Hx;
+ simpl in Hx; rewrite Hx; simpl.
+ reflexivity.
+ Qed.
+
+ Lemma wordToN_testbit: forall {n} (x: word n) k,
+ N.testbit (& x) k = wbit x (N.to_nat k).
+ Proof.
+ assert (forall x: N, match x with
+ | 0%N => 0%N
+ | N.pos q => N.pos (q~0)%positive
+ end = N.double x) as kill_match by (
+ induction x; simpl; intuition).
+
+ induction n; intros.
+
+ - shatter x; simpl; intuition.
+
+ - revert IHn; rewrite <- (N2Nat.id k).
+ generalize (N.to_nat k) as k'; intros; clear k.
+ rewrite Nat2N.id in *.
+
+ induction k'.
+
+ + clear IHn; induction x; simpl; intuition.
+ destruct (& x), b; simpl; intuition.
+
+ + clear IHk'.
+ shatter x; simpl.
+
+ rewrite kill_match.
+ replace (N.pos (Pos.of_succ_nat k'))
+ with (N.succ (N.of_nat k'))
+ by (rewrite <- Nat2N.inj_succ;
+ simpl; intuition).
+
+ rewrite N.double_spec.
+ replace (N.succ (2 * & wtl x))
+ with (2 * & wtl x + 1)%N
+ by nomega.
+
+ destruct (whd x);
+ try rewrite N.testbit_odd_succ;
+ try rewrite N.testbit_even_succ;
+ try abstract (
+ unfold N.le; simpl;
+ induction (N.of_nat k'); intuition;
+ try inversion H);
+ rewrite IHn;
+ rewrite Nat2N.id;
+ reflexivity.
+ Qed.
+
+ Lemma wordToN_split1: forall {n m} x,
+ & (@split1 n m x) = N.land (& x) (& (wones n)).
+ Proof.
+ intros.
+
+ pose proof (Word.combine_split _ _ x) as C; revert C.
+ generalize (split1 n m x) as a, (split2 n m x) as b.
+ intros a b C; rewrite <- C; clear C x.
+
+ apply N.bits_inj_iff; unfold N.eqf; intro x.
+ rewrite N.land_spec.
+ repeat rewrite wordToN_testbit.
+ revert x a b.
+
+ induction n, m; intros;
+ shatter a; shatter b;
+ induction (N.to_nat x) as [|n0];
+ try rewrite <- (Nat2N.id n0);
+ try rewrite andb_false_r;
+ try rewrite andb_true_r;
+ simpl; intuition.
+ Qed.
+
+ Lemma wordToN_split2: forall {n m} x,
+ & (@split2 n m x) = N.shiftr (& x) (N.of_nat n).
+ Proof.
+ intros.
+
+ pose proof (Word.combine_split _ _ x) as C; revert C.
+ generalize (split1 n m x) as a, (split2 n m x) as b.
+ intros a b C.
+ rewrite <- C; clear C x.
+
+ apply N.bits_inj_iff; unfold N.eqf; intro x;
+ rewrite N.shiftr_spec;
+ repeat rewrite wordToN_testbit;
+ try apply N_ge_0.
+
+ revert x a b.
+ induction n, m; intros;
+ shatter a;
+ try apply N_ge_0.
+
+ - simpl; intuition.
+
+ - replace (x + N.of_nat 0)%N with x by nomega.
+ simpl; intuition.
+
+ - rewrite (IHn x (wtl a) b).
+ rewrite <- (N2Nat.id x).
+ repeat rewrite <- Nat2N.inj_add.
+ repeat rewrite Nat2N.id; simpl.
+ replace (N.to_nat x + S n) with (S (N.to_nat x + n)) by omega.
+ reflexivity.
+
+ - rewrite (IHn x (wtl a) b).
+ rewrite <- (N2Nat.id x).
+ repeat rewrite <- Nat2N.inj_add.
+ repeat rewrite Nat2N.id; simpl.
+ replace (N.to_nat x + S n) with (S (N.to_nat x + n)) by omega.
+ reflexivity.
+ Qed.
+
+ Lemma wordToN_combine: forall {n m} a b,
+ & (@Word.combine n a m b) = N.lxor (N.shiftl (& b) (N.of_nat n)) (& a).
+ Proof.
+ intros; symmetry.
+
+ replace' a with (Word.split1 _ _ (Word.combine a b)) at 1
+ by (apply Word.split1_combine).
+
+ replace' b with (Word.split2 _ _ (Word.combine a b)) at 1
+ by (apply Word.split2_combine).
+
+ generalize (Word.combine a b); intro x; clear a b.
+
+ rewrite wordToN_split1, wordToN_split2.
+ generalize (&x); clear x; intro x.
+ apply N.bits_inj_iff; unfold N.eqf; intro k.
+
+ rewrite N.lxor_spec.
+ destruct (Nge_dec k (N.of_nat n)).
+
+ - rewrite N.shiftl_spec_high; try apply N_ge_0;
+ try (apply ge_to_le; assumption).
+ rewrite N.shiftr_spec; try apply N_ge_0.
+ replace (k - N.of_nat n + N.of_nat n)%N with k by nomega.
+ rewrite N.land_spec.
+ induction (N.testbit x k);
+ replace (N.testbit (& wones n) k) with false;
+ simpl; intuition;
+ try apply testbit_wones_false;
+ try assumption.
+
+ - rewrite N.shiftl_spec_low; try assumption; try apply N_ge_0.
+ rewrite N.land_spec.
+ induction (N.testbit x k);
+ replace (N.testbit (& wones n) k) with true;
+ simpl; intuition;
+ try apply testbit_wones_true;
+ try assumption.
+ Qed.
+
+ Lemma wordToN_wones: forall x, & (wones x) = N.ones (N.of_nat x).
+ Proof.
+ induction x.
+
+ - simpl; intuition.
+
+ - rewrite Nat2N.inj_succ.
+ replace (& wones (S x)) with (2 * & (wones x) + N.b2n true)%N
+ by (simpl; nomega).
+ replace (N.ones (N.succ _))
+ with (2 * N.ones (N.of_nat x) + N.b2n true)%N.
+
+ + rewrite IHx; nomega.
+
+ + replace (N.succ (N.of_nat x)) with (1 + (N.of_nat x))%N by (
+ rewrite N.add_comm; nomega).
+ rewrite N.ones_add.
+ replace (N.ones 1) with 1%N by (
+ unfold N.ones; simpl; intuition).
+ simpl.
+ reflexivity.
+ Qed.
+
+ Lemma wordToN_zero: forall w, wordToN (wzero w) = 0%N.
+ Proof.
+ intros.
+ unfold wzero; rewrite wordToN_nat.
+ rewrite wordToNat_natToWord_idempotent; simpl; intuition.
+ apply Npow2_gt0.
+ Qed.
+
+ Lemma NToWord_zero: forall w, NToWord w 0%N = wzero w.
+ Proof.
+ intros.
+ unfold wzero; rewrite NToWord_nat.
+ f_equal.
+ Qed.
+
+ Ltac propagate_wordToN :=
+ unfold extend, low, high, break;
+ repeat match goal with
+ | [|- context[@wordToN _ (@convS _ _ _ _)] ] =>
+ rewrite wordToN_convS
+ | [|- context[@wordToN _ (@split1 _ _ _)] ] =>
+ rewrite wordToN_split1
+ | [|- context[@wordToN _ (@split2 _ _ _)] ] =>
+ rewrite wordToN_split2
+ | [|- context[@wordToN _ (@combine _ _ _ _)] ] =>
+ rewrite wordToN_combine
+ | [|- context[@wordToN _ (@zext _ _ _)] ] =>
+ rewrite wordToN_zext
+ | [|- context[@wordToN _ (@wones _)] ] =>
+ rewrite wordToN_wones
+ end.
+
+ Lemma break_spec: forall (m n: nat) (x: word n) low high,
+ (low, high) = break m x
+ -> &x = (&high * Npow2 m + &low)%N.
+ Proof.
+ intros m n x low high H.
+ unfold break in H.
+ destruct (le_dec m n).
+
+ - inversion H; subst; clear H.
+ propagate_wordToN.
+ rewrite N.land_ones.
+ rewrite N.shiftr_div_pow2.
+ replace (n - (n - m)) with m by omega.
+ rewrite N.mul_comm.
+ rewrite Npow2_N.
+ rewrite <- (N.div_mod' (& x) (2 ^ (N.of_nat m))%N).
+ reflexivity.
+
+ - inversion H; subst; clear H.
+ propagate_wordToN; simpl; nomega.
+ Qed.
+
+ Lemma extend_bound: forall k n (p: (k <= n)%nat) (w: word k),
+ (& (extend p w) < Npow2 k)%N.
+ Proof.
+ intros.
+ propagate_wordToN.
+ apply word_size_bound.
+ Qed.
+
+ Lemma mask_spec : forall (n: nat) (x: word n) m,
+ & (mask (N.to_nat m) x) = (N.land (& x) (N.ones m)).
+ Proof.
+ intros; unfold mask.
+ destruct (le_dec (N.to_nat m) n).
+
+ - propagate_wordToN.
+ rewrite N2Nat.id.
+ reflexivity.
+
+ - rewrite N.land_ones.
+ rewrite N.mod_small; try reflexivity.
+ rewrite <- (N2Nat.id m).
+ rewrite <- Npow2_N.
+ apply (N.lt_le_trans _ (Npow2 n) _); try apply word_size_bound.
+ apply Npow2_ordered.
+ omega.
+ Qed.
+
+ Lemma mask_bound : forall (n: nat) (x: word n) m,
+ (& (mask m x) < Npow2 m)%N.
+ Proof.
+ intros; unfold mask.
+ destruct (le_dec m n).
+
+ - apply extend_bound.
+
+ - apply (N.lt_le_trans _ (Npow2 n) _); try apply word_size_bound.
+ apply Npow2_ordered.
+ omega.
+ Qed.
+
+End SpecialFunctions.
+
+Section TopLevel.
+ Local Open Scope nword_scope.
+
+ Coercion ind : bool >-> N.
+
+ Lemma wordize_plus: forall {n} (x y: word n),
+ (&x + &y < Npow2 n)%N
+ -> (&x + &y)%N = & (x ^+ y).
+ Proof.
+ intros n x y H.
+ pose proof (word_size_bound x) as Hbx.
+ pose proof (word_size_bound y) as Hby.
+
+ unfold wplus, wordBin.
+ rewrite wordToN_NToWord; intuition.
+ Qed.
+
+ Lemma wordize_awc: forall {n} (x y: word n) (c: bool),
+ (&x + &y + c < Npow2 n)%N
+ -> (&x + &y + c)%N = &(addWithCarry x y c).
+ Proof.
+ intros n x y c H.
+ unfold wplus, wordBin, addWithCarry.
+ destruct c; simpl in *.
+
+ - replace 1%N with (wordToN (natToWord n 1)) in * by (
+ rewrite wordToN_nat;
+ rewrite wordToNat_natToWord_idempotent;
+ nomega).
+
+ rewrite <- N.add_assoc.
+ rewrite wordize_plus; try nomega.
+ rewrite wordize_plus; try nomega.
+
+ + rewrite wplus_assoc.
+ reflexivity.
+
+ + apply (N.le_lt_trans _ (& x + & y + & natToWord n 1)%N _);
+ try assumption.
+ rewrite <- N.add_assoc.
+ apply N.add_le_mono.
+
+ * apply N.eq_le_incl; reflexivity.
+
+ * apply plus_le.
+
+ - rewrite wplus_comm.
+ rewrite wplus_unit.
+ rewrite N.add_0_r in *.
+ apply wordize_plus; assumption.
+ Qed.
+
+ Lemma wordize_mult: forall {n} (x y: word n),
+ (&x * &y < Npow2 n)%N
+ -> (&x * &y)%N = &(x ^* y).
+ Proof.
+ intros n x y H.
+ pose proof (word_size_bound x) as Hbx.
+ pose proof (word_size_bound y) as Hby.
+
+ unfold wmult, wordBin.
+ rewrite wordToN_NToWord; intuition.
+ Qed.
+
+ Lemma wordize_shiftr: forall {n} (x: word n) (k: nat),
+ (N.shiftr_nat (&x) k) = & (shiftr x k).
+ Proof.
+ intros n x k.
+ unfold shiftr, extend, high.
+ destruct (le_dec k n).
+
+ - repeat first [
+ rewrite wordToN_convS
+ | rewrite wordToN_zext
+ | rewrite wordToN_split2 ].
+ rewrite <- Nshiftr_equiv_nat.
+ reflexivity.
+
+ - rewrite (wordToN_nat (wzero n)); unfold wzero.
+ destruct (Nat.eq_dec n O); subst.
+
+ + rewrite (shatter_word_0 x); simpl; intuition.
+ rewrite <- Nshiftr_equiv_nat.
+ rewrite N.shiftr_0_l.
+ reflexivity.
+
+ + rewrite wordToNat_natToWord_idempotent;
+ try nomega.
+
+ * pose proof (word_size_bound x).
+ rewrite <- Nshiftr_equiv_nat.
+ rewrite N.shiftr_eq_0_iff.
+ destruct (N.eq_dec (&x) 0%N) as [E|E];
+ try rewrite E in *;
+ try abstract (left; reflexivity).
+
+ right; split; try nomega.
+ apply (N.le_lt_trans _ (N.log2 (Npow2 n)) _). {
+ apply N.log2_le_mono.
+ apply N.lt_le_incl.
+ assumption.
+ }
+
+ rewrite Npow2_N.
+ rewrite N.log2_pow2; try nomega.
+ apply N_ge_0.
+
+ * simpl; apply Npow2_gt0.
+ Qed.
+
+ Lemma conv_mask: forall {n} (x: word n) (k: nat),
+ (k <= n)%nat ->
+ mask k x = x ^& (NToWord _ (N.ones (N.of_nat k))).
+ Proof.
+ intros n x k H.
+ apply NToWord_equal.
+
+ rewrite <- (Nat2N.id k).
+ rewrite mask_spec.
+ apply N.bits_inj_iff; unfold N.eqf; intro m.
+ rewrite N.land_spec.
+ repeat rewrite wordToN_testbit.
+ rewrite <- (N2Nat.id m).
+ rewrite <- wordToN_wones.
+ repeat rewrite wordToN_testbit.
+ repeat rewrite N2Nat.id.
+ rewrite <- wordToN_wones.
+
+ assert (forall n (a b: word n) k,
+ wbit (a ^& b) k = andb (wbit a k) (wbit b k)) as Hwand. {
+ intros n0 a b.
+ induction n0 as [|n1];
+ shatter a; shatter b;
+ simpl; try reflexivity.
+
+ intro k0; induction k0 as [|k0];
+ simpl; try reflexivity.
+
+ fold wand.
+ rewrite IHn1.
+ reflexivity.
+ }
+
+ rewrite Hwand; clear Hwand.
+ induction (wbit x (N.to_nat m));
+ repeat rewrite andb_false_l;
+ repeat rewrite andb_true_l;
+ try reflexivity.
+
+ repeat rewrite <- wordToN_testbit.
+ rewrite wordToN_NToWord; try reflexivity.
+ apply (N.lt_le_trans _ (Npow2 k) _).
+
+ + apply word_size_bound.
+
+ + apply Npow2_ordered.
+ omega.
+ Qed.
+
+ Close Scope nword_scope.
+End TopLevel.
+