Module: wine Branch: master Commit: 1edd53f00ffbc32d38d7ef71f91c63c84c3a330c URL: https://gitlab.winehq.org/wine/wine/-/commit/1edd53f00ffbc32d38d7ef71f91c63c...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Mar 7 13:39:51 2024 +0100
ntdll: Implement _setjmpex on ARM64EC.
---
dlls/ntdll/signal_arm64ec.c | 78 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index c307714e56e..6f73919c886 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -1755,12 +1755,19 @@ BOOLEAN WINAPI RtlIsEcCode( ULONG_PTR ptr ) }
+/* unwind context by one call frame */ +static void unwind_one_frame( CONTEXT *context ) +{ + void *data; + ULONG_PTR base, frame, pc = context->Rip - 4; + RUNTIME_FUNCTION *func = RtlLookupFunctionEntry( pc, &base, NULL ); + + RtlVirtualUnwind( UNW_FLAG_NHANDLER, base, pc, func, context, &data, &frame, NULL ); +} + /* capture context information; helper for RtlCaptureContext */ static void __attribute__((used)) capture_context( CONTEXT *context, UINT cpsr, UINT fpcr, UINT fpsr ) { - RUNTIME_FUNCTION *func; - void *handler_data; - ULONG_PTR pc, base, frame; CONTEXT unwind_context;
context->ContextFlags = CONTEXT_AMD64_FULL; @@ -1772,9 +1779,7 @@ static void __attribute__((used)) capture_context( CONTEXT *context, UINT cpsr,
/* unwind one level to get register values from caller function */ unwind_context = *context; - pc = context->Rip - 4; - func = RtlLookupFunctionEntry( pc, &base, NULL ); - RtlVirtualUnwind( UNW_FLAG_NHANDLER, base, pc, func, &unwind_context, &handler_data, &frame, NULL ); + unwind_one_frame( &unwind_context ); memcpy( &context->Rax, &unwind_context.Rax, offsetof(CONTEXT,FltSave) - offsetof(CONTEXT,Rax) ); }
@@ -1826,6 +1831,67 @@ void __attribute__((naked)) RtlCaptureContext( CONTEXT *context ) ".seh_endproc" ); }
+/* fixup jump buffer information; helper for _setjmpex */ +static int __attribute__((used)) do_setjmpex( _JUMP_BUFFER *buf, UINT fpcr, UINT fpsr ) +{ + CONTEXT context = { .ContextFlags = CONTEXT_FULL }; + + buf->MxCsr = fpcsr_to_mxcsr( fpcr, fpsr ); + buf->FpCsr = 0x27f; + + context.Rbx = buf->Rbx; + context.Rsp = buf->Rsp; + context.Rbp = buf->Rbp; + context.Rsi = buf->Rsi; + context.Rdi = buf->Rdi; + context.R12 = buf->R12; + context.R13 = buf->R13; + context.R14 = buf->R14; + context.R15 = buf->R15; + context.Rip = buf->Rip; + memcpy( &context.Xmm6, &buf->Xmm6, 10 * sizeof(context.Xmm6) ); + unwind_one_frame( &context ); + if (!RtlIsEcCode( context.Rip )) /* caller is x64, use its context instead of the ARM one */ + { + buf->Rbx = context.Rbx; + buf->Rsp = context.Rsp; + buf->Rbp = context.Rbp; + buf->Rsi = context.Rsi; + buf->Rdi = context.Rdi; + buf->R12 = context.R12; + buf->R13 = context.R13; + buf->R14 = context.R14; + buf->R15 = context.R15; + buf->Rip = context.Rip; + memcpy( &buf->Xmm6, &context.Xmm6, 10 * sizeof(context.Xmm6) ); + } + return 0; +} + +/*********************************************************************** + * _setjmpex (NTDLL.@) + */ +int __attribute__((naked)) NTDLL__setjmpex( _JUMP_BUFFER *buf, void *frame ) +{ + asm( ".seh_proc NTDLL__setjmpex\n\t" + ".seh_endprologue\n\t" + "stp x1, x27, [x0]\n\t" /* jmp_buf->Frame,Rbx */ + "mov x1, sp\n\t" + "stp x1, x29, [x0, #0x10]\n\t" /* jmp_buf->Rsp,Rbp */ + "stp x25, x26, [x0, #0x20]\n\t" /* jmp_buf->Rsi,Rdi */ + "stp x19, x20, [x0, #0x30]\n\t" /* jmp_buf->R12,R13 */ + "stp x21, x22, [x0, #0x40]\n\t" /* jmp_buf->R14,R15 */ + "str x30, [x0, #0x50]\n\t" /* jmp_buf->Rip */ + "stp d8, d9, [x0, #0x80]\n\t" /* jmp_buf->Xmm8,Xmm9 */ + "stp d10, d11, [x0, #0xa0]\n\t" /* jmp_buf->Xmm10,Xmm11 */ + "stp d12, d13, [x0, #0xc0]\n\t" /* jmp_buf->Xmm12,Xmm13 */ + "stp d14, d15, [x0, #0xe0]\n\t" /* jmp_buf->Xmm14,Xmm15 */ + "mrs x1, fpcr\n\t" + "mrs x2, fpsr\n\t" + "b do_setjmpex\n\t" + ".seh_endproc" ); +} +
/******************************************************************* * RtlRestoreContext (NTDLL.@)