NCBI C++ ToolKit
alignment.h
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /**
2  * \file alignment.h
3  *
4  * \brief Utility code for dealing with unaligned memory accesses
5  */
6 /*
7  * Copyright The Mbed TLS Contributors
8  * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
9  */
10 
11 #ifndef MBEDTLS_LIBRARY_ALIGNMENT_H
12 #define MBEDTLS_LIBRARY_ALIGNMENT_H
13 
14 #include <stdint.h>
15 #include <string.h>
16 #include <stdlib.h>
17 
18 /*
19  * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory
20  * accesses are known to be efficient.
21  *
22  * All functions defined here will behave correctly regardless, but might be less
23  * efficient when this is not defined.
24  */
25 #if defined(__ARM_FEATURE_UNALIGNED) \
26  || defined(MBEDTLS_ARCH_IS_X86) || defined(MBEDTLS_ARCH_IS_X64) \
27  || defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
28 /*
29  * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9
30  * (and later versions) for Arm v7 and later; all x86 platforms should have
31  * efficient unaligned access.
32  *
33  * https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment
34  * specifies that on Windows-on-Arm64, unaligned access is safe (except for uncached
35  * device memory).
36  */
37 #define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS
38 #endif
39 
40 #if defined(__IAR_SYSTEMS_ICC__) && \
41  (defined(MBEDTLS_ARCH_IS_ARM64) || defined(MBEDTLS_ARCH_IS_ARM32) \
42  || defined(__ICCRX__) || defined(__ICCRL78__) || defined(__ICCRISCV__))
43 #pragma language=save
44 #pragma language=extended
45 #define MBEDTLS_POP_IAR_LANGUAGE_PRAGMA
46 /* IAR recommend this technique for accessing unaligned data in
47  * https://www.iar.com/knowledge/support/technical-notes/compiler/accessing-unaligned-data
48  * This results in a single load / store instruction (if unaligned access is supported).
49  * According to that document, this is only supported on certain architectures.
50  */
51  #define UINT_UNALIGNED
52 typedef uint16_t __packed mbedtls_uint16_unaligned_t;
53 typedef uint32_t __packed mbedtls_uint32_unaligned_t;
54 typedef uint64_t __packed mbedtls_uint64_unaligned_t;
55 #elif defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 40504) && \
56  ((MBEDTLS_GCC_VERSION < 60300) || (!defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)))
57 /*
58  * gcc may generate a branch to memcpy for calls like `memcpy(dest, src, 4)` rather than
59  * generating some LDR or LDRB instructions (similar for stores).
60  *
61  * This is architecture dependent: x86-64 seems fine even with old gcc; 32-bit Arm
62  * is affected. To keep it simple, we enable for all architectures.
63  *
64  * For versions of gcc < 5.4.0 this issue always happens.
65  * For gcc < 6.3.0, this issue happens at -O0
66  * For all versions, this issue happens iff unaligned access is not supported.
67  *
68  * For gcc 4.x, this implementation will generate byte-by-byte loads even if unaligned access is
69  * supported, which is correct but not optimal.
70  *
71  * For performance (and code size, in some cases), we want to avoid the branch and just generate
72  * some inline load/store instructions since the access is small and constant-size.
73  *
74  * The manual states:
75  * "The packed attribute specifies that a variable or structure field should have the smallest
76  * possible alignment—one byte for a variable"
77  * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Variable-Attributes.html
78  *
79  * Previous implementations used __attribute__((__aligned__(1)), but had issues with a gcc bug:
80  * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94662
81  *
82  * Tested with several versions of GCC from 4.5.0 up to 13.2.0
83  * We don't enable for older than 4.5.0 as this has not been tested.
84  */
85  #define UINT_UNALIGNED_STRUCT
86 typedef struct {
87  uint16_t x;
88 } __attribute__((packed)) mbedtls_uint16_unaligned_t;
89 typedef struct {
90  uint32_t x;
91 } __attribute__((packed)) mbedtls_uint32_unaligned_t;
92 typedef struct {
93  uint64_t x;
94 } __attribute__((packed)) mbedtls_uint64_unaligned_t;
95  #endif
96 
97 /*
98  * We try to force mbedtls_(get|put)_unaligned_uintXX to be always inline, because this results
99  * in code that is both smaller and faster. IAR and gcc both benefit from this when optimising
100  * for size.
101  */
102 
103 /**
104  * Read the unsigned 16 bits integer from the given address, which need not
105  * be aligned.
106  *
107  * \param p pointer to 2 bytes of data
108  * \return Data at the given address
109  */
110 #if defined(__IAR_SYSTEMS_ICC__)
111 #pragma inline = forced
112 #elif defined(__GNUC__)
113 __attribute__((always_inline))
114 #endif
115 static inline uint16_t mbedtls_get_unaligned_uint16(const void *p)
116 {
117  uint16_t r;
118 #if defined(UINT_UNALIGNED)
119  mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
120  r = *p16;
121 #elif defined(UINT_UNALIGNED_STRUCT)
122  mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
123  r = p16->x;
124 #else
125  memcpy(&r, p, sizeof(r));
126 #endif
127  return r;
128 }
129 
130 /**
131  * Write the unsigned 16 bits integer to the given address, which need not
132  * be aligned.
133  *
134  * \param p pointer to 2 bytes of data
135  * \param x data to write
136  */
137 #if defined(__IAR_SYSTEMS_ICC__)
138 #pragma inline = forced
139 #elif defined(__GNUC__)
140 __attribute__((always_inline))
141 #endif
142 static inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x)
143 {
144 #if defined(UINT_UNALIGNED)
145  mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
146  *p16 = x;
147 #elif defined(UINT_UNALIGNED_STRUCT)
148  mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
149  p16->x = x;
150 #else
151  memcpy(p, &x, sizeof(x));
152 #endif
153 }
154 
155 /**
156  * Read the unsigned 32 bits integer from the given address, which need not
157  * be aligned.
158  *
159  * \param p pointer to 4 bytes of data
160  * \return Data at the given address
161  */
162 #if defined(__IAR_SYSTEMS_ICC__)
163 #pragma inline = forced
164 #elif defined(__GNUC__)
165 __attribute__((always_inline))
166 #endif
167 static inline uint32_t mbedtls_get_unaligned_uint32(const void *p)
168 {
169  uint32_t r;
170 #if defined(UINT_UNALIGNED)
171  mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
172  r = *p32;
173 #elif defined(UINT_UNALIGNED_STRUCT)
174  mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
175  r = p32->x;
176 #else
177  memcpy(&r, p, sizeof(r));
178 #endif
179  return r;
180 }
181 
182 /**
183  * Write the unsigned 32 bits integer to the given address, which need not
184  * be aligned.
185  *
186  * \param p pointer to 4 bytes of data
187  * \param x data to write
188  */
189 #if defined(__IAR_SYSTEMS_ICC__)
190 #pragma inline = forced
191 #elif defined(__GNUC__)
192 __attribute__((always_inline))
193 #endif
194 static inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
195 {
196 #if defined(UINT_UNALIGNED)
197  mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
198  *p32 = x;
199 #elif defined(UINT_UNALIGNED_STRUCT)
200  mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
201  p32->x = x;
202 #else
203  memcpy(p, &x, sizeof(x));
204 #endif
205 }
206 
207 /**
208  * Read the unsigned 64 bits integer from the given address, which need not
209  * be aligned.
210  *
211  * \param p pointer to 8 bytes of data
212  * \return Data at the given address
213  */
214 #if defined(__IAR_SYSTEMS_ICC__)
215 #pragma inline = forced
216 #elif defined(__GNUC__)
217 __attribute__((always_inline))
218 #endif
219 static inline uint64_t mbedtls_get_unaligned_uint64(const void *p)
220 {
221  uint64_t r;
222 #if defined(UINT_UNALIGNED)
223  mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
224  r = *p64;
225 #elif defined(UINT_UNALIGNED_STRUCT)
226  mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
227  r = p64->x;
228 #else
229  memcpy(&r, p, sizeof(r));
230 #endif
231  return r;
232 }
233 
234 /**
235  * Write the unsigned 64 bits integer to the given address, which need not
236  * be aligned.
237  *
238  * \param p pointer to 8 bytes of data
239  * \param x data to write
240  */
241 #if defined(__IAR_SYSTEMS_ICC__)
242 #pragma inline = forced
243 #elif defined(__GNUC__)
244 __attribute__((always_inline))
245 #endif
246 static inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x)
247 {
248 #if defined(UINT_UNALIGNED)
249  mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
250  *p64 = x;
251 #elif defined(UINT_UNALIGNED_STRUCT)
252  mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
253  p64->x = x;
254 #else
255  memcpy(p, &x, sizeof(x));
256 #endif
257 }
258 
259 #if defined(MBEDTLS_POP_IAR_LANGUAGE_PRAGMA)
260 #pragma language=restore
261 #endif
262 
263 /** Byte Reading Macros
264  *
265  * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
266  * byte from x, where byte 0 is the least significant byte.
267  */
268 #define MBEDTLS_BYTE_0(x) ((uint8_t) ((x) & 0xff))
269 #define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >> 8) & 0xff))
270 #define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff))
271 #define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff))
272 #define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff))
273 #define MBEDTLS_BYTE_5(x) ((uint8_t) (((x) >> 40) & 0xff))
274 #define MBEDTLS_BYTE_6(x) ((uint8_t) (((x) >> 48) & 0xff))
275 #define MBEDTLS_BYTE_7(x) ((uint8_t) (((x) >> 56) & 0xff))
276 
277 /*
278  * Detect GCC built-in byteswap routines
279  */
280 #if defined(__GNUC__) && defined(__GNUC_PREREQ)
281 #if __GNUC_PREREQ(4, 8)
282 #define MBEDTLS_BSWAP16 __builtin_bswap16
283 #endif /* __GNUC_PREREQ(4,8) */
284 #if __GNUC_PREREQ(4, 3)
285 #define MBEDTLS_BSWAP32 __builtin_bswap32
286 #define MBEDTLS_BSWAP64 __builtin_bswap64
287 #endif /* __GNUC_PREREQ(4,3) */
288 #endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */
289 
290 /*
291  * Detect Clang built-in byteswap routines
292  */
293 #if defined(__clang__) && defined(__has_builtin)
294 #if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16)
295 #define MBEDTLS_BSWAP16 __builtin_bswap16
296 #endif /* __has_builtin(__builtin_bswap16) */
297 #if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32)
298 #define MBEDTLS_BSWAP32 __builtin_bswap32
299 #endif /* __has_builtin(__builtin_bswap32) */
300 #if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64)
301 #define MBEDTLS_BSWAP64 __builtin_bswap64
302 #endif /* __has_builtin(__builtin_bswap64) */
303 #endif /* defined(__clang__) && defined(__has_builtin) */
304 
305 /*
306  * Detect MSVC built-in byteswap routines
307  */
308 #if defined(_MSC_VER)
309 #if !defined(MBEDTLS_BSWAP16)
310 #define MBEDTLS_BSWAP16 _byteswap_ushort
311 #endif
312 #if !defined(MBEDTLS_BSWAP32)
313 #define MBEDTLS_BSWAP32 _byteswap_ulong
314 #endif
315 #if !defined(MBEDTLS_BSWAP64)
316 #define MBEDTLS_BSWAP64 _byteswap_uint64
317 #endif
318 #endif /* defined(_MSC_VER) */
319 
320 /* Detect armcc built-in byteswap routine */
321 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32)
322 #if defined(__ARM_ACLE) /* ARM Compiler 6 - earlier versions don't need a header */
323 #include <arm_acle.h>
324 #endif
325 #define MBEDTLS_BSWAP32 __rev
326 #endif
327 
328 /* Detect IAR built-in byteswap routine */
329 #if defined(__IAR_SYSTEMS_ICC__)
330 #if defined(__ARM_ACLE)
331 #include <arm_acle.h>
332 #define MBEDTLS_BSWAP16(x) ((uint16_t) __rev16((uint32_t) (x)))
333 #define MBEDTLS_BSWAP32 __rev
334 #define MBEDTLS_BSWAP64 __revll
335 #endif
336 #endif
337 
338 /*
339  * Where compiler built-ins are not present, fall back to C code that the
340  * compiler may be able to detect and transform into the relevant bswap or
341  * similar instruction.
342  */
343 #if !defined(MBEDTLS_BSWAP16)
345 {
346  return
347  (x & 0x00ff) << 8 |
348  (x & 0xff00) >> 8;
349 }
350 #define MBEDTLS_BSWAP16 mbedtls_bswap16
351 #endif /* !defined(MBEDTLS_BSWAP16) */
352 
353 #if !defined(MBEDTLS_BSWAP32)
355 {
356  return
357  (x & 0x000000ff) << 24 |
358  (x & 0x0000ff00) << 8 |
359  (x & 0x00ff0000) >> 8 |
360  (x & 0xff000000) >> 24;
361 }
362 #define MBEDTLS_BSWAP32 mbedtls_bswap32
363 #endif /* !defined(MBEDTLS_BSWAP32) */
364 
365 #if !defined(MBEDTLS_BSWAP64)
367 {
368  return
369  (x & 0x00000000000000ffULL) << 56 |
370  (x & 0x000000000000ff00ULL) << 40 |
371  (x & 0x0000000000ff0000ULL) << 24 |
372  (x & 0x00000000ff000000ULL) << 8 |
373  (x & 0x000000ff00000000ULL) >> 8 |
374  (x & 0x0000ff0000000000ULL) >> 24 |
375  (x & 0x00ff000000000000ULL) >> 40 |
376  (x & 0xff00000000000000ULL) >> 56;
377 }
378 #define MBEDTLS_BSWAP64 mbedtls_bswap64
379 #endif /* !defined(MBEDTLS_BSWAP64) */
380 
381 #if !defined(__BYTE_ORDER__)
382 
383 #if defined(__LITTLE_ENDIAN__)
384 /* IAR defines __xxx_ENDIAN__, but not __BYTE_ORDER__ */
385 #define MBEDTLS_IS_BIG_ENDIAN 0
386 #elif defined(__BIG_ENDIAN__)
387 #define MBEDTLS_IS_BIG_ENDIAN 1
388 #else
389 static const uint16_t mbedtls_byte_order_detector = { 0x100 };
390 #define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01)
391 #endif
392 
393 #else
394 
395 #if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__)
396 #define MBEDTLS_IS_BIG_ENDIAN 1
397 #else
398 #define MBEDTLS_IS_BIG_ENDIAN 0
399 #endif
400 
401 #endif /* !defined(__BYTE_ORDER__) */
402 
403 /**
404  * Get the unsigned 32 bits integer corresponding to four bytes in
405  * big-endian order (MSB first).
406  *
407  * \param data Base address of the memory to get the four bytes from.
408  * \param offset Offset from \p data of the first and most significant
409  * byte of the four bytes to build the 32 bits unsigned
410  * integer from.
411  */
412 #define MBEDTLS_GET_UINT32_BE(data, offset) \
413  ((MBEDTLS_IS_BIG_ENDIAN) \
414  ? mbedtls_get_unaligned_uint32((data) + (offset)) \
415  : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
416  )
417 
418 /**
419  * Put in memory a 32 bits unsigned integer in big-endian order.
420  *
421  * \param n 32 bits unsigned integer to put in memory.
422  * \param data Base address of the memory where to put the 32
423  * bits unsigned integer in.
424  * \param offset Offset from \p data where to put the most significant
425  * byte of the 32 bits unsigned integer \p n.
426  */
427 #define MBEDTLS_PUT_UINT32_BE(n, data, offset) \
428  { \
429  if (MBEDTLS_IS_BIG_ENDIAN) \
430  { \
431  mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \
432  } \
433  else \
434  { \
435  mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
436  } \
437  }
438 
439 /**
440  * Get the unsigned 32 bits integer corresponding to four bytes in
441  * little-endian order (LSB first).
442  *
443  * \param data Base address of the memory to get the four bytes from.
444  * \param offset Offset from \p data of the first and least significant
445  * byte of the four bytes to build the 32 bits unsigned
446  * integer from.
447  */
448 #define MBEDTLS_GET_UINT32_LE(data, offset) \
449  ((MBEDTLS_IS_BIG_ENDIAN) \
450  ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
451  : mbedtls_get_unaligned_uint32((data) + (offset)) \
452  )
453 
454 
455 /**
456  * Put in memory a 32 bits unsigned integer in little-endian order.
457  *
458  * \param n 32 bits unsigned integer to put in memory.
459  * \param data Base address of the memory where to put the 32
460  * bits unsigned integer in.
461  * \param offset Offset from \p data where to put the least significant
462  * byte of the 32 bits unsigned integer \p n.
463  */
464 #define MBEDTLS_PUT_UINT32_LE(n, data, offset) \
465  { \
466  if (MBEDTLS_IS_BIG_ENDIAN) \
467  { \
468  mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
469  } \
470  else \
471  { \
472  mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n))); \
473  } \
474  }
475 
476 /**
477  * Get the unsigned 16 bits integer corresponding to two bytes in
478  * little-endian order (LSB first).
479  *
480  * \param data Base address of the memory to get the two bytes from.
481  * \param offset Offset from \p data of the first and least significant
482  * byte of the two bytes to build the 16 bits unsigned
483  * integer from.
484  */
485 #define MBEDTLS_GET_UINT16_LE(data, offset) \
486  ((MBEDTLS_IS_BIG_ENDIAN) \
487  ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
488  : mbedtls_get_unaligned_uint16((data) + (offset)) \
489  )
490 
491 /**
492  * Put in memory a 16 bits unsigned integer in little-endian order.
493  *
494  * \param n 16 bits unsigned integer to put in memory.
495  * \param data Base address of the memory where to put the 16
496  * bits unsigned integer in.
497  * \param offset Offset from \p data where to put the least significant
498  * byte of the 16 bits unsigned integer \p n.
499  */
500 #define MBEDTLS_PUT_UINT16_LE(n, data, offset) \
501  { \
502  if (MBEDTLS_IS_BIG_ENDIAN) \
503  { \
504  mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
505  } \
506  else \
507  { \
508  mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \
509  } \
510  }
511 
512 /**
513  * Get the unsigned 16 bits integer corresponding to two bytes in
514  * big-endian order (MSB first).
515  *
516  * \param data Base address of the memory to get the two bytes from.
517  * \param offset Offset from \p data of the first and most significant
518  * byte of the two bytes to build the 16 bits unsigned
519  * integer from.
520  */
521 #define MBEDTLS_GET_UINT16_BE(data, offset) \
522  ((MBEDTLS_IS_BIG_ENDIAN) \
523  ? mbedtls_get_unaligned_uint16((data) + (offset)) \
524  : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
525  )
526 
527 /**
528  * Put in memory a 16 bits unsigned integer in big-endian order.
529  *
530  * \param n 16 bits unsigned integer to put in memory.
531  * \param data Base address of the memory where to put the 16
532  * bits unsigned integer in.
533  * \param offset Offset from \p data where to put the most significant
534  * byte of the 16 bits unsigned integer \p n.
535  */
536 #define MBEDTLS_PUT_UINT16_BE(n, data, offset) \
537  { \
538  if (MBEDTLS_IS_BIG_ENDIAN) \
539  { \
540  mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \
541  } \
542  else \
543  { \
544  mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
545  } \
546  }
547 
548 /**
549  * Get the unsigned 24 bits integer corresponding to three bytes in
550  * big-endian order (MSB first).
551  *
552  * \param data Base address of the memory to get the three bytes from.
553  * \param offset Offset from \p data of the first and most significant
554  * byte of the three bytes to build the 24 bits unsigned
555  * integer from.
556  */
557 #define MBEDTLS_GET_UINT24_BE(data, offset) \
558  ( \
559  ((uint32_t) (data)[(offset)] << 16) \
560  | ((uint32_t) (data)[(offset) + 1] << 8) \
561  | ((uint32_t) (data)[(offset) + 2]) \
562  )
563 
564 /**
565  * Put in memory a 24 bits unsigned integer in big-endian order.
566  *
567  * \param n 24 bits unsigned integer to put in memory.
568  * \param data Base address of the memory where to put the 24
569  * bits unsigned integer in.
570  * \param offset Offset from \p data where to put the most significant
571  * byte of the 24 bits unsigned integer \p n.
572  */
573 #define MBEDTLS_PUT_UINT24_BE(n, data, offset) \
574  { \
575  (data)[(offset)] = MBEDTLS_BYTE_2(n); \
576  (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \
577  (data)[(offset) + 2] = MBEDTLS_BYTE_0(n); \
578  }
579 
580 /**
581  * Get the unsigned 24 bits integer corresponding to three bytes in
582  * little-endian order (LSB first).
583  *
584  * \param data Base address of the memory to get the three bytes from.
585  * \param offset Offset from \p data of the first and least significant
586  * byte of the three bytes to build the 24 bits unsigned
587  * integer from.
588  */
589 #define MBEDTLS_GET_UINT24_LE(data, offset) \
590  ( \
591  ((uint32_t) (data)[(offset)]) \
592  | ((uint32_t) (data)[(offset) + 1] << 8) \
593  | ((uint32_t) (data)[(offset) + 2] << 16) \
594  )
595 
596 /**
597  * Put in memory a 24 bits unsigned integer in little-endian order.
598  *
599  * \param n 24 bits unsigned integer to put in memory.
600  * \param data Base address of the memory where to put the 24
601  * bits unsigned integer in.
602  * \param offset Offset from \p data where to put the least significant
603  * byte of the 24 bits unsigned integer \p n.
604  */
605 #define MBEDTLS_PUT_UINT24_LE(n, data, offset) \
606  { \
607  (data)[(offset)] = MBEDTLS_BYTE_0(n); \
608  (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \
609  (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \
610  }
611 
612 /**
613  * Get the unsigned 64 bits integer corresponding to eight bytes in
614  * big-endian order (MSB first).
615  *
616  * \param data Base address of the memory to get the eight bytes from.
617  * \param offset Offset from \p data of the first and most significant
618  * byte of the eight bytes to build the 64 bits unsigned
619  * integer from.
620  */
621 #define MBEDTLS_GET_UINT64_BE(data, offset) \
622  ((MBEDTLS_IS_BIG_ENDIAN) \
623  ? mbedtls_get_unaligned_uint64((data) + (offset)) \
624  : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
625  )
626 
627 /**
628  * Put in memory a 64 bits unsigned integer in big-endian order.
629  *
630  * \param n 64 bits unsigned integer to put in memory.
631  * \param data Base address of the memory where to put the 64
632  * bits unsigned integer in.
633  * \param offset Offset from \p data where to put the most significant
634  * byte of the 64 bits unsigned integer \p n.
635  */
636 #define MBEDTLS_PUT_UINT64_BE(n, data, offset) \
637  { \
638  if (MBEDTLS_IS_BIG_ENDIAN) \
639  { \
640  mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \
641  } \
642  else \
643  { \
644  mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
645  } \
646  }
647 
648 /**
649  * Get the unsigned 64 bits integer corresponding to eight bytes in
650  * little-endian order (LSB first).
651  *
652  * \param data Base address of the memory to get the eight bytes from.
653  * \param offset Offset from \p data of the first and least significant
654  * byte of the eight bytes to build the 64 bits unsigned
655  * integer from.
656  */
657 #define MBEDTLS_GET_UINT64_LE(data, offset) \
658  ((MBEDTLS_IS_BIG_ENDIAN) \
659  ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
660  : mbedtls_get_unaligned_uint64((data) + (offset)) \
661  )
662 
663 /**
664  * Put in memory a 64 bits unsigned integer in little-endian order.
665  *
666  * \param n 64 bits unsigned integer to put in memory.
667  * \param data Base address of the memory where to put the 64
668  * bits unsigned integer in.
669  * \param offset Offset from \p data where to put the least significant
670  * byte of the 64 bits unsigned integer \p n.
671  */
672 #define MBEDTLS_PUT_UINT64_LE(n, data, offset) \
673  { \
674  if (MBEDTLS_IS_BIG_ENDIAN) \
675  { \
676  mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
677  } \
678  else \
679  { \
680  mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \
681  } \
682  }
683 
684 #endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */
static void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
Write the unsigned 32 bits integer to the given address, which need not be aligned.
Definition: alignment.h:194
static uint64_t mbedtls_get_unaligned_uint64(const void *p)
Read the unsigned 64 bits integer from the given address, which need not be aligned.
Definition: alignment.h:219
static const uint16_t mbedtls_byte_order_detector
Definition: alignment.h:389
static uint32_t mbedtls_get_unaligned_uint32(const void *p)
Read the unsigned 32 bits integer from the given address, which need not be aligned.
Definition: alignment.h:167
static void mbedtls_put_unaligned_uint64(void *p, uint64_t x)
Write the unsigned 64 bits integer to the given address, which need not be aligned.
Definition: alignment.h:246
static uint16_t mbedtls_bswap16(uint16_t x)
Definition: alignment.h:344
static void mbedtls_put_unaligned_uint16(void *p, uint16_t x)
Write the unsigned 16 bits integer to the given address, which need not be aligned.
Definition: alignment.h:142
static uint32_t mbedtls_bswap32(uint32_t x)
Definition: alignment.h:354
static uint16_t mbedtls_get_unaligned_uint16(const void *p)
Read the unsigned 16 bits integer from the given address, which need not be aligned.
Definition: alignment.h:115
static uint64_t mbedtls_bswap64(uint64_t x)
Definition: alignment.h:366
Uint8 uint64_t
Uint2 uint16_t
Uint4 uint32_t
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
Modified on Thu Jul 18 16:08:43 2024 by modify_doxy.py rev. 669887