[RTL}
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Thu, 23 Dec 2010 19:11:19 +0000 (19:11 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Thu, 23 Dec 2010 19:11:19 +0000 (19:11 +0000)
Replace RtlMoveMemory x86 asm code with the code from CRT's memmove, which is better. Now we can close bug #1941

svn path=/trunk/; revision=50116

reactos/lib/rtl/i386/rtlmem.s

index d26f5b4..0925b96 100644 (file)
@@ -210,70 +210,124 @@ ByteZero:
 
 
 _RtlMoveMemory@12:
+       push ebp
+       mov ebp, esp
 
-    /* Save volatiles */
+    /* Save non-volatiles */
     push esi
     push edi
 
     /* Get pointers and size  */
-    mov esi, [esp+16]
-    mov edi, [esp+12]
-    mov ecx, [esp+20]
-    cld
-
-    /* Check if the destination is higher (or equal) */
-    cmp esi, edi
-    jbe Overlap
-
-    /* Set ULONG size and UCHAR remainder */
-DoMove:
-    mov edx, ecx
-    and edx, 3
-    shr ecx, 2
-
-    /* Do the move */
-    rep movsd
-    or ecx, edx
-    jnz ByteMove
-
-    /* Return */
-    pop edi
-    pop esi
-    ret 12
-
-ByteMove:
-    /* Move what's left */
-    rep movsb
-
-DoneMove:
-    /* Restore volatiles */
-    pop edi
-    pop esi
-    ret 12
+       mov     edi, [ebp + 8]
+       mov     esi, [ebp + 12]
+       mov     ecx, [ebp + 16]
+
+    /* Use downward copy if source < dest and overlapping */
+       cmp     edi, esi
+       jbe     .CopyUp
+       mov     eax, ecx
+       add     eax, esi
+       cmp     edi, eax
+       jb .CopyDown
+
+.CopyUp:
+       cld
+
+    /* Check for small moves */
+       cmp     ecx, 16
+       jb .CopyUpBytes
+
+    /* Check if its already aligned */
+       mov edx, ecx
+       test edi, 3
+       je .CopyUpDwords
+
+    /* Make the destination dword aligned */
+       mov ecx, edi
+       and ecx, 3
+       sub ecx, 5
+       not ecx
+       sub edx, ecx
+       rep movsb
+       mov ecx, edx
+
+.CopyUpDwords:
+       shr ecx, 2
+       rep movsd
+       mov ecx, edx
+       and ecx, 3
+
+.CopyUpBytes:
+       test ecx, ecx
+       je .CopyUpEnd
+       rep movsb
+
+.CopyUpEnd:
+       mov eax, [ebp + 8]
+       pop edi
+       pop esi
+       pop ebp
+       ret 12
+
+.CopyDown:
+       std
+
+    /* Go to the end of the region */
+       add edi, ecx
+       add esi, ecx
+
+    /* Check for small moves */
+       cmp ecx, 16
+       jb .CopyDownSmall
+
+    /* Check if its already aligned */
+       mov edx, ecx
+       test edi, 3
+       je .CopyDownAligned
+
+    /* Make the destination dword aligned */
+       mov ecx, edi
+       and ecx, 3
+       sub edx, ecx
+       dec esi
+       dec edi
+       rep movsb
+       mov ecx, edx
+       sub esi, 3
+       sub edi, 3
+
+.CopyDownDwords:
+       shr ecx, 2
+       rep movsd
+       mov ecx, edx
+       and ecx, 3
+       je .CopyDownEnd
+       add esi, 3
+       add edi, 3
+
+.CopyDownBytes:
+       rep movsb
+
+.CopyDownEnd:
+       cld
+       mov eax, [ebp + 8]
+       pop edi
+       pop esi
+       pop ebp
+       ret 12
+
+.CopyDownAligned:
+       sub edi, 4
+       sub esi, 4
+       jmp .CopyDownDwords
+
+.CopyDownSmall:
+       test ecx, ecx
+       je .CopyDownEnd
+       dec esi
+       dec edi
+       jmp .CopyDownBytes
 
-Overlap:
-    /* Don't copy if they're equal */
-    jz DoneMove
-
-    /* Compare pointer distance with given length and check for overlap */
-    mov eax, edi
-    sub eax, esi
-    cmp ecx, eax
-    jbe DoMove
-
-    /* Set direction flag for backward move */
-    std
-
-    /* Copy byte-by-byte the non-overlapping distance */
-    add esi, ecx
-    add edi, ecx
-    dec esi
-    dec edi
-
-    /* Do the move, reset flag and return */
-    rep movsb
-    cld
-    jmp DoneMove
 
 
 @RtlPrefetchMemoryNonTemporal@8: