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