[project @ 1998-08-14 13:00:57 by sof]
authorsof <unknown>
Fri, 14 Aug 1998 13:00:58 +0000 (13:00 +0000)
committersof <unknown>
Fri, 14 Aug 1998 13:00:58 +0000 (13:00 +0000)
Complete Int64 and Word64 support on 32-bit platforms

ghc/lib/exts/Int.lhs
ghc/lib/exts/Word.lhs

index 138d668..c93678c 100644 (file)
@@ -53,6 +53,20 @@ module Int
        , sizeofInt32
        , sizeofInt64
        
+       -- The "official" place to get these from is Foreign
+       , indexInt8OffForeignObj
+       , indexInt16OffForeignObj
+       , indexInt32OffForeignObj
+       , indexInt64OffForeignObj
+       , readInt8OffForeignObj
+       , readInt16OffForeignObj
+       , readInt32OffForeignObj
+       , readInt64OffForeignObj
+       , writeInt8OffForeignObj
+       , writeInt16OffForeignObj
+       , writeInt32OffForeignObj
+       , writeInt64OffForeignObj
+       
        -- non-standard, GHC specific
        , intToWord
 
@@ -65,6 +79,7 @@ import PrelGHC
 import CCall
 import Numeric ( readDec )
 import Word    ( Word32 )
+import PrelForeign
 
 -----------------------------------------------------------------------------
 -- The "official" coercion functions
@@ -157,14 +172,12 @@ instance Integral Int8 where
        if x > 0 && y < 0       then quotInt8 (x-y-1) y
        else if x < 0 && y > 0  then quotInt8 (x-y+1) y
        else quotInt8 x y
