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 InternalMemCopyMem(OUT VOID * DestinationBuffer,IN CONST VOID * SourceBuffer,IN UINTN Length)29InternalMemCopyMem ( 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 } 147