diff options
author | Luca Barbieri <luca@luca-barbieri.com> | 2010-08-05 22:04:38 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-08-12 00:03:28 -0400 |
commit | 30246557a06bb20618bed906a06d1e1e0faa8bb4 (patch) | |
tree | 26f1493097b00e1cf3fdbf40b4abced115ac219d /arch | |
parent | 8fd49936a8cac246fc9ed85508556c82cd44cf68 (diff) |
x86, asm: Refactor atomic64_386_32.S to support old binutils and be cleaner
The old code didn't work on binutils 2.12 because setting a symbol to
a register apparently requires a fairly recent version.
This commit refactors the code to use the C preprocessor instead, and
in the process makes the whole code a bit easier to understand.
The object code produced is unchanged as expected.
This fixes kernel bugzilla 16506.
Reported-by: Dieter Stussy <kd6lvw+software@kd6lvw.ampr.org>
Signed-off-by: Luca Barbieri <luca@luca-barbieri.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Cc: <stable@kernel.org> 2.6.35
LKML-Reference: <tip-*@git.kernel.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/lib/atomic64_386_32.S | 236 |
1 files changed, 128 insertions, 108 deletions
diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S index 4a5979aa6883..78ee8e0fa278 100644 --- a/arch/x86/lib/atomic64_386_32.S +++ b/arch/x86/lib/atomic64_386_32.S | |||
@@ -25,150 +25,170 @@ | |||
25 | CFI_ADJUST_CFA_OFFSET -4 | 25 | CFI_ADJUST_CFA_OFFSET -4 |
26 | .endm | 26 | .endm |
27 | 27 | ||
28 | .macro BEGIN func reg | 28 | #define BEGIN(op) \ |
29 | $v = \reg | 29 | .macro END; \ |
30 | 30 | CFI_ENDPROC; \ | |
31 | ENTRY(atomic64_\func\()_386) | 31 | ENDPROC(atomic64_##op##_386); \ |
32 | CFI_STARTPROC | 32 | .purgem END; \ |
33 | LOCK $v | 33 | .endm; \ |
34 | 34 | ENTRY(atomic64_##op##_386); \ | |
35 | .macro RETURN | 35 | CFI_STARTPROC; \ |
36 | UNLOCK $v | 36 | LOCK v; |
37 | |||
38 | #define RET \ | ||
39 | UNLOCK v; \ | ||
37 | ret | 40 | ret |
38 | .endm | ||
39 | |||
40 | .macro END_ | ||
41 | CFI_ENDPROC | ||
42 | ENDPROC(atomic64_\func\()_386) | ||
43 | .purgem RETURN | ||
44 | .purgem END_ | ||
45 | .purgem END | ||
46 | .endm | ||
47 | |||
48 | .macro END | ||
49 | RETURN | ||
50 | END_ | ||
51 | .endm | ||
52 | .endm | ||
53 | |||
54 | BEGIN read %ecx | ||
55 | movl ($v), %eax | ||
56 | movl 4($v), %edx | ||
57 | END | ||
58 | |||
59 | BEGIN set %esi | ||
60 | movl %ebx, ($v) | ||
61 | movl %ecx, 4($v) | ||
62 | END | ||
63 | |||
64 | BEGIN xchg %esi | ||
65 | movl ($v), %eax | ||
66 | movl 4($v), %edx | ||
67 | movl %ebx, ($v) | ||
68 | movl %ecx, 4($v) | ||
69 | END | ||
70 | |||
71 | BEGIN add %ecx | ||
72 | addl %eax, ($v) | ||
73 | adcl %edx, 4($v) | ||
74 | END | ||
75 | 41 | ||
76 | BEGIN add_return %ecx | 42 | #define RET_END \ |
77 | addl ($v), %eax | 43 | RET; \ |
78 | adcl 4($v), %edx | 44 | END |
79 | movl %eax, ($v) | 45 | |
80 | movl %edx, 4($v) | 46 | #define v %ecx |
81 | END | 47 | BEGIN(read) |
82 | 48 | movl (v), %eax | |
83 | BEGIN sub %ecx | 49 | movl 4(v), %edx |
84 | subl %eax, ($v) | 50 | RET_END |
85 | sbbl %edx, 4($v) | 51 | #undef v |
86 | END | 52 | |
87 | 53 | #define v %esi | |
88 | BEGIN sub_return %ecx | 54 | BEGIN(set) |
55 | movl %ebx, (v) | ||
56 | movl %ecx, 4(v) | ||
57 | RET_END | ||
58 | #undef v | ||
59 | |||
60 | #define v %esi | ||
61 | BEGIN(xchg) | ||
62 | movl (v), %eax | ||
63 | movl 4(v), %edx | ||
64 | movl %ebx, (v) | ||
65 | movl %ecx, 4(v) | ||
66 | RET_END | ||
67 | #undef v | ||
68 | |||
69 | #define v %ecx | ||
70 | BEGIN(add) | ||
71 | addl %eax, (v) | ||
72 | adcl %edx, 4(v) | ||
73 | RET_END | ||
74 | #undef v | ||
75 | |||
76 | #define v %ecx | ||
77 | BEGIN(add_return) | ||
78 | addl (v), %eax | ||
79 | adcl 4(v), %edx | ||
80 | movl %eax, (v) | ||
81 | movl %edx, 4(v) | ||
82 | RET_END | ||
83 | #undef v | ||
84 | |||
85 | #define v %ecx | ||
86 | BEGIN(sub) | ||
87 | subl %eax, (v) | ||
88 | sbbl %edx, 4(v) | ||
89 | RET_END | ||
90 | #undef v | ||
91 | |||
92 | #define v %ecx | ||
93 | BEGIN(sub_return) | ||
89 | negl %edx | 94 | negl %edx |
90 | negl %eax | 95 | negl %eax |
91 | sbbl $0, %edx | 96 | sbbl $0, %edx |
92 | addl ($v), %eax | 97 | addl (v), %eax |
93 | adcl 4($v), %edx | 98 | adcl 4(v), %edx |
94 | movl %eax, ($v) | 99 | movl %eax, (v) |
95 | movl %edx, 4($v) | 100 | movl %edx, 4(v) |
96 | END | 101 | RET_END |
97 | 102 | #undef v | |
98 | BEGIN inc %esi | 103 | |
99 | addl $1, ($v) | 104 | #define v %esi |
100 | adcl $0, 4($v) | 105 | BEGIN(inc) |
101 | END | 106 | addl $1, (v) |
102 | 107 | adcl $0, 4(v) | |
103 | BEGIN inc_return %esi | 108 | RET_END |
104 | movl ($v), %eax | 109 | #undef v |
105 | movl 4($v), %edx | 110 | |
111 | #define v %esi | ||
112 | BEGIN(inc_return) | ||
113 | movl (v), %eax | ||
114 | movl 4(v), %edx | ||
106 | addl $1, %eax | 115 | addl $1, %eax |
107 | adcl $0, %edx | 116 | adcl $0, %edx |
108 | movl %eax, ($v) | 117 | movl %eax, (v) |
109 | movl %edx, 4($v) | 118 | movl %edx, 4(v) |
110 | END | 119 | RET_END |
111 | 120 | #undef v | |
112 | BEGIN dec %esi | 121 | |
113 | subl $1, ($v) | 122 | #define v %esi |
114 | sbbl $0, 4($v) | 123 | BEGIN(dec) |
115 | END | 124 | subl $1, (v) |
116 | 125 | sbbl $0, 4(v) | |
117 | BEGIN dec_return %esi | 126 | RET_END |
118 | movl ($v), %eax | 127 | #undef v |
119 | movl 4($v), %edx | 128 | |
129 | #define v %esi | ||
130 | BEGIN(dec_return) | ||
131 | movl (v), %eax | ||
132 | movl 4(v), %edx | ||
120 | subl $1, %eax | 133 | subl $1, %eax |
121 | sbbl $0, %edx | 134 | sbbl $0, %edx |
122 | movl %eax, ($v) | 135 | movl %eax, (v) |
123 | movl %edx, 4($v) | 136 | movl %edx, 4(v) |
124 | END | 137 | RET_END |
138 | #undef v | ||
125 | 139 | ||
126 | BEGIN add_unless %ecx | 140 | #define v %ecx |
141 | BEGIN(add_unless) | ||
127 | addl %eax, %esi | 142 | addl %eax, %esi |
128 | adcl %edx, %edi | 143 | adcl %edx, %edi |
129 | addl ($v), %eax | 144 | addl (v), %eax |
130 | adcl 4($v), %edx | 145 | adcl 4(v), %edx |
131 | cmpl %eax, %esi | 146 | cmpl %eax, %esi |
132 | je 3f | 147 | je 3f |
133 | 1: | 148 | 1: |
134 | movl %eax, ($v) | 149 | movl %eax, (v) |
135 | movl %edx, 4($v) | 150 | movl %edx, 4(v) |
136 | movl $1, %eax | 151 | movl $1, %eax |
137 | 2: | 152 | 2: |
138 | RETURN | 153 | RET |
139 | 3: | 154 | 3: |
140 | cmpl %edx, %edi | 155 | cmpl %edx, %edi |
141 | jne 1b | 156 | jne 1b |
142 | xorl %eax, %eax | 157 | xorl %eax, %eax |
143 | jmp 2b | 158 | jmp 2b |
144 | END_ | 159 | END |
160 | #undef v | ||
145 | 161 | ||
146 | BEGIN inc_not_zero %esi | 162 | #define v %esi |
147 | movl ($v), %eax | 163 | BEGIN(inc_not_zero) |
148 | movl 4($v), %edx | 164 | movl (v), %eax |
165 | movl 4(v), %edx | ||
149 | testl %eax, %eax | 166 | testl %eax, %eax |
150 | je 3f | 167 | je 3f |
151 | 1: | 168 | 1: |
152 | addl $1, %eax | 169 | addl $1, %eax |
153 | adcl $0, %edx | 170 | adcl $0, %edx |
154 | movl %eax, ($v) | 171 | movl %eax, (v) |
155 | movl %edx, 4($v) | 172 | movl %edx, 4(v) |
156 | movl $1, %eax | 173 | movl $1, %eax |
157 | 2: | 174 | 2: |
158 | RETURN | 175 | RET |
159 | 3: | 176 | 3: |
160 | testl %edx, %edx | 177 | testl %edx, %edx |
161 | jne 1b | 178 | jne 1b |
162 | jmp 2b | 179 | jmp 2b |
163 | END_ | 180 | END |
181 | #undef v | ||
164 | 182 | ||
165 | BEGIN dec_if_positive %esi | 183 | #define v %esi |
166 | movl ($v), %eax | 184 | BEGIN(dec_if_positive) |
167 | movl 4($v), %edx | 185 | movl (v), %eax |
186 | movl 4(v), %edx | ||
168 | subl $1, %eax | 187 | subl $1, %eax |
169 | sbbl $0, %edx | 188 | sbbl $0, %edx |
170 | js 1f | 189 | js 1f |
171 | movl %eax, ($v) | 190 | movl %eax, (v) |
172 | movl %edx, 4($v) | 191 | movl %edx, 4(v) |
173 | 1: | 192 | 1: |
174 | END | 193 | RET_END |
194 | #undef v | ||