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 | |
| 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>
| -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 | ||
