unaligned.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #ifndef _ASM_GENERIC_UNALIGNED_H_
  2. #define _ASM_GENERIC_UNALIGNED_H_
  3. /*
  4. * For the benefit of those who are trying to port Linux to another
  5. * architecture, here are some C-language equivalents.
  6. *
  7. * This is based almost entirely upon Richard Henderson's
  8. * asm-alpha/unaligned.h implementation. Some comments were
  9. * taken from David Mosberger's asm-ia64/unaligned.h header.
  10. */
  11. #include <linux/types.h>
  12. /*
  13. * The main single-value unaligned transfer routines.
  14. */
  15. #define get_unaligned(ptr) \
  16. __get_unaligned((ptr), sizeof(*(ptr)))
  17. #define put_unaligned(x,ptr) \
  18. __put_unaligned((__u64)(x), (ptr), sizeof(*(ptr)))
  19. /*
  20. * This function doesn't actually exist. The idea is that when
  21. * someone uses the macros below with an unsupported size (datatype),
  22. * the linker will alert us to the problem via an unresolved reference
  23. * error.
  24. */
  25. extern void bad_unaligned_access_length(void) __attribute__((noreturn));
  26. struct __una_u64 { __u64 x __attribute__((packed)); };
  27. struct __una_u32 { __u32 x __attribute__((packed)); };
  28. struct __una_u16 { __u16 x __attribute__((packed)); };
  29. /*
  30. * Elemental unaligned loads
  31. */
  32. static inline __u64 __uldq(const __u64 *addr)
  33. {
  34. const struct __una_u64 *ptr = (const struct __una_u64 *) addr;
  35. return ptr->x;
  36. }
  37. static inline __u32 __uldl(const __u32 *addr)
  38. {
  39. const struct __una_u32 *ptr = (const struct __una_u32 *) addr;
  40. return ptr->x;
  41. }
  42. static inline __u16 __uldw(const __u16 *addr)
  43. {
  44. const struct __una_u16 *ptr = (const struct __una_u16 *) addr;
  45. return ptr->x;
  46. }
  47. /*
  48. * Elemental unaligned stores
  49. */
  50. static inline void __ustq(__u64 val, __u64 *addr)
  51. {
  52. struct __una_u64 *ptr = (struct __una_u64 *) addr;
  53. ptr->x = val;
  54. }
  55. static inline void __ustl(__u32 val, __u32 *addr)
  56. {
  57. struct __una_u32 *ptr = (struct __una_u32 *) addr;
  58. ptr->x = val;
  59. }
  60. static inline void __ustw(__u16 val, __u16 *addr)
  61. {
  62. struct __una_u16 *ptr = (struct __una_u16 *) addr;
  63. ptr->x = val;
  64. }
  65. #define __get_unaligned(ptr, size) ({ \
  66. const void *__gu_p = ptr; \
  67. __u64 val; \
  68. switch (size) { \
  69. case 1: \
  70. val = *(const __u8 *)__gu_p; \
  71. break; \
  72. case 2: \
  73. val = __uldw(__gu_p); \
  74. break; \
  75. case 4: \
  76. val = __uldl(__gu_p); \
  77. break; \
  78. case 8: \
  79. val = __uldq(__gu_p); \
  80. break; \
  81. default: \
  82. bad_unaligned_access_length(); \
  83. }; \
  84. (__typeof__(*(ptr)))val; \
  85. })
  86. #define __put_unaligned(val, ptr, size) \
  87. do { \
  88. void *__gu_p = ptr; \
  89. switch (size) { \
  90. case 1: \
  91. *(__u8 *)__gu_p = val; \
  92. break; \
  93. case 2: \
  94. __ustw(val, __gu_p); \
  95. break; \
  96. case 4: \
  97. __ustl(val, __gu_p); \
  98. break; \
  99. case 8: \
  100. __ustq(val, __gu_p); \
  101. break; \
  102. default: \
  103. bad_unaligned_access_length(); \
  104. }; \
  105. } while(0)
  106. #endif /* _ASM_GENERIC_UNALIGNED_H */