summaryrefslogtreecommitdiff
path: root/src/vm/arm64/crthelpers.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/arm64/crthelpers.S')
-rw-r--r--src/vm/arm64/crthelpers.S291
1 files changed, 291 insertions, 0 deletions
diff --git a/src/vm/arm64/crthelpers.S b/src/vm/arm64/crthelpers.S
new file mode 100644
index 0000000000..2c677e0a31
--- /dev/null
+++ b/src/vm/arm64/crthelpers.S
@@ -0,0 +1,291 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// ==++==
+//
+
+#include "unixasmmacros.inc"
+
+//
+// ==--==
+
+// Calls to JIT_MemSet is emitted by jit for initialization of large structs.
+// We need to provide our own implementation of memset instead of using the ones in crt because crt implementation does not gurantee
+// that aligned 8/4/2 - byte memory will be written atomically. This is required because members in a struct can be read atomically
+// and their values should be written atomically.
+//
+//
+//void JIT_MemSet(void *dst, int val, SIZE_T count)
+//
+// uintptr_t valEx = (char)val;
+// valEx = valEx | valEx << 8;
+// valEx = valEx | valEx << 16;
+// valEx = valEx | valEx << 32;
+//
+// // If not aligned then make it 8-byte aligned
+// if(((uintptr_t)dst&0x7) != 0)
+// {
+// if(((uintptr_t)dst&0x3) == 0)
+// {
+// *(UINT*)dst = (UINT)valEx;
+// dst = (UINT*)dst + 1;
+// count-=4;
+// }
+// else if(((uintptr_t)dst&0x1) == 0)
+// {
+// while(count > 0 && ((uintptr_t)dst&0x7) != 0)
+// {
+// *(short*)dst = (short)valEx;
+// dst = (short*)dst + 1;
+// count-=2;
+// }
+// }
+// else
+// {
+// while(count > 0 && ((uintptr_t)dst&0x7) != 0)
+// {
+// *(char*)dst = (char)valEx;
+// dst = (char*)dst + 1;
+// count--;
+// }
+// }
+// }
+//
+// while(count > 8)
+// {
+// *(uintptr_t*)dst = valEx;
+// dst = (uintptr_t*)dst + 1;
+// count-=8;
+// }
+//
+// if(count & 4)
+// {
+// *(UINT*)dst = (UINT)valEx;
+// dst = (UINT*)dst + 1;
+// }
+//
+// if(count & 2)
+// {
+// *(short*)dst = (short)valEx;
+// dst = (short*)dst + 1;
+// }
+//
+// if(count & 1)
+// {
+// *(char*)dst = (char)valEx;
+// }
+//
+//
+
+// Assembly code corresponding to above C++ method. JIT_MemSet can AV and clr exception personality routine needs to
+// determine if the exception has taken place inside JIT_Memset in order to throw corresponding managed exception.
+// Determining this is slow if the method were implemented as C++ method (using unwind info). In .asm file by adding JIT_MemSet_End
+// marker it can be easily determined if exception happened in JIT_MemSet. Therefore, JIT_MemSet has been written in assembly instead of
+// as C++ method.
+
+LEAF_ENTRY JIT_MemSet, _TEXT
+ sxtb w8,w1
+ sxtw x8,w8
+ orr x8,x8,x8, lsl #8
+ orr x8,x8,x8, lsl #0x10
+ orr x9,x8,x8, lsl #0x20
+ and x8,x0,#7
+ cbz x8,LOCAL_LABEL(JIT_MemSet_0x7c)
+ and x8,x0,#3
+ cbnz x8,LOCAL_LABEL(JIT_MemSet_0x38)
+ str w9,[x0]
+ add x0,x0,#4
+ mov x8,#-4
+ add x2,x2,x8
+ b LOCAL_LABEL(JIT_MemSet_0x7c)
+LOCAL_LABEL(JIT_MemSet_0x38):
+ cbz x2,LOCAL_LABEL(JIT_MemSet_0x7c)
+ tbnz x0,#0,LOCAL_LABEL(JIT_MemSet_0x60)
+LOCAL_LABEL(JIT_MemSet_0x40):
+ and x8,x0,#7
+ cbz x8,LOCAL_LABEL(JIT_MemSet_0x7c)
+ strh w9,[x0]
+ add x0,x0,#2
+ mov x8,#-2
+ add x2,x2,x8
+ cbnz x2,LOCAL_LABEL(JIT_MemSet_0x40)
+ b LOCAL_LABEL(JIT_MemSet_0x7c)
+LOCAL_LABEL(JIT_MemSet_0x60):
+ and x8,x0,#7
+ cbz x8,LOCAL_LABEL(JIT_MemSet_0x7c)
+ strb w9,[x0]
+ add x0,x0,#1
+ mov x8,#-1
+ add x2,x2,x8
+ cbnz x2,LOCAL_LABEL(JIT_MemSet_0x60)
+LOCAL_LABEL(JIT_MemSet_0x7c):
+ cmp x2,#8
+ bls LOCAL_LABEL(JIT_MemSet_0xb8)
+ mov x8,#-9
+ add x8,x2,x8
+ lsr x8,x8,#3
+ add x11,x8,#1
+ mov x10,x0
+ add x8,x10,x11, lsl #3
+LOCAL_LABEL(JIT_MemSet_0x9c):
+ cmp x10,x8
+ beq LOCAL_LABEL(JIT_MemSet_0xac)
+ str x9,[x10],#8
+ b LOCAL_LABEL(JIT_MemSet_0x9c)
+LOCAL_LABEL(JIT_MemSet_0xac):
+ mov x8,#-8
+ madd x2,x11,x8,x2
+ add x0,x0,x11, lsl #3
+LOCAL_LABEL(JIT_MemSet_0xb8):
+ tbz x2,#2,LOCAL_LABEL(JIT_MemSet_0xc4)
+ str w9,[x0]
+ add x0,x0,#4
+LOCAL_LABEL(JIT_MemSet_0xc4):
+ tbz x2,#1,LOCAL_LABEL(JIT_MemSet_0xd0)
+ strh w9,[x0]
+ add x0,x0,#2
+LOCAL_LABEL(JIT_MemSet_0xd0):
+ tbz x2,#0,LOCAL_LABEL(JIT_MemSet_0xd8)
+ strb w9,[x0]
+LOCAL_LABEL(JIT_MemSet_0xd8):
+ ret lr
+LEAF_END JIT_MemSet, _TEXT
+
+// See comments above for JIT_MemSet
+
+//void JIT_MemCpy(void *dst, const void *src, SIZE_T count)
+//
+// // If not aligned then make it 8-byte aligned
+// if(((uintptr_t)dst&0x7) != 0)
+// {
+// if(((uintptr_t)dst&0x3) == 0)
+// {
+// *(UINT*)dst = *(UINT*)src;
+// dst = (UINT*)dst + 1;
+// src = (UINT*)src + 1;
+// count-=4;
+// }
+// else if(((uintptr_t)dst&0x1) == 0)
+// {
+// while(count > 0 && ((uintptr_t)dst&0x7) != 0)
+// {
+// *(short*)dst = *(short*)src;
+// dst = (short*)dst + 1;
+// src = (short*)src + 1;
+// count-=2;
+// }
+// }
+// else
+// {
+// while(count > 0 && ((uintptr_t)dst&0x7) != 0)
+// {
+// *(char*)dst = *(char*)src;
+// dst = (char*)dst + 1;
+// src = (char*)src + 1;
+// count--;
+// }
+// }
+// }
+//
+// while(count > 8)
+// {
+// *(uintptr_t*)dst = *(uintptr_t*)src;
+// dst = (uintptr_t*)dst + 1;
+// src = (uintptr_t*)src + 1;
+// count-=8;
+// }
+//
+// if(count & 4)
+// {
+// *(UINT*)dst = *(UINT*)src;
+// dst = (UINT*)dst + 1;
+// src = (UINT*)src + 1;
+// }
+//
+// if(count & 2)
+// {
+// *(short*)dst = *(short*)src;
+// dst = (short*)dst + 1;
+// src = (short*)src + 1;
+// }
+//
+// if(count & 1)
+// {
+// *(char*)dst = *(char*)src;
+// }
+//
+//
+
+// Assembly code corresponding to above C++ method.
+// See comments above for JIT_MemSet method
+LEAF_ENTRY JIT_MemCpy, _TEXT
+ and x8,x0,#7
+ cbz x8,LOCAL_LABEL(JIT_MemCpy_0x80)
+ and x8,x0,#3
+ cbnz x8,LOCAL_LABEL(JIT_MemCpy_0x2c)
+ ldr w8,[x1]
+ str w8,[x0]
+ add x0,x0,#4
+ add x1,x1,#4
+ mov x8,#-4
+ add x2,x2,x8
+ b LOCAL_LABEL(JIT_MemCpy_0x80)
+LOCAL_LABEL(JIT_MemCpy_0x2c):
+ cbz x2,LOCAL_LABEL(JIT_MemCpy_0x80)
+ tbnz x0,#0,LOCAL_LABEL(JIT_MemCpy_0x5c)
+LOCAL_LABEL(JIT_MemCpy_0x34):
+ and x8,x0,#7
+ cbz x8,LOCAL_LABEL(JIT_MemCpy_0x80)
+ ldrsh w8,[x1]
+ strh w8,[x0]
+ add x0,x0,#2
+ add x1,x1,#2
+ mov x8,#-2
+ add x2,x2,x8
+ cbnz x2,LOCAL_LABEL(JIT_MemCpy_0x34)
+ b LOCAL_LABEL(JIT_MemCpy_0x80)
+LOCAL_LABEL(JIT_MemCpy_0x5c):
+ and x8,x0,#7
+ cbz x8,LOCAL_LABEL(JIT_MemCpy_0x80)
+ ldrsb w8,[x1]
+ strb w8,[x0]
+ add x0,x0,#1
+ add x1,x1,#1
+ mov x8,#-1
+ add x2,x2,x8
+ cbnz x2,LOCAL_LABEL(JIT_MemCpy_0x5c)
+LOCAL_LABEL(JIT_MemCpy_0x80):
+ cmp x2,#8
+ bls LOCAL_LABEL(JIT_MemCpy_0xb4)
+ mov x8,#-9
+ add x8,x2,x8
+ lsr x8,x8,#3
+ add x9,x8,#1
+ mov x8,#-8
+ madd x2,x9,x8,x2
+LOCAL_LABEL(JIT_MemCpy_0xa0):
+ ldr x8,[x1],#8
+ str x8,[x0],#8
+ mov x8,#-1
+ add x9,x9,x8
+ cbnz x9,LOCAL_LABEL(JIT_MemCpy_0xa0)
+LOCAL_LABEL(JIT_MemCpy_0xb4):
+ tbz x2,#2,LOCAL_LABEL(JIT_MemCpy_0xc8)
+ ldr w8,[x1]
+ str w8,[x0]
+ add x0,x0,#4
+ add x1,x1,#4
+LOCAL_LABEL(JIT_MemCpy_0xc8):
+ tbz x2,#1,LOCAL_LABEL(JIT_MemCpy_0xdc)
+ ldrsh w8,[x1]
+ strh w8,[x0]
+ add x0,x0,#2
+ add x1,x1,#2
+LOCAL_LABEL(JIT_MemCpy_0xdc):
+ tbz x2,#0,LOCAL_LABEL(JIT_MemCpy_0xe8)
+ ldrsb w8,[x1]
+ strb w8,[x0]
+LOCAL_LABEL(JIT_MemCpy_0xe8):
+ ret lr
+LEAF_END JIT_MemCpy, _TEXT