Linux-2.6.12-rc2
[linux-3.10.git] / arch / arm26 / lib / putuser.S
1 /*
2  *  linux/arch/arm26/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  *              r1, r2 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/asm_offsets.h>
30 #include <asm/thread_info.h>
31 #include <asm/errno.h>
32
33         .global __put_user_1
34 __put_user_1:
35         bic     r2, sp, #0x1f00
36         bic     r2, r2, #0x00ff
37         str     lr, [sp, #-4]!
38         ldr     r2, [r2, #TI_ADDR_LIMIT]
39         sub     r2, r2, #1
40         cmp     r0, r2
41         bge     __put_user_bad
42 1:      cmp     r0, #0x02000000
43         strlsbt r1, [r0]
44         strgeb  r1, [r0]
45         mov     r0, #0
46         ldmfd   sp!, {pc}^
47
48         .global __put_user_2
49 __put_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     __put_user_bad
57 2:      cmp     r0, #0x02000000
58         strlsbt r1, [r0], #1
59         strgeb  r1, [r0], #1
60         mov     r1, r1, lsr #8
61 3:      strlsbt r1, [r0]
62         strgeb  r1, [r0]
63         mov     r0, #0
64         ldmfd   sp!, {pc}^
65
66         .global __put_user_4
67 __put_user_4:
68         bic     r2, sp, #0x1f00
69         bic     r2, r2, #0x00ff
70         str     lr, [sp, #-4]!
71         ldr     r2, [r2, #TI_ADDR_LIMIT]
72         sub     r2, r2, #4
73         cmp     r0, r2
74 4:      bge     __put_user_bad
75         cmp     r0, #0x02000000
76         strlst  r1, [r0]
77         strge   r1, [r0]
78         mov     r0, #0
79         ldmfd   sp!, {pc}^
80
81         .global __put_user_8
82 __put_user_8:
83         bic     ip, sp, #0x1f00
84         bic     ip, ip, #0x00ff
85         str     lr, [sp, #-4]!
86         ldr     ip, [ip, #TI_ADDR_LIMIT]
87         sub     ip, ip, #8
88         cmp     r0, ip
89         bge     __put_user_bad
90         cmp     r0, #0x02000000
91 5:      strlst  r1, [r0], #4
92 6:      strlst  r2, [r0]
93         strge   r1, [r0], #4
94         strge   r2, [r0]
95         mov     r0, #0
96         ldmfd   sp!, {pc}^
97
98 __put_user_bad:
99         mov     r0, #-EFAULT
100         mov     pc, lr
101
102 .section __ex_table, "a"
103         .long   1b, __put_user_bad
104         .long   2b, __put_user_bad
105         .long   3b, __put_user_bad
106         .long   4b, __put_user_bad
107         .long   5b, __put_user_bad
108         .long   6b, __put_user_bad
109 .previous