Speed up the read_{u32,u64}{,v}_{le,be} and write_{u32,u64}_{be,le} functions

The original implementations of these functions were fairly efficient, however
they didn't respect the alignment requirements of the platform which could
cause crashes on ARM. The previous implementations of these functions were
designed to avoid the alignment issues, not necessarily to be optimal. The
result is that while the functions worked on ARM, they did a lot of unecessary
bounds checks and were not using the byte-swap instrinsics. I confirmed that
LLVM was not able to eliminate these checks by examining the X86_64 assembly
that was generated.

The functions have been re-written to use a similiar strategy as the original
implementations - namely processing u32 or u64 chunks of memory all at once
and using the byte-swap instrinsics. In order to avoid the alignment issues
of the original impementation, instead of coercing [u8] arrays into
[u64] (or [u32]) arrays (which might not be properly aligned) and then reading
or writing them, the new imlementation only works on [u8] arrays using the
copy_nonoverlapping_memory() instrinsic which does not have any particular
alignment restrictions.

The new implementations may be a bit slower than the original ones - it looks
like the original ones would generate some slightly different code using
some of the SSE registers. However, they definitally generate smaller code
with many fewer branches than the previous ones.