Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6] / arch / i386 / lib / putuser.S
1 /*
2  * __put_user functions.
3  *
4  * (C) Copyright 2005 Linus Torvalds
5  *
6  * These functions have a non-standard call interface
7  * to make them more efficient, especially as they
8  * return an error value in addition to the "real"
9  * return value.
10  */
11 #include <linux/linkage.h>
12 #include <asm/dwarf2.h>
13 #include <asm/thread_info.h>
14
15
16 /*
17  * __put_user_X
18  *
19  * Inputs:      %eax[:%edx] contains the data
20  *              %ecx contains the address
21  *
22  * Outputs:     %eax is error code (0 or -EFAULT)
23  *
24  * These functions should not modify any other registers,
25  * as they get called from within inline assembly.
26  */
27
28 #define ENTER   CFI_STARTPROC ; \
29                 pushl %ebx ; \
30                 CFI_ADJUST_CFA_OFFSET 4 ; \
31                 CFI_REL_OFFSET ebx, 0 ; \
32                 GET_THREAD_INFO(%ebx)
33 #define EXIT    popl %ebx ; \
34                 CFI_ADJUST_CFA_OFFSET -4 ; \
35                 CFI_RESTORE ebx ; \
36                 ret ; \
37                 CFI_ENDPROC
38
39 .text
40 ENTRY(__put_user_1)
41         ENTER
42         cmpl TI_addr_limit(%ebx),%ecx
43         jae bad_put_user
44 1:      movb %al,(%ecx)
45         xorl %eax,%eax
46         EXIT
47 ENDPROC(__put_user_1)
48
49 ENTRY(__put_user_2)
50         ENTER
51         movl TI_addr_limit(%ebx),%ebx
52         subl $1,%ebx
53         cmpl %ebx,%ecx
54         jae bad_put_user
55 2:      movw %ax,(%ecx)
56         xorl %eax,%eax
57         EXIT
58 ENDPROC(__put_user_2)
59
60 ENTRY(__put_user_4)
61         ENTER
62         movl TI_addr_limit(%ebx),%ebx
63         subl $3,%ebx
64         cmpl %ebx,%ecx
65         jae bad_put_user
66 3:      movl %eax,(%ecx)
67         xorl %eax,%eax
68         EXIT
69 ENDPROC(__put_user_4)
70
71 ENTRY(__put_user_8)
72         ENTER
73         movl TI_addr_limit(%ebx),%ebx
74         subl $7,%ebx
75         cmpl %ebx,%ecx
76         jae bad_put_user
77 4:      movl %eax,(%ecx)
78 5:      movl %edx,4(%ecx)
79         xorl %eax,%eax
80         EXIT
81 ENDPROC(__put_user_8)
82
83 bad_put_user:
84         CFI_STARTPROC simple
85         CFI_DEF_CFA esp, 2*4
86         CFI_OFFSET eip, -1*4
87         CFI_OFFSET ebx, -2*4
88         movl $-14,%eax
89         EXIT
90 END(bad_put_user)
91
92 .section __ex_table,"a"
93         .long 1b,bad_put_user
94         .long 2b,bad_put_user
95         .long 3b,bad_put_user
96         .long 4b,bad_put_user
97         .long 5b,bad_put_user
98 .previous