aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuanXuetao <gxt@mprc.pku.edu.cn>2011-01-15 05:23:09 -0500
committerGuanXuetao <gxt@mprc.pku.edu.cn>2011-03-16 21:19:13 -0400
commit96cf5185a95e0b304596fe19edcf8dfcd5c10699 (patch)
treeaebdf44fdfa8841577171df18cb1b0745b54d64e
parent77c93b2f2388b974253af4149aa025b4751f92ad (diff)
unicore32 additional architecture files: low-level lib: misc
This patch implements the rest low-level libraries. Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn> Acked-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--arch/unicore32/include/asm/assembler.h131
-rw-r--r--arch/unicore32/include/asm/bitops.h47
-rw-r--r--arch/unicore32/include/asm/checksum.h41
-rw-r--r--arch/unicore32/include/asm/delay.h52
-rw-r--r--arch/unicore32/include/asm/futex.h143
-rw-r--r--arch/unicore32/include/asm/io.h52
-rw-r--r--arch/unicore32/include/asm/mutex.h20
-rw-r--r--arch/unicore32/lib/Makefile27
-rw-r--r--arch/unicore32/lib/delay.S51
-rw-r--r--arch/unicore32/lib/findbit.S98
10 files changed, 662 insertions, 0 deletions
diff --git a/arch/unicore32/include/asm/assembler.h b/arch/unicore32/include/asm/assembler.h
new file mode 100644
index 000000000000..8e87ed7faeba
--- /dev/null
+++ b/arch/unicore32/include/asm/assembler.h
@@ -0,0 +1,131 @@
1/*
2 * linux/arch/unicore32/include/asm/assembler.h
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * Do not include any C declarations in this file - it is included by
13 * assembler source.
14 */
15#ifndef __ASSEMBLY__
16#error "Only include this from assembly code"
17#endif
18
19#include <asm/ptrace.h>
20
21/*
22 * Little Endian independent macros for shifting bytes within registers.
23 */
24#define pull >>
25#define push <<
26#define get_byte_0 << #0
27#define get_byte_1 >> #8
28#define get_byte_2 >> #16
29#define get_byte_3 >> #24
30#define put_byte_0 << #0
31#define put_byte_1 << #8
32#define put_byte_2 << #16
33#define put_byte_3 << #24
34
35#define cadd cmpadd
36#define cand cmpand
37#define csub cmpsub
38#define cxor cmpxor
39
40/*
41 * Enable and disable interrupts
42 */
43 .macro disable_irq, temp
44 mov \temp, asr
45 andn \temp, \temp, #0xFF
46 or \temp, \temp, #PSR_I_BIT | PRIV_MODE
47 mov.a asr, \temp
48 .endm
49
50 .macro enable_irq, temp
51 mov \temp, asr
52 andn \temp, \temp, #0xFF
53 or \temp, \temp, #PRIV_MODE
54 mov.a asr, \temp
55 .endm
56
57#define USER(x...) \
589999: x; \
59 .pushsection __ex_table, "a"; \
60 .align 3; \
61 .long 9999b, 9001f; \
62 .popsection
63
64 .macro notcond, cond, nexti = .+8
65 .ifc \cond, eq
66 bne \nexti
67 .else; .ifc \cond, ne
68 beq \nexti
69 .else; .ifc \cond, ea
70 bub \nexti
71 .else; .ifc \cond, ub
72 bea \nexti
73 .else; .ifc \cond, fs
74 bns \nexti
75 .else; .ifc \cond, ns
76 bfs \nexti
77 .else; .ifc \cond, fv
78 bnv \nexti
79 .else; .ifc \cond, nv
80 bfv \nexti
81 .else; .ifc \cond, ua
82 beb \nexti
83 .else; .ifc \cond, eb
84 bua \nexti
85 .else; .ifc \cond, eg
86 bsl \nexti
87 .else; .ifc \cond, sl
88 beg \nexti
89 .else; .ifc \cond, sg
90 bel \nexti
91 .else; .ifc \cond, el
92 bsg \nexti
93 .else; .ifnc \cond, al
94 .error "Unknown cond in notcond macro argument"
95 .endif; .endif; .endif; .endif; .endif; .endif; .endif
96 .endif; .endif; .endif; .endif; .endif; .endif; .endif
97 .endif
98 .endm
99
100 .macro usracc, instr, reg, ptr, inc, cond, rept, abort
101 .rept \rept
102 notcond \cond, .+8
1039999 :
104 .if \inc == 1
105 \instr\()b.u \reg, [\ptr], #\inc
106 .elseif \inc == 4
107 \instr\()w.u \reg, [\ptr], #\inc
108 .else
109 .error "Unsupported inc macro argument"
110 .endif
111
112 .pushsection __ex_table, "a"
113 .align 3
114 .long 9999b, \abort
115 .popsection
116 .endr
117 .endm
118
119 .macro strusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f
120 usracc st, \reg, \ptr, \inc, \cond, \rept, \abort
121 .endm
122
123 .macro ldrusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f
124 usracc ld, \reg, \ptr, \inc, \cond, \rept, \abort
125 .endm
126
127 .macro nop8
128 .rept 8
129 nop
130 .endr
131 .endm
diff --git a/arch/unicore32/include/asm/bitops.h b/arch/unicore32/include/asm/bitops.h
new file mode 100644
index 000000000000..1628a6328994
--- /dev/null
+++ b/arch/unicore32/include/asm/bitops.h
@@ -0,0 +1,47 @@
1/*
2 * linux/arch/unicore32/include/asm/bitops.h
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __UNICORE_BITOPS_H__
14#define __UNICORE_BITOPS_H__
15
16#define find_next_bit __uc32_find_next_bit
17#define find_next_zero_bit __uc32_find_next_zero_bit
18
19#define find_first_bit __uc32_find_first_bit
20#define find_first_zero_bit __uc32_find_first_zero_bit
21
22#define _ASM_GENERIC_BITOPS_FLS_H_
23#define _ASM_GENERIC_BITOPS___FLS_H_
24#define _ASM_GENERIC_BITOPS_FFS_H_
25#define _ASM_GENERIC_BITOPS___FFS_H_
26/*
27 * On UNICORE, those functions can be implemented around
28 * the cntlz instruction for much better code efficiency.
29 */
30
31static inline int fls(int x)
32{
33 int ret;
34
35 asm("cntlz\t%0, %1" : "=r" (ret) : "r" (x) : "cc");
36 ret = 32 - ret;
37
38 return ret;
39}
40
41#define __fls(x) (fls(x) - 1)
42#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
43#define __ffs(x) (ffs(x) - 1)
44
45#include <asm-generic/bitops.h>
46
47#endif /* __UNICORE_BITOPS_H__ */
diff --git a/arch/unicore32/include/asm/checksum.h b/arch/unicore32/include/asm/checksum.h
new file mode 100644
index 000000000000..f55c3f937c3e
--- /dev/null
+++ b/arch/unicore32/include/asm/checksum.h
@@ -0,0 +1,41 @@
1/*
2 * linux/arch/unicore32/include/asm/checksum.h
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * IP checksum routines
13 */
14#ifndef __UNICORE_CHECKSUM_H__
15#define __UNICORE_CHECKSUM_H__
16
17/*
18 * computes the checksum of the TCP/UDP pseudo-header
19 * returns a 16-bit checksum, already complemented
20 */
21
22static inline __wsum
23csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
24 unsigned short proto, __wsum sum)
25{
26 __asm__(
27 "add.a %0, %1, %2\n"
28 "addc.a %0, %0, %3\n"
29 "addc.a %0, %0, %4 << #8\n"
30 "addc.a %0, %0, %5\n"
31 "addc %0, %0, #0\n"
32 : "=&r"(sum)
33 : "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto))
34 : "cc");
35 return sum;
36}
37#define csum_tcpudp_nofold csum_tcpudp_nofold
38
39#include <asm-generic/checksum.h>
40
41#endif
diff --git a/arch/unicore32/include/asm/delay.h b/arch/unicore32/include/asm/delay.h
new file mode 100644
index 000000000000..164ae61cd6f7
--- /dev/null
+++ b/arch/unicore32/include/asm/delay.h
@@ -0,0 +1,52 @@
1/*
2 * linux/arch/unicore32/include/asm/delay.h
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * Delay routines, using a pre-computed "loops_per_second" value.
13 */
14#ifndef __UNICORE_DELAY_H__
15#define __UNICORE_DELAY_H__
16
17#include <asm/param.h> /* HZ */
18
19extern void __delay(int loops);
20
21/*
22 * This function intentionally does not exist; if you see references to
23 * it, it means that you're calling udelay() with an out of range value.
24 *
25 * With currently imposed limits, this means that we support a max delay
26 * of 2000us. Further limits: HZ<=1000 and bogomips<=3355
27 */
28extern void __bad_udelay(void);
29
30/*
31 * division by multiplication: you don't have to worry about
32 * loss of precision.
33 *
34 * Use only for very small delays ( < 1 msec). Should probably use a
35 * lookup table, really, as the multiplications take much too long with
36 * short delays. This is a "reasonable" implementation, though (and the
37 * first constant multiplications gets optimized away if the delay is
38 * a constant)
39 */
40extern void __udelay(unsigned long usecs);
41extern void __const_udelay(unsigned long);
42
43#define MAX_UDELAY_MS 2
44
45#define udelay(n) \
46 (__builtin_constant_p(n) ? \
47 ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() : \
48 __const_udelay((n) * ((2199023U*HZ)>>11))) : \
49 __udelay(n))
50
51#endif /* __UNICORE_DELAY_H__ */
52
diff --git a/arch/unicore32/include/asm/futex.h b/arch/unicore32/include/asm/futex.h
new file mode 100644
index 000000000000..07dea6170558
--- /dev/null
+++ b/arch/unicore32/include/asm/futex.h
@@ -0,0 +1,143 @@
1/*
2 * linux/arch/unicore32/include/asm/futex.h
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __UNICORE_FUTEX_H__
14#define __UNICORE_FUTEX_H__
15
16#ifdef __KERNEL__
17
18#include <linux/futex.h>
19#include <linux/preempt.h>
20#include <linux/uaccess.h>
21#include <linux/errno.h>
22
23#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
24 __asm__ __volatile__( \
25 "1: ldw.u %1, [%2]\n" \
26 " " insn "\n" \
27 "2: stw.u %0, [%2]\n" \
28 " mov %0, #0\n" \
29 "3:\n" \
30 " .pushsection __ex_table,\"a\"\n" \
31 " .align 3\n" \
32 " .long 1b, 4f, 2b, 4f\n" \
33 " .popsection\n" \
34 " .pushsection .fixup,\"ax\"\n" \
35 "4: mov %0, %4\n" \
36 " b 3b\n" \
37 " .popsection" \
38 : "=&r" (ret), "=&r" (oldval) \
39 : "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \
40 : "cc", "memory")
41
42static inline int
43futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
44{
45 int op = (encoded_op >> 28) & 7;
46 int cmp = (encoded_op >> 24) & 15;
47 int oparg = (encoded_op << 8) >> 20;
48 int cmparg = (encoded_op << 20) >> 20;
49 int oldval = 0, ret;
50
51 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
52 oparg = 1 << oparg;
53
54 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
55 return -EFAULT;
56
57 pagefault_disable(); /* implies preempt_disable() */
58
59 switch (op) {
60 case FUTEX_OP_SET:
61 __futex_atomic_op("mov %0, %3", ret, oldval, uaddr, oparg);
62 break;
63 case FUTEX_OP_ADD:
64 __futex_atomic_op("add %0, %1, %3", ret, oldval, uaddr, oparg);
65 break;
66 case FUTEX_OP_OR:
67 __futex_atomic_op("or %0, %1, %3", ret, oldval, uaddr, oparg);
68 break;
69 case FUTEX_OP_ANDN:
70 __futex_atomic_op("and %0, %1, %3",
71 ret, oldval, uaddr, ~oparg);
72 break;
73 case FUTEX_OP_XOR:
74 __futex_atomic_op("xor %0, %1, %3", ret, oldval, uaddr, oparg);
75 break;
76 default:
77 ret = -ENOSYS;
78 }
79
80 pagefault_enable(); /* subsumes preempt_enable() */
81
82 if (!ret) {
83 switch (cmp) {
84 case FUTEX_OP_CMP_EQ:
85 ret = (oldval == cmparg);
86 break;
87 case FUTEX_OP_CMP_NE:
88 ret = (oldval != cmparg);
89 break;
90 case FUTEX_OP_CMP_LT:
91 ret = (oldval < cmparg);
92 break;
93 case FUTEX_OP_CMP_GE:
94 ret = (oldval >= cmparg);
95 break;
96 case FUTEX_OP_CMP_LE:
97 ret = (oldval <= cmparg);
98 break;
99 case FUTEX_OP_CMP_GT:
100 ret = (oldval > cmparg);
101 break;
102 default:
103 ret = -ENOSYS;
104 }
105 }
106 return ret;
107}
108
109static inline int
110futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
111{
112 int val;
113
114 if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
115 return -EFAULT;
116
117 pagefault_disable(); /* implies preempt_disable() */
118
119 __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
120 "1: ldw.u %0, [%3]\n"
121 " cmpxor.a %0, %1\n"
122 " bne 3f\n"
123 "2: stw.u %2, [%3]\n"
124 "3:\n"
125 " .pushsection __ex_table,\"a\"\n"
126 " .align 3\n"
127 " .long 1b, 4f, 2b, 4f\n"
128 " .popsection\n"
129 " .pushsection .fixup,\"ax\"\n"
130 "4: mov %0, %4\n"
131 " b 3b\n"
132 " .popsection"
133 : "=&r" (val)
134 : "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
135 : "cc", "memory");
136
137 pagefault_enable(); /* subsumes preempt_enable() */
138
139 return val;
140}
141
142#endif /* __KERNEL__ */
143#endif /* __UNICORE_FUTEX_H__ */
diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h
new file mode 100644
index 000000000000..d73457c1800a
--- /dev/null
+++ b/arch/unicore32/include/asm/io.h
@@ -0,0 +1,52 @@
1/*
2 * linux/arch/unicore32/include/asm/io.h
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#ifndef __UNICORE_IO_H__
13#define __UNICORE_IO_H__
14
15#ifdef __KERNEL__
16
17#include <asm/byteorder.h>
18#include <asm/memory.h>
19#include <asm/system.h>
20
21#include <asm-generic/io.h>
22
23/*
24 * __uc32_ioremap and __uc32_ioremap_cached takes CPU physical address.
25 */
26extern void __iomem *__uc32_ioremap(unsigned long, size_t);
27extern void __iomem *__uc32_ioremap_cached(unsigned long, size_t);
28extern void __uc32_iounmap(volatile void __iomem *addr);
29
30/*
31 * ioremap and friends.
32 *
33 * ioremap takes a PCI memory address, as specified in
34 * Documentation/IO-mapping.txt.
35 *
36 */
37#define ioremap(cookie, size) __uc32_ioremap(cookie, size)
38#define ioremap_cached(cookie, size) __uc32_ioremap_cached(cookie, size)
39#define iounmap(cookie) __uc32_iounmap(cookie)
40
41extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
42extern void ioport_unmap(void __iomem *addr);
43
44/*
45 * Convert a physical pointer to a virtual kernel pointer for /dev/mem
46 * access
47 */
48#undef xlate_dev_mem_ptr
49#define xlate_dev_mem_ptr(p) __va(p)
50
51#endif /* __KERNEL__ */
52#endif /* __UNICORE_IO_H__ */
diff --git a/arch/unicore32/include/asm/mutex.h b/arch/unicore32/include/asm/mutex.h
new file mode 100644
index 000000000000..fab7d0e8adf6
--- /dev/null
+++ b/arch/unicore32/include/asm/mutex.h
@@ -0,0 +1,20 @@
1/*
2 * linux/arch/unicore32/include/asm/mutex.h
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * UniCore optimized mutex locking primitives
13 *
14 * Please look into asm-generic/mutex-xchg.h for a formal definition.
15 */
16#ifndef __UNICORE_MUTEX_H__
17#define __UNICORE_MUTEX_H__
18
19# include <asm-generic/mutex-xchg.h>
20#endif
diff --git a/arch/unicore32/lib/Makefile b/arch/unicore32/lib/Makefile
new file mode 100644
index 000000000000..87229a558b36
--- /dev/null
+++ b/arch/unicore32/lib/Makefile
@@ -0,0 +1,27 @@
1#
2# linux/arch/unicore32/lib/Makefile
3#
4# Copyright (C) 2001-2010 GUAN Xue-tao
5#
6
7lib-y := backtrace.o delay.o findbit.o
8lib-y += strncpy_from_user.o strnlen_user.o
9lib-y += clear_user.o copy_page.o
10lib-y += copy_from_user.o copy_to_user.o
11
12GNU_LIBC_A := $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libc.a)
13GNU_LIBC_A_OBJS := memchr.o memcpy.o memmove.o memset.o
14GNU_LIBC_A_OBJS += strchr.o strrchr.o
15GNU_LIBC_A_OBJS += rawmemchr.o # needed by strrchr.o
16
17GNU_LIBGCC_A := $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libgcc.a)
18GNU_LIBGCC_A_OBJS := _ashldi3.o _ashrdi3.o _lshrdi3.o
19GNU_LIBGCC_A_OBJS += _divsi3.o _modsi3.o _ucmpdi2.o _umodsi3.o _udivsi3.o
20
21lib-y += $(GNU_LIBC_A_OBJS) $(GNU_LIBGCC_A_OBJS)
22
23$(addprefix $(obj)/, $(GNU_LIBC_A_OBJS)):
24 $(Q)$(AR) p $(GNU_LIBC_A) $(notdir $@) > $@
25
26$(addprefix $(obj)/, $(GNU_LIBGCC_A_OBJS)):
27 $(Q)$(AR) p $(GNU_LIBGCC_A) $(notdir $@) > $@
diff --git a/arch/unicore32/lib/delay.S b/arch/unicore32/lib/delay.S
new file mode 100644
index 000000000000..24664c009e78
--- /dev/null
+++ b/arch/unicore32/lib/delay.S
@@ -0,0 +1,51 @@
1/*
2 * linux/arch/unicore32/lib/delay.S
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14#include <asm/param.h>
15 .text
16
17.LC0: .word loops_per_jiffy
18.LC1: .word (2199023*HZ)>>11
19
20/*
21 * r0 <= 2000
22 * lpj <= 0x01ffffff (max. 3355 bogomips)
23 * HZ <= 1000
24 */
25
26ENTRY(__udelay)
27 ldw r2, .LC1
28 mul r0, r2, r0
29ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06
30 ldw r2, .LC0
31 ldw r2, [r2] @ max = 0x01ffffff
32 mov r0, r0 >> #14 @ max = 0x0001ffff
33 mov r2, r2 >> #10 @ max = 0x00007fff
34 mul r0, r2, r0 @ max = 2^32-1
35 mov.a r0, r0 >> #6
36 cmoveq pc, lr
37
38/*
39 * loops = r0 * HZ * loops_per_jiffy / 1000000
40 *
41 * Oh, if only we had a cycle counter...
42 */
43
44@ Delay routine
45ENTRY(__delay)
46 sub.a r0, r0, #2
47 bua __delay
48 mov pc, lr
49ENDPROC(__udelay)
50ENDPROC(__const_udelay)
51ENDPROC(__delay)
diff --git a/arch/unicore32/lib/findbit.S b/arch/unicore32/lib/findbit.S
new file mode 100644
index 000000000000..c360ce905d8b
--- /dev/null
+++ b/arch/unicore32/lib/findbit.S
@@ -0,0 +1,98 @@
1/*
2 * linux/arch/unicore32/lib/findbit.S
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14 .text
15
16/*
17 * Purpose : Find a 'zero' bit
18 * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
19 */
20__uc32_find_first_zero_bit:
21 cxor.a r1, #0
22 beq 3f
23 mov r2, #0
241: ldb r3, [r0+], r2 >> #3
25 xor.a r3, r3, #0xff @ invert bits
26 bne .L_found @ any now set - found zero bit
27 add r2, r2, #8 @ next bit pointer
282: csub.a r2, r1 @ any more?
29 bub 1b
303: mov r0, r1 @ no free bits
31 mov pc, lr
32
33/*
34 * Purpose : Find next 'zero' bit
35 * Prototype: int find_next_zero_bit
36 * (void *addr, unsigned int maxbit, int offset)
37 */
38ENTRY(__uc32_find_next_zero_bit)
39 cxor.a r1, #0
40 beq 3b
41 and.a ip, r2, #7
42 beq 1b @ If new byte, goto old routine
43 ldb r3, [r0+], r2 >> #3
44 xor r3, r3, #0xff @ now looking for a 1 bit
45 mov.a r3, r3 >> ip @ shift off unused bits
46 bne .L_found
47 or r2, r2, #7 @ if zero, then no bits here
48 add r2, r2, #1 @ align bit pointer
49 b 2b @ loop for next bit
50ENDPROC(__uc32_find_next_zero_bit)
51
52/*
53 * Purpose : Find a 'one' bit
54 * Prototype: int find_first_bit
55 * (const unsigned long *addr, unsigned int maxbit);
56 */
57__uc32_find_first_bit:
58 cxor.a r1, #0
59 beq 3f
60 mov r2, #0
611: ldb r3, [r0+], r2 >> #3
62 mov.a r3, r3
63 bne .L_found @ any now set - found zero bit
64 add r2, r2, #8 @ next bit pointer
652: csub.a r2, r1 @ any more?
66 bub 1b
673: mov r0, r1 @ no free bits
68 mov pc, lr
69
70/*
71 * Purpose : Find next 'one' bit
72 * Prototype: int find_next_zero_bit
73 * (void *addr, unsigned int maxbit, int offset)
74 */
75ENTRY(__uc32_find_next_bit)
76 cxor.a r1, #0
77 beq 3b
78 and.a ip, r2, #7
79 beq 1b @ If new byte, goto old routine
80 ldb r3, [r0+], r2 >> #3
81 mov.a r3, r3 >> ip @ shift off unused bits
82 bne .L_found
83 or r2, r2, #7 @ if zero, then no bits here
84 add r2, r2, #1 @ align bit pointer
85 b 2b @ loop for next bit
86ENDPROC(__uc32_find_next_bit)
87
88/*
89 * One or more bits in the LSB of r3 are assumed to be set.
90 */
91.L_found:
92 rsub r1, r3, #0
93 and r3, r3, r1
94 cntlz r3, r3
95 rsub r3, r3, #31
96 add r0, r2, r3
97 mov pc, lr
98