Corollary xor_zero_l: forall x, xor zero x = x.

(* Specifications: *)
Theorem xor_idem: forall x, xor x x = zero.
Theorem xor_zero_one: xor zero one = one.
Theorem xor_one_one: xor one one = zero.
Theorem xor_zero_equal: forall x y, xor x y = zero -> x = y.
Theorem xor_is_zero: forall x y, eq (xor x y) zero = eq x y.
Theorem and_xor_distrib: forall x y z, and x (xor y z) = xor (and x y) (and x z).
Theorem and_le: forall x y, unsigned (and x y) <= unsigned x.
Theorem or_le: forall x y, unsigned x <= unsigned (or x y).
Theorem not_involutive: forall (x: int), not (not x) = x.
Theorem not_zero: not zero = mone.
Theorem not_mone: not mone = zero.
Theorem not_or_and_not: forall x y, not (or x y) = and (not x) (not y).
Theorem not_and_or_not: forall x y, not (and x y) = or (not x) (not y).
Theorem and_not_self: forall x, and x (not x) = zero.
Theorem or_not_self: forall x, or x (not x) = mone.
Theorem xor_not_self: forall x, xor x (not x) = mone.
Lemma unsigned_not: forall x, unsigned (not x) = max_unsigned - unsigned x.
Theorem not_neg: forall x, not x = add (neg x) mone.
Theorem neg_not: forall x, neg x = add (not x) one.
Theorem sub_add_not: forall x y, sub x y = add (add x (not y)) one.
Theorem sub_add_not_3: forall x y b, b = zero \/ b = one -> sub (sub x y) b = add (add x (not y)) (xor b one).
Theorem sub_borrow_add_carry: forall x y b, b = zero \/ b = one -> sub_borrow x y b = xor (add_carry x (not y) (xor b one)) one.
Lemma Z_add_is_or: forall i, 0 <= i -> forall x y, (forall j, 0 <= j <= i -> Z.testbit x j && Z.testbit y j = false) -> Z.testbit (x + y) i = Z.testbit x i || Z.testbit y i.
Theorem add_is_or: forall x y, and x y = zero -> add x y = or x y.
Theorem xor_is_or: forall x y, and x y = zero -> xor x y = or x y.
Theorem add_is_xor: forall x y, and x y = zero -> add x y = xor x y.
Theorem add_and: forall x y z, and y z = zero -> add (and x y) (and x z) = and x (or y z).
Lemma bits_shl: forall x y i, 0 <= i < zwordsize -> testbit (shl x y) i = if zlt i (unsigned y) then false else testbit x (i - unsigned y).
Lemma bits_shru: forall x y i, 0 <= i < zwordsize -> testbit (shru x y) i = if zlt (i + unsigned y) zwordsize then testbit x (i + unsigned y) else false.
Lemma bits_shr: forall x y i, 0 <= i < zwordsize -> testbit (shr x y) i = testbit x (if zlt (i + unsigned y) zwordsize then i + unsigned y else zwordsize - 1).
Theorem shl_zero: forall x, shl x zero = x.
Lemma bitwise_binop_shl: forall f f' x y n, (forall x y i, 0 <= i < zwordsize -> testbit (f x y) i = f' (testbit x i) (testbit y i)) -> f' false false = false -> f (shl x n) (shl y n) = shl (f x y) n.
Theorem and_shl: forall x y n, and (shl x n) (shl y n) = shl (and x y) n.
Theorem or_shl: forall x y n, or (shl x n) (shl y n) = shl (or x y) n.
Theorem xor_shl: forall x y n, xor (shl x n) (shl y n) = shl (xor x y) n.
Lemma ltu_inv: forall x y, ltu x y = true -> 0 <= unsigned x < unsigned y.
Lemma ltu_iwordsize_inv: forall x, ltu x iwordsize = true -> 0 <= unsigned x < zwordsize.
Theorem shl_shl: forall x y z, ltu y iwordsize = true -> ltu z iwordsize = true -> ltu (add y z) iwordsize = true -> shl (shl x y) z = shl x (add y z).
Theorem sub_ltu: forall x y, ltu x y = true -> 0 <= unsigned y - unsigned x <= unsigned y.
Theorem shru_zero: forall x, shru x zero = x.
Lemma bitwise_binop_shru: forall f f' x y n, (forall x y i, 0 <= i < zwordsize -> testbit (f x y) i = f' (testbit x i) (testbit y i)) -> f' false false = false -> f (shru x n) (shru y n) = shru (f x y) n.
Theorem and_shru: forall x y n, and (shru x n) (shru y n) = shru (and x y) n.
Theorem or_shru: forall x y n, or (shru x n) (shru y n) = shru (or x y) n.
Theorem xor_shru: forall x y n, xor (shru x n) (shru y n) = shru (xor x y) n.
Theorem shru_shru: forall x y z, ltu y iwordsize = true -> ltu z iwordsize = true -> ltu (add y z) iwordsize = true -> shru (shru x y) z = shru x (add y z).
Theorem shr_zero: forall x, shr x zero = x.
Lemma bitwise_binop_shr: forall f f' x y n, (forall x y i, 0 <= i < zwordsize -> testbit (f x y) i = f' (testbit x i) (testbit y i)) -> f (shr x n) (shr y n) = shr (f x y) n.
Theorem and_shr: forall x y n, and (shr x n) (shr y n) = shr (and x y) n.
Theorem or_shr: forall x y n, or (shr x n) (shr y n) = shr (or x y) n.
Theorem xor_shr: forall x y n, xor (shr x n) (shr y n) = shr (xor x y) n.
Theorem shr_shr: forall x y z, ltu y iwordsize = true -> ltu z iwordsize = true -> ltu (add y z) iwordsize = true -> shr (shr x y) z = shr x (add y z).
Theorem and_shr_shru: forall x y z, and (shr x z) (shru y z) = shru (and x y) z.
Theorem shr_and_shru_and: forall x y z, shru (shl z y) y = z -> and (shr x y) z = and (shru x y) z.
Theorem shru_lt_zero: forall x, shru x (repr (zwordsize - 1)) = if lt x zero then one else zero.
Theorem shr_lt_zero: forall x, shr x (repr (zwordsize - 1)) = if lt x zero then mone else zero.
Lemma bits_rol: forall x y i, 0 <= i < zwordsize -> testbit (rol x y) i = testbit x ((i - unsigned y) mod zwordsize).
Lemma bits_ror: forall x y i, 0 <= i < zwordsize -> testbit (ror x y) i = testbit x ((i + unsigned y) mod zwordsize).
Theorem shl_rolm: forall x n, ltu n iwordsize = true -> shl x n = rolm x n (shl mone n).
Theorem shru_rolm: forall x n, ltu n iwordsize = true -> shru x n = rolm x (sub iwordsize n) (shru mone n).
Theorem rol_zero: forall x, rol x zero = x.
Lemma bitwise_binop_rol: forall f f' x y n, (forall x y i, 0 <= i < zwordsize -> testbit (f x y) i = f' (testbit x i) (testbit y i)) -> rol (f x y) n = f (rol x n) (rol y n).
Theorem rol_and: forall x y n, rol (and x y) n = and (rol x n) (rol y n).
Theorem rol_or: forall x y n, rol (or x y) n = or (rol x n) (rol y n).
Theorem rol_xor: forall x y n, rol (xor x y) n = xor (rol x n) (rol y n).
Theorem rol_rol: forall x n m, Z.divide zwordsize modulus -> rol (rol x n) m = rol x (modu (add n m) iwordsize).
Theorem rolm_zero: forall x m, rolm x zero m = and x m.
Theorem rolm_rolm: forall x n1 m1 n2 m2, Z.divide zwordsize modulus -> rolm (rolm x n1 m1) n2 m2 = rolm x (modu (add n1 n2) iwordsize) (and (rol m1 n2) m2).
Theorem or_rolm: forall x n m1 m2, or (rolm x n m1) (rolm x n m2) = rolm x n (or m1 m2).
Theorem ror_rol: forall x y, ltu y iwordsize = true -> ror x y = rol x (sub iwordsize y).
Theorem or_ror: forall x y z, ltu y iwordsize = true -> ltu z iwordsize = true -> add y z = iwordsize -> ror x z = or (shl x y) (shru x z).
Theorem xor_idem: forall x, xor x x = zero.
Theorem xor_zero_one: xor zero one = one.
Theorem xor_one_one: xor one one = zero.
Theorem xor_zero_equal: forall x y, xor x y = zero -> x = y.
Theorem xor_is_zero: forall x y, eq (xor x y) zero = eq x y.
Theorem and_xor_distrib: forall x y z, and x (xor y z) = xor (and x y) (and x z).
Theorem and_le: forall x y, unsigned (and x y) <= unsigned x.
Theorem or_le: forall x y, unsigned x <= unsigned (or x y).
Theorem not_involutive: forall (x: int), not (not x) = x.
Theorem not_zero: not zero = mone.
Theorem not_mone: not mone = zero.
Theorem not_or_and_not: forall x y, not (or x y) = and (not x) (not y).
Theorem not_and_or_not: forall x y, not (and x y) = or (not x) (not y).
Theorem and_not_self: forall x, and x (not x) = zero.
Theorem or_not_self: forall x, or x (not x) = mone.
Theorem xor_not_self: forall x, xor x (not x) = mone.
Lemma unsigned_not: forall x, unsigned (not x) = max_unsigned - unsigned x.
Theorem not_neg: forall x, not x = add (neg x) mone.
Theorem neg_not: forall x, neg x = add (not x) one.
Theorem sub_add_not: forall x y, sub x y = add (add x (not y)) one.
Theorem sub_add_not_3: forall x y b, b = zero \/ b = one -> sub (sub x y) b = add (add x (not y)) (xor b one).
Theorem sub_borrow_add_carry: forall x y b, b = zero \/ b = one -> sub_borrow x y b = xor (add_carry x (not y) (xor b one)) one.
Lemma Z_add_is_or: forall i, 0 <= i -> forall x y, (forall j, 0 <= j <= i -> Z.testbit x j && Z.testbit y j = false) -> Z.testbit (x + y) i = Z.testbit x i || Z.testbit y i.
Theorem add_is_or: forall x y, and x y = zero -> add x y = or x y.
Theorem xor_is_or: forall x y, and x y = zero -> xor x y = or x y.
Theorem add_is_xor: forall x y, and x y = zero -> add x y = xor x y.
Theorem add_and: forall x y z, and y z = zero -> add (and x y) (and x z) = and x (or y z).
Lemma bits_shl: forall x y i, 0 <= i < zwordsize -> testbit (shl x y) i = if zlt i (unsigned y) then false else testbit x (i - unsigned y).
Lemma bits_shru: forall x y i, 0 <= i < zwordsize -> testbit (shru x y) i = if zlt (i + unsigned y) zwordsize then testbit x (i + unsigned y) else false.
Lemma bits_shr: forall x y i, 0 <= i < zwordsize -> testbit (shr x y) i = testbit x (if zlt (i + unsigned y) zwordsize then i + unsigned y else zwordsize - 1).
Theorem shl_zero: forall x, shl x zero = x.
Lemma bitwise_binop_shl: forall f f' x y n, (forall x y i, 0 <= i < zwordsize -> testbit (f x y) i = f' (testbit x i) (testbit y i)) -> f' false false = false -> f (shl x n) (shl y n) = shl (f x y) n.
Theorem and_shl: forall x y n, and (shl x n) (shl y n) = shl (and x y) n.
Theorem or_shl: forall x y n, or (shl x n) (shl y n) = shl (or x y) n.
Theorem xor_shl: forall x y n, xor (shl x n) (shl y n) = shl (xor x y) n.
Lemma ltu_inv: forall x y, ltu x y = true -> 0 <= unsigned x < unsigned y.
Lemma ltu_iwordsize_inv: forall x, ltu x iwordsize = true -> 0 <= unsigned x < zwordsize.
Theorem shl_shl: forall x y z, ltu y iwordsize = true -> ltu z iwordsize = true -> ltu (add y z) iwordsize = true -> shl (shl x y) z = shl x (add y z).
Theorem sub_ltu: forall x y, ltu x y = true -> 0 <= unsigned y - unsigned x <= unsigned y.
Theorem shru_zero: forall x, shru x zero = x.
Lemma bitwise_binop_shru: forall f f' x y n, (forall x y i, 0 <= i < zwordsize -> testbit (f x y) i = f' (testbit x i) (testbit y i)) -> f' false false = false -> f (shru x n) (shru y n) = shru (f x y) n.
Theorem and_shru: forall x y n, and (shru x n) (shru y n) = shru (and x y) n.
Theorem or_shru: forall x y n, or (shru x n) (shru y n) = shru (or x y) n.
Theorem xor_shru: forall x y n, xor (shru x n) (shru y n) = shru (xor x y) n.
Theorem shru_shru: forall x y z, ltu y iwordsize = true -> ltu z iwordsize = true -> ltu (add y z) iwordsize = true -> shru (shru x y) z = shru x (add y z).
Theorem shr_zero: forall x, shr x zero = x.
Lemma bitwise_binop_shr: forall f f' x y n, (forall x y i, 0 <= i < zwordsize -> testbit (f x y) i = f' (testbit x i) (testbit y i)) -> f (shr x n) (shr y n) = shr (f x y) n.
Theorem and_shr: forall x y n, and (shr x n) (shr y n) = shr (and x y) n.
Theorem or_shr: forall x y n, or (shr x n) (shr y n) = shr (or x y) n.
Theorem xor_shr: forall x y n, xor (shr x n) (shr y n) = shr (xor x y) n.
Theorem shr_shr: forall x y z, ltu y iwordsize = true -> ltu z iwordsize = true -> ltu (add y z) iwordsize = true -> shr (shr x y) z = shr x (add y z).
Theorem and_shr_shru: forall x y z, and (shr x z) (shru y z) = shru (and x y) z.
Theorem shr_and_shru_and: forall x y z, shru (shl z y) y = z -> and (shr x y) z = and (shru x y) z.
Theorem shru_lt_zero: forall x, shru x (repr (zwordsize - 1)) = if lt x zero then one else zero.
Theorem shr_lt_zero: forall x, shr x (repr (zwordsize - 1)) = if lt x zero then mone else zero.
Lemma bits_rol: forall x y i, 0 <= i < zwordsize -> testbit (rol x y) i = testbit x ((i - unsigned y) mod zwordsize).
Lemma bits_ror: forall x y i, 0 <= i < zwordsize -> testbit (ror x y) i = testbit x ((i + unsigned y) mod zwordsize).
Theorem shl_rolm: forall x n, ltu n iwordsize = true -> shl x n = rolm x n (shl mone n).
Theorem shru_rolm: forall x n, ltu n iwordsize = true -> shru x n = rolm x (sub iwordsize n) (shru mone n).
Theorem rol_zero: forall x, rol x zero = x.
Lemma bitwise_binop_rol: forall f f' x y n, (forall x y i, 0 <= i < zwordsize -> testbit (f x y) i = f' (testbit x i) (testbit y i)) -> rol (f x y) n = f (rol x n) (rol y n).
Theorem rol_and: forall x y n, rol (and x y) n = and (rol x n) (rol y n).
Theorem rol_or: forall x y n, rol (or x y) n = or (rol x n) (rol y n).
Theorem rol_xor: forall x y n, rol (xor x y) n = xor (rol x n) (rol y n).
Theorem rol_rol: forall x n m, Z.divide zwordsize modulus -> rol (rol x n) m = rol x (modu (add n m) iwordsize).
Theorem rolm_zero: forall x m, rolm x zero m = and x m.
Theorem rolm_rolm: forall x n1 m1 n2 m2, Z.divide zwordsize modulus -> rolm (rolm x n1 m1) n2 m2 = rolm x (modu (add n1 n2) iwordsize) (and (rol m1 n2) m2).
Theorem or_rolm: forall x n m1 m2, or (rolm x n m1) (rolm x n m2) = rolm x n (or m1 m2).
Theorem ror_rol: forall x y, ltu y iwordsize = true -> ror x y = rol x (sub iwordsize y).
Theorem or_ror: forall x y z, ltu y iwordsize = true -> ltu z iwordsize = true -> add y z = iwordsize -> ror x z = or (shl x y) (shru x z).