summaryrefslogtreecommitdiff
path: root/src/pal/src/arch
diff options
context:
space:
mode:
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.h106
-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.S259
-rw-r--r--src/pal/src/arch/amd64/debugbreak.S12
-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.S42
-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.cpp64
-rw-r--r--src/pal/src/arch/arm/exceptionhelper.S2
-rw-r--r--src/pal/src/arch/i386/asmconstants.h76
-rw-r--r--src/pal/src/arch/i386/context2.S354
-rw-r--r--src/pal/src/arch/i386/exceptionhelper.S47
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