Linux-2.6.12-rc2
[linux-2.6.git] / arch / arm26 / lib / getuser.S
1 /*
2  *  linux/arch/arm26/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  *              r1, r2 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/asm_offsets.h>
30 #include <asm/thread_info.h>
31 #include <asm/errno.h>
32
33         .global __get_user_1
34 __get_user_1:
35         bic     r1, sp, #0x1f00
36         bic     r1, r1, #0x00ff
37         str     lr, [sp, #-4]!
38         ldr     r1, [r1, #TI_ADDR_LIMIT]
39         sub     r1, r1, #1
40         cmp     r0, r1
41         bge     __get_user_bad
42         cmp     r0, #0x02000000
43 1:      ldrlsbt r1, [r0]
44         ldrgeb  r1, [r0]
45         mov     r0, #0
46         ldmfd   sp!, {pc}^
47
48         .global __get_user_2
49 __get_user_2:
50         bic     r2, sp, #0x1f00
51         bic     r2, r2, #0x00ff
52         str     lr, [sp, #-4]!
53         ldr     r2, [r2, #TI_ADDR_LIMIT]
54         sub     r2, r2, #2
55         cmp     r0, r2
56         bge     __get_user_bad
57         cmp     r0, #0x02000000
58 2:      ldrlsbt r1, [r0], #1
59 3:      ldrlsbt r2, [r0]
60         ldrgeb  r1, [r0], #1
61         ldrgeb  r2, [r0]
62         orr     r1, r1, r2, lsl #8
63         mov     r0, #0
64         ldmfd   sp!, {pc}^
65
66         .global __get_user_4
67 __get_user_4:
68         bic     r1, sp, #0x1f00
69         bic     r1, r1, #0x00ff
70         str     lr, [sp, #-4]!
71         ldr     r1, [r1, #TI_ADDR_LIMIT]
72         sub     r1, r1, #4
73         cmp     r0, r1
74         bge     __get_user_bad
75         cmp     r0, #0x02000000
76 4:      ldrlst  r1, [r0]
77         ldrge   r1, [r0]
78         mov     r0, #0
79         ldmfd   sp!, {pc}^
80
81         .global __get_user_8
82 __get_user_8:
83         bic     r2, sp, #0x1f00
84         bic     r2, r2, #0x00ff
85         str     lr, [sp, #-4]!
86         ldr     r2, [r2, #TI_ADDR_LIMIT]
87         sub     r2, r2, #8
88         cmp     r0, r2
89         bge     __get_user_bad_8
90         cmp     r0, #0x02000000
91 5:      ldrlst  r1, [r0], #4
92 6:      ldrlst  r2, [r0]
93         ldrge   r1, [r0], #4
94         ldrge   r2, [r0]
95         mov     r0, #0
96         ldmfd   sp!, {pc}^
97
98 __get_user_bad_8:
99         mov     r2, #0
100 __get_user_bad:
101         mov     r1, #0
102         mov     r0, #-EFAULT
103         ldmfd   sp!, {pc}^
104
105 .section __ex_table, "a"
106         .long   1b, __get_user_bad
107         .long   2b, __get_user_bad
108         .long   3b, __get_user_bad
109         .long   4b, __get_user_bad
110         .long   5b, __get_user_bad_8
111         .long   6b, __get_user_bad_8
112 .previous