0001
0002 #ifndef __ASM_ARM_WORD_AT_A_TIME_H
0003 #define __ASM_ARM_WORD_AT_A_TIME_H
0004
0005 #ifndef __ARMEB__
0006
0007
0008
0009
0010
0011 #include <linux/kernel.h>
0012
0013 struct word_at_a_time {
0014 const unsigned long one_bits, high_bits;
0015 };
0016
0017 #define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
0018
0019 static inline unsigned long has_zero(unsigned long a, unsigned long *bits,
0020 const struct word_at_a_time *c)
0021 {
0022 unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits;
0023 *bits = mask;
0024 return mask;
0025 }
0026
0027 #define prep_zero_mask(a, bits, c) (bits)
0028
0029 static inline unsigned long create_zero_mask(unsigned long bits)
0030 {
0031 bits = (bits - 1) & ~bits;
0032 return bits >> 7;
0033 }
0034
0035 static inline unsigned long find_zero(unsigned long mask)
0036 {
0037 unsigned long ret;
0038
0039 #if __LINUX_ARM_ARCH__ >= 5
0040
0041 ret = fls(mask) >> 3;
0042 #else
0043
0044 ret = (0x0ff0001 + mask) >> 23;
0045
0046 ret &= mask;
0047 #endif
0048
0049 return ret;
0050 }
0051
0052 #define zero_bytemask(mask) (mask)
0053
0054 #else
0055 #include <asm-generic/word-at-a-time.h>
0056 #endif
0057
0058 #ifdef CONFIG_DCACHE_WORD_ACCESS
0059
0060
0061
0062
0063
0064
0065
0066
0067 static inline unsigned long load_unaligned_zeropad(const void *addr)
0068 {
0069 unsigned long ret, offset;
0070
0071
0072 asm(
0073 "1: ldr %0, [%2]\n"
0074 "2:\n"
0075 " .pushsection .text.fixup,\"ax\"\n"
0076 " .align 2\n"
0077 "3: and %1, %2, #0x3\n"
0078 " bic %2, %2, #0x3\n"
0079 " ldr %0, [%2]\n"
0080 " lsl %1, %1, #0x3\n"
0081 #ifndef __ARMEB__
0082 " lsr %0, %0, %1\n"
0083 #else
0084 " lsl %0, %0, %1\n"
0085 #endif
0086 " b 2b\n"
0087 " .popsection\n"
0088 " .pushsection __ex_table,\"a\"\n"
0089 " .align 3\n"
0090 " .long 1b, 3b\n"
0091 " .popsection"
0092 : "=&r" (ret), "=&r" (offset)
0093 : "r" (addr), "Qo" (*(unsigned long *)addr));
0094
0095 return ret;
0096 }
0097
0098 #endif
0099 #endif