[Arm64] Helpers for ReadyToRun
authorRahul Kumar <rahku@microsoft.com>
Thu, 5 May 2016 22:53:07 +0000 (15:53 -0700)
committerRahul Kumar <rahku@microsoft.com>
Mon, 9 May 2016 17:26:12 +0000 (10:26 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/559719a62aa7134da929d22f40c3c772e5d06348

src/coreclr/src/vm/arm64/stubs.cpp
src/coreclr/src/zap/zapimport.cpp

index e7700f5..426093b 100644 (file)
@@ -1709,53 +1709,283 @@ void StubLinkerCPU::EmitUnboxMethodStub(MethodDesc *pMD)
     EmitCallManagedMethod(pMD, TRUE /* tail call */);
 }
 
-#endif // CROSSGEN_COMPILE
+#ifdef FEATURE_READYTORUN
 
-#endif // #ifndef DACCESS_COMPILE
+//
+// Allocation of dynamic helpers
+//
+
+#define DYNAMIC_HELPER_ALIGNMENT sizeof(TADDR)
+
+#define BEGIN_DYNAMIC_HELPER_EMIT(size) \
+    SIZE_T cb = size; \
+    SIZE_T cbAligned = ALIGN_UP(cb, DYNAMIC_HELPER_ALIGNMENT); \
+    BYTE * pStart = (BYTE *)(void *)pAllocator->GetDynamicHelpersHeap()->AllocAlignedMem(cbAligned, DYNAMIC_HELPER_ALIGNMENT); \
+    BYTE * p = pStart;
+
+#define END_DYNAMIC_HELPER_EMIT() \
+    _ASSERTE(pStart + cb == p); \
+    while (p < pStart + cbAligned) { *(DWORD*)p = 0xBADC0DF0; p += 4; }\
+    ClrFlushInstructionCache(pStart, cbAligned); \
+    return (PCODE)pStart
+
+// Uses x8 as scratch register to store address of data label
+// After load x8 is increment to point to next data
+// only accepts positive offsets
+static void LoadRegPair(BYTE* p, int reg1, int reg2, UINT32 offset)
+{
+    LIMITED_METHOD_CONTRACT;
+
+    // adr x8, <label>
+    *(DWORD*)(p + 0) = 0x10000008 | ((offset >> 2) << 5);
+    // ldp reg1, reg2, [x8], #16 ; postindex & wback
+    *(DWORD*)(p + 4) = 0xa8c10100 | (reg2 << 10) | reg1;
+}
 
