diff options
Diffstat (limited to 'src/pal/src/arch')
-rw-r--r-- | src/pal/src/arch/amd64/activationhandlerwrapper.S (renamed from src/pal/src/arch/i386/activationhandlerwrapper.S) | 0 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/asmconstants.h | 106 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/context.S (renamed from src/pal/src/arch/i386/context.S) | 0 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/context2.S | 259 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/debugbreak.S | 12 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/dispatchexceptionwrapper.S (renamed from src/pal/src/arch/i386/dispatchexceptionwrapper.S) | 0 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/exceptionhelper.S | 42 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/optimizedtls.cpp (renamed from src/pal/src/arch/i386/optimizedtls.cpp) | 2 | ||||
-rw-r--r-- | src/pal/src/arch/amd64/processor.cpp | 64 | ||||
-rw-r--r-- | src/pal/src/arch/arm/exceptionhelper.S | 2 | ||||
-rw-r--r-- | src/pal/src/arch/i386/asmconstants.h | 76 | ||||
-rw-r--r-- | src/pal/src/arch/i386/context2.S | 354 | ||||
-rw-r--r-- | src/pal/src/arch/i386/exceptionhelper.S | 47 |
13 files changed, 632 insertions, 332 deletions
diff --git a/src/pal/src/arch/i386/activationhandlerwrapper.S b/src/pal/src/arch/amd64/activationhandlerwrapper.S index 63f718e81f..63f718e81f 100644 --- a/src/pal/src/arch/i386/activationhandlerwrapper.S +++ b/src/pal/src/arch/amd64/activationhandlerwrapper.S diff --git a/src/pal/src/arch/amd64/asmconstants.h b/src/pal/src/arch/amd64/asmconstants.h new file mode 100644 index 0000000000..182c1191e4 --- /dev/null +++ b/src/pal/src/arch/amd64/asmconstants.h @@ -0,0 +1,106 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifdef BIT64 + +#define CONTEXT_AMD64 0x100000 + +#define CONTEXT_CONTROL 1 // SegSs, Rsp, SegCs, Rip, and EFlags +#define CONTEXT_INTEGER 2 // Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, R8-R15 +#define CONTEXT_SEGMENTS 4 // SegDs, SegEs, SegFs, SegGs +#define CONTEXT_FLOATING_POINT 8 +#define CONTEXT_DEBUG_REGISTERS 16 // Dr0-Dr3 and Dr6-Dr7 + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +#define CONTEXT_XSTATE 64 + +#define CONTEXT_ContextFlags 6*8 +#define CONTEXT_SegCs CONTEXT_ContextFlags+8 +#define CONTEXT_SegDs CONTEXT_SegCs+2 +#define CONTEXT_SegEs CONTEXT_SegDs+2 +#define CONTEXT_SegFs CONTEXT_SegEs+2 +#define CONTEXT_SegGs CONTEXT_SegFs+2 +#define CONTEXT_SegSs CONTEXT_SegGs+2 +#define CONTEXT_EFlags CONTEXT_SegSs+2 +#define CONTEXT_Dr0 CONTEXT_EFlags+4 +#define CONTEXT_Dr1 CONTEXT_Dr0+8 +#define CONTEXT_Dr2 CONTEXT_Dr1+8 +#define CONTEXT_Dr3 CONTEXT_Dr2+8 +#define CONTEXT_Dr6 CONTEXT_Dr3+8 +#define CONTEXT_Dr7 CONTEXT_Dr6+8 +#define CONTEXT_Rax CONTEXT_Dr7+8 +#define CONTEXT_Rcx CONTEXT_Rax+8 +#define CONTEXT_Rdx CONTEXT_Rcx+8 +#define CONTEXT_Rbx CONTEXT_Rdx+8 +#define CONTEXT_Rsp CONTEXT_Rbx+8 +#define CONTEXT_Rbp CONTEXT_Rsp+8 +#define CONTEXT_Rsi CONTEXT_Rbp+8 +#define CONTEXT_Rdi CONTEXT_Rsi+8 +#define CONTEXT_R8 CONTEXT_Rdi+8 +#define CONTEXT_R9 CONTEXT_R8+8 +#define CONTEXT_R10 CONTEXT_R9+8 +#define CONTEXT_R11 CONTEXT_R10+8 +#define CONTEXT_R12 CONTEXT_R11+8 +#define CONTEXT_R13 CONTEXT_R12+8 +#define CONTEXT_R14 CONTEXT_R13+8 +#define CONTEXT_R15 CONTEXT_R14+8 +#define CONTEXT_Rip CONTEXT_R15+8 +#define CONTEXT_FltSave CONTEXT_Rip+8 +#define FLOATING_SAVE_AREA_SIZE 4*8+24*16+96 +#define CONTEXT_Xmm0 CONTEXT_FltSave+10*16 +#define CONTEXT_Xmm1 CONTEXT_Xmm0+16 +#define CONTEXT_Xmm2 CONTEXT_Xmm1+16 +#define CONTEXT_Xmm3 CONTEXT_Xmm2+16 +#define CONTEXT_Xmm4 CONTEXT_Xmm3+16 +#define CONTEXT_Xmm5 CONTEXT_Xmm4+16 +#define CONTEXT_Xmm6 CONTEXT_Xmm5+16 +#define CONTEXT_Xmm7 CONTEXT_Xmm6+16 +#define CONTEXT_Xmm8 CONTEXT_Xmm7+16 +#define CONTEXT_Xmm9 CONTEXT_Xmm8+16 +#define CONTEXT_Xmm10 CONTEXT_Xmm9+16 +#define CONTEXT_Xmm11 CONTEXT_Xmm10+16 +#define CONTEXT_Xmm12 CONTEXT_Xmm11+16 +#define CONTEXT_Xmm13 CONTEXT_Xmm12+16 +#define CONTEXT_Xmm14 CONTEXT_Xmm13+16 +#define CONTEXT_Xmm15 CONTEXT_Xmm14+16 +#define CONTEXT_VectorRegister CONTEXT_FltSave+FLOATING_SAVE_AREA_SIZE +#define CONTEXT_VectorControl CONTEXT_VectorRegister+16*26 +#define CONTEXT_DebugControl CONTEXT_VectorControl+8 +#define CONTEXT_LastBranchToRip CONTEXT_DebugControl+8 +#define CONTEXT_LastBranchFromRip CONTEXT_LastBranchToRip+8 +#define CONTEXT_LastExceptionToRip CONTEXT_LastBranchFromRip+8 +#define CONTEXT_LastExceptionFromRip CONTEXT_LastExceptionToRip+8 +#define CONTEXT_Size CONTEXT_LastExceptionFromRip+8 + +#else // BIT64 + +#define CONTEXT_ContextFlags 0 +#define CONTEXT_FLOATING_POINT 8 +#define CONTEXT_FloatSave 7*4 +#define FLOATING_SAVE_AREA_SIZE 8*4+80 +#define CONTEXT_Edi CONTEXT_FloatSave + FLOATING_SAVE_AREA_SIZE + 4*4 +#define CONTEXT_Esi CONTEXT_Edi+4 +#define CONTEXT_Ebx CONTEXT_Esi+4 +#define CONTEXT_Edx CONTEXT_Ebx+4 +#define CONTEXT_Ecx CONTEXT_Edx+4 +#define CONTEXT_Eax CONTEXT_Ecx+4 +#define CONTEXT_Ebp CONTEXT_Eax+4 +#define CONTEXT_Eip CONTEXT_Ebp+4 +#define CONTEXT_SegCs CONTEXT_Eip+4 +#define CONTEXT_EFlags CONTEXT_SegCs+4 +#define CONTEXT_Esp CONTEXT_EFlags+4 +#define CONTEXT_SegSs CONTEXT_Esp+4 +#define CONTEXT_EXTENDED_REGISTERS 32 +#define CONTEXT_ExtendedRegisters CONTEXT_SegSs+4 +#define CONTEXT_Xmm0 CONTEXT_ExtendedRegisters+160 +#define CONTEXT_Xmm1 CONTEXT_Xmm0+16 +#define CONTEXT_Xmm2 CONTEXT_Xmm1+16 +#define CONTEXT_Xmm3 CONTEXT_Xmm2+16 +#define CONTEXT_Xmm4 CONTEXT_Xmm3+16 +#define CONTEXT_Xmm5 CONTEXT_Xmm4+16 +#define CONTEXT_Xmm6 CONTEXT_Xmm5+16 +#define CONTEXT_Xmm7 CONTEXT_Xmm6+16 + +#endif // BIT64 diff --git a/src/pal/src/arch/i386/context.S b/src/pal/src/arch/amd64/context.S index f8a2dca89c..f8a2dca89c 100644 --- a/src/pal/src/arch/i386/context.S +++ b/src/pal/src/arch/amd64/context.S diff --git a/src/pal/src/arch/amd64/context2.S b/src/pal/src/arch/amd64/context2.S new file mode 100644 index 0000000000..0e93e81a55 --- /dev/null +++ b/src/pal/src/arch/amd64/context2.S @@ -0,0 +1,259 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// Implementation of _CONTEXT_CaptureContext for the Intel x86 platform. +// This function is processor dependent. It is used by exception handling, +// and is always apply to the current thread. +// + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +#ifdef BIT64 + +#define IRETFRAME_Rip 0 +#define IRETFRAME_SegCs IRETFRAME_Rip+8 +#define IRETFRAME_EFlags IRETFRAME_SegCs+8 +#define IRETFRAME_Rsp IRETFRAME_EFlags+8 +#define IRETFRAME_SegSs IRETFRAME_Rsp+8 +#define IRetFrameLength IRETFRAME_SegSs+8 +#define IRetFrameLengthAligned 16*((IRetFrameLength+8)/16) + +// Incoming: +// RDI: Context* +// +LEAF_ENTRY CONTEXT_CaptureContext, _TEXT + // Save processor flags before calling any of the following 'test' instructions + // because they will modify state of some flags + push_eflags + END_PROLOGUE + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER + je LOCAL_LABEL(Done_CONTEXT_INTEGER) + mov [rdi + CONTEXT_Rdi], rdi + mov [rdi + CONTEXT_Rsi], rsi + mov [rdi + CONTEXT_Rbx], rbx + mov [rdi + CONTEXT_Rdx], rdx + mov [rdi + CONTEXT_Rcx], rcx + mov [rdi + CONTEXT_Rax], rax + mov [rdi + CONTEXT_Rbp], rbp + mov [rdi + CONTEXT_R8], r8 + mov [rdi + CONTEXT_R9], r9 + mov [rdi + CONTEXT_R10], r10 + mov [rdi + CONTEXT_R11], r11 + mov [rdi + CONTEXT_R12], r12 + mov [rdi + CONTEXT_R13], r13 + mov [rdi + CONTEXT_R14], r14 + mov [rdi + CONTEXT_R15], r15 +LOCAL_LABEL(Done_CONTEXT_INTEGER): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL + je LOCAL_LABEL(Done_CONTEXT_CONTROL) + + // Return address is @ (RSP + 8) + mov rdx, [rsp + 8] + mov [rdi + CONTEXT_Rip], rdx +.att_syntax + mov %cs, CONTEXT_SegCs(%rdi) +.intel_syntax noprefix + // Get the value of EFlags that was pushed on stack at the beginning of the function + mov rdx, [rsp] + mov [rdi + CONTEXT_EFlags], edx + lea rdx, [rsp + 16] + mov [rdi + CONTEXT_Rsp], rdx +.att_syntax + mov %ss, CONTEXT_SegSs(%rdi) +.intel_syntax noprefix +LOCAL_LABEL(Done_CONTEXT_CONTROL): + + // Need to double check this is producing the right result + // also that FFSXR (fast save/restore) is not turned on + // otherwise it omits the xmm registers. + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + je LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) + fxsave [rdi + CONTEXT_FltSave] +LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS + je LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS) + mov rdx, dr0 + mov [rdi + CONTEXT_Dr0], rdx + mov rdx, dr1 + mov [rdi + CONTEXT_Dr1], rdx + mov rdx, dr2 + mov [rdi + CONTEXT_Dr2], rdx + mov rdx, dr3 + mov [rdi + CONTEXT_Dr3], rdx + mov rdx, dr6 + mov [rdi + CONTEXT_Dr6], rdx + mov rdx, dr7 + mov [rdi + CONTEXT_Dr7], rdx +LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS): + + free_stack 8 + ret +LEAF_END CONTEXT_CaptureContext, _TEXT + +LEAF_ENTRY RtlCaptureContext, _TEXT + mov DWORD PTR [rdi + CONTEXT_ContextFlags], (CONTEXT_AMD64 | CONTEXT_FULL | CONTEXT_SEGMENTS) + jmp C_FUNC(CONTEXT_CaptureContext) +LEAF_END RtlCaptureContext, _TEXT + +LEAF_ENTRY RtlRestoreContext, _TEXT + push_nonvol_reg rbp + alloc_stack (IRetFrameLengthAligned) + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS + je LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS) + mov rdx, [rdi + CONTEXT_Dr0] + mov dr0, rdx + mov rdx, [rdi + CONTEXT_Dr1] + mov dr1, rdx + mov rdx, [rdi + CONTEXT_Dr2] + mov dr2, rdx + mov rdx, [rdi + CONTEXT_Dr3] + mov dr3, rdx + mov rdx, [rdi + CONTEXT_Dr6] + mov dr6, rdx + mov rdx, [rdi + CONTEXT_Dr7] + mov dr7, rdx +LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + je LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT) + fxrstor [rdi + CONTEXT_FltSave] +LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_XSTATE + je LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE) + + // Restore the extended state (for now, this is just the upper halves of YMM registers) + vinsertf128 ymm0, ymm0, xmmword ptr [rdi + (CONTEXT_VectorRegister + 0 * 16)], 1 + vinsertf128 ymm1, ymm1, xmmword ptr [rdi + (CONTEXT_VectorRegister + 1 * 16)], 1 + vinsertf128 ymm2, ymm2, xmmword ptr [rdi + (CONTEXT_VectorRegister + 2 * 16)], 1 + vinsertf128 ymm3, ymm3, xmmword ptr [rdi + (CONTEXT_VectorRegister + 3 * 16)], 1 + vinsertf128 ymm4, ymm4, xmmword ptr [rdi + (CONTEXT_VectorRegister + 4 * 16)], 1 + vinsertf128 ymm5, ymm5, xmmword ptr [rdi + (CONTEXT_VectorRegister + 5 * 16)], 1 + vinsertf128 ymm6, ymm6, xmmword ptr [rdi + (CONTEXT_VectorRegister + 6 * 16)], 1 + vinsertf128 ymm7, ymm7, xmmword ptr [rdi + (CONTEXT_VectorRegister + 7 * 16)], 1 + vinsertf128 ymm8, ymm8, xmmword ptr [rdi + (CONTEXT_VectorRegister + 8 * 16)], 1 + vinsertf128 ymm9, ymm9, xmmword ptr [rdi + (CONTEXT_VectorRegister + 9 * 16)], 1 + vinsertf128 ymm10, ymm10, xmmword ptr [rdi + (CONTEXT_VectorRegister + 10 * 16)], 1 + vinsertf128 ymm11, ymm11, xmmword ptr [rdi + (CONTEXT_VectorRegister + 11 * 16)], 1 + vinsertf128 ymm12, ymm12, xmmword ptr [rdi + (CONTEXT_VectorRegister + 12 * 16)], 1 + vinsertf128 ymm13, ymm13, xmmword ptr [rdi + (CONTEXT_VectorRegister + 13 * 16)], 1 + vinsertf128 ymm14, ymm14, xmmword ptr [rdi + (CONTEXT_VectorRegister + 14 * 16)], 1 + vinsertf128 ymm15, ymm15, xmmword ptr [rdi + (CONTEXT_VectorRegister + 15 * 16)], 1 +LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE): + + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL + je LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL) + + // The control registers are restored via the iret instruction + // so we build the frame for the iret on the stack. +#ifdef __APPLE__ +.att_syntax + // On OSX, we cannot read SS via the thread_get_context and RtlRestoreContext + // needs to be used on context extracted by thread_get_context. So we + // don't change the SS. + mov %ss, %ax +.intel_syntax noprefix +#else + mov ax, [rdi + CONTEXT_SegSs] +#endif + mov [rsp + IRETFRAME_SegSs], ax + mov rax, [rdi + CONTEXT_Rsp] + mov [rsp + IRETFRAME_Rsp], rax + mov eax, [rdi + CONTEXT_EFlags] + mov [rsp + IRETFRAME_EFlags], eax + mov ax, [rdi + CONTEXT_SegCs] + mov [rsp + IRETFRAME_SegCs], ax + mov rax, [rdi + CONTEXT_Rip] + mov [rsp + IRETFRAME_Rip], rax + +LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL): + // Remember the result of the test for the CONTEXT_CONTROL + push_eflags + test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER + je LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER) + mov rsi, [rdi + CONTEXT_Rsi] + mov rbx, [rdi + CONTEXT_Rbx] + mov rdx, [rdi + CONTEXT_Rdx] + mov rcx, [rdi + CONTEXT_Rcx] + mov rax, [rdi + CONTEXT_Rax] + mov rbp, [rdi + CONTEXT_Rbp] + mov r8, [rdi + CONTEXT_R8] + mov r9, [rdi + CONTEXT_R9] + mov r10, [rdi + CONTEXT_R10] + mov r11, [rdi + CONTEXT_R11] + mov r12, [rdi + CONTEXT_R12] + mov r13, [rdi + CONTEXT_R13] + mov r14, [rdi + CONTEXT_R14] + mov r15, [rdi + CONTEXT_R15] + mov rdi, [rdi + CONTEXT_Rdi] +LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER): + + // Restore the result of the test for the CONTEXT_CONTROL + pop_eflags + je LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) + // The function was asked to restore the control registers, so + // we perform iretq that restores them all. + // We don't return to the caller in this case. + iretq +LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): + + // The function was not asked to restore the control registers + // so we return back to the caller. + free_stack (IRetFrameLengthAligned) + pop_nonvol_reg rbp + ret +LEAF_END RtlRestoreContext, _TEXT + +#else + + .globl C_FUNC(CONTEXT_CaptureContext) +C_FUNC(CONTEXT_CaptureContext): + push %eax + mov 8(%esp), %eax + mov %edi, CONTEXT_Edi(%eax) + mov %esi, CONTEXT_Esi(%eax) + mov %ebx, CONTEXT_Ebx(%eax) + mov %edx, CONTEXT_Edx(%eax) + mov %ecx, CONTEXT_Ecx(%eax) + pop %ecx + mov %ecx, CONTEXT_Eax(%eax) + mov %ebp, CONTEXT_Ebp(%eax) + mov (%esp), %edx + mov %edx, CONTEXT_Eip(%eax) + push %cs + pop %edx + mov %edx, CONTEXT_SegCs(%eax) + pushf + pop %edx + mov %edx, CONTEXT_EFlags(%eax) + lea 4(%esp), %edx + mov %edx, CONTEXT_Esp(%eax) + push %ss + pop %edx + mov %edx, CONTEXT_SegSs(%eax) + testb $CONTEXT_FLOATING_POINT, CONTEXT_ContextFlags(%eax) + je 0f + fnsave CONTEXT_FloatSave(%eax) + frstor CONTEXT_FloatSave(%eax) +0: + testb $CONTEXT_EXTENDED_REGISTERS, CONTEXT_ContextFlags(%eax) + je 2f + movdqu %xmm0, CONTEXT_Xmm0(%eax) + movdqu %xmm1, CONTEXT_Xmm1(%eax) + movdqu %xmm2, CONTEXT_Xmm2(%eax) + movdqu %xmm3, CONTEXT_Xmm3(%eax) + movdqu %xmm4, CONTEXT_Xmm4(%eax) + movdqu %xmm5, CONTEXT_Xmm5(%eax) + movdqu %xmm6, CONTEXT_Xmm6(%eax) + movdqu %xmm7, CONTEXT_Xmm7(%eax) +2: + ret + +#endif diff --git a/src/pal/src/arch/amd64/debugbreak.S b/src/pal/src/arch/amd64/debugbreak.S new file mode 100644 index 0000000000..3065e4064c --- /dev/null +++ b/src/pal/src/arch/amd64/debugbreak.S @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.intel_syntax noprefix +#include "unixasmmacros.inc" + +LEAF_ENTRY DBG_DebugBreak, _TEXT + int3 + ret +LEAF_END_MARKED DBG_DebugBreak, _TEXT + diff --git a/src/pal/src/arch/i386/dispatchexceptionwrapper.S b/src/pal/src/arch/amd64/dispatchexceptionwrapper.S index ee5ff468d6..ee5ff468d6 100644 --- a/src/pal/src/arch/i386/dispatchexceptionwrapper.S +++ b/src/pal/src/arch/amd64/dispatchexceptionwrapper.S diff --git a/src/pal/src/arch/amd64/exceptionhelper.S b/src/pal/src/arch/amd64/exceptionhelper.S new file mode 100644 index 0000000000..b7b34ace41 --- /dev/null +++ b/src/pal/src/arch/amd64/exceptionhelper.S @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +////////////////////////////////////////////////////////////////////////// +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers from the passed in context, sets the RSP to that frame and sets the +// return address to the target frame's RIP. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); +LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT + // Save the RBP to the stack so that the unwind can work at the instruction after + // loading the RBP from the context, but before loading the RSP from the context. + push_nonvol_reg rbp + mov r12, [rdi + CONTEXT_R12] + mov r13, [rdi + CONTEXT_R13] + mov r14, [rdi + CONTEXT_R14] + mov r15, [rdi + CONTEXT_R15] + mov rbx, [rdi + CONTEXT_Rbx] + mov rbp, [rdi + CONTEXT_Rbp] + mov rsp, [rdi + CONTEXT_Rsp] + // The RSP was set to the target frame's value, so the current function's + // CFA is now right at the RSP. + .cfi_def_cfa_offset 0 + + // Indicate that now that we have moved the RSP to the target address, + // the RBP is no longer saved in the current stack frame. + .cfi_restore rbp + + mov rax, [rdi + CONTEXT_Rip] + + // Store return address to the stack + push_register rax + // The PAL_SEHException pointer + mov rdi, rsi + jmp EXTERNAL_C_FUNC(ThrowExceptionHelper) +LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/src/pal/src/arch/i386/optimizedtls.cpp b/src/pal/src/arch/amd64/optimizedtls.cpp index 910a6eb931..cd89db6b0a 100644 --- a/src/pal/src/arch/i386/optimizedtls.cpp +++ b/src/pal/src/arch/amd64/optimizedtls.cpp @@ -79,7 +79,7 @@ CorUnix::TLSMakeOptimizedGetter( } // Need to preserve %ecx, %edx, and %esi registers as specified in - // GetThreadGeneric(void) in vm/i386/asmhelpers.s + // GetThreadGeneric(void) in vm/amd64/asmhelpers.s p[i++] = 0x51; // push %ecx p[i++] = 0x52; // push %edx p[i++] = 0x89; // mov %esp,%eax // %eax = sp; diff --git a/src/pal/src/arch/amd64/processor.cpp b/src/pal/src/arch/amd64/processor.cpp new file mode 100644 index 0000000000..ac3d448a81 --- /dev/null +++ b/src/pal/src/arch/amd64/processor.cpp @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + + + +Module Name: + + processor.cpp + +Abstract: + + Implementation of processor related functions for the Intel x86/x64 + platforms. These functions are processor dependent. + + + +--*/ + +#include "pal/palinternal.h" + +/*++ +Function: +YieldProcessor + +The YieldProcessor function signals to the processor to give resources +to threads that are waiting for them. This macro is only effective on +processors that support technology allowing multiple threads running +on a single processor, such as Intel's Hyper-Threading technology. + +--*/ +void +PALAPI +YieldProcessor( + VOID) +{ + __asm__ __volatile__ ( + "rep\n" + "nop" + ); +} + +/*++ +Function: +XmmYmmStateSupport + +Check if OS has enabled both XMM and YMM state support + +Return value: +1 if XMM and YMM are enabled, 0 otherwise +--*/ +extern "C" unsigned int XmmYmmStateSupport() +{ + unsigned int eax; + __asm(" xgetbv\n" \ + : "=a"(eax) /*output in eax*/\ + : "c"(0) /*inputs - 0 in ecx*/\ + : "eax", "edx" /* registers that are clobbered*/ + ); + // Check OS has enabled both XMM and YMM state support + return ((eax & 0x06) == 0x06) ? 1 : 0; +} diff --git a/src/pal/src/arch/arm/exceptionhelper.S b/src/pal/src/arch/arm/exceptionhelper.S index ed1c9c3dc2..76cdcba9b4 100644 --- a/src/pal/src/arch/arm/exceptionhelper.S +++ b/src/pal/src/arch/arm/exceptionhelper.S @@ -10,7 +10,7 @@ // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT - // Ported from src/pal/src/arch/i386/exceptionhelper.S + // Ported from src/pal/src/arch/amd64/exceptionhelper.S push_nonvol_reg {r7} /* FP. x64-RBP */ ldr r4, [r0, #(CONTEXT_R4)] diff --git a/src/pal/src/arch/i386/asmconstants.h b/src/pal/src/arch/i386/asmconstants.h index 182c1191e4..ff763ef16b 100644 --- a/src/pal/src/arch/i386/asmconstants.h +++ b/src/pal/src/arch/i386/asmconstants.h @@ -2,80 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#ifdef BIT64 - -#define CONTEXT_AMD64 0x100000 - -#define CONTEXT_CONTROL 1 // SegSs, Rsp, SegCs, Rip, and EFlags -#define CONTEXT_INTEGER 2 // Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, R8-R15 -#define CONTEXT_SEGMENTS 4 // SegDs, SegEs, SegFs, SegGs -#define CONTEXT_FLOATING_POINT 8 -#define CONTEXT_DEBUG_REGISTERS 16 // Dr0-Dr3 and Dr6-Dr7 - -#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) - -#define CONTEXT_XSTATE 64 - -#define CONTEXT_ContextFlags 6*8 -#define CONTEXT_SegCs CONTEXT_ContextFlags+8 -#define CONTEXT_SegDs CONTEXT_SegCs+2 -#define CONTEXT_SegEs CONTEXT_SegDs+2 -#define CONTEXT_SegFs CONTEXT_SegEs+2 -#define CONTEXT_SegGs CONTEXT_SegFs+2 -#define CONTEXT_SegSs CONTEXT_SegGs+2 -#define CONTEXT_EFlags CONTEXT_SegSs+2 -#define CONTEXT_Dr0 CONTEXT_EFlags+4 -#define CONTEXT_Dr1 CONTEXT_Dr0+8 -#define CONTEXT_Dr2 CONTEXT_Dr1+8 -#define CONTEXT_Dr3 CONTEXT_Dr2+8 -#define CONTEXT_Dr6 CONTEXT_Dr3+8 -#define CONTEXT_Dr7 CONTEXT_Dr6+8 -#define CONTEXT_Rax CONTEXT_Dr7+8 -#define CONTEXT_Rcx CONTEXT_Rax+8 -#define CONTEXT_Rdx CONTEXT_Rcx+8 -#define CONTEXT_Rbx CONTEXT_Rdx+8 -#define CONTEXT_Rsp CONTEXT_Rbx+8 -#define CONTEXT_Rbp CONTEXT_Rsp+8 -#define CONTEXT_Rsi CONTEXT_Rbp+8 -#define CONTEXT_Rdi CONTEXT_Rsi+8 -#define CONTEXT_R8 CONTEXT_Rdi+8 -#define CONTEXT_R9 CONTEXT_R8+8 -#define CONTEXT_R10 CONTEXT_R9+8 -#define CONTEXT_R11 CONTEXT_R10+8 -#define CONTEXT_R12 CONTEXT_R11+8 -#define CONTEXT_R13 CONTEXT_R12+8 -#define CONTEXT_R14 CONTEXT_R13+8 -#define CONTEXT_R15 CONTEXT_R14+8 -#define CONTEXT_Rip CONTEXT_R15+8 -#define CONTEXT_FltSave CONTEXT_Rip+8 -#define FLOATING_SAVE_AREA_SIZE 4*8+24*16+96 -#define CONTEXT_Xmm0 CONTEXT_FltSave+10*16 -#define CONTEXT_Xmm1 CONTEXT_Xmm0+16 -#define CONTEXT_Xmm2 CONTEXT_Xmm1+16 -#define CONTEXT_Xmm3 CONTEXT_Xmm2+16 -#define CONTEXT_Xmm4 CONTEXT_Xmm3+16 -#define CONTEXT_Xmm5 CONTEXT_Xmm4+16 -#define CONTEXT_Xmm6 CONTEXT_Xmm5+16 -#define CONTEXT_Xmm7 CONTEXT_Xmm6+16 -#define CONTEXT_Xmm8 CONTEXT_Xmm7+16 -#define CONTEXT_Xmm9 CONTEXT_Xmm8+16 -#define CONTEXT_Xmm10 CONTEXT_Xmm9+16 -#define CONTEXT_Xmm11 CONTEXT_Xmm10+16 -#define CONTEXT_Xmm12 CONTEXT_Xmm11+16 -#define CONTEXT_Xmm13 CONTEXT_Xmm12+16 -#define CONTEXT_Xmm14 CONTEXT_Xmm13+16 -#define CONTEXT_Xmm15 CONTEXT_Xmm14+16 -#define CONTEXT_VectorRegister CONTEXT_FltSave+FLOATING_SAVE_AREA_SIZE -#define CONTEXT_VectorControl CONTEXT_VectorRegister+16*26 -#define CONTEXT_DebugControl CONTEXT_VectorControl+8 -#define CONTEXT_LastBranchToRip CONTEXT_DebugControl+8 -#define CONTEXT_LastBranchFromRip CONTEXT_LastBranchToRip+8 -#define CONTEXT_LastExceptionToRip CONTEXT_LastBranchFromRip+8 -#define CONTEXT_LastExceptionFromRip CONTEXT_LastExceptionToRip+8 -#define CONTEXT_Size CONTEXT_LastExceptionFromRip+8 - -#else // BIT64 - #define CONTEXT_ContextFlags 0 #define CONTEXT_FLOATING_POINT 8 #define CONTEXT_FloatSave 7*4 @@ -102,5 +28,3 @@ #define CONTEXT_Xmm5 CONTEXT_Xmm4+16 #define CONTEXT_Xmm6 CONTEXT_Xmm5+16 #define CONTEXT_Xmm7 CONTEXT_Xmm6+16 - -#endif // BIT64 diff --git a/src/pal/src/arch/i386/context2.S b/src/pal/src/arch/i386/context2.S index 0e93e81a55..16cbcc855c 100644 --- a/src/pal/src/arch/i386/context2.S +++ b/src/pal/src/arch/i386/context2.S @@ -1,259 +1,151 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// -// Implementation of _CONTEXT_CaptureContext for the Intel x86 platform. -// This function is processor dependent. It is used by exception handling, -// and is always apply to the current thread. -// .intel_syntax noprefix #include "unixasmmacros.inc" #include "asmconstants.h" -#ifdef BIT64 - -#define IRETFRAME_Rip 0 -#define IRETFRAME_SegCs IRETFRAME_Rip+8 -#define IRETFRAME_EFlags IRETFRAME_SegCs+8 -#define IRETFRAME_Rsp IRETFRAME_EFlags+8 -#define IRETFRAME_SegSs IRETFRAME_Rsp+8 -#define IRetFrameLength IRETFRAME_SegSs+8 -#define IRetFrameLengthAligned 16*((IRetFrameLength+8)/16) - -// Incoming: -// RDI: Context* +// +// Implementation of CONTEXT_CaptureContext for the Intel x86 platform. +// +// extern void CONTEXT_CaptureContext(LPCONTEXT lpContext); +// +// This function is processor-dependent. It is used by exception handling, +// and is always apply to the current thread. // LEAF_ENTRY CONTEXT_CaptureContext, _TEXT - // Save processor flags before calling any of the following 'test' instructions - // because they will modify state of some flags - push_eflags - END_PROLOGUE + // Store + push eax + push ebx + + // The stack will contain the following elements on the top of + // the caller's stack + // [ebx] / esp + 00 + // [eax] / esp + 04 + // [ret] / esp + 08 + // [arg0: lpContext] / esp + 12 + + mov eax, [esp + 12] // eax will point to lpContext + + // Capture INTEGER registers + mov ebx, [esp + 4] + mov [eax + CONTEXT_Eax], ebx + mov ebx, [esp] + mov [eax + CONTEXT_Ebx], ebx + mov [eax + CONTEXT_Ecx], ecx + mov [eax + CONTEXT_Edx], edx + mov [eax + CONTEXT_Esi], esi + mov [eax + CONTEXT_Edi], edi + + // Capture CONTROL registers + mov [eax + CONTEXT_Ebp], ebp + lea ebx, [esp + 12] + mov [eax + CONTEXT_Esp], ebx + mov ebx, [esp + 8] + mov [eax + CONTEXT_Eip], ebx + + push cs + xor ebx, ebx + pop bx + mov [eax + CONTEXT_SegCs], ebx + + push ss + xor ebx, ebx + pop bx + mov [eax + CONTEXT_SegSs], ebx - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER - je LOCAL_LABEL(Done_CONTEXT_INTEGER) - mov [rdi + CONTEXT_Rdi], rdi - mov [rdi + CONTEXT_Rsi], rsi - mov [rdi + CONTEXT_Rbx], rbx - mov [rdi + CONTEXT_Rdx], rdx - mov [rdi + CONTEXT_Rcx], rcx - mov [rdi + CONTEXT_Rax], rax - mov [rdi + CONTEXT_Rbp], rbp - mov [rdi + CONTEXT_R8], r8 - mov [rdi + CONTEXT_R9], r9 - mov [rdi + CONTEXT_R10], r10 - mov [rdi + CONTEXT_R11], r11 - mov [rdi + CONTEXT_R12], r12 - mov [rdi + CONTEXT_R13], r13 - mov [rdi + CONTEXT_R14], r14 - mov [rdi + CONTEXT_R15], r15 -LOCAL_LABEL(Done_CONTEXT_INTEGER): - - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL - je LOCAL_LABEL(Done_CONTEXT_CONTROL) - - // Return address is @ (RSP + 8) - mov rdx, [rsp + 8] - mov [rdi + CONTEXT_Rip], rdx -.att_syntax - mov %cs, CONTEXT_SegCs(%rdi) -.intel_syntax noprefix - // Get the value of EFlags that was pushed on stack at the beginning of the function - mov rdx, [rsp] - mov [rdi + CONTEXT_EFlags], edx - lea rdx, [rsp + 16] - mov [rdi + CONTEXT_Rsp], rdx -.att_syntax - mov %ss, CONTEXT_SegSs(%rdi) -.intel_syntax noprefix -LOCAL_LABEL(Done_CONTEXT_CONTROL): + pushf + xor ebx, ebx + pop bx + mov [eax + CONTEXT_EFlags], ebx - // Need to double check this is producing the right result - // also that FFSXR (fast save/restore) is not turned on - // otherwise it omits the xmm registers. - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT je LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) - fxsave [rdi + CONTEXT_FltSave] + // Capture FPU status + fnsave [eax + CONTEXT_FloatSave] + frstor [eax + CONTEXT_FloatSave] LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS - je LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS) - mov rdx, dr0 - mov [rdi + CONTEXT_Dr0], rdx - mov rdx, dr1 - mov [rdi + CONTEXT_Dr1], rdx - mov rdx, dr2 - mov [rdi + CONTEXT_Dr2], rdx - mov rdx, dr3 - mov [rdi + CONTEXT_Dr3], rdx - mov rdx, dr6 - mov [rdi + CONTEXT_Dr6], rdx - mov rdx, dr7 - mov [rdi + CONTEXT_Dr7], rdx -LOCAL_LABEL(Done_CONTEXT_DEBUG_REGISTERS): - - free_stack 8 - ret + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_EXTENDED_REGISTERS + je LOCAL_LABEL(Done_CONTEXT_EXTENDED_REGISTERS) + movdqu [eax + CONTEXT_Xmm0], xmm0 + movdqu [eax + CONTEXT_Xmm1], xmm1 + movdqu [eax + CONTEXT_Xmm2], xmm2 + movdqu [eax + CONTEXT_Xmm3], xmm3 + movdqu [eax + CONTEXT_Xmm4], xmm4 + movdqu [eax + CONTEXT_Xmm5], xmm5 + movdqu [eax + CONTEXT_Xmm6], xmm6 + movdqu [eax + CONTEXT_Xmm7], xmm7 +LOCAL_LABEL(Done_CONTEXT_EXTENDED_REGISTERS): + + // Restore + pop ebx + pop eax + ret 4 LEAF_END CONTEXT_CaptureContext, _TEXT LEAF_ENTRY RtlCaptureContext, _TEXT - mov DWORD PTR [rdi + CONTEXT_ContextFlags], (CONTEXT_AMD64 | CONTEXT_FULL | CONTEXT_SEGMENTS) + push eax + mov eax, [esp + 8] + mov DWORD PTR [eax + CONTEXT_ContextFlags], (CONTEXT_FLOATING_POINT) + pop eax jmp C_FUNC(CONTEXT_CaptureContext) LEAF_END RtlCaptureContext, _TEXT LEAF_ENTRY RtlRestoreContext, _TEXT - push_nonvol_reg rbp - alloc_stack (IRetFrameLengthAligned) - - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_DEBUG_REGISTERS - je LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS) - mov rdx, [rdi + CONTEXT_Dr0] - mov dr0, rdx - mov rdx, [rdi + CONTEXT_Dr1] - mov dr1, rdx - mov rdx, [rdi + CONTEXT_Dr2] - mov dr2, rdx - mov rdx, [rdi + CONTEXT_Dr3] - mov dr3, rdx - mov rdx, [rdi + CONTEXT_Dr6] - mov dr6, rdx - mov rdx, [rdi + CONTEXT_Dr7] - mov dr7, rdx -LOCAL_LABEL(Done_Restore_CONTEXT_DEBUG_REGISTERS): + mov eax, [esp + 4] - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT je LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT) - fxrstor [rdi + CONTEXT_FltSave] + frstor [eax + CONTEXT_FloatSave] LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT): - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_XSTATE - je LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE) - - // Restore the extended state (for now, this is just the upper halves of YMM registers) - vinsertf128 ymm0, ymm0, xmmword ptr [rdi + (CONTEXT_VectorRegister + 0 * 16)], 1 - vinsertf128 ymm1, ymm1, xmmword ptr [rdi + (CONTEXT_VectorRegister + 1 * 16)], 1 - vinsertf128 ymm2, ymm2, xmmword ptr [rdi + (CONTEXT_VectorRegister + 2 * 16)], 1 - vinsertf128 ymm3, ymm3, xmmword ptr [rdi + (CONTEXT_VectorRegister + 3 * 16)], 1 - vinsertf128 ymm4, ymm4, xmmword ptr [rdi + (CONTEXT_VectorRegister + 4 * 16)], 1 - vinsertf128 ymm5, ymm5, xmmword ptr [rdi + (CONTEXT_VectorRegister + 5 * 16)], 1 - vinsertf128 ymm6, ymm6, xmmword ptr [rdi + (CONTEXT_VectorRegister + 6 * 16)], 1 - vinsertf128 ymm7, ymm7, xmmword ptr [rdi + (CONTEXT_VectorRegister + 7 * 16)], 1 - vinsertf128 ymm8, ymm8, xmmword ptr [rdi + (CONTEXT_VectorRegister + 8 * 16)], 1 - vinsertf128 ymm9, ymm9, xmmword ptr [rdi + (CONTEXT_VectorRegister + 9 * 16)], 1 - vinsertf128 ymm10, ymm10, xmmword ptr [rdi + (CONTEXT_VectorRegister + 10 * 16)], 1 - vinsertf128 ymm11, ymm11, xmmword ptr [rdi + (CONTEXT_VectorRegister + 11 * 16)], 1 - vinsertf128 ymm12, ymm12, xmmword ptr [rdi + (CONTEXT_VectorRegister + 12 * 16)], 1 - vinsertf128 ymm13, ymm13, xmmword ptr [rdi + (CONTEXT_VectorRegister + 13 * 16)], 1 - vinsertf128 ymm14, ymm14, xmmword ptr [rdi + (CONTEXT_VectorRegister + 14 * 16)], 1 - vinsertf128 ymm15, ymm15, xmmword ptr [rdi + (CONTEXT_VectorRegister + 15 * 16)], 1 -LOCAL_LABEL(Done_Restore_CONTEXT_XSTATE): - - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_CONTROL - je LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL) - - // The control registers are restored via the iret instruction - // so we build the frame for the iret on the stack. -#ifdef __APPLE__ -.att_syntax - // On OSX, we cannot read SS via the thread_get_context and RtlRestoreContext - // needs to be used on context extracted by thread_get_context. So we - // don't change the SS. - mov %ss, %ax -.intel_syntax noprefix -#else - mov ax, [rdi + CONTEXT_SegSs] -#endif - mov [rsp + IRETFRAME_SegSs], ax - mov rax, [rdi + CONTEXT_Rsp] - mov [rsp + IRETFRAME_Rsp], rax - mov eax, [rdi + CONTEXT_EFlags] - mov [rsp + IRETFRAME_EFlags], eax - mov ax, [rdi + CONTEXT_SegCs] - mov [rsp + IRETFRAME_SegCs], ax - mov rax, [rdi + CONTEXT_Rip] - mov [rsp + IRETFRAME_Rip], rax - -LOCAL_LABEL(Done_Restore_CONTEXT_CONTROL): - // Remember the result of the test for the CONTEXT_CONTROL - push_eflags - test BYTE PTR [rdi + CONTEXT_ContextFlags], CONTEXT_INTEGER - je LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER) - mov rsi, [rdi + CONTEXT_Rsi] - mov rbx, [rdi + CONTEXT_Rbx] - mov rdx, [rdi + CONTEXT_Rdx] - mov rcx, [rdi + CONTEXT_Rcx] - mov rax, [rdi + CONTEXT_Rax] - mov rbp, [rdi + CONTEXT_Rbp] - mov r8, [rdi + CONTEXT_R8] - mov r9, [rdi + CONTEXT_R9] - mov r10, [rdi + CONTEXT_R10] - mov r11, [rdi + CONTEXT_R11] - mov r12, [rdi + CONTEXT_R12] - mov r13, [rdi + CONTEXT_R13] - mov r14, [rdi + CONTEXT_R14] - mov r15, [rdi + CONTEXT_R15] - mov rdi, [rdi + CONTEXT_Rdi] -LOCAL_LABEL(Done_Restore_CONTEXT_INTEGER): - - // Restore the result of the test for the CONTEXT_CONTROL - pop_eflags - je LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) - // The function was asked to restore the control registers, so - // we perform iretq that restores them all. - // We don't return to the caller in this case. - iretq -LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): - - // The function was not asked to restore the control registers - // so we return back to the caller. - free_stack (IRetFrameLengthAligned) - pop_nonvol_reg rbp - ret + test BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_EXTENDED_REGISTERS + je LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS) + movdqu xmm0, [eax + CONTEXT_Xmm0] + movdqu xmm1, [eax + CONTEXT_Xmm1] + movdqu xmm2, [eax + CONTEXT_Xmm2] + movdqu xmm3, [eax + CONTEXT_Xmm3] + movdqu xmm4, [eax + CONTEXT_Xmm4] + movdqu xmm5, [eax + CONTEXT_Xmm5] + movdqu xmm6, [eax + CONTEXT_Xmm6] + movdqu xmm7, [eax + CONTEXT_Xmm7] +LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS): + + // Restore CONTROL register(s) + mov ecx, [eax + CONTEXT_Eip] + mov [esp], ecx + + mov ecx, [eax + CONTEXT_Esp] + push ecx + mov ecx, [eax + CONTEXT_Ebp] + push ecx + + pop ebp + pop esp + + // Restore INTEGER register(s) + mov ecx, [eax + CONTEXT_Edi] + push ecx + mov ecx, [eax + CONTEXT_Esi] + push ecx + mov ecx, [eax + CONTEXT_Edx] + push ecx + mov ecx, [eax + CONTEXT_Ecx] + push ecx + mov ecx, [eax + CONTEXT_Ebx] + push ecx + mov ecx, [eax + CONTEXT_Eax] + push ecx + + pop eax + pop ebx + pop ecx + pop edx + pop esi + pop edi + + ret 8 LEAF_END RtlRestoreContext, _TEXT -#else - - .globl C_FUNC(CONTEXT_CaptureContext) -C_FUNC(CONTEXT_CaptureContext): - push %eax - mov 8(%esp), %eax - mov %edi, CONTEXT_Edi(%eax) - mov %esi, CONTEXT_Esi(%eax) - mov %ebx, CONTEXT_Ebx(%eax) - mov %edx, CONTEXT_Edx(%eax) - mov %ecx, CONTEXT_Ecx(%eax) - pop %ecx - mov %ecx, CONTEXT_Eax(%eax) - mov %ebp, CONTEXT_Ebp(%eax) - mov (%esp), %edx - mov %edx, CONTEXT_Eip(%eax) - push %cs - pop %edx - mov %edx, CONTEXT_SegCs(%eax) - pushf - pop %edx - mov %edx, CONTEXT_EFlags(%eax) - lea 4(%esp), %edx - mov %edx, CONTEXT_Esp(%eax) - push %ss - pop %edx - mov %edx, CONTEXT_SegSs(%eax) - testb $CONTEXT_FLOATING_POINT, CONTEXT_ContextFlags(%eax) - je 0f - fnsave CONTEXT_FloatSave(%eax) - frstor CONTEXT_FloatSave(%eax) -0: - testb $CONTEXT_EXTENDED_REGISTERS, CONTEXT_ContextFlags(%eax) - je 2f - movdqu %xmm0, CONTEXT_Xmm0(%eax) - movdqu %xmm1, CONTEXT_Xmm1(%eax) - movdqu %xmm2, CONTEXT_Xmm2(%eax) - movdqu %xmm3, CONTEXT_Xmm3(%eax) - movdqu %xmm4, CONTEXT_Xmm4(%eax) - movdqu %xmm5, CONTEXT_Xmm5(%eax) - movdqu %xmm6, CONTEXT_Xmm6(%eax) - movdqu %xmm7, CONTEXT_Xmm7(%eax) -2: - ret - -#endif diff --git a/src/pal/src/arch/i386/exceptionhelper.S b/src/pal/src/arch/i386/exceptionhelper.S index b7b34ace41..2061be26f8 100644 --- a/src/pal/src/arch/i386/exceptionhelper.S +++ b/src/pal/src/arch/i386/exceptionhelper.S @@ -8,35 +8,36 @@ ////////////////////////////////////////////////////////////////////////// // -// This function creates a stack frame right below the target frame, restores all callee -// saved registers from the passed in context, sets the RSP to that frame and sets the -// return address to the target frame's RIP. -// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. // EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers from the passed in context, sets the SP to that frame and sets the +// return address to the target frame's IP. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// +////////////////////////////////////////////////////////////////////////// + LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT - // Save the RBP to the stack so that the unwind can work at the instruction after - // loading the RBP from the context, but before loading the RSP from the context. - push_nonvol_reg rbp - mov r12, [rdi + CONTEXT_R12] - mov r13, [rdi + CONTEXT_R13] - mov r14, [rdi + CONTEXT_R14] - mov r15, [rdi + CONTEXT_R15] - mov rbx, [rdi + CONTEXT_Rbx] - mov rbp, [rdi + CONTEXT_Rbp] - mov rsp, [rdi + CONTEXT_Rsp] - // The RSP was set to the target frame's value, so the current function's - // CFA is now right at the RSP. + push ebp + mov eax, [esp + 12] // ebx: PAL_SEHException * + mov ebx, [esp + 8] // eax: CONTEXT * + + mov ebp, [ebx + CONTEXT_Ebp] + mov esp, [ebx + CONTEXT_Esp] + + // The ESP is re-initialized as the target frame's value, so the current function's + // CFA is now right at the ESP. .cfi_def_cfa_offset 0 - // Indicate that now that we have moved the RSP to the target address, - // the RBP is no longer saved in the current stack frame. - .cfi_restore rbp + // Indicate that now that we have moved the RSP to the target address, + // the EBP is no longer saved in the current stack frame. + .cfi_restore ebp - mov rax, [rdi + CONTEXT_Rip] + // Store PAL_SEHException as the first argument + push eax // Store return address to the stack - push_register rax - // The PAL_SEHException pointer - mov rdi, rsi + mov ebx, [ebx + CONTEXT_Eip] + push ebx jmp EXTERNAL_C_FUNC(ThrowExceptionHelper) LEAF_END ThrowExceptionFromContextInternal, _TEXT |