CopyMem.S 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. .text
  35. .align 2
  36. GCC_ASM_EXPORT(InternalMemCopyMem)
  37. ASM_PFX(InternalMemCopyMem):
  38. stmfd sp!, {r4-r11, lr}
  39. // Save the input parameters in extra registers (r11 = destination, r14 = source, r12 = length)
  40. mov r11, r0
  41. mov r10, r0
  42. mov r12, r2
  43. mov r14, r1
  44. memcopy_check_overlapped:
  45. cmp r11, r1
  46. // If (dest < source)
  47. bcc memcopy_check_optim_default
  48. // If (dest <= source). But with the previous condition -> If (dest == source)
  49. bls memcopy_end
  50. // If (source + length < dest)
  51. rsb r3, r1, r11
  52. cmp r12, r3
  53. bcc memcopy_check_optim_default
  54. // If (length == 0)
  55. cmp r12, #0
  56. beq memcopy_end
  57. b memcopy_check_optim_overlap
  58. memcopy_check_optim_default:
  59. // Check if we can use an optimized path ((length >= 32) && destination word-aligned && source word-aligned) for the memcopy (optimized path if r0 == 1)
  60. tst r0, #0xF
  61. movne r0, #0
  62. bne memcopy_default
  63. tst r1, #0xF
  64. movne r3, #0
  65. moveq r3, #1
  66. cmp r2, #31
  67. movls r0, #0
  68. andhi r0, r3, #1
  69. b memcopy_default
  70. memcopy_check_optim_overlap:
  71. // r10 = dest_end, r14 = source_end
  72. add r10, r11, r12
  73. add r14, r12, r1
  74. // Are we in the optimized case ((length >= 32) && dest_end word-aligned && source_end word-aligned)
  75. cmp r2, #31
  76. movls r0, #0
  77. movhi r0, #1
  78. tst r10, #0xF
  79. movne r0, #0
  80. tst r14, #0xF
  81. movne r0, #0
  82. b memcopy_overlapped
  83. memcopy_overlapped_non_optim:
  84. // We read 1 byte from the end of the source buffer
  85. sub r3, r14, #1
  86. sub r12, r12, #1
  87. ldrb r3, [r3, #0]
  88. sub r2, r10, #1
  89. cmp r12, #0
  90. // We write 1 byte at the end of the dest buffer
  91. sub r10, r10, #1
  92. sub r14, r14, #1
  93. strb r3, [r2, #0]
  94. bne memcopy_overlapped_non_optim
  95. b memcopy_end
  96. // r10 = dest_end, r14 = source_end
  97. memcopy_overlapped:
  98. // Are we in the optimized case ?
  99. cmp r0, #0
  100. beq memcopy_overlapped_non_optim
  101. // Optimized Overlapped - Read 32 bytes
  102. sub r14, r14, #32
  103. sub r12, r12, #32
  104. cmp r12, #31
  105. ldmia r14, {r2-r9}
  106. // If length is less than 32 then disable optim
  107. movls r0, #0
  108. cmp r12, #0
  109. // Optimized Overlapped - Write 32 bytes
  110. sub r10, r10, #32
  111. stmia r10, {r2-r9}
  112. // while (length != 0)
  113. bne memcopy_overlapped
  114. b memcopy_end
  115. memcopy_default_non_optim:
  116. // Byte copy
  117. ldrb r3, [r14], #1
  118. sub r12, r12, #1
  119. strb r3, [r10], #1
  120. memcopy_default:
  121. cmp r12, #0
  122. beq memcopy_end
  123. // r10 = dest, r14 = source
  124. memcopy_default_loop:
  125. cmp r0, #0
  126. beq memcopy_default_non_optim
  127. // Optimized memcopy - Read 32 Bytes
  128. sub r12, r12, #32
  129. cmp r12, #31
  130. ldmia r14!, {r2-r9}
  131. // If length is less than 32 then disable optim
  132. movls r0, #0
  133. cmp r12, #0
  134. // Optimized memcopy - Write 32 Bytes
  135. stmia r10!, {r2-r9}
  136. // while (length != 0)
  137. bne memcopy_default_loop
  138. memcopy_end:
  139. mov r0, r11
  140. ldmfd sp!, {r4-r11, pc}