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
ReadUnaligned16(IN CONST UINT16 * Buffer)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
WriteUnaligned16(OUT UINT16 * Buffer,IN UINT16 Value)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
ReadUnaligned24(IN CONST UINT32 * Buffer)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
WriteUnaligned24(OUT UINT32 * Buffer,IN UINT32 Value)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
ReadUnaligned32(IN CONST UINT32 * Buffer)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
WriteUnaligned32(OUT UINT32 * Buffer,IN UINT32 Value)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
ReadUnaligned64(IN CONST UINT64 * Buffer)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
WriteUnaligned64(OUT UINT64 * Buffer,IN UINT64 Value)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