Commit 96cf5185a95e0b304596fe19edcf8dfcd5c10699
1 parent
77c93b2f23
Exists in
master
and in
7 other branches
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>
Showing 10 changed files with 662 additions and 0 deletions Side-by-side Diff
- arch/unicore32/include/asm/assembler.h
- arch/unicore32/include/asm/bitops.h
- arch/unicore32/include/asm/checksum.h
- arch/unicore32/include/asm/delay.h
- arch/unicore32/include/asm/futex.h
- arch/unicore32/include/asm/io.h
- arch/unicore32/include/asm/mutex.h
- arch/unicore32/lib/Makefile
- arch/unicore32/lib/delay.S
- arch/unicore32/lib/findbit.S
arch/unicore32/include/asm/assembler.h
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...) \ | |
58 | +9999: 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 | |
103 | +9999 : | |
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 |
arch/unicore32/include/asm/bitops.h
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 | + | |
31 | +static 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__ */ |
arch/unicore32/include/asm/checksum.h
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 | + | |
22 | +static inline __wsum | |
23 | +csum_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 |
arch/unicore32/include/asm/delay.h
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 | + | |
19 | +extern 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 | + */ | |
28 | +extern 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 | + */ | |
40 | +extern void __udelay(unsigned long usecs); | |
41 | +extern 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__ */ |
arch/unicore32/include/asm/futex.h
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 | + | |
42 | +static inline int | |
43 | +futex_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 | + | |
109 | +static inline int | |
110 | +futex_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__ */ |
arch/unicore32/include/asm/io.h
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 | + */ | |
26 | +extern void __iomem *__uc32_ioremap(unsigned long, size_t); | |
27 | +extern void __iomem *__uc32_ioremap_cached(unsigned long, size_t); | |
28 | +extern 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 | + | |
41 | +extern void __iomem *ioport_map(unsigned long port, unsigned int nr); | |
42 | +extern 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__ */ |
arch/unicore32/include/asm/mutex.h
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 |
arch/unicore32/lib/Makefile
1 | +# | |
2 | +# linux/arch/unicore32/lib/Makefile | |
3 | +# | |
4 | +# Copyright (C) 2001-2010 GUAN Xue-tao | |
5 | +# | |
6 | + | |
7 | +lib-y := backtrace.o delay.o findbit.o | |
8 | +lib-y += strncpy_from_user.o strnlen_user.o | |
9 | +lib-y += clear_user.o copy_page.o | |
10 | +lib-y += copy_from_user.o copy_to_user.o | |
11 | + | |
12 | +GNU_LIBC_A := $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libc.a) | |
13 | +GNU_LIBC_A_OBJS := memchr.o memcpy.o memmove.o memset.o | |
14 | +GNU_LIBC_A_OBJS += strchr.o strrchr.o | |
15 | +GNU_LIBC_A_OBJS += rawmemchr.o # needed by strrchr.o | |
16 | + | |
17 | +GNU_LIBGCC_A := $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libgcc.a) | |
18 | +GNU_LIBGCC_A_OBJS := _ashldi3.o _ashrdi3.o _lshrdi3.o | |
19 | +GNU_LIBGCC_A_OBJS += _divsi3.o _modsi3.o _ucmpdi2.o _umodsi3.o _udivsi3.o | |
20 | + | |
21 | +lib-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 $@) > $@ |
arch/unicore32/lib/delay.S
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 | + | |
26 | +ENTRY(__udelay) | |
27 | + ldw r2, .LC1 | |
28 | + mul r0, r2, r0 | |
29 | +ENTRY(__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 | |
45 | +ENTRY(__delay) | |
46 | + sub.a r0, r0, #2 | |
47 | + bua __delay | |
48 | + mov pc, lr | |
49 | +ENDPROC(__udelay) | |
50 | +ENDPROC(__const_udelay) | |
51 | +ENDPROC(__delay) |
arch/unicore32/lib/findbit.S
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 | |
24 | +1: 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 | |
28 | +2: csub.a r2, r1 @ any more? | |
29 | + bub 1b | |
30 | +3: 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 | + */ | |
38 | +ENTRY(__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 | |
50 | +ENDPROC(__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 | |
61 | +1: 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 | |
65 | +2: csub.a r2, r1 @ any more? | |
66 | + bub 1b | |
67 | +3: 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 | + */ | |
75 | +ENTRY(__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 | |
86 | +ENDPROC(__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 |