home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-v850 / unaligned.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  3.4 KB  |  131 lines

  1. /*
  2.  * include/asm-v850/unaligned.h -- Unaligned memory access
  3.  *
  4.  *  Copyright (C) 2001  NEC Corporation
  5.  *  Copyright (C) 2001  Miles Bader <miles@gnu.org>
  6.  *
  7.  * This file is subject to the terms and conditions of the GNU General
  8.  * Public License.  See the file COPYING in the main directory of this
  9.  * archive for more details.
  10.  *
  11.  * This file is a copy of the arm version, include/asm-arm/unaligned.h
  12.  *
  13.  * Note that some v850 chips support unaligned access, but it seems too
  14.  * annoying to use.
  15.  */
  16.  
  17. #ifndef __V850_UNALIGNED_H__
  18. #define __V850_UNALIGNED_H__
  19.  
  20. #include <asm/types.h>
  21.  
  22. extern int __bug_unaligned_x(void *ptr);
  23.  
  24. /*
  25.  * What is the most efficient way of loading/storing an unaligned value?
  26.  *
  27.  * That is the subject of this file.  Efficiency here is defined as
  28.  * minimum code size with minimum register usage for the common cases.
  29.  * It is currently not believed that long longs are common, so we
  30.  * trade efficiency for the chars, shorts and longs against the long
  31.  * longs.
  32.  *
  33.  * Current stats with gcc 2.7.2.2 for these functions:
  34.  *
  35.  *    ptrsize    get:    code    regs    put:    code    regs
  36.  *    1        1    1        1    2
  37.  *    2        3    2        3    2
  38.  *    4        7    3        7    3
  39.  *    8        20    6        16    6
  40.  *
  41.  * gcc 2.95.1 seems to code differently:
  42.  *
  43.  *    ptrsize    get:    code    regs    put:    code    regs
  44.  *    1        1    1        1    2
  45.  *    2        3    2        3    2
  46.  *    4        7    4        7    4
  47.  *    8        19    8        15    6
  48.  *
  49.  * which may or may not be more efficient (depending upon whether
  50.  * you can afford the extra registers).  Hopefully the gcc 2.95
  51.  * is inteligent enough to decide if it is better to use the
  52.  * extra register, but evidence so far seems to suggest otherwise.
  53.  *
  54.  * Unfortunately, gcc is not able to optimise the high word
  55.  * out of long long >> 32, or the low word from long long << 32
  56.  */
  57.  
  58. #define __get_unaligned_2(__p)                    \
  59.     (__p[0] | __p[1] << 8)
  60.  
  61. #define __get_unaligned_4(__p)                    \
  62.     (__p[0] | __p[1] << 8 | __p[2] << 16 | __p[3] << 24)
  63.  
  64. #define get_unaligned(ptr)                    \
  65.     ({                            \
  66.         __typeof__(*(ptr)) __v;                \
  67.         __u8 *__p = (__u8 *)(ptr);            \
  68.         switch (sizeof(*(ptr))) {            \
  69.         case 1:    __v = *(ptr);            break;    \
  70.         case 2: __v = __get_unaligned_2(__p);    break;    \
  71.         case 4: __v = __get_unaligned_4(__p);    break;    \
  72.         case 8: {                    \
  73.                 unsigned int __v1, __v2;    \
  74.                 __v2 = __get_unaligned_4((__p+4)); \
  75.                 __v1 = __get_unaligned_4(__p);    \
  76.                 __v = ((unsigned long long)__v2 << 32 | __v1);    \
  77.             }                    \
  78.             break;                    \
  79.         default: __v = __bug_unaligned_x(__p);    break;    \
  80.         }                        \
  81.         __v;                        \
  82.     })
  83.  
  84.  
  85. static inline void __put_unaligned_2(__u32 __v, register __u8 *__p)
  86. {
  87.     *__p++ = __v;
  88.     *__p++ = __v >> 8;
  89. }
  90.  
  91. static inline void __put_unaligned_4(__u32 __v, register __u8 *__p)
  92. {
  93.     __put_unaligned_2(__v >> 16, __p + 2);
  94.     __put_unaligned_2(__v, __p);
  95. }
  96.  
  97. static inline void __put_unaligned_8(const unsigned long long __v, register __u8 *__p)
  98. {
  99.     /*
  100.      * tradeoff: 8 bytes of stack for all unaligned puts (2
  101.      * instructions), or an extra register in the long long
  102.      * case - go for the extra register.
  103.      */
  104.     __put_unaligned_4(__v >> 32, __p+4);
  105.     __put_unaligned_4(__v, __p);
  106. }
  107.  
  108. /*
  109.  * Try to store an unaligned value as efficiently as possible.
  110.  */
  111. #define put_unaligned(val,ptr)                    \
  112.     ({                            \
  113.         switch (sizeof(*(ptr))) {            \
  114.         case 1:                        \
  115.             *(ptr) = (val);                \
  116.             break;                    \
  117.         case 2: __put_unaligned_2((val),(__u8 *)(ptr));    \
  118.             break;                    \
  119.         case 4:    __put_unaligned_4((val),(__u8 *)(ptr));    \
  120.             break;                    \
  121.         case 8:    __put_unaligned_8((val),(__u8 *)(ptr)); \
  122.             break;                    \
  123.         default: __bug_unaligned_x(ptr);        \
  124.             break;                    \
  125.         }                        \
  126.         (void) 0;                    \
  127.     })
  128.  
  129.  
  130. #endif /* __V850_UNALIGNED_H__ */
  131.