aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/lib')
-rw-r--r--arch/arm/lib/Makefile29
-rw-r--r--arch/arm/lib/ashldi3.c61
-rw-r--r--arch/arm/lib/ashrdi3.c61
-rw-r--r--arch/arm/lib/backtrace.S157
-rw-r--r--arch/arm/lib/changebit.S28
-rw-r--r--arch/arm/lib/clearbit.S31
-rw-r--r--arch/arm/lib/copy_page.S46
-rw-r--r--arch/arm/lib/csumipv6.S32
-rw-r--r--arch/arm/lib/csumpartial.S137
-rw-r--r--arch/arm/lib/csumpartialcopy.S52
-rw-r--r--arch/arm/lib/csumpartialcopygeneric.S331
-rw-r--r--arch/arm/lib/csumpartialcopyuser.S104
-rw-r--r--arch/arm/lib/delay.S58
-rw-r--r--arch/arm/lib/div64.S200
-rw-r--r--arch/arm/lib/ecard.S45
-rw-r--r--arch/arm/lib/findbit.S168
-rw-r--r--arch/arm/lib/floppydma.S32
-rw-r--r--arch/arm/lib/gcclib.h25
-rw-r--r--arch/arm/lib/getuser.S78
-rw-r--r--arch/arm/lib/io-acorn.S32
-rw-r--r--arch/arm/lib/io-readsb.S122
-rw-r--r--arch/arm/lib/io-readsl.S78
-rw-r--r--arch/arm/lib/io-readsw-armv3.S107
-rw-r--r--arch/arm/lib/io-readsw-armv4.S130
-rw-r--r--arch/arm/lib/io-shark.c83
-rw-r--r--arch/arm/lib/io-writesb.S92
-rw-r--r--arch/arm/lib/io-writesl.S66
-rw-r--r--arch/arm/lib/io-writesw-armv3.S127
-rw-r--r--arch/arm/lib/io-writesw-armv4.S95
-rw-r--r--arch/arm/lib/lib1funcs.S314
-rw-r--r--arch/arm/lib/longlong.h183
-rw-r--r--arch/arm/lib/lshrdi3.c61
-rw-r--r--arch/arm/lib/memchr.S25
-rw-r--r--arch/arm/lib/memcpy.S393
-rw-r--r--arch/arm/lib/memset.S80
-rw-r--r--arch/arm/lib/memzero.S80
-rw-r--r--arch/arm/lib/muldi3.c77
-rw-r--r--arch/arm/lib/putuser.S76
-rw-r--r--arch/arm/lib/setbit.S29
-rw-r--r--arch/arm/lib/strchr.S26
-rw-r--r--arch/arm/lib/strncpy_from_user.S43
-rw-r--r--arch/arm/lib/strnlen_user.S40
-rw-r--r--arch/arm/lib/strrchr.S25
-rw-r--r--arch/arm/lib/testchangebit.S29
-rw-r--r--arch/arm/lib/testclearbit.S29
-rw-r--r--arch/arm/lib/testsetbit.S29
-rw-r--r--arch/arm/lib/uaccess.S697
-rw-r--r--arch/arm/lib/ucmpdi2.c51
-rw-r--r--arch/arm/lib/udivdi3.c242
49 files changed, 5136 insertions, 0 deletions
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
new file mode 100644
index 000000000000..c0e65833ffc4
--- /dev/null
+++ b/arch/arm/lib/Makefile
@@ -0,0 +1,29 @@
1#
2# linux/arch/arm/lib/Makefile
3#
4# Copyright (C) 1995-2000 Russell King
5#
6
7lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
8 csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
9 copy_page.o delay.o findbit.o memchr.o memcpy.o \
10 memset.o memzero.o setbit.o strncpy_from_user.o \
11 strnlen_user.o strchr.o strrchr.o testchangebit.o \
12 testclearbit.o testsetbit.o uaccess.o getuser.o \
13 putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
14 ucmpdi2.o udivdi3.o lib1funcs.o div64.o \
15 io-readsb.o io-writesb.o io-readsl.o io-writesl.o
16
17ifeq ($(CONFIG_CPU_32v3),y)
18 lib-y += io-readsw-armv3.o io-writesw-armv3.o
19else
20 lib-y += io-readsw-armv4.o io-writesw-armv4.o
21endif
22
23lib-$(CONFIG_ARCH_RPC) += ecard.o io-acorn.o floppydma.o
24lib-$(CONFIG_ARCH_CLPS7500) += io-acorn.o
25lib-$(CONFIG_ARCH_L7200) += io-acorn.o
26lib-$(CONFIG_ARCH_SHARK) += io-shark.o
27
28$(obj)/csumpartialcopy.o: $(obj)/csumpartialcopygeneric.S
29$(obj)/csumpartialcopyuser.o: $(obj)/csumpartialcopygeneric.S
diff --git a/arch/arm/lib/ashldi3.c b/arch/arm/lib/ashldi3.c
new file mode 100644
index 000000000000..130f5a839669
--- /dev/null
+++ b/arch/arm/lib/ashldi3.c
@@ -0,0 +1,61 @@
1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
3/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22/* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License.
28 */
29/* support functions required by the kernel. based on code from gcc-2.95.3 */
30/* I Molton 29/07/01 */
31
32#include "gcclib.h"
33
34DItype
35__ashldi3 (DItype u, word_type b)
36{
37 DIunion w;
38 word_type bm;
39 DIunion uu;
40
41 if (b == 0)
42 return u;
43
44 uu.ll = u;
45
46 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
47 if (bm <= 0)
48 {
49 w.s.low = 0;
50 w.s.high = (USItype)uu.s.low << -bm;
51 }
52 else
53 {
54 USItype carries = (USItype)uu.s.low >> bm;
55 w.s.low = (USItype)uu.s.low << b;
56 w.s.high = ((USItype)uu.s.high << b) | carries;
57 }
58
59 return w.ll;
60}
61
diff --git a/arch/arm/lib/ashrdi3.c b/arch/arm/lib/ashrdi3.c
new file mode 100644
index 000000000000..71625d218f8d
--- /dev/null
+++ b/arch/arm/lib/ashrdi3.c
@@ -0,0 +1,61 @@
1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
3/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22/* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License.
28 */
29/* support functions required by the kernel. based on code from gcc-2.95.3 */
30/* I Molton 29/07/01 */
31
32#include "gcclib.h"
33
34DItype
35__ashrdi3 (DItype u, word_type b)
36{
37 DIunion w;
38 word_type bm;
39 DIunion uu;
40
41 if (b == 0)
42 return u;
43
44 uu.ll = u;
45
46 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
47 if (bm <= 0)
48 {
49 /* w.s.high = 1..1 or 0..0 */
50 w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
51 w.s.low = uu.s.high >> -bm;
52 }
53 else
54 {
55 USItype carries = (USItype)uu.s.high << bm;
56 w.s.high = uu.s.high >> b;
57 w.s.low = ((USItype)uu.s.low >> b) | carries;
58 }
59
60 return w.ll;
61}
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
new file mode 100644
index 000000000000..68a21c0f3f52
--- /dev/null
+++ b/arch/arm/lib/backtrace.S
@@ -0,0 +1,157 @@
1/*
2 * linux/arch/arm/lib/backtrace.S
3 *
4 * Copyright (C) 1995, 1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * 27/03/03 Ian Molton Clean up CONFIG_CPU
11 *
12 */
13#include <linux/config.h>
14#include <linux/linkage.h>
15#include <asm/assembler.h>
16 .text
17
18@ fp is 0 or stack frame
19
20#define frame r4
21#define next r5
22#define save r6
23#define mask r7
24#define offset r8
25
26ENTRY(__backtrace)
27 mov r1, #0x10
28 mov r0, fp
29
30ENTRY(c_backtrace)
31
32#ifndef CONFIG_FRAME_POINTER
33 mov pc, lr
34#else
35
36 stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location...
37 tst r1, #0x10 @ 26 or 32-bit?
38 moveq mask, #0xfc000003
39 movne mask, #0
40 tst mask, r0
41 movne r0, #0
42 movs frame, r0
431: moveq r0, #-2
44 LOADREGS(eqfd, sp!, {r4 - r8, pc})
45
462: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction
47 ldr r0, [sp], #4
48 adr r1, 2b - 4
49 sub offset, r0, r1
50
513: tst frame, mask @ Check for address exceptions...
52 bne 1b
53
541001: ldr next, [frame, #-12] @ get fp
551002: ldr r2, [frame, #-4] @ get lr
561003: ldr r3, [frame, #0] @ get pc
57 sub save, r3, offset @ Correct PC for prefetching
58 bic save, save, mask
591004: ldr r1, [save, #0] @ get instruction at function
60 mov r1, r1, lsr #10
61 ldr r3, .Ldsi+4
62 teq r1, r3
63 subeq save, save, #4
64 mov r0, save
65 bic r1, r2, mask
66 bl dump_backtrace_entry
67
68 ldr r0, [frame, #-8] @ get sp
69 sub r0, r0, #4
701005: ldr r1, [save, #4] @ get instruction at function+4
71 mov r3, r1, lsr #10
72 ldr r2, .Ldsi+4
73 teq r3, r2 @ Check for stmia sp!, {args}
74 addeq save, save, #4 @ next instruction
75 bleq .Ldumpstm
76
77 sub r0, frame, #16
781006: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction
79 mov r3, r1, lsr #10
80 ldr r2, .Ldsi
81 teq r3, r2
82 bleq .Ldumpstm
83
84 /*
85 * A zero next framepointer means we're done.
86 */
87 teq next, #0
88 LOADREGS(eqfd, sp!, {r4 - r8, pc})
89
90 /*
91 * The next framepointer must be above the
92 * current framepointer.
93 */
94 cmp next, frame
95 mov frame, next
96 bhi 3b
97 b 1007f
98
99/*
100 * Fixup for LDMDB
101 */
102 .section .fixup,"ax"
103 .align 0
1041007: ldr r0, =.Lbad
105 mov r1, frame
106 bl printk
107 LOADREGS(fd, sp!, {r4 - r8, pc})
108 .ltorg
109 .previous
110
111 .section __ex_table,"a"
112 .align 3
113 .long 1001b, 1007b
114 .long 1002b, 1007b
115 .long 1003b, 1007b
116 .long 1004b, 1007b
117 .long 1005b, 1007b
118 .long 1006b, 1007b
119 .previous
120
121#define instr r4
122#define reg r5
123#define stack r6
124
125.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr}
126 mov stack, r0
127 mov instr, r1
128 mov reg, #9
129 mov r7, #0
1301: mov r3, #1
131 tst instr, r3, lsl reg
132 beq 2f
133 add r7, r7, #1
134 teq r7, #4
135 moveq r7, #0
136 moveq r3, #'\n'
137 movne r3, #' '
138 ldr r2, [stack], #-4
139 mov r1, reg
140 adr r0, .Lfp
141 bl printk
1422: subs reg, reg, #1
143 bpl 1b
144 teq r7, #0
145 adrne r0, .Lcr
146 blne printk
147 mov r0, stack
148 LOADREGS(fd, sp!, {instr, reg, stack, r7, pc})
149
150.Lfp: .asciz " r%d = %08X%c"
151.Lcr: .asciz "\n"
152.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
153 .align
154.Ldsi: .word 0x00e92dd8 >> 2
155 .word 0x00e92d00 >> 2
156
157#endif
diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S
new file mode 100644
index 000000000000..3af45cab70e1
--- /dev/null
+++ b/arch/arm/lib/changebit.S
@@ -0,0 +1,28 @@
1/*
2 * linux/arch/arm/lib/changebit.S
3 *
4 * Copyright (C) 1995-1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12 .text
13
14/* Purpose : Function to change a bit
15 * Prototype: int change_bit(int bit, void *addr)
16 */
17ENTRY(_change_bit_be)
18 eor r0, r0, #0x18 @ big endian byte ordering
19ENTRY(_change_bit_le)
20 and r2, r0, #7
21 mov r3, #1
22 mov r3, r3, lsl r2
23 save_and_disable_irqs ip, r2
24 ldrb r2, [r1, r0, lsr #3]
25 eor r2, r2, r3
26 strb r2, [r1, r0, lsr #3]
27 restore_irqs ip
28 RETINSTR(mov,pc,lr)
diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S
new file mode 100644
index 000000000000..069a2ce413f0
--- /dev/null
+++ b/arch/arm/lib/clearbit.S
@@ -0,0 +1,31 @@
1/*
2 * linux/arch/arm/lib/clearbit.S
3 *
4 * Copyright (C) 1995-1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12 .text
13
14/*
15 * Purpose : Function to clear a bit
16 * Prototype: int clear_bit(int bit, void *addr)
17 */
18ENTRY(_clear_bit_be)
19 eor r0, r0, #0x18 @ big endian byte ordering
20ENTRY(_clear_bit_le)
21 and r2, r0, #7
22 mov r3, #1
23 mov r3, r3, lsl r2
24 save_and_disable_irqs ip, r2
25 ldrb r2, [r1, r0, lsr #3]
26 bic r2, r2, r3
27 strb r2, [r1, r0, lsr #3]
28 restore_irqs ip
29 RETINSTR(mov,pc,lr)
30
31
diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S
new file mode 100644
index 000000000000..4c38abdbe497
--- /dev/null
+++ b/arch/arm/lib/copy_page.S
@@ -0,0 +1,46 @@
1/*
2 * linux/arch/arm/lib/copypage.S
3 *
4 * Copyright (C) 1995-1999 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ASM optimised string functions
11 */
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14#include <asm/constants.h>
15
16#define COPY_COUNT (PAGE_SZ/64 PLD( -1 ))
17
18 .text
19 .align 5
20/*
21 * StrongARM optimised copy_page routine
22 * now 1.78bytes/cycle, was 1.60 bytes/cycle (50MHz bus -> 89MB/s)
23 * Note that we probably achieve closer to the 100MB/s target with
24 * the core clock switching.
25 */
26ENTRY(copy_page)
27 stmfd sp!, {r4, lr} @ 2
28 PLD( pld [r1, #0] )
29 PLD( pld [r1, #32] )
30 mov r2, #COPY_COUNT @ 1
31 ldmia r1!, {r3, r4, ip, lr} @ 4+1
321: PLD( pld [r1, #64] )
33 PLD( pld [r1, #96] )
342: stmia r0!, {r3, r4, ip, lr} @ 4
35 ldmia r1!, {r3, r4, ip, lr} @ 4+1
36 stmia r0!, {r3, r4, ip, lr} @ 4
37 ldmia r1!, {r3, r4, ip, lr} @ 4+1
38 stmia r0!, {r3, r4, ip, lr} @ 4
39 ldmia r1!, {r3, r4, ip, lr} @ 4
40 subs r2, r2, #1 @ 1
41 stmia r0!, {r3, r4, ip, lr} @ 4
42 ldmgtia r1!, {r3, r4, ip, lr} @ 4
43 bgt 1b @ 1
44 PLD( ldmeqia r1!, {r3, r4, ip, lr} )
45 PLD( beq 2b )
46 LOADREGS(fd, sp!, {r4, pc}) @ 3
diff --git a/arch/arm/lib/csumipv6.S b/arch/arm/lib/csumipv6.S
new file mode 100644
index 000000000000..7065a20ee8ad
--- /dev/null
+++ b/arch/arm/lib/csumipv6.S
@@ -0,0 +1,32 @@
1/*
2 * linux/arch/arm/lib/csumipv6.S
3 *
4 * Copyright (C) 1995-1998 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12
13 .text
14
15ENTRY(__csum_ipv6_magic)
16 str lr, [sp, #-4]!
17 adds ip, r2, r3
18 ldmia r1, {r1 - r3, lr}
19 adcs ip, ip, r1
20 adcs ip, ip, r2
21 adcs ip, ip, r3
22 adcs ip, ip, lr
23 ldmia r0, {r0 - r3}
24 adcs r0, ip, r0
25 adcs r0, r0, r1
26 adcs r0, r0, r2
27 ldr r2, [sp, #4]
28 adcs r0, r0, r3
29 adcs r0, r0, r2
30 adcs r0, r0, #0
31 LOADREGS(fd, sp!, {pc})
32
diff --git a/arch/arm/lib/csumpartial.S b/arch/arm/lib/csumpartial.S
new file mode 100644
index 000000000000..cb5e3708f118
--- /dev/null
+++ b/arch/arm/lib/csumpartial.S
@@ -0,0 +1,137 @@
1/*
2 * linux/arch/arm/lib/csumpartial.S
3 *
4 * Copyright (C) 1995-1998 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12
13 .text
14
15/*
16 * Function: __u32 csum_partial(const char *src, int len, __u32 sum)
17 * Params : r0 = buffer, r1 = len, r2 = checksum
18 * Returns : r0 = new checksum
19 */
20
21buf .req r0
22len .req r1
23sum .req r2
24td0 .req r3
25td1 .req r4 @ save before use
26td2 .req r5 @ save before use
27td3 .req lr
28
29.zero: mov r0, sum
30 add sp, sp, #4
31 ldr pc, [sp], #4
32
33 /*
34 * Handle 0 to 7 bytes, with any alignment of source and
35 * destination pointers. Note that when we get here, C = 0
36 */
37.less8: teq len, #0 @ check for zero count
38 beq .zero
39
40 /* we must have at least one byte. */
41 tst buf, #1 @ odd address?
42 ldrneb td0, [buf], #1
43 subne len, len, #1
44 adcnes sum, sum, td0, put_byte_1
45
46.less4: tst len, #6
47 beq .less8_byte
48
49 /* we are now half-word aligned */
50
51.less8_wordlp:
52#if __LINUX_ARM_ARCH__ >= 4
53 ldrh td0, [buf], #2
54 sub len, len, #2
55#else
56 ldrb td0, [buf], #1
57 ldrb td3, [buf], #1
58 sub len, len, #2
59#ifndef __ARMEB__
60 orr td0, td0, td3, lsl #8
61#else
62 orr td0, td3, td0, lsl #8
63#endif
64#endif
65 adcs sum, sum, td0
66 tst len, #6
67 bne .less8_wordlp
68
69.less8_byte: tst len, #1 @ odd number of bytes
70 ldrneb td0, [buf], #1 @ include last byte
71 adcnes sum, sum, td0, put_byte_0 @ update checksum
72
73.done: adc r0, sum, #0 @ collect up the last carry
74 ldr td0, [sp], #4
75 tst td0, #1 @ check buffer alignment
76 movne r0, r0, ror #8 @ rotate checksum by 8 bits
77 ldr pc, [sp], #4 @ return
78
79.not_aligned: tst buf, #1 @ odd address
80 ldrneb td0, [buf], #1 @ make even
81 subne len, len, #1
82 adcnes sum, sum, td0, put_byte_1 @ update checksum
83
84 tst buf, #2 @ 32-bit aligned?
85#if __LINUX_ARM_ARCH__ >= 4
86 ldrneh td0, [buf], #2 @ make 32-bit aligned
87 subne len, len, #2
88#else
89 ldrneb td0, [buf], #1
90 ldrneb ip, [buf], #1
91 subne len, len, #2
92#ifndef __ARMEB__
93 orrne td0, td0, ip, lsl #8
94#else
95 orrne td0, ip, td0, lsl #8
96#endif
97#endif
98 adcnes sum, sum, td0 @ update checksum
99 mov pc, lr
100
101ENTRY(csum_partial)
102 stmfd sp!, {buf, lr}
103 cmp len, #8 @ Ensure that we have at least
104 blo .less8 @ 8 bytes to copy.
105
106 adds sum, sum, #0 @ C = 0
107 tst buf, #3 @ Test destination alignment
108 blne .not_aligned @ aligh destination, return here
109
1101: bics ip, len, #31
111 beq 3f
112
113 stmfd sp!, {r4 - r5}
1142: ldmia buf!, {td0, td1, td2, td3}
115 adcs sum, sum, td0
116 adcs sum, sum, td1
117 adcs sum, sum, td2
118 adcs sum, sum, td3
119 ldmia buf!, {td0, td1, td2, td3}
120 adcs sum, sum, td0
121 adcs sum, sum, td1
122 adcs sum, sum, td2
123 adcs sum, sum, td3
124 sub ip, ip, #32
125 teq ip, #0
126 bne 2b
127 ldmfd sp!, {r4 - r5}
128
1293: tst len, #0x1c @ should not change C
130 beq .less4
131
1324: ldr td0, [buf], #4
133 sub len, len, #4
134 adcs sum, sum, td0
135 tst len, #0x1c
136 bne 4b
137 b .less4
diff --git a/arch/arm/lib/csumpartialcopy.S b/arch/arm/lib/csumpartialcopy.S
new file mode 100644
index 000000000000..990ee63b2465
--- /dev/null
+++ b/arch/arm/lib/csumpartialcopy.S
@@ -0,0 +1,52 @@
1/*
2 * linux/arch/arm/lib/csumpartialcopy.S
3 *
4 * Copyright (C) 1995-1998 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12
13 .text
14
15/* Function: __u32 csum_partial_copy_nocheck(const char *src, char *dst, int len, __u32 sum)
16 * Params : r0 = src, r1 = dst, r2 = len, r3 = checksum
17 * Returns : r0 = new checksum
18 */
19
20 .macro save_regs
21 stmfd sp!, {r1, r4 - r8, fp, ip, lr, pc}
22 .endm
23
24 .macro load_regs,flags
25 LOADREGS(\flags,fp,{r1, r4 - r8, fp, sp, pc})
26 .endm
27
28 .macro load1b, reg1
29 ldrb \reg1, [r0], #1
30 .endm
31
32 .macro load2b, reg1, reg2
33 ldrb \reg1, [r0], #1
34 ldrb \reg2, [r0], #1
35 .endm
36
37 .macro load1l, reg1
38 ldr \reg1, [r0], #4
39 .endm
40
41 .macro load2l, reg1, reg2
42 ldr \reg1, [r0], #4
43 ldr \reg2, [r0], #4
44 .endm
45
46 .macro load4l, reg1, reg2, reg3, reg4
47 ldmia r0!, {\reg1, \reg2, \reg3, \reg4}
48 .endm
49
50#define FN_ENTRY ENTRY(csum_partial_copy_nocheck)
51
52#include "csumpartialcopygeneric.S"
diff --git a/arch/arm/lib/csumpartialcopygeneric.S b/arch/arm/lib/csumpartialcopygeneric.S
new file mode 100644
index 000000000000..d3a2f4667db4
--- /dev/null
+++ b/arch/arm/lib/csumpartialcopygeneric.S
@@ -0,0 +1,331 @@
1/*
2 * linux/arch/arm/lib/csumpartialcopygeneric.S
3 *
4 * Copyright (C) 1995-2001 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11/*
12 * unsigned int
13 * csum_partial_copy_xxx(const char *src, char *dst, int len, int sum, )
14 * r0 = src, r1 = dst, r2 = len, r3 = sum
15 * Returns : r0 = checksum
16 *
17 * Note that 'tst' and 'teq' preserve the carry flag.
18 */
19
20src .req r0
21dst .req r1
22len .req r2
23sum .req r3
24
25.zero: mov r0, sum
26 load_regs ea
27
28 /*
29 * Align an unaligned destination pointer. We know that
30 * we have >= 8 bytes here, so we don't need to check
31 * the length. Note that the source pointer hasn't been
32 * aligned yet.
33 */
34.dst_unaligned: tst dst, #1
35 beq .dst_16bit
36
37 load1b ip
38 sub len, len, #1
39 adcs sum, sum, ip, put_byte_1 @ update checksum
40 strb ip, [dst], #1
41 tst dst, #2
42 moveq pc, lr @ dst is now 32bit aligned
43
44.dst_16bit: load2b r8, ip
45 sub len, len, #2
46 adcs sum, sum, r8, put_byte_0
47 strb r8, [dst], #1
48 adcs sum, sum, ip, put_byte_1
49 strb ip, [dst], #1
50 mov pc, lr @ dst is now 32bit aligned
51
52 /*
53 * Handle 0 to 7 bytes, with any alignment of source and
54 * destination pointers. Note that when we get here, C = 0
55 */
56.less8: teq len, #0 @ check for zero count
57 beq .zero
58
59 /* we must have at least one byte. */
60 tst dst, #1 @ dst 16-bit aligned
61 beq .less8_aligned
62
63 /* Align dst */
64 load1b ip
65 sub len, len, #1
66 adcs sum, sum, ip, put_byte_1 @ update checksum
67 strb ip, [dst], #1
68 tst len, #6
69 beq .less8_byteonly
70
711: load2b r8, ip
72 sub len, len, #2
73 adcs sum, sum, r8, put_byte_0
74 strb r8, [dst], #1
75 adcs sum, sum, ip, put_byte_1
76 strb ip, [dst], #1
77.less8_aligned: tst len, #6
78 bne 1b
79.less8_byteonly:
80 tst len, #1
81 beq .done
82 load1b r8
83 adcs sum, sum, r8, put_byte_0 @ update checksum
84 strb r8, [dst], #1
85 b .done
86
87FN_ENTRY
88 mov ip, sp
89 save_regs
90 sub fp, ip, #4
91
92 cmp len, #8 @ Ensure that we have at least
93 blo .less8 @ 8 bytes to copy.
94
95 adds sum, sum, #0 @ C = 0
96 tst dst, #3 @ Test destination alignment
97 blne .dst_unaligned @ align destination, return here
98
99 /*
100 * Ok, the dst pointer is now 32bit aligned, and we know
101 * that we must have more than 4 bytes to copy. Note
102 * that C contains the carry from the dst alignment above.
103 */
104
105 tst src, #3 @ Test source alignment
106 bne .src_not_aligned
107
108 /* Routine for src & dst aligned */
109
110 bics ip, len, #15
111 beq 2f
112
1131: load4l r4, r5, r6, r7
114 stmia dst!, {r4, r5, r6, r7}
115 adcs sum, sum, r4
116 adcs sum, sum, r5
117 adcs sum, sum, r6
118 adcs sum, sum, r7
119 sub ip, ip, #16
120 teq ip, #0
121 bne 1b
122
1232: ands ip, len, #12
124 beq 4f
125 tst ip, #8
126 beq 3f
127 load2l r4, r5
128 stmia dst!, {r4, r5}
129 adcs sum, sum, r4
130 adcs sum, sum, r5
131 tst ip, #4
132 beq 4f
133
1343: load1l r4
135 str r4, [dst], #4
136 adcs sum, sum, r4
137
1384: ands len, len, #3
139 beq .done
140 load1l r4
141 tst len, #2
142 mov r5, r4, get_byte_0
143 beq .exit
144 adcs sum, sum, r4, push #16
145 strb r5, [dst], #1
146 mov r5, r4, get_byte_1
147 strb r5, [dst], #1
148 mov r5, r4, get_byte_2
149.exit: tst len, #1
150 strneb r5, [dst], #1
151 andne r5, r5, #255
152 adcnes sum, sum, r5, put_byte_0
153
154 /*
155 * If the dst pointer was not 16-bit aligned, we
156 * need to rotate the checksum here to get around
157 * the inefficient byte manipulations in the
158 * architecture independent code.
159 */
160.done: adc r0, sum, #0
161 ldr sum, [sp, #0] @ dst
162 tst sum, #1
163 movne r0, r0, ror #8
164 load_regs ea
165
166.src_not_aligned:
167 adc sum, sum, #0 @ include C from dst alignment
168 and ip, src, #3
169 bic src, src, #3
170 load1l r5
171 cmp ip, #2
172 beq .src2_aligned
173 bhi .src3_aligned
174 mov r4, r5, pull #8 @ C = 0
175 bics ip, len, #15
176 beq 2f
1771: load4l r5, r6, r7, r8
178 orr r4, r4, r5, push #24
179 mov r5, r5, pull #8
180 orr r5, r5, r6, push #24
181 mov r6, r6, pull #8
182 orr r6, r6, r7, push #24
183 mov r7, r7, pull #8
184 orr r7, r7, r8, push #24
185 stmia dst!, {r4, r5, r6, r7}
186 adcs sum, sum, r4
187 adcs sum, sum, r5
188 adcs sum, sum, r6
189 adcs sum, sum, r7
190 mov r4, r8, pull #8
191 sub ip, ip, #16
192 teq ip, #0
193 bne 1b
1942: ands ip, len, #12
195 beq 4f
196 tst ip, #8
197 beq 3f
198 load2l r5, r6
199 orr r4, r4, r5, push #24
200 mov r5, r5, pull #8
201 orr r5, r5, r6, push #24
202 stmia dst!, {r4, r5}
203 adcs sum, sum, r4
204 adcs sum, sum, r5
205 mov r4, r6, pull #8
206 tst ip, #4
207 beq 4f
2083: load1l r5
209 orr r4, r4, r5, push #24
210 str r4, [dst], #4
211 adcs sum, sum, r4
212 mov r4, r5, pull #8
2134: ands len, len, #3
214 beq .done
215 mov r5, r4, get_byte_0
216 tst len, #2
217 beq .exit
218 adcs sum, sum, r4, push #16
219 strb r5, [dst], #1
220 mov r5, r4, get_byte_1
221 strb r5, [dst], #1
222 mov r5, r4, get_byte_2
223 b .exit
224
225.src2_aligned: mov r4, r5, pull #16
226 adds sum, sum, #0
227 bics ip, len, #15
228 beq 2f
2291: load4l r5, r6, r7, r8
230 orr r4, r4, r5, push #16
231 mov r5, r5, pull #16
232 orr r5, r5, r6, push #16
233 mov r6, r6, pull #16
234 orr r6, r6, r7, push #16
235 mov r7, r7, pull #16
236 orr r7, r7, r8, push #16
237 stmia dst!, {r4, r5, r6, r7}
238 adcs sum, sum, r4
239 adcs sum, sum, r5
240 adcs sum, sum, r6
241 adcs sum, sum, r7
242 mov r4, r8, pull #16
243 sub ip, ip, #16
244 teq ip, #0
245 bne 1b
2462: ands ip, len, #12
247 beq 4f
248 tst ip, #8
249 beq 3f
250 load2l r5, r6
251 orr r4, r4, r5, push #16
252 mov r5, r5, pull #16
253 orr r5, r5, r6, push #16
254 stmia dst!, {r4, r5}
255 adcs sum, sum, r4
256 adcs sum, sum, r5
257 mov r4, r6, pull #16
258 tst ip, #4
259 beq 4f
2603: load1l r5
261 orr r4, r4, r5, push #16
262 str r4, [dst], #4
263 adcs sum, sum, r4
264 mov r4, r5, pull #16
2654: ands len, len, #3
266 beq .done
267 mov r5, r4, get_byte_0
268 tst len, #2
269 beq .exit
270 adcs sum, sum, r4
271 strb r5, [dst], #1
272 mov r5, r4, get_byte_1
273 strb r5, [dst], #1
274 tst len, #1
275 beq .done
276 load1b r5
277 b .exit
278
279.src3_aligned: mov r4, r5, pull #24
280 adds sum, sum, #0
281 bics ip, len, #15
282 beq 2f
2831: load4l r5, r6, r7, r8
284 orr r4, r4, r5, push #8
285 mov r5, r5, pull #24
286 orr r5, r5, r6, push #8
287 mov r6, r6, pull #24
288 orr r6, r6, r7, push #8
289 mov r7, r7, pull #24
290 orr r7, r7, r8, push #8
291 stmia dst!, {r4, r5, r6, r7}
292 adcs sum, sum, r4
293 adcs sum, sum, r5
294 adcs sum, sum, r6
295 adcs sum, sum, r7
296 mov r4, r8, pull #24
297 sub ip, ip, #16
298 teq ip, #0
299 bne 1b
3002: ands ip, len, #12
301 beq 4f
302 tst ip, #8
303 beq 3f
304 load2l r5, r6
305 orr r4, r4, r5, push #8
306 mov r5, r5, pull #24
307 orr r5, r5, r6, push #8
308 stmia dst!, {r4, r5}
309 adcs sum, sum, r4
310 adcs sum, sum, r5
311 mov r4, r6, pull #24
312 tst ip, #4
313 beq 4f
3143: load1l r5
315 orr r4, r4, r5, push #8
316 str r4, [dst], #4
317 adcs sum, sum, r4
318 mov r4, r5, pull #24
3194: ands len, len, #3
320 beq .done
321 mov r5, r4, get_byte_0
322 tst len, #2
323 beq .exit
324 strb r5, [dst], #1
325 adcs sum, sum, r4
326 load1l r4
327 mov r5, r4, get_byte_0
328 strb r5, [dst], #1
329 adcs sum, sum, r4, push #24
330 mov r5, r4, get_byte_1
331 b .exit
diff --git a/arch/arm/lib/csumpartialcopyuser.S b/arch/arm/lib/csumpartialcopyuser.S
new file mode 100644
index 000000000000..46a2dc962e9d
--- /dev/null
+++ b/arch/arm/lib/csumpartialcopyuser.S
@@ -0,0 +1,104 @@
1/*
2 * linux/arch/arm/lib/csumpartialcopyuser.S
3 *
4 * Copyright (C) 1995-1998 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * 27/03/03 Ian Molton Clean up CONFIG_CPU
11 *
12 */
13#include <linux/linkage.h>
14#include <asm/assembler.h>
15#include <asm/errno.h>
16#include <asm/constants.h>
17
18 .text
19
20 .macro save_regs
21 stmfd sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc}
22 .endm
23
24 .macro load_regs,flags
25 ldm\flags fp, {r1, r2, r4-r8, fp, sp, pc}
26 .endm
27
28 .macro load1b, reg1
299999: ldrbt \reg1, [r0], $1
30 .section __ex_table, "a"
31 .align 3
32 .long 9999b, 6001f
33 .previous
34 .endm
35
36 .macro load2b, reg1, reg2
379999: ldrbt \reg1, [r0], $1
389998: ldrbt \reg2, [r0], $1
39 .section __ex_table, "a"
40 .long 9999b, 6001f
41 .long 9998b, 6001f
42 .previous
43 .endm
44
45 .macro load1l, reg1
469999: ldrt \reg1, [r0], $4
47 .section __ex_table, "a"
48 .align 3
49 .long 9999b, 6001f
50 .previous
51 .endm
52
53 .macro load2l, reg1, reg2
549999: ldrt \reg1, [r0], $4
559998: ldrt \reg2, [r0], $4
56 .section __ex_table, "a"
57 .long 9999b, 6001f
58 .long 9998b, 6001f
59 .previous
60 .endm
61
62 .macro load4l, reg1, reg2, reg3, reg4
639999: ldrt \reg1, [r0], $4
649998: ldrt \reg2, [r0], $4
659997: ldrt \reg3, [r0], $4
669996: ldrt \reg4, [r0], $4
67 .section __ex_table, "a"
68 .long 9999b, 6001f
69 .long 9998b, 6001f
70 .long 9997b, 6001f
71 .long 9996b, 6001f
72 .previous
73 .endm
74
75/*
76 * unsigned int
77 * csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr)
78 * r0 = src, r1 = dst, r2 = len, r3 = sum, [sp] = *err_ptr
79 * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT
80 */
81
82#define FN_ENTRY ENTRY(csum_partial_copy_from_user)
83
84#include "csumpartialcopygeneric.S"
85
86/*
87 * FIXME: minor buglet here
88 * We don't return the checksum for the data present in the buffer. To do
89 * so properly, we would have to add in whatever registers were loaded before
90 * the fault, which, with the current asm above is not predictable.
91 */
92 .section .fixup,"ax"
93 .align 4
946001: mov r4, #-EFAULT
95 ldr r5, [fp, #4] @ *err_ptr
96 str r4, [r5]
97 ldmia sp, {r1, r2} @ retrieve dst, len
98 add r2, r2, r1
99 mov r0, #0 @ zero the buffer
1006002: teq r2, r1
101 strneb r0, [r1], #1
102 bne 6002b
103 load_regs ea
104 .previous
diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay.S
new file mode 100644
index 000000000000..3c7f7e675dd8
--- /dev/null
+++ b/arch/arm/lib/delay.S
@@ -0,0 +1,58 @@
1/*
2 * linux/arch/arm/lib/delay.S
3 *
4 * Copyright (C) 1995, 1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12 .text
13
14LC0: .word loops_per_jiffy
15
16/*
17 * 0 <= r0 <= 2000
18 */
19ENTRY(__udelay)
20 mov r2, #0x6800
21 orr r2, r2, #0x00db
22 mul r0, r2, r0
23ENTRY(__const_udelay) @ 0 <= r0 <= 0x01ffffff
24 ldr r2, LC0
25 ldr r2, [r2] @ max = 0x0fffffff
26 mov r0, r0, lsr #11 @ max = 0x00003fff
27 mov r2, r2, lsr #11 @ max = 0x0003ffff
28 mul r0, r2, r0 @ max = 2^32-1
29 movs r0, r0, lsr #6
30 RETINSTR(moveq,pc,lr)
31
32/*
33 * loops = (r0 * 0x10c6 * 100 * loops_per_jiffy) / 2^32
34 *
35 * Oh, if only we had a cycle counter...
36 */
37
38@ Delay routine
39ENTRY(__delay)
40 subs r0, r0, #1
41#if 0
42 RETINSTR(movls,pc,lr)
43 subs r0, r0, #1
44 RETINSTR(movls,pc,lr)
45 subs r0, r0, #1
46 RETINSTR(movls,pc,lr)
47 subs r0, r0, #1
48 RETINSTR(movls,pc,lr)
49 subs r0, r0, #1
50 RETINSTR(movls,pc,lr)
51 subs r0, r0, #1
52 RETINSTR(movls,pc,lr)
53 subs r0, r0, #1
54 RETINSTR(movls,pc,lr)
55 subs r0, r0, #1
56#endif
57 bhi __delay
58 RETINSTR(mov,pc,lr)
diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S
new file mode 100644
index 000000000000..ec9a1cd6176f
--- /dev/null
+++ b/arch/arm/lib/div64.S
@@ -0,0 +1,200 @@
1/*
2 * linux/arch/arm/lib/div64.S
3 *
4 * Optimized computation of 64-bit dividend / 32-bit divisor
5 *
6 * Author: Nicolas Pitre
7 * Created: Oct 5, 2003
8 * Copyright: Monta Vista Software, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/linkage.h>
16
17#ifdef __ARMEB__
18#define xh r0
19#define xl r1
20#define yh r2
21#define yl r3
22#else
23#define xl r0
24#define xh r1
25#define yl r2
26#define yh r3
27#endif
28
29/*
30 * __do_div64: perform a division with 64-bit dividend and 32-bit divisor.
31 *
32 * Note: Calling convention is totally non standard for optimal code.
33 * This is meant to be used by do_div() from include/asm/div64.h only.
34 *
35 * Input parameters:
36 * xh-xl = dividend (clobbered)
37 * r4 = divisor (preserved)
38 *
39 * Output values:
40 * yh-yl = result
41 * xh = remainder
42 *
43 * Clobbered regs: xl, ip
44 */
45
46ENTRY(__do_div64)
47
48 @ Test for easy paths first.
49 subs ip, r4, #1
50 bls 9f @ divisor is 0 or 1
51 tst ip, r4
52 beq 8f @ divisor is power of 2
53
54 @ See if we need to handle upper 32-bit result.
55 cmp xh, r4
56 mov yh, #0
57 blo 3f
58
59 @ Align divisor with upper part of dividend.
60 @ The aligned divisor is stored in yl preserving the original.
61 @ The bit position is stored in ip.
62
63#if __LINUX_ARM_ARCH__ >= 5
64
65 clz yl, r4
66 clz ip, xh
67 sub yl, yl, ip
68 mov ip, #1
69 mov ip, ip, lsl yl
70 mov yl, r4, lsl yl
71
72#else
73
74 mov yl, r4
75 mov ip, #1
761: cmp yl, #0x80000000
77 cmpcc yl, xh
78 movcc yl, yl, lsl #1
79 movcc ip, ip, lsl #1
80 bcc 1b
81
82#endif
83
84 @ The division loop for needed upper bit positions.
85 @ Break out early if dividend reaches 0.
862: cmp xh, yl
87 orrcs yh, yh, ip
88 subcss xh, xh, yl
89 movnes ip, ip, lsr #1
90 mov yl, yl, lsr #1
91 bne 2b
92
93 @ See if we need to handle lower 32-bit result.
943: cmp xh, #0
95 mov yl, #0
96 cmpeq xl, r4
97 movlo xh, xl
98 movlo pc, lr
99
100 @ The division loop for lower bit positions.
101 @ Here we shift remainer bits leftwards rather than moving the
102 @ divisor for comparisons, considering the carry-out bit as well.
103 mov ip, #0x80000000
1044: movs xl, xl, lsl #1
105 adcs xh, xh, xh
106 beq 6f
107 cmpcc xh, r4
1085: orrcs yl, yl, ip
109 subcs xh, xh, r4
110 movs ip, ip, lsr #1
111 bne 4b
112 mov pc, lr
113
114 @ The top part of remainder became zero. If carry is set
115 @ (the 33th bit) this is a false positive so resume the loop.
116 @ Otherwise, if lower part is also null then we are done.
1176: bcs 5b
118 cmp xl, #0
119 moveq pc, lr
120
121 @ We still have remainer bits in the low part. Bring them up.
122
123#if __LINUX_ARM_ARCH__ >= 5
124
125 clz xh, xl @ we know xh is zero here so...
126 add xh, xh, #1
127 mov xl, xl, lsl xh
128 mov ip, ip, lsr xh
129
130#else
131
1327: movs xl, xl, lsl #1
133 mov ip, ip, lsr #1
134 bcc 7b
135
136#endif
137
138 @ Current remainder is now 1. It is worthless to compare with
139 @ divisor at this point since divisor can not be smaller than 3 here.
140 @ If possible, branch for another shift in the division loop.
141 @ If no bit position left then we are done.
142 movs ip, ip, lsr #1
143 mov xh, #1
144 bne 4b
145 mov pc, lr
146
1478: @ Division by a power of 2: determine what that divisor order is
148 @ then simply shift values around
149
150#if __LINUX_ARM_ARCH__ >= 5
151
152 clz ip, r4
153 rsb ip, ip, #31
154
155#else
156
157 mov yl, r4
158 cmp r4, #(1 << 16)
159 mov ip, #0
160 movhs yl, yl, lsr #16
161 movhs ip, #16
162
163 cmp yl, #(1 << 8)
164 movhs yl, yl, lsr #8
165 addhs ip, ip, #8
166
167 cmp yl, #(1 << 4)
168 movhs yl, yl, lsr #4
169 addhs ip, ip, #4
170
171 cmp yl, #(1 << 2)
172 addhi ip, ip, #3
173 addls ip, ip, yl, lsr #1
174
175#endif
176
177 mov yh, xh, lsr ip
178 mov yl, xl, lsr ip
179 rsb ip, ip, #32
180 orr yl, yl, xh, lsl ip
181 mov xh, xl, lsl ip
182 mov xh, xh, lsr ip
183 mov pc, lr
184
185 @ eq -> division by 1: obvious enough...
1869: moveq yl, xl
187 moveq yh, xh
188 moveq xh, #0
189 moveq pc, lr
190
191 @ Division by 0:
192 str lr, [sp, #-4]!
193 bl __div0
194
195 @ as wrong as it could be...
196 mov yl, #0
197 mov yh, #0
198 mov xh, #0
199 ldr pc, [sp], #4
200
diff --git a/arch/arm/lib/ecard.S b/arch/arm/lib/ecard.S
new file mode 100644
index 000000000000..fb7b602a6f76
--- /dev/null
+++ b/arch/arm/lib/ecard.S
@@ -0,0 +1,45 @@
1/*
2 * linux/arch/arm/lib/ecard.S
3 *
4 * Copyright (C) 1995, 1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * 27/03/03 Ian Molton Clean up CONFIG_CPU
11 *
12 */
13#include <linux/linkage.h>
14#include <asm/assembler.h>
15#include <asm/hardware.h>
16
17#define CPSR2SPSR(rt) \
18 mrs rt, cpsr; \
19 msr spsr_cxsf, rt
20
21@ Purpose: call an expansion card loader to read bytes.
22@ Proto : char read_loader(int offset, char *card_base, char *loader);
23@ Returns: byte read
24
25ENTRY(ecard_loader_read)
26 stmfd sp!, {r4 - r12, lr}
27 mov r11, r1
28 mov r1, r0
29 CPSR2SPSR(r0)
30 mov lr, pc
31 mov pc, r2
32 LOADREGS(fd, sp!, {r4 - r12, pc})
33
34@ Purpose: call an expansion card loader to reset the card
35@ Proto : void read_loader(int card_base, char *loader);
36@ Returns: byte read
37
38ENTRY(ecard_loader_reset)
39 stmfd sp!, {r4 - r12, lr}
40 mov r11, r0
41 CPSR2SPSR(r0)
42 mov lr, pc
43 add pc, r1, #8
44 LOADREGS(fd, sp!, {r4 - r12, pc})
45
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
new file mode 100644
index 000000000000..f055d56ea68a
--- /dev/null
+++ b/arch/arm/lib/findbit.S
@@ -0,0 +1,168 @@
1/*
2 * linux/arch/arm/lib/findbit.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * 16th March 2001 - John Ripley <jripley@sonicblue.com>
11 * Fixed so that "size" is an exclusive not an inclusive quantity.
12 * All users of these functions expect exclusive sizes, and may
13 * also call with zero size.
14 * Reworked by rmk.
15 */
16#include <linux/linkage.h>
17#include <asm/assembler.h>
18 .text
19
20/*
21 * Purpose : Find a 'zero' bit
22 * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
23 */
24ENTRY(_find_first_zero_bit_le)
25 teq r1, #0
26 beq 3f
27 mov r2, #0
281: ldrb r3, [r0, r2, lsr #3]
29 eors r3, r3, #0xff @ invert bits
30 bne .found @ any now set - found zero bit
31 add r2, r2, #8 @ next bit pointer
322: cmp r2, r1 @ any more?
33 blo 1b
343: mov r0, r1 @ no free bits
35 RETINSTR(mov,pc,lr)
36
37/*
38 * Purpose : Find next 'zero' bit
39 * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
40 */
41ENTRY(_find_next_zero_bit_le)
42 teq r1, #0
43 beq 3b
44 ands ip, r2, #7
45 beq 1b @ If new byte, goto old routine
46 ldrb r3, [r0, r2, lsr #3]
47 eor r3, r3, #0xff @ now looking for a 1 bit
48 movs r3, r3, lsr ip @ shift off unused bits
49 bne .found
50 orr r2, r2, #7 @ if zero, then no bits here
51 add r2, r2, #1 @ align bit pointer
52 b 2b @ loop for next bit
53
54/*
55 * Purpose : Find a 'one' bit
56 * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
57 */
58ENTRY(_find_first_bit_le)
59 teq r1, #0
60 beq 3f
61 mov r2, #0
621: ldrb r3, [r0, r2, lsr #3]
63 movs r3, r3
64 bne .found @ any now set - found zero bit
65 add r2, r2, #8 @ next bit pointer
662: cmp r2, r1 @ any more?
67 blo 1b
683: mov r0, r1 @ no free bits
69 RETINSTR(mov,pc,lr)
70
71/*
72 * Purpose : Find next 'one' bit
73 * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
74 */
75ENTRY(_find_next_bit_le)
76 teq r1, #0
77 beq 3b
78 ands ip, r2, #7
79 beq 1b @ If new byte, goto old routine
80 ldrb r3, [r0, r2, lsr #3]
81 movs r3, r3, lsr ip @ shift off unused bits
82 bne .found
83 orr 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
87#ifdef __ARMEB__
88
89ENTRY(_find_first_zero_bit_be)
90 teq r1, #0
91 beq 3f
92 mov r2, #0
931: eor r3, r2, #0x18 @ big endian byte ordering
94 ldrb r3, [r0, r3, lsr #3]
95 eors r3, r3, #0xff @ invert bits
96 bne .found @ any now set - found zero bit
97 add r2, r2, #8 @ next bit pointer
982: cmp r2, r1 @ any more?
99 blo 1b
1003: mov r0, r1 @ no free bits
101 RETINSTR(mov,pc,lr)
102
103ENTRY(_find_next_zero_bit_be)
104 teq r1, #0
105 beq 3b
106 ands ip, r2, #7
107 beq 1b @ If new byte, goto old routine
108 eor r3, r2, #0x18 @ big endian byte ordering
109 ldrb r3, [r0, r3, lsr #3]
110 eor r3, r3, #0xff @ now looking for a 1 bit
111 movs r3, r3, lsr ip @ shift off unused bits
112 bne .found
113 orr r2, r2, #7 @ if zero, then no bits here
114 add r2, r2, #1 @ align bit pointer
115 b 2b @ loop for next bit
116
117ENTRY(_find_first_bit_be)
118 teq r1, #0
119 beq 3f
120 mov r2, #0
1211: eor r3, r2, #0x18 @ big endian byte ordering
122 ldrb r3, [r0, r3, lsr #3]
123 movs r3, r3
124 bne .found @ any now set - found zero bit
125 add r2, r2, #8 @ next bit pointer
1262: cmp r2, r1 @ any more?
127 blo 1b
1283: mov r0, r1 @ no free bits
129 RETINSTR(mov,pc,lr)
130
131ENTRY(_find_next_bit_be)
132 teq r1, #0
133 beq 3b
134 ands ip, r2, #7
135 beq 1b @ If new byte, goto old routine
136 eor r3, r2, #0x18 @ big endian byte ordering
137 ldrb r3, [r0, r3, lsr #3]
138 movs r3, r3, lsr ip @ shift off unused bits
139 bne .found
140 orr r2, r2, #7 @ if zero, then no bits here
141 add r2, r2, #1 @ align bit pointer
142 b 2b @ loop for next bit
143
144#endif
145
146/*
147 * One or more bits in the LSB of r3 are assumed to be set.
148 */
149.found:
150#if __LINUX_ARM_ARCH__ >= 5
151 rsb r1, r3, #0
152 and r3, r3, r1
153 clz r3, r3
154 rsb r3, r3, #31
155 add r0, r2, r3
156#else
157 tst r3, #0x0f
158 addeq r2, r2, #4
159 movne r3, r3, lsl #4
160 tst r3, #0x30
161 addeq r2, r2, #2
162 movne r3, r3, lsl #2
163 tst r3, #0x40
164 addeq r2, r2, #1
165 mov r0, r2
166#endif
167 RETINSTR(mov,pc,lr)
168
diff --git a/arch/arm/lib/floppydma.S b/arch/arm/lib/floppydma.S
new file mode 100644
index 000000000000..617150b1baef
--- /dev/null
+++ b/arch/arm/lib/floppydma.S
@@ -0,0 +1,32 @@
1/*
2 * linux/arch/arm/lib/floppydma.S
3 *
4 * Copyright (C) 1995, 1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12 .text
13
14 .global floppy_fiqin_end
15ENTRY(floppy_fiqin_start)
16 subs r9, r9, #1
17 ldrgtb r12, [r11, #-4]
18 ldrleb r12, [r11], #0
19 strb r12, [r10], #1
20 subs pc, lr, #4
21floppy_fiqin_end:
22
23 .global floppy_fiqout_end
24ENTRY(floppy_fiqout_start)
25 subs r9, r9, #1
26 ldrgeb r12, [r10], #1
27 movlt r12, #0
28 strleb r12, [r11], #0
29 subles pc, lr, #4
30 strb r12, [r11, #-4]
31 subs pc, lr, #4
32floppy_fiqout_end:
diff --git a/arch/arm/lib/gcclib.h b/arch/arm/lib/gcclib.h
new file mode 100644
index 000000000000..65314a3d9e27
--- /dev/null
+++ b/arch/arm/lib/gcclib.h
@@ -0,0 +1,25 @@
1/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
2/* I Molton 29/07/01 */
3
4#define BITS_PER_UNIT 8
5#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
6
7typedef unsigned int UQItype __attribute__ ((mode (QI)));
8typedef int SItype __attribute__ ((mode (SI)));
9typedef unsigned int USItype __attribute__ ((mode (SI)));
10typedef int DItype __attribute__ ((mode (DI)));
11typedef int word_type __attribute__ ((mode (__word__)));
12typedef unsigned int UDItype __attribute__ ((mode (DI)));
13
14#ifdef __ARMEB__
15 struct DIstruct {SItype high, low;};
16#else
17 struct DIstruct {SItype low, high;};
18#endif
19
20typedef union
21{
22 struct DIstruct s;
23 DItype ll;
24} DIunion;
25
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
new file mode 100644
index 000000000000..64aa6f4fe5e4
--- /dev/null
+++ b/arch/arm/lib/getuser.S
@@ -0,0 +1,78 @@
1/*
2 * linux/arch/arm/lib/getuser.S
3 *
4 * Copyright (C) 2001 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Idea from x86 version, (C) Copyright 1998 Linus Torvalds
11 *
12 * These functions have a non-standard call interface to make them more
13 * efficient, especially as they return an error value in addition to
14 * the "real" return value.
15 *
16 * __get_user_X
17 *
18 * Inputs: r0 contains the address
19 * Outputs: r0 is the error code
20 * r2, r3 contains the zero-extended value
21 * lr corrupted
22 *
23 * No other registers must be altered. (see include/asm-arm/uaccess.h
24 * for specific ASM register usage).
25 *
26 * Note that ADDR_LIMIT is either 0 or 0xc0000000.
27 * Note also that it is intended that __get_user_bad is not global.
28 */
29#include <asm/constants.h>
30#include <asm/thread_info.h>
31#include <asm/errno.h>
32
33 .global __get_user_1
34__get_user_1:
351: ldrbt r2, [r0]
36 mov r0, #0
37 mov pc, lr
38
39 .global __get_user_2
40__get_user_2:
412: ldrbt r2, [r0], #1
423: ldrbt r3, [r0]
43#ifndef __ARMEB__
44 orr r2, r2, r3, lsl #8
45#else
46 orr r2, r3, r2, lsl #8
47#endif
48 mov r0, #0
49 mov pc, lr
50
51 .global __get_user_4
52__get_user_4:
534: ldrt r2, [r0]
54 mov r0, #0
55 mov pc, lr
56
57 .global __get_user_8
58__get_user_8:
595: ldrt r2, [r0], #4
606: ldrt r3, [r0]
61 mov r0, #0
62 mov pc, lr
63
64__get_user_bad_8:
65 mov r3, #0
66__get_user_bad:
67 mov r2, #0
68 mov r0, #-EFAULT
69 mov pc, lr
70
71.section __ex_table, "a"
72 .long 1b, __get_user_bad
73 .long 2b, __get_user_bad
74 .long 3b, __get_user_bad
75 .long 4b, __get_user_bad
76 .long 5b, __get_user_bad_8
77 .long 6b, __get_user_bad_8
78.previous
diff --git a/arch/arm/lib/io-acorn.S b/arch/arm/lib/io-acorn.S
new file mode 100644
index 000000000000..3aacd01d40e1
--- /dev/null
+++ b/arch/arm/lib/io-acorn.S
@@ -0,0 +1,32 @@
1/*
2 * linux/arch/arm/lib/io-acorn.S
3 *
4 * Copyright (C) 1995, 1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * 27/03/03 Ian Molton Clean up CONFIG_CPU
11 *
12 */
13#include <linux/linkage.h>
14#include <asm/assembler.h>
15#include <asm/hardware.h>
16
17 .text
18 .align
19
20.iosl_warning:
21 .ascii "<4>insl/outsl not implemented, called from %08lX\0"
22 .align
23
24/*
25 * These make no sense on Acorn machines.
26 * Print a warning message.
27 */
28ENTRY(insl)
29ENTRY(outsl)
30 adr r0, .iosl_warning
31 mov r1, lr
32 b printk
diff --git a/arch/arm/lib/io-readsb.S b/arch/arm/lib/io-readsb.S
new file mode 100644
index 000000000000..081ef749298a
--- /dev/null
+++ b/arch/arm/lib/io-readsb.S
@@ -0,0 +1,122 @@
1/*
2 * linux/arch/arm/lib/io-readsb.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12
13.insb_align: rsb ip, ip, #4
14 cmp ip, r2
15 movgt ip, r2
16 cmp ip, #2
17 ldrb r3, [r0]
18 strb r3, [r1], #1
19 ldrgeb r3, [r0]
20 strgeb r3, [r1], #1
21 ldrgtb r3, [r0]
22 strgtb r3, [r1], #1
23 subs r2, r2, ip
24 bne .insb_aligned
25
26ENTRY(__raw_readsb)
27 teq r2, #0 @ do we have to check for the zero len?
28 moveq pc, lr
29 ands ip, r1, #3
30 bne .insb_align
31
32.insb_aligned: stmfd sp!, {r4 - r6, lr}
33
34 subs r2, r2, #16
35 bmi .insb_no_16
36
37.insb_16_lp: ldrb r3, [r0]
38 ldrb r4, [r0]
39 ldrb r5, [r0]
40 mov r3, r3, put_byte_0
41 ldrb r6, [r0]
42 orr r3, r3, r4, put_byte_1
43 ldrb r4, [r0]
44 orr r3, r3, r5, put_byte_2
45 ldrb r5, [r0]
46 orr r3, r3, r6, put_byte_3
47 ldrb r6, [r0]
48 mov r4, r4, put_byte_0
49 ldrb ip, [r0]
50 orr r4, r4, r5, put_byte_1
51 ldrb r5, [r0]
52 orr r4, r4, r6, put_byte_2
53 ldrb r6, [r0]
54 orr r4, r4, ip, put_byte_3
55 ldrb ip, [r0]
56 mov r5, r5, put_byte_0
57 ldrb lr, [r0]
58 orr r5, r5, r6, put_byte_1
59 ldrb r6, [r0]
60 orr r5, r5, ip, put_byte_2
61 ldrb ip, [r0]
62 orr r5, r5, lr, put_byte_3
63 ldrb lr, [r0]
64 mov r6, r6, put_byte_0
65 orr r6, r6, ip, put_byte_1
66 ldrb ip, [r0]
67 orr r6, r6, lr, put_byte_2
68 orr r6, r6, ip, put_byte_3
69 stmia r1!, {r3 - r6}
70
71 subs r2, r2, #16
72 bpl .insb_16_lp
73
74 tst r2, #15
75 LOADREGS(eqfd, sp!, {r4 - r6, pc})
76
77.insb_no_16: tst r2, #8
78 beq .insb_no_8
79
80 ldrb r3, [r0]
81 ldrb r4, [r0]
82 ldrb r5, [r0]
83 mov r3, r3, put_byte_0
84 ldrb r6, [r0]
85 orr r3, r3, r4, put_byte_1
86 ldrb r4, [r0]
87 orr r3, r3, r5, put_byte_2
88 ldrb r5, [r0]
89 orr r3, r3, r6, put_byte_3
90 ldrb r6, [r0]
91 mov r4, r4, put_byte_0
92 ldrb ip, [r0]
93 orr r4, r4, r5, put_byte_1
94 orr r4, r4, r6, put_byte_2
95 orr r4, r4, ip, put_byte_3
96 stmia r1!, {r3, r4}
97
98.insb_no_8: tst r2, #4
99 beq .insb_no_4
100
101 ldrb r3, [r0]
102 ldrb r4, [r0]
103 ldrb r5, [r0]
104 ldrb r6, [r0]
105 mov r3, r3, put_byte_0
106 orr r3, r3, r4, put_byte_1
107 orr r3, r3, r5, put_byte_2
108 orr r3, r3, r6, put_byte_3
109 str r3, [r1], #4
110
111.insb_no_4: ands r2, r2, #3
112 LOADREGS(eqfd, sp!, {r4 - r6, pc})
113
114 cmp r2, #2
115 ldrb r3, [r0]
116 strb r3, [r1], #1
117 ldrgeb r3, [r0]
118 strgeb r3, [r1], #1
119 ldrgtb r3, [r0]
120 strgtb r3, [r1]
121
122 LOADREGS(fd, sp!, {r4 - r6, pc})
diff --git a/arch/arm/lib/io-readsl.S b/arch/arm/lib/io-readsl.S
new file mode 100644
index 000000000000..75a9121cb23f
--- /dev/null
+++ b/arch/arm/lib/io-readsl.S
@@ -0,0 +1,78 @@
1/*
2 * linux/arch/arm/lib/io-readsl.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12
13ENTRY(__raw_readsl)
14 teq r2, #0 @ do we have to check for the zero len?
15 moveq pc, lr
16 ands ip, r1, #3
17 bne 3f
18
19 subs r2, r2, #4
20 bmi 2f
21 stmfd sp!, {r4, lr}
221: ldr r3, [r0, #0]
23 ldr r4, [r0, #0]
24 ldr ip, [r0, #0]
25 ldr lr, [r0, #0]
26 subs r2, r2, #4
27 stmia r1!, {r3, r4, ip, lr}
28 bpl 1b
29 ldmfd sp!, {r4, lr}
302: movs r2, r2, lsl #31
31 ldrcs r3, [r0, #0]
32 ldrcs ip, [r0, #0]
33 stmcsia r1!, {r3, ip}
34 ldrne r3, [r0, #0]
35 strne r3, [r1, #0]
36 mov pc, lr
37
383: ldr r3, [r0]
39 cmp ip, #2
40 mov ip, r3, get_byte_0
41 strb ip, [r1], #1
42 bgt 6f
43 mov ip, r3, get_byte_1
44 strb ip, [r1], #1
45 beq 5f
46 mov ip, r3, get_byte_2
47 strb ip, [r1], #1
48
494: subs r2, r2, #1
50 mov ip, r3, pull #24
51 ldrne r3, [r0]
52 orrne ip, ip, r3, push #8
53 strne ip, [r1], #4
54 bne 4b
55 b 8f
56
575: subs r2, r2, #1
58 mov ip, r3, pull #16
59 ldrne r3, [r0]
60 orrne ip, ip, r3, push #16
61 strne ip, [r1], #4
62 bne 5b
63 b 7f
64
656: subs r2, r2, #1
66 mov ip, r3, pull #8
67 ldrne r3, [r0]
68 orrne ip, ip, r3, push #24
69 strne ip, [r1], #4
70 bne 6b
71
72 mov r3, ip, get_byte_2
73 strb r3, [r1, #2]
747: mov r3, ip, get_byte_1
75 strb r3, [r1, #1]
768: mov r3, ip, get_byte_0
77 strb r3, [r1, #0]
78 mov pc, lr
diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S
new file mode 100644
index 000000000000..476cf7f8a633
--- /dev/null
+++ b/arch/arm/lib/io-readsw-armv3.S
@@ -0,0 +1,107 @@
1/*
2 * linux/arch/arm/lib/io-readsw-armv3.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12#include <asm/hardware.h>
13
14.insw_bad_alignment:
15 adr r0, .insw_bad_align_msg
16 mov r2, lr
17 b panic
18.insw_bad_align_msg:
19 .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
20 .align
21
22.insw_align: tst r1, #1
23 bne .insw_bad_alignment
24
25 ldr r3, [r0]
26 strb r3, [r1], #1
27 mov r3, r3, lsr #8
28 strb r3, [r1], #1
29
30 subs r2, r2, #1
31 RETINSTR(moveq, pc, lr)
32
33ENTRY(__raw_readsw)
34 teq r2, #0 @ do we have to check for the zero len?
35 moveq pc, lr
36 tst r1, #3
37 bne .insw_align
38
39.insw_aligned: mov ip, #0xff
40 orr ip, ip, ip, lsl #8
41 stmfd sp!, {r4, r5, r6, lr}
42
43 subs r2, r2, #8
44 bmi .no_insw_8
45
46.insw_8_lp: ldr r3, [r0]
47 and r3, r3, ip
48 ldr r4, [r0]
49 orr r3, r3, r4, lsl #16
50
51 ldr r4, [r0]
52 and r4, r4, ip
53 ldr r5, [r0]
54 orr r4, r4, r5, lsl #16
55
56 ldr r5, [r0]
57 and r5, r5, ip
58 ldr r6, [r0]
59 orr r5, r5, r6, lsl #16
60
61 ldr r6, [r0]
62 and r6, r6, ip
63 ldr lr, [r0]
64 orr r6, r6, lr, lsl #16
65
66 stmia r1!, {r3 - r6}
67
68 subs r2, r2, #8
69 bpl .insw_8_lp
70
71 tst r2, #7
72 LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
73
74.no_insw_8: tst r2, #4
75 beq .no_insw_4
76
77 ldr r3, [r0]
78 and r3, r3, ip
79 ldr r4, [r0]
80 orr r3, r3, r4, lsl #16
81
82 ldr r4, [r0]
83 and r4, r4, ip
84 ldr r5, [r0]
85 orr r4, r4, r5, lsl #16
86
87 stmia r1!, {r3, r4}
88
89.no_insw_4: tst r2, #2
90 beq .no_insw_2
91
92 ldr r3, [r0]
93 and r3, r3, ip
94 ldr r4, [r0]
95 orr r3, r3, r4, lsl #16
96
97 str r3, [r1], #4
98
99.no_insw_2: tst r2, #1
100 ldrne r3, [r0]
101 strneb r3, [r1], #1
102 movne r3, r3, lsr #8
103 strneb r3, [r1]
104
105 LOADREGS(fd, sp!, {r4, r5, r6, pc})
106
107
diff --git a/arch/arm/lib/io-readsw-armv4.S b/arch/arm/lib/io-readsw-armv4.S
new file mode 100644
index 000000000000..c92b66ecbe86
--- /dev/null
+++ b/arch/arm/lib/io-readsw-armv4.S
@@ -0,0 +1,130 @@
1/*
2 * linux/arch/arm/lib/io-readsw-armv4.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12
13 .macro pack, rd, hw1, hw2
14#ifndef __ARMEB__
15 orr \rd, \hw1, \hw2, lsl #16
16#else
17 orr \rd, \hw2, \hw1, lsl #16
18#endif
19 .endm
20
21.insw_align: movs ip, r1, lsl #31
22 bne .insw_noalign
23 ldrh ip, [r0]
24 sub r2, r2, #1
25 strh ip, [r1], #2
26
27ENTRY(__raw_readsw)
28 teq r2, #0
29 moveq pc, lr
30 tst r1, #3
31 bne .insw_align
32
33 stmfd sp!, {r4, r5, lr}
34
35 subs r2, r2, #8
36 bmi .no_insw_8
37
38.insw_8_lp: ldrh r3, [r0]
39 ldrh r4, [r0]
40 pack r3, r3, r4
41
42 ldrh r4, [r0]
43 ldrh r5, [r0]
44 pack r4, r4, r5
45
46 ldrh r5, [r0]
47 ldrh ip, [r0]
48 pack r5, r5, ip
49
50 ldrh ip, [r0]
51 ldrh lr, [r0]
52 pack ip, ip, lr
53
54 subs r2, r2, #8
55 stmia r1!, {r3 - r5, ip}
56 bpl .insw_8_lp
57
58.no_insw_8: tst r2, #4
59 beq .no_insw_4
60
61 ldrh r3, [r0]
62 ldrh r4, [r0]
63 pack r3, r3, r4
64
65 ldrh r4, [r0]
66 ldrh ip, [r0]
67 pack r4, r4, ip
68
69 stmia r1!, {r3, r4}
70
71.no_insw_4: movs r2, r2, lsl #31
72 bcc .no_insw_2
73
74 ldrh r3, [r0]
75 ldrh ip, [r0]
76 pack r3, r3, ip
77 str r3, [r1], #4
78
79.no_insw_2: ldrneh r3, [r0]
80 strneh r3, [r1]
81
82 ldmfd sp!, {r4, r5, pc}
83
84#ifdef __ARMEB__
85#define _BE_ONLY_(code...) code
86#define _LE_ONLY_(code...)
87#define push_hbyte0 lsr #8
88#define pull_hbyte1 lsl #24
89#else
90#define _BE_ONLY_(code...)
91#define _LE_ONLY_(code...) code
92#define push_hbyte0 lsl #24
93#define pull_hbyte1 lsr #8
94#endif
95
96.insw_noalign: stmfd sp!, {r4, lr}
97 ldrccb ip, [r1, #-1]!
98 bcc 1f
99
100 ldrh ip, [r0]
101 sub r2, r2, #1
102 _BE_ONLY_( mov ip, ip, ror #8 )
103 strb ip, [r1], #1
104 _LE_ONLY_( mov ip, ip, lsr #8 )
105 _BE_ONLY_( mov ip, ip, lsr #24 )
106
1071: subs r2, r2, #2
108 bmi 3f
109 _BE_ONLY_( mov ip, ip, lsl #24 )
110
1112: ldrh r3, [r0]
112 ldrh r4, [r0]
113 subs r2, r2, #2
114 orr ip, ip, r3, lsl #8
115 orr ip, ip, r4, push_hbyte0
116 str ip, [r1], #4
117 mov ip, r4, pull_hbyte1
118 bpl 2b
119
120 _BE_ONLY_( mov ip, ip, lsr #24 )
121
1223: tst r2, #1
123 strb ip, [r1], #1
124 ldrneh ip, [r0]
125 _BE_ONLY_( movne ip, ip, ror #8 )
126 strneb ip, [r1], #1
127 _LE_ONLY_( movne ip, ip, lsr #8 )
128 _BE_ONLY_( movne ip, ip, lsr #24 )
129 strneb ip, [r1]
130 ldmfd sp!, {r4, pc}
diff --git a/arch/arm/lib/io-shark.c b/arch/arm/lib/io-shark.c
new file mode 100644
index 000000000000..108d4573e970
--- /dev/null
+++ b/arch/arm/lib/io-shark.c
@@ -0,0 +1,83 @@
1/*
2 * linux/arch/arm/lib/io-shark.c
3 *
4 * by Alexander Schulz
5 *
6 * derived from:
7 * linux/arch/arm/lib/io-ebsa.S
8 * Copyright (C) 1995, 1996 Russell King
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14#include <linux/kernel.h>
15
16#include <asm/io.h>
17
18void print_warning(void)
19{
20 printk(KERN_WARNING "ins?/outs? not implemented on this architecture\n");
21}
22
23void insl(unsigned int port, void *to, int len)
24{
25 print_warning();
26}
27
28void insb(unsigned int port, void *to, int len)
29{
30 print_warning();
31}
32
33void outsl(unsigned int port, const void *from, int len)
34{
35 print_warning();
36}
37
38void outsb(unsigned int port, const void *from, int len)
39{
40 print_warning();
41}
42
43/* these should be in assembler again */
44
45/*
46 * Purpose: read a block of data from a hardware register to memory.
47 * Proto : insw(int from_port, void *to, int len_in_words);
48 * Proto : inswb(int from_port, void *to, int len_in_bytes);
49 * Notes : increment to
50 */
51
52void insw(unsigned int port, void *to, int len)
53{
54 int i;
55
56 for (i = 0; i < len; i++)
57 ((unsigned short *) to)[i] = inw(port);
58}
59
60void inswb(unsigned int port, void *to, int len)
61{
62 insw(port, to, len >> 2);
63}
64
65/*
66 * Purpose: write a block of data from memory to a hardware register.
67 * Proto : outsw(int to_reg, void *from, int len_in_words);
68 * Proto : outswb(int to_reg, void *from, int len_in_bytes);
69 * Notes : increments from
70 */
71
72void outsw(unsigned int port, const void *from, int len)
73{
74 int i;
75
76 for (i = 0; i < len; i++)
77 outw(((unsigned short *) from)[i], port);
78}
79
80void outswb(unsigned int port, const void *from, int len)
81{
82 outsw(port, from, len >> 2);
83}
diff --git a/arch/arm/lib/io-writesb.S b/arch/arm/lib/io-writesb.S
new file mode 100644
index 000000000000..70b2561bdb09
--- /dev/null
+++ b/arch/arm/lib/io-writesb.S
@@ -0,0 +1,92 @@
1/*
2 * linux/arch/arm/lib/io-writesb.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12
13 .macro outword, rd
14#ifndef __ARMEB__
15 strb \rd, [r0]
16 mov \rd, \rd, lsr #8
17 strb \rd, [r0]
18 mov \rd, \rd, lsr #8
19 strb \rd, [r0]
20 mov \rd, \rd, lsr #8
21 strb \rd, [r0]
22#else
23 mov lr, \rd, lsr #24
24 strb lr, [r0]
25 mov lr, \rd, lsr #16
26 strb lr, [r0]
27 mov lr, \rd, lsr #8
28 strb lr, [r0]
29 strb \rd, [r0]
30#endif
31 .endm
32
33.outsb_align: rsb ip, ip, #4
34 cmp ip, r2
35 movgt ip, r2
36 cmp ip, #2
37 ldrb r3, [r1], #1
38 strb r3, [r0]
39 ldrgeb r3, [r1], #1
40 strgeb r3, [r0]
41 ldrgtb r3, [r1], #1
42 strgtb r3, [r0]
43 subs r2, r2, ip
44 bne .outsb_aligned
45
46ENTRY(__raw_writesb)
47 teq r2, #0 @ do we have to check for the zero len?
48 moveq pc, lr
49 ands ip, r1, #3
50 bne .outsb_align
51
52.outsb_aligned: stmfd sp!, {r4, r5, lr}
53
54 subs r2, r2, #16
55 bmi .outsb_no_16
56
57.outsb_16_lp: ldmia r1!, {r3, r4, r5, ip}
58 outword r3
59 outword r4
60 outword r5
61 outword ip
62 subs r2, r2, #16
63 bpl .outsb_16_lp
64
65 tst r2, #15
66 LOADREGS(eqfd, sp!, {r4, r5, pc})
67
68.outsb_no_16: tst r2, #8
69 beq .outsb_no_8
70
71 ldmia r1!, {r3, r4}
72 outword r3
73 outword r4
74
75.outsb_no_8: tst r2, #4
76 beq .outsb_no_4
77
78 ldr r3, [r1], #4
79 outword r3
80
81.outsb_no_4: ands r2, r2, #3
82 LOADREGS(eqfd, sp!, {r4, r5, pc})
83
84 cmp r2, #2
85 ldrb r3, [r1], #1
86 strb r3, [r0]
87 ldrgeb r3, [r1], #1
88 strgeb r3, [r0]
89 ldrgtb r3, [r1]
90 strgtb r3, [r0]
91
92 LOADREGS(fd, sp!, {r4, r5, pc})
diff --git a/arch/arm/lib/io-writesl.S b/arch/arm/lib/io-writesl.S
new file mode 100644
index 000000000000..f8f14dd227ca
--- /dev/null
+++ b/arch/arm/lib/io-writesl.S
@@ -0,0 +1,66 @@
1/*
2 * linux/arch/arm/lib/io-writesl.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12
13ENTRY(__raw_writesl)
14 teq r2, #0 @ do we have to check for the zero len?
15 moveq pc, lr
16 ands ip, r1, #3
17 bne 3f
18
19 subs r2, r2, #4
20 bmi 2f
21 stmfd sp!, {r4, lr}
221: ldmia r1!, {r3, r4, ip, lr}
23 subs r2, r2, #4
24 str r3, [r0, #0]
25 str r4, [r0, #0]
26 str ip, [r0, #0]
27 str lr, [r0, #0]
28 bpl 1b
29 ldmfd sp!, {r4, lr}
302: movs r2, r2, lsl #31
31 ldmcsia r1!, {r3, ip}
32 strcs r3, [r0, #0]
33 ldrne r3, [r1, #0]
34 strcs ip, [r0, #0]
35 strne r3, [r0, #0]
36 mov pc, lr
37
383: bic r1, r1, #3
39 ldr r3, [r1], #4
40 cmp ip, #2
41 blt 5f
42 bgt 6f
43
444: mov ip, r3, pull #16
45 ldr r3, [r1], #4
46 subs r2, r2, #1
47 orr ip, ip, r3, push #16
48 str ip, [r0]
49 bne 4b
50 mov pc, lr
51
525: mov ip, r3, pull #8
53 ldr r3, [r1], #4
54 subs r2, r2, #1
55 orr ip, ip, r3, push #24
56 str ip, [r0]
57 bne 5b
58 mov pc, lr
59
606: mov ip, r3, pull #24
61 ldr r3, [r1], #4
62 subs r2, r2, #1
63 orr ip, ip, r3, push #8
64 str ip, [r0]
65 bne 6b
66 mov pc, lr
diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S
new file mode 100644
index 000000000000..950e7e310f1a
--- /dev/null
+++ b/arch/arm/lib/io-writesw-armv3.S
@@ -0,0 +1,127 @@
1/*
2 * linux/arch/arm/lib/io-writesw-armv3.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12#include <asm/hardware.h>
13
14.outsw_bad_alignment:
15 adr r0, .outsw_bad_align_msg
16 mov r2, lr
17 b panic
18.outsw_bad_align_msg:
19 .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n"
20 .align
21
22.outsw_align: tst r1, #1
23 bne .outsw_bad_alignment
24
25 add r1, r1, #2
26
27 ldr r3, [r1, #-4]
28 mov r3, r3, lsr #16
29 orr r3, r3, r3, lsl #16
30 str r3, [r0]
31 subs r2, r2, #1
32 RETINSTR(moveq, pc, lr)
33
34ENTRY(__raw_writesw)
35 teq r2, #0 @ do we have to check for the zero len?
36 moveq pc, lr
37 tst r1, #3
38 bne .outsw_align
39
40.outsw_aligned: stmfd sp!, {r4, r5, r6, lr}
41
42 subs r2, r2, #8
43 bmi .no_outsw_8
44
45.outsw_8_lp: ldmia r1!, {r3, r4, r5, r6}
46
47 mov ip, r3, lsl #16
48 orr ip, ip, ip, lsr #16
49 str ip, [r0]
50
51 mov ip, r3, lsr #16
52 orr ip, ip, ip, lsl #16
53 str ip, [r0]
54
55 mov ip, r4, lsl #16
56 orr ip, ip, ip, lsr #16
57 str ip, [r0]
58
59 mov ip, r4, lsr #16
60 orr ip, ip, ip, lsl #16
61 str ip, [r0]
62
63 mov ip, r5, lsl #16
64 orr ip, ip, ip, lsr #16
65 str ip, [r0]
66
67 mov ip, r5, lsr #16
68 orr ip, ip, ip, lsl #16
69 str ip, [r0]
70
71 mov ip, r6, lsl #16
72 orr ip, ip, ip, lsr #16
73 str ip, [r0]
74
75 mov ip, r6, lsr #16
76 orr ip, ip, ip, lsl #16
77 str ip, [r0]
78
79 subs r2, r2, #8
80 bpl .outsw_8_lp
81
82 tst r2, #7
83 LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
84
85.no_outsw_8: tst r2, #4
86 beq .no_outsw_4
87
88 ldmia r1!, {r3, r4}
89
90 mov ip, r3, lsl #16
91 orr ip, ip, ip, lsr #16
92 str ip, [r0]
93
94 mov ip, r3, lsr #16
95 orr ip, ip, ip, lsl #16
96 str ip, [r0]
97
98 mov ip, r4, lsl #16
99 orr ip, ip, ip, lsr #16
100 str ip, [r0]
101
102 mov ip, r4, lsr #16
103 orr ip, ip, ip, lsl #16
104 str ip, [r0]
105
106.no_outsw_4: tst r2, #2
107 beq .no_outsw_2
108
109 ldr r3, [r1], #4
110
111 mov ip, r3, lsl #16
112 orr ip, ip, ip, lsr #16
113 str ip, [r0]
114
115 mov ip, r3, lsr #16
116 orr ip, ip, ip, lsl #16
117 str ip, [r0]
118
119.no_outsw_2: tst r2, #1
120
121 ldrne r3, [r1]
122
123 movne ip, r3, lsl #16
124 orrne ip, ip, ip, lsr #16
125 strne ip, [r0]
126
127 LOADREGS(fd, sp!, {r4, r5, r6, pc})
diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S
new file mode 100644
index 000000000000..6d1d7c27806e
--- /dev/null
+++ b/arch/arm/lib/io-writesw-armv4.S
@@ -0,0 +1,95 @@
1/*
2 * linux/arch/arm/lib/io-writesw-armv4.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12
13 .macro outword, rd
14#ifndef __ARMEB__
15 strh \rd, [r0]
16 mov \rd, \rd, lsr #16
17 strh \rd, [r0]
18#else
19 mov lr, \rd, lsr #16
20 strh lr, [r0]
21 strh \rd, [r0]
22#endif
23 .endm
24
25.outsw_align: movs ip, r1, lsl #31
26 bne .outsw_noalign
27
28 ldrh r3, [r1], #2
29 sub r2, r2, #1
30 strh r3, [r0]
31
32ENTRY(__raw_writesw)
33 teq r2, #0
34 moveq pc, lr
35 ands r3, r1, #3
36 bne .outsw_align
37
38 stmfd sp!, {r4, r5, lr}
39
40 subs r2, r2, #8
41 bmi .no_outsw_8
42
43.outsw_8_lp: ldmia r1!, {r3, r4, r5, ip}
44 subs r2, r2, #8
45 outword r3
46 outword r4
47 outword r5
48 outword ip
49 bpl .outsw_8_lp
50
51.no_outsw_8: tst r2, #4
52 beq .no_outsw_4
53
54 ldmia r1!, {r3, ip}
55 outword r3
56 outword ip
57
58.no_outsw_4: movs r2, r2, lsl #31
59 bcc .no_outsw_2
60
61 ldr r3, [r1], #4
62 outword r3
63
64.no_outsw_2: ldrneh r3, [r1]
65 strneh r3, [r0]
66
67 ldmfd sp!, {r4, r5, pc}
68
69#ifdef __ARMEB__
70#define pull_hbyte0 lsl #8
71#define push_hbyte1 lsr #24
72#else
73#define pull_hbyte0 lsr #24
74#define push_hbyte1 lsl #8
75#endif
76
77.outsw_noalign: ldr r3, [r1, -r3]!
78 subcs r2, r2, #1
79 bcs 2f
80 subs r2, r2, #2
81 bmi 3f
82
831: mov ip, r3, lsr #8
84 strh ip, [r0]
852: mov ip, r3, pull_hbyte0
86 ldr r3, [r1, #4]!
87 subs r2, r2, #2
88 orr ip, ip, r3, push_hbyte1
89 strh ip, [r0]
90 bpl 2b
91
923: tst r2, #1
932: movne ip, r3, lsr #8
94 strneh ip, [r0]
95 mov pc, lr
diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S
new file mode 100644
index 000000000000..59026029d017
--- /dev/null
+++ b/arch/arm/lib/lib1funcs.S
@@ -0,0 +1,314 @@
1/*
2 * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
3 *
4 * Author: Nicolas Pitre <nico@cam.org>
5 * - contributed to gcc-3.4 on Sep 30, 2003
6 * - adapted for the Linux kernel on Oct 2, 2003
7 */
8
9/* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
10
11This file is free software; you can redistribute it and/or modify it
12under the terms of the GNU General Public License as published by the
13Free Software Foundation; either version 2, or (at your option) any
14later version.
15
16In addition to the permissions in the GNU General Public License, the
17Free Software Foundation gives you unlimited permission to link the
18compiled version of this file into combinations with other programs,
19and to distribute those combinations without any restriction coming
20from the use of this file. (The General Public License restrictions
21do apply in other respects; for example, they cover modification of
22the file, and distribution when not linked into a combine
23executable.)
24
25This file is distributed in the hope that it will be useful, but
26WITHOUT ANY WARRANTY; without even the implied warranty of
27MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28General Public License for more details.
29
30You should have received a copy of the GNU General Public License
31along with this program; see the file COPYING. If not, write to
32the Free Software Foundation, 59 Temple Place - Suite 330,
33Boston, MA 02111-1307, USA. */
34
35
36#include <linux/linkage.h>
37#include <asm/assembler.h>
38
39
40.macro ARM_DIV_BODY dividend, divisor, result, curbit
41
42#if __LINUX_ARM_ARCH__ >= 5
43
44 clz \curbit, \divisor
45 clz \result, \dividend
46 sub \result, \curbit, \result
47 mov \curbit, #1
48 mov \divisor, \divisor, lsl \result
49 mov \curbit, \curbit, lsl \result
50 mov \result, #0
51
52#else
53
54 @ Initially shift the divisor left 3 bits if possible,
55 @ set curbit accordingly. This allows for curbit to be located
56 @ at the left end of each 4 bit nibbles in the division loop
57 @ to save one loop in most cases.
58 tst \divisor, #0xe0000000
59 moveq \divisor, \divisor, lsl #3
60 moveq \curbit, #8
61 movne \curbit, #1
62
63 @ Unless the divisor is very big, shift it up in multiples of
64 @ four bits, since this is the amount of unwinding in the main
65 @ division loop. Continue shifting until the divisor is
66 @ larger than the dividend.
671: cmp \divisor, #0x10000000
68 cmplo \divisor, \dividend
69 movlo \divisor, \divisor, lsl #4
70 movlo \curbit, \curbit, lsl #4
71 blo 1b
72
73 @ For very big divisors, we must shift it a bit at a time, or
74 @ we will be in danger of overflowing.
751: cmp \divisor, #0x80000000
76 cmplo \divisor, \dividend
77 movlo \divisor, \divisor, lsl #1
78 movlo \curbit, \curbit, lsl #1
79 blo 1b
80
81 mov \result, #0
82
83#endif
84
85 @ Division loop
861: cmp \dividend, \divisor
87 subhs \dividend, \dividend, \divisor
88 orrhs \result, \result, \curbit
89 cmp \dividend, \divisor, lsr #1
90 subhs \dividend, \dividend, \divisor, lsr #1
91 orrhs \result, \result, \curbit, lsr #1
92 cmp \dividend, \divisor, lsr #2
93 subhs \dividend, \dividend, \divisor, lsr #2
94 orrhs \result, \result, \curbit, lsr #2
95 cmp \dividend, \divisor, lsr #3
96 subhs \dividend, \dividend, \divisor, lsr #3
97 orrhs \result, \result, \curbit, lsr #3
98 cmp \dividend, #0 @ Early termination?
99 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
100 movne \divisor, \divisor, lsr #4
101 bne 1b
102
103.endm
104
105
106.macro ARM_DIV2_ORDER divisor, order
107
108#if __LINUX_ARM_ARCH__ >= 5
109
110 clz \order, \divisor
111 rsb \order, \order, #31
112
113#else
114
115 cmp \divisor, #(1 << 16)
116 movhs \divisor, \divisor, lsr #16
117 movhs \order, #16
118 movlo \order, #0
119
120 cmp \divisor, #(1 << 8)
121 movhs \divisor, \divisor, lsr #8
122 addhs \order, \order, #8
123
124 cmp \divisor, #(1 << 4)
125 movhs \divisor, \divisor, lsr #4
126 addhs \order, \order, #4
127
128 cmp \divisor, #(1 << 2)
129 addhi \order, \order, #3
130 addls \order, \order, \divisor, lsr #1
131
132#endif
133
134.endm
135
136
137.macro ARM_MOD_BODY dividend, divisor, order, spare
138
139#if __LINUX_ARM_ARCH__ >= 5
140
141 clz \order, \divisor
142 clz \spare, \dividend
143 sub \order, \order, \spare
144 mov \divisor, \divisor, lsl \order
145
146#else
147
148 mov \order, #0
149
150 @ Unless the divisor is very big, shift it up in multiples of
151 @ four bits, since this is the amount of unwinding in the main
152 @ division loop. Continue shifting until the divisor is
153 @ larger than the dividend.
1541: cmp \divisor, #0x10000000
155 cmplo \divisor, \dividend
156 movlo \divisor, \divisor, lsl #4
157 addlo \order, \order, #4
158 blo 1b
159
160 @ For very big divisors, we must shift it a bit at a time, or
161 @ we will be in danger of overflowing.
1621: cmp \divisor, #0x80000000
163 cmplo \divisor, \dividend
164 movlo \divisor, \divisor, lsl #1
165 addlo \order, \order, #1
166 blo 1b
167
168#endif
169
170 @ Perform all needed substractions to keep only the reminder.
171 @ Do comparisons in batch of 4 first.
172 subs \order, \order, #3 @ yes, 3 is intended here
173 blt 2f
174
1751: cmp \dividend, \divisor
176 subhs \dividend, \dividend, \divisor
177 cmp \dividend, \divisor, lsr #1
178 subhs \dividend, \dividend, \divisor, lsr #1
179 cmp \dividend, \divisor, lsr #2
180 subhs \dividend, \dividend, \divisor, lsr #2
181 cmp \dividend, \divisor, lsr #3
182 subhs \dividend, \dividend, \divisor, lsr #3
183 cmp \dividend, #1
184 mov \divisor, \divisor, lsr #4
185 subges \order, \order, #4
186 bge 1b
187
188 tst \order, #3
189 teqne \dividend, #0
190 beq 5f
191
192 @ Either 1, 2 or 3 comparison/substractions are left.
1932: cmn \order, #2
194 blt 4f
195 beq 3f
196 cmp \dividend, \divisor
197 subhs \dividend, \dividend, \divisor
198 mov \divisor, \divisor, lsr #1
1993: cmp \dividend, \divisor
200 subhs \dividend, \dividend, \divisor
201 mov \divisor, \divisor, lsr #1
2024: cmp \dividend, \divisor
203 subhs \dividend, \dividend, \divisor
2045:
205.endm
206
207
208ENTRY(__udivsi3)
209
210 subs r2, r1, #1
211 moveq pc, lr
212 bcc Ldiv0
213 cmp r0, r1
214 bls 11f
215 tst r1, r2
216 beq 12f
217
218 ARM_DIV_BODY r0, r1, r2, r3
219
220 mov r0, r2
221 mov pc, lr
222
22311: moveq r0, #1
224 movne r0, #0
225 mov pc, lr
226
22712: ARM_DIV2_ORDER r1, r2
228
229 mov r0, r0, lsr r2
230 mov pc, lr
231
232
233ENTRY(__umodsi3)
234
235 subs r2, r1, #1 @ compare divisor with 1
236 bcc Ldiv0
237 cmpne r0, r1 @ compare dividend with divisor
238 moveq r0, #0
239 tsthi r1, r2 @ see if divisor is power of 2
240 andeq r0, r0, r2
241 movls pc, lr
242
243 ARM_MOD_BODY r0, r1, r2, r3
244
245 mov pc, lr
246
247
248ENTRY(__divsi3)
249
250 cmp r1, #0
251 eor ip, r0, r1 @ save the sign of the result.
252 beq Ldiv0
253 rsbmi r1, r1, #0 @ loops below use unsigned.
254 subs r2, r1, #1 @ division by 1 or -1 ?
255 beq 10f
256 movs r3, r0
257 rsbmi r3, r0, #0 @ positive dividend value
258 cmp r3, r1
259 bls 11f
260 tst r1, r2 @ divisor is power of 2 ?
261 beq 12f
262
263 ARM_DIV_BODY r3, r1, r0, r2
264
265 cmp ip, #0
266 rsbmi r0, r0, #0
267 mov pc, lr
268
26910: teq ip, r0 @ same sign ?
270 rsbmi r0, r0, #0
271 mov pc, lr
272
27311: movlo r0, #0
274 moveq r0, ip, asr #31
275 orreq r0, r0, #1
276 mov pc, lr
277
27812: ARM_DIV2_ORDER r1, r2
279
280 cmp ip, #0
281 mov r0, r3, lsr r2
282 rsbmi r0, r0, #0
283 mov pc, lr
284
285
286ENTRY(__modsi3)
287
288 cmp r1, #0
289 beq Ldiv0
290 rsbmi r1, r1, #0 @ loops below use unsigned.
291 movs ip, r0 @ preserve sign of dividend
292 rsbmi r0, r0, #0 @ if negative make positive
293 subs r2, r1, #1 @ compare divisor with 1
294 cmpne r0, r1 @ compare dividend with divisor
295 moveq r0, #0
296 tsthi r1, r2 @ see if divisor is power of 2
297 andeq r0, r0, r2
298 bls 10f
299
300 ARM_MOD_BODY r0, r1, r2, r3
301
30210: cmp ip, #0
303 rsbmi r0, r0, #0
304 mov pc, lr
305
306
307Ldiv0:
308
309 str lr, [sp, #-4]!
310 bl __div0
311 mov r0, #0 @ About as wrong as it could be.
312 ldr pc, [sp], #4
313
314
diff --git a/arch/arm/lib/longlong.h b/arch/arm/lib/longlong.h
new file mode 100644
index 000000000000..179eea4edc35
--- /dev/null
+++ b/arch/arm/lib/longlong.h
@@ -0,0 +1,183 @@
1/* longlong.h -- based on code from gcc-2.95.3
2
3 definitions for mixed size 32/64 bit arithmetic.
4 Copyright (C) 1991, 92, 94, 95, 96, 1997, 1998 Free Software Foundation, Inc.
5
6 This definition file is free software; you can redistribute it
7 and/or modify it under the terms of the GNU General Public
8 License as published by the Free Software Foundation; either
9 version 2, or (at your option) any later version.
10
11 This definition file is distributed in the hope that it will be
12 useful, but WITHOUT ANY WARRANTY; without even the implied
13 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21/* Borrowed from GCC 2.95.3, I Molton 29/07/01 */
22
23#ifndef SI_TYPE_SIZE
24#define SI_TYPE_SIZE 32
25#endif
26
27#define __BITS4 (SI_TYPE_SIZE / 4)
28#define __ll_B (1L << (SI_TYPE_SIZE / 2))
29#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
30#define __ll_highpart(t) ((USItype) (t) / __ll_B)
31
32/* Define auxiliary asm macros.
33
34 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
35 multiplies two USItype integers MULTIPLER and MULTIPLICAND,
36 and generates a two-part USItype product in HIGH_PROD and
37 LOW_PROD.
38
39 2) __umulsidi3(a,b) multiplies two USItype integers A and B,
40 and returns a UDItype product. This is just a variant of umul_ppmm.
41
42 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
43 denominator) divides a two-word unsigned integer, composed by the
44 integers HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and
45 places the quotient in QUOTIENT and the remainder in REMAINDER.
46 HIGH_NUMERATOR must be less than DENOMINATOR for correct operation.
47 If, in addition, the most significant bit of DENOMINATOR must be 1,
48 then the pre-processor symbol UDIV_NEEDS_NORMALIZATION is defined to 1.
49
50 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
51 denominator). Like udiv_qrnnd but the numbers are signed. The
52 quotient is rounded towards 0.
53
54 5) count_leading_zeros(count, x) counts the number of zero-bits from
55 the msb to the first non-zero bit. This is the number of steps X
56 needs to be shifted left to set the msb. Undefined for X == 0.
57
58 6) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
59 high_addend_2, low_addend_2) adds two two-word unsigned integers,
60 composed by HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and
61 LOW_ADDEND_2 respectively. The result is placed in HIGH_SUM and
62 LOW_SUM. Overflow (i.e. carry out) is not stored anywhere, and is
63 lost.
64
65 7) sub_ddmmss(high_difference, low_difference, high_minuend,
66 low_minuend, high_subtrahend, low_subtrahend) subtracts two
67 two-word unsigned integers, composed by HIGH_MINUEND_1 and
68 LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and LOW_SUBTRAHEND_2
69 respectively. The result is placed in HIGH_DIFFERENCE and
70 LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
71 and is lost.
72
73 If any of these macros are left undefined for a particular CPU,
74 C macros are used. */
75
76#if defined (__arm__)
77#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
78 __asm__ ("adds %1, %4, %5 \n\
79 adc %0, %2, %3" \
80 : "=r" ((USItype) (sh)), \
81 "=&r" ((USItype) (sl)) \
82 : "%r" ((USItype) (ah)), \
83 "rI" ((USItype) (bh)), \
84 "%r" ((USItype) (al)), \
85 "rI" ((USItype) (bl)))
86#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
87 __asm__ ("subs %1, %4, %5 \n\
88 sbc %0, %2, %3" \
89 : "=r" ((USItype) (sh)), \
90 "=&r" ((USItype) (sl)) \
91 : "r" ((USItype) (ah)), \
92 "rI" ((USItype) (bh)), \
93 "r" ((USItype) (al)), \
94 "rI" ((USItype) (bl)))
95#define umul_ppmm(xh, xl, a, b) \
96{register USItype __t0, __t1, __t2; \
97 __asm__ ("%@ Inlined umul_ppmm \n\
98 mov %2, %5, lsr #16 \n\
99 mov %0, %6, lsr #16 \n\
100 bic %3, %5, %2, lsl #16 \n\
101 bic %4, %6, %0, lsl #16 \n\
102 mul %1, %3, %4 \n\
103 mul %4, %2, %4 \n\
104 mul %3, %0, %3 \n\
105 mul %0, %2, %0 \n\
106 adds %3, %4, %3 \n\
107 addcs %0, %0, #65536 \n\
108 adds %1, %1, %3, lsl #16 \n\
109 adc %0, %0, %3, lsr #16" \
110 : "=&r" ((USItype) (xh)), \
111 "=r" ((USItype) (xl)), \
112 "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
113 : "r" ((USItype) (a)), \
114 "r" ((USItype) (b)));}
115#define UMUL_TIME 20
116#define UDIV_TIME 100
117#endif /* __arm__ */
118
119#define __umulsidi3(u, v) \
120 ({DIunion __w; \
121 umul_ppmm (__w.s.high, __w.s.low, u, v); \
122 __w.ll; })
123
124#define __udiv_qrnnd_c(q, r, n1, n0, d) \
125 do { \
126 USItype __d1, __d0, __q1, __q0; \
127 USItype __r1, __r0, __m; \
128 __d1 = __ll_highpart (d); \
129 __d0 = __ll_lowpart (d); \
130 \
131 __r1 = (n1) % __d1; \
132 __q1 = (n1) / __d1; \
133 __m = (USItype) __q1 * __d0; \
134 __r1 = __r1 * __ll_B | __ll_highpart (n0); \
135 if (__r1 < __m) \
136 { \
137 __q1--, __r1 += (d); \
138 if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
139 if (__r1 < __m) \
140 __q1--, __r1 += (d); \
141 } \
142 __r1 -= __m; \
143 \
144 __r0 = __r1 % __d1; \
145 __q0 = __r1 / __d1; \
146 __m = (USItype) __q0 * __d0; \
147 __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
148 if (__r0 < __m) \
149 { \
150 __q0--, __r0 += (d); \
151 if (__r0 >= (d)) \
152 if (__r0 < __m) \
153 __q0--, __r0 += (d); \
154 } \
155 __r0 -= __m; \
156 \
157 (q) = (USItype) __q1 * __ll_B | __q0; \
158 (r) = __r0; \
159 } while (0)
160
161#define UDIV_NEEDS_NORMALIZATION 1
162#define udiv_qrnnd __udiv_qrnnd_c
163
164#define count_leading_zeros(count, x) \
165 do { \
166 USItype __xr = (x); \
167 USItype __a; \
168 \
169 if (SI_TYPE_SIZE <= 32) \
170 { \
171 __a = __xr < ((USItype)1<<2*__BITS4) \
172 ? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4) \
173 : (__xr < ((USItype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
174 } \
175 else \
176 { \
177 for (__a = SI_TYPE_SIZE - 8; __a > 0; __a -= 8) \
178 if (((__xr >> __a) & 0xff) != 0) \
179 break; \
180 } \
181 \
182 (count) = SI_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
183 } while (0)
diff --git a/arch/arm/lib/lshrdi3.c b/arch/arm/lib/lshrdi3.c
new file mode 100644
index 000000000000..b666f1bad451
--- /dev/null
+++ b/arch/arm/lib/lshrdi3.c
@@ -0,0 +1,61 @@
1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
3/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22/* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License.
28 */
29/* support functions required by the kernel. based on code from gcc-2.95.3 */
30/* I Molton 29/07/01 */
31
32#include "gcclib.h"
33
34DItype
35__lshrdi3 (DItype u, word_type b)
36{
37 DIunion w;
38 word_type bm;
39 DIunion uu;
40
41 if (b == 0)
42 return u;
43
44 uu.ll = u;
45
46 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
47 if (bm <= 0)
48 {
49 w.s.high = 0;
50 w.s.low = (USItype)uu.s.high >> -bm;
51 }
52 else
53 {
54 USItype carries = (USItype)uu.s.high << bm;
55 w.s.high = (USItype)uu.s.high >> b;
56 w.s.low = ((USItype)uu.s.low >> b) | carries;
57 }
58
59 return w.ll;
60}
61
diff --git a/arch/arm/lib/memchr.S b/arch/arm/lib/memchr.S
new file mode 100644
index 000000000000..ac34fe55d21a
--- /dev/null
+++ b/arch/arm/lib/memchr.S
@@ -0,0 +1,25 @@
1/*
2 * linux/arch/arm/lib/memchr.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ASM optimised string functions
11 */
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14
15 .text
16 .align 5
17ENTRY(memchr)
181: subs r2, r2, #1
19 bmi 2f
20 ldrb r3, [r0], #1
21 teq r3, r1
22 bne 1b
23 sub r0, r0, #1
242: movne r0, #0
25 RETINSTR(mov,pc,lr)
diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S
new file mode 100644
index 000000000000..f5a593ceb8cc
--- /dev/null
+++ b/arch/arm/lib/memcpy.S
@@ -0,0 +1,393 @@
1/*
2 * linux/arch/arm/lib/memcpy.S
3 *
4 * Copyright (C) 1995-1999 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ASM optimised string functions
11 */
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14
15 .text
16
17#define ENTER \
18 mov ip,sp ;\
19 stmfd sp!,{r0,r4-r9,fp,ip,lr,pc} ;\
20 sub fp,ip,#4
21
22#define EXIT \
23 LOADREGS(ea, fp, {r0, r4 - r9, fp, sp, pc})
24
25#define EXITEQ \
26 LOADREGS(eqea, fp, {r0, r4 - r9, fp, sp, pc})
27
28/*
29 * Prototype: void memcpy(void *to,const void *from,unsigned long n);
30 */
31ENTRY(memcpy)
32ENTRY(memmove)
33 ENTER
34 cmp r1, r0
35 bcc 23f
36 subs r2, r2, #4
37 blt 6f
38 PLD( pld [r1, #0] )
39 ands ip, r0, #3
40 bne 7f
41 ands ip, r1, #3
42 bne 8f
43
441: subs r2, r2, #8
45 blt 5f
46 subs r2, r2, #20
47 blt 4f
48 PLD( pld [r1, #28] )
49 PLD( subs r2, r2, #64 )
50 PLD( blt 3f )
512: PLD( pld [r1, #60] )
52 PLD( pld [r1, #92] )
53 ldmia r1!, {r3 - r9, ip}
54 subs r2, r2, #32
55 stmgeia r0!, {r3 - r9, ip}
56 ldmgeia r1!, {r3 - r9, ip}
57 subges r2, r2, #32
58 stmia r0!, {r3 - r9, ip}
59 bge 2b
603: PLD( ldmia r1!, {r3 - r9, ip} )
61 PLD( adds r2, r2, #32 )
62 PLD( stmgeia r0!, {r3 - r9, ip} )
63 PLD( ldmgeia r1!, {r3 - r9, ip} )
64 PLD( subges r2, r2, #32 )
65 PLD( stmia r0!, {r3 - r9, ip} )
664: cmn r2, #16
67 ldmgeia r1!, {r3 - r6}
68 subge r2, r2, #16
69 stmgeia r0!, {r3 - r6}
70 adds r2, r2, #20
71 ldmgeia r1!, {r3 - r5}
72 subge r2, r2, #12
73 stmgeia r0!, {r3 - r5}
745: adds r2, r2, #8
75 blt 6f
76 subs r2, r2, #4
77 ldrlt r3, [r1], #4
78 ldmgeia r1!, {r4, r5}
79 subge r2, r2, #4
80 strlt r3, [r0], #4
81 stmgeia r0!, {r4, r5}
82
836: adds r2, r2, #4
84 EXITEQ
85 cmp r2, #2
86 ldrb r3, [r1], #1
87 ldrgeb r4, [r1], #1
88 ldrgtb r5, [r1], #1
89 strb r3, [r0], #1
90 strgeb r4, [r0], #1
91 strgtb r5, [r0], #1
92 EXIT
93
947: rsb ip, ip, #4
95 cmp ip, #2
96 ldrb r3, [r1], #1
97 ldrgeb r4, [r1], #1
98 ldrgtb r5, [r1], #1
99 strb r3, [r0], #1
100 strgeb r4, [r0], #1
101 strgtb r5, [r0], #1
102 subs r2, r2, ip
103 blt 6b
104 ands ip, r1, #3
105 beq 1b
106
1078: bic r1, r1, #3
108 ldr r7, [r1], #4
109 cmp ip, #2
110 bgt 18f
111 beq 13f
112 cmp r2, #12
113 blt 11f
114 PLD( pld [r1, #12] )
115 sub r2, r2, #12
116 PLD( subs r2, r2, #32 )
117 PLD( blt 10f )
118 PLD( pld [r1, #28] )
1199: PLD( pld [r1, #44] )
12010: mov r3, r7, pull #8
121 ldmia r1!, {r4 - r7}
122 subs r2, r2, #16
123 orr r3, r3, r4, push #24
124 mov r4, r4, pull #8
125 orr r4, r4, r5, push #24
126 mov r5, r5, pull #8
127 orr r5, r5, r6, push #24
128 mov r6, r6, pull #8
129 orr r6, r6, r7, push #24
130 stmia r0!, {r3 - r6}
131 bge 9b
132 PLD( cmn r2, #32 )
133 PLD( bge 10b )
134 PLD( add r2, r2, #32 )
135 adds r2, r2, #12
136 blt 12f
13711: mov r3, r7, pull #8
138 ldr r7, [r1], #4
139 subs r2, r2, #4
140 orr r3, r3, r7, push #24
141 str r3, [r0], #4
142 bge 11b
14312: sub r1, r1, #3
144 b 6b
145
14613: cmp r2, #12
147 blt 16f
148 PLD( pld [r1, #12] )
149 sub r2, r2, #12
150 PLD( subs r2, r2, #32 )
151 PLD( blt 15f )
152 PLD( pld [r1, #28] )
15314: PLD( pld [r1, #44] )
15415: mov r3, r7, pull #16
155 ldmia r1!, {r4 - r7}
156 subs r2, r2, #16
157 orr r3, r3, r4, push #16
158 mov r4, r4, pull #16
159 orr r4, r4, r5, push #16
160 mov r5, r5, pull #16
161 orr r5, r5, r6, push #16
162 mov r6, r6, pull #16
163 orr r6, r6, r7, push #16
164 stmia r0!, {r3 - r6}
165 bge 14b
166 PLD( cmn r2, #32 )
167 PLD( bge 15b )
168 PLD( add r2, r2, #32 )
169 adds r2, r2, #12
170 blt 17f
17116: mov r3, r7, pull #16
172 ldr r7, [r1], #4
173 subs r2, r2, #4
174 orr r3, r3, r7, push #16
175 str r3, [r0], #4
176 bge 16b
17717: sub r1, r1, #2
178 b 6b
179
18018: cmp r2, #12
181 blt 21f
182 PLD( pld [r1, #12] )
183 sub r2, r2, #12
184 PLD( subs r2, r2, #32 )
185 PLD( blt 20f )
186 PLD( pld [r1, #28] )
18719: PLD( pld [r1, #44] )
18820: mov r3, r7, pull #24
189 ldmia r1!, {r4 - r7}
190 subs r2, r2, #16
191 orr r3, r3, r4, push #8
192 mov r4, r4, pull #24
193 orr r4, r4, r5, push #8
194 mov r5, r5, pull #24
195 orr r5, r5, r6, push #8
196 mov r6, r6, pull #24
197 orr r6, r6, r7, push #8
198 stmia r0!, {r3 - r6}
199 bge 19b
200 PLD( cmn r2, #32 )
201 PLD( bge 20b )
202 PLD( add r2, r2, #32 )
203 adds r2, r2, #12
204 blt 22f
20521: mov r3, r7, pull #24
206 ldr r7, [r1], #4
207 subs r2, r2, #4
208 orr r3, r3, r7, push #8
209 str r3, [r0], #4
210 bge 21b
21122: sub r1, r1, #1
212 b 6b
213
214
21523: add r1, r1, r2
216 add r0, r0, r2
217 subs r2, r2, #4
218 blt 29f
219 PLD( pld [r1, #-4] )
220 ands ip, r0, #3
221 bne 30f
222 ands ip, r1, #3
223 bne 31f
224
22524: subs r2, r2, #8
226 blt 28f
227 subs r2, r2, #20
228 blt 27f
229 PLD( pld [r1, #-32] )
230 PLD( subs r2, r2, #64 )
231 PLD( blt 26f )
23225: PLD( pld [r1, #-64] )
233 PLD( pld [r1, #-96] )
234 ldmdb r1!, {r3 - r9, ip}
235 subs r2, r2, #32
236 stmgedb r0!, {r3 - r9, ip}
237 ldmgedb r1!, {r3 - r9, ip}
238 subges r2, r2, #32
239 stmdb r0!, {r3 - r9, ip}
240 bge 25b
24126: PLD( ldmdb r1!, {r3 - r9, ip} )
242 PLD( adds r2, r2, #32 )
243 PLD( stmgedb r0!, {r3 - r9, ip} )
244 PLD( ldmgedb r1!, {r3 - r9, ip} )
245 PLD( subges r2, r2, #32 )
246 PLD( stmdb r0!, {r3 - r9, ip} )
24727: cmn r2, #16
248 ldmgedb r1!, {r3 - r6}
249 subge r2, r2, #16
250 stmgedb r0!, {r3 - r6}
251 adds r2, r2, #20
252 ldmgedb r1!, {r3 - r5}
253 subge r2, r2, #12
254 stmgedb r0!, {r3 - r5}
25528: adds r2, r2, #8
256 blt 29f
257 subs r2, r2, #4
258 ldrlt r3, [r1, #-4]!
259 ldmgedb r1!, {r4, r5}
260 subge r2, r2, #4
261 strlt r3, [r0, #-4]!
262 stmgedb r0!, {r4, r5}
263
26429: adds r2, r2, #4
265 EXITEQ
266 cmp r2, #2
267 ldrb r3, [r1, #-1]!
268 ldrgeb r4, [r1, #-1]!
269 ldrgtb r5, [r1, #-1]!
270 strb r3, [r0, #-1]!
271 strgeb r4, [r0, #-1]!
272 strgtb r5, [r0, #-1]!
273 EXIT
274
27530: cmp ip, #2
276 ldrb r3, [r1, #-1]!
277 ldrgeb r4, [r1, #-1]!
278 ldrgtb r5, [r1, #-1]!
279 strb r3, [r0, #-1]!
280 strgeb r4, [r0, #-1]!
281 strgtb r5, [r0, #-1]!
282 subs r2, r2, ip
283 blt 29b
284 ands ip, r1, #3
285 beq 24b
286
28731: bic r1, r1, #3
288 ldr r3, [r1], #0
289 cmp ip, #2
290 blt 41f
291 beq 36f
292 cmp r2, #12
293 blt 34f
294 PLD( pld [r1, #-16] )
295 sub r2, r2, #12
296 PLD( subs r2, r2, #32 )
297 PLD( blt 33f )
298 PLD( pld [r1, #-32] )
29932: PLD( pld [r1, #-48] )
30033: mov r7, r3, push #8
301 ldmdb r1!, {r3, r4, r5, r6}
302 subs r2, r2, #16
303 orr r7, r7, r6, pull #24
304 mov r6, r6, push #8
305 orr r6, r6, r5, pull #24
306 mov r5, r5, push #8
307 orr r5, r5, r4, pull #24
308 mov r4, r4, push #8
309 orr r4, r4, r3, pull #24
310 stmdb r0!, {r4, r5, r6, r7}
311 bge 32b
312 PLD( cmn r2, #32 )
313 PLD( bge 33b )
314 PLD( add r2, r2, #32 )
315 adds r2, r2, #12
316 blt 35f
31734: mov ip, r3, push #8
318 ldr r3, [r1, #-4]!
319 subs r2, r2, #4
320 orr ip, ip, r3, pull #24
321 str ip, [r0, #-4]!
322 bge 34b
32335: add r1, r1, #3
324 b 29b
325
32636: cmp r2, #12
327 blt 39f
328 PLD( pld [r1, #-16] )
329 sub r2, r2, #12
330 PLD( subs r2, r2, #32 )
331 PLD( blt 38f )
332 PLD( pld [r1, #-32] )
33337: PLD( pld [r1, #-48] )
33438: mov r7, r3, push #16
335 ldmdb r1!, {r3, r4, r5, r6}
336 subs r2, r2, #16
337 orr r7, r7, r6, pull #16
338 mov r6, r6, push #16
339 orr r6, r6, r5, pull #16
340 mov r5, r5, push #16
341 orr r5, r5, r4, pull #16
342 mov r4, r4, push #16
343 orr r4, r4, r3, pull #16
344 stmdb r0!, {r4, r5, r6, r7}
345 bge 37b
346 PLD( cmn r2, #32 )
347 PLD( bge 38b )
348 PLD( add r2, r2, #32 )
349 adds r2, r2, #12
350 blt 40f
35139: mov ip, r3, push #16
352 ldr r3, [r1, #-4]!
353 subs r2, r2, #4
354 orr ip, ip, r3, pull #16
355 str ip, [r0, #-4]!
356 bge 39b
35740: add r1, r1, #2
358 b 29b
359
36041: cmp r2, #12
361 blt 44f
362 PLD( pld [r1, #-16] )
363 sub r2, r2, #12
364 PLD( subs r2, r2, #32 )
365 PLD( blt 43f )
366 PLD( pld [r1, #-32] )
36742: PLD( pld [r1, #-48] )
36843: mov r7, r3, push #24
369 ldmdb r1!, {r3, r4, r5, r6}
370 subs r2, r2, #16
371 orr r7, r7, r6, pull #8
372 mov r6, r6, push #24
373 orr r6, r6, r5, pull #8
374 mov r5, r5, push #24
375 orr r5, r5, r4, pull #8
376 mov r4, r4, push #24
377 orr r4, r4, r3, pull #8
378 stmdb r0!, {r4, r5, r6, r7}
379 bge 42b
380 PLD( cmn r2, #32 )
381 PLD( bge 43b )
382 PLD( add r2, r2, #32 )
383 adds r2, r2, #12
384 blt 45f
38544: mov ip, r3, push #24
386 ldr r3, [r1, #-4]!
387 subs r2, r2, #4
388 orr ip, ip, r3, pull #8
389 str ip, [r0, #-4]!
390 bge 44b
39145: add r1, r1, #1
392 b 29b
393
diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
new file mode 100644
index 000000000000..a1795f599937
--- /dev/null
+++ b/arch/arm/lib/memset.S
@@ -0,0 +1,80 @@
1/*
2 * linux/arch/arm/lib/memset.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ASM optimised string functions
11 */
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14
15 .text
16 .align 5
17 .word 0
18
191: subs r2, r2, #4 @ 1 do we have enough
20 blt 5f @ 1 bytes to align with?
21 cmp r3, #2 @ 1
22 strltb r1, [r0], #1 @ 1
23 strleb r1, [r0], #1 @ 1
24 strb r1, [r0], #1 @ 1
25 add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
26/*
27 * The pointer is now aligned and the length is adjusted. Try doing the
28 * memzero again.
29 */
30
31ENTRY(memset)
32 ands r3, r0, #3 @ 1 unaligned?
33 bne 1b @ 1
34/*
35 * we know that the pointer in r0 is aligned to a word boundary.
36 */
37 orr r1, r1, r1, lsl #8
38 orr r1, r1, r1, lsl #16
39 mov r3, r1
40 cmp r2, #16
41 blt 4f
42/*
43 * We need an extra register for this loop - save the return address and
44 * use the LR
45 */
46 str lr, [sp, #-4]!
47 mov ip, r1
48 mov lr, r1
49
502: subs r2, r2, #64
51 stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time.
52 stmgeia r0!, {r1, r3, ip, lr}
53 stmgeia r0!, {r1, r3, ip, lr}
54 stmgeia r0!, {r1, r3, ip, lr}
55 bgt 2b
56 LOADREGS(eqfd, sp!, {pc}) @ Now <64 bytes to go.
57/*
58 * No need to correct the count; we're only testing bits from now on
59 */
60 tst r2, #32
61 stmneia r0!, {r1, r3, ip, lr}
62 stmneia r0!, {r1, r3, ip, lr}
63 tst r2, #16
64 stmneia r0!, {r1, r3, ip, lr}
65 ldr lr, [sp], #4
66
674: tst r2, #8
68 stmneia r0!, {r1, r3}
69 tst r2, #4
70 strne r1, [r0], #4
71/*
72 * When we get here, we've got less than 4 bytes to zero. We
73 * may have an unaligned pointer as well.
74 */
755: tst r2, #2
76 strneb r1, [r0], #1
77 strneb r1, [r0], #1
78 tst r2, #1
79 strneb r1, [r0], #1
80 RETINSTR(mov,pc,lr)
diff --git a/arch/arm/lib/memzero.S b/arch/arm/lib/memzero.S
new file mode 100644
index 000000000000..51ccc60160fd
--- /dev/null
+++ b/arch/arm/lib/memzero.S
@@ -0,0 +1,80 @@
1/*
2 * linux/arch/arm/lib/memzero.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12
13 .text
14 .align 5
15 .word 0
16/*
17 * Align the pointer in r0. r3 contains the number of bytes that we are
18 * mis-aligned by, and r1 is the number of bytes. If r1 < 4, then we
19 * don't bother; we use byte stores instead.
20 */
211: subs r1, r1, #4 @ 1 do we have enough
22 blt 5f @ 1 bytes to align with?
23 cmp r3, #2 @ 1
24 strltb r2, [r0], #1 @ 1
25 strleb r2, [r0], #1 @ 1
26 strb r2, [r0], #1 @ 1
27 add r1, r1, r3 @ 1 (r1 = r1 - (4 - r3))
28/*
29 * The pointer is now aligned and the length is adjusted. Try doing the
30 * memzero again.
31 */
32
33ENTRY(__memzero)
34 mov r2, #0 @ 1
35 ands r3, r0, #3 @ 1 unaligned?
36 bne 1b @ 1
37/*
38 * r3 = 0, and we know that the pointer in r0 is aligned to a word boundary.
39 */
40 cmp r1, #16 @ 1 we can skip this chunk if we
41 blt 4f @ 1 have < 16 bytes
42/*
43 * We need an extra register for this loop - save the return address and
44 * use the LR
45 */
46 str lr, [sp, #-4]! @ 1
47 mov ip, r2 @ 1
48 mov lr, r2 @ 1
49
503: subs r1, r1, #64 @ 1 write 32 bytes out per loop
51 stmgeia r0!, {r2, r3, ip, lr} @ 4
52 stmgeia r0!, {r2, r3, ip, lr} @ 4
53 stmgeia r0!, {r2, r3, ip, lr} @ 4
54 stmgeia r0!, {r2, r3, ip, lr} @ 4
55 bgt 3b @ 1
56 LOADREGS(eqfd, sp!, {pc}) @ 1/2 quick exit
57/*
58 * No need to correct the count; we're only testing bits from now on
59 */
60 tst r1, #32 @ 1
61 stmneia r0!, {r2, r3, ip, lr} @ 4
62 stmneia r0!, {r2, r3, ip, lr} @ 4
63 tst r1, #16 @ 1 16 bytes or more?
64 stmneia r0!, {r2, r3, ip, lr} @ 4
65 ldr lr, [sp], #4 @ 1
66
674: tst r1, #8 @ 1 8 bytes or more?
68 stmneia r0!, {r2, r3} @ 2
69 tst r1, #4 @ 1 4 bytes or more?
70 strne r2, [r0], #4 @ 1
71/*
72 * When we get here, we've got less than 4 bytes to zero. We
73 * may have an unaligned pointer as well.
74 */
755: tst r1, #2 @ 1 2 bytes or more?
76 strneb r2, [r0], #1 @ 1
77 strneb r2, [r0], #1 @ 1
78 tst r1, #1 @ 1 a byte left over
79 strneb r2, [r0], #1 @ 1
80 RETINSTR(mov,pc,lr) @ 1
diff --git a/arch/arm/lib/muldi3.c b/arch/arm/lib/muldi3.c
new file mode 100644
index 000000000000..44d611b1cfdb
--- /dev/null
+++ b/arch/arm/lib/muldi3.c
@@ -0,0 +1,77 @@
1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
3/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22/* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License.
28 */
29/* support functions required by the kernel. based on code from gcc-2.95.3 */
30/* I Molton 29/07/01 */
31
32#include "gcclib.h"
33
34#define umul_ppmm(xh, xl, a, b) \
35{register USItype __t0, __t1, __t2; \
36 __asm__ ("%@ Inlined umul_ppmm \n\
37 mov %2, %5, lsr #16 \n\
38 mov %0, %6, lsr #16 \n\
39 bic %3, %5, %2, lsl #16 \n\
40 bic %4, %6, %0, lsl #16 \n\
41 mul %1, %3, %4 \n\
42 mul %4, %2, %4 \n\
43 mul %3, %0, %3 \n\
44 mul %0, %2, %0 \n\
45 adds %3, %4, %3 \n\
46 addcs %0, %0, #65536 \n\
47 adds %1, %1, %3, lsl #16 \n\
48 adc %0, %0, %3, lsr #16" \
49 : "=&r" ((USItype) (xh)), \
50 "=r" ((USItype) (xl)), \
51 "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
52 : "r" ((USItype) (a)), \
53 "r" ((USItype) (b)));}
54
55
56#define __umulsidi3(u, v) \
57 ({DIunion __w; \
58 umul_ppmm (__w.s.high, __w.s.low, u, v); \
59 __w.ll; })
60
61
62DItype
63__muldi3 (DItype u, DItype v)
64{
65 DIunion w;
66 DIunion uu, vv;
67
68 uu.ll = u,
69 vv.ll = v;
70
71 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
72 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
73 + (USItype) uu.s.high * (USItype) vv.s.low);
74
75 return w.ll;
76}
77
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
new file mode 100644
index 000000000000..b09398d95aac
--- /dev/null
+++ b/arch/arm/lib/putuser.S
@@ -0,0 +1,76 @@
1/*
2 * linux/arch/arm/lib/putuser.S
3 *
4 * Copyright (C) 2001 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Idea from x86 version, (C) Copyright 1998 Linus Torvalds
11 *
12 * These functions have a non-standard call interface to make
13 * them more efficient, especially as they return an error
14 * value in addition to the "real" return value.
15 *
16 * __put_user_X
17 *
18 * Inputs: r0 contains the address
19 * r2, r3 contains the value
20 * Outputs: r0 is the error code
21 * lr corrupted
22 *
23 * No other registers must be altered. (see include/asm-arm/uaccess.h
24 * for specific ASM register usage).
25 *
26 * Note that ADDR_LIMIT is either 0 or 0xc0000000
27 * Note also that it is intended that __put_user_bad is not global.
28 */
29#include <asm/constants.h>
30#include <asm/thread_info.h>
31#include <asm/errno.h>
32
33 .global __put_user_1
34__put_user_1:
351: strbt r2, [r0]
36 mov r0, #0
37 mov pc, lr
38
39 .global __put_user_2
40__put_user_2:
41 mov ip, r2, lsr #8
42#ifndef __ARMEB__
432: strbt r2, [r0], #1
443: strbt ip, [r0]
45#else
462: strbt ip, [r0], #1
473: strbt r2, [r0]
48#endif
49 mov r0, #0
50 mov pc, lr
51
52 .global __put_user_4
53__put_user_4:
544: strt r2, [r0]
55 mov r0, #0
56 mov pc, lr
57
58 .global __put_user_8
59__put_user_8:
605: strt r2, [r0], #4
616: strt r3, [r0]
62 mov r0, #0
63 mov pc, lr
64
65__put_user_bad:
66 mov r0, #-EFAULT
67 mov pc, lr
68
69.section __ex_table, "a"
70 .long 1b, __put_user_bad
71 .long 2b, __put_user_bad
72 .long 3b, __put_user_bad
73 .long 4b, __put_user_bad
74 .long 5b, __put_user_bad
75 .long 6b, __put_user_bad
76.previous
diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S
new file mode 100644
index 000000000000..8f337df5d99b
--- /dev/null
+++ b/arch/arm/lib/setbit.S
@@ -0,0 +1,29 @@
1/*
2 * linux/arch/arm/lib/setbit.S
3 *
4 * Copyright (C) 1995-1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12 .text
13
14/*
15 * Purpose : Function to set a bit
16 * Prototype: int set_bit(int bit, void *addr)
17 */
18ENTRY(_set_bit_be)
19 eor r0, r0, #0x18 @ big endian byte ordering
20ENTRY(_set_bit_le)
21 and r2, r0, #7
22 mov r3, #1
23 mov r3, r3, lsl r2
24 save_and_disable_irqs ip, r2
25 ldrb r2, [r1, r0, lsr #3]
26 orr r2, r2, r3
27 strb r2, [r1, r0, lsr #3]
28 restore_irqs ip
29 RETINSTR(mov,pc,lr)
diff --git a/arch/arm/lib/strchr.S b/arch/arm/lib/strchr.S
new file mode 100644
index 000000000000..5b9b493733fc
--- /dev/null
+++ b/arch/arm/lib/strchr.S
@@ -0,0 +1,26 @@
1/*
2 * linux/arch/arm/lib/strchr.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ASM optimised string functions
11 */
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14
15 .text
16 .align 5
17ENTRY(strchr)
18 and r1, r1, #0xff
191: ldrb r2, [r0], #1
20 teq r2, r1
21 teqne r2, #0
22 bne 1b
23 teq r2, r1
24 movne r0, #0
25 subeq r0, r0, #1
26 RETINSTR(mov,pc,lr)
diff --git a/arch/arm/lib/strncpy_from_user.S b/arch/arm/lib/strncpy_from_user.S
new file mode 100644
index 000000000000..629cc8775276
--- /dev/null
+++ b/arch/arm/lib/strncpy_from_user.S
@@ -0,0 +1,43 @@
1/*
2 * linux/arch/arm/lib/strncpy_from_user.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12#include <asm/errno.h>
13
14 .text
15 .align 5
16
17/*
18 * Copy a string from user space to kernel space.
19 * r0 = dst, r1 = src, r2 = byte length
20 * returns the number of characters copied (strlen of copied string),
21 * -EFAULT on exception, or "len" if we fill the whole buffer
22 */
23ENTRY(__arch_strncpy_from_user)
24 save_lr
25 mov ip, r1
261: subs r2, r2, #1
27USER( ldrplbt r3, [r1], #1)
28 bmi 2f
29 strb r3, [r0], #1
30 teq r3, #0
31 bne 1b
32 sub r1, r1, #1 @ take NUL character out of count
332: sub r0, r1, ip
34 restore_pc
35
36 .section .fixup,"ax"
37 .align 0
389001: mov r3, #0
39 strb r3, [r0, #0] @ null terminate
40 mov r0, #-EFAULT
41 restore_pc
42 .previous
43
diff --git a/arch/arm/lib/strnlen_user.S b/arch/arm/lib/strnlen_user.S
new file mode 100644
index 000000000000..67bcd8268128
--- /dev/null
+++ b/arch/arm/lib/strnlen_user.S
@@ -0,0 +1,40 @@
1/*
2 * linux/arch/arm/lib/strnlen_user.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12#include <asm/errno.h>
13
14 .text
15 .align 5
16
17/* Prototype: unsigned long __arch_strnlen_user(const char *str, long n)
18 * Purpose : get length of a string in user memory
19 * Params : str - address of string in user memory
20 * Returns : length of string *including terminator*
21 * or zero on exception, or n + 1 if too long
22 */
23ENTRY(__arch_strnlen_user)
24 save_lr
25 mov r2, r0
261:
27USER( ldrbt r3, [r0], #1)
28 teq r3, #0
29 beq 2f
30 subs r1, r1, #1
31 bne 1b
32 add r0, r0, #1
332: sub r0, r0, r2
34 restore_pc
35
36 .section .fixup,"ax"
37 .align 0
389001: mov r0, #0
39 restore_pc
40 .previous
diff --git a/arch/arm/lib/strrchr.S b/arch/arm/lib/strrchr.S
new file mode 100644
index 000000000000..fa923f026f15
--- /dev/null
+++ b/arch/arm/lib/strrchr.S
@@ -0,0 +1,25 @@
1/*
2 * linux/arch/arm/lib/strrchr.S
3 *
4 * Copyright (C) 1995-2000 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ASM optimised string functions
11 */
12#include <linux/linkage.h>
13#include <asm/assembler.h>
14
15 .text
16 .align 5
17ENTRY(strrchr)
18 mov r3, #0
191: ldrb r2, [r0], #1
20 teq r2, r1
21 subeq r3, r0, #1
22 teq r2, #0
23 bne 1b
24 mov r0, r3
25 RETINSTR(mov,pc,lr)
diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S
new file mode 100644
index 000000000000..4aba4676b984
--- /dev/null
+++ b/arch/arm/lib/testchangebit.S
@@ -0,0 +1,29 @@
1/*
2 * linux/arch/arm/lib/testchangebit.S
3 *
4 * Copyright (C) 1995-1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12 .text
13
14ENTRY(_test_and_change_bit_be)
15 eor r0, r0, #0x18 @ big endian byte ordering
16ENTRY(_test_and_change_bit_le)
17 add r1, r1, r0, lsr #3
18 and r3, r0, #7
19 mov r0, #1
20 save_and_disable_irqs ip, r2
21 ldrb r2, [r1]
22 tst r2, r0, lsl r3
23 eor r2, r2, r0, lsl r3
24 strb r2, [r1]
25 restore_irqs ip
26 moveq r0, #0
27 RETINSTR(mov,pc,lr)
28
29
diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S
new file mode 100644
index 000000000000..e07c5bd24307
--- /dev/null
+++ b/arch/arm/lib/testclearbit.S
@@ -0,0 +1,29 @@
1/*
2 * linux/arch/arm/lib/testclearbit.S
3 *
4 * Copyright (C) 1995-1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12 .text
13
14ENTRY(_test_and_clear_bit_be)
15 eor r0, r0, #0x18 @ big endian byte ordering
16ENTRY(_test_and_clear_bit_le)
17 add r1, r1, r0, lsr #3 @ Get byte offset
18 and r3, r0, #7 @ Get bit offset
19 mov r0, #1
20 save_and_disable_irqs ip, r2
21 ldrb r2, [r1]
22 tst r2, r0, lsl r3
23 bic r2, r2, r0, lsl r3
24 strb r2, [r1]
25 restore_irqs ip
26 moveq r0, #0
27 RETINSTR(mov,pc,lr)
28
29
diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S
new file mode 100644
index 000000000000..a570fc74cddd
--- /dev/null
+++ b/arch/arm/lib/testsetbit.S
@@ -0,0 +1,29 @@
1/*
2 * linux/arch/arm/lib/testsetbit.S
3 *
4 * Copyright (C) 1995-1996 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/linkage.h>
11#include <asm/assembler.h>
12 .text
13
14ENTRY(_test_and_set_bit_be)
15 eor r0, r0, #0x18 @ big endian byte ordering
16ENTRY(_test_and_set_bit_le)
17 add r1, r1, r0, lsr #3 @ Get byte offset
18 and r3, r0, #7 @ Get bit offset
19 mov r0, #1
20 save_and_disable_irqs ip, r2
21 ldrb r2, [r1]
22 tst r2, r0, lsl r3
23 orr r2, r2, r0, lsl r3
24 strb r2, [r1]
25 restore_irqs ip
26 moveq r0, #0
27 RETINSTR(mov,pc,lr)
28
29
diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S
new file mode 100644
index 000000000000..d3ed0636c008
--- /dev/null
+++ b/arch/arm/lib/uaccess.S
@@ -0,0 +1,697 @@
1/*
2 * linux/arch/arm/lib/uaccess.S
3 *
4 * Copyright (C) 1995, 1996,1997,1998 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Routines to block copy data to/from user memory
11 * These are highly optimised both for the 4k page size
12 * and for various alignments.
13 */
14#include <linux/linkage.h>
15#include <asm/assembler.h>
16#include <asm/errno.h>
17
18 .text
19
20#define PAGE_SHIFT 12
21
22/* Prototype: int __arch_copy_to_user(void *to, const char *from, size_t n)
23 * Purpose : copy a block to user memory from kernel memory
24 * Params : to - user memory
25 * : from - kernel memory
26 * : n - number of bytes to copy
27 * Returns : Number of bytes NOT copied.
28 */
29
30.c2u_dest_not_aligned:
31 rsb ip, ip, #4
32 cmp ip, #2
33 ldrb r3, [r1], #1
34USER( strbt r3, [r0], #1) @ May fault
35 ldrgeb r3, [r1], #1
36USER( strgebt r3, [r0], #1) @ May fault
37 ldrgtb r3, [r1], #1
38USER( strgtbt r3, [r0], #1) @ May fault
39 sub r2, r2, ip
40 b .c2u_dest_aligned
41
42ENTRY(__arch_copy_to_user)
43 stmfd sp!, {r2, r4 - r7, lr}
44 cmp r2, #4
45 blt .c2u_not_enough
46 PLD( pld [r1, #0] )
47 PLD( pld [r0, #0] )
48 ands ip, r0, #3
49 bne .c2u_dest_not_aligned
50.c2u_dest_aligned:
51
52 ands ip, r1, #3
53 bne .c2u_src_not_aligned
54/*
55 * Seeing as there has to be at least 8 bytes to copy, we can
56 * copy one word, and force a user-mode page fault...
57 */
58
59.c2u_0fupi: subs r2, r2, #4
60 addmi ip, r2, #4
61 bmi .c2u_0nowords
62 ldr r3, [r1], #4
63USER( strt r3, [r0], #4) @ May fault
64 mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
65 rsb ip, ip, #0
66 movs ip, ip, lsr #32 - PAGE_SHIFT
67 beq .c2u_0fupi
68/*
69 * ip = max no. of bytes to copy before needing another "strt" insn
70 */
71 cmp r2, ip
72 movlt ip, r2
73 sub r2, r2, ip
74 subs ip, ip, #32
75 blt .c2u_0rem8lp
76 PLD( pld [r1, #28] )
77 PLD( pld [r0, #28] )
78 PLD( subs ip, ip, #64 )
79 PLD( blt .c2u_0cpynopld )
80 PLD( pld [r1, #60] )
81 PLD( pld [r0, #60] )
82
83.c2u_0cpy8lp:
84 PLD( pld [r1, #92] )
85 PLD( pld [r0, #92] )
86.c2u_0cpynopld: ldmia r1!, {r3 - r6}
87 stmia r0!, {r3 - r6} @ Shouldnt fault
88 ldmia r1!, {r3 - r6}
89 subs ip, ip, #32
90 stmia r0!, {r3 - r6} @ Shouldnt fault
91 bpl .c2u_0cpy8lp
92 PLD( cmn ip, #64 )
93 PLD( bge .c2u_0cpynopld )
94 PLD( add ip, ip, #64 )
95
96.c2u_0rem8lp: cmn ip, #16
97 ldmgeia r1!, {r3 - r6}
98 stmgeia r0!, {r3 - r6} @ Shouldnt fault
99 tst ip, #8
100 ldmneia r1!, {r3 - r4}
101 stmneia r0!, {r3 - r4} @ Shouldnt fault
102 tst ip, #4
103 ldrne r3, [r1], #4
104 strnet r3, [r0], #4 @ Shouldnt fault
105 ands ip, ip, #3
106 beq .c2u_0fupi
107.c2u_0nowords: teq ip, #0
108 beq .c2u_finished
109.c2u_nowords: cmp ip, #2
110 ldrb r3, [r1], #1
111USER( strbt r3, [r0], #1) @ May fault
112 ldrgeb r3, [r1], #1
113USER( strgebt r3, [r0], #1) @ May fault
114 ldrgtb r3, [r1], #1
115USER( strgtbt r3, [r0], #1) @ May fault
116 b .c2u_finished
117
118.c2u_not_enough:
119 movs ip, r2
120 bne .c2u_nowords
121.c2u_finished: mov r0, #0
122 LOADREGS(fd,sp!,{r2, r4 - r7, pc})
123
124.c2u_src_not_aligned:
125 bic r1, r1, #3
126 ldr r7, [r1], #4
127 cmp ip, #2
128 bgt .c2u_3fupi
129 beq .c2u_2fupi
130.c2u_1fupi: subs r2, r2, #4
131 addmi ip, r2, #4
132 bmi .c2u_1nowords
133 mov r3, r7, pull #8
134 ldr r7, [r1], #4
135 orr r3, r3, r7, push #24
136USER( strt r3, [r0], #4) @ May fault
137 mov ip, r0, lsl #32 - PAGE_SHIFT
138 rsb ip, ip, #0
139 movs ip, ip, lsr #32 - PAGE_SHIFT
140 beq .c2u_1fupi
141 cmp r2, ip
142 movlt ip, r2
143 sub r2, r2, ip
144 subs ip, ip, #16
145 blt .c2u_1rem8lp
146 PLD( pld [r1, #12] )
147 PLD( pld [r0, #12] )
148 PLD( subs ip, ip, #32 )
149 PLD( blt .c2u_1cpynopld )
150 PLD( pld [r1, #28] )
151 PLD( pld [r0, #28] )
152
153.c2u_1cpy8lp:
154 PLD( pld [r1, #44] )
155 PLD( pld [r0, #44] )
156.c2u_1cpynopld: mov r3, r7, pull #8
157 ldmia r1!, {r4 - r7}
158 subs ip, ip, #16
159 orr r3, r3, r4, push #24
160 mov r4, r4, pull #8
161 orr r4, r4, r5, push #24
162 mov r5, r5, pull #8
163 orr r5, r5, r6, push #24
164 mov r6, r6, pull #8
165 orr r6, r6, r7, push #24
166 stmia r0!, {r3 - r6} @ Shouldnt fault
167 bpl .c2u_1cpy8lp
168 PLD( cmn ip, #32 )
169 PLD( bge .c2u_1cpynopld )
170 PLD( add ip, ip, #32 )
171
172.c2u_1rem8lp: tst ip, #8
173 movne r3, r7, pull #8
174 ldmneia r1!, {r4, r7}
175 orrne r3, r3, r4, push #24
176 movne r4, r4, pull #8
177 orrne r4, r4, r7, push #24
178 stmneia r0!, {r3 - r4} @ Shouldnt fault
179 tst ip, #4
180 movne r3, r7, pull #8
181 ldrne r7, [r1], #4
182 orrne r3, r3, r7, push #24
183 strnet r3, [r0], #4 @ Shouldnt fault
184 ands ip, ip, #3
185 beq .c2u_1fupi
186.c2u_1nowords: mov r3, r7, get_byte_1
187 teq ip, #0
188 beq .c2u_finished
189 cmp ip, #2
190USER( strbt r3, [r0], #1) @ May fault
191 movge r3, r7, get_byte_2
192USER( strgebt r3, [r0], #1) @ May fault
193 movgt r3, r7, get_byte_3
194USER( strgtbt r3, [r0], #1) @ May fault
195 b .c2u_finished
196
197.c2u_2fupi: subs r2, r2, #4
198 addmi ip, r2, #4
199 bmi .c2u_2nowords
200 mov r3, r7, pull #16
201 ldr r7, [r1], #4
202 orr r3, r3, r7, push #16
203USER( strt r3, [r0], #4) @ May fault
204 mov ip, r0, lsl #32 - PAGE_SHIFT
205 rsb ip, ip, #0
206 movs ip, ip, lsr #32 - PAGE_SHIFT
207 beq .c2u_2fupi
208 cmp r2, ip
209 movlt ip, r2
210 sub r2, r2, ip
211 subs ip, ip, #16
212 blt .c2u_2rem8lp
213 PLD( pld [r1, #12] )
214 PLD( pld [r0, #12] )
215 PLD( subs ip, ip, #32 )
216 PLD( blt .c2u_2cpynopld )
217 PLD( pld [r1, #28] )
218 PLD( pld [r0, #28] )
219
220.c2u_2cpy8lp:
221 PLD( pld [r1, #44] )
222 PLD( pld [r0, #44] )
223.c2u_2cpynopld: mov r3, r7, pull #16
224 ldmia r1!, {r4 - r7}
225 subs ip, ip, #16
226 orr r3, r3, r4, push #16
227 mov r4, r4, pull #16
228 orr r4, r4, r5, push #16
229 mov r5, r5, pull #16
230 orr r5, r5, r6, push #16
231 mov r6, r6, pull #16
232 orr r6, r6, r7, push #16
233 stmia r0!, {r3 - r6} @ Shouldnt fault
234 bpl .c2u_2cpy8lp
235 PLD( cmn ip, #32 )
236 PLD( bge .c2u_2cpynopld )
237 PLD( add ip, ip, #32 )
238
239.c2u_2rem8lp: tst ip, #8
240 movne r3, r7, pull #16
241 ldmneia r1!, {r4, r7}
242 orrne r3, r3, r4, push #16
243 movne r4, r4, pull #16
244 orrne r4, r4, r7, push #16
245 stmneia r0!, {r3 - r4} @ Shouldnt fault
246 tst ip, #4
247 movne r3, r7, pull #16
248 ldrne r7, [r1], #4
249 orrne r3, r3, r7, push #16
250 strnet r3, [r0], #4 @ Shouldnt fault
251 ands ip, ip, #3
252 beq .c2u_2fupi
253.c2u_2nowords: mov r3, r7, get_byte_2
254 teq ip, #0
255 beq .c2u_finished
256 cmp ip, #2
257USER( strbt r3, [r0], #1) @ May fault
258 movge r3, r7, get_byte_3
259USER( strgebt r3, [r0], #1) @ May fault
260 ldrgtb r3, [r1], #0
261USER( strgtbt r3, [r0], #1) @ May fault
262 b .c2u_finished
263
264.c2u_3fupi: subs r2, r2, #4
265 addmi ip, r2, #4
266 bmi .c2u_3nowords
267 mov r3, r7, pull #24
268 ldr r7, [r1], #4
269 orr r3, r3, r7, push #8
270USER( strt r3, [r0], #4) @ May fault
271 mov ip, r0, lsl #32 - PAGE_SHIFT
272 rsb ip, ip, #0
273 movs ip, ip, lsr #32 - PAGE_SHIFT
274 beq .c2u_3fupi
275 cmp r2, ip
276 movlt ip, r2
277 sub r2, r2, ip
278 subs ip, ip, #16
279 blt .c2u_3rem8lp
280 PLD( pld [r1, #12] )
281 PLD( pld [r0, #12] )
282 PLD( subs ip, ip, #32 )
283 PLD( blt .c2u_3cpynopld )
284 PLD( pld [r1, #28] )
285 PLD( pld [r0, #28] )
286
287.c2u_3cpy8lp:
288 PLD( pld [r1, #44] )
289 PLD( pld [r0, #44] )
290.c2u_3cpynopld: mov r3, r7, pull #24
291 ldmia r1!, {r4 - r7}
292 subs ip, ip, #16
293 orr r3, r3, r4, push #8
294 mov r4, r4, pull #24
295 orr r4, r4, r5, push #8
296 mov r5, r5, pull #24
297 orr r5, r5, r6, push #8
298 mov r6, r6, pull #24
299 orr r6, r6, r7, push #8
300 stmia r0!, {r3 - r6} @ Shouldnt fault
301 bpl .c2u_3cpy8lp
302 PLD( cmn ip, #32 )
303 PLD( bge .c2u_3cpynopld )
304 PLD( add ip, ip, #32 )
305
306.c2u_3rem8lp: tst ip, #8
307 movne r3, r7, pull #24
308 ldmneia r1!, {r4, r7}
309 orrne r3, r3, r4, push #8
310 movne r4, r4, pull #24
311 orrne r4, r4, r7, push #8
312 stmneia r0!, {r3 - r4} @ Shouldnt fault
313 tst ip, #4
314 movne r3, r7, pull #24
315 ldrne r7, [r1], #4
316 orrne r3, r3, r7, push #8
317 strnet r3, [r0], #4 @ Shouldnt fault
318 ands ip, ip, #3
319 beq .c2u_3fupi
320.c2u_3nowords: mov r3, r7, get_byte_3
321 teq ip, #0
322 beq .c2u_finished
323 cmp ip, #2
324USER( strbt r3, [r0], #1) @ May fault
325 ldrgeb r3, [r1], #1
326USER( strgebt r3, [r0], #1) @ May fault
327 ldrgtb r3, [r1], #0
328USER( strgtbt r3, [r0], #1) @ May fault
329 b .c2u_finished
330
331 .section .fixup,"ax"
332 .align 0
3339001: LOADREGS(fd,sp!, {r0, r4 - r7, pc})
334 .previous
335
336/* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
337 * Purpose : copy a block from user memory to kernel memory
338 * Params : to - kernel memory
339 * : from - user memory
340 * : n - number of bytes to copy
341 * Returns : Number of bytes NOT copied.
342 */
343.cfu_dest_not_aligned:
344 rsb ip, ip, #4
345 cmp ip, #2
346USER( ldrbt r3, [r1], #1) @ May fault
347 strb r3, [r0], #1
348USER( ldrgebt r3, [r1], #1) @ May fault
349 strgeb r3, [r0], #1
350USER( ldrgtbt r3, [r1], #1) @ May fault
351 strgtb r3, [r0], #1
352 sub r2, r2, ip
353 b .cfu_dest_aligned
354
355ENTRY(__arch_copy_from_user)
356 stmfd sp!, {r0, r2, r4 - r7, lr}
357 cmp r2, #4
358 blt .cfu_not_enough
359 PLD( pld [r1, #0] )
360 PLD( pld [r0, #0] )
361 ands ip, r0, #3
362 bne .cfu_dest_not_aligned
363.cfu_dest_aligned:
364 ands ip, r1, #3
365 bne .cfu_src_not_aligned
366/*
367 * Seeing as there has to be at least 8 bytes to copy, we can
368 * copy one word, and force a user-mode page fault...
369 */
370
371.cfu_0fupi: subs r2, r2, #4
372 addmi ip, r2, #4
373 bmi .cfu_0nowords
374USER( ldrt r3, [r1], #4)
375 str r3, [r0], #4
376 mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
377 rsb ip, ip, #0
378 movs ip, ip, lsr #32 - PAGE_SHIFT
379 beq .cfu_0fupi
380/*
381 * ip = max no. of bytes to copy before needing another "strt" insn
382 */
383 cmp r2, ip
384 movlt ip, r2
385 sub r2, r2, ip
386 subs ip, ip, #32
387 blt .cfu_0rem8lp
388 PLD( pld [r1, #28] )
389 PLD( pld [r0, #28] )
390 PLD( subs ip, ip, #64 )
391 PLD( blt .cfu_0cpynopld )
392 PLD( pld [r1, #60] )
393 PLD( pld [r0, #60] )
394
395.cfu_0cpy8lp:
396 PLD( pld [r1, #92] )
397 PLD( pld [r0, #92] )
398.cfu_0cpynopld: ldmia r1!, {r3 - r6} @ Shouldnt fault
399 stmia r0!, {r3 - r6}
400 ldmia r1!, {r3 - r6} @ Shouldnt fault
401 subs ip, ip, #32
402 stmia r0!, {r3 - r6}
403 bpl .cfu_0cpy8lp
404 PLD( cmn ip, #64 )
405 PLD( bge .cfu_0cpynopld )
406 PLD( add ip, ip, #64 )
407
408.cfu_0rem8lp: cmn ip, #16
409 ldmgeia r1!, {r3 - r6} @ Shouldnt fault
410 stmgeia r0!, {r3 - r6}
411 tst ip, #8
412 ldmneia r1!, {r3 - r4} @ Shouldnt fault
413 stmneia r0!, {r3 - r4}
414 tst ip, #4
415 ldrnet r3, [r1], #4 @ Shouldnt fault
416 strne r3, [r0], #4
417 ands ip, ip, #3
418 beq .cfu_0fupi
419.cfu_0nowords: teq ip, #0
420 beq .cfu_finished
421.cfu_nowords: cmp ip, #2
422USER( ldrbt r3, [r1], #1) @ May fault
423 strb r3, [r0], #1
424USER( ldrgebt r3, [r1], #1) @ May fault
425 strgeb r3, [r0], #1
426USER( ldrgtbt r3, [r1], #1) @ May fault
427 strgtb r3, [r0], #1
428 b .cfu_finished
429
430.cfu_not_enough:
431 movs ip, r2
432 bne .cfu_nowords
433.cfu_finished: mov r0, #0
434 add sp, sp, #8
435 LOADREGS(fd,sp!,{r4 - r7, pc})
436
437.cfu_src_not_aligned:
438 bic r1, r1, #3
439USER( ldrt r7, [r1], #4) @ May fault
440 cmp ip, #2
441 bgt .cfu_3fupi
442 beq .cfu_2fupi
443.cfu_1fupi: subs r2, r2, #4
444 addmi ip, r2, #4
445 bmi .cfu_1nowords
446 mov r3, r7, pull #8
447USER( ldrt r7, [r1], #4) @ May fault
448 orr r3, r3, r7, push #24
449 str r3, [r0], #4
450 mov ip, r1, lsl #32 - PAGE_SHIFT
451 rsb ip, ip, #0
452 movs ip, ip, lsr #32 - PAGE_SHIFT
453 beq .cfu_1fupi
454 cmp r2, ip
455 movlt ip, r2
456 sub r2, r2, ip
457 subs ip, ip, #16
458 blt .cfu_1rem8lp
459 PLD( pld [r1, #12] )
460 PLD( pld [r0, #12] )
461 PLD( subs ip, ip, #32 )
462 PLD( blt .cfu_1cpynopld )
463 PLD( pld [r1, #28] )
464 PLD( pld [r0, #28] )
465
466.cfu_1cpy8lp:
467 PLD( pld [r1, #44] )
468 PLD( pld [r0, #44] )
469.cfu_1cpynopld: mov r3, r7, pull #8
470 ldmia r1!, {r4 - r7} @ Shouldnt fault
471 subs ip, ip, #16
472 orr r3, r3, r4, push #24
473 mov r4, r4, pull #8
474 orr r4, r4, r5, push #24
475 mov r5, r5, pull #8
476 orr r5, r5, r6, push #24
477 mov r6, r6, pull #8
478 orr r6, r6, r7, push #24
479 stmia r0!, {r3 - r6}
480 bpl .cfu_1cpy8lp
481 PLD( cmn ip, #32 )
482 PLD( bge .cfu_1cpynopld )
483 PLD( add ip, ip, #32 )
484
485.cfu_1rem8lp: tst ip, #8
486 movne r3, r7, pull #8
487 ldmneia r1!, {r4, r7} @ Shouldnt fault
488 orrne r3, r3, r4, push #24
489 movne r4, r4, pull #8
490 orrne r4, r4, r7, push #24
491 stmneia r0!, {r3 - r4}
492 tst ip, #4
493 movne r3, r7, pull #8
494USER( ldrnet r7, [r1], #4) @ May fault
495 orrne r3, r3, r7, push #24
496 strne r3, [r0], #4
497 ands ip, ip, #3
498 beq .cfu_1fupi
499.cfu_1nowords: mov r3, r7, get_byte_1
500 teq ip, #0
501 beq .cfu_finished
502 cmp ip, #2
503 strb r3, [r0], #1
504 movge r3, r7, get_byte_2
505 strgeb r3, [r0], #1
506 movgt r3, r7, get_byte_3
507 strgtb r3, [r0], #1
508 b .cfu_finished
509
510.cfu_2fupi: subs r2, r2, #4
511 addmi ip, r2, #4
512 bmi .cfu_2nowords
513 mov r3, r7, pull #16
514USER( ldrt r7, [r1], #4) @ May fault
515 orr r3, r3, r7, push #16
516 str r3, [r0], #4
517 mov ip, r1, lsl #32 - PAGE_SHIFT
518 rsb ip, ip, #0
519 movs ip, ip, lsr #32 - PAGE_SHIFT
520 beq .cfu_2fupi
521 cmp r2, ip
522 movlt ip, r2
523 sub r2, r2, ip
524 subs ip, ip, #16
525 blt .cfu_2rem8lp
526 PLD( pld [r1, #12] )
527 PLD( pld [r0, #12] )
528 PLD( subs ip, ip, #32 )
529 PLD( blt .cfu_2cpynopld )
530 PLD( pld [r1, #28] )
531 PLD( pld [r0, #28] )
532
533.cfu_2cpy8lp:
534 PLD( pld [r1, #44] )
535 PLD( pld [r0, #44] )
536.cfu_2cpynopld: mov r3, r7, pull #16
537 ldmia r1!, {r4 - r7} @ Shouldnt fault
538 subs ip, ip, #16
539 orr r3, r3, r4, push #16
540 mov r4, r4, pull #16
541 orr r4, r4, r5, push #16
542 mov r5, r5, pull #16
543 orr r5, r5, r6, push #16
544 mov r6, r6, pull #16
545 orr r6, r6, r7, push #16
546 stmia r0!, {r3 - r6}
547 bpl .cfu_2cpy8lp
548 PLD( cmn ip, #32 )
549 PLD( bge .cfu_2cpynopld )
550 PLD( add ip, ip, #32 )
551
552.cfu_2rem8lp: tst ip, #8
553 movne r3, r7, pull #16
554 ldmneia r1!, {r4, r7} @ Shouldnt fault
555 orrne r3, r3, r4, push #16
556 movne r4, r4, pull #16
557 orrne r4, r4, r7, push #16
558 stmneia r0!, {r3 - r4}
559 tst ip, #4
560 movne r3, r7, pull #16
561USER( ldrnet r7, [r1], #4) @ May fault
562 orrne r3, r3, r7, push #16
563 strne r3, [r0], #4
564 ands ip, ip, #3
565 beq .cfu_2fupi
566.cfu_2nowords: mov r3, r7, get_byte_2
567 teq ip, #0
568 beq .cfu_finished
569 cmp ip, #2
570 strb r3, [r0], #1
571 movge r3, r7, get_byte_3
572 strgeb r3, [r0], #1
573USER( ldrgtbt r3, [r1], #0) @ May fault
574 strgtb r3, [r0], #1
575 b .cfu_finished
576
577.cfu_3fupi: subs r2, r2, #4
578 addmi ip, r2, #4
579 bmi .cfu_3nowords
580 mov r3, r7, pull #24
581USER( ldrt r7, [r1], #4) @ May fault
582 orr r3, r3, r7, push #8
583 str r3, [r0], #4
584 mov ip, r1, lsl #32 - PAGE_SHIFT
585 rsb ip, ip, #0
586 movs ip, ip, lsr #32 - PAGE_SHIFT
587 beq .cfu_3fupi
588 cmp r2, ip
589 movlt ip, r2
590 sub r2, r2, ip
591 subs ip, ip, #16
592 blt .cfu_3rem8lp
593 PLD( pld [r1, #12] )
594 PLD( pld [r0, #12] )
595 PLD( subs ip, ip, #32 )
596 PLD( blt .cfu_3cpynopld )
597 PLD( pld [r1, #28] )
598 PLD( pld [r0, #28] )
599
600.cfu_3cpy8lp:
601 PLD( pld [r1, #44] )
602 PLD( pld [r0, #44] )
603.cfu_3cpynopld: mov r3, r7, pull #24
604 ldmia r1!, {r4 - r7} @ Shouldnt fault
605 orr r3, r3, r4, push #8
606 mov r4, r4, pull #24
607 orr r4, r4, r5, push #8
608 mov r5, r5, pull #24
609 orr r5, r5, r6, push #8
610 mov r6, r6, pull #24
611 orr r6, r6, r7, push #8
612 stmia r0!, {r3 - r6}
613 subs ip, ip, #16
614 bpl .cfu_3cpy8lp
615 PLD( cmn ip, #32 )
616 PLD( bge .cfu_3cpynopld )
617 PLD( add ip, ip, #32 )
618
619.cfu_3rem8lp: tst ip, #8
620 movne r3, r7, pull #24
621 ldmneia r1!, {r4, r7} @ Shouldnt fault
622 orrne r3, r3, r4, push #8
623 movne r4, r4, pull #24
624 orrne r4, r4, r7, push #8
625 stmneia r0!, {r3 - r4}
626 tst ip, #4
627 movne r3, r7, pull #24
628USER( ldrnet r7, [r1], #4) @ May fault
629 orrne r3, r3, r7, push #8
630 strne r3, [r0], #4
631 ands ip, ip, #3
632 beq .cfu_3fupi
633.cfu_3nowords: mov r3, r7, get_byte_3
634 teq ip, #0
635 beq .cfu_finished
636 cmp ip, #2
637 strb r3, [r0], #1
638USER( ldrgebt r3, [r1], #1) @ May fault
639 strgeb r3, [r0], #1
640USER( ldrgtbt r3, [r1], #1) @ May fault
641 strgtb r3, [r0], #1
642 b .cfu_finished
643
644 .section .fixup,"ax"
645 .align 0
646 /*
647 * We took an exception. r0 contains a pointer to
648 * the byte not copied.
649 */
6509001: ldr r2, [sp], #4 @ void *to
651 sub r2, r0, r2 @ bytes copied
652 ldr r1, [sp], #4 @ unsigned long count
653 subs r4, r1, r2 @ bytes left to copy
654 movne r1, r4
655 blne __memzero
656 mov r0, r4
657 LOADREGS(fd,sp!, {r4 - r7, pc})
658 .previous
659
660/* Prototype: int __arch_clear_user(void *addr, size_t sz)
661 * Purpose : clear some user memory
662 * Params : addr - user memory address to clear
663 * : sz - number of bytes to clear
664 * Returns : number of bytes NOT cleared
665 */
666ENTRY(__arch_clear_user)
667 stmfd sp!, {r1, lr}
668 mov r2, #0
669 cmp r1, #4
670 blt 2f
671 ands ip, r0, #3
672 beq 1f
673 cmp ip, #2
674USER( strbt r2, [r0], #1)
675USER( strlebt r2, [r0], #1)
676USER( strltbt r2, [r0], #1)
677 rsb ip, ip, #4
678 sub r1, r1, ip @ 7 6 5 4 3 2 1
6791: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
680USER( strplt r2, [r0], #4)
681USER( strplt r2, [r0], #4)
682 bpl 1b
683 adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
684USER( strplt r2, [r0], #4)
6852: tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
686USER( strnebt r2, [r0], #1)
687USER( strnebt r2, [r0], #1)
688 tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
689USER( strnebt r2, [r0], #1)
690 mov r0, #0
691 LOADREGS(fd,sp!, {r1, pc})
692
693 .section .fixup,"ax"
694 .align 0
6959001: LOADREGS(fd,sp!, {r0, pc})
696 .previous
697
diff --git a/arch/arm/lib/ucmpdi2.c b/arch/arm/lib/ucmpdi2.c
new file mode 100644
index 000000000000..6c6ae63efa02
--- /dev/null
+++ b/arch/arm/lib/ucmpdi2.c
@@ -0,0 +1,51 @@
1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
3/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22/* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License.
28 */
29/* support functions required by the kernel. based on code from gcc-2.95.3 */
30/* I Molton 29/07/01 */
31
32#include "gcclib.h"
33
34word_type
35__ucmpdi2 (DItype a, DItype b)
36{
37 DIunion au, bu;
38
39 au.ll = a, bu.ll = b;
40
41 if ((USItype) au.s.high < (USItype) bu.s.high)
42 return 0;
43 else if ((USItype) au.s.high > (USItype) bu.s.high)
44 return 2;
45 if ((USItype) au.s.low < (USItype) bu.s.low)
46 return 0;
47 else if ((USItype) au.s.low > (USItype) bu.s.low)
48 return 2;
49 return 1;
50}
51
diff --git a/arch/arm/lib/udivdi3.c b/arch/arm/lib/udivdi3.c
new file mode 100644
index 000000000000..d25195f673f4
--- /dev/null
+++ b/arch/arm/lib/udivdi3.c
@@ -0,0 +1,242 @@
1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
3/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
21
22/* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License.
28 */
29/* support functions required by the kernel. based on code from gcc-2.95.3 */
30/* I Molton 29/07/01 */
31
32#include "gcclib.h"
33#include "longlong.h"
34
35static const UQItype __clz_tab[] =
36{
37 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
38 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
39 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
40 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
41 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
42 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
43 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
44 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
45};
46
47UDItype
48__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
49{
50 DIunion ww;
51 DIunion nn, dd;
52 DIunion rr;
53 USItype d0, d1, n0, n1, n2;
54 USItype q0, q1;
55 USItype b, bm;
56
57 nn.ll = n;
58 dd.ll = d;
59
60 d0 = dd.s.low;
61 d1 = dd.s.high;
62 n0 = nn.s.low;
63 n1 = nn.s.high;
64
65 if (d1 == 0)
66 {
67 if (d0 > n1)
68 {
69 /* 0q = nn / 0D */
70
71 count_leading_zeros (bm, d0);
72
73 if (bm != 0)
74 {
75 /* Normalize, i.e. make the most significant bit of the
76 denominator set. */
77
78 d0 = d0 << bm;
79 n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
80 n0 = n0 << bm;
81 }
82
83 udiv_qrnnd (q0, n0, n1, n0, d0);
84 q1 = 0;
85
86 /* Remainder in n0 >> bm. */
87 }
88 else
89 {
90 /* qq = NN / 0d */
91
92 if (d0 == 0)
93 d0 = 1 / d0; /* Divide intentionally by zero. */
94
95 count_leading_zeros (bm, d0);
96
97 if (bm == 0)
98 {
99 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
100 conclude (the most significant bit of n1 is set) /\ (the
101 leading quotient digit q1 = 1).
102
103 This special case is necessary, not an optimization.
104 (Shifts counts of SI_TYPE_SIZE are undefined.) */
105
106 n1 -= d0;
107 q1 = 1;
108 }
109 else
110 {
111 /* Normalize. */
112
113 b = SI_TYPE_SIZE - bm;
114
115 d0 = d0 << bm;
116 n2 = n1 >> b;
117 n1 = (n1 << bm) | (n0 >> b);
118 n0 = n0 << bm;
119
120 udiv_qrnnd (q1, n1, n2, n1, d0);
121 }
122
123 /* n1 != d0... */
124
125 udiv_qrnnd (q0, n0, n1, n0, d0);
126
127 /* Remainder in n0 >> bm. */
128 }
129
130 if (rp != 0)
131 {
132 rr.s.low = n0 >> bm;
133 rr.s.high = 0;
134 *rp = rr.ll;
135 }
136 }
137 else
138 {
139 if (d1 > n1)
140 {
141 /* 00 = nn / DD */
142
143 q0 = 0;
144 q1 = 0;
145
146 /* Remainder in n1n0. */
147 if (rp != 0)
148 {
149 rr.s.low = n0;
150 rr.s.high = n1;
151 *rp = rr.ll;
152 }
153 }
154 else
155 {
156 /* 0q = NN / dd */
157
158 count_leading_zeros (bm, d1);
159 if (bm == 0)
160 {
161 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
162 conclude (the most significant bit of n1 is set) /\ (the
163 quotient digit q0 = 0 or 1).
164
165 This special case is necessary, not an optimization. */
166
167 /* The condition on the next line takes advantage of that
168 n1 >= d1 (true due to program flow). */
169 if (n1 > d1 || n0 >= d0)
170 {
171 q0 = 1;
172 sub_ddmmss (n1, n0, n1, n0, d1, d0);
173 }
174 else
175 q0 = 0;
176
177 q1 = 0;
178
179 if (rp != 0)
180 {
181 rr.s.low = n0;
182 rr.s.high = n1;
183 *rp = rr.ll;
184 }
185 }
186 else
187 {
188 USItype m1, m0;
189 /* Normalize. */
190
191 b = SI_TYPE_SIZE - bm;
192
193 d1 = (d1 << bm) | (d0 >> b);
194 d0 = d0 << bm;
195 n2 = n1 >> b;
196 n1 = (n1 << bm) | (n0 >> b);
197 n0 = n0 << bm;
198
199 udiv_qrnnd (q0, n1, n2, n1, d1);
200 umul_ppmm (m1, m0, q0, d0);
201
202 if (m1 > n1 || (m1 == n1 && m0 > n0))
203 {
204 q0--;
205 sub_ddmmss (m1, m0, m1, m0, d1, d0);
206 }
207
208 q1 = 0;
209
210 /* Remainder in (n1n0 - m1m0) >> bm. */
211 if (rp != 0)
212 {
213 sub_ddmmss (n1, n0, n1, n0, m1, m0);
214 rr.s.low = (n1 << b) | (n0 >> bm);
215 rr.s.high = n1 >> bm;
216 *rp = rr.ll;
217 }
218 }
219 }
220 }
221
222 ww.s.low = q0;
223 ww.s.high = q1;
224 return ww.ll;
225}
226
227UDItype
228__udivdi3 (UDItype n, UDItype d)
229{
230 return __udivmoddi4 (n, d, (UDItype *) 0);
231}
232
233UDItype
234__umoddi3 (UDItype u, UDItype v)
235{
236 UDItype w;
237
238 (void) __udivmoddi4 (u ,v, &w);
239
240 return w;
241}
242