]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseMemoryLib/CopyMem.c
929f7007478fe13a743f7cf1d5198ed00fba20c7
[mirror_edk2.git] / MdePkg / Library / BaseMemoryLib / CopyMem.c
1 /** @file
2 Implementation of the InternalMemCopyMem routine. This function is broken
3 out into its own source file so that it can be excluded from a build for a
4 particular platform easily if an optimized version is desired.
5
6 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
7 Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>
8 Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
9
10 SPDX-License-Identifier: BSD-2-Clause-Patent
11
12 **/
13
14 #include "MemLibInternals.h"
15
16 /**
17 Copy Length bytes from Source to Destination.
18
19 @param DestinationBuffer The target of the copy request.
20 @param SourceBuffer The place to copy from.
21 @param Length The number of bytes to copy.
22
23 @return Destination
24
25 **/
26 VOID *
27 EFIAPI
28 InternalMemCopyMem (
29 OUT VOID *DestinationBuffer,
30 IN CONST VOID *SourceBuffer,
31 IN UINTN Length
32 )
33 {
34 //
35 // Declare the local variables that actually move the data elements as
36 // volatile to prevent the optimizer from replacing this function with
37 // the intrinsic memcpy()
38 //
39 volatile UINT8 *Destination8;
40 CONST UINT8 *Source8;
41 volatile UINT32 *Destination32;
42 CONST UINT32 *Source32;
43 volatile UINT64 *Destination64;
44 CONST UINT64 *Source64;
45 UINTN Alignment;
46
47 if ((((UINTN)DestinationBuffer & 0x7) == 0) && (((UINTN)SourceBuffer & 0x7) == 0) && (Length >= 8)) {
48 if (SourceBuffer > DestinationBuffer) {
49 Destination64 = (UINT64 *)DestinationBuffer;
50 Source64 = (CONST UINT64 *)SourceBuffer;
51 while (Length >= 8) {
52 *(Destination64++) = *(Source64++);
53 Length -= 8;
54 }
55
56 // Finish if there are still some bytes to copy
57 Destination8 = (UINT8 *)Destination64;
58 Source8 = (CONST UINT8 *)Source64;
59 while (Length-- != 0) {
60 *(Destination8++) = *(Source8++);
61 }
62 } else if (SourceBuffer < DestinationBuffer) {
63 Destination64 = (UINT64 *)((UINTN)DestinationBuffer + Length);
64 Source64 = (CONST UINT64 *)((UINTN)SourceBuffer + Length);
65
66 // Destination64 and Source64 were aligned on a 64-bit boundary
67 // but if length is not a multiple of 8 bytes then they won't be
68 // anymore.
69
70 Alignment = Length & 0x7;
71 if (Alignment != 0) {
72 Destination8 = (UINT8 *)Destination64;
73 Source8 = (CONST UINT8 *)Source64;
74
75 while (Alignment-- != 0) {
76 *(--Destination8) = *(--Source8);
77 --Length;
78 }
79
80 Destination64 = (UINT64 *)Destination8;
81 Source64 = (CONST UINT64 *)Source8;
82 }
83
84 while (Length > 0) {
85 *(--Destination64) = *(--Source64);
86 Length -= 8;
87 }
88 }
89 } else if ((((UINTN)DestinationBuffer & 0x3) == 0) && (((UINTN)SourceBuffer & 0x3) == 0) && (Length >= 4)) {
90 if (SourceBuffer > DestinationBuffer) {
91 Destination32 = (UINT32 *)DestinationBuffer;
92 Source32 = (CONST UINT32 *)SourceBuffer;
93 while (Length >= 4) {
94 *(Destination32++) = *(Source32++);
95 Length -= 4;
96 }
97
98 // Finish if there are still some bytes to copy
99 Destination8 = (UINT8 *)Destination32;
100 Source8 = (CONST UINT8 *)Source32;
101 while (Length-- != 0) {
102 *(Destination8++) = *(Source8++);
103 }
104 } else if (SourceBuffer < DestinationBuffer) {
105 Destination32 = (UINT32 *)((UINTN)DestinationBuffer + Length);
106 Source32 = (CONST UINT32 *)((UINTN)SourceBuffer + Length);
107
108 // Destination32 and Source32 were aligned on a 32-bit boundary
109 // but if length is not a multiple of 4 bytes then they won't be
110 // anymore.
111
112 Alignment = Length & 0x3;
113 if (Alignment != 0) {
114 Destination8 = (UINT8 *)Destination32;
115 Source8 = (CONST UINT8 *)Source32;
116
117 while (Alignment-- != 0) {
118 *(--Destination8) = *(--Source8);
119 --Length;
120 }
121
122 Destination32 = (UINT32 *)Destination8;
123 Source32 = (CONST UINT32 *)Source8;
124 }
125
126 while (Length > 0) {
127 *(--Destination32) = *(--Source32);
128 Length -= 4;
129 }
130 }
131 } else {
132 if (SourceBuffer > DestinationBuffer) {
133 Destination8 = (UINT8 *)DestinationBuffer;
134 Source8 = (CONST UINT8 *)SourceBuffer;
135 while (Length-- != 0) {
136 *(Destination8++) = *(Source8++);
137 }
138 } else if (SourceBuffer < DestinationBuffer) {
139 Destination8 = (UINT8 *)DestinationBuffer + (Length - 1);
140 Source8 = (CONST UINT8 *)SourceBuffer + (Length - 1);
141 while (Length-- != 0) {
142 *(Destination8--) = *(Source8--);
143 }
144 }
145 }
146
147 return DestinationBuffer;
148 }