]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseMemoryLib/CopyMem.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
e1f414b6 14#include "MemLibInternals.h"\r
15\r
16/**\r
17 Copy Length bytes from Source to Destination.\r
18\r
15c952e7 19 @param DestinationBuffer The target of the copy request.\r
20 @param SourceBuffer The place to copy from.\r
21 @param Length The number of bytes to copy.\r
e1f414b6 22\r
23 @return Destination\r
24\r
25**/\r
26VOID *\r
27EFIAPI\r
28InternalMemCopyMem (\r
2f88bd3a
MK
29 OUT VOID *DestinationBuffer,\r
30 IN CONST VOID *SourceBuffer,\r
31 IN UINTN Length\r
e1f414b6 32 )\r
33{\r
34 //\r
35 // Declare the local variables that actually move the data elements as\r
36 // volatile to prevent the optimizer from replacing this function with\r
37 // the intrinsic memcpy()\r
38 //\r
2f88bd3a
MK
39 volatile UINT8 *Destination8;\r
40 CONST UINT8 *Source8;\r
41 volatile UINT32 *Destination32;\r
42 CONST UINT32 *Source32;\r
43 volatile UINT64 *Destination64;\r
44 CONST UINT64 *Source64;\r
45 UINTN Alignment;\r
01f688be
AB
46\r
47 if ((((UINTN)DestinationBuffer & 0x7) == 0) && (((UINTN)SourceBuffer & 0x7) == 0) && (Length >= 8)) {\r
48 if (SourceBuffer > DestinationBuffer) {\r
2f88bd3a
MK
49 Destination64 = (UINT64 *)DestinationBuffer;\r
50 Source64 = (CONST UINT64 *)SourceBuffer;\r
01f688be
AB
51 while (Length >= 8) {\r
52 *(Destination64++) = *(Source64++);\r
2f88bd3a 53 Length -= 8;\r
01f688be
AB
54 }\r
55\r
56 // Finish if there are still some bytes to copy\r
2f88bd3a
MK
57 Destination8 = (UINT8 *)Destination64;\r
58 Source8 = (CONST UINT8 *)Source64;\r
01f688be
AB
59 while (Length-- != 0) {\r
60 *(Destination8++) = *(Source8++);\r
61 }\r
62 } else if (SourceBuffer < DestinationBuffer) {\r
2f88bd3a
MK
63 Destination64 = (UINT64 *)((UINTN)DestinationBuffer + Length);\r
64 Source64 = (CONST UINT64 *)((UINTN)SourceBuffer + Length);\r
01f688be
AB
65\r
66 // Destination64 and Source64 were aligned on a 64-bit boundary\r
67 // but if length is not a multiple of 8 bytes then they won't be\r
68 // anymore.\r
69\r
70 Alignment = Length & 0x7;\r
71 if (Alignment != 0) {\r
2f88bd3a
MK
72 Destination8 = (UINT8 *)Destination64;\r
73 Source8 = (CONST UINT8 *)Source64;\r
01f688be
AB
74\r
75 while (Alignment-- != 0) {\r
76 *(--Destination8) = *(--Source8);\r
77 --Length;\r
78 }\r
2f88bd3a
MK
79\r
80 Destination64 = (UINT64 *)Destination8;\r
81 Source64 = (CONST UINT64 *)Source8;\r
01f688be
AB
82 }\r
83\r
84 while (Length > 0) {\r
85 *(--Destination64) = *(--Source64);\r
2f88bd3a 86 Length -= 8;\r
01f688be
AB
87 }\r
88 }\r
89 } else if ((((UINTN)DestinationBuffer & 0x3) == 0) && (((UINTN)SourceBuffer & 0x3) == 0) && (Length >= 4)) {\r
90 if (SourceBuffer > DestinationBuffer) {\r
2f88bd3a
MK
91 Destination32 = (UINT32 *)DestinationBuffer;\r
92 Source32 = (CONST UINT32 *)SourceBuffer;\r
01f688be
AB
93 while (Length >= 4) {\r
94 *(Destination32++) = *(Source32++);\r
2f88bd3a 95 Length -= 4;\r
01f688be
AB
96 }\r
97\r
98 // Finish if there are still some bytes to copy\r
2f88bd3a
MK
99 Destination8 = (UINT8 *)Destination32;\r
100 Source8 = (CONST UINT8 *)Source32;\r
01f688be
AB
101 while (Length-- != 0) {\r
102 *(Destination8++) = *(Source8++);\r
103 }\r
104 } else if (SourceBuffer < DestinationBuffer) {\r
2f88bd3a
MK
105 Destination32 = (UINT32 *)((UINTN)DestinationBuffer + Length);\r
106 Source32 = (CONST UINT32 *)((UINTN)SourceBuffer + Length);\r
01f688be
AB
107\r
108 // Destination32 and Source32 were aligned on a 32-bit boundary\r
109 // but if length is not a multiple of 4 bytes then they won't be\r
110 // anymore.\r
111\r
112 Alignment = Length & 0x3;\r
113 if (Alignment != 0) {\r
2f88bd3a
MK
114 Destination8 = (UINT8 *)Destination32;\r
115 Source8 = (CONST UINT8 *)Source32;\r
01f688be
AB
116\r
117 while (Alignment-- != 0) {\r
118 *(--Destination8) = *(--Source8);\r
119 --Length;\r
120 }\r
2f88bd3a
MK
121\r
122 Destination32 = (UINT32 *)Destination8;\r
123 Source32 = (CONST UINT32 *)Source8;\r
01f688be 124 }\r
e1f414b6 125\r
01f688be
AB
126 while (Length > 0) {\r
127 *(--Destination32) = *(--Source32);\r
2f88bd3a 128 Length -= 4;\r
01f688be 129 }\r
e1f414b6 130 }\r
01f688be
AB
131 } else {\r
132 if (SourceBuffer > DestinationBuffer) {\r
2f88bd3a
MK
133 Destination8 = (UINT8 *)DestinationBuffer;\r
134 Source8 = (CONST UINT8 *)SourceBuffer;\r
01f688be
AB
135 while (Length-- != 0) {\r
136 *(Destination8++) = *(Source8++);\r
137 }\r
138 } else if (SourceBuffer < DestinationBuffer) {\r
2f88bd3a
MK
139 Destination8 = (UINT8 *)DestinationBuffer + (Length - 1);\r
140 Source8 = (CONST UINT8 *)SourceBuffer + (Length - 1);\r
01f688be 141 while (Length-- != 0) {\r
5ea2bad0 142 *(Destination8--) = *(Source8--);\r
01f688be 143 }\r
e1f414b6 144 }\r
145 }\r
2f88bd3a 146\r
efb23117 147 return DestinationBuffer;\r
e1f414b6 148}\r