aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-avr32/unaligned.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-avr32/unaligned.h')
-rw-r--r--include/asm-avr32/unaligned.h29
1 files changed, 20 insertions, 9 deletions
diff --git a/include/asm-avr32/unaligned.h b/include/asm-avr32/unaligned.h
index 3042723fcbfd..791361786fcc 100644
--- a/include/asm-avr32/unaligned.h
+++ b/include/asm-avr32/unaligned.h
@@ -6,20 +6,31 @@
* implementation. The AVR32 AP implementation can handle unaligned
* words, but halfwords must be halfword-aligned, and doublewords must
* be word-aligned.
- *
- * TODO: Make all this CPU-specific and optimize.
*/
-#include <linux/string.h>
+#include <asm-generic/unaligned.h>
-/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
+#ifdef CONFIG_CPU_AT32AP7000
+/* REVISIT calling memmove() may be smaller for 64-bit values ... */
+
+#undef get_unaligned
#define get_unaligned(ptr) \
- ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+ ___get_unaligned(ptr, sizeof((*ptr)))
+#define ___get_unaligned(ptr, size) \
+ ((size == 4) ? *(ptr) : __get_unaligned(ptr, size))
+
+#undef put_unaligned
+#define put_unaligned(val, ptr) \
+ ___put_unaligned((__u64)(val), ptr, sizeof((*ptr)))
+#define ___put_unaligned(val, ptr, size) \
+do { \
+ if (size == 4) \
+ *(ptr) = (val); \
+ else \
+ __put_unaligned(val, ptr, size); \
+} while (0)
-#define put_unaligned(val, ptr) \
- ({ __typeof__(*(ptr)) __tmp = (val); \
- memmove((ptr), &__tmp, sizeof(*(ptr))); \
- (void)0; })
+#endif
#endif /* __ASM_AVR32_UNALIGNED_H */