Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -1029,11 +1029,10 @@ - (size_t)lowlevelReadIntoBuffer: (void*)buffer length: (size_t)length { ssize_t ret; - if (_fd == -1 || _atEndOfStream) @throw [OFReadFailedException exceptionWithObject: self requestedLength: length]; Index: src/OFSystemInfo.h ================================================================== --- src/OFSystemInfo.h +++ src/OFSystemInfo.h @@ -72,6 +72,78 @@ * On Haiku, it uses the `B_USER_SETTINGS_DIRECTORY` directory. * * @return The path where user configuration for the application can be stored */ + (OFString*)userConfigPath; + +/*! + * @brief Returns the vendor of the CPU. + * + * If the vendor could not be determined, nil is returned instead. + * + * @return The vendor of the CPU + */ ++ (OFString*)CPUVendor; + +/*! + * @brief Returns whether the CPU supports MMX. + * + * @return Whether the CPU supports MMX + */ ++ (bool)supportsMMX; + +/*! + * @brief Returns whether the CPU supports SSE. + * + * @return Whether the CPU supports SSE + */ ++ (bool)supportsSSE; + +/*! + * @brief Returns whether the CPU supports SSE2. + * + * @return Whether the CPU supports SSE2 + */ ++ (bool)supportsSSE2; + +/*! + * @brief Returns whether the CPU supports SSE3. + * + * @return Whether the CPU supports SSE3 + */ ++ (bool)supportsSSE3; + +/*! + * @brief Returns whether the CPU supports SSSE3. + * + * @return Whether the CPU supports SSSE3 + */ ++ (bool)supportsSSSE3; + +/*! + * @brief Returns whether the CPU supports SSE4.1. + * + * @return Whether the CPU supports SSE4.1 + */ ++ (bool)supportsSSE41; + +/*! + * @brief Returns whether the CPU supports SSE4.2. + * + * @return Whether the CPU supports SSE4.2 + */ ++ (bool)supportsSSE42; + +/*! + * @brief Returns whether the CPU supports AVX. + * + * @return Whether the CPU supports AVX + */ ++ (bool)supportsAVX; + +/*! + * @brief Returns whether the CPU supports AVX2. + * + * @return Whether the CPU supports AVX2 + */ ++ (bool)supportsAVX2; @end Index: src/OFSystemInfo.m ================================================================== --- src/OFSystemInfo.m +++ src/OFSystemInfo.m @@ -44,13 +44,35 @@ # include #endif #ifdef __QNX__ # include #endif + +struct cpuid_regs { + uint32_t eax, ebx, ecx, edx; +}; static size_t pageSize; static size_t numberOfCPUs; + +static OF_INLINE struct cpuid_regs OF_CONST_FUNC +cpuid(uint32_t eax, uint32_t ecx) +{ + struct cpuid_regs regs; + +#if defined(OF_X86_64_ASM) || defined(OF_X86_ASM) + __asm__( + "cpuid" + : "=a"(regs.eax), "=b"(regs.ebx), "=c"(regs.ecx), "=d"(regs.edx) + : "a"(eax), "c"(ecx) + ); +#else + regs.eax = regs.ebx = regs.ecx = regs.edx = 0; +#endif + + return regs; +} @implementation OFSystemInfo + (void)initialize { if (self != [OFSystemInfo class]) @@ -254,6 +276,68 @@ [var retain]; objc_autoreleasePoolPop(pool); return [var autorelease]; #endif } + ++ (OFString*)CPUVendor +{ + struct cpuid_regs regs = cpuid(0, 0); + char buffer[12]; + + if (regs.eax == 0) + return nil; + + memcpy(buffer, ®s.ebx, 4); + memcpy(buffer + 4, ®s.edx, 4); + memcpy(buffer + 8, ®s.ecx, 4); + + return [OFString stringWithCString: buffer + encoding: OF_STRING_ENCODING_ASCII + length: 12]; +} + ++ (bool)supportsMMX +{ + return (cpuid(1, 0).edx & (1 << 23)); +} + ++ (bool)supportsSSE +{ + return (cpuid(1, 0).edx & (1 << 25)); +} + ++ (bool)supportsSSE2 +{ + return (cpuid(1, 0).edx & (1 << 26)); +} + ++ (bool)supportsSSE3 +{ + return (cpuid(1, 0).ecx & (1 << 0)); +} + ++ (bool)supportsSSSE3 +{ + return (cpuid(1, 0).ecx & (1 << 9)); +} + ++ (bool)supportsSSE41 +{ + return (cpuid(1, 0).ecx & (1 << 19)); +} + ++ (bool)supportsSSE42 +{ + return (cpuid(1, 0).ecx & (1 << 20)); +} + ++ (bool)supportsAVX +{ + return (cpuid(1, 0).ecx & (1 << 28)); +} + ++ (bool)supportsAVX2 +{ + return cpuid(0, 0).eax >= 7 && (cpuid(7, 0).ebx & (1 << 5)); +} @end