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
{
ZapImage * pImage = ZapImage::GetImage(pZapWriter);
- BYTE buffer[42];
+ BYTE buffer[44];
BYTE * p = buffer;
#if defined(_TARGET_X86_)
{
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;
*(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