Arm32 support VFP registers context to/from native context (dotnet/coreclr#25775)
authorSteve MacLean <Steve.MacLean@microsoft.com>
Fri, 19 Jul 2019 04:30:09 +0000 (00:30 -0400)
committerGitHub <noreply@github.com>
Fri, 19 Jul 2019 04:30:09 +0000 (00:30 -0400)
Commit migrated from https://github.com/dotnet/coreclr/commit/a2edc1ca3a66cd4e9a9c665f3bfcfbec8a93497a

src/coreclr/src/pal/src/include/pal/context.h
src/coreclr/src/pal/src/thread/context.cpp

index 69acd361bbadae51695117a0631612bb3be80c4b..1f7c7517b6315c6c0f71ce817a475d144ee5f2a3 100644 (file)
@@ -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<VfpSigFrame *>(&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<native_context_t*>(mc));
+}
+
 #elif defined(_X86_)
 
 #define MCREG_Ebx(mc)       ((mc).mc_ebx)
index b65190da7200cbdd832a2c22acafaf747ce9bd37..cd2fe41bc46da0b3fc5794ff6a80cc986d1d859e 100644 (file)
@@ -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
     }