diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-01-07 02:33:00 +0000 |
commit | beb116954b9b7f3bb56412b2494b562f02b864b1 (patch) | |
tree | 120e997879884e1b9d93b265221b939d2ef1ade1 /include/asm-alpha/unaligned.h | |
parent | 908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff) |
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'include/asm-alpha/unaligned.h')
-rw-r--r-- | include/asm-alpha/unaligned.h | 97 |
1 files changed, 78 insertions, 19 deletions
diff --git a/include/asm-alpha/unaligned.h b/include/asm-alpha/unaligned.h index 071477496..35da3d5ae 100644 --- a/include/asm-alpha/unaligned.h +++ b/include/asm-alpha/unaligned.h @@ -1,55 +1,72 @@ #ifndef __ALPHA_UNALIGNED_H #define __ALPHA_UNALIGNED_H +/* + * 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))) + +/* + * This is a silly but good way to make sure that + * the get/put functions are indeed always optimized, + * and that we use the correct sizes. + */ +extern void bad_unaligned_access_length(void); + /* - * inline functions to do unaligned accesses.. See entUna in traps.c + * Elemental unaligned loads */ -extern inline unsigned long ldq_u(unsigned long * r11) + +extern inline unsigned long __uldq(const unsigned long * r11) { unsigned long r1,r2; __asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extql %0,%2,%0\n\t" - "extqh %1,%2,%1\n\t" - "bis %1,%0,%0" + "extqh %1,%2,%1" :"=&r" (r1), "=&r" (r2) :"r" (r11), "m" (*r11), - "m" (*(unsigned long *)(7+(char *) r11))); - return r1; + "m" (*(const unsigned long *)(7+(char *) r11))); + return r1 | r2; } -extern inline unsigned long ldl_u(unsigned int * r11) +extern inline unsigned long __uldl(const unsigned int * r11) { unsigned long r1,r2; __asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extll %0,%2,%0\n\t" - "extlh %1,%2,%1\n\t" - "bis %1,%0,%0" + "extlh %1,%2,%1" :"=&r" (r1), "=&r" (r2) :"r" (r11), "m" (*r11), - "m" (*(unsigned long *)(3+(char *) r11))); - return r1; + "m" (*(const unsigned long *)(3+(char *) r11))); + return r1 | r2; } -extern inline unsigned long ldw_u(unsigned short * r11) +extern inline unsigned long __uldw(const unsigned short * r11) { unsigned long r1,r2; __asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extwl %0,%2,%0\n\t" - "extwh %1,%2,%1\n\t" - "bis %1,%0,%0" + "extwh %1,%2,%1" :"=&r" (r1), "=&r" (r2) :"r" (r11), "m" (*r11), - "m" (*(unsigned long *)(1+(char *) r11))); - return r1; + "m" (*(const unsigned long *)(1+(char *) r11))); + return r1 | r2; } -extern inline void stq_u(unsigned long r5, unsigned long * r11) +/* + * Elemental unaligned stores + */ + +extern inline void __ustq(unsigned long r5, unsigned long * r11) { unsigned long r1,r2,r3,r4; @@ -69,7 +86,7 @@ extern inline void stq_u(unsigned long r5, unsigned long * r11) :"r" (r5), "r" (r11)); } -extern inline void stl_u(unsigned long r5, unsigned int * r11) +extern inline void __ustl(unsigned long r5, unsigned int * r11) { unsigned long r1,r2,r3,r4; @@ -89,7 +106,7 @@ extern inline void stl_u(unsigned long r5, unsigned int * r11) :"r" (r5), "r" (r11)); } -extern inline void stw_u(unsigned long r5, unsigned short * r11) +extern inline void __ustw(unsigned long r5, unsigned short * r11) { unsigned long r1,r2,r3,r4; @@ -109,4 +126,46 @@ extern inline void stw_u(unsigned long r5, unsigned short * r11) :"r" (r5), "r" (r11)); } +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 = __uldw((const unsigned short *)ptr); + break; + case 4: + val = __uldl((const unsigned int *)ptr); + break; + case 8: + val = __uldq((const unsigned long *)ptr); + break; + default: + bad_unaligned_access_length(); + } + 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: + __ustw(val, (unsigned short *)ptr); + break; + case 4: + __ustl(val, (unsigned int *)ptr); + break; + case 8: + __ustq(val, (unsigned long *)ptr); + break; + default: + bad_unaligned_access_length(); + } +} + #endif |