-#ifdef FEATURE_READYTORUN
 PCODE DynamicHelpers::CreateHelper(LoaderAllocator * pAllocator, TADDR arg, PCODE target)
 {
-    UNREACHABLE();
+    STANDARD_VM_CONTRACT;
+
+    BEGIN_DYNAMIC_HELPER_EMIT(32);
+
+    // adr x8, <label>
+    // ldp x0, x12, [x8]
+    LoadRegPair(p, 0, 12, 16);
+    p += 8;
+    // br x12
+    *(DWORD*)p = 0xd61f0180;
+    p += 4;
+
+    // padding to make 8 byte aligned
+    *(DWORD*)p = 0xBADC0DF0; p += 4;
+    
+    // label:
+    // arg
+    *(TADDR*)p = arg;
+    p += 8;
+    // target
+    *(PCODE*)p = target;
+    p += 8;
+    
+    END_DYNAMIC_HELPER_EMIT();
 }
 
 PCODE DynamicHelpers::CreateHelperWithArg(LoaderAllocator * pAllocator, TADDR arg, PCODE target)
 {
-    UNREACHABLE();
+    STANDARD_VM_CONTRACT;
+
+    BEGIN_DYNAMIC_HELPER_EMIT(32);
+    
+    // adr x8, <label>
+    // ldp x1, x12, [x8]
+    LoadRegPair(p, 1, 12, 16);
+    p += 8;
+
+    // br x12
+    *(DWORD*)p = 0xd61f0180;
+    p += 4; 
+
+    // padding to make 8 byte aligned
+    *(DWORD*)p = 0xBADC0DF0; p += 4;
+    
+    // label:
+    // arg
+    *(TADDR*)p = arg;
+    p += 8;
+    // target
+    *(PCODE*)p = target;
+    p += 8;
+    
+    END_DYNAMIC_HELPER_EMIT();  
 }
 
 PCODE DynamicHelpers::CreateHelper(LoaderAllocator * pAllocator, TADDR arg, TADDR arg2, PCODE target)
 {
-    UNREACHABLE();
+    STANDARD_VM_CONTRACT;
+
+    BEGIN_DYNAMIC_HELPER_EMIT(40);
+    
+    // adr x8, <label>
+    // ldp x0, x1, [x8] ; wback
+    LoadRegPair(p, 0, 1, 16);
+    p += 8;
+
+    // ldr x12, [x8]
+    *(DWORD*)p = 0xf940010c;
+    p += 4;
+    // br x12
+    *(DWORD*)p = 0xd61f0180;
+    p += 4;     
+    // label:
+    // arg
+    *(TADDR*)p = arg;
+    p += 8;
+    // arg2
+    *(TADDR*)p = arg2;
+    p += 8;
+    // target
+    *(TADDR*)p = target;
+    p += 8;
+
+    END_DYNAMIC_HELPER_EMIT();      
 }
 
 PCODE DynamicHelpers::CreateHelperArgMove(LoaderAllocator * pAllocator, TADDR arg, PCODE target)
 {
-    UNREACHABLE();
+    STANDARD_VM_CONTRACT;
+
+    BEGIN_DYNAMIC_HELPER_EMIT(32);
+    
+    // mov x1, x0
+    *(DWORD*)p = 0x91000001;
+    p += 4;
+
+    // adr x8, <label>
+    // ldp x0, x12, [x8]
+    LoadRegPair(p, 0, 12, 12);
+    p += 8;
+
+    // br x12
+    *(DWORD*)p = 0xd61f0180;
+    p += 4;     
+
+    // label:
+    // arg
+    *(TADDR*)p = arg;
+    p += 8; 
+    // target
+    *(TADDR*)p = target;
+    p += 8;
+    
+    END_DYNAMIC_HELPER_EMIT();          
 }
 
 PCODE DynamicHelpers::CreateReturn(LoaderAllocator * pAllocator)
 {
-    UNREACHABLE();
+    STANDARD_VM_CONTRACT;
+
+    BEGIN_DYNAMIC_HELPER_EMIT(4);
+    
+    // br lr
+    *(DWORD*)p = 0xd61f03c0;
+    p += 4;
+    END_DYNAMIC_HELPER_EMIT();              
 }
 
 PCODE DynamicHelpers::CreateReturnConst(LoaderAllocator * pAllocator, TADDR arg)
 {
-    UNREACHABLE();
+    STANDARD_VM_CONTRACT;
+
+    BEGIN_DYNAMIC_HELPER_EMIT(16);
+    // ldr x0, <lable>
+    *(DWORD*)p = 0x58000040;
+    p += 4;
+    
+    // br lr
+    *(DWORD*)p = 0xd61f03c0;
+    p += 4;
+
+    // label:
+    // arg
+    *(TADDR*)p = arg;
+    p += 8; 
+
+    END_DYNAMIC_HELPER_EMIT();              
 }
 
 PCODE DynamicHelpers::CreateReturnIndirConst(LoaderAllocator * pAllocator, TADDR arg, INT8 offset)
 {
-    UNREACHABLE();
+    STANDARD_VM_CONTRACT;
+
+    BEGIN_DYNAMIC_HELPER_EMIT(24);
+    
+    // ldr x0, <label>
+    *(DWORD*)p = 0x58000080;
+    p += 4;
+
+    // ldr x0, [x0]
+    *(DWORD*)p = 0xf9400000;
+    p += 4;
+    
+    // add x0, x0, offset
+    *(DWORD*)p = 0x91000000 | (offset << 10);
+    p += 4;
+    
+    // br lr
+    *(DWORD*)p = 0xd61f03c0;
+    p += 4;
+    
+    // label:
+    // arg
+    *(TADDR*)p = arg;
+    p += 8; 
+    
+    END_DYNAMIC_HELPER_EMIT();              
 }
 
 PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADDR arg, PCODE target)
 {
-    UNREACHABLE();
+    STANDARD_VM_CONTRACT;
+
+    BEGIN_DYNAMIC_HELPER_EMIT(32);
+    
+    // adr x8, <label>
+    // ldp x2, x12, [x8]
+    LoadRegPair(p, 2, 12, 16);
+    p += 8;
+
+    // br x12
+    *(DWORD*)p = 0xd61f0180;
+    p += 4; 
+
+    // padding to make 8 byte aligned
+    *(DWORD*)p = 0xBADC0DF0; p += 4;
+    
+    // label:
+    // arg
+    *(TADDR*)p = arg;
+    p += 8; 
+
+    // target
+    *(TADDR*)p = target;
+    p += 8;
+    END_DYNAMIC_HELPER_EMIT();              
 }
 
 PCODE DynamicHelpers::CreateHelperWithTwoArgs(LoaderAllocator * pAllocator, TADDR arg, TADDR arg2, PCODE target)
 {
-    UNREACHABLE();
-}
-#endif
+    STANDARD_VM_CONTRACT;
+
+    BEGIN_DYNAMIC_HELPER_EMIT(40);
+    
+    // adr x8, <label>
+    // ldp x2, x3, [x8]; wback
+    LoadRegPair(p, 2, 3, 16);
+    p += 8;
+    
+    // ldr x12, [x8]
+    *(DWORD*)p = 0xf940010c;
+    p += 4;
+
+    // br x12
+    *(DWORD*)p = 0xd61f0180;
+    p += 4;     
+
+    // label:
+    // arg
+    *(TADDR*)p = arg;
+    p += 8;
+    // arg2
+    *(TADDR*)p = arg2;
+    p += 8;
+    // target
+    *(TADDR*)p = target;
+    p += 8;
+    END_DYNAMIC_HELPER_EMIT();              
+}
+#endif // FEATURE_READYTORUN
+
+#endif // CROSSGEN_COMPILE
+
+#endif // #ifndef DACCESS_COMPILE
index 98e7afe..c0ea827 100644 (file)
@@ -1907,7 +1907,7 @@ DWORD ZapIndirectHelperThunk::SaveWorker(ZapWriter * pZapWriter)
 {
     ZapImage * pImage = ZapImage::GetImage(pZapWriter);
 
-    BYTE buffer[42];
+    BYTE buffer[44];
     BYTE * p = buffer;
 
 #if defined(_TARGET_X86_)
@@ -2087,50 +2087,50 @@ DWORD ZapIndirectHelperThunk::SaveWorker(ZapWriter * pZapWriter)
     {
         if (IsVSD())
         {
-                       // x11 contains indirection cell
-                       // Do nothing x11 contains our first param
+            // x11 contains indirection cell
+            // Do nothing x11 contains our first param
         }
         else
         {
             // mov x11, x12
-                       *(DWORD*)p = 0xaa0c03eb;
-                       p += 4;
+            *(DWORD*)p = 0xaa0c03eb;
+            p += 4;
         }
 
         //  movz x8, #index
-               DWORD index = GetSectionIndex();
-               _ASSERTE(index <= 0x7F);
-               *(DWORD*)p = 0xd2800008 | (index << 5);
-               p += 4;
+        DWORD index = GetSectionIndex();
+        _ASSERTE(index <= 0x7F);
+        *(DWORD*)p = 0xd2800008 | (index << 5);
+        p += 4;
 
         // move Module* -> x9
-               // ldr x9, [PC+0x14]
-               *(DWORD*)p = 0x58000289;
-               p += 4;
+        // ldr x9, [PC+0x14]
+        *(DWORD*)p = 0x58000289;
+        p += 4;
                
-               //ldr x9, [x9]
-               *(DWORD*)p = 0xf9400129;
-               p += 4;
-       }
+        //ldr x9, [x9]
+        *(DWORD*)p = 0xf9400129;
+        p += 4;
+    }
     else
     if (IsLazyHelper())
     {
-               // Move Module* -> x1
+        // Move Module* -> x1
         // ldr x1, [PC+0x14]
-               *(DWORD*)p = 0x58000289;
-               p += 4;
+        *(DWORD*)p = 0x58000289;
+        p += 4;
 
-               // ldr x1, [x1]
-               *(DWORD*)p = 0xf9400021;
-               p += 4;
-       }
+        // ldr x1, [x1]
+        *(DWORD*)p = 0xf9400021;
+        p += 4;
+    }
 
     // branch to helper
        
     // mov x12, [helper]
-       // ldr x12, [PC+0x14]
-       *(DWORD*)p = 0x58000289;
-       p += 4;
+    // ldr x12, [PC+0x14]
+    *(DWORD*)p = 0x58000289;
+    p += 4;
 
     // ldr x12, [x12]
     *(DWORD *)p = 0xf940018c;
@@ -2140,14 +2140,14 @@ DWORD ZapIndirectHelperThunk::SaveWorker(ZapWriter * pZapWriter)
     *(DWORD *)p = 0xd61f0180;
     p += 4;    
 
-       // [Module*]
-       if (pImage != NULL)
-               pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR);
-       p += 8;
+    // [Module*]
+    if (pImage != NULL)
+        pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR);
+    p += 8;
     // [helper]
-       if (pImage != NULL)
-               pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_PTR);
-       p += 8;
+    if (pImage != NULL)
+        pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_PTR);
+    p += 8;
 #else
     PORTABILITY_ASSERT("ZapIndirectHelperThunk::SaveWorker");
 #endif