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

嵌入式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, 2001 by Ralf Baechle
  7.  * Copyright (C) 1999, 2000, 2001 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 quad unaligned.
  15.  */
  16. extern inline unsigned long __ldq_u(const unsigned long * __addr)
  17. {
  18. unsigned long __res;
  19. __asm__("uldt%0,%1"
  20. : "=&r" (__res)
  21. : "m" (*__addr));
  22. return __res;
  23. }
  24. /*
  25.  * Load long unaligned.
  26.  */
  27. extern inline unsigned long __ldl_u(const unsigned int * __addr)
  28. {
  29. unsigned long __res;
  30. __asm__("ulwt%0,%1"
  31. : "=&r" (__res)
  32. : "m" (*__addr));
  33. return __res;
  34. }
  35. /*
  36.  * Load word unaligned.
  37.  */
  38. extern inline unsigned long __ldw_u(const unsigned short * __addr)
  39. {
  40. unsigned long __res;
  41. __asm__("ulht%0,%1"
  42. : "=&r" (__res)
  43. : "m" (*__addr));
  44. return __res;
  45. }
  46. /*
  47.  * Store quad ununaligned.
  48.  */
  49. extern inline void __stq_u(unsigned long __val, unsigned long * __addr)
  50. {
  51. __asm__("usdt%1, %0"
  52. : "=m" (*__addr)
  53. : "r" (__val));
  54. }
  55. /*
  56.  * Store long ununaligned.
  57.  */
  58. extern inline void __stl_u(unsigned long __val, unsigned int * __addr)
  59. {
  60. __asm__("uswt%1, %0"
  61. : "=m" (*__addr)
  62. : "r" (__val));
  63. }
  64. /*
  65.  * Store word ununaligned.
  66.  */
  67. extern inline void __stw_u(unsigned long __val, unsigned short * __addr)
  68. {
  69. __asm__("usht%1, %0"
  70. : "=m" (*__addr)
  71. : "r" (__val));
  72. }
  73. /*
  74.  * get_unaligned - get value from possibly mis-aligned location
  75.  * @ptr: pointer to value
  76.  *
  77.  * This macro should be used for accessing values larger in size than 
  78.  * single bytes at locations that are expected to be improperly aligned, 
  79.  * e.g. retrieving a u16 value from a location not u16-aligned.
  80.  *
  81.  * Note that unaligned accesses can be very expensive on some architectures.
  82.  */
  83. #define get_unaligned(ptr)
  84. ({
  85. __typeof__(*(ptr)) __val;
  86. switch (sizeof(*(ptr))) {
  87. case 1:
  88. __val = *(const unsigned char *)(ptr);
  89. break;
  90. case 2:
  91. __val = __ldw_u((const unsigned short *)(ptr));
  92. break;
  93. case 4:
  94. __val = __ldl_u((const unsigned int *)(ptr));
  95. break;
  96. case 8:
  97. __val = __ldq_u((const unsigned long *)(ptr));
  98. break;
  99. default:
  100. __get_unaligned_bad_length();
  101. break;
  102. }
  103. __val;
  104. })
  105. /*
  106.  * put_unaligned - put value to a possibly mis-aligned location
  107.  * @val: value to place
  108.  * @ptr: pointer to location
  109.  *
  110.  * This macro should be used for placing values larger in size than 
  111.  * single bytes at locations that are expected to be improperly aligned, 
  112.  * e.g. writing a u16 value to a location not u16-aligned.
  113.  *
  114.  * Note that unaligned accesses can be very expensive on some architectures.
  115.  */
  116. #define put_unaligned(val,ptr)
  117. do {
  118. switch (sizeof(*(ptr))) {
  119. case 1:
  120. *(unsigned char *)(ptr) = (val);
  121. break;
  122. case 2:
  123. __stw_u((val), (unsigned short *)(ptr));
  124. break;
  125. case 4:
  126. __stl_u((val), (unsigned int *)(ptr));
  127. break;
  128. case 8:
  129. __stq_u((val), (unsigned long long *)(ptr));
  130. break;
  131. default:
  132. __put_unaligned_bad_length();
  133. break;
  134. }
  135. } while(0)
  136. #endif /* _ASM_UNALIGNED_H */