From e4ece90664bcbbfe2e5e2e1bcc33b3fe99a9f6cb Mon Sep 17 00:00:00 2001 From: Steve MacLean Date: Fri, 19 Jul 2019 00:30:09 -0400 Subject: [PATCH] Arm32 support VFP registers context to/from native context (#25775) --- src/pal/src/include/pal/context.h | 53 +++++++++++++++++++++++++++++++++++++++ src/pal/src/thread/context.cpp | 26 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/pal/src/include/pal/context.h b/src/pal/src/include/pal/context.h index 69acd36..1f7c751 100644 --- a/src/pal/src/include/pal/context.h +++ b/src/pal/src/include/pal/context.h @@ -375,6 +375,59 @@ const fpsimd_context* GetConstNativeSigSimdContext(const native_context_t *mc) #define MCREG_Pc(mc) ((mc).arm_pc) #define MCREG_Cpsr(mc) ((mc).arm_cpsr) + +// Flatterned layout of the arm kernel struct vfp_sigframe +struct VfpSigFrame +{ + DWORD magic; + DWORD size; + DWORD64 D[32]; // Some arm cpus have 16 D registers. The kernel will ignore the extra. + DWORD Fpscr; + DWORD Padding; + DWORD Fpexc; + DWORD Fpinst; + DWORD Fpinst2; + DWORD Padding2; +}; + +inline +VfpSigFrame* GetNativeSigSimdContext(native_context_t *mc) +{ + size_t size = 0; + + const DWORD VfpMagic = 0x56465001; // VFP_MAGIC from arm kernel + + do + { + VfpSigFrame* fp = reinterpret_cast(&mc->uc_regspace[size]); + + if (fp->magic == VfpMagic) + { + _ASSERTE(fp->size == sizeof(VfpSigFrame)); + _ASSERTE(size + fp->size <= sizeof(mc->uc_regspace)); + + return fp; + } + + if (fp->size == 0) + { + break; + } + + size += fp->size; + } while (size + sizeof(VfpSigFrame) <= sizeof(mc->uc_regspace)); + + // VFP is not required on all armv7 processors, this structure may not be present + + return nullptr; +} + +inline +const VfpSigFrame* GetConstNativeSigSimdContext(const native_context_t *mc) +{ + return GetNativeSigSimdContext(const_cast(mc)); +} + #elif defined(_X86_) #define MCREG_Ebx(mc) ((mc).mc_ebx) diff --git a/src/pal/src/thread/context.cpp b/src/pal/src/thread/context.cpp index b65190d..cd2fe41 100644 --- a/src/pal/src/thread/context.cpp +++ b/src/pal/src/thread/context.cpp @@ -476,6 +476,16 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) *(NEON128*) &fp->vregs[i] = lpContext->V[i]; } } +#elif defined(_ARM_) + VfpSigFrame* fp = GetNativeSigSimdContext(native); + if (fp) + { + fp->Fpscr = lpContext->Fpscr; + for (int i = 0; i < 32; i++) + { + fp->D[i] = lpContext->D[i]; + } + } #endif } @@ -585,6 +595,22 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex lpContext->V[i] = *(NEON128*) &fp->vregs[i]; } } +#elif defined(_ARM_) + const VfpSigFrame* fp = GetConstNativeSigSimdContext(native); + if (fp) + { + lpContext->Fpscr = fp->Fpscr; + for (int i = 0; i < 32; i++) + { + lpContext->D[i] = fp->D[i]; + } + } + else + { + // Floating point state is not valid + // Mark the context correctly + lpContext->ContextFlags &= ~(ULONG)CONTEXT_FLOATING_POINT; + } #endif } -- 2.7.4