unaligned.h
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:4k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * Copyright (C) 1996, 1999, 2000 by Ralf Baechle
  7.  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  8.  */
  9. #ifndef _ASM_UNALIGNED_H
  10. #define _ASM_UNALIGNED_H
  11. extern void __get_unaligned_bad_length(void);
  12. extern void __put_unaligned_bad_length(void);
  13. /*
  14.  * Load double unaligned.
  15.  *
  16.  * This could have been implemented in plain C like IA64 but egcs 1.0.3a
  17.  * inflates this to 23 instructions ...
  18.  */
  19. extern inline unsigned long long __ldq_u(const unsigned long long * __addr)
  20. {
  21. unsigned long long __res;
  22. __asm__("ulwt%0, %1nt"
  23. "ulwt%D0, 4+%1"
  24. : "=&r" (__res)
  25. : "m" (*__addr));
  26. return __res;
  27. }
  28. /*
  29.  * Load word unaligned.
  30.  */
  31. extern inline unsigned long __ldl_u(const unsigned int * __addr)
  32. {
  33. unsigned long __res;
  34. __asm__("ulwt%0,%1"
  35. : "=&r" (__res)
  36. : "m" (*__addr));
  37. return __res;
  38. }
  39. /*
  40.  * Load halfword unaligned.
  41.  */
  42. extern inline unsigned long __ldw_u(const unsigned short * __addr)
  43. {
  44. unsigned long __res;
  45. __asm__("ulht%0,%1"
  46. : "=&r" (__res)
  47. : "m" (*__addr));
  48. return __res;
  49. }
  50. /*
  51.  * Store doubleword ununaligned.
  52.  */
  53. extern inline void __stq_u(unsigned long __val, unsigned long long * __addr)
  54. {
  55. __asm__("uswt%1, %0nt"
  56. "uswt%D1, 4+%0"
  57. : "=m" (*__addr)
  58. : "r" (__val));
  59. }
  60. /*
  61.  * Store long ununaligned.
  62.  */
  63. extern inline void __stl_u(unsigned long __val, unsigned int * __addr)
  64. {
  65. __asm__("uswt%1, %0"
  66. : "=m" (*__addr)
  67. : "r" (__val));
  68. }
  69. /*
  70.  * Store word ununaligned.
  71.  */
  72. extern inline void __stw_u(unsigned long __val, unsigned short * __addr)
  73. {
  74. __asm__("usht%1, %0"
  75. : "=m" (*__addr)
  76. : "r" (__val));
  77. }
  78. /*
  79.  * get_unaligned - get value from possibly mis-aligned location
  80.  * @ptr: pointer to value
  81.  *
  82.  * This macro should be used for accessing values larger in size than 
  83.  * single bytes at locations that are expected to be improperly aligned, 
  84.  * e.g. retrieving a u16 value from a location not u16-aligned.
  85.  *
  86.  * Note that unaligned accesses can be very expensive on some architectures.
  87.  */
  88. #define get_unaligned(ptr)
  89. ({
  90. __typeof__(*(ptr)) __val;
  91. switch (sizeof(*(ptr))) {
  92. case 1:
  93. __val = *(const unsigned char *)ptr;
  94. break;
  95. case 2:
  96. __val = __ldw_u((const unsigned short *)ptr);
  97. break;
  98. case 4:
  99. __val = __ldl_u((const unsigned int *)ptr);
  100. break;
  101. case 8:
  102. __val = __ldq_u((const unsigned long long *)ptr);
  103. break;
  104. default:
  105. __get_unaligned_bad_length();
  106. break;
  107. }
  108. __val;
  109. })
  110. /*
  111.  * put_unaligned - put value to a possibly mis-aligned location
  112.  * @val: value to place
  113.  * @ptr: pointer to location
  114.  *
  115.  * This macro should be used for placing values larger in size than 
  116.  * single bytes at locations that are expected to be improperly aligned, 
  117.  * e.g. writing a u16 value to a location not u16-aligned.
  118.  *
  119.  * Note that unaligned accesses can be very expensive on some architectures.
  120.  */
  121. #define put_unaligned(val,ptr)
  122. do {
  123. switch (sizeof(*(ptr))) {
  124. case 1:
  125. *(unsigned char *)(ptr) = (val);
  126. break;
  127. case 2:
  128. __stw_u(val, (unsigned short *)(ptr));
  129. break;
  130. case 4:
  131. __stl_u(val, (unsigned int *)(ptr));
  132. break;
  133. case 8:
  134. __stq_u(val, (unsigned long long *)(ptr));
  135. break;
  136. default:
  137. __put_unaligned_bad_length();
  138. break;
  139. }
  140. } while(0)
  141. #endif /* _ASM_UNALIGNED_H */