-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use CRT implementation of memset/memcpy (#67788)
* Use CRT implementation of memset/memcpy * Remove the outdated comment:
- Loading branch information
1 parent
4a8f230
commit cde7799
Showing
2 changed files
with
63 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,176 +1,86 @@ | ||
; Licensed to the .NET Foundation under one or more agreements. | ||
; The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
;; ==++== | ||
;; | ||
|
||
;; | ||
;; ==--== | ||
; ==++== | ||
; | ||
|
||
; | ||
; ==--== | ||
#include "ksarm64.h" | ||
#include "asmconstants.h" | ||
#include "asmmacros.h" | ||
|
||
TEXTAREA | ||
IMPORT memset | ||
IMPORT memmove | ||
|
||
;void JIT_MemSet(void *dst, int val, SIZE_T count) | ||
;{ | ||
; uint64_t valEx = (unsigned char)val; | ||
; valEx = valEx | valEx << 8; | ||
; valEx = valEx | valEx << 16; | ||
; valEx = valEx | valEx << 32; | ||
; | ||
; count-=16; | ||
; | ||
; while(count >= 0) | ||
; { | ||
; *(uint64_t*)dst = valEx; | ||
; dst = (uint64_t*)dst + 1; | ||
; *(uint64_t*)dst = valEx; | ||
; dst = (uint64_t*)dst + 1; | ||
; count-=16; | ||
; } | ||
; | ||
; if(count & 8) | ||
; { | ||
; *(uint64_t*)dst = valEx; | ||
; dst = (uint64_t*)dst + 1; | ||
; } | ||
; | ||
; if(count & 4) | ||
; { | ||
; *(uint32_t*)dst = (uint32_t)valEx; | ||
; dst = (uint32_t*)dst + 1; | ||
; } | ||
; | ||
; if(count & 2) | ||
; { | ||
; *(uint16_t*)dst = (uint16_t)valEx; | ||
; dst = (uint16_t*)dst + 1; | ||
; } | ||
; | ||
; if(count & 1) | ||
; { | ||
; *(uint8_t*)dst = (uint8_t)valEx; | ||
; } | ||
;} | ||
; JIT_MemSet/JIT_MemCpy | ||
; | ||
; It is IMPORTANT that the exception handling code is able to find these guys | ||
; on the stack, but on windows platforms we can just defer to the platform | ||
; implementation. | ||
; | ||
|
||
; 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. | ||
; void JIT_MemSet(void* dest, int c, size_t count) | ||
; | ||
; Purpose: | ||
; Sets the first "count" bytes of the block of memory pointed byte | ||
; "dest" to the specified value (interpreted as an unsigned char). | ||
; | ||
; Entry: | ||
; RCX: void* dest - Pointer to the block of memory to fill. | ||
; RDX: int c - Value to be set. | ||
; R8: size_t count - Number of bytes to be set to the value. | ||
; | ||
; Exit: | ||
; | ||
; Uses: | ||
; | ||
; Exceptions: | ||
; | ||
|
||
TEXTAREA | ||
LEAF_ENTRY JIT_MemSet | ||
ands w1, w1, #0xff | ||
orr w1, w1, w1, lsl #8 | ||
orr w1, w1, w1, lsl #0x10 | ||
orr x1, x1, x1, lsl #0x20 | ||
cbz x2, JIT_MemSet_ret ; check if count is zero, no bytes to set | ||
|
||
b JIT_MemSet_bottom | ||
JIT_MemSet_top | ||
stp x1, x1, [x0], #16 | ||
JIT_MemSet_bottom | ||
subs x2, x2, #16 | ||
bge JIT_MemSet_top | ||
|
||
tbz x2, #3, JIT_MemSet_tbz4 | ||
str x1, [x0], #8 | ||
JIT_MemSet_tbz4 | ||
tbz x2, #2, JIT_MemSet_tbz2 | ||
str w1, [x0], #4 | ||
JIT_MemSet_tbz2 | ||
tbz x2, #1, JIT_MemSet_tbz1 | ||
strh w1, [x0], #2 | ||
JIT_MemSet_tbz1 | ||
tbz x2, #0, JIT_MemSet_ret | ||
strb w1, [x0] | ||
JIT_MemSet_ret | ||
ret lr | ||
LEAF_END | ||
|
||
LEAF_ENTRY JIT_MemSet_End | ||
nop | ||
LEAF_END | ||
ldrb wzr, [x0] ; check dest for null | ||
|
||
b memset ; forward to the CRT implementation | ||
|
||
; See comments above for JIT_MemSet | ||
JIT_MemSet_ret | ||
ret lr | ||
LEAF_END_MARKED JIT_MemSet | ||
|
||
;void JIT_MemCpy(void *dst, const void *src, SIZE_T count) | ||
;{ | ||
; count-=16; | ||
; | ||
; while(count >= 0) | ||
; { | ||
; *(unit64_t*)dst = *(unit64_t*)src; | ||
; dst = (unit64_t*)dst + 1; | ||
; src = (unit64_t*)src + 1; | ||
; *(unit64_t*)dst = *(unit64_t*)src; | ||
; dst = (unit64_t*)dst + 1; | ||
; src = (unit64_t*)src + 1; | ||
; count-=16; | ||
; } | ||
; | ||
; if(count & 8) | ||
; { | ||
; *(unit64_t*)dst = *(unit64_t*)src; | ||
; dst = (unit64_t*)dst + 1; | ||
; src = (unit64_t*)src + 1; | ||
; } | ||
; | ||
; if(count & 4) | ||
; { | ||
; *(unit32_t*)dst = *(unit32_t*)src; | ||
; dst = (unit32_t*)dst + 1; | ||
; src = (unit32_t*)src + 1; | ||
; } | ||
; | ||
; if(count & 2) | ||
; { | ||
; *(unit16_t*)dst = *(unit16_t*)src; | ||
; dst = (unit16_t*)dst + 1; | ||
; src = (unit16_t*)src + 1; | ||
; } | ||
; | ||
; if(count & 1) | ||
; { | ||
; *(unit8_t*)dst = *(unit8_t*)src; | ||
; } | ||
;} | ||
; void JIT_MemCpy(void* dest, const void* src, size_t count) | ||
; | ||
; Purpose: | ||
; Copies the values of "count" bytes from the location pointed to | ||
; by "src" to the memory block pointed by "dest". | ||
; | ||
; Entry: | ||
; RCX: void* dest - Pointer to the destination array where content is to be copied. | ||
; RDX: const void* src - Pointer to the source of the data to be copied. | ||
; R8: size_t count - Number of bytes to copy. | ||
; | ||
; Exit: | ||
; | ||
; Uses: | ||
; | ||
; Exceptions: | ||
; | ||
|
||
; Assembly code corresponding to above C++ method. | ||
; See comments above for JIT_MemSet method | ||
LEAF_ENTRY JIT_MemCpy | ||
b JIT_MemCpy_bottom | ||
JIT_MemCpy_top | ||
ldp x8, x9, [x1], #16 | ||
stp x8, x9, [x0], #16 | ||
JIT_MemCpy_bottom | ||
subs x2, x2, #16 | ||
bge JIT_MemCpy_top | ||
cbz x2, JIT_MemCpy_ret ; check if count is zero, no bytes to set | ||
|
||
ldrb wzr, [x0] ; check dest for null | ||
ldrb wzr, [x1] ; check src for null | ||
|
||
b memmove ; forward to the CRT implementation | ||
|
||
tbz x2, #3, JIT_MemCpy_tbz4 | ||
ldr x8, [x1], #8 | ||
str x8, [x0], #8 | ||
JIT_MemCpy_tbz4 | ||
tbz x2, #2, JIT_MemCpy_tbz2 | ||
ldr w8, [x1], #4 | ||
str w8, [x0], #4 | ||
JIT_MemCpy_tbz2 | ||
tbz x2, #1, JIT_MemCpy_tbz1 | ||
ldrsh w8, [x1], #2 | ||
strh w8, [x0], #2 | ||
JIT_MemCpy_tbz1 | ||
tbz x2, #0, JIT_MemCpy_ret | ||
ldrsb w8, [x1] | ||
strb w8, [x0] | ||
JIT_MemCpy_ret | ||
ret lr | ||
LEAF_END | ||
|
||
LEAF_ENTRY JIT_MemCpy_End | ||
nop | ||
LEAF_END | ||
LEAF_END_MARKED JIT_MemCpy | ||
|
||
; Must be at very end of file | ||
END | ||
END |