diff options
author | Mark Salter <msalter@redhat.com> | 1997-09-01 20:29:30 +0000 |
---|---|---|
committer | Mark Salter <msalter@redhat.com> | 1997-09-01 20:29:30 +0000 |
commit | bb56ec72b6ca0a744d7746c02d553f3fdd799f0f (patch) | |
tree | 1c57d74ac93eb8470dd171c81469e939afda9c80 /include | |
parent | ca6a48c886feeb26fde786c6d6782703bf42e93f (diff) |
Fixed unaligned access macros. gcc's builtin memcpy won't work.
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-mips/unaligned.h | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/include/asm-mips/unaligned.h b/include/asm-mips/unaligned.h index ff7803316..8a68d5b98 100644 --- a/include/asm-mips/unaligned.h +++ b/include/asm-mips/unaligned.h @@ -15,7 +15,7 @@ /* * Load quad unaligned. */ -extern __inline__ unsigned long ldq_u(unsigned long long * __addr) +extern __inline__ unsigned long ldq_u(const unsigned long long * __addr) { unsigned long long __res; @@ -29,7 +29,7 @@ extern __inline__ unsigned long ldq_u(unsigned long long * __addr) /* * Load long unaligned. */ -extern __inline__ unsigned long ldl_u(unsigned int * __addr) +extern __inline__ unsigned long ldl_u(const unsigned int * __addr) { unsigned long __res; @@ -43,7 +43,7 @@ extern __inline__ unsigned long ldl_u(unsigned int * __addr) /* * Load word unaligned. */ -extern __inline__ unsigned long ldw_u(unsigned short * __addr) +extern __inline__ unsigned long ldw_u(const unsigned short * __addr) { unsigned long __res; @@ -90,12 +90,50 @@ extern __inline__ void stw_u(unsigned long __val, unsigned short * __addr) "r" (__addr)); } -#define get_unaligned(ptr) \ - ({ __typeof__(*(ptr)) __tmp; memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) +extern inline unsigned long __get_unaligned(const void *ptr, size_t size) +{ + unsigned long val; + switch (size) { + case 1: + val = *(const unsigned char *)ptr; + break; + case 2: + val = ldw_u((const unsigned short *)ptr); + break; + case 4: + val = ldl_u((const unsigned int *)ptr); + break; + case 8: + val = ldq_u((const unsigned long long *)ptr); + break; + } + return val; +} + +extern inline void __put_unaligned(unsigned long val, void *ptr, size_t size) +{ + switch (size) { + case 1: + *(unsigned char *)ptr = (val); + break; + case 2: + stw_u(val, (unsigned short *)ptr); + break; + case 4: + stl_u(val, (unsigned int *)ptr); + break; + case 8: + stq_u(val, (unsigned long long *)ptr); + break; + } +} -#define put_unaligned(val, ptr) \ - ({ __typeof__(*(ptr)) __tmp = (val); \ - memcpy((ptr), &__tmp, sizeof(*(ptr))); \ - (void)0; }) +/* + * The main single-value unaligned transfer routines. + */ +#define get_unaligned(ptr) \ + ((__typeof__(*(ptr)))__get_unaligned((ptr), sizeof(*(ptr)))) +#define put_unaligned(x,ptr) \ + __put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr))) #endif /* __ASM_MIPS_UNALIGNED_H */ |