cpu-0.1.2/0000755000000000000000000000000012240337201010461 5ustar0000000000000000cpu-0.1.2/LICENSE0000644000000000000000000000272412240337201011473 0ustar0000000000000000Copyright (c) 2012 Vincent Hanquez 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. cpu-0.1.2/cpu.cabal0000644000000000000000000000420512240337201012235 0ustar0000000000000000Name: cpu Version: 0.1.2 Description: Lowlevel cpu routines to get basic properties of the cpu platform, like endianness and architecture. License: BSD3 License-file: LICENSE Copyright: Vincent Hanquez Author: Vincent Hanquez Maintainer: Vincent Hanquez 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 Extra-source-files: cbits/endian.c 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 if impl(ghc < 7.8) 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 cpu-0.1.2/README.md0000644000000000000000000000027012240337201011737 0ustar0000000000000000Cpu haskell library =================== The library provides access to property and information helpers related to the cpu: * Endianness * Architecture * Cpuid (for x86 and x86\_64) cpu-0.1.2/Setup.hs0000644000000000000000000000005612240337201012116 0ustar0000000000000000import Distribution.Simple main = defaultMain cpu-0.1.2/System/0000755000000000000000000000000012240337201011745 5ustar0000000000000000cpu-0.1.2/System/Cpuid.hs0000644000000000000000000000241212240337201013344 0ustar0000000000000000{-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE CPP #-} -- | -- Module : System.Cpuid -- License : BSD-style -- Maintainer : Vincent Hanquez -- 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 cpu-0.1.2/System/Arch.hs0000644000000000000000000000253512240337201013163 0ustar0000000000000000{-# LANGUAGE CPP #-} -- | -- Module : System.Arch -- License : BSD-style -- Maintainer : Vincent Hanquez -- 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 cpu-0.1.2/System/Endian.hs0000644000000000000000000000733612240337201013510 0ustar0000000000000000{-# LANGUAGE CPP, ForeignFunctionInterface #-} -- | -- Module : System.Endian -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : unknown -- module System.Endian ( Endianness(..) , getSystemEndianness -- little endian to and from cpu , fromLE32 , fromLE64 , fromLE16 , toLE32 , toLE64 , toLE16 -- big endian to and from cpu , fromBE32 , fromBE64 , fromBE16 , toBE32 , toBE64 , toBE16 ) where #include "MachDeps.h" import Foreign.C.Types 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 #ifdef WORDS_BIGENDIAN getSystemEndianness = BigEndian #else getSystemEndianness = LittleEndian #endif -- | 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 from a big endian 16 bit value to the cpu endianness fromBE16 :: Word16 -> Word16 fromBE16 = if getSystemEndianness == BigEndian then id else swap16 -- | Convert from a little endian 16 bit value to the cpu endianness fromLE16 :: Word16 -> Word16 fromLE16 = if getSystemEndianness == LittleEndian then id else swap16 -- | 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 -- | Convert a 16 bit value in cpu endianness to big endian toBE16 :: Word16 -> Word16 toBE16 = fromBE16 -- | Convert a 16 bit value in cpu endianness to little endian toLE16 :: Word16 -> Word16 toLE16 = fromLE16 #if MIN_VERSION_base(4,7,0) -- | Transform a 16 bit value bytes from a.b to b.a swap16 :: Word16 -> Word16 swap16 = byteSwap16 -- | Transform a 32 bit value bytes from a.b.c.d to d.c.b.a swap32 :: Word32 -> Word32 swap32 = byteSwap32 -- | Transform a 64 bit value bytes from a.b.c.d.e.f.g.h to h.g.f.e.d.c.b.a swap64 :: Word64 -> Word64 swap64 = byteSwap64 #else -- | Transform a 16 bit value bytes from a.b to b.a {-# INLINE swap16 #-} swap16 :: Word16 -> Word16 swap16 = fromIntegral . c_swap16 . fromIntegral -- | 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 unsafe "bitfn_swap16" c_swap16 :: CUShort -> CUShort foreign import ccall unsafe "bitfn_swap32" c_swap32 :: CUInt -> CUInt foreign import ccall unsafe "bitfn_swap64" c_swap64 :: CULLong -> CULLong #endif cpu-0.1.2/cpuid/0000755000000000000000000000000012240337201011565 5ustar0000000000000000cpu-0.1.2/cpuid/Cpuid.hs0000644000000000000000000000064712240337201013174 0ustar0000000000000000module Main where import System.Environment import System.Cpuid import Text.Printf usage = do error "usage: cpuid [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 cpu-0.1.2/cbits/0000755000000000000000000000000012240337201011565 5ustar0000000000000000cpu-0.1.2/cbits/endian.c0000644000000000000000000000241612240337201013172 0ustar0000000000000000#include #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 uint16_t bitfn_swap16(uint16_t a) { return (a << 8) | (a >> 8); } cpu-0.1.2/cbits/cpuid.c0000644000000000000000000000075712240337201013046 0ustar0000000000000000#include 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" ); }