diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2012 Vincent Hanquez <vincent@snarc.org>
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the author nor the names of his contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+Cpu haskell library
+===================
+
+The library provides access to property and information helpers related to the cpu:
+
+* Endianness
+* Architecture
+* Cpuid (for x86 and x86\_64)
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/System/Arch.hs b/System/Arch.hs
new file mode 100644
--- /dev/null
+++ b/System/Arch.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE CPP #-}
+-- |
+-- Module      : System.Arch
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+module System.Arch
+    ( Arch(..)
+    , getSystemArch
+    ) where
+
+-- | List of all cpu architecture
+data Arch = X86
+          | X86_64
+          | PPC
+          | PPC64
+          | Sparc
+          | Arm
+          | Mips
+          | SH
+          | IA64
+          | S390
+          | Alpha
+          | Hppa
+          | Rs6000
+          | M68K
+          | VAX
+          deriving (Show,Eq)
+
+-- | Return the system's cpu architecture
+getSystemArch :: Arch
+#if defined(ARCH_X86)
+getSystemArch = X86
+#elif defined(ARCH_X86_64)
+getSystemArch = X86_64
+#elif defined(ARCH_PPC)
+getSystemArch = PPC
+#elif defined(ARCH_PPC64)
+getSystemArch = PPC64
+#elif defined(ARCH_SPARC)
+getSystemArch = Sparc
+#elif defined(ARCH_ARM)
+getSystemArch = Arm
+#elif defined(ARCH_MIPS)
+getSystemArch = Mips
+#elif defined(ARCH_SH)
+getSystemArch = SH
+#elif defined(ARCH_IA64)
+getSystemArch = IA64
+#elif defined(ARCH_S390)
+getSystemArch = S390
+#elif defined(ARCH_ALPHA)
+getSystemArch = Alpha
+#elif defined(ARCH_HPPA)
+getSystemArch = Hppa
+#elif defined(ARCH_RS6000)
+getSystemArch = Rs6000
+#elif defined(ARCH_M68K)
+getSystemArch = M68K
+#elif defined(ARCH_VAX)
+getSystemArch = VAX
+#else
+getSystemArch = undefined
+#endif
diff --git a/System/Cpuid.hs b/System/Cpuid.hs
new file mode 100644
--- /dev/null
+++ b/System/Cpuid.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE CPP #-}
+-- |
+-- Module      : System.Cpuid
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+module System.Cpuid
+    ( cpuidWithIndex
+    , cpuid
+    ) where
+
+import Data.Word
+import Control.Applicative
+import Foreign.C.Types
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.Marshal.Alloc
+
+#if defined(ARCH_X86) || defined(ARCH_X86_64)
+
+foreign import ccall safe "cpuid" c_cpuid :: CUInt -> CUInt -> Ptr CUInt -> IO ()
+
+-- | complete cpuid call with eax and ecx set.
+cpuidWithIndex :: Word32 -> Word32 -> IO (Word32, Word32, Word32, Word32)
+cpuidWithIndex eax ecx = allocaBytes 16 $ \ptr -> do
+    c_cpuid (fromIntegral eax) (fromIntegral ecx) ptr
+    (,,,) <$> peekW32 ptr <*> peekW32 (ptr `plusPtr` 4) <*> peekW32 (ptr `plusPtr` 8) <*> peekW32 (ptr `plusPtr` 12)
+    where peekW32 :: Ptr CUInt -> IO Word32
+          peekW32 ptr = fromIntegral <$> peek ptr
+
+#else
+
+cpuidWithIndex :: Word32 -> Word32 -> IO (Word32, Word32, Word32, Word32)
+cpuidWithIndex _ _ = error "cpuid is not supported on non-x86 architecture"
+
+#endif
+
+-- | simple cpuid call.
+cpuid :: Word32 -> IO (Word32, Word32, Word32, Word32)
+cpuid eax = cpuidWithIndex eax 0
diff --git a/System/Endian.hs b/System/Endian.hs
new file mode 100644
--- /dev/null
+++ b/System/Endian.hs
@@ -0,0 +1,95 @@
+{-# LANGUAGE CPP, ForeignFunctionInterface #-}
+-- |
+-- Module      : System.Endian
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+module System.Endian
+    ( Endianness(..)
+    , getSystemEndianness
+    -- little endian to and from cpu
+    , fromLE32
+    , fromLE64
+    , toLE32
+    , toLE64
+    -- big endian to and from cpu
+    , fromBE32
+    , fromBE64
+    , toBE32
+    , toBE64
+    ) where
+
+import Foreign.Marshal.Alloc
+import Foreign.Storable
+import Foreign.Ptr
+import Foreign.C.Types
+import System.IO.Unsafe (unsafePerformIO)
+import Data.Word
+
+-- | represent the CPU endianness
+--
+-- Big endian system stores bytes with the MSB as the first byte.
+-- Little endian system stores bytes with the LSB as the first byte.
+--
+-- middle endian is purposely avoided.
+data Endianness = LittleEndian
+                | BigEndian
+                deriving (Show,Eq)
+
+-- | return the system endianness
+getSystemEndianness :: Endianness
+getSystemEndianness = unsafePerformIO $ alloca $ \p ->
+    poke p cst >> peek (castPtr p) >>= return . check
+    where cst :: Word32
+          cst = 0x01000000
+          check :: Word8 -> Endianness
+          check x
+              | x == 0x01 = BigEndian 
+              | otherwise = LittleEndian
+
+-- | Convert from a big endian 64 bit value to the cpu endianness
+fromBE64 :: Word64 -> Word64
+fromBE64 = if getSystemEndianness == BigEndian then id else swap64
+
+-- | Convert from a little endian 64 bit value to the cpu endianness
+fromLE64 :: Word64 -> Word64
+fromLE64 = if getSystemEndianness == LittleEndian then id else swap64
+
+-- | Convert from a big endian 32 bit value to the cpu endianness
+fromBE32 :: Word32 -> Word32
+fromBE32 = if getSystemEndianness == BigEndian then id else swap32
+
+-- | Convert from a little endian 32 bit value to the cpu endianness
+fromLE32 :: Word32 -> Word32
+fromLE32 = if getSystemEndianness == LittleEndian then id else swap32
+
+-- | Convert a 64 bit value in cpu endianess to big endian
+toBE64 :: Word64 -> Word64
+toBE64 = fromBE64
+
+-- | Convert a 64 bit value in cpu endianess to little endian
+toLE64 :: Word64 -> Word64
+toLE64 = fromLE64
+
+-- | Convert a 32 bit value in cpu endianess to big endian
+toBE32 :: Word32 -> Word32
+toBE32 = fromBE32
+
+-- | Convert a 32 bit value in cpu endianess to little endian
+toLE32 :: Word32 -> Word32
+toLE32 = fromLE32
+
+-- | Transform a 32 bit value bytes from a.b.c.d to d.c.b.a
+{-# INLINE swap32 #-}
+swap32 :: Word32 -> Word32
+swap32 = fromIntegral . c_swap32 . fromIntegral
+
+-- | Transform a 64 bit value bytes from a.b.c.d.e.f.g.h to h.g.f.e.d.c.b.a
+{-# INLINE swap64 #-}
+swap64 :: Word64 -> Word64
+swap64 = fromIntegral . c_swap64 . fromIntegral
+
+foreign import ccall safe "bitfn_swap32" c_swap32 :: CUInt -> CUInt
+foreign import ccall safe "bitfn_swap64" c_swap64 :: CULLong -> CULLong
diff --git a/cbits/cpuid.c b/cbits/cpuid.c
new file mode 100644
--- /dev/null
+++ b/cbits/cpuid.c
@@ -0,0 +1,29 @@
+#include <stdint.h>
+
+void cpuid(uint32_t eax, uint32_t ecx, uint32_t regs[4])
+{
+	asm volatile (
+#ifdef __i386__
+		"push %%ebx\n\t"
+		"push %%edx\n\t"
+#else
+		"push %%rbx\n\t"
+		"push %%rdx\n\t"
+#endif
+		"cpuid\n\t"
+		"mov %%eax,(%4)\n\t"
+		"mov %%ebx,4(%4)\n\t"
+		"mov %%ecx,8(%4)\n\t"
+		"mov %%edx,12(%4)\n\t"
+#ifdef __i386__
+		"pop %%edx\n\t"
+		"pop %%ebx\n\t"
+#else
+		"pop %%rdx\n\t"
+		"pop %%rbx\n\t"
+#endif
+		: "=a" (eax), "=c" (ecx)
+		: "0" (eax), "1" (ecx), "S" (regs)
+		: "memory"
+	);
+}
diff --git a/cbits/endian.c b/cbits/endian.c
new file mode 100644
--- /dev/null
+++ b/cbits/endian.c
@@ -0,0 +1,54 @@
+#include <stdint.h>
+
+#if (defined(__i386__))
+#  define ARCH_HAS_SWAP32
+uint32_t bitfn_swap32(uint32_t a)
+{
+	asm ("bswap %0" : "=r" (a) : "0" (a));
+	return a;
+}
+/**********************************************************/
+# elif (defined(__arm__))
+#  define ARCH_HAS_SWAP32
+uint32_t bitfn_swap32(uint32_t a)
+{
+	uint32_t tmp = a;
+	asm volatile ("eor %1, %0, %0, ror #16\n"
+	              "bic %1, %1, #0xff0000\n"
+	              "mov %0, %0, ror #8\n"
+	              "eor %0, %0, %1, lsr #8\n"
+	              : "=r" (a), "=r" (tmp) : "0" (a), "1" (tmp));
+	return a;
+}
+/**********************************************************/
+# elif defined(__x86_64__)
+#  define ARCH_HAS_SWAP32
+#  define ARCH_HAS_SWAP64
+uint32_t bitfn_swap32(uint32_t a)
+{
+	asm ("bswap %0" : "=r" (a) : "0" (a));
+	return a;
+}
+
+uint64_t bitfn_swap64(uint64_t a)
+{
+	asm ("bswap %0" : "=r" (a) : "0" (a));
+	return a;
+}
+
+# endif
+
+#ifndef ARCH_HAS_SWAP32
+uint32_t bitfn_swap32(uint32_t a)
+{
+	return (a << 24) | ((a & 0xff00) << 8) | ((a >> 8) & 0xff00) | (a >> 24);
+}
+#endif
+
+#ifndef ARCH_HAS_SWAP64
+uint64_t bitfn_swap64(uint64_t a)
+{
+	return ((uint64_t) bitfn_swap32((uint32_t) (a >> 32))) |
+	        (((uint64_t) bitfn_swap32((uint32_t) a)) << 32);
+}
+#endif
diff --git a/cpu.cabal b/cpu.cabal
new file mode 100644
--- /dev/null
+++ b/cpu.cabal
@@ -0,0 +1,79 @@
+Name:                cpu
+Version:             0.1.0
+Description:         
+    Lowlevel cpu routines to get basic properties of the cpu platform, like endianness and architecture.
+License:             BSD3
+License-file:        LICENSE
+Copyright:           Vincent Hanquez <vincent@snarc.org>
+Author:              Vincent Hanquez <vincent@snarc.org>
+Maintainer:          Vincent Hanquez <vincent@snarc.org>
+Synopsis:            Cpu information and properties helpers.
+Build-Type:          Simple
+Category:            Data
+stability:           experimental
+Cabal-Version:       >=1.8
+Homepage:            http://github.com/vincenthz/hs-cpu
+data-files:          README.md
+
+Flag executable
+  Description:       Build the executable
+  Default:           False
+
+Library
+  Build-Depends:     base >= 3 && < 5
+  Exposed-modules:   System.Cpuid
+                     System.Endian
+                     System.Arch
+  ghc-options:       -Wall
+
+  C-sources:   cbits/endian.c
+
+  if arch(i386)
+    Cpp-options: -DARCH_X86
+  if arch(x86_64)
+    Cpp-options: -DARCH_X86_64
+  if arch(ppc)
+    Cpp-options: -DARCH_PPC
+  if arch(ppc64)
+    Cpp-options: -DARCH_PPC64
+  if arch(sparc)
+    Cpp-options: -DARCH_SPARC
+  if arch(arm)
+    Cpp-options: -DARCH_ARM
+  if arch(mips)
+    Cpp-options: -DARCH_MIPS
+  if arch(sh)
+    Cpp-options: -DARCH_SH
+  if arch(ia64)
+    Cpp-options: -DARCH_IA64
+  if arch(s390)
+    Cpp-options: -DARCH_S390
+  if arch(alpha)
+    Cpp-options: -DARCH_ALPHA
+  if arch(hppa)
+    Cpp-options: -DARCH_HPPA
+  if arch(rs6000)
+    Cpp-options: -DARCH_RS6000
+  if arch(m68k)
+    Cpp-options: -DARCH_M68K
+  if arch(vax)
+    Cpp-options: -DARCH_VAX
+
+  if arch(i386) || arch(x86_64)
+    C-sources:   cbits/cpuid.c
+
+executable           cpuid
+  hs-source-dirs:    cpuid
+  Main-is:           Cpuid.hs
+  if flag(executable)
+    Buildable:       True
+    Build-Depends:   base >= 3 && < 5
+                   , cpu
+                   , bytestring
+  else
+    Buildable:       False
+  ghc-options:       -Wall -fno-warn-orphans -fno-warn-missing-signatures
+
+source-repository head
+  type: git
+  location: git://github.com/vincenthz/hs-cpu
diff --git a/cpuid/Cpuid.hs b/cpuid/Cpuid.hs
new file mode 100644
--- /dev/null
+++ b/cpuid/Cpuid.hs
@@ -0,0 +1,18 @@
+module Main where
+
+import System.Environment
+import System.Cpuid
+import Text.Printf
+
+usage = do
+    error "usage: cpuid <eax> [ecx]"
+
+printResult (eax,ebx,ecx,edx) = do
+    printf "%.8x %.8x %.8x %.8x\n" eax ebx ecx edx
+
+main = do
+    args <- getArgs
+    case args of
+        []        -> usage
+        eax:[]    -> cpuid (read eax) >>= printResult
+        eax:ecx:_ -> cpuidWithIndex (read eax) (read ecx) >>= printResult
