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