]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/BaseMemoryLibStm/AArch64/CopyMem.c
71ae02a03e73d150fc0bb326810fc908c6cfc9be
[mirror_edk2.git] / ArmPkg / Library / BaseMemoryLibStm / AArch64 / CopyMem.c
1 /** @file
2
3 Copyright (c) 2012-2013, ARM Ltd. All rights reserved.<BR>
4
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "MemLibInternals.h"
16
17 /**
18 Copy Length bytes from Source to Destination.
19
20 @param DestinationBuffer Target of copy
21 @param SourceBuffer Place to copy from
22 @param Length Number of bytes to copy
23
24 @return Destination
25
26 **/
27 VOID *
28 EFIAPI
29 InternalMemCopyMem (
30 OUT VOID *DestinationBuffer,
31 IN CONST VOID *SourceBuffer,
32 IN UINTN Length
33 )
34 {
35 //
36 // Declare the local variables that actually move the data elements as
37 // volatile to prevent the optimizer from replacing this function with
38 // the intrinsic memcpy()
39 //
40 volatile UINT8 *Destination8;
41 CONST UINT8 *Source8;
42 volatile UINT32 *Destination32;
43 CONST UINT32 *Source32;
44 volatile UINT64 *Destination64;
45 CONST UINT64 *Source64;
46 UINTN Alignment;
47
48 if ((((UINTN)DestinationBuffer & 0x7) == 0) && (((UINTN)SourceBuffer & 0x7) == 0) && (Length >= 8)) {
49 if (SourceBuffer > DestinationBuffer) {
50 Destination64 = (UINT64*)DestinationBuffer;
51 Source64 = (CONST UINT64*)SourceBuffer;
52 while (Length >= 8) {
53 *(Destination64++) = *(Source64++);
54 Length -= 8;
55 }
56
57 // Finish if there are still some bytes to copy
58 Destination8 = (UINT8*)Destination64;
59 Source8 = (CONST UINT8*)Source64;
60 while (Length-- != 0) {
61 *(Destination8++) = *(Source8++);
62 }
63 } else if (SourceBuffer < DestinationBuffer) {
64 Destination64 = (UINT64*)((UINTN)DestinationBuffer + Length);
65 Source64 = (CONST UINT64*)((UINTN)SourceBuffer + Length);
66
67 // Destination64 and Source64 were aligned on a 64-bit boundary
68 // but if length is not a multiple of 8 bytes then they won't be
69 // anymore.
70
71 Alignment = Length & 0x7;
72 if (Alignment != 0) {
73 Destination8 = (UINT8*)Destination64;
74 Source8 = (CONST UINT8*)Source64;
75
76 while (Alignment-- != 0) {
77 *(--Destination8) = *(--Source8);
78 --Length;
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 Destination32 = (UINT32*)Destination8;
122 Source32 = (CONST UINT32*)Source8;
123 }
124
125 while (Length > 0) {
126 *(--Destination32) = *(--Source32);
127 Length -= 4;
128 }
129 }
130 } else {
131 if (SourceBuffer > DestinationBuffer) {
132 Destination8 = (UINT8*)DestinationBuffer;
133 Source8 = (CONST UINT8*)SourceBuffer;
134 while (Length-- != 0) {
135 *(Destination8++) = *(Source8++);
136 }
137 } else if (SourceBuffer < DestinationBuffer) {
138 Destination8 = (UINT8*)DestinationBuffer + Length;
139 Source8 = (CONST UINT8*)SourceBuffer + Length;
140 while (Length-- != 0) {
141 *(--Destination8) = *(--Source8);
142 }
143 }
144 }
145 return DestinationBuffer;
146 }