Commit 495711c2 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

ntdll: Fix export and calling convention of RtlUlonglongByteSwap().

The RtlU*ByteSwap() family: - has FASTCALL calling convention - is only exported from ntdll and ntoskrnl.exe in 32bit mode (didn't check ARM though) Wine's support for RtlUlonglongByteSwap() doesn't follow these constraints. Note: in __fastcall, 64bit paramaters are passed on the stack, to RtlUlonglongByteSwap() calling convention acts as __stdcall. So: - fix ntdll.spec (resp. ntoskrnl.exe.spec) to only export (resp. forward) RtlUlonglongByteSwap for i386 - always provide an inline implementation in winternl.h - reimplement ntdll.RtlUlonglongByteSwap() for i386 with __fastcall calling convention. - fix ntdll/tests/rtl.c to use correct calling convention. - add test in ntdll/tests/rtl.c for inlined version. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53536Signed-off-by: 's avatarEric Pouech <eric.pouech@gmail.com>
parent b7380acb
...@@ -1039,7 +1039,7 @@ ...@@ -1039,7 +1039,7 @@
@ stdcall RtlTryEnterCriticalSection(ptr) @ stdcall RtlTryEnterCriticalSection(ptr)
@ stdcall RtlUTF8ToUnicodeN(ptr long ptr ptr long) @ stdcall RtlUTF8ToUnicodeN(ptr long ptr ptr long)
@ cdecl -i386 -norelay RtlUlongByteSwap() NTDLL_RtlUlongByteSwap @ cdecl -i386 -norelay RtlUlongByteSwap() NTDLL_RtlUlongByteSwap
@ cdecl -ret64 RtlUlonglongByteSwap(int64) @ stdcall -fastcall -arch=i386 -norelay RtlUlonglongByteSwap(int64)
# @ stub RtlUnhandledExceptionFilter2 # @ stub RtlUnhandledExceptionFilter2
# @ stub RtlUnhandledExceptionFilter # @ stub RtlUnhandledExceptionFilter
@ stdcall RtlUnicodeStringToAnsiSize(ptr) @ stdcall RtlUnicodeStringToAnsiSize(ptr)
......
...@@ -641,10 +641,14 @@ DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen) ...@@ -641,10 +641,14 @@ DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen)
* RETURNS * RETURNS
* The value with its bytes swapped. * The value with its bytes swapped.
*/ */
ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG i) #ifdef __i386__
{ __ASM_FASTCALL_FUNC(RtlUlonglongByteSwap, 8,
return ((ULONGLONG)RtlUlongByteSwap(i) << 32) | RtlUlongByteSwap(i>>32); "movl 4(%esp),%edx\n\t"
} "bswap %edx\n\t"
"movl 8(%esp),%eax\n\t"
"bswap %eax\n\t"
"ret $8")
#endif
/************************************************************************* /*************************************************************************
* RtlUlongByteSwap [NTDLL.@] * RtlUlongByteSwap [NTDLL.@]
......
...@@ -68,7 +68,7 @@ static VOID (WINAPI *pRtlMoveMemory)(LPVOID,LPCVOID,SIZE_T); ...@@ -68,7 +68,7 @@ static VOID (WINAPI *pRtlMoveMemory)(LPVOID,LPCVOID,SIZE_T);
static VOID (WINAPI *pRtlFillMemory)(LPVOID,SIZE_T,BYTE); static VOID (WINAPI *pRtlFillMemory)(LPVOID,SIZE_T,BYTE);
static VOID (WINAPI *pRtlFillMemoryUlong)(LPVOID,SIZE_T,ULONG); static VOID (WINAPI *pRtlFillMemoryUlong)(LPVOID,SIZE_T,ULONG);
static VOID (WINAPI *pRtlZeroMemory)(LPVOID,SIZE_T); static VOID (WINAPI *pRtlZeroMemory)(LPVOID,SIZE_T);
static ULONGLONG (WINAPIV *pRtlUlonglongByteSwap)(ULONGLONG source); static ULONGLONG (FASTCALL *pRtlUlonglongByteSwap)(ULONGLONG source);
static DWORD (WINAPI *pRtlGetThreadErrorMode)(void); static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD); static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD);
static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG); static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG);
...@@ -319,18 +319,22 @@ static void test_RtlZeroMemory(void) ...@@ -319,18 +319,22 @@ static void test_RtlZeroMemory(void)
static void test_RtlUlonglongByteSwap(void) static void test_RtlUlonglongByteSwap(void)
{ {
ULONGLONG result; ULONGLONG llresult;
if ( !pRtlUlonglongByteSwap ) #ifdef _WIN64
/* the Rtl*ByteSwap() are always inlined and not exported from ntdll on 64bit */
llresult = RtlUlonglongByteSwap( 0x7654321087654321ull );
ok( 0x2143658710325476 == llresult,
"inlined RtlUlonglongByteSwap() returns %#I64x\n", llresult );
#else
ok( pRtlUlonglongByteSwap != NULL, "RtlUlonglongByteSwap is not available\n");
if ( pRtlUlonglongByteSwap )
{ {
win_skip("RtlUlonglongByteSwap is not available\n"); llresult = pRtlUlonglongByteSwap( 0x7654321087654321ull );
return; ok( 0x2143658710325476ull == llresult,
"ntdll.RtlUlonglongByteSwap() returns %#I64x\n", llresult );
} }
#endif
result = pRtlUlonglongByteSwap( ((ULONGLONG)0x76543210 << 32) | 0x87654321 );
ok( (((ULONGLONG)0x21436587 << 32) | 0x10325476) == result,
"RtlUlonglongByteSwap(0x7654321087654321) returns 0x%s, expected 0x2143658710325476\n",
wine_dbgstr_longlong(result));
} }
......
...@@ -2185,6 +2185,19 @@ LONG FASTCALL NTOSKRNL_InterlockedIncrement( LONG volatile *dest ) ...@@ -2185,6 +2185,19 @@ LONG FASTCALL NTOSKRNL_InterlockedIncrement( LONG volatile *dest )
return InterlockedIncrement( dest ); return InterlockedIncrement( dest );
} }
#ifdef __i386__
/*************************************************************************
* RtlUlonglongByteSwap (NTOSKRNL.EXE.@)
*/
__ASM_FASTCALL_FUNC(RtlUlonglongByteSwap, 8,
"movl 4(%esp),%edx\n\t"
"bswap %edx\n\t"
"movl 8(%esp),%eax\n\t"
"bswap %eax\n\t"
"ret $8")
#endif /* __i386__ */
/*********************************************************************** /***********************************************************************
* ExAllocatePool (NTOSKRNL.EXE.@) * ExAllocatePool (NTOSKRNL.EXE.@)
......
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
@ stdcall -fastcall ObfReferenceObject(ptr) @ stdcall -fastcall ObfReferenceObject(ptr)
@ stub RtlPrefetchMemoryNonTemporal @ stub RtlPrefetchMemoryNonTemporal
@ cdecl -i386 -norelay RtlUlongByteSwap() @ cdecl -i386 -norelay RtlUlongByteSwap()
@ cdecl -ret64 RtlUlonglongByteSwap(int64) @ stdcall -fastcall -arch=i386 -norelay RtlUlonglongByteSwap(int64)
@ cdecl -i386 -norelay RtlUshortByteSwap() @ cdecl -i386 -norelay RtlUshortByteSwap()
@ stub WmiGetClock @ stub WmiGetClock
@ stub Kei386EoiHelper @ stub Kei386EoiHelper
......
...@@ -4567,7 +4567,6 @@ NTSYSAPI BOOLEAN WINAPI RtlTryAcquireSRWLockExclusive(RTL_SRWLOCK *); ...@@ -4567,7 +4567,6 @@ NTSYSAPI BOOLEAN WINAPI RtlTryAcquireSRWLockExclusive(RTL_SRWLOCK *);
NTSYSAPI BOOLEAN WINAPI RtlTryAcquireSRWLockShared(RTL_SRWLOCK *); NTSYSAPI BOOLEAN WINAPI RtlTryAcquireSRWLockShared(RTL_SRWLOCK *);
NTSYSAPI BOOL WINAPI RtlTryEnterCriticalSection(RTL_CRITICAL_SECTION *); NTSYSAPI BOOL WINAPI RtlTryEnterCriticalSection(RTL_CRITICAL_SECTION *);
NTSYSAPI NTSTATUS WINAPI RtlUTF8ToUnicodeN(WCHAR*,DWORD,DWORD*,const char*,DWORD); NTSYSAPI NTSTATUS WINAPI RtlUTF8ToUnicodeN(WCHAR*,DWORD,DWORD*,const char*,DWORD);
NTSYSAPI ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG);
NTSYSAPI DWORD WINAPI RtlUnicodeStringToAnsiSize(const UNICODE_STRING*); NTSYSAPI DWORD WINAPI RtlUnicodeStringToAnsiSize(const UNICODE_STRING*);
NTSYSAPI NTSTATUS WINAPI RtlUnicodeStringToAnsiString(PANSI_STRING,PCUNICODE_STRING,BOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlUnicodeStringToAnsiString(PANSI_STRING,PCUNICODE_STRING,BOOLEAN);
NTSYSAPI NTSTATUS WINAPI RtlUnicodeStringToInteger(const UNICODE_STRING *,ULONG,ULONG *); NTSYSAPI NTSTATUS WINAPI RtlUnicodeStringToInteger(const UNICODE_STRING *,ULONG,ULONG *);
...@@ -4733,20 +4732,20 @@ static inline BOOLEAN RtlCheckBit(PCRTL_BITMAP lpBits, ULONG ulBit) ...@@ -4733,20 +4732,20 @@ static inline BOOLEAN RtlCheckBit(PCRTL_BITMAP lpBits, ULONG ulBit)
return FALSE; return FALSE;
} }
/* These are implemented as __fastcall, so we can't let Winelib apps link with them */ /* These are implemented as __fastcall, so we can't let Winelib apps link with them.
* Moreover, they're always inlined and not exported on 64bit systems.
*/
static inline USHORT RtlUshortByteSwap(USHORT s) static inline USHORT RtlUshortByteSwap(USHORT s)
{ {
return (s >> 8) | (s << 8); return (s >> 8) | (s << 8);
} }
static inline ULONG RtlUlongByteSwap(ULONG i) static inline ULONG RtlUlongByteSwap(ULONG i)
{ {
#if defined(__i386__) && defined(__GNUC__)
ULONG ret;
__asm__("bswap %0" : "=r" (ret) : "0" (i) );
return ret;
#else
return ((ULONG)RtlUshortByteSwap((USHORT)i) << 16) | RtlUshortByteSwap((USHORT)(i >> 16)); return ((ULONG)RtlUshortByteSwap((USHORT)i) << 16) | RtlUshortByteSwap((USHORT)(i >> 16));
#endif }
static inline ULONGLONG RtlUlonglongByteSwap(ULONGLONG i)
{
return ((ULONGLONG)RtlUlongByteSwap((ULONG)i) << 32) | RtlUlongByteSwap((ULONG)(i >> 32));
} }
/* list manipulation macros */ /* list manipulation macros */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment