1 /** @file 2 Unaligned access functions of BaseLib for ARM. 3 4 volatile was added to work around optimization issues. 5 6 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> 7 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> 8 This program and the accompanying materials 9 are licensed and made available under the terms and conditions of the BSD License 10 which accompanies this distribution. The full text of the license may be found at 11 http://opensource.org/licenses/bsd-license.php. 12 13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 15 16 **/ 17 18 #include "BaseLibInternals.h" 19 20 /** 21 Reads a 16-bit value from memory that may be unaligned. 22 23 This function returns the 16-bit value pointed to by Buffer. The function 24 guarantees that the read operation does not produce an alignment fault. 25 26 If the Buffer is NULL, then ASSERT(). 27 28 @param Buffer The pointer to a 16-bit value that may be unaligned. 29 30 @return The 16-bit value read from Buffer. 31 32 **/ 33 UINT16 34 EFIAPI 35 ReadUnaligned16 ( 36 IN CONST UINT16 *Buffer 37 ) 38 { 39 volatile UINT8 LowerByte; 40 volatile UINT8 HigherByte; 41 42 ASSERT (Buffer != NULL); 43 44 LowerByte = ((UINT8*)Buffer)[0]; 45 HigherByte = ((UINT8*)Buffer)[1]; 46 47 return (UINT16)(LowerByte | (HigherByte << 8)); 48 } 49 50 /** 51 Writes a 16-bit value to memory that may be unaligned. 52 53 This function writes the 16-bit value specified by Value to Buffer. Value is 54 returned. The function guarantees that the write operation does not produce 55 an alignment fault. 56 57 If the Buffer is NULL, then ASSERT(). 58 59 @param Buffer The pointer to a 16-bit value that may be unaligned. 60 @param Value 16-bit value to write to Buffer. 61 62 @return The 16-bit value to write to Buffer. 63 64 **/ 65 UINT16 66 EFIAPI 67 WriteUnaligned16 ( 68 OUT UINT16 *Buffer, 69 IN UINT16 Value 70 ) 71 { 72 ASSERT (Buffer != NULL); 73 74 ((volatile UINT8*)Buffer)[0] = (UINT8)Value; 75 ((volatile UINT8*)Buffer)[1] = (UINT8)(Value >> 8); 76 77 return Value; 78 } 79 80 /** 81 Reads a 24-bit value from memory that may be unaligned. 82 83 This function returns the 24-bit value pointed to by Buffer. The function 84 guarantees that the read operation does not produce an alignment fault. 85 86 If the Buffer is NULL, then ASSERT(). 87 88 @param Buffer The pointer to a 24-bit value that may be unaligned. 89 90 @return The 24-bit value read from Buffer. 91 92 **/ 93 UINT32 94 EFIAPI 95 ReadUnaligned24 ( 96 IN CONST UINT32 *Buffer 97 ) 98 { 99 ASSERT (Buffer != NULL); 100 101 return (UINT32)( 102 ReadUnaligned16 ((UINT16*)Buffer) | 103 (((UINT8*)Buffer)[2] << 16) 104 ); 105 } 106 107 /** 108 Writes a 24-bit value to memory that may be unaligned. 109 110 This function writes the 24-bit value specified by Value to Buffer. Value is 111 returned. The function guarantees that the write operation does not produce 112 an alignment fault. 113 114 If the Buffer is NULL, then ASSERT(). 115 116 @param Buffer The pointer to a 24-bit value that may be unaligned. 117 @param Value 24-bit value to write to Buffer. 118 119 @return The 24-bit value to write to Buffer. 120 121 **/ 122 UINT32 123 EFIAPI 124 WriteUnaligned24 ( 125 OUT UINT32 *Buffer, 126 IN UINT32 Value 127 ) 128 { 129 ASSERT (Buffer != NULL); 130 131 WriteUnaligned16 ((UINT16*)Buffer, (UINT16)Value); 132 *(UINT8*)((UINT16*)Buffer + 1) = (UINT8)(Value >> 16); 133 return Value; 134 } 135 136 /** 137 Reads a 32-bit value from memory that may be unaligned. 138 139 This function returns the 32-bit value pointed to by Buffer. The function 140 guarantees that the read operation does not produce an alignment fault. 141 142 If the Buffer is NULL, then ASSERT(). 143 144 @param Buffer The pointer to a 32-bit value that may be unaligned. 145 146 @return The 32-bit value read from Buffer. 147 148 **/ 149 UINT32 150 EFIAPI 151 ReadUnaligned32 ( 152 IN CONST UINT32 *Buffer 153 ) 154 { 155 UINT16 LowerBytes; 156 UINT16 HigherBytes; 157 158 ASSERT (Buffer != NULL); 159 160 LowerBytes = ReadUnaligned16 ((UINT16*) Buffer); 161 HigherBytes = ReadUnaligned16 ((UINT16*) Buffer + 1); 162 163 return (UINT32) (LowerBytes | (HigherBytes << 16)); 164 } 165 166 /** 167 Writes a 32-bit value to memory that may be unaligned. 168 169 This function writes the 32-bit value specified by Value to Buffer. Value is 170 returned. The function guarantees that the write operation does not produce 171 an alignment fault. 172 173 If the Buffer is NULL, then ASSERT(). 174 175 @param Buffer The pointer to a 32-bit value that may be unaligned. 176 @param Value 32-bit value to write to Buffer. 177 178 @return The 32-bit value to write to Buffer. 179 180 **/ 181 UINT32 182 EFIAPI 183 WriteUnaligned32 ( 184 OUT UINT32 *Buffer, 185 IN UINT32 Value 186 ) 187 { 188 ASSERT (Buffer != NULL); 189 190 WriteUnaligned16 ((UINT16*)Buffer, (UINT16)Value); 191 WriteUnaligned16 ((UINT16*)Buffer + 1, (UINT16)(Value >> 16)); 192 return Value; 193 } 194 195 /** 196 Reads a 64-bit value from memory that may be unaligned. 197 198 This function returns the 64-bit value pointed to by Buffer. The function 199 guarantees that the read operation does not produce an alignment fault. 200 201 If the Buffer is NULL, then ASSERT(). 202 203 @param Buffer The pointer to a 64-bit value that may be unaligned. 204 205 @return The 64-bit value read from Buffer. 206 207 **/ 208 UINT64 209 EFIAPI 210 ReadUnaligned64 ( 211 IN CONST UINT64 *Buffer 212 ) 213 { 214 UINT32 LowerBytes; 215 UINT32 HigherBytes; 216 217 ASSERT (Buffer != NULL); 218 219 LowerBytes = ReadUnaligned32 ((UINT32*) Buffer); 220 HigherBytes = ReadUnaligned32 ((UINT32*) Buffer + 1); 221 222 return (UINT64) (LowerBytes | LShiftU64 (HigherBytes, 32)); 223 } 224 225 /** 226 Writes a 64-bit value to memory that may be unaligned. 227 228 This function writes the 64-bit value specified by Value to Buffer. Value is 229 returned. The function guarantees that the write operation does not produce 230 an alignment fault. 231 232 If the Buffer is NULL, then ASSERT(). 233 234 @param Buffer The pointer to a 64-bit value that may be unaligned. 235 @param Value 64-bit value to write to Buffer. 236 237 @return The 64-bit value to write to Buffer. 238 239 **/ 240 UINT64 241 EFIAPI 242 WriteUnaligned64 ( 243 OUT UINT64 *Buffer, 244 IN UINT64 Value 245 ) 246 { 247 ASSERT (Buffer != NULL); 248 249 WriteUnaligned32 ((UINT32*)Buffer, (UINT32)Value); 250 WriteUnaligned32 ((UINT32*)Buffer + 1, (UINT32)RShiftU64 (Value, 32)); 251 return Value; 252 } 253