singrdk/base/Kernel/Native/ix86/halasm.asm

1421 lines
41 KiB
NASM

;
; Copyright (c) Microsoft Corporation. All rights reserved.
;
include hal.inc
externdef __throwDispatcher:NEAR
externdef __throwDispatcherExplicitAddrAfter:NEAR
externdef ?ExceptionTableLookup@@YI_KPAUClass_System_Exception@@I@Z:NEAR
ifdef SINGULARITY_KERNEL
externdef ?g_setStopContext@Class_System_Threading_Thread@@SIXPAU1@PAUClass_System_Exception@@@Z:NEAR
externdef __throwBeyondMarker:NEAR
endif ; SINGULARITY_KERNEL
externdef __throwDivideByZeroException:NEAR
externdef __throwNullPointerException:NEAR
externdef __throwOverflowException:NEAR
externdef __throwStackOverflowException:NEAR
if EXCLUDED
externdef __checkFPStackDepth0:NEAR
externdef __checkFPStackDepth1:NEAR
externdef __checkFPStackDepth2:NEAR
externdef __checkFPStackDepth3:NEAR
externdef __checkFPStackDepth4:NEAR
externdef __checkFPStackDepth5:NEAR
externdef __checkFPStackDepth6:NEAR
externdef __checkFPStackDepth7:NEAR
endif ;; EXCLUDED
align 8
$DBLMAXINT DQ 041dfffffffc00000r ; 2.14747e+009
$DBLMININT DQ 0c1e0000000000000r ; -2.14748e+009
$MAXLONG DQ 07fffffffffffffffh
$MINLONG DQ 08000000000000000h
;
; __throwDispatcher(ecx=exception)
;
; Description: this function is called to explicitly throw an exception.
; It assumes that the return address points to the instruction immediately
; after the one where the exception was thrown
;
; Arguments:
; ecx = exception object
; [esp] = the return address
; Effects:
; 1. Create ebp chain entry
; 2. Get return address and uses it to calculate the address of the
; instruction that threw the exception.
; 3. Looks up the appropriate handler and jumps to code to process it.
align 16
__throwDispatcher proc
push ebp ; create ebp chain entry
mov ebp, esp ; set new ebp
mov edx, [ebp+4] ; get return address
push ecx ; save exception
sub edx, 1 ; adjust to point to throw location
call ?ExceptionTableLookup@@YI_KPAUClass_System_Exception@@I@Z
pop ecx ; restore exception
pop ebp ; remove ebp chain
add esp, 4 ; remove eip from the stack
; mov edx is already ok
jmp __throwDispatcherHandler
__throwDispatcher endp
;
; __throwDispatcherExplicitAddr (ecx=exception, edx=throwAddress)
;
; Description:
; This is to be used when the address where the exception occurred
; is passed in as an extra argument
;
; Arguments:
; ecx = exception object
; edx = address where the exception was thrown
;
align 16
__throwDispatcherExplicitAddr proc
push ecx ; save exception
call ?ExceptionTableLookup@@YI_KPAUClass_System_Exception@@I@Z
pop ecx ; restore exception
; mov edx is already ok
jmp __throwDispatcherHandler
__throwDispatcherExplicitAddr endp
;
; __throwDispatcherExplictAddrAfter (ecx=exception, edx=throwAddress)
;
; Description:
; This is to be used when the address of the instruction immediately after
; the one that actually threw the exception is passed as an argument.
;
; Arguments:
; ecx = pointer to exception object being thrown
; edx = address of the instruction following the one where
; the exception was thrown
;
; This is used, for example, in stack unwinding, where edx is the
; return address on the stack for the current procedure.
;
; Stack unwinding occurs when the current procedure does not have a handler
; for the routine. The idea is to pop the stack frame and treat the call
; instruction in the caller as though it threw. We only have the return
; address, though, which points to the instruction *after* the call.
;
align 16
__throwDispatcherExplicitAddrAfter proc
ifdef SINGULARITY
; int 3
push ecx
push edx
mov ecx, edx
call ?g_IsUnlinkStack@Class_System_Exception@@SI_NPAUuintPtr@@@Z
pop edx
pop ecx
test al, al
je normal
mov eax, ecx ; save exception type
mov ecx, edx
mov edx, [ebp+4] ; save the return addr in caller
mov [ebp+4], afterUnlinkStack ; override return addr to instr after
jmp ecx ; unlink stack which saves eax, edx
afterUnlinkStack:
mov ecx, eax ; restore return addr in caller
normal:
; Have we reached a kernel->process or process->kernel boundary?
; Call Exception.CheckKernelProcessBoundary(esp, ebp, exception)
push ecx
push edx
push ecx ; arg 3 (exception)
mov ecx, esp ; arg 2 (ebp)
mov edx, ebp ; arg 1 (esp)
call ?g_CheckKernelProcessBoundary@Class_System_Threading_Thread@@SIPAUuintPtr@@PAU2@0PAUClass_System_Exception@@@Z
pop edx
pop ecx
; A non-zero return value means we reached a boundary.
test eax, eax
jz normal2
ifdef SINGULARITY_PROCESS
;; The process's exception reached the kernel's frames.
; Return gracefully to the kernel (i.e. jump to the kernel's
; return address), and the kernel's popStackMark
; will check uncaughtFlag and throw a new exception.
jmp edx
endif ; SINGULARITY_PROCESS
ifdef SINGULARITY_KERNEL
; There are 3 control paths that merge here:
; (1) When Thread.cs stops a process mode thread, it sets eip to point here.
; (2) When Thread.cs stops a blocked kernel thread, it sets eip to point here.
; (3) The stack unwinder falls through to this case when a kernel exception
; reaches a process's frames.
; For control path (3), a finally block puts us in a GC safe state
; just before we reach here.
; We also expect to be in the GC safe state most of the
; time for control paths (1) and (2), but
; because pushStackMark and popStackMark are not atomic operations,
; we cannot be 100% sure that we're in the GC safe state.
; eax: kernel->process or kernel->kernel marker
; ecx: exception
__throwBeyondMarker LABEL NEAR
push ecx
push eax
; Leave the GC safe state (if we're actually in it)
call ?g_RestoreMutatorControlIfNeeded@Class_System_GCs_Transitions@@SIXXZ
pop eax
pop ecx
; eax: kernel->process or kernel->kernel marker
; ecx: exception
; Restore state from the marker, skipping over any intermediate frames.
; Keep the original exception in ecx.
; Get the return address for the frame beyond the marker into edx:
mov edx, dword ptr [eax].Struct_System_GCs_CallStack_TransitionRecord._stackBottom
mov edx, dword ptr [edx - 4]
; Restore the kernel's ebx, edi, esi, ebp from the marker:
mov ebx, dword ptr [eax].Struct_System_GCs_CallStack_TransitionRecord._calleeSaveRegisters._EBX
mov edi, dword ptr [eax].Struct_System_GCs_CallStack_TransitionRecord._calleeSaveRegisters._EDI
mov esi, dword ptr [eax].Struct_System_GCs_CallStack_TransitionRecord._calleeSaveRegisters._ESI
mov ebp, dword ptr [eax].Struct_System_GCs_CallStack_TransitionRecord._calleeSaveRegisters._EBP
; Keep a copy of transition record (eax) and oldTransitionRecord
push eax
push dword ptr [eax].Struct_System_GCs_CallStack_TransitionRecord._oldTransitionRecord
; Read _stackBottom (the new esp) from the kernel->process marker:
mov eax, dword ptr [eax].Struct_System_GCs_CallStack_TransitionRecord._stackBottom
; Save ecx, edx to new stack -- this may overwrite the transition record,
; so don't read any more fields from the transition record after this point.
mov [eax - 4], ecx ; (exception)
mov [eax - 8], edx ; (return address)
; Set up the two arguments to DiscardStackSegments
pop edx ; (oldTransitionRecord)
pop ecx ; (marker)
; Restore the kernel's esp from the kernel->process marker:
lea esp, [eax - 8]
; Free any stack segments that we skipped over:
;; TODO: are we sure there's enough stack space to call this?
call ?g_DiscardSkippedStackSegments@Class_System_Threading_Thread@@SIXPAUStruct_System_GCs_CallStack_TransitionRecord@@0@Z
pop edx ; (return address)
pop ecx ; (exception)
endif ; SINGULARITY_KERNEL
normal2:
endif
push ecx ; save exception
dec edx
call ?ExceptionTableLookup@@YI_KPAUClass_System_Exception@@I@Z
pop ecx ; restore exception
; mov edx is already ok
jmp __throwDispatcherHandler
__throwDispatcherExplicitAddrAfter endp
; __throwDispatcherHandler (eax=frameSetupInfo or exceptionType,
; ecx=exception,
; edx=spillSize,frameSetupSize, or handlerAddress
;
; Description:
; After the exception table entry has been found, the values are passed here
; for processing. This method simply checks for the easy case of an explicit
; handler (known if the exceptionType is given <-- low bit is zero).
; In this case it simply jumps to the handler. Otherwise it passes the
; information along to __throwDispatcherUnwind.
;
; Arguments:
; If low bit of eax is set:
; eax = frame setup information
; ecx = exception object
; edx = spill size excluding callee-save register saves
; or offset from ebp to end of callee-save register saves
; Otherwise:
; eax = exception type (unused)
; ecx = exception object
; edx = handler address
align 16
__throwDispatcherHandler proc
test eax, 1
jne __throwDispatcherUnwind
;; ecx=exception, edx=handler
jmp edx
__throwDispatcherHandler endp
; __throwDispatcherUnwind (eax=frame setup info, ecx=exception, edx=spill size
;
; Description:
; This is the global unwind handler. It is used to unwind a single stack
; frame if there are no explicit handlers that catch an exception in a given
; function.
;
; Arguments:
; eax = frame setup information, must have low bit set
; ecx = exception object
; edx = spill size excluding callee-save register saves
; or offset from ebp to end of callee-save register saves
;
; See tables\ExceptionTable.cs for details on these values
align 16
__throwDispatcherUnwind proc
;; eax=frame info
;; edx=spill size
;; obviously ebp isn't useful under frame pointer omission
;; but less obviously esp may be invalid if ebp is good
;; (e.g. under varargs we may not have known how many arguments to
;; pop; this is one reason why varargs turns off frame pointer omission)
test eax, 2h
jne esp_is_good
;; ebp_is_good
add edx, ebp
mov esp, edx
jmp esp_is_setup
esp_is_good:
;; pop spill slots
add esp, edx
esp_is_setup:
;; restore callee-saves and pop values from stack
;; (excludes ebp if used as the frame pointer)
test eax, 4h
je skip_edi_restore
;; restore edi
pop edi
skip_edi_restore:
test eax, 8h
je skip_esi_restore
;; restore esi
pop esi
skip_esi_restore:
test eax, 10h
je skip_ebp_restore
;; restore ebp
pop ebp
skip_ebp_restore:
test eax, 20h
je skip_ebx_restore
;; restore ebx
pop ebx
skip_ebx_restore:
test eax, 40h
je skip_jump_transition_record
;; jump over transition record
add esp, (SIZE Struct_System_GCs_CallStack_TransitionRecord)
skip_jump_transition_record:
;; restore ebp if it was used as the frame pointer
test eax, 2h
jne skip_frame_pointer_restore
;; restore frame pointer (esp == ebp already)
pop ebp
skip_frame_pointer_restore:
;; set edx=return address
pop edx
;; pop arguments
shr eax, 16
add esp, eax
;; At this point
;; ecx=exception, edx=return address
;; esi/edi/ebx/ebp/esp have been restored
;; eax is scratch
;; set up next handler search
jmp __throwDispatcherExplicitAddrAfter
__throwDispatcherUnwind endp
;
; __throwDivideByZeroException: instantiate an divide-by-zero exception
; and throw it.
;
; Assumes edx points to the address after the one that threw.
;
align 16
__throwDivideByZeroException proc
push ebx
push esi
mov ebx,edx ; save address
if SINGLE_THREADED
inc ?c_allocationInhibitGC@Class_System_GC@@2_NA
else ; SINGLE_THREADED
lock inc ?c_allocationInhibitGC@Class_System_GC@@2_NA
endif ; SINGLE_THREADED
mov ecx,offset ??_7System_DivideByZeroException@@6B@
call ?g_AllocateObject@Class_System_GC@@SIPAUClass_System_Object@@PAUClass_System_VTable@@@Z
mov esi,eax ; save pointer to instance of exception
mov ecx,eax ; initialize instance
call ?m__ctor@Class_System_DivideByZeroException@@SIXPAU1@@Z
if SINGLE_THREADED
dec ?c_allocationInhibitGC@Class_System_GC@@2_NA
else ; SINGLE_THREADED
lock dec ?c_allocationInhibitGC@Class_System_GC@@2_NA
endif ; SINGLE_THREADED
mov ecx,esi
mov edx,ebx
pop esi
pop ebx
jmp __throwDispatcherExplicitAddr
__throwDivideByZeroException endp
;
; __throwStackOverflowException: instantiate an StackOverflow exception
; and throw it.
;
; Assumes edx points to the address of the instruction that faulted
;
align 16
__throwStackOverflowException proc
push ebx
push esi
mov ebx,edx ; save address
if SINGLE_THREADED
inc ?c_allocationInhibitGC@Class_System_GC@@2_NA
else ; SINGLE_THREADED
lock inc ?c_allocationInhibitGC@Class_System_GC@@2_NA
endif ; MULTI_THREADED
mov ecx,offset ??_7System_StackOverflowException@@6B@
call ?g_AllocateObject@Class_System_GC@@SIPAUClass_System_Object@@PAUClass_System_VTable@@@Z
mov esi,eax ; save pointer to instance of exception
mov ecx,eax ; initialize instance
call ?m__ctor@Class_System_StackOverflowException@@SIXPAU1@@Z
if SINGLE_THREADED
dec ?c_allocationInhibitGC@Class_System_GC@@2_NA
else ; SINGLE_THREADED
lock dec ?c_allocationInhibitGC@Class_System_GC@@2_NA
endif ; MULTI_THREADED
mov ecx,esi
mov edx,ebx
call ?ExceptionTableLookup@@YI_KPAUClass_System_Exception@@I@Z
ifndef SINGULARITY
push esi
push edx
call ?ResetGuardPage@@YIXXZ
pop edx
pop eax
endif
pop esi
pop ebx
mov ecx,eax
; mov edx is already ok
jmp edx
__throwStackOverflowException endp
;
; __throwNullReferenceException: instantiate an NullReference exception
; and throw it.
;
; Assumes edx points to the address of the instruction that faulted
;
align 16
__throwNullReferenceException proc
push ebx
push esi
mov ebx,edx ; save address
if SINGLE_THREADED
inc ?c_allocationInhibitGC@Class_System_GC@@2_NA
else ; SINGLE_THREADED
lock inc ?c_allocationInhibitGC@Class_System_GC@@2_NA
endif ; SINGLE_THREADED
mov ecx,offset ??_7System_NullReferenceException@@6B@
call ?g_AllocateObject@Class_System_GC@@SIPAUClass_System_Object@@PAUClass_System_VTable@@@Z
mov esi,eax ; save pointer to instance of exception
mov ecx,eax ; initialize instance
call ?m__ctor@Class_System_NullReferenceException@@SIXPAU1@@Z
if SINGLE_THREADED
dec ?c_allocationInhibitGC@Class_System_GC@@2_NA
else ; SINGLE_THREADED
lock dec ?c_allocationInhibitGC@Class_System_GC@@2_NA
endif ; SINGLE_THREADED
mov ecx,esi
mov edx,ebx
pop esi
pop ebx
jmp __throwDispatcherExplicitAddr
__throwNullReferenceException endp
;
; __throwDivideByZeroException: instantiate an divide-by-zero exception
; and throw it.
;
; Assumes edx points to the address of the instruction that faulted
;
align 16
__throwOverflowException proc
push ebx
push esi
mov ebx,edx ; save address
if SINGLE_THREADED
inc ?c_allocationInhibitGC@Class_System_GC@@2_NA
else ; SINGLE_THREADED
lock inc ?c_allocationInhibitGC@Class_System_GC@@2_NA
endif ; SINGLE_THREADED
mov ecx,offset ??_7System_OverflowException@@6B@
call ?g_AllocateObject@Class_System_GC@@SIPAUClass_System_Object@@PAUClass_System_VTable@@@Z
mov esi,eax ; save pointer to instance of exception
mov ecx,eax ; initialize instance
call ?m__ctor@Class_System_OverflowException@@SIXPAU1@@Z
if SINGLE_THREADED
dec ?c_allocationInhibitGC@Class_System_GC@@2_NA
else ; SINGLE_THREADED
lock dec ?c_allocationInhibitGC@Class_System_GC@@2_NA
endif ; SINGLE_THREADED
mov ecx,esi
mov edx,ebx
pop esi
pop ebx
jmp __throwDispatcherExplicitAddr
__throwOverflowException endp
ifdef SINGULARITY_KERNEL
;
; void Thread.setStopContext(Thread t, Exception exn)
;
align 16
?g_setStopContext@Class_System_Threading_Thread@@SIXPAU1@PAUClass_System_Exception@@@Z proc
; ecx = ecx.context
add ecx, Class_System_Threading_Thread._context
; context.eip = __throwBeyondMarker
; context.ecx = processStopException
; context.eax = context.stackMarkers
mov [ecx].Struct_Microsoft_Singularity_ThreadContext._threadRecord._spill._ip, __throwBeyondMarker
mov [ecx].Struct_Microsoft_Singularity_ThreadContext._threadRecord._spill._cx, edx
mov eax, [ecx].Struct_Microsoft_Singularity_ThreadContext._stackMarkers
mov [ecx].Struct_Microsoft_Singularity_ThreadContext._threadRecord._spill._ax, eax
ret
?g_setStopContext@Class_System_Threading_Thread@@SIXPAU1@PAUClass_System_Exception@@@Z endp
endif ; SINGULARITY_KERNEL
;
; int System.VTable.doubleToInt(double)
;
align 16
?g_doubleToInt@Class_System_VTable@@SIHN@Z proc
push ebp
mov ebp,esp
add esp,-8
fld real8 ptr [ebp+8]
wait
fnstcw word ptr [ebp-2]
wait
mov ax,word ptr [ebp-2]
or eax,0C00h
mov word ptr [ebp-4],ax
fldcw word ptr [ebp-4]
fistp dword ptr [ebp-8]
fldcw word ptr [ebp-2]
mov eax,dword ptr [ebp-8]
cmp eax,080000000h
je possible_overflow
return:
mov esp,ebp
pop ebp
ret 8
possible_overflow:
fld real8 ptr [ebp+8]
fcomp real8 ptr $DBLMAXINT
fnstsw ax
test ah,4
jne short return_zero
test ah,1
jne short return_MININT
return_MAXINT:
mov eax, 07fffffffh
jmp short return
return_zero:
xor eax, eax
jmp short return
return_MININT:
mov eax, 080000000h
jmp short return
?g_doubleToInt@Class_System_VTable@@SIHN@Z endp
;
; long System.VTable.doubleToLong(double)
;
align 16
?g_doubleToLong@Class_System_VTable@@SI_JN@Z proc
push ebp
mov ebp,esp
add esp,-12
fld real8 ptr [ebp+8]
wait
fnstcw word ptr [ebp-2]
wait
mov ax,word ptr [ebp-2]
or eax,0C00h
mov word ptr [ebp-4],ax
fldcw word ptr [ebp-4]
fistp qword ptr [ebp-12]
fldcw word ptr [ebp-2]
mov eax,dword ptr [ebp-12]
mov edx,dword ptr [ebp-8]
cmp edx,080000000h
je possible_overflow
return:
mov esp,ebp
pop ebp
ret 8
possible_overflow:
mov edx,eax ; save lsw
fld real8 ptr [ebp+8]
fild qword ptr $MAXLONG
fcompp
fnstsw ax
test ah,4
jne short return_zero
test ah,65
je short check_MINLONG
return_MAXLONG:
mov eax, 0ffffffffh
mov edx, 07fffffffh
jmp short return
return_zero:
xor eax, eax
xor edx, edx
jmp short return
check_MINLONG:
fld real8 ptr [ebp+8]
fild qword ptr $MINLONG
fcompp
fnstsw ax
test ah,1
jne short return_original
return_MINLONG:
xor edx, edx ; zero lsw
return_original:
mov eax, edx ; restore lsw to eax
mov edx, 080000000h
jmp short return
?g_doubleToLong@Class_System_VTable@@SI_JN@Z endp
;
; int System.VTable.floatToInt(float)
;
align 16
?g_floatToInt@Class_System_VTable@@SIHM@Z proc
push ebp
mov ebp,esp
add esp,-8
fld real4 ptr [ebp+8]
wait
fnstcw word ptr [ebp-2]
wait
xor eax,eax
mov ax,word ptr [ebp-2]
or eax,0C00h
mov word ptr [ebp-4],ax
fldcw word ptr [ebp-4]
fistp dword ptr [ebp-8]
fldcw word ptr [ebp-2]
mov eax,dword ptr [ebp-8]
cmp eax,080000000h
je possible_overflow
return:
mov esp,ebp
pop ebp
ret 4
possible_overflow:
fld real4 ptr [ebp+8]
fcomp real8 ptr $DBLMAXINT
fnstsw ax
test ah,4
jne short return_zero
test ah,1
jne short return_MININT
mov eax, 07fffffffh
jmp short return
return_zero:
xor eax, eax
jmp short return
return_MININT:
mov eax, 080000000h
jmp short return
?g_floatToInt@Class_System_VTable@@SIHM@Z endp
;
; long System.VTable.floatToLong(float)
;
align 16
?g_floatToLong@Class_System_VTable@@SI_JM@Z proc
push ebp
mov ebp,esp
add esp,-12
fld real4 ptr [ebp+8]
wait
fnstcw word ptr [ebp-2]
wait
mov ax,word ptr [ebp-2]
or eax,0C00h
mov word ptr [ebp-4],ax
fldcw word ptr [ebp-4]
fistp qword ptr [ebp-12]
fldcw word ptr [ebp-2]
mov eax,dword ptr [ebp-12]
mov edx,dword ptr [ebp-8]
cmp edx,080000000h
je possible_overflow
return:
mov esp,ebp
pop ebp
ret 4
possible_overflow:
mov edx,eax ; save lsw
fld real4 ptr [ebp+8]
fild qword ptr $MAXLONG
fcompp
fnstsw ax
test ah,4
jne short return_zero
test ah,65
je short check_MINLONG
return_MAXLONG:
mov eax, 0ffffffffh
mov edx, 07fffffffh
jmp short return
return_zero:
xor eax, eax
xor edx, edx
jmp short return
check_MINLONG:
fld real4 ptr [ebp+8]
fild qword ptr $MINLONG
fcompp
fnstsw ax
test ah,1
jne short return_original
return_MINLONG:
xor edx, edx ; zero lsw
return_original:
mov eax, edx ; restore lsw to eax
mov edx, 080000000h
jmp short return
?g_floatToLong@Class_System_VTable@@SI_JM@Z endp
;
; int System.VTable.checkedDoubleToInt(double)
;
align 16
?g_checkedDoubleToInt@Class_System_VTable@@SIHN@Z proc
push ebp
mov ebp,esp
add esp,-8
fld real8 ptr [ebp+8]
wait
fnstcw word ptr [ebp-2]
wait
mov ax,word ptr [ebp-2]
or eax,0C00h
mov word ptr [ebp-4],ax
fldcw word ptr [ebp-4]
fistp dword ptr [ebp-8]
fldcw word ptr [ebp-2]
mov eax,dword ptr [ebp-8]
cmp eax,080000000h
je possible_overflow
return:
mov esp,ebp
pop ebp
ret 8
possible_overflow:
fld real8 ptr [ebp+8]
fcomp real8 ptr $DBLMAXINT
fnstsw ax
test ah,4 ; test for unordered
jne short throw_exception
test ah,1 ; test for <$DBLMAXINT
jne short return_MININT
; src > $DBLMAXINT
; throw an overflow exception
jmp short throw_exception
return_MININT:
; check against $DBLMININT
fld real8 ptr [ebp+8]
fcomp real8 ptr $DBLMININT
fnstsw ax
test ah, 1 ; test for < $DBLMININT
jne short throw_exception ; throw exception if true
mov eax, 080000000h
jmp short return
throw_exception:
; throw an overflow exception
; set up stack frame so that it looks like a call to throwNewOverflowException
; from the caller of this function.
mov esp,ebp
pop ebp
pop eax ; grab return address
add esp, 4 ; move esp pass the first parameter.
mov [esp],eax ; overwrite argument
jmp ?g_throwNewOverflowException@Class_System_VTable@@SIXXZ
?g_checkedDoubleToInt@Class_System_VTable@@SIHN@Z endp
;
; long System.VTable.checkedDoubleToLong(double)
;
align 16
?g_checkedDoubleToLong@Class_System_VTable@@SI_JN@Z proc
push ebp
mov ebp,esp
add esp,-12
fld real8 ptr [ebp+8]
wait
fnstcw word ptr [ebp-2]
wait
mov ax,word ptr [ebp-2]
or eax,0C00h
mov word ptr [ebp-4],ax
fldcw word ptr [ebp-4]
fistp qword ptr [ebp-12]
fldcw word ptr [ebp-2]
mov eax,dword ptr [ebp-12]
mov edx,dword ptr [ebp-8]
cmp edx,080000000h
je possible_overflow
return:
mov esp,ebp
pop ebp
ret 8
possible_overflow:
mov edx,eax ; save lsw
fld real8 ptr [ebp+8]
fild qword ptr $MAXLONG
fcompp
fnstsw ax
test ah,4 ; test for unordered
jne short return_zero
test ah,65 ; test for <= $MAXLONG
je short check_MINLONG
return_MAXLONG:
; src > $MAXLONG
; throw an exception
jmp short throw_exception
return_zero:
jmp short throw_exception
check_MINLONG:
; src <= $MINLONG
fild qword ptr $MINLONG
fld real8 ptr [ebp+8]
fcompp ; real8 ptr [ebp+8] < $MINLONG
fnstsw ax
test ah,1
jne short throw_exception
return_MINLONG:
mov eax, edx ; restore lsw to eax
mov edx, 080000000h
jmp short return
throw_exception:
; throw an overflow exception
; set up stack frame so that it looks like a call to throwNewOverflowException
; from the caller of this function.
mov esp,ebp
pop ebp
pop eax ; grab return address
add esp, 4 ; move esp pass the first parameter.
mov [esp],eax ; overwrite argument
jmp ?g_throwNewOverflowException@Class_System_VTable@@SIXXZ
?g_checkedDoubleToLong@Class_System_VTable@@SI_JN@Z endp
;
; int System.VTable.checkedFloatToInt(float)
;
align 16
?g_checkedFloatToInt@Class_System_VTable@@SIHM@Z proc
push ebp
mov ebp,esp
add esp,-8
fld real4 ptr [ebp+8]
wait
fnstcw word ptr [ebp-2]
wait
xor eax,eax
mov ax,word ptr [ebp-2]
or eax,0C00h
mov word ptr [ebp-4],ax
fldcw word ptr [ebp-4]
fistp dword ptr [ebp-8]
fldcw word ptr [ebp-2]
mov eax,dword ptr [ebp-8]
cmp eax,080000000h
je possible_overflow
return:
mov esp,ebp
pop ebp
ret 4
possible_overflow:
fld real4 ptr [ebp+8]
fcomp real8 ptr $DBLMAXINT
fnstsw ax
test ah,4 ; test for unordered
jne short throw_exception
test ah,1 ; test for src < $DBLMAXINT
jne short return_MININT
; src > $DBLMAXINT
; throw an overflow exception
jmp short throw_exception
return_MININT:
; need to check against $DBLMININT, if it is less than,
; then throw an overflow exception
fld real4 ptr [ebp+8]
fcomp real8 ptr $DBLMININT
fnstsw ax
test ah,1 ; test for less than
jne short throw_exception
mov eax, 080000000h
jmp short return
throw_exception:
; throw an overflow exception
; set up stack frame so that it looks like a call to throwNewOverflowException
; from the caller of this function.
mov esp,ebp
pop ebp
pop eax ; grab return address
mov [esp],eax ; overwrite argument
jmp ?g_throwNewOverflowException@Class_System_VTable@@SIXXZ
?g_checkedFloatToInt@Class_System_VTable@@SIHM@Z endp
;
; long System.VTable.checkedFloatToLong(float)
;
align 16
?g_checkedFloatToLong@Class_System_VTable@@SI_JM@Z proc
push ebp
mov ebp,esp
add esp,-12
fld real4 ptr [ebp+8]
wait
fnstcw word ptr [ebp-2]
wait
mov ax,word ptr [ebp-2]
or eax,0C00h
mov word ptr [ebp-4],ax
fldcw word ptr [ebp-4]
fistp qword ptr [ebp-12]
fldcw word ptr [ebp-2]
mov eax,dword ptr [ebp-12]
mov edx,dword ptr [ebp-8]
cmp edx,080000000h
je possible_overflow
return:
mov esp,ebp
pop ebp
ret 4
possible_overflow:
mov edx,eax ; save lsw
fld real4 ptr [ebp+8]
fild qword ptr $MAXLONG
fcompp
fnstsw ax
test ah,4 ; test for unordered
jne short return_zero
test ah,65 ; test for <= $MAXLONG
je short check_MINLONG
return_MAXLONG:
; src > $MAXLONG
; throw an exception
jmp short throw_exception
return_zero:
; compare with $MAXLONG results in unordered
; throw an overflow exception
jmp short throw_exception
check_MINLONG:
; src <= $MINLONG
fild qword ptr $MINLONG
fld real4 ptr [ebp+8]
fcompp ; real8 ptr [ebp+8] < $MINLONG
fnstsw ax
test ah,1
jne short throw_exception ; throw an overflow exception when src < $MINLONG
return_MINLONG:
mov eax, edx ; restore lsw
mov edx, 080000000h
jmp short return
throw_exception:
; throw an overflow exception
; set up stack frame so that it looks like a call to throwNewOverflowException
; from the caller of this function.
mov esp,ebp
pop ebp
pop eax ; grab return address
mov [esp],eax ; overwrite argument
jmp ?g_throwNewOverflowException@Class_System_VTable@@SIXXZ
?g_checkedFloatToLong@Class_System_VTable@@SI_JM@Z endp
align 16
?g_floatRem@Class_System_VTable@@SIMMM@Z proc
fld real4 ptr [esp+8]
fld real4 ptr [esp+4]
fremloop:
fprem
fstsw ax
fwait
sahf
jp fremloop ; Continue while the FPU status bit C2 is set
ffree st(1)
ret 8
?g_floatRem@Class_System_VTable@@SIMMM@Z endp
align 16
?g_doubleRem@Class_System_VTable@@SINNN@Z proc
fld real8 ptr [esp+12]
fld real8 ptr [esp+4]
fremloop:
fprem
fstsw ax
fwait
sahf
jp fremloop ; Continue while the FPU status bit C2 is set
ffree st(1)
ret 16
?g_doubleRem@Class_System_VTable@@SINNN@Z endp
if EXCLUDED
;
; void __checkFPStackDepth0
;
align 16
__checkFPStackDepth0 proc
push ebp
mov ebp,esp
push eax
pushfd
xor eax,eax
wait
fnstsw ax
wait
shr eax,11
and eax,7
cmp eax,0
je ok
oops:
int 3
ok:
popfd
pop eax
pop ebp
ret 0
__checkFPStackDepth0 endp
;
; void __checkFPStackDepth1
;
align 16
__checkFPStackDepth1 proc
push ebp
mov ebp,esp
push eax
pushfd
xor eax,eax
wait
fnstsw ax
wait
shr eax,11
and eax,7
cmp eax,8-1
je ok
oops:
int 3
ok:
popfd
pop eax
pop ebp
ret 0
__checkFPStackDepth1 endp
;
; void __checkFPStackDepth2
;
align 16
__checkFPStackDepth2 proc
push ebp
mov ebp,esp
push eax
pushfd
xor eax,eax
wait
fnstsw ax
wait
shr eax,11
and eax,7
cmp eax,8-2
je ok
oops:
int 3
ok:
popfd
pop eax
pop ebp
ret 0
__checkFPStackDepth2 endp
;
; void __checkFPStackDepth3
;
align 16
__checkFPStackDepth3 proc
push ebp
mov ebp,esp
push eax
pushfd
xor eax,eax
wait
fnstsw ax
wait
shr eax,11
and eax,7
cmp eax,8-3
je ok
oops:
int 3
ok:
popfd
pop eax
pop ebp
ret 0
__checkFPStackDepth3 endp
;
; void __checkFPStackDepth4
;
align 16
__checkFPStackDepth4 proc
push ebp
mov ebp,esp
push eax
pushfd
xor eax,eax
wait
fnstsw ax
wait
shr eax,11
and eax,7
cmp eax,8-4
je ok
oops:
int 3
ok:
popfd
pop eax
pop ebp
ret 0
__checkFPStackDepth4 endp
;
; void __checkFPStackDepth5
;
align 16
__checkFPStackDepth5 proc
push ebp
mov ebp,esp
push eax
pushfd
xor eax,eax
wait
fnstsw ax
wait
shr eax,11
and eax,7
cmp eax,8-5
je ok
oops:
int 3
ok:
popfd
pop eax
pop ebp
ret 0
__checkFPStackDepth5 endp
;
; void __checkFPStackDepth6
;
align 16
__checkFPStackDepth6 proc
push ebp
mov ebp,esp
push eax
pushfd
xor eax,eax
wait
fnstsw ax
wait
shr eax,11
and eax,7
cmp eax,8-6
je ok
oops:
int 3
ok:
popfd
pop eax
pop ebp
ret 0
__checkFPStackDepth6 endp
;
; void __checkFPStackDepth7
;
align 16
__checkFPStackDepth7 proc
push ebp
mov ebp,esp
push eax
pushfd
xor eax,eax
wait
fnstsw ax
wait
shr eax,11
and eax,7
cmp eax,8-7
je ok
oops:
int 3
ok:
popfd
pop eax
pop ebp
ret 0
__checkFPStackDepth7 endp
endif ; EXCLUDED
;;;
;;;
;;;
;;;
ifdef SINGULARITY
?g_ZeroPages@Class_System_Buffer@@SIXPAEH@Z proc
;; ECX = dst
;; EDX = len (bytes)
push ebp
mov ebp, esp
pxor mm0, mm0
next:
movntq [ecx + 0], mm0
movntq [ecx + 8], mm0
movntq [ecx + 16], mm0
movntq [ecx + 24], mm0
movntq [ecx + 32], mm0
movntq [ecx + 40], mm0
movntq [ecx + 48], mm0
movntq [ecx + 56], mm0
add ecx, 64
sub edx, 64
ja next
sfence
emms
pop ebp
ret
?g_ZeroPages@Class_System_Buffer@@SIXPAEH@Z endp
?g_CopyPages@Class_System_Buffer@@SIXPAE0H@Z proc
;; ECX = dst
;; EDX = src
;; [ebp+8] len (bytes)
push ebp
mov ebp, esp
mov eax, [ebp + 8]
cmp ecx, edx
js down
;; destination is lower than source
add ecx, eax
add edx, eax
sub ecx, 64
sub edx, 64
up:
movq mm0, [edx + 0]
movq mm1, [edx + 8]
movq mm2, [edx + 16]
movq mm3, [edx + 24]
movq mm4, [edx + 32]
movq mm5, [edx + 40]
movq mm6, [edx + 48]
movq mm7, [edx + 56]
movntq [ecx + 0], mm0
movntq [ecx + 8], mm1
movntq [ecx + 16], mm2
movntq [ecx + 24], mm3
movntq [ecx + 32], mm4
movntq [ecx + 40], mm5
movntq [ecx + 48], mm6
movntq [ecx + 56], mm7
sub ecx, 64
sub edx, 64
sub eax, 64
ja up
sfence
emms
pop ebp
ret 4
;; destination is higher than source
down:
movq mm0, [edx + 0]
movq mm1, [edx + 8]
movq mm2, [edx + 16]
movq mm3, [edx + 24]
movq mm4, [edx + 32]
movq mm5, [edx + 40]
movq mm6, [edx + 48]
movq mm7, [edx + 56]
movntq [ecx + 0], mm0
movntq [ecx + 8], mm1
movntq [ecx + 16], mm2
movntq [ecx + 24], mm3
movntq [ecx + 32], mm4
movntq [ecx + 40], mm5
movntq [ecx + 48], mm6
movntq [ecx + 56], mm7
add ecx, 64
add edx, 64
sub eax, 64
ja down
sfence
emms
pop ebp
ret 4
?g_CopyPages@Class_System_Buffer@@SIXPAE0H@Z endp
endif
end