CopyMem.asm 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. ;------------------------------------------------------------------------------
  2. ;
  3. ; CopyMem() worker for ARM
  4. ;
  5. ; This file started out as C code that did 64 bit moves if the buffer was
  6. ; 32-bit aligned, else it does a byte copy. It also does a byte copy for
  7. ; any trailing bytes. It was updated to do 32-byte copies using stm/ldm.
  8. ;
  9. ; Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
  10. ; This program and the accompanying materials
  11. ; are licensed and made available under the terms and conditions of the BSD License
  12. ; which accompanies this distribution. The full text of the license may be found at
  13. ; http://opensource.org/licenses/bsd-license.php
  14. ;
  15. ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  16. ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  17. ;
  18. ;------------------------------------------------------------------------------
  19. /**
  20. Copy Length bytes from Source to Destination. Overlap is OK.
  21. This implementation
  22. @param Destination Target of copy
  23. @param Source Place to copy from
  24. @param Length Number of bytes to copy
  25. @return Destination
  26. VOID *
  27. EFIAPI
  28. InternalMemCopyMem (
  29. OUT VOID *DestinationBuffer,
  30. IN CONST VOID *SourceBuffer,
  31. IN UINTN Length
  32. )
  33. **/
  34. EXPORT InternalMemCopyMem
  35. AREA AsmMemStuff, CODE, READONLY
  36. InternalMemCopyMem
  37. stmfd sp!, {r4-r11, lr}
  38. // Save the input parameters in extra registers (r11 = destination, r14 = source, r12 = length)
  39. mov r11, r0
  40. mov r10, r0
  41. mov r12, r2
  42. mov r14, r1
  43. memcopy_check_overlapped
  44. cmp r11, r1
  45. // If (dest < source)
  46. bcc memcopy_check_optim_default
  47. // If (dest <= source). But with the previous condition -> If (dest == source)
  48. bls memcopy_end
  49. // If (source + length < dest)
  50. rsb r3, r1, r11
  51. cmp r12, r3
  52. bcc memcopy_check_optim_default
  53. // If (length == 0)
  54. cmp r12, #0
  55. beq memcopy_end
  56. b memcopy_check_optim_overlap
  57. memcopy_check_optim_default
  58. // Check if we can use an optimized path ((length >= 32) && destination word-aligned && source word-aligned) for the memcopy (optimized path if r0 == 1)
  59. tst r0, #0xF
  60. movne r0, #0
  61. bne memcopy_default
  62. tst r1, #0xF
  63. movne r3, #0
  64. moveq r3, #1
  65. cmp r2, #31
  66. movls r0, #0
  67. andhi r0, r3, #1
  68. b memcopy_default
  69. memcopy_check_optim_overlap
  70. // r10 = dest_end, r14 = source_end
  71. add r10, r11, r12
  72. add r14, r12, r1
  73. // Are we in the optimized case ((length >= 32) && dest_end word-aligned && source_end word-aligned)
  74. cmp r2, #31
  75. movls r0, #0
  76. movhi r0, #1
  77. tst r10, #0xF
  78. movne r0, #0
  79. tst r14, #0xF
  80. movne r0, #0
  81. b memcopy_overlapped
  82. memcopy_overlapped_non_optim
  83. // We read 1 byte from the end of the source buffer
  84. sub r3, r14, #1
  85. sub r12, r12, #1
  86. ldrb r3, [r3, #0]
  87. sub r2, r10, #1
  88. cmp r12, #0
  89. // We write 1 byte at the end of the dest buffer
  90. sub r10, r10, #1
  91. sub r14, r14, #1
  92. strb r3, [r2, #0]
  93. bne memcopy_overlapped_non_optim
  94. b memcopy_end
  95. // r10 = dest_end, r14 = source_end
  96. memcopy_overlapped
  97. // Are we in the optimized case ?
  98. cmp r0, #0
  99. beq memcopy_overlapped_non_optim
  100. // Optimized Overlapped - Read 32 bytes
  101. sub r14, r14, #32
  102. sub r12, r12, #32
  103. cmp r12, #31
  104. ldmia r14, {r2-r9}
  105. // If length is less than 32 then disable optim
  106. movls r0, #0
  107. cmp r12, #0
  108. // Optimized Overlapped - Write 32 bytes
  109. sub r10, r10, #32
  110. stmia r10, {r2-r9}
  111. // while (length != 0)
  112. bne memcopy_overlapped
  113. b memcopy_end
  114. memcopy_default_non_optim
  115. // Byte copy
  116. ldrb r3, [r14], #1
  117. sub r12, r12, #1
  118. strb r3, [r10], #1
  119. memcopy_default
  120. cmp r12, #0
  121. beq memcopy_end
  122. // r10 = dest, r14 = source
  123. memcopy_default_loop
  124. cmp r0, #0
  125. beq memcopy_default_non_optim
  126. // Optimized memcopy - Read 32 Bytes
  127. sub r12, r12, #32
  128. cmp r12, #31
  129. ldmia r14!, {r2-r9}
  130. // If length is less than 32 then disable optim
  131. movls r0, #0
  132. cmp r12, #0
  133. // Optimized memcopy - Write 32 Bytes
  134. stmia r10!, {r2-r9}
  135. // while (length != 0)
  136. bne memcopy_default_loop
  137. memcopy_end
  138. mov r0, r11
  139. ldmfd sp!, {r4-r11, pc}
  140. END