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