summaryrefslogtreecommitdiffstats
path: root/include/asm-alpha/unaligned.h
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
committer <ralf@linux-mips.org>1997-01-07 02:33:00 +0000
commitbeb116954b9b7f3bb56412b2494b562f02b864b1 (patch)
tree120e997879884e1b9d93b265221b939d2ef1ade1 /include/asm-alpha/unaligned.h
parent908d4681a1dc3792ecafbe64265783a86c4cccb6 (diff)
Import of Linux/MIPS 2.1.14
Diffstat (limited to 'include/asm-alpha/unaligned.h')
-rw-r--r--include/asm-alpha/unaligned.h97
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