winpr: add intrin.h

Exposing lzcnt in crt.h might causes compiler errors (redefinition) with
recent versions of gcc (>=4.9) when winpr is included in other projects.
As lzcnt isn't part of crt according to MSDN and also shouldn't be
exported by default it was moved to intrin.h.

The related test was also moved to the top level directory of winpr.
This commit is contained in:
Bernhard Miklautz 2015-05-26 16:41:29 +02:00
parent 83d5b26a46
commit f9c7e03044
8 changed files with 98 additions and 45 deletions

View File

@ -34,6 +34,7 @@
#include <winpr/print.h>
#include <winpr/sysinfo.h>
#include <winpr/bitstream.h>
#include <winpr/intrin.h>
#include "rfx_bitstream.h"

View File

@ -75,6 +75,10 @@ if(NOT ANDROID AND NOT IOS)
add_subdirectory(tools)
endif()
if(BUILD_TESTING)
add_subdirectory(test)
endif()
# Exporting
if(${CMAKE_VERSION} VERSION_GREATER "2.8.10")

View File

@ -95,50 +95,7 @@ static INLINE UINT16 _byteswap_ushort(UINT16 _val) {
#endif
/**
* __lzcnt16, __lzcnt, __lzcnt64:
* http://msdn.microsoft.com/en-us/library/bb384809/
*/
#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))
/**
* __lzcnt16, __lzcnt, __lzcnt64:
* http://msdn.microsoft.com/en-us/library/bb384809/
*
* Beware: the result of __builtin_clz(0) is undefined
*/
static INLINE UINT32 __lzcnt(UINT32 _val32) {
return _val32 ? ((UINT32) __builtin_clz(_val32)) : 32;
}
static INLINE UINT16 __lzcnt16(UINT16 _val16) {
return _val16 ? ((UINT16) (__builtin_clz((UINT32) _val16) - 16)) : 16;
}
#else
static INLINE UINT32 __lzcnt(UINT32 x) {
unsigned y;
int n = 32;
y = x >> 16; if (y != 0) { n = n - 16; x = y; }
y = x >> 8; if (y != 0) { n = n - 8; x = y; }
y = x >> 4; if (y != 0) { n = n - 4; x = y; }
y = x >> 2; if (y != 0) { n = n - 2; x = y; }
y = x >> 1; if (y != 0) return n - 2;
return n - x;
}
static INLINE UINT16 __lzcnt16(UINT16 x) {
return ((UINT16) __lzcnt((UINT32) x));
}
#endif
#endif
#ifndef _WIN32
#define CopyMemory(Destination, Source, Length) memcpy((Destination), (Source), (Length))
#define MoveMemory(Destination, Source, Length) memmove((Destination), (Source), (Length))

View File

@ -0,0 +1,66 @@
/**
* WinPR: Windows Portable Runtime
* C Run-Time Library Routines
*
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 Bernhard Miklautz <bernhard.miklautz@thincast.com>
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef WINPR_INTRIN_H
#define WINPR_INTRIN_H
#ifndef _WIN32
/**
* __lzcnt16, __lzcnt, __lzcnt64:
* http://msdn.microsoft.com/en-us/library/bb384809/
*
* Beware: the result of __builtin_clz(0) is undefined
*/
#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))
static INLINE UINT32 __lzcnt(UINT32 _val32) {
return ((UINT32) __builtin_clz(_val32));
}
static INLINE UINT16 __lzcnt16(UINT16 _val16) {
return ((UINT16) (__builtin_clz((UINT32) _val16) - 16));
}
#else /* (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2) */
static INLINE UINT32 __lzcnt(UINT32 x)
{
unsigned y;
int n = 32;
y = x >> 16; if (y != 0) { n = n - 16; x = y; }
y = x >> 8; if (y != 0) { n = n - 8; x = y; }
y = x >> 4; if (y != 0) { n = n - 4; x = y; }
y = x >> 2; if (y != 0) { n = n - 2; x = y; }
y = x >> 1; if (y != 0) return n - 2;
return n - x;
}
static INLINE UINT16 __lzcnt16(UINT16 x)
{
return ((UINT16) __lzcnt((UINT32) x));
}
#endif /* (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2) */
#endif /* _WIN32 */
#endif /* WINPR_INTRIN_H */

View File

@ -8,7 +8,6 @@ set(${MODULE_PREFIX}_TESTS
TestTypes.c
TestAlignment.c
TestString.c
TestIntrinsics.c
TestUnicodeConversion.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS

1
winpr/test/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
TestWinpr.c

24
winpr/test/CMakeLists.txt Normal file
View File

@ -0,0 +1,24 @@
set(MODULE_NAME "TestWinpr")
set(MODULE_PREFIX "TEST_WINPR")
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS TestIntrinsics.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}
${${MODULE_PREFIX}_TESTS})
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
target_link_libraries(${MODULE_NAME} winpr)
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Test")

View File

@ -1,8 +1,9 @@
#include <winpr/crt.h>
#include <winpr/sysinfo.h>
#include <winpr/windows.h>
#include <winpr/intrin.h>
static BOOL g_LZCNT = FALSE;
static INLINE UINT32 lzcnt_s(UINT32 x)