-    quot x@(I8# _) y@(I8# y#) =
-       if y# /=# 0#
-       then x `quotInt8` y
-       else error "Integral.Int8.quot: divide by 0\n"
-    rem x@(I8# _) y@(I8# y#) =
-       if y# /=# 0#
-       then x `remInt8` y
-       else error "Integral.Int8.rem: divide by 0\n"
+    quot x@(I8# _) y@(I8# y#)
+       | y# /=# 0# = x `quotInt8` y
+       | otherwise = error "Integral.Int8.quot: divide by 0\n"
+    rem x@(I8# _) y@(I8# y#)
+       | y# /=# 0#  = x `remInt8` y
+       | otherwise  = error "Integral.Int8.rem: divide by 0\n"
     mod x@(I8# x#) y@(I8# y#) =
        if x > 0 && y < 0 || x < 0 && y > 0 then
          if r/=0 then r+y else 0
@@ -237,6 +250,9 @@ instance Bits Int8 where
 pow2# :: Int# -> Int#
 pow2# x# = iShiftL# 1# x#
 
+pow2_64# :: Int# -> Int64#
+pow2_64# x# = word64ToInt64# (shiftL64# (wordToWord64# (int2Word# 1#)) x#)
+
 sizeofInt8 :: Word32
 sizeofInt8 = 1
 \end{code}
@@ -289,14 +305,12 @@ instance Integral Int16 where
        if x > 0 && y < 0       then quotInt16 (x-y-1) y
        else if x < 0 && y > 0  then quotInt16 (x-y+1) y
        else quotInt16 x y
-    quot x@(I16# _) y@(I16# y#) =
-       if y# /=# 0#
-       then x `quotInt16` y
-       else error "Integral.Int16.quot: divide by 0\n"
-    rem x@(I16# _) y@(I16# y#) =
-       if y# /=# 0#
-       then x `remInt16` y
-       else error "Integral.Int16.rem: divide by 0\n"
+    quot x@(I16# _) y@(I16# y#)
+       | y# /=# 0#      = x `quotInt16` y
+       | otherwise      = error "Integral.Int16.quot: divide by 0\n"
+    rem x@(I16# _) y@(I16# y#)
+       | y# /=# 0#      = x `remInt16` y
+       | otherwise      = error "Integral.Int16.rem: divide by 0\n"
     mod x@(I16# x#) y@(I16# y#) =
        if x > 0 && y < 0 || x < 0 && y > 0 then
          if r/=0 then r+y else 0
@@ -321,8 +335,8 @@ instance Ix Int16 where
     inRange (m,n) i      = m <= i && i <= n
 
 instance Enum Int16 where
-    toEnum         = intToInt16
-    fromEnum       = int16ToInt
+    toEnum           = intToInt16
+    fromEnum         = int16ToInt
     enumFrom c       = map toEnum [fromEnum c .. fromEnum (maxBound::Int16)]
     enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Int16)]
                          where last = if d < c then minBound else maxBound
@@ -437,14 +451,12 @@ instance Integral Int32 where
        if x > 0 && y < 0       then quotInt32 (x-y-1) y
        else if x < 0 && y > 0  then quotInt32 (x-y+1) y
        else quotInt32 x y
-    quot x@(I32# _) y@(I32# y#) =
-       if y# /=# 0#
-       then x `quotInt32` y
-       else error "Integral.Int32.quot: divide by 0\n"
-    rem x@(I32# _) y@(I32# y#) =
-       if y# /=# 0#
-       then x `remInt32` y
-       else error "Integral.Int32.rem: divide by 0\n"
+    quot x@(I32# _) y@(I32# y#)
+       | y# /=# 0#  = x `quotInt32` y
+       | otherwise  = error "Integral.Int32.quot: divide by 0\n"
+    rem x@(I32# _) y@(I32# y#)
+       | y# /=# 0#  = x `remInt32` y
+       | otherwise  = error "Integral.Int32.rem: divide by 0\n"
     mod x@(I32# x#) y@(I32# y#) =
        if x > 0 && y < 0 || x < 0 && y > 0 then
          if r/=0 then r+y else 0
@@ -526,20 +538,144 @@ sizeofInt32 = 4
 
 
 \begin{code}
-data Int64 = I64 {lo,hi::Int32} deriving (Eq, Ord, Bounded)
+#if WORD_SIZE_IN_BYTES == 8
+data Int64 = I64# Int#
+
+int32ToInt64 :: Int32 -> Int64
+int32ToInt64 (I32# i#) = I64# i#
+
+intToInt32# :: Int# -> Int#
+intToInt32# i# = word2Int# ((int2Word# i#) `and#` (case (maxBound::Word32) of W# x# -> x#))
+
+int64ToInt32 :: Int64 -> Int32
+int64ToInt32 (I64# i#) = I32# (intToInt32# w#)
+
+instance Eq  Int64     where 
+  (I64# x) == (I64# y) = x `eqInt#` y
+  (I64# x) /= (I64# y) = x `neInt#` y
+
+instance Ord Int32    where
+  compare (I64# x#) (I64# y#) = compareInt# x# y#
+
+instance Num Int64 where
+  (I64# x) + (I64# y) = I64# (x +# y)
+  (I64# x) - (I64# y) = I64# (x -# y)
+  (I64# x) * (I64# y) = I64# (x *# y)
+  negate w@(I64# x)   = I64# (negateInt# x)
+  abs x               = absReal
+  signum              = signumReal
+  fromInteger (J# a# s# d#) = case (integer2Int# a# s# d#) of { i# -> I64# i# }
+  fromInt       = intToInt64
+
+instance Bounded Int64 where
+  minBound = integerToInt64 (-0x8000000000000000)
+  maxBound = integerToInt64 0x7fffffffffffffff
+
+instance Real Int64 where
+  toRational x = toInteger x % 1
+
+instance Integral Int64 where
+    div x@(I64# x#) y@(I64# y#)
+      | x > 0 && y < 0 = quotInt64 (x-y-1) y
+      | x < 0 && y > 0 = quotInt64 (x-y+1) y
+      | otherwise       = quotInt64 x y
+
+    quot x@(I64# _) y@(I64# y#)
+       | y# /=# 0# = x `quotInt64` y
+       | otherwise = error "Integral.Int64.quot: divide by 0\n"
+
+    rem x@(I64# _) y@(I64# y#)
+       | y# /=# 0# = x `remInt64` y
+       | otherwise = error "Integral.Int32.rem: divide by 0\n"
+
+    mod x@(I64# x#) y@(I64# y#)
+       | x > 0 && y < 0 || x < 0 && y > 0 = if r/=0 then r+y else 0
+       | otherwise = r
+       where r = remInt64 x y
+
+    a@(I64# _) `quotRem` b@(I64# _) = (a `quotInt64` b, a `remInt64` b)
+    toInteger (I64# i#) = toInteger (I# i#)
+    toInt     (I64# i#) = I# i#
+
+instance Enum Int64 where
+    toEnum    (I# i)   = I64# i#
+    fromEnum  (I64# i) = I64# i#
+    enumFrom c         = map toEnum [fromEnum c .. fromEnum (maxBound::Int64)] -- a long list!
+    enumFromThen c d   = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Int64)]
+                      where last = if d < c then minBound else maxBound
+
+
+instance Read Int64 where
+    readsPrec p s = [ (intToInt64 x,r) | (x,r) <- readsPrec p s ]
+
+instance Show Int64 where
+    showsPrec p i64 = showsPrec p (int64ToInt i64)
+
+instance Bits Int64 where
+  (I64# x) .&. (I64# y)   = I64# (word2Int# ((int2Word# x) `and#` (int2Word# y)))
+  (I64# x) .|. (I64# y)   = I64# (word2Int# ((int2Word# x) `or#`  (int2Word# y)))
+  (I64# x) `xor` (I64# y) = I64# (word2Int# ((int2Word# x) `xor#` (int2Word# y)))
+  complement (I64# x)     = I64# (negateInt# x)
+  shift (I64# x) i@(I# i#)
+       | i > 0     = I64# (iShiftL# x  i#)
+       | otherwise = I64# (iShiftRA# x (negateInt# i#))
+  i64@(I64# x)  `rotate` (I# i)
+        | i ==# 0#    = i64
+       | i ># 0#     = 
+             -- ( (x<<i') | ((x&(0x10000000000000000-2^i2))>>i2) )
+            I64# (word2Int# (
+                   (int2Word# (iShiftL# x i')) 
+                         `or#`
+                    (int2Word# (iShiftRA# (word2Int# (
+                                             (int2Word# x) 
+                                                 `and#` 
+                                              (int2Word# (maxBound# -# pow2# i2 +# 1#))))
+                                         i2))))
+       | otherwise = rotate i64 (I# (64# +# i))
+          where
+           i' = word2Int# (int2Word# i `and#` int2Word# 63#)
+           i2 = 64# -# i'
+           (I64# maxBound#) = maxBound
+  bit i                = shift 1 i
+  setBit x i    = x .|. bit i
+  clearBit x i  = x .&. complement (bit i)
+  complementBit x i = x `xor` bit i
+  testBit x i   = (x .&. bit i) /= 0
+  bitSize  _    = 64
+  isSigned _    = True
+
+
+
+remInt64  (I64# x) (I64# y) = I64# (x `remInt#` y)
+quotInt64 (I64# x) (I64# y) = I64# (x `quotInt#` y)
 
 int64ToInteger :: Int64 -> Integer
-int64ToInteger I64{lo,hi} = toInteger lo + 0x100000000 * toInteger hi 
+int64ToInteger (I64# i#) = toInteger (I# i#)
 
 integerToInt64 :: Integer -> Int64
-integerToInt64 x = case x `quotRem` 0x100000000 of 
-                 (h,l) -> I64{lo=fromInteger l, hi=fromInteger h}
+integerToInt64 i = case fromInteger i of { I# i# -> I64# i# }
 
 intToInt64 :: Int -> Int64
-intToInt64 x =  I64{lo=intToInt32 x, hi=0}
+intToInt64 (I# i#) = I64# i#
 
 int64ToInt :: Int64 -> Int
-int64ToInt (I64 lo _) = int32ToInt lo
+int64ToInt (I64# i#) = I# i#
+
+#else
+--assume: support for long-longs
+--data Int64 = I64 Int64# deriving (Eq, Ord, Bounded)
+
+int32ToInt64 :: Int32 -> Int64
+int32ToInt64 (I32# i#) = I64# (intToInt64# i#)
+
+int64ToInt32 :: Int64 -> Int32
+int64ToInt32 (I64# i#) = I32# (int64ToInt# i#)
+
+int64ToInteger :: Int64 -> Integer
+int64ToInteger (I64# x#) = int64ToInteger# x#
+
+integerToInt64 :: Integer -> Int64
+integerToInt64 (J# a# s# d#) = I64# (integerToInt64# a# s# d#)
 
 instance Show Int64 where
   showsPrec p x = showsPrec p (int64ToInteger x)
@@ -547,6 +683,281 @@ instance Show Int64 where
 instance Read Int64 where
   readsPrec p s = [ (integerToInt64 x,r) | (x,r) <- readDec s ]
 
+instance Eq  Int64     where 
+  (I64# x) == (I64# y) = x `eqInt64#` y
+  (I64# x) /= (I64# y) = x `neInt64#` y
+
+instance Ord Int64     where 
+  compare (I64# x) (I64# y)   = compareInt64# x y
+  (<)  (I64# x) (I64# y)      = x `ltInt64#` y
+  (<=) (I64# x) (I64# y)      = x `leInt64#` y
+  (>=) (I64# x) (I64# y)      = x `geInt64#` y
+  (>)  (I64# x) (I64# y)      = x `gtInt64#` y
+  max x@(I64# x#) y@(I64# y#) = 
+     case (compareInt64# x# y#) of { LT -> y ; EQ -> x ; GT -> x }
+  min x@(I64# x#) y@(I64# y#) =
+     case (compareInt64# x# y#) of { LT -> x ; EQ -> x ; GT -> y }
+
+instance Num Int64 where
+  (I64# x) + (I64# y) = I64# (x `plusInt64#`  y)
+  (I64# x) - (I64# y) = I64# (x `minusInt64#` y)
+  (I64# x) * (I64# y) = I64# (x `timesInt64#` y)
+  negate (I64# x)     = I64# (negateInt64# x)
+  abs x               = absReal x
+  signum              = signumReal
+  fromInteger i       = integerToInt64 i
+  fromInt     i       = intToInt64 i
+
+compareInt64# i# j# 
+ | i# `ltInt64#` j# = LT
+ | i# `eqInt64#` j# = EQ
+ | otherwise       = GT
+
+instance Bounded Int64 where
+  minBound = integerToInt64 (-0x8000000000000000)
+  maxBound = integerToInt64 0x7fffffffffffffff
+
+instance Real Int64 where
+  toRational x = toInteger x % 1
+
+instance Integral Int64 where
+    div x@(I64# x#) y@(I64# y#)
+      | x > 0 && y < 0 = quotInt64 (x-y-1) y
+      | x < 0 && y > 0 = quotInt64 (x-y+1) y
+      | otherwise       = quotInt64 x y
+
+    quot x@(I64# _) y@(I64# y#)
+       | y# `neInt64#` (intToInt64# 0#) = x `quotInt64` y
+       | otherwise = error "Integral.Int64.quot: divide by 0\n"
+
+    rem x@(I64# _) y@(I64# y#)
+       | y# `neInt64#` (intToInt64# 0#) = x `remInt64` y
+       | otherwise = error "Integral.Int32.rem: divide by 0\n"
+
+    mod x@(I64# x#) y@(I64# y#)
+       | x > 0 && y < 0 || x < 0 && y > 0 = if r/=0 then r+y else 0
+       | otherwise = r
+       where r = remInt64 x y
+
+    a@(I64# _) `quotRem` b@(I64# _) = (a `quotInt64` b, a `remInt64` b)
+    toInteger i         = int64ToInteger i
+    toInt     i         = int64ToInt i
+
+instance Enum Int64 where
+    toEnum    (I# i)   = I64# (intToInt64# i)
+    fromEnum  (I64# w) = I# (int64ToInt# w)
+    enumFrom i              = eft64 i 1
+    enumFromTo   i1 i2      = eftt64 i1 1 (> i2)
+    enumFromThen i1 i2      = eftt64 i1 (i2 - i1) (>last)
+        where 
+        last
+         | i1 < i2   = maxBound::Int64
+         | otherwise = minBound
+
+
+instance Bits Int64 where
+  (I64# x) .&. (I64# y)   = I64# (word64ToInt64# ((int64ToWord64# x) `and64#` (int64ToWord64# y)))
+  (I64# x) .|. (I64# y)   = I64# (word64ToInt64# ((int64ToWord64# x) `or64#`  (int64ToWord64# y)))
+  (I64# x) `xor` (I64# y) = I64# (word64ToInt64# ((int64ToWord64# x) `xor64#` (int64ToWord64# y)))
+  complement (I64# x)     = I64# (negateInt64# x)
+  shift (I64# x) i@(I# i#)
+       | i > 0     = I64# (iShiftL64# x  i#)
+       | otherwise = I64# (iShiftRA64# x (negateInt# i#))
+  i64@(I64# x)  `rotate` (I# i)
+        | i ==# 0#    = i64
+       | i ># 0#     = 
+             -- ( (x<<i') | ((x&(0x10000000000000000-2^i2))>>i2) )
+            I64# (word64ToInt64# (
+                   (int64ToWord64# (iShiftL64# x i'))                    `or64#`
+                    (int64ToWord64# (iShiftRA64# (word64ToInt64# ((int64ToWord64# x)     `and64#` 
+                                                (int64ToWord64# (maxBound# `minusInt64#` (pow2_64# i2 `plusInt64#` (intToInt64# 1#))))))
+                                               i2))))
+       | otherwise = rotate i64 (I# (64# +# i))
+          where
+           i' = word2Int# (int2Word# i `and#` int2Word# 63#)
+           i2 = 64# -# i'
+           (I64# maxBound#) = maxBound
+  bit i                = shift 1 i
+  setBit x i    = x .|. bit i
+  clearBit x i  = x .&. complement (bit i)
+  complementBit x i = x `xor` bit i
+  testBit x i   = (x .&. bit i) /= 0
+  bitSize  _    = 64
+  isSigned _    = True
+
+remInt64  (I64# x) (I64# y) = I64# (x `remInt64#` y)
+quotInt64 (I64# x) (I64# y) = I64# (x `quotInt64#` y)
+
+intToInt64 :: Int -> Int64
+intToInt64 (I# i#) = I64# (intToInt64# i#)
+
+int64ToInt :: Int64 -> Int
+int64ToInt (I64# i#) = I# (int64ToInt# i#)
+
+-- Enum Int64 helper funs:
+
+eftt64 :: Int64 -> Int64 -> (Int64->Bool) -> [Int64]
+eftt64 now step done = go now
+  where
+   go now
+     | done now  = []
+     | otherwise = now : go (now+step)
+
+eft64 :: Int64 -> Int64 -> [Int64]
+eft64 now step = go now
+  where 
+   go x
+    | x == maxBound = [x]
+    | otherwise     = x:go (x+step)
+
+
+-- Word64# primop wrappers:
+
+ltInt64# :: Int64# -> Int64# -> Bool
+ltInt64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_ltInt64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+      
+leInt64# :: Int64# -> Int64# -> Bool
+leInt64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_leInt64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+      
+eqInt64# :: Int64# -> Int64# -> Bool
+eqInt64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_eqInt64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+      
+neInt64# :: Int64# -> Int64# -> Bool
+neInt64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_neInt64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+      
+geInt64# :: Int64# -> Int64# -> Bool
+geInt64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_geInt64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+      
+gtInt64# :: Int64# -> Int64# -> Bool
+gtInt64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_gtInt64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+
+plusInt64# :: Int64# -> Int64# -> Int64#
+plusInt64# a# b# = 
+  case (unsafePerformIO (_ccall_ stg_plusInt64 a# b#)) of
+    I64# i# -> i#
+
+minusInt64# :: Int64# -> Int64# -> Int64#
+minusInt64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_minusInt64 a# b#)) of
+    I64# i# -> i#
+
+timesInt64# :: Int64# -> Int64# -> Int64#
+timesInt64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_timesInt64 a# b#)) of
+    I64# i# -> i#
+
+quotInt64# :: Int64# -> Int64# -> Int64#
+quotInt64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_quotInt64 a# b#)) of
+    I64# i# -> i#
+
+remInt64# :: Int64# -> Int64# -> Int64#
+remInt64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_remInt64 a# b#)) of
+    I64# i# -> i#
+
+negateInt64# :: Int64# -> Int64#
+negateInt64# a# =
+  case (unsafePerformIO (_ccall_ stg_negateInt64 a#)) of
+    I64# i# -> i#
+
+and64# :: Word64# -> Word64# -> Word64#
+and64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_and64 a# b#)) of
+    W64# w# -> w#
+
+or64# :: Word64# -> Word64# -> Word64#
+or64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_or64 a# b#)) of
+    W64# w# -> w#
+
+xor64# :: Word64# -> Word64# -> Word64#
+xor64# a# b# = 
+  case (unsafePerformIO (_ccall_ stg_xor64 a# b#)) of
+    W64# w# -> w#
+
+not64# :: Word64# -> Word64#
+not64# a# = 
+  case (unsafePerformIO (_ccall_ stg_not64 a#)) of
+    W64# w# -> w#
+
+shiftL64# :: Word64# -> Int# -> Word64#
+shiftL64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_shiftL64 a# b#)) of
+    W64# w# -> w#
+
+iShiftL64# :: Int64# -> Int# -> Int64#
+iShiftL64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_iShiftL64 a# b#)) of
+    I64# i# -> i#
+
+iShiftRL64# :: Int64# -> Int# -> Int64#
+iShiftRL64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_iShiftRL64 a# b#)) of
+    I64# i# -> i#
+
+iShiftRA64# :: Int64# -> Int# -> Int64#
+iShiftRA64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_iShiftRA64 a# b#)) of
+    I64# i# -> i#
+
+shiftRL64# :: Word64# -> Int# -> Word64#
+shiftRL64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_shifRtL64 a# b#)) of
+    W64# w# -> w#
+
+int64ToInt# :: Int64# -> Int#
+int64ToInt# i# =
+  case (unsafePerformIO (_ccall_ stg_int64ToInt i#)) of
+    I# i# -> i#
+
+wordToWord64# :: Word# -> Word64#
+wordToWord64# w# =
+  case (unsafePerformIO (_ccall_ stg_wordToWord64 w#)) of
+    W64# w# -> w#
+
+word64ToInt64# :: Word64# -> Int64#
+word64ToInt64# w# =
+  case (unsafePerformIO (_ccall_ stg_word64ToInt64 w#)) of
+    I64# i# -> i#
+
+int64ToWord64# :: Int64# -> Word64#
+int64ToWord64# w# =
+  case (unsafePerformIO (_ccall_ stg_int64ToWord64 w#)) of
+    W64# w# -> w#
+
+intToInt64# :: Int# -> Int64#
+intToInt64# i# =
+  case (unsafePerformIO (_ccall_ stg_intToInt64 i#)) of
+    I64# i# -> i#
+      
+
+#endif
+
 sizeofInt64 :: Word32
 sizeofInt64 = 8
 \end{code}
@@ -572,6 +983,9 @@ signumReal x | x == 0    =  0
 indexInt8OffAddr  :: Addr -> Int -> Int8
 indexInt8OffAddr (A# a#) (I# i#) = intToInt8 (I# (ord# (indexCharOffAddr# a# i#)))
 
+indexInt8OffForeignObj  :: ForeignObj -> Int -> Int8
+indexInt8OffForeignObj (ForeignObj fo#) (I# i#) = intToInt8 (I# (ord# (indexCharOffForeignObj# fo# i#)))
+
 indexInt16OffAddr :: Addr -> Int -> Int16
 indexInt16OffAddr a i =
 #ifdef WORDS_BIGENDIAN
@@ -584,6 +998,18 @@ indexInt16OffAddr a i =
    l = indexInt8OffAddr a byte_idx
    h = indexInt8OffAddr a (byte_idx+1)
 
+indexInt16OffForeignObj :: ForeignObj -> Int -> Int16
+indexInt16OffForeignObj fo i =
+#ifdef WORDS_BIGENDIAN
+  intToInt16 ( int8ToInt l + (int8ToInt maxBound) * int8ToInt h)
+#else
+  intToInt16 ( int8ToInt h + (int8ToInt maxBound) * int8ToInt l)
+#endif
+ where
+   byte_idx = i * 2
+   l = indexInt8OffForeignObj fo byte_idx
+   h = indexInt8OffForeignObj fo (byte_idx+1)
+
 indexInt32OffAddr :: Addr -> Int -> Int32
 indexInt32OffAddr (A# a#) i = intToInt32 (I# (indexIntOffAddr# a# i'#))
  where
@@ -595,12 +1021,31 @@ indexInt32OffAddr (A# a#) i = intToInt32 (I# (indexIntOffAddr# a# i'#))
    = i
 #endif
 
+indexInt32OffForeignObj :: ForeignObj -> Int -> Int32
+indexInt32OffForeignObj (ForeignObj fo#) i = intToInt32 (I# (indexIntOffForeignObj# fo# i'#))
+ where
+   -- adjust index to be in Int units, not Int32 ones.
+  (I# i'#) 
+#if WORD_SIZE_IN_BYTES==8
+   = i `div` 2
+#else
+   = i
+#endif
+
 indexInt64OffAddr :: Addr -> Int -> Int64
-indexInt64OffAddr (A# i#)
+indexInt64OffAddr (A# a#) (I# i#)
 #if WORD_SIZE_IN_BYTES==8
  = I64# (indexIntOffAddr# a# i#)
 #else
- = error "Int.indexInt64OffAddr: not implemented yet"
+ = I64# (indexInt64OffAddr# a# i#)
+#endif
+
+indexInt64OffForeignObj :: ForeignObj -> Int -> Int64
+indexInt64OffForeignObj (ForeignObj fo#) (I# i#)
+#if WORD_SIZE_IN_BYTES==8
+ = I64# (indexIntOffForeignObj# fo# i#)
+#else
+ = I64# (indexInt64OffForeignObj# fo# i#)
 #endif
 
 \end{code}
@@ -611,17 +1056,33 @@ Read words out of mutable memory:
 readInt8OffAddr :: Addr -> Int -> IO Int8
 readInt8OffAddr a i = _casm_ `` %r=(StgInt8)(((StgInt8*)%0)[(StgInt)%1]); '' a i
 
+readInt8OffForeignObj :: ForeignObj -> Int -> IO Int8
+readInt8OffForeignObj fo i = _casm_ `` %r=(StgInt8)(((StgInt8*)%0)[(StgInt)%1]); '' fo i
+
 readInt16OffAddr  :: Addr -> Int -> IO Int16
 readInt16OffAddr a i = _casm_ `` %r=(StgInt16)(((StgInt16*)%0)[(StgInt)%1]); '' a i
 
+readInt16OffForeignObj  :: ForeignObj -> Int -> IO Int16
+readInt16OffForeignObj fo i = _casm_ `` %r=(StgInt16)(((StgInt16*)%0)[(StgInt)%1]); '' fo i
+
 readInt32OffAddr  :: Addr -> Int -> IO Int32
 readInt32OffAddr a i = _casm_ `` %r=(StgInt32)(((StgInt32*)%0)[(StgInt)%1]); '' a i
 
+readInt32OffForeignObj  :: ForeignObj -> Int -> IO Int32
+readInt32OffForeignObj fo i = _casm_ `` %r=(StgInt32)(((StgInt32*)%0)[(StgInt)%1]); '' fo i
+
 readInt64OffAddr  :: Addr -> Int -> IO Int64
 #if WORD_SIZE_IN_BYTES==8
 readInt64OffAddr a i = _casm_ `` %r=(StgInt)(((StgInt*)%0)[(StgInt)%1]); '' a i
 #else
-readInt64OffAddr a i = error "Int.readInt64OffAddr: not implemented yet"
+readInt64OffAddr a i = _casm_ `` %r=(StgInt64)(((StgInt64*)%0)[(StgInt)%1]); '' a i
+#endif
+
+readInt64OffForeignObj  :: ForeignObj -> Int -> IO Int64
+#if WORD_SIZE_IN_BYTES==8
+readInt64OffForeignObj fo i = _casm_ `` %r=(StgInt)(((StgInt*)%0)[(StgInt)%1]); '' fo i
+#else
+readInt64OffForeignObj fo i = _casm_ `` %r=(StgInt64)(((StgInt64*)%0)[(StgInt)%1]); '' fo i
 #endif
 \end{code}
 
@@ -629,17 +1090,33 @@ readInt64OffAddr a i = error "Int.readInt64OffAddr: not implemented yet"
 writeInt8OffAddr  :: Addr -> Int -> Int8  -> IO ()
 writeInt8OffAddr a i e = _casm_ `` (((StgInt8*)%0)[(StgInt)%1])=(StgInt8)%2; '' a i e
 
+writeInt8OffForeignObj  :: ForeignObj -> Int -> Int8  -> IO ()
+writeInt8OffForeignObj fo i e = _casm_ `` (((StgInt8*)%0)[(StgInt)%1])=(StgInt8)%2; '' fo i e
+
 writeInt16OffAddr :: Addr -> Int -> Int16 -> IO ()
 writeInt16OffAddr a i e = _casm_ `` (((StgInt16*)%0)[(StgInt)%1])=(StgInt16)%2; '' a i e
 
+writeInt16OffForeignObj :: ForeignObj -> Int -> Int16 -> IO ()
+writeInt16OffForeignObj fo i e = _casm_ `` (((StgInt16*)%0)[(StgInt)%1])=(StgInt16)%2; '' fo i e
+
 writeInt32OffAddr :: Addr -> Int -> Int32 -> IO ()
 writeInt32OffAddr a i e = _casm_ `` (((StgInt32*)%0)[(StgInt)%1])=(StgInt32)%2; '' a i e
 
+writeInt32OffForeignObj :: ForeignObj -> Int -> Int32 -> IO ()
+writeInt32OffForeignObj fo i e = _casm_ `` (((StgInt32*)%0)[(StgInt)%1])=(StgInt32)%2; '' fo i e
+
 writeInt64OffAddr :: Addr -> Int -> Int64 -> IO ()
 #if WORD_SIZE_IN_BYTES==8
 writeInt64OffAddr a i e = _casm_ `` (((StgInt*)%0)[(StgInt)%1])=(StgInt)%2; '' a i e
 #else
-writeInt64OffAddr = error "Int.writeInt64OffAddr: not implemented yet"
+writeInt64OffAddr a i e = _casm_ `` (((StgInt64*)%0)[(StgInt)%1])=(StgInt64)%2; '' a i e
+#endif
+
+writeInt64OffForeignObj :: ForeignObj -> Int -> Int64 -> IO ()
+#if WORD_SIZE_IN_BYTES==8
+writeInt64OffForeignObj fo i e = _casm_ `` (((StgInt*)%0)[(StgInt)%1])=(StgInt)%2; '' fo i e
+#else
+writeInt64OffForeignObj fo i e = _casm_ `` (((StgInt64*)%0)[(StgInt)%1])=(StgInt64)%2; '' fo i e
 #endif
 
 \end{code}
index 75a4749..f8a6df4 100644 (file)
@@ -38,12 +38,14 @@ module Word
        , integerToWord64 -- :: Integer -> Word64
 
        -- NB! GHC SPECIFIC:
-       , wordToWord8     -- :: Word -> Word8
-       , word8ToWord     -- :: Word8 -> Word
-       , wordToWord16    -- :: Word -> Word16
+       , wordToWord8     -- :: Word   -> Word8
+       , word8ToWord     -- :: Word8  -> Word
+       , wordToWord16    -- :: Word   -> Word16
        , word16ToWord    -- :: Word16 -> Word
-       , wordToWord32    -- :: Word -> Word32
+       , wordToWord32    -- :: Word   -> Word32
        , word32ToWord    -- :: Word32 -> Word
+       , wordToWord64    -- :: Word   -> Word64
+       , word64ToWord    -- :: Word64 -> Word
 
        -- The "official" place to get these from is Addr.
        , indexWord8OffAddr
@@ -66,6 +68,22 @@ module Word
        , sizeofWord32
        , sizeofWord64
 
+       -- The "official" place to get these from is Foreign
+       , indexWord8OffForeignObj
+       , indexWord16OffForeignObj
+       , indexWord32OffForeignObj
+       , indexWord64OffForeignObj
+       
+       , readWord8OffForeignObj
+       , readWord16OffForeignObj
+       , readWord32OffForeignObj
+       , readWord64OffForeignObj
+       
+       , writeWord8OffForeignObj
+       , writeWord16OffForeignObj
+       , writeWord32OffForeignObj
+       , writeWord64OffForeignObj
+       
        -- non-standard, GHC specific
        , wordToInt
 
@@ -76,6 +94,8 @@ import Ix
 import Bits
 import CCall
 import Numeric (readDec, showInt)
+import PrelForeign
+import PrelIOBase
 
 -----------------------------------------------------------------------------
 -- The "official" coercion functions
@@ -253,6 +273,9 @@ instance Bits Word8 where
 pow2# :: Int# -> Int#
 pow2# x# = word2Int# (shiftL# (int2Word# 1#) x#)
 
+pow2_64# :: Int# -> Int64#
+pow2_64# x# = word64ToInt64# (shiftL64# (wordToWord64# (int2Word# 1#)) x#)
+
 sizeofWord8 :: Word32
 sizeofWord8 = 1
 
@@ -454,7 +477,6 @@ wordToWord32# :: Word# -> Word#
 #if WORD_SIZE_IN_BYTES == 8
 intToWord32#  i# = (int2Word# i#) `and#` (int2Word# 0xffffffff)
 wordToWord32# w# = w# `and#` (int2Word# 0xffffffff)
-wordToWord64# w# = w#
 #else
 intToWord32#  i# = int2Word# i#
 wordToWord32# w# = w#
@@ -498,11 +520,29 @@ instance Ix Word32 where
     inRange (m,n) i      = m <= i && i <= n
 
 instance Enum Word32 where
-    toEnum        = intToWord32
-    fromEnum      = word32ToInt
-    enumFrom c       = map toEnum [fromEnum c .. fromEnum (maxBound::Word32)]
-    enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Word32)]
-                      where last = if d < c then minBound else maxBound
+    toEnum                  = intToWord32
+    fromEnum                = word32ToInt   -- lossy, don't use.
+    enumFrom w              = eft32 w 1
+    enumFromTo   w1 w2      = eftt32 w1 1 (> w2)
+    enumFromThen w1 w2      = eftt32 w1 (w2 - w1) (>last)
+        where 
+        last
+         | w1 < w2   = maxBound::Word32
+         | otherwise = minBound
+
+eftt32 :: Word32 -> Word32 -> (Word32->Bool) -> [Word32]
+eftt32 now step done = go now
+  where
+   go now
+     | done now  = []
+     | otherwise = now : go (now+step)
+
+eft32 :: Word32 -> Word32 -> [Word32]
+eft32 now step = go now
+  where 
+   go x
+    | x == maxBound = [x]
+    | otherwise     = x:go (x+step)
 
 instance Read Word32 where
     readsPrec p = readDec
@@ -563,6 +603,9 @@ wordToWord32# w# = w# `and#` (case (maxBound::Word32) of W# x# -> x#)
 word64ToWord32 :: Word64 -> Word32
 word64ToWord32 (W64# w#) = W32# (wordToWord32# w#)
 
+wordToWord64# w# = w#
+word64ToWord# w# = w#
+
 instance Eq  Word64     where 
   (W64# x) == (W64# y) = x `eqWord#` y
   (W64# x) /= (W64# y) = x `neWord#` y
@@ -613,7 +656,7 @@ instance Integral Word64 where
   quotRem (W64# x) (W64# y) = (W64# (x `quotWord#` y), W64# (x `remWord#` y))
   divMod  (W64# x) (W64# y) = (W64# (x `quotWord#` y), W64# (x `remWord#` y))
   toInteger (W64# x)        = word2Integer# x
-  toInt x                   = word8ToInt x
+  toInt x                   = word64ToInt x
 
 instance Ix Word64 where
     range (m,n)          = [m..n]
@@ -626,11 +669,15 @@ instance Ix Word64 where
     inRange (m,n) i      = m <= i && i <= n
 
 instance Enum Word64 where
-    toEnum    (I# i)   = W64# (intToWord# i)
-    fromEnum  (W64# w) = I# (word2Int# w)
-    enumFrom c       = map toEnum [fromEnum c .. fromEnum (maxBound::Word64)] -- a long list!
-    enumFromThen c d = map toEnum [fromEnum c, fromEnum d .. fromEnum (last::Word64)]
-                      where last = if d < c then minBound else maxBound
+    toEnum    (I# i)        = W64# (intToWord# i)
+    fromEnum  (W64# w)      = I# (word2Int# w)    -- lossy, don't use.
+    enumFrom w              = eft64 w 1
+    enumFromTo   w1 w2      = eftt64 w1 1 (> w2)
+    enumFromThen w1 w2      = eftt64 w1 (w2 - w1) (>last)
+        where 
+        last
+         | w1 < w2   = maxBound::Word64
+         | otherwise = minBound
 
 instance Read Word64 where
     readsPrec p = readDec
@@ -676,21 +723,31 @@ instance Bits Word64 where
   isSigned _    = False
 
 #else
-data Word64 = W64 {lo,hi::Word32} deriving (Eq, Ord, Bounded)
+--defined in PrelCCall: data Word64 = W64 Word64# deriving (Eq, Ord, Bounded)
 
 -- for completeness sake
 word32ToWord64 :: Word32 -> Word64
-word32ToWord64 w = W64 w 0
+word32ToWord64 (W32# w#) = W64# (wordToWord64# w#)
 
 word64ToWord32 :: Word64 -> Word32
-word64ToWord32 (W64 lo _) = lo
+word64ToWord32 (W64# w#) = W32# (word64ToWord# w#)
 
 word64ToInteger :: Word64 -> Integer
-word64ToInteger W64{lo,hi} = toInteger lo + 0x100000000 * toInteger hi 
+word64ToInteger (W64# w#) = word64ToInteger# w#
+
+word64ToInt :: Word64 -> Int
+word64ToInt w = 
+   case w `quotRem` 0x100000000 of 
+     (h,l) -> toInt (word64ToWord32 l)
+
+intToWord64# :: Int# -> Word64#
+intToWord64# i# = wordToWord64# (int2Word# i#)
+
+intToWord64 :: Int -> Word64
+intToWord64 (I# i#) = W64# (intToWord64# i#)
 
 integerToWord64 :: Integer -> Word64
-integerToWord64 x = case x `quotRem` 0x100000000 of 
-                      (h,l) -> W64{lo=fromInteger l, hi=fromInteger h}
+integerToWord64 (J# a# s# d#) = W64# (integerToWord64# a# s# d#)
 
 instance Show Word64 where
   showsPrec p x = showsPrec p (word64ToInteger x)
@@ -698,10 +755,269 @@ instance Show Word64 where
 instance Read Word64 where
   readsPrec p s = [ (integerToWord64 x,r) | (x,r) <- readDec s ]
 
+instance Eq  Word64     where 
+  (W64# x) == (W64# y) = x `eqWord64#` y
+  (W64# x) /= (W64# y) = not (x `eqWord64#` y)
+
+instance Ord Word64     where 
+  compare (W64# x#) (W64# y#) = compareWord64# x# y#
+  (<)  (W64# x) (W64# y)      = x `ltWord64#` y
+  (<=) (W64# x) (W64# y)      = x `leWord64#` y
+  (>=) (W64# x) (W64# y)      = x `geWord64#` y
+  (>)  (W64# x) (W64# y)      = x `gtWord64#` y
+  max x@(W64# x#) y@(W64# y#) = 
+     case (compareWord64# x# y#) of { LT -> y ; EQ -> x ; GT -> x }
+  min x@(W64# x#) y@(W64# y#) =
+     case (compareWord64# x# y#) of { LT -> x ; EQ -> x ; GT -> y }
+
+instance Num Word64 where
+  (W64# x) + (W64# y) = 
+      W64# (int64ToWord64# (word64ToInt64# x `plusInt64#` word64ToInt64# y))
+  (W64# x) - (W64# y) = 
+      W64# (int64ToWord64# (word64ToInt64# x `minusInt64#` word64ToInt64# y))
+  (W64# x) * (W64# y) = 
+      W64# (int64ToWord64# (word64ToInt64# x `timesInt64#` word64ToInt64# y))
+  negate w
+     | w == 0     = w
+     | otherwise  = maxBound - w
+
+  abs x         = x
+  signum        = signumReal
+  fromInteger i = integerToWord64 i
+  fromInt       = intToWord64
+
+instance Bounded Word64 where
+  minBound = 0
+  maxBound = minBound - 1
+
+instance Real Word64 where
+  toRational x = toInteger x % 1
+
+-- Note: no need to mask results here 
+-- as they cannot overflow.
+instance Integral Word64 where
+  div  (W64# x)  (W64# y)   = W64# (x `quotWord64#` y)
+  quot (W64# x)  (W64# y)   = W64# (x `quotWord64#` y)
+  rem  (W64# x)  (W64# y)   = W64# (x `remWord64#` y)
+  mod  (W64# x)  (W64# y)   = W64# (x `remWord64#` y)
+  quotRem (W64# x) (W64# y) = (W64# (x `quotWord64#` y), W64# (x `remWord64#` y))
+  divMod  (W64# x) (W64# y) = (W64# (x `quotWord64#` y), W64# (x `remWord64#` y))
+  toInteger w64             = word64ToInteger w64
+  toInt x                   = word64ToInt x
+
+
+instance Ix Word64 where
+    range (m,n)          = [m..n]
+    index b@(m,n) i
+          | inRange b i = word64ToInt (i-m)
+          | otherwise   = error (showString "Ix{Word64}.index: Index " .
+                                 showParen True (showsPrec 0 i) .
+                                  showString " out of range " $
+                                 showParen True (showsPrec 0 b) "")
+    inRange (m,n) i      = m <= i && i <= n
+
+instance Enum Word64 where
+    toEnum    (I# i)        = W64# (intToWord64# i)
+    fromEnum  (W64# w)      = I# (word2Int# (word64ToWord# w))  -- lossy, don't use.
+    enumFrom w              = eft64 w 1
+    enumFromTo   w1 w2      = eftt64 w1 1 (> w2)
+    enumFromThen w1 w2      = eftt64 w1 (w2 - w1) (>last)
+        where 
+        last
+         | w1 < w2   = maxBound::Word64
+         | otherwise = minBound
+
+instance Bits Word64 where
+  (W64# x)  .&.  (W64# y)    = W64# (x `and64#` y)
+  (W64# x)  .|.  (W64# y)    = W64# (x `or64#` y)
+  (W64# x) `xor` (W64# y)    = W64# (x `xor64#` y)
+  complement (W64# x)        = W64# (x `xor64#` (case (maxBound::Word64) of W64# x# -> x#))
+  shift (W64# x#) i@(I# i#)
+       | i > 0     = W64# (shiftL64# x# i#)
+       | otherwise = W64# (shiftRL64# x# (negateInt# i#))
+
+  w@(W64# x)  `rotate` (I# i)
+        | i ==# 0#    = w
+       | i ># 0#     = W64# ((shiftL64# x i') `or64#`
+                             (shiftRL64# (x `and64#` 
+                                          (int64ToWord64# ((word64ToInt64# maxBound#) `minusInt64#` 
+                                                          (pow2_64# i2 `plusInt64#` (intToInt64# 1#))))))
+                                    i2)
+       | otherwise = rotate w (I# (64# +# i))
+          where
+           i' = word2Int# (int2Word# i `and#` int2Word# 63#)
+           i2 = 64# -# i'
+           (W64# maxBound#) = maxBound
+
+  bit (I# i#)
+       | i# >=# 0# && i# <=# 63# = W64# (shiftL64# (wordToWord64# (int2Word# 1#)) i#)
+       | otherwise = 0 -- We'll be overbearing, for now..
+
+  setBit x i    = x .|. bit i
+  clearBit x i  = x .&. complement (bit i)
+  complementBit x i = x `xor` bit i
+
+  testBit (W64# x#) (I# i#)
+    | i# <# 64# && i# >=# 0# = (word2Int# (word64ToWord# (x# `and64#` (shiftL64# (wordToWord64# (int2Word# 1#)) i#)))) /=# 0#
+    | otherwise              = False -- for now, this is really an error.
+
+  bitSize  _    = 64
+  isSigned _    = False
+
+compareWord64# i# j# 
+ | i# `ltWord64#` j# = LT
+ | i# `eqWord64#` j# = EQ
+ | otherwise        = GT
+
+-- Word64# primop wrappers:
+
+ltWord64# :: Word64# -> Word64# -> Bool
+ltWord64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_ltWord64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+      
+leWord64# :: Word64# -> Word64# -> Bool
+leWord64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_leWord64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+      
+eqWord64# :: Word64# -> Word64# -> Bool
+eqWord64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_eqWord64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+      
+neWord64# :: Word64# -> Word64# -> Bool
+neWord64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_neWord64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+      
+geWord64# :: Word64# -> Word64# -> Bool
+geWord64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_geWord64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+      
+gtWord64# :: Word64# -> Word64# -> Bool
+gtWord64# x# y# =  unsafePerformIO $ do
+       v <- _ccall_ stg_gtWord64 x# y# 
+       case (v::Int) of
+         0 -> return False
+         _ -> return True
+
+plusInt64# :: Int64# -> Int64# -> Int64#
+plusInt64# a# b# = 
+  case (unsafePerformIO (_ccall_ stg_plusInt64 a# b#)) of
+    I64# i# -> i#
+
+minusInt64# :: Int64# -> Int64# -> Int64#
+minusInt64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_minusInt64 a# b#)) of
+    I64# i# -> i#
+
+timesInt64# :: Int64# -> Int64# -> Int64#
+timesInt64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_timesInt64 a# b#)) of
+    I64# i# -> i#
+
+quotWord64# :: Word64# -> Word64# -> Word64#
+quotWord64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_quotWord64 a# b#)) of
+    W64# w# -> w#
+
+remWord64# :: Word64# -> Word64# -> Word64#
+remWord64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_remWord64 a# b#)) of
+    W64# w# -> w#
+
+negateInt64# :: Int64# -> Int64#
+negateInt64# a# =
+  case (unsafePerformIO (_ccall_ stg_negateInt64 a#)) of
+    I64# i# -> i#
+
+and64# :: Word64# -> Word64# -> Word64#
+and64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_and64 a# b#)) of
+    W64# w# -> w#
+
+or64# :: Word64# -> Word64# -> Word64#
+or64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_or64 a# b#)) of
+    W64# w# -> w#
+
+xor64# :: Word64# -> Word64# -> Word64#
+xor64# a# b# = 
+  case (unsafePerformIO (_ccall_ stg_xor64 a# b#)) of
+    W64# w# -> w#
+
+not64# :: Word64# -> Word64#
+not64# a# = 
+  case (unsafePerformIO (_ccall_ stg_not64 a#)) of
+    W64# w# -> w#
+
+shiftL64# :: Word64# -> Int# -> Word64#
+shiftL64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_shiftL64 a# b#)) of
+    W64# w# -> w#
+
+shiftRL64# :: Word64# -> Int# -> Word64#
+shiftRL64# a# b# =
+  case (unsafePerformIO (_ccall_ stg_shiftRL64 a# b#)) of
+    W64# w# -> w#
+
+word64ToWord# :: Word64# -> Word#
+word64ToWord# w# =
+  case (unsafePerformIO (_ccall_ stg_word64ToWord w#)) of
+    W# w# -> w#
+      
+wordToWord64# :: Word# -> Word64#
+wordToWord64# w# =
+  case (unsafePerformIO (_ccall_ stg_wordToWord64 w#)) of
+    W64# w# -> w#
+
+word64ToInt64# :: Word64# -> Int64#
+word64ToInt64# w# =
+  case (unsafePerformIO (_ccall_ stg_word64ToInt64 w#)) of
+    I64# i# -> i#
+
+int64ToWord64# :: Int64# -> Word64#
+int64ToWord64# w# =
+  case (unsafePerformIO (_ccall_ stg_int64ToWord64 w#)) of
+    W64# w# -> w#
+
+intToInt64# :: Int# -> Int64#
+intToInt64# i# =
+  case (unsafePerformIO (_ccall_ stg_intToInt64 i#)) of
+    I64# i# -> i#
+      
 #endif
 
 sizeofWord64 :: Word32
 sizeofWord64 = 8
+
+-- Enum Word64 helper funs:
+
+eftt64 :: Word64 -> Word64 -> (Word64->Bool) -> [Word64]
+eftt64 now step done = go now
+  where
+   go now
+     | done now  = []
+     | otherwise = now : go (now+step)
+
+eft64 :: Word64 -> Word64 -> [Word64]
+eft64 now step = go now
+  where 
+   go x
+    | x == maxBound = [x]
+    | otherwise     = x:go (x+step)
 \end{code}
 
 
@@ -725,6 +1041,13 @@ wordToWord16 (W# w#)   = W16# (w# `and#` (case (maxBound::Word16) of W16# x# ->
 word32ToWord (W32# w#) = W# w#
 wordToWord32 (W# w#)   = W32# (w# `and#` (case (maxBound::Word32) of W32# x# -> x#))
 
+wordToWord64  :: Word -> Word64
+wordToWord64 (W# w#) = W64# (wordToWord64# w#)
+
+-- lossy on 32-bit platforms, but provided nontheless.
+word64ToWord :: Word64 -> Word
+word64ToWord (W64# w#) = W# (word64ToWord# w#)
+
 \end{code}
 
 
@@ -740,13 +1063,15 @@ signumReal x | x == 0    =  0
 
 \end{code}
 
-
 NOTE: the index is in units of the size of the type, *not* bytes.
 
 \begin{code}
 indexWord8OffAddr  :: Addr -> Int -> Word8
 indexWord8OffAddr (A# a#) (I# i#) = intToWord8 (I# (ord# (indexCharOffAddr# a# i#)))
 
+indexWord8OffForeignObj  :: ForeignObj -> Int -> Word8
+indexWord8OffForeignObj (ForeignObj fo#) (I# i#) = intToWord8 (I# (ord# (indexCharOffForeignObj# fo# i#)))
+
 indexWord16OffAddr :: Addr -> Int -> Word16
 indexWord16OffAddr a i =
 #ifdef WORDS_BIGENDIAN
@@ -759,6 +1084,18 @@ indexWord16OffAddr a i =
    l = indexWord8OffAddr a byte_idx
    h = indexWord8OffAddr a (byte_idx+1)
 
+indexWord16OffForeignObj :: ForeignObj -> Int -> Word16
+indexWord16OffForeignObj fo i =
+#ifdef WORDS_BIGENDIAN
+  intToWord16 ( word8ToInt l + (word8ToInt maxBound) * word8ToInt h)
+#else
+  intToWord16 ( word8ToInt h + (word8ToInt maxBound) * word8ToInt l)
+#endif
+ where
+   byte_idx = i * 2
+   l = indexWord8OffForeignObj fo byte_idx
+   h = indexWord8OffForeignObj fo (byte_idx+1)
+
 indexWord32OffAddr :: Addr -> Int -> Word32
 indexWord32OffAddr (A# a#) i = wordToWord32 (W# (indexWordOffAddr# a# i'#))
  where
@@ -770,12 +1107,31 @@ indexWord32OffAddr (A# a#) i = wordToWord32 (W# (indexWordOffAddr# a# i'#))
    = i
 #endif
 
+indexWord32OffForeignObj :: ForeignObj -> Int -> Word32
+indexWord32OffForeignObj (ForeignObj fo#) i = wordToWord32 (W# (indexWordOffForeignObj# fo# i'#))
+ where
+   -- adjust index to be in Word units, not Word32 ones.
+  (I# i'#) 
+#if WORD_SIZE_IN_BYTES==8
+   = i `div` 2
+#else
+   = i
+#endif
+
 indexWord64OffAddr :: Addr -> Int -> Word64
-indexWord64OffAddr (A# i#)
+indexWord64OffAddr (A# a#) (I# i#)
 #if WORD_SIZE_IN_BYTES==8
  = W64# (indexWordOffAddr# a# i#)
 #else
- = error "Word.indexWord64OffAddr: not implemented yet"
+ = W64# (indexWord64OffAddr# a# i#)
+#endif
+
+indexWord64OffForeignObj :: ForeignObj -> Int -> Word64
+indexWord64OffForeignObj (ForeignObj fo#) (I# i#)
+#if WORD_SIZE_IN_BYTES==8
+ = W64# (indexWordOffForeignObj# fo# i#)
+#else
+ = W64# (indexWord64OffForeignObj# fo# i#)
 #endif
 
 \end{code}
@@ -786,35 +1142,91 @@ Read words out of mutable memory:
 readWord8OffAddr :: Addr -> Int -> IO Word8
 readWord8OffAddr a i = _casm_ `` %r=(StgWord8)(((StgWord8*)%0)[(StgInt)%1]); '' a i
 
+readWord8OffForeignObj :: ForeignObj -> Int -> IO Word8
+readWord8OffForeignObj fo i = _casm_ `` %r=(StgWord8)(((StgWord8*)%0)[(StgInt)%1]); '' fo i
+
 readWord16OffAddr  :: Addr -> Int -> IO Word16
 readWord16OffAddr a i = _casm_ `` %r=(StgWord16)(((StgWord16*)%0)[(StgInt)%1]); '' a i
 
+readWord16OffForeignObj  :: ForeignObj -> Int -> IO Word16
+readWord16OffForeignObj fo i = _casm_ `` %r=(StgWord16)(((StgWord16*)%0)[(StgInt)%1]); '' fo i
+
 readWord32OffAddr  :: Addr -> Int -> IO Word32
 readWord32OffAddr a i = _casm_ `` %r=(StgWord32)(((StgWord32*)%0)[(StgInt)%1]); '' a i
 
+readWord32OffForeignObj  :: ForeignObj -> Int -> IO Word32
+readWord32OffForeignObj fo i = _casm_ `` %r=(StgWord32)(((StgWord32*)%0)[(StgInt)%1]); '' fo i
+
 readWord64OffAddr  :: Addr -> Int -> IO Word64
 #if WORD_SIZE_IN_BYTES==8
 readWord64OffAddr a i = _casm_ `` %r=(StgWord)(((StgWord*)%0)[(StgInt)%1]); '' a i
 #else
-readWord64OffAddr a i = error "Word.readWord64OffAddr: not implemented yet"
+readWord64OffAddr a i = _casm_ `` %r=(StgWord64)(((StgWord64*)%0)[(StgInt)%1]); '' a i
+#endif
+
+readWord64OffForeignObj  :: ForeignObj -> Int -> IO Word64
+#if WORD_SIZE_IN_BYTES==8
+readWord64OffForeignObj fo i = _casm_ `` %r=(StgWord)(((StgWord*)%0)[(StgInt)%1]); '' fo i
+#else
+readWord64OffForeignObj fo i = _casm_ `` %r=(StgWord64)(((StgWord64*)%0)[(StgInt)%1]); '' fo i
 #endif
 \end{code}
 
+Note: we provide primops for the writing via Addrs since that's used
+in the IO implementation (a place where we *really* do care about cycles.)
+
 \begin{code}
 writeWord8OffAddr  :: Addr -> Int -> Word8  -> IO ()
-writeWord8OffAddr a i e = _casm_ `` (((StgWord8*)%0)[(StgInt)%1])=(StgWord8)%2; '' a i e
+writeWord8OffAddr (A# a#) (I# i#) (W8# w#) = IO $ \ s# ->
+      case (writeCharOffAddr# a# i# (chr# (word2Int# w#)) s#) of s2# -> IOok s2# () 
 
 writeWord16OffAddr :: Addr -> Int -> Word16 -> IO ()
 writeWord16OffAddr a i e = _casm_ `` (((StgWord16*)%0)[(StgInt)%1])=(StgWord16)%2; '' a i e
 
 writeWord32OffAddr :: Addr -> Int -> Word32 -> IO ()
-writeWord32OffAddr a i e = _casm_ `` (((StgWord32*)%0)[(StgInt)%1])=(StgWord32)%2; '' a i e
+writeWord32OffAddr (A# a#) i@(I# i#) (W32# w#) = IO $ \ s# ->
+      case (writeWordOffAddr#  a# i'# w# s#) of s2# -> IOok s2# () 
+ where
+   -- adjust index to be in Word units, not Word32 ones.
+  (I# i'#) 
+#if WORD_SIZE_IN_BYTES==8
+   = i `div` 2
+#else
+   = i
+#endif
 
 writeWord64OffAddr :: Addr -> Int -> Word64 -> IO ()
 #if WORD_SIZE_IN_BYTES==8
-writeWord64OffAddr a i e = _casm_ `` (((StgWord*)%0)[(StgInt)%1])=(StgWord)%2; '' a i e
+writeWord64OffAddr (A# a#) (I# i#) (W64# w#) = IO $ \ s# ->
+      case (writeWordOffAddr#  a# i# w# s#) of s2# -> IOok s2# () 
+#else
+writeWord64OffAddr (A# a#) (I# i#) (W64# w#) = IO $ \ s# ->
+      case (writeWord64OffAddr#  a# i# w# s#) of s2# -> IOok s2# () 
+#endif
+
+writeWord8OffForeignObj  :: ForeignObj -> Int -> Word8  -> IO ()
+writeWord8OffForeignObj fo i w = _casm_ `` (((StgWord16*)%0)[(StgInt)%1])=(StgWord16)%2; '' fo i w
+
+writeWord16OffForeignObj :: ForeignObj -> Int -> Word16 -> IO ()
+writeWord16OffForeignObj fo i w = _casm_ `` (((StgWord16*)%0)[(StgInt)%1])=(StgWord16)%2; '' fo i w
+
+writeWord32OffForeignObj :: ForeignObj -> Int -> Word32 -> IO ()
+writeWord32OffForeignObj fo i w = _casm_ `` (((StgWord16*)%0)[(StgInt)%1])=(StgWord16)%2; '' fo i' w
+ where
+   -- adjust index to be in Word units, not Word32 ones.
+  i' 
+#if WORD_SIZE_IN_BYTES==8
+   = i `div` 2
+#else
+   = i
+#endif
+
+writeWord64OffForeignObj :: ForeignObj -> Int -> Word64 -> IO ()
+#if WORD_SIZE_IN_BYTES==8
+writeWord64OffForeignObj fo i e = _casm_ `` (((StgWord*)%0)[(StgInt)%1])=(StgWord)%2; '' fo i e
 #else
-writeWord64OffAddr = error "Word.writeWord64OffAddr: not implemented yet"
+writeWord64OffForeignObj fo i e = _casm_ `` (((StgWord64*)%0)[(StgInt)%1])=(StgWord64)%2; '' fo i e
 #endif
 
+
 \end{code}