diff --git a/Data/Hashable/Class.hs b/Data/Hashable/Class.hs
--- a/Data/Hashable/Class.hs
+++ b/Data/Hashable/Class.hs
@@ -276,10 +276,12 @@
 instance Hashable Integer where
 #if defined(__GLASGOW_HASKELL__) && defined(VERSION_integer_gmp)
     hashWithSalt salt (S# int) = hashWithSalt salt (I# int)
-    hashWithSalt salt n@(J# size byteArray)
+    hashWithSalt salt n@(J# size# byteArray)
         | n >= minInt && n <= maxInt = hashWithSalt salt (fromInteger n :: Int)
-        | otherwise = let numBytes = SIZEOF_HSWORD * (I# size)
+        | otherwise = let size = I# size#
+                          numBytes = SIZEOF_HSWORD * abs size
                       in hashByteArrayWithSalt byteArray 0 numBytes salt
+                         `hashWithSalt` size
       where minInt = fromIntegral (minBound :: Int)
             maxInt = fromIntegral (maxBound :: Int)
 #else
diff --git a/Data/Hashable/SipHash.hs b/Data/Hashable/SipHash.hs
new file mode 100644
--- /dev/null
+++ b/Data/Hashable/SipHash.hs
@@ -0,0 +1,159 @@
+{-# LANGUAGE BangPatterns, CPP, GeneralizedNewtypeDeriving, RecordWildCards #-}
+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
+
+module Data.Hashable.SipHash
+    (
+      LE64
+    , Sip
+    , fromWord64
+    , fullBlock
+    , lastBlock
+    , finalize
+    , hashByteString
+    ) where
+
+#include "MachDeps.h"
+
+import Data.Bits ((.|.), (.&.), rotateL, shiftL, xor)
+#if MIN_VERSION_base(4,5,0)
+import Data.Bits (unsafeShiftL)
+#endif
+import Data.Word (Word8, Word64)
+import Foreign.ForeignPtr (withForeignPtr)
+import Foreign.Ptr (Ptr, castPtr, plusPtr)
+import Data.ByteString.Internal (ByteString(PS), inlinePerformIO)
+import Foreign.Storable (peek)
+import Numeric (showHex)
+
+newtype LE64 = LE64 { fromLE64 :: Word64 }
+    deriving (Eq)
+
+instance Show LE64 where
+    show (LE64 !v) = let s = showHex v ""
+                     in "0x" ++ replicate (16 - length s) '0' ++ s
+
+data Sip = Sip {
+      v0 :: {-# UNPACK #-} !Word64, v1 :: {-# UNPACK #-} !Word64
+    , v2 :: {-# UNPACK #-} !Word64, v3 :: {-# UNPACK #-} !Word64
+    }
+
+fromWord64 :: Word64 -> LE64
+#ifndef WORDS_BIGENDIAN
+fromWord64 = LE64
+#else
+#error big endian support TBD
+#endif
+
+initState :: (Sip -> r) -> Word64 -> Word64 -> r
+initState k k0 k1 = k (Sip s0 s1 s2 s3)
+    where !s0 = (k0 `xor` 0x736f6d6570736575)
+          !s1 = (k1 `xor` 0x646f72616e646f6d)
+          !s2 = (k0 `xor` 0x6c7967656e657261)
+          !s3 = (k1 `xor` 0x7465646279746573)
+
+sipRound :: (Sip -> r) -> Sip -> r
+sipRound k Sip{..} = k (Sip v0_c v1_d v2_c v3_d)
+  where v0_a = v0 + v1
+        v2_a = v2 + v3
+        v1_a = v1 `rotateL` 13
+        v3_a = v3 `rotateL` 16
+        v1_b = v1_a `xor` v0_a
+        v3_b = v3_a `xor` v2_a
+        v0_b = v0_a `rotateL` 32
+        v2_b = v2_a + v1_b
+        v0_c = v0_b + v3_b
+        v1_c = v1_b `rotateL` 17
+        v3_c = v3_b `rotateL` 21
+        v1_d = v1_c `xor` v2_b
+        v3_d = v3_c `xor` v0_c
+        v2_c = v2_b `rotateL` 32
+
+fullBlock :: Int -> LE64 -> (Sip -> r) -> Sip -> r
+fullBlock c m k st@Sip{..}
+    | c == 2    = sipRound (sipRound k') st'
+    | otherwise = runRounds c k' st'
+  where k' st1@Sip{..} = k st1{ v0 = v0 `xor` fromLE64 m }
+        st'           = st{ v3 = v3 `xor` fromLE64 m }
+{-# INLINE fullBlock #-}
+
+runRounds :: Int -> (Sip -> r) -> Sip -> r
+runRounds c k = go 0
+  where go i st
+            | i < c     = sipRound (go (i+1)) st
+            | otherwise = k st
+{-# INLINE runRounds #-}
+
+lastBlock :: Int -> Int -> LE64 -> (Sip -> r) -> Sip -> r
+lastBlock !c !len !m k st =
+#ifndef WORDS_BIGENDIAN
+    fullBlock c (LE64 m') k st
+#else
+#error big endian support TBD
+#endif
+  where m' = fromLE64 m .|. ((fromIntegral len .&. 0xff) `shiftL` 56)
+{-# INLINE lastBlock #-}
+
+finalize :: Int -> (Word64 -> r) -> Sip -> r
+finalize d k st@Sip{..}
+    | d == 4    = sipRound (sipRound (sipRound (sipRound k'))) st'
+    | otherwise = runRounds d k' st'
+  where k' Sip{..} = k $! v0 `xor` v1 `xor` v2 `xor` v3
+        st'        = st{ v2 = v2 `xor` 0xff }
+{-# INLINE finalize #-}
+
+hashByteString :: Int -> Int -> Word64 -> Word64 -> ByteString -> Word64
+hashByteString !c !d k0 k1 (PS fp off len) =
+  inlinePerformIO . withForeignPtr fp $ \basePtr ->
+    let ptr0 = basePtr `plusPtr` off
+        scant = len .&. 7
+        endBlocks = ptr0 `plusPtr` (len - scant)
+        go !ptr st
+            | ptr == endBlocks = readLast ptr
+            | otherwise = do
+                m <- peekLE64 ptr
+                fullBlock c m (go (ptr `plusPtr` 8)) st
+          where
+            zero !m _ _ = lastBlock c len (LE64 m) (finalize d return) st
+            one k m p s = do
+              w <- fromIntegral `fmap` peekByte p
+              k (m .|. (w `unsafeShiftL` s)) (p `plusPtr` 1) (s+8)
+            readLast p =
+              case scant of
+                0 -> zero 0 p (0::Int)
+                1 -> one zero 0 p 0
+                2 -> one (one zero) 0 p 0
+                3 -> one (one (one zero)) 0 p 0
+                4 -> one (one (one (one zero))) 0 p 0
+                5 -> one (one (one (one (one zero)))) 0 p 0
+                6 -> one (one (one (one (one (one zero))))) 0 p 0
+                _ -> one (one (one (one (one (one (one zero)))))) 0 p 0
+    in initState (go ptr0) k0 k1
+
+peekByte :: Ptr Word8 -> IO Word8
+peekByte = peek
+
+peekLE64 :: Ptr Word8 -> IO LE64
+#if defined(x86_64_HOST_ARCH) || defined(i386_HOST_ARCH)
+-- platforms on which unaligned loads are legal and usually fast
+peekLE64 p = LE64 `fmap` peek (castPtr p)
+#else
+peekLE64 p = do
+  let peek8 d = fromIntegral `fmap` peekByte (p `plusPtr` d)
+  b0 <- peek8 0
+  b1 <- peek8 1
+  b2 <- peek8 2
+  b3 <- peek8 3
+  b4 <- peek8 4
+  b5 <- peek8 5
+  b6 <- peek8 6
+  b7 <- peek8 7
+  let !w = (b7 `shiftL` 56) .|. (b6 `shiftL` 48) .|. (b5 `shiftL` 40) .|.
+           (b4 `shiftL` 32) .|. (b3 `shiftL` 24) .|. (b2 `shiftL` 16) .|.
+           (b1 `shiftL` 8) .|. b0
+  return (fromWord64 w)
+#endif
+
+#if !MIN_VERSION_base(4,5,0)
+unsafeShiftL :: Word64 -> Int -> Word64
+unsafeShiftL = shiftL
+#endif
diff --git a/cbits/siphash.c b/cbits/siphash.c
--- a/cbits/siphash.c
+++ b/cbits/siphash.c
@@ -107,6 +107,7 @@
 	 :"+a" (eax), "=S" (ebx), "=c" (ecx), "=d" (edx)
 	 : :"edi");
 
+#if defined(HAVE_SSE2)
     if (edx & (1 << 26))
 	_siphash24 = hashable_siphash24_sse2;
 #if defined(HAVE_SSE41)
@@ -114,6 +115,7 @@
 	_siphash24 = hashable_siphash24_sse41;
 #endif
     else
+#endif
 	_siphash24 = plain_siphash24;
 }
 
diff --git a/hashable.cabal b/hashable.cabal
--- a/hashable.cabal
+++ b/hashable.cabal
@@ -1,5 +1,5 @@
 Name:                hashable
-Version:             1.2.0.7
+Version:             1.2.0.8
 Synopsis:            A class for types that can be converted to a hash value
 Description:         This package defines a class, 'Hashable', for types that
                      can be converted to a hash value.  This class
@@ -58,6 +58,7 @@
                      cbits/inthash.c
                      cbits/siphash.c
   if arch(i386) && flag(sse2)
+    CPP-Options:   -DHAVE_SSE2
     C-sources:       cbits/siphash-sse2.c
 
     if flag(sse41)
@@ -110,6 +111,7 @@
     Data.Hashable
     Data.Hashable.Class
     Data.Hashable.RandomSource
+    Data.Hashable.SipHash
   type: exitcode-stdio-1.0
 
   build-depends:
