repeat match goal with
| [ |- context[wordToNat (natToWord ?sz ?w)] ] =>
let Heq := fresh "Heq" in
destruct (wordToNat_natToWord sz w) as [? [Heq ?]]; rewrite Heq
end.
rewrite mult_minus_distr_l.
rewrite mult_minus_distr_r.
match goal with
| [ |- natToWord _ (_ - _ * (?x0' * _)) = natToWord _ (_ - ?x1' * _ * _) ]
=> rename x0' into x0, x1' into x1 (* force the names to not be autogenerated *)
end.
rewrite (mult_assoc (wordToNat x) x0).
rewrite <- (mult_assoc x1).
rewrite (mult_comm (pow2 sz)).
rewrite (mult_assoc x1).
repeat rewrite drop_sub; auto with arith.
rewrite (mult_comm x1).
rewrite <- (mult_assoc (wordToNat x)).
rewrite (mult_comm (wordToNat y)).
rewrite mult_assoc.
rewrite (mult_comm (wordToNat x)).
repeat rewrite <- mult_assoc.
auto with arith.
repeat rewrite <- mult_assoc.
auto with arith.
Qed.

(* Specifications: *)
Theorem wmult_plus_distr : forall sz (x y z : word sz), (x ^+ y) ^* z = (x ^* z) ^+ (y ^* z).
intros sz x y z; repeat rewrite wmult_alt; repeat rewrite wplus_alt; unfold wmultN, wplusN, wordBinN; intros.