summaryrefslogtreecommitdiff
path: root/src/utilcode/util.cpp
diff options
context:
space:
mode:
authorKyungwoo Lee <kyulee@microsoft.com>2016-04-29 10:29:28 -0700
committerKyungwoo Lee <kyulee@microsoft.com>2016-04-29 14:52:46 -0700
commit45798f661f8c8c042f3582cde8b611d1c9c7343f (patch)
tree0d75dad9935f95c5bf4bd309899a37456e4478bd /src/utilcode/util.cpp
parent601b1051c1022d5f764224e35be59f02a6074ad0 (diff)
downloadcoreclr-45798f661f8c8c042f3582cde8b611d1c9c7343f.tar.gz
coreclr-45798f661f8c8c042f3582cde8b611d1c9c7343f.tar.bz2
coreclr-45798f661f8c8c042f3582cde8b611d1c9c7343f.zip
ARM64: Enabling Crossgen End-to-End Mscorlib
Fixes https://github.com/dotnet/coreclr/issues/4350 Fixes https://github.com/dotnet/coreclr/issues/4615 This is a bit large change across VM/Zap/JIT to properly support crossgen scenario. 1. Fix incorrect `ldr` encoding with size. 2. Enforce JIT data following JIT code per method by allocating them together. This guarantees correct PC-relative encoding for such constant data access without fix-up. 3. For the general fix-up data acceess, use `adrp/add` instruction pairs with fix-ups. Two more relocations types are implemented in all sides. 4. Interface dispatch stub is now implemented which is needed for interface call for crossgen. I've verified hello world runs with mscorlib.ni.dll.
Diffstat (limited to 'src/utilcode/util.cpp')
-rw-r--r--src/utilcode/util.cpp81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/utilcode/util.cpp b/src/utilcode/util.cpp
index f801f94b60..50643d4a7e 100644
--- a/src/utilcode/util.cpp
+++ b/src/utilcode/util.cpp
@@ -2684,6 +2684,41 @@ INT32 GetArm64Rel28(UINT32 * pCode)
}
//*****************************************************************************
+// Extract the PC-Relative offset from an adrp instruction
+//*****************************************************************************
+INT32 GetArm64Rel21(UINT32 * pCode)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ UINT32 addInstr = *pCode;
+
+ // 23-5 bits for the high part. Shift it by 5.
+ INT32 immhi = (((INT32)(addInstr & 0xFFFFE0))) >> 5;
+ // 30,29 bits for the lower part. Shift it by 29.
+ INT32 immlo = ((INT32)(addInstr & 0x60000000)) >> 29;
+
+ // Merge them
+ INT32 imm21 = (immhi << 2) | immlo;
+
+ return imm21;
+}
+
+//*****************************************************************************
+// Extract the PC-Relative offset from an add instruction
+//*****************************************************************************
+INT32 GetArm64Rel12(UINT32 * pCode)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ UINT32 addInstr = *pCode;
+
+ // 21-10 contains value. Mask 12 bits and shift by 10 bits.
+ INT32 imm12 = (INT32)(addInstr & 0x003FFC00) >> 10;
+
+ return imm12;
+}
+
+//*****************************************************************************
// Deposit the PC-Relative offset 'imm28' into a b or bl instruction
//*****************************************************************************
void PutArm64Rel28(UINT32 * pCode, INT32 imm28)
@@ -2706,6 +2741,52 @@ void PutArm64Rel28(UINT32 * pCode, INT32 imm28)
_ASSERTE(GetArm64Rel28(pCode) == imm28);
}
+//*****************************************************************************
+// Deposit the PC-Relative offset 'imm21' into an adrp instruction
+//*****************************************************************************
+void PutArm64Rel21(UINT32 * pCode, INT32 imm21)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ // Verify that we got a valid offset
+ _ASSERTE(FitsInRel21(imm21));
+
+ UINT32 adrpInstr = *pCode;
+ // Check adrp opcode 1ii1 0000 ...
+ _ASSERTE((adrpInstr & 0x9F000000) == 0x90000000);
+
+ adrpInstr &= 0x9F00001F; // keep bits 31, 28-24, 4-0.
+ INT32 immlo = imm21 & 0x03; // Extract low 2 bits which will occupy 30-29 bits.
+ INT32 immhi = (imm21 & 0x1FFFFC) >> 2; // Extract high 19 bits which will occupy 23-5 bits.
+ adrpInstr |= ((immlo << 29) | (immhi << 5));
+
+ *pCode = adrpInstr; // write the assembled instruction
+
+ _ASSERTE(GetArm64Rel21(pCode) == imm21);
+}
+
+//*****************************************************************************
+// Deposit the PC-Relative offset 'imm12' into an add instruction
+//*****************************************************************************
+void PutArm64Rel12(UINT32 * pCode, INT32 imm12)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ // Verify that we got a valid offset
+ _ASSERTE(FitsInRel12(imm12));
+
+ UINT32 addInstr = *pCode;
+ // Check add opcode 1001 0001 00...
+ _ASSERTE((addInstr & 0xFFC00000) == 0x91000000);
+
+ addInstr &= 0xFFC003FF; // keep bits 31-22, 9-0
+ addInstr |= (imm12 << 10); // Occupy 21-10.
+
+ *pCode = addInstr; // write the assembled instruction
+
+ _ASSERTE(GetArm64Rel12(pCode) == imm12);
+}
+
//---------------------------------------------------------------------
// Splits a command line into argc/argv lists, using the VC7 parsing rules.
//