Author: tkreuzer Date: Wed Jan 6 01:39:07 2010 New Revision: 44970
URL: http://svn.reactos.org/svn/reactos?rev=44970&view=rev Log: [RTL] Merge from amd64 branch 35738,37004,37308,37324,37330,37331,37332,37370,37419,37424,37425,37428,37473,37492,37844,37911,37987,40604,41006,43686,43951,43953,43980,43993,44001,44289,44295,44296,44428,44966,44967,44968
- Implement amd64 specific RTL functions: RtlLookupFunctionTable, RtlLookupFunctionEntry, RtlCaptureContext, RtlVirtualUnwind, RtlWalkFrameChain, RtlGetCallersAddress, RtlRaiseException (Timo Kreuzer) - Implement amd64 asm functions: RtlCompareMemory, DebugService, RtlInterlockedPopEntrySList, RtlInterlockedPushEntrySList and RtlInterlockedFlushSList (Timo Kreuzer) - Don't use double in rtl's sprintf / swprintf, use double_t union instead. (Stefan Ginsberg)
Added: trunk/reactos/lib/rtl/amd64/ (with props) trunk/reactos/lib/rtl/amd64/debug_asm.S (with props) trunk/reactos/lib/rtl/amd64/except_asm.S (with props) trunk/reactos/lib/rtl/amd64/rtlmem.S (with props) trunk/reactos/lib/rtl/amd64/slist.S (with props) trunk/reactos/lib/rtl/amd64/stubs.c (with props) trunk/reactos/lib/rtl/amd64/unwind.c (with props) Modified: trunk/reactos/lib/rtl/exception.c trunk/reactos/lib/rtl/rtl.rbuild trunk/reactos/lib/rtl/rtlp.h trunk/reactos/lib/rtl/slist.c trunk/reactos/lib/rtl/sprintf.c trunk/reactos/lib/rtl/swprintf.c
Propchange: trunk/reactos/lib/rtl/amd64/ ------------------------------------------------------------------------------ --- bugtraq:logregex (added) +++ bugtraq:logregex Wed Jan 6 01:39:07 2010 @@ -1,0 +1,2 @@ +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+)
Propchange: trunk/reactos/lib/rtl/amd64/ ------------------------------------------------------------------------------ bugtraq:message = See issue #%BUGID% for more details.
Propchange: trunk/reactos/lib/rtl/amd64/ ------------------------------------------------------------------------------ bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%
Propchange: trunk/reactos/lib/rtl/amd64/ ------------------------------------------------------------------------------ tsvn:logminsize = 10
Added: trunk/reactos/lib/rtl/amd64/debug_asm.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/amd64/debug_asm.S?r... ============================================================================== --- trunk/reactos/lib/rtl/amd64/debug_asm.S (added) +++ trunk/reactos/lib/rtl/amd64/debug_asm.S [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -1,0 +1,79 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Run-Time Library + * PURPOSE: Debug Routines + * FILE: lib/rtl/i386/debug.S + * PROGRAMER: Alex Ionescu (alex@relsoft.net) + */ + +.intel_syntax noprefix + +/* GLOBALS ****************************************************************/ + +.globl _DbgBreakPoint +.globl _DbgBreakPointWithStatus +.globl _DbgUserBreakPoint +.globl _DebugService +.globl _DebugService2 +.globl _DbgBreakPointNoBugCheck +.globl _RtlpBreakWithStatusInstruction + +/* FUNCTIONS ***************************************************************/ + +.func DbgBreakPointNoBugCheck +_DbgBreakPointNoBugCheck: + int 3 + ret +.endfunc + +.func DbgBreakPoint +_DbgBreakPoint: +_DbgUserBreakPoint: + int 3 + ret +.endfunc + +.func DbgBreakPointWithStatus +_DbgBreakPointWithStatus: + mov eax, ecx + +_RtlpBreakWithStatusInstruction: + int 3 + ret +.endfunc + +.func DebugService2 +_DebugService2: + ret + /* Call the interrupt */ +// mov eax, [rbp+8] +// int 0x2D +// int 3 + +.endfunc + +/****************************************************************************** + * NTSTATUS NTAPI DebugService( + * IN ULONG Service, // <rcx> = [rsp + 8] + * IN PVOID Buffer, // <rdx> = [rsp + 16] + * IN ULONG Length, // <r8> = [rsp + 24] + * IN PVOID Argument1, // <r9> = [rsp + 32] + * IN PVOID Argument2); // [rsp + 40] + */ +.func DebugService +_DebugService: + + /* Prepare registers for interrupt */ + mov eax, ecx // Service + mov rcx, rdx // Buffer + mov edx, r8d // Length + mov r8, r9 // Argument1 + mov r9, [rsp + 40] // Argument2 + + /* Call the Interrupt */ + int 0x2D + int 3 + + /* Return */ + ret +.endfunc
Propchange: trunk/reactos/lib/rtl/amd64/debug_asm.S ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/lib/rtl/amd64/except_asm.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/amd64/except_asm.S?... ============================================================================== --- trunk/reactos/lib/rtl/amd64/except_asm.S (added) +++ trunk/reactos/lib/rtl/amd64/except_asm.S [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -1,0 +1,100 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Runtime Library (RTL) + * FILE: lib/rtl/amd64/except_asm.S + * PURPOSE: Exception support for AMD64 + * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include <ndk/asm.h> +.intel_syntax noprefix + +/* FUNCTIONS *****************************************************************/ + +/* + * VOID NTAPI + * RtlCaptureContext( + * PCONTEXT ContextRecord); <rcx> + */ +.func RtlCaptureContext +.global _RtlCaptureContext +_RtlCaptureContext: + .cfi_startproc + + /* Push rflags */ + pushfq + .cfi_adjust_cfa_offset 8 + + /* Save the basic register context */ + mov [rcx + CONTEXT_Rax], rax + mov [rcx + CONTEXT_Rcx], rcx + mov [rcx + CONTEXT_Rdx], rdx + + /* Load rflags into rax */ + mov rax, [rsp] + + mov [rcx + CONTEXT_Rbx], rbx + mov [rcx + CONTEXT_Rsi], rsi + mov [rcx + CONTEXT_Rdi], rdi + + /* Store rflags */ + mov [rcx + CONTEXT_EFlags], rax + + mov [rcx + CONTEXT_Rbp], rbp + mov [rcx + CONTEXT_R8], r8 + mov [rcx + CONTEXT_R9], r9 + + /* Load former stack pointer in rax */ + lea rax, [rsp + 0x10] + + mov [rcx + CONTEXT_R10], r10 + mov [rcx + CONTEXT_R11], r11 + mov [rcx + CONTEXT_R12], r12 + + /* Store stack pointer */ + mov [rcx + CONTEXT_Rsp], rax + + mov [rcx + CONTEXT_R13], r13 + mov [rcx + CONTEXT_R14], r14 + mov [rcx + CONTEXT_R15], r15 + + /* Load return address in rax */ + mov rax, [rsp + 8] + + /* Safe segment selectors */ + mov [rcx + CONTEXT_SegCs], cs + mov [rcx + CONTEXT_SegDs], ds + mov [rcx + CONTEXT_SegEs], es + mov [rcx + CONTEXT_SegFs], fs + mov [rcx + CONTEXT_SegGs], gs + mov [rcx + CONTEXT_SegSs], ss + + /* Store return address */ + mov [rcx + CONTEXT_Rip], rax + + /* Safe xmm registers */ + movdqa [rcx + CONTEXT_Xmm0], xmm0 + movdqa [rcx + CONTEXT_Xmm1], xmm1 + movdqa [rcx + CONTEXT_Xmm2], xmm2 + movdqa [rcx + CONTEXT_Xmm3], xmm3 + movdqa [rcx + CONTEXT_Xmm4], xmm4 + movdqa [rcx + CONTEXT_Xmm5], xmm5 + movdqa [rcx + CONTEXT_Xmm6], xmm6 + movdqa [rcx + CONTEXT_Xmm7], xmm7 + movdqa [rcx + CONTEXT_Xmm8], xmm8 + movdqa [rcx + CONTEXT_Xmm9], xmm9 + movdqa [rcx + CONTEXT_Xmm10], xmm10 + movdqa [rcx + CONTEXT_Xmm11], xmm11 + movdqa [rcx + CONTEXT_Xmm12], xmm12 + movdqa [rcx + CONTEXT_Xmm13], xmm13 + movdqa [rcx + CONTEXT_Xmm14], xmm14 + movdqa [rcx + CONTEXT_Xmm15], xmm15 + + /* Cleanup stack and return */ + add rsp, 8 + ret + .cfi_endproc +.endfunc +
Propchange: trunk/reactos/lib/rtl/amd64/except_asm.S ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/lib/rtl/amd64/rtlmem.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/amd64/rtlmem.S?rev=... ============================================================================== --- trunk/reactos/lib/rtl/amd64/rtlmem.S (added) +++ trunk/reactos/lib/rtl/amd64/rtlmem.S [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -1,0 +1,78 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Run-Time Library + * PURPOSE: Memory functions for amd64 + * FILE: lib/rtl/i386/rtlswap.S + * PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include <ndk/amd64/asmmacro.S> + +/* FUNCTIONS *****************************************************************/ +.intel_syntax noprefix + +/* SIZE_T + * RtlCompareMemory( + * IN CONST VOID *Source1, <rcx> + * IN CONST VOID *Source2, <rdx> + * IN SIZE_T Length <r8> + * ); + */ +.proc RtlCompareMemory + + /* Save registers */ + push rsi + .pushreg rsi + push rdi + .pushreg rdi + + /* Setup registers for compare */ + mov rsi, rcx + mov rdi, rdx + + /* Clear direction flag */ + cli + + /* Get number of qwords */ + mov rcx, r8 + shr rcx, 3 + jz 2f + + /* Compare qwords */ + repe cmpsq + jnz 4f + +2: /* Compare rest */ + mov rcx, r8 + and rcx, 7 + jz 3f + + repe cmpsb + jnz 5f + +3: /* All equal */ + /* Return the full count */ + mov rax, rcx + jmp 6f + +4: /* Not equal after comparing qwords */ + /* Compare the last qword */ + sub rsi, 8 + sub rdi, 8 + mov rcx, 8 + repe cmpsb + +5: /* Not equal after comparing bytes */ + /* Return difference */ + sub rdi, rdx + dec rdi + mov rax, rdi + +6: /* Cleanup and return */ + pop rdi + pop rsi + ret +.endproc +
Propchange: trunk/reactos/lib/rtl/amd64/rtlmem.S ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/lib/rtl/amd64/slist.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/amd64/slist.S?rev=4... ============================================================================== --- trunk/reactos/lib/rtl/amd64/slist.S (added) +++ trunk/reactos/lib/rtl/amd64/slist.S [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -1,0 +1,343 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/rtl/amd64/interlck.S + * PURPOSE: Rtl Interlocked Functions for amd64 + * PROGRAMMERS: Timo Kreuzer + */ + +#include <ndk/asm.h> +#include <ndk/amd64/asmmacro.S> +.intel_syntax noprefix + +#define SLIST8A_DEPTH_MASK 0x000000000000FFFF +#define SLIST8A_DEPTH_INC 0x0000000000000001 +#define SLIST8A_SEQUENCE_MASK 0x0000000001FF0000 +#define SLIST8A_SEQUENCE_INC 0x0000000000010000 +#define SLIST8A_NEXTENTRY_MASK 0xFFFFFFFFFE000000 +#define SLIST8A_NEXTENTRY_SHIFT 21 +#define SLIST8B_HEADERTYPE_MASK 0x0000000000000001 +#define SLIST8B_INIT_MASK 0x0000000000000002 +#define SLIST8B_REGION_MASK 0xE000000000000000 +#define SLIST8_POINTER_MASK 0x000007FFFFFFFFF0 + +#define SLIST16A_DEPTH_MASK 0x000000000000FFFF +#define SLIST16A_DEPTH_INC 0x0000000000000001 +#define SLIST16A_SEQUENCE_MASK 0xFFFFFFFFFFFF0000 +#define SLIST16A_SEQUENCE_INC 0x0000000000010000 +#define SLIST16B_HEADERTYPE_MASK 0x0000000000000001 +#define SLIST16B_INIT_MASK 0x0000000000000002 +#define SLIST16B_NEXTENTY_MASK 0xFFFFFFFFFFFFFFF0 + + +/* FUNCTIONS ****************************************************************/ + +.global _ExpInterlockedPopEntrySList +.global _ExpInterlockedPopEntrySListResume +.global _ExpInterlockedPopEntrySListFault +.global _ExpInterlockedPopEntrySListEnd +.global _ExpInterlockedPopEntrySListResume16 +.global _ExpInterlockedPopEntrySListFault16 +.global _ExpInterlockedPopEntrySListEnd16 +.global _ExpInterlockedPushEntrySList +.global _ExpInterlockedFlushSList + +/* PSLIST_ENTRY + * NTAPI + * RtlInterlockedPopEntrySList( + * IN PSLIST_HEADER ListHead); + */ +.proc RtlInterlockedPopEntrySList +_ExpInterlockedPopEntrySList: + + /* Load ListHead->Region into rdx */ + mov rdx, [rcx + 8] + + /* Load ListHead->Alignment into rax */ + mov rax, [rcx] + + /* Check what kind of header this is */ + test rdx, SLIST8B_HEADERTYPE_MASK + jnz _RtlInterlockedPopEntrySList16 + + /* We have an 8 byte header */ + +_ExpInterlockedPopEntrySListResume: + + /* Check if ListHead->NextEntry is NULL */ + mov r9, rax + and r9, SLIST8A_NEXTENTRY_MASK + jz _RtlInterlockedPopEntrySListEmpty + + /* Copy Depth and Sequence number and adjust Depth */ + lea r8, [rax - SLIST8A_DEPTH_INC] + and r8, SLIST8A_SEQUENCE_MASK | SLIST8A_DEPTH_MASK + + /* Create a pointer template from rcx in rdx */ + mov rdx, ~SLIST8_POINTER_MASK + and rdx, rcx + + /* Shift the NextEntry pointer */ + shr r9, SLIST8A_NEXTENTRY_SHIFT + + /* Combine to new pointer in rdx */ + or rdx, r9 + +_ExpInterlockedPopEntrySListFault: + + /* Load the next NextEntry pointer to r9 */ + mov r9, [rdx] + + /* Shift bits in place */ + shl r9, SLIST8A_NEXTENTRY_SHIFT + + /* Combine into r8 */ + or r8, r9 + +_ExpInterlockedPopEntrySListEnd: + + /* If [rcx] equals rax, exchange it with r8 */ + lock cmpxchg [rcx], r8 + + /* If not equal, retry with rax, being the content of [rcx] now */ + jnz _ExpInterlockedPopEntrySListResume + + /* Shift the pointer bits in place */ + and rax, SLIST8A_NEXTENTRY_MASK + shr rax, SLIST8A_NEXTENTRY_SHIFT + + /* Use rcx as pointer template */ + mov rdx, ~SLIST8_POINTER_MASK + and rdx, rcx + + /* Combine result and return */ + or rax, rdx + ret + +_RtlInterlockedPopEntrySListEmpty: + xor rax, rax + ret + +_RtlInterlockedPopEntrySList16: + /* This is a 16 byte header */ + + /* Save rbx */ + push rbx + + /* Copy rcx to r8, as we need rcx for the exchange */ + mov r8, rcx + +_ExpInterlockedPopEntrySListResume16: + + /* Check if ListHead->NextEntry is NULL */ + mov r9, rdx + and r9, SLIST16B_NEXTENTY_MASK + jz _RtlInterlockedPopEntrySListEmpty16 + +_ExpInterlockedPopEntrySListFault16: + + /* Get next pointer */ + mov rcx, [r9] + + /* Set ListHead->HeaderType = 1 and ListHead->Init = 1 */ + or rcx, 0x3 + + /* Copy Depth and Sequence number and adjust Depth */ + lea rbx, [rax - SLIST16A_DEPTH_INC] + +_ExpInterlockedPopEntrySListEnd16: + + /* If [r8] equals rdx:rax, exchange it with rcx:rbx */ + lock cmpxchg16b [r8] + + /* If not equal, retry with rdx:rax, being the content of [r8] now */ + jnz _ExpInterlockedPopEntrySListResume16 + + /* Copy the old NextEntry pointer to rax */ + mov rax, rdx + and rax, SLIST16B_NEXTENTY_MASK + + /* Return */ + pop rbx + ret + +_RtlInterlockedPopEntrySListEmpty16: + xor rax, rax + pop rbx + ret + +.endproc + + +/* PSLIST_ENTRY + * NTAPI + * RtlInterlockedPushEntrySList( + * IN PSLIST_HEADER ListHead, + * IN PSLIST_ENTRY ListEntry); + */ +.proc RtlInterlockedPushEntrySList +_ExpInterlockedPushEntrySList: + + /* Load ListHead->Alignment into rax */ + mov rax, [rcx] + + /* Load ListHead->Region into rdx */ + mov r9, [rcx + 8] + + /* Check what kind of header this is */ + test r9, SLIST8B_HEADERTYPE_MASK + jnz _RtlInterlockedPushEntrySList16 + + /* We have an 8 byte header */ + +_RtlInterlockedPushEntrySListLoop: + + /* Get ListHead->NextEntry */ + mov r8, rax + and r8, SLIST8A_NEXTENTRY_MASK + jz _RtlInterlockedPushEntrySListEmpty + + /* Shift the NextEntry pointer */ + shr r8, SLIST8A_NEXTENTRY_SHIFT + + /* Create a pointer template from rcx in rdx */ + mov r9, ~SLIST8_POINTER_MASK + and r9, rcx + + /* Combine to new pointer and save as ListEntry->NextEntry */ + or r8, r9 + +_RtlInterlockedPushEntrySListEmpty: + /* Store the NextEntry pointer in the new ListEntry */ + mov [rdx], r8 + + /* Shift and mask the new ListEntry pointer */ + mov r8, rdx + shl r8, SLIST8A_NEXTENTRY_SHIFT + and r8, SLIST8A_NEXTENTRY_MASK + + /* Copy and adjust depth and sequence number */ + lea r9, [rax + SLIST8A_DEPTH_INC + SLIST8A_SEQUENCE_INC] + and r9, SLIST8A_SEQUENCE_MASK | SLIST8A_DEPTH_MASK + + /* Combine to exchange value in r8 */ + or r8, r9 + + /* Save the NextEntry in r9 */ + mov r9, [rdx] + + /* If [rcx] equals rax, exchange it with r8 */ + lock cmpxchg [rcx], r8 + + /* If not equal, retry with rax, being the content of [rcx] now */ + jnz _RtlInterlockedPushEntrySListLoop + + /* Return the old NextEntry pointer */ + mov rax, r9 + ret + +_RtlInterlockedPushEntrySList16: + /* This is a 16 byte header */ + + /* Save rbx */ + push rbx + + /* Copy rcx/rdx to r8/r9, as we need rcx/rdx for the exchange */ + mov r8, rcx + mov r9, rdx + + /* Set ListHead->HeaderType = 1 and ListHead->Init = 1 */ + mov rcx, rdx + or rcx, 0x3 + + mov rdx, [r8 + 8] + +_RtlInterlockedPushEntrySListLoop16: + + /* Move ListHead->NextEntry to rbx */ + mov rbx, rdx + and rbx, SLIST16B_NEXTENTY_MASK + + /* Store next pointer in ListEntry->NextEntry */ + mov [r9], rbx + + /* Copy Depth and Sequence number and adjust Depth */ + lea rbx, [rax + SLIST16A_DEPTH_INC + SLIST16A_SEQUENCE_INC] + + /* If [r8] equals rdx:rax, exchange it with rcx:rbx */ + lock cmpxchg16b [r8] + + /* If not equal, retry with rdx:rax, being the content of [r8] now */ + jnz _RtlInterlockedPushEntrySListLoop16 + + /* Copy the old NextEntry pointer to rax */ + mov rax, rdx + and rax, SLIST16B_NEXTENTY_MASK + + /* Return */ + pop rbx + ret + +.endproc + +/* PSLIST_ENTRY + * NTAPI + * RtlInterlockedFlushSList( + * IN PSINGLE_LIST_ENTRY ListHead); + */ +.proc RtlInterlockedFlushSList +_ExpInterlockedFlushSList: + + /* Load ListHead->Region into rdx */ + mov rax, [rcx + 8] + + /* Check what kind of header this is */ + test rax, SLIST8B_HEADERTYPE_MASK + jnz _RtlInterlockedFlushSList16 + + /* We have an 8 byte header */ + +_RtlInterlockedFlushSListLoop: + + /* Zero ListHead->Alignment */ + xor r8, r8 + + /* If [rcx] equals rax, exchange it with r8 */ + lock cmpxchg [rcx], r8 + + /* If not equal, retry with rax, being the content of [rcx] now */ + jnz _RtlInterlockedFlushSListLoop + + /* Use rcx as pointer template */ + mov rdx, ~SLIST8_POINTER_MASK + or rdx, rcx + + /* Combine result and return */ + or rax, rdx + ret + +_RtlInterlockedFlushSList16: + /* We have a 16 byte header */ + push rbx + + mov rdx, [rcx + 8] + xor rbx, rbx + mov rcx, 0x3 + +_RtlInterlockedFlushSListLoop16: + + /* If [r8] equals rdx:rax, exchange it with rcx:rbx */ + lock cmpxchg16b [r8] + + /* If not equal, retry with rdx:rax, being the content of [r8] now */ + jnz _RtlInterlockedFlushSListLoop16 + + /* Copy the old NextEntry pointer to rax */ + mov rax, rdx + and rax, SLIST16B_NEXTENTY_MASK + + /* Return */ + pop rbx + ret + +.endproc
Propchange: trunk/reactos/lib/rtl/amd64/slist.S ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/lib/rtl/amd64/stubs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/amd64/stubs.c?rev=4... ============================================================================== --- trunk/reactos/lib/rtl/amd64/stubs.c (added) +++ trunk/reactos/lib/rtl/amd64/stubs.c [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -1,0 +1,53 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Run-Time Library + * PURPOSE: AMD64 stubs + * FILE: lib/rtl/amd64/stubs.c + * PROGRAMMERS: Stefan Ginsberg (stefan.ginsberg@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include <rtl.h> +#define NDEBUG +#include <debug.h> + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @unimplemented + */ +VOID +NTAPI +RtlInitializeContext(IN HANDLE ProcessHandle, + OUT PCONTEXT ThreadContext, + IN PVOID ThreadStartParam OPTIONAL, + IN PTHREAD_START_ROUTINE ThreadStartAddress, + IN PINITIAL_TEB InitialTeb) +{ + UNIMPLEMENTED; + return; +} + +/* + * @unimplemented + */ +PVOID +NTAPI +RtlpGetExceptionAddress(VOID) +{ + UNIMPLEMENTED; + return NULL; +} + +/* + * @unimplemented + */ +BOOLEAN +NTAPI +RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context) +{ + UNIMPLEMENTED; + return FALSE; +}
Propchange: trunk/reactos/lib/rtl/amd64/stubs.c ------------------------------------------------------------------------------ svn:eol-style = native
Added: trunk/reactos/lib/rtl/amd64/unwind.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/amd64/unwind.c?rev=... ============================================================================== --- trunk/reactos/lib/rtl/amd64/unwind.c (added) +++ trunk/reactos/lib/rtl/amd64/unwind.c [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -1,0 +1,684 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * PURPOSE: Unwinding related functions + * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include <rtl.h> + +#define NDEBUG +#include <debug.h> + +#define UNWIND_HISTORY_TABLE_NONE 0 +#define UNWIND_HISTORY_TABLE_GLOBAL 1 +#define UNWIND_HISTORY_TABLE_LOCAL 2 + +#define UWOP_PUSH_NONVOL 0 +#define UWOP_ALLOC_LARGE 1 +#define UWOP_ALLOC_SMALL 2 +#define UWOP_SET_FPREG 3 +#define UWOP_SAVE_NONVOL 4 +#define UWOP_SAVE_NONVOL_FAR 5 +#define UWOP_SAVE_XMM 6 +#define UWOP_SAVE_XMM_FAR 7 +#define UWOP_SAVE_XMM128 8 +#define UWOP_SAVE_XMM128_FAR 9 +#define UWOP_PUSH_MACHFRAME 10 + +#define UNW_FLAG_NHANDLER 0 +#define UNW_FLAG_EHANDLER 1 +#define UNW_FLAG_UHANDLER 2 +#define UNW_FLAG_CHAININFO 4 + +typedef unsigned char UBYTE; + +typedef union _UNWIND_CODE +{ + struct + { + UBYTE CodeOffset; + UBYTE UnwindOp:4; + UBYTE OpInfo:4; + }; + USHORT FrameOffset; +} UNWIND_CODE, *PUNWIND_CODE; + +typedef struct _UNWIND_INFO +{ + UBYTE Version:3; + UBYTE Flags:5; + UBYTE SizeOfProlog; + UBYTE CountOfCodes; + UBYTE FrameRegister:4; + UBYTE FrameOffset:4; + UNWIND_CODE UnwindCode[1]; +/* union { + OPTIONAL ULONG ExceptionHandler; + OPTIONAL ULONG FunctionEntry; + }; + OPTIONAL ULONG ExceptionData[]; +*/ +} UNWIND_INFO, *PUNWIND_INFO; + +/* FUNCTIONS *****************************************************************/ + +/*! RtlLookupFunctionTable + * \brief Locates the table of RUNTIME_FUNCTION entries for a code address. + * \param ControlPc + * Address of the code, for which the table should be searched. + * \param ImageBase + * Pointer to a DWORD64 that receives the base address of the + * corresponding executable image. + * \param Length + * Pointer to an ULONG that receives the number of table entries + * present in the table. + */ +PRUNTIME_FUNCTION +NTAPI +RtlLookupFunctionTable( + IN DWORD64 ControlPc, + OUT PDWORD64 ImageBase, + OUT PULONG Length) +{ + PVOID Table; + ULONG Size; + + /* Find corresponding file header from code address */ + if (!RtlPcToFileHeader((PVOID)ControlPc, (PVOID*)ImageBase)) + { + /* Nothing found */ + return NULL; + } + + /* Locate the exception directory */ + Table = RtlImageDirectoryEntryToData((PVOID)*ImageBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXCEPTION, + &Size); + + /* Return the number of entries */ + *Length = Size / sizeof(RUNTIME_FUNCTION); + + /* Return the address of the table */ + return Table; +} + +/*! RtlLookupFunctionEntry + * \brief Locates the RUNTIME_FUNCTION entry corresponding to a code address. + * \ref http://msdn.microsoft.com/en-us/library/ms680597(VS.85).aspx + * \todo Implement HistoryTable + */ +PRUNTIME_FUNCTION +NTAPI +RtlLookupFunctionEntry( + IN DWORD64 ControlPc, + OUT PDWORD64 ImageBase, + OUT PUNWIND_HISTORY_TABLE HistoryTable) +{ + PRUNTIME_FUNCTION FunctionTable, FunctionEntry; + ULONG TableLength; + ULONG IndexLo, IndexHi, IndexMid; + + /* Find the corresponding table */ + FunctionTable = RtlLookupFunctionTable(ControlPc, ImageBase, &TableLength); + + /* Fail, if no table is found */ + if (!FunctionTable) + { + return NULL; + } + + /* Use relative virtual address */ + ControlPc -= *ImageBase; + + /* Do a binary search */ + IndexLo = 0; + IndexHi = TableLength; + while (IndexHi > IndexLo) + { + IndexMid = (IndexLo + IndexHi) / 2; + FunctionEntry = &FunctionTable[IndexMid]; + + if (ControlPc < FunctionEntry->BeginAddress) + { + /* Continue search in lower half */ + IndexHi = IndexMid; + } + else if (ControlPc >= FunctionEntry->EndAddress) + { + /* Continue search in upper half */ + IndexLo = IndexMid + 1; + } + else + { + /* ControlPc is within limits, return entry */ + return FunctionEntry; + } + } + + /* Nothing found, return NULL */ + return NULL; +} + +BOOLEAN +NTAPI +RtlAddFunctionTable( + IN PRUNTIME_FUNCTION FunctionTable, + IN DWORD EntryCount, + IN DWORD64 BaseAddress) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOLEAN +NTAPI +RtlDeleteFunctionTable( + IN PRUNTIME_FUNCTION FunctionTable) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOLEAN +NTAPI +RtlInstallFunctionTableCallback( + IN DWORD64 TableIdentifier, + IN DWORD64 BaseAddress, + IN DWORD Length, + IN PGET_RUNTIME_FUNCTION_CALLBACK Callback, + IN PVOID Context, + IN PCWSTR OutOfProcessCallbackDll) +{ + UNIMPLEMENTED; + return FALSE; +} + +void +FORCEINLINE +SetReg(PCONTEXT Context, BYTE Reg, DWORD64 Value) +{ + ((DWORD64*)(&Context->Rax))[Reg] = Value; +} + +DWORD64 +FORCEINLINE +GetReg(PCONTEXT Context, BYTE Reg) +{ + return ((DWORD64*)(&Context->Rax))[Reg]; +} + +void +FORCEINLINE +PopReg(PCONTEXT Context, BYTE Reg) +{ + DWORD64 Value = *(DWORD64*)Context->Rsp; + Context->Rsp += 8; + SetReg(Context, Reg, Value); +} + +/*! RtlpTryToUnwindEpilog + * \brief Helper function that tries to unwind epilog instructions. + * \return TRUE if we have been in an epilog and it could be unwound. + * FALSE if the instructions were not allowed for an epilog. + * \ref + * http://msdn.microsoft.com/en-us/library/8ydc79k6(VS.80).aspx + * http://msdn.microsoft.com/en-us/library/tawsa7cb.aspx + * \todo + * - Test and compare with Windows behaviour + */ +BOOLEAN +static +inline +RtlpTryToUnwindEpilog( + PCONTEXT Context, + ULONG64 ImageBase, + PRUNTIME_FUNCTION FunctionEntry) +{ + CONTEXT LocalContext; + BYTE *InstrPtr; + DWORD Instr; + BYTE Reg, Mod; + ULONG64 EndAddress; + + /* Make a local copy of the context */ + LocalContext = *Context; + + InstrPtr = (BYTE*)LocalContext.Rip; + + /* Check if first instruction of epilog is "add rsp, x" */ + Instr = *(DWORD*)InstrPtr; + if ( (Instr & 0x00fffdff) == 0x00c48148 ) + { + if ( (Instr & 0x0000ff00) == 0x8300 ) + { + /* This is "add rsp, 0x??" */ + LocalContext.Rsp += Instr >> 24; + InstrPtr += 4; + } + else + { + /* This is "add rsp, 0x???????? */ + LocalContext.Rsp += *(DWORD*)(InstrPtr + 3); + InstrPtr += 7; + } + } + /* Check if first instruction of epilog is "lea rsp, ..." */ + else if ( (Instr & 0x38fffe) == 0x208d48 ) + { + /* Get the register */ + Reg = ((Instr << 8) | (Instr >> 16)) & 0x7; + + LocalContext.Rsp = GetReg(&LocalContext, Reg); + + /* Get adressing mode */ + Mod = (Instr >> 22) & 0x3; + if (Mod == 0) + { + /* No displacement */ + InstrPtr += 3; + } + else if (Mod == 1) + { + /* 1 byte displacement */ + LocalContext.Rsp += Instr >> 24; + InstrPtr += 4; + } + else if (Mod == 2) + { + /* 4 bytes displacement */ + LocalContext.Rsp += *(DWORD*)(InstrPtr + 3); + InstrPtr += 7; + } + } + + /* Loop the following instructions */ + EndAddress = FunctionEntry->EndAddress + ImageBase; + while((DWORD64)InstrPtr < EndAddress) + { + Instr = *(DWORD*)InstrPtr; + + /* Check for a simple pop */ + if ( (Instr & 0xf8) == 0x58 ) + { + /* Opcode pops a basic register from stack */ + Reg = Instr & 0x7; + PopReg(&LocalContext, Reg); + InstrPtr++; + continue; + } + + /* Check for REX + pop */ + if ( (Instr & 0xf8fb) == 0x5841 ) + { + /* Opcode is pop r8 .. r15 */ + Reg = (Instr & 0x7) + 8; + PopReg(&LocalContext, Reg); + InstrPtr += 2; + continue; + } + + /* Check for retn / retf */ + if ( (Instr & 0xf7) == 0xc3 ) + { + /* We are finished */ + break; + } + + /* Opcode not allowed for Epilog */ + return FALSE; + } + + /* Unwind is finished, pop new Rip from Stack */ + LocalContext.Rip = *(DWORD64*)LocalContext.Rsp; + LocalContext.Rsp += sizeof(DWORD64); + + *Context = LocalContext; + return TRUE; +} + + +PEXCEPTION_ROUTINE +NTAPI +RtlVirtualUnwind( + IN ULONG HandlerType, + IN ULONG64 ImageBase, + IN ULONG64 ControlPc, + IN PRUNTIME_FUNCTION FunctionEntry, + IN OUT PCONTEXT Context, + OUT PVOID *HandlerData, + OUT PULONG64 EstablisherFrame, + IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers) +{ + PUNWIND_INFO UnwindInfo; + ULONG CodeOffset; + ULONG i; + UNWIND_CODE UnwindCode; + BYTE Reg; + + /* Use relative virtual address */ + ControlPc -= ImageBase; + + /* Sanity checks */ + if ( (ControlPc < FunctionEntry->BeginAddress) || + (ControlPc >= FunctionEntry->EndAddress) ) + { + return NULL; + } + + /* Get a pointer to the unwind info */ + UnwindInfo = RVA(ImageBase, FunctionEntry->UnwindData); + + /* Calculate relative offset to function start */ + CodeOffset = ControlPc - FunctionEntry->BeginAddress; + + /* Check if we are in the function epilog and try to finish it */ + if (CodeOffset > UnwindInfo->SizeOfProlog) + { + if (RtlpTryToUnwindEpilog(Context, ImageBase, FunctionEntry)) + { + /* There's no exception routine */ + return NULL; + } + } + + /* Skip all Ops with an offset greater than the current Offset */ + i = 0; + while (i < UnwindInfo->CountOfCodes && + CodeOffset < UnwindInfo->UnwindCode[i].CodeOffset) + { + UnwindCode = UnwindInfo->UnwindCode[i]; + switch (UnwindCode.UnwindOp) + { + case UWOP_SAVE_NONVOL: + case UWOP_SAVE_XMM: + case UWOP_SAVE_XMM128: + i += 2; + break; + + case UWOP_SAVE_NONVOL_FAR: + case UWOP_SAVE_XMM_FAR: + case UWOP_SAVE_XMM128_FAR: + i += 3; + break; + + case UWOP_ALLOC_LARGE: + i += UnwindCode.OpInfo ? 3 : 2; + break; + + default: + i++; + } + } + + /* Process the left Ops */ + while (i < UnwindInfo->CountOfCodes) + { + UnwindCode = UnwindInfo->UnwindCode[i]; + switch (UnwindCode.UnwindOp) + { + case UWOP_PUSH_NONVOL: + Reg = UnwindCode.OpInfo; + SetReg(Context, Reg, *(DWORD64*)Context->Rsp); + Context->Rsp += sizeof(DWORD64); + i++; + break; + + case UWOP_ALLOC_LARGE: + if (UnwindCode.OpInfo) + { + ULONG Offset = *(ULONG*)(&UnwindInfo->UnwindCode[i+1]); + Context->Rsp += Offset; + i += 3; + } + else + { + USHORT Offset = UnwindInfo->UnwindCode[i+1].FrameOffset; + Context->Rsp += Offset * 8; + i += 2; + } + break; + + case UWOP_ALLOC_SMALL: + Context->Rsp += (UnwindCode.OpInfo + 1) * 8; + i++; + break; + + case UWOP_SET_FPREG: + i++; + break; + + case UWOP_SAVE_NONVOL: + i += 2; + break; + + case UWOP_SAVE_NONVOL_FAR: + i += 3; + break; + + case UWOP_SAVE_XMM: + i += 2; + break; + + case UWOP_SAVE_XMM_FAR: + i += 3; + break; + + case UWOP_SAVE_XMM128: + i += 2; + break; + + case UWOP_SAVE_XMM128_FAR: + i += 3; + break; + + case UWOP_PUSH_MACHFRAME: + i += 1; + break; + } + } + + /* Unwind is finished, pop new Rip from Stack */ + Context->Rip = *(DWORD64*)Context->Rsp; + Context->Rsp += sizeof(DWORD64); + + return 0; +} + +VOID +NTAPI +RtlUnwindEx( + IN ULONG64 TargetFrame, + IN ULONG64 TargetIp, + IN PEXCEPTION_RECORD ExceptionRecord, + IN PVOID ReturnValue, + OUT PCONTEXT OriginalContext, + IN PUNWIND_HISTORY_TABLE HistoryTable) +{ + UNIMPLEMENTED; + return; +} + +VOID +NTAPI +RtlUnwind( + IN PVOID TargetFrame, + IN PVOID TargetIp, + IN PEXCEPTION_RECORD ExceptionRecord, + IN PVOID ReturnValue) +{ + UNIMPLEMENTED; + return; +} + +ULONG +NTAPI +RtlWalkFrameChain(OUT PVOID *Callers, + IN ULONG Count, + IN ULONG Flags) +{ + CONTEXT Context; + ULONG64 ControlPc, ImageBase, EstablisherFrame; + ULONG64 StackLow, StackHigh; + PVOID HandlerData; + INT i; + PRUNTIME_FUNCTION FunctionEntry; + + DPRINT("Enter RtlWalkFrameChain\n"); + + /* Capture the current Context */ + RtlCaptureContext(&Context); + ControlPc = Context.Rip; + + /* Get the stack limits */ + RtlpGetStackLimits(&StackLow, &StackHigh); + + /* Check if we want the user-mode stack frame */ + if (Flags == 1) + { + } + + /* Loop the frames */ + for (i = 0; i < Count; i++) + { + /* Lookup the FunctionEntry for the current ControlPc */ + FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL); + + /* Is this a leaf function? */ + if (!FunctionEntry) + { + Context.Rip = *(DWORD64*)Context.Rsp; + Context.Rsp += sizeof(DWORD64); + DPRINT("leaf funtion, new Rip = %p, new Rsp = %p\n", (PVOID)Context.Rip, (PVOID)Context.Rsp); + } + else + { + RtlVirtualUnwind(0, + ImageBase, + ControlPc, + FunctionEntry, + &Context, + &HandlerData, + &EstablisherFrame, + NULL); + DPRINT("normal funtion, new Rip = %p, new Rsp = %p\n", (PVOID)Context.Rip, (PVOID)Context.Rsp); + } + + /* Check if new Rip is valid */ + if (!Context.Rip) + { + break; + } + + /* Check, if we have left our stack */ + if ((Context.Rsp < StackLow) || (Context.Rsp > StackHigh)) + { + break; + } + + /* Save this frame and continue with new Rip */ + ControlPc = Context.Rip; + Callers[i] = (PVOID)ControlPc; + } + + DPRINT("RtlWalkFrameChain returns %ld\n", i); + return i; +} + +/*! RtlGetCallersAddress + * \ref http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Debug/... + */ +#undef RtlGetCallersAddress +VOID +NTAPI +RtlGetCallersAddress( + OUT PVOID *CallersAddress, + OUT PVOID *CallersCaller ) +{ + PVOID Callers[4]; + ULONG Number; + + /* Get callers: + * RtlWalkFrameChain -> RtlGetCallersAddress -> x -> y */ + Number = RtlWalkFrameChain(Callers, 4, 0); + + if (CallersAddress) + { + *CallersAddress = (Number >= 3) ? Callers[2] : NULL; + } + if (CallersCaller) + { + *CallersCaller = (Number == 4) ? Callers[3] : NULL; + } + + return; +} + +// FIXME: move to different file +VOID +NTAPI +RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord) +{ + CONTEXT Context; + NTSTATUS Status = STATUS_INVALID_DISPOSITION; + ULONG64 ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + PVOID HandlerData; + ULONG64 EstablisherFrame; + + /* Capture the context */ + RtlCaptureContext(&Context); + + /* Get the function entry for this function */ + FunctionEntry = RtlLookupFunctionEntry(Context.Rip, + &ImageBase, + NULL); + + /* Check if we found it */ + if (FunctionEntry) + { + /* Unwind to the caller of this function */ + RtlVirtualUnwind(UNW_FLAG_NHANDLER, + ImageBase, + Context.Rip, + FunctionEntry, + &Context, + &HandlerData, + &EstablisherFrame, + NULL); + + /* Save the exception address */ + ExceptionRecord->ExceptionAddress = (PVOID)Context.Rip; + + /* Write the context flag */ + Context.ContextFlags = CONTEXT_FULL; + + /* Check if user mode debugger is active */ + if (RtlpCheckForActiveDebugger()) + { + /* Raise an exception immediately */ + Status = ZwRaiseException(ExceptionRecord, &Context, TRUE); + } + else + { + /* Dispatch the exception and check if we should continue */ + if (!RtlDispatchException(ExceptionRecord, &Context)) + { + /* Raise the exception */ + Status = ZwRaiseException(ExceptionRecord, &Context, FALSE); + } + else + { + /* Continue, go back to previous context */ + Status = ZwContinue(&Context, FALSE); + } + } + } + + /* If we returned, raise a status */ + RtlRaiseStatus(Status); +} +
Propchange: trunk/reactos/lib/rtl/amd64/unwind.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/lib/rtl/exception.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/exception.c?rev=449... ============================================================================== --- trunk/reactos/lib/rtl/exception.c [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/exception.c [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -17,7 +17,7 @@
/* FUNCTIONS ***************************************************************/
-#if !defined(_M_IX86) +#if !defined(_M_IX86) && !defined(_M_AMD64)
/* * @implemented @@ -62,6 +62,10 @@ /* If we returned, raise a status */ RtlRaiseStatus(Status); } + +#endif + +#if !defined(_M_IX86)
#ifdef _MSC_VER #pragma warning(push)
Modified: trunk/reactos/lib/rtl/rtl.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/rtl.rbuild?rev=4497... ============================================================================== --- trunk/reactos/lib/rtl/rtl.rbuild [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/rtl.rbuild [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -31,6 +31,17 @@ <if property="ARCH" value="arm"> <directory name="arm"> <file>debug_asm.S</file> + </directory> + <file>mem.c</file> + <file>memgen.c</file> + </if> + <if property="ARCH" value="amd64"> + <directory name="amd64"> + <file>debug_asm.S</file> + <file>except_asm.S</file> + <file>slist.S</file> + <file>unwind.c</file> + <file>stubs.c</file> </directory> <file>mem.c</file> <file>memgen.c</file>
Modified: trunk/reactos/lib/rtl/rtlp.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/rtlp.h?rev=44970&am... ============================================================================== --- trunk/reactos/lib/rtl/rtlp.h [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/rtlp.h [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -32,10 +32,12 @@ #define ROUND_UP(n, align) \ ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
+#define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m))) + VOID NTAPI -RtlpGetStackLimits(PULONG_PTR StackBase, - PULONG_PTR StackLimit); +RtlpGetStackLimits(PULONG_PTR LowLimit, + PULONG_PTR HighLimit);
PEXCEPTION_REGISTRATION_RECORD NTAPI
Modified: trunk/reactos/lib/rtl/slist.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/slist.c?rev=44970&a... ============================================================================== --- trunk/reactos/lib/rtl/slist.c [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/slist.c [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -20,7 +20,10 @@ RtlInitializeSListHead(IN PSLIST_HEADER ListHead) { #ifdef _WIN64 - UNIMPLEMENTED; + ListHead->Alignment = 0; + ListHead->Region = 0; + ListHead->Header8.Init = 1; + // ListHead->Header8.HeaderType = 1; // FIXME: depending on cmpxchg16b support? #else ListHead->Alignment = 0; #endif @@ -31,8 +34,25 @@ RtlFirstEntrySList(IN const SLIST_HEADER *ListHead) { #ifdef _WIN64 - UNIMPLEMENTED; - return NULL; + if (ListHead->Header8.HeaderType) + { + return (PVOID)(ListHead->Region & ~0xF); + } + else + { + union { + PVOID P; + struct { + ULONG64 Reserved:4; + ULONG64 NextEntry:39; + ULONG64 Reserved2:21; + } Bits; + } Pointer; + + Pointer.P = (PVOID)ListHead; + Pointer.Bits.NextEntry = ListHead->Header8.NextEntry; + return Pointer.P; + } #else return ListHead->Next.Next; #endif @@ -43,8 +63,8 @@ RtlQueryDepthSList(IN PSLIST_HEADER ListHead) { #ifdef _WIN64 - UNIMPLEMENTED; - return 0; + return ListHead->Header8.HeaderType ? + ListHead->Header16.Sequence : ListHead->Header8.Sequence; #else return ListHead->Depth; #endif
Modified: trunk/reactos/lib/rtl/sprintf.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/sprintf.c?rev=44970... ============================================================================== --- trunk/reactos/lib/rtl/sprintf.c [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/sprintf.c [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -27,40 +27,33 @@ #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ #define REMOVEHEX 256 /* use 256 as remve 0x frim BASE 16 */ -typedef struct { - unsigned int mantissal:32; - unsigned int mantissah:20; - unsigned int exponent:11; - unsigned int sign:1; +typedef union { + struct { + unsigned int mantissal:32; + unsigned int mantissah:20; + unsigned int exponent:11; + unsigned int sign:1; + }; + long long AsLongLong; } double_t; + +/* We depend on this being true */ +C_ASSERT(sizeof(double_t) == sizeof(double));
static __inline int -_isinf(double __x) -{ - union - { - double* __x; - double_t* x; - } x; - - x.__x = &__x; - return ( x.x->exponent == 0x7ff && ( x.x->mantissah == 0 && x.x->mantissal == 0 )); +_isinf(double_t x) +{ + return ( x.exponent == 0x7ff && ( x.mantissah == 0 && x.mantissal == 0 )); }
static __inline int -_isnan(double __x) -{ - union - { - double* __x; - double_t* x; - } x; - x.__x = &__x; - return ( x.x->exponent == 0x7ff && ( x.x->mantissah != 0 || x.x->mantissal != 0 )); +_isnan(double_t x) +{ + return ( x.exponent == 0x7ff && ( x.mantissah != 0 || x.mantissal != 0 )); }
@@ -180,14 +173,13 @@ }
static char * -numberf(char * buf, char * end, double num, int base, int size, int precision, int type) +numberf(char * buf, char * end, double_t num, int base, int size, int precision, int type) { char c,sign,tmp[66]; const char *digits; const char *small_digits = "0123456789abcdefghijklmnopqrstuvwxyz"; const char *large_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int i; - long long x;
/* FIXME the float version of number is direcly copy of number @@ -201,9 +193,9 @@ c = (type & ZEROPAD) ? '0' : ' '; sign = 0; if (type & SIGN) { - if (num < 0) { + if (num.sign) { sign = '-'; - num = -num; + num.sign = 0; size--; } else if (type & PLUS) { sign = '+'; @@ -220,15 +212,11 @@ size--; } i = 0; - if (num == 0) + if (num.AsLongLong == 0) tmp[i++] = '0'; - else while (num != 0) + else while (num.AsLongLong != 0) { - x = num; - tmp[i++] = digits[do_div(&x,base)]; -#ifndef _M_ARM // Missing __floatdidf in CeGCC 0.55 -- GCC 4.4 - num=x; -#endif + tmp[i++] = digits[do_div(&num.AsLongLong,base)]; } if (i > precision) precision = i; @@ -389,7 +377,7 @@ { int len; unsigned long long num; - double _double; + double_t _double;
int base; char *str, *end; @@ -600,7 +588,7 @@ case 'f': case 'g': case 'G': - _double = (double)va_arg(args, double); + _double = va_arg(args, double_t); if ( _isnan(_double) ) { s = "Nan"; len = 3; @@ -631,7 +619,7 @@ } else { if ( precision == -1 ) precision = 6; - str = numberf(str, end, (int)_double, base, field_width, precision, flags); + str = numberf(str, end, _double, base, field_width, precision, flags); }
continue;
Modified: trunk/reactos/lib/rtl/swprintf.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/swprintf.c?rev=4497... ============================================================================== --- trunk/reactos/lib/rtl/swprintf.c [iso-8859-1] (original) +++ trunk/reactos/lib/rtl/swprintf.c [iso-8859-1] Wed Jan 6 01:39:07 2010 @@ -27,40 +27,33 @@ #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ #define REMOVEHEX 256 /* use 256 as remve 0x frim BASE 16 */ -typedef struct { - unsigned int mantissal:32; - unsigned int mantissah:20; - unsigned int exponent:11; - unsigned int sign:1; +typedef union { + struct { + unsigned int mantissal:32; + unsigned int mantissah:20; + unsigned int exponent:11; + unsigned int sign:1; + }; + long long AsLongLong; } double_t; + +/* We depend on this being true */ +C_ASSERT(sizeof(double_t) == sizeof(double));
static __inline int -_isinf(double __x) -{ - union - { - double* __x; - double_t* x; - } x; - - x.__x = &__x; - return ( x.x->exponent == 0x7ff && ( x.x->mantissah == 0 && x.x->mantissal == 0 )); +_isinf(double_t x) +{ + return ( x.exponent == 0x7ff && ( x.mantissah == 0 && x.mantissal == 0 )); }
static __inline int -_isnan(double __x) -{ - union - { - double* __x; - double_t* x; - } x; - x.__x = &__x; - return ( x.x->exponent == 0x7ff && ( x.x->mantissah != 0 || x.x->mantissal != 0 )); +_isnan(double_t x) +{ + return ( x.exponent == 0x7ff && ( x.mantissah != 0 || x.mantissal != 0 )); }
@@ -179,14 +172,13 @@ }
static wchar_t * -numberf(wchar_t * buf, wchar_t * end, double num, int base, int size, int precision, int type) +numberf(wchar_t * buf, wchar_t * end, double_t num, int base, int size, int precision, int type) { wchar_t c, sign, tmp[66]; const wchar_t *digits; const wchar_t *small_digits = L"0123456789abcdefghijklmnopqrstuvwxyz"; const wchar_t *large_digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int i; - long long x;
/* FIXME the float version of number is direcly copy of number @@ -201,9 +193,9 @@ c = (type & ZEROPAD) ? L'0' : L' '; sign = 0; if (type & SIGN) { - if (num < 0) { + if (num.sign) { sign = L'-'; - num = -num; + num.sign = 0; size--; } else if (type & PLUS) { sign = L'+'; @@ -220,15 +212,11 @@ size--; } i = 0; - if (num == 0) + if (num.AsLongLong == 0) tmp[i++] = L'0'; - else while (num != 0) - { - x = num; - tmp[i++] = digits[do_div(&x,base)]; -#ifndef _M_ARM // Missing __floatdidf in CeGCC 0.55 -- GCC 4.4 - num = x; -#endif + else while (num.AsLongLong != 0) + { + tmp[i++] = digits[do_div(&num.AsLongLong,base)]; } if (i > precision) precision = i; @@ -394,7 +382,7 @@ const char *s; const wchar_t *sw; const wchar_t *ss; - double _double; + double_t _double;
int flags; /* flags to number() */
@@ -597,7 +585,7 @@ case 'f': case 'g': case 'G': - _double = (double)va_arg(args, double); + _double = va_arg(args, double_t);
if ( _isnan(_double) ) { ss = L"Nan";