atomic64_386_32.S 2.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * atomic64_t for 386/486
 *
 * Copyright © 2010  Luca Barbieri
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/linkage.h>
#include <asm/alternative-asm.h>

/* if you want SMP support, implement these with real spinlocks */
.macro LOCK reg
17
	pushfl
18 19 20 21
	cli
.endm

.macro UNLOCK reg
22
	popfl
23 24
.endm

25
#define BEGIN(op) \
26
.macro endp; \
27
ENDPROC(atomic64_##op##_386); \
28
.purgem endp; \
29 30 31 32
.endm; \
ENTRY(atomic64_##op##_386); \
	LOCK v;

33 34
#define ENDP endp

35 36
#define RET \
	UNLOCK v; \
37 38
	ret

39
#define RET_ENDP \
40
	RET; \
41
	ENDP
42 43 44 45 46

#define v %ecx
BEGIN(read)
	movl  (v), %eax
	movl 4(v), %edx
47
RET_ENDP
48 49 50 51 52 53
#undef v

#define v %esi
BEGIN(set)
	movl %ebx,  (v)
	movl %ecx, 4(v)
54
RET_ENDP
55 56 57 58 59 60 61 62
#undef v

#define v  %esi
BEGIN(xchg)
	movl  (v), %eax
	movl 4(v), %edx
	movl %ebx,  (v)
	movl %ecx, 4(v)
63
RET_ENDP
64 65 66 67 68 69
#undef v

#define v %ecx
BEGIN(add)
	addl %eax,  (v)
	adcl %edx, 4(v)
70
RET_ENDP
71 72 73 74 75 76 77 78
#undef v

#define v %ecx
BEGIN(add_return)
	addl  (v), %eax
	adcl 4(v), %edx
	movl %eax,  (v)
	movl %edx, 4(v)
79
RET_ENDP
80 81 82 83 84 85
#undef v

#define v %ecx
BEGIN(sub)
	subl %eax,  (v)
	sbbl %edx, 4(v)
86
RET_ENDP
87 88 89 90
#undef v

#define v %ecx
BEGIN(sub_return)
91 92 93
	negl %edx
	negl %eax
	sbbl $0, %edx
94 95 96 97
	addl  (v), %eax
	adcl 4(v), %edx
	movl %eax,  (v)
	movl %edx, 4(v)
98
RET_ENDP
99 100 101 102 103 104
#undef v

#define v %esi
BEGIN(inc)
	addl $1,  (v)
	adcl $0, 4(v)
105
RET_ENDP
106 107 108 109 110 111
#undef v

#define v %esi
BEGIN(inc_return)
	movl  (v), %eax
	movl 4(v), %edx
112 113
	addl $1, %eax
	adcl $0, %edx
114 115
	movl %eax,  (v)
	movl %edx, 4(v)
116
RET_ENDP
117 118 119 120 121 122
#undef v

#define v %esi
BEGIN(dec)
	subl $1,  (v)
	sbbl $0, 4(v)
123
RET_ENDP
124 125 126 127 128 129
#undef v

#define v %esi
BEGIN(dec_return)
	movl  (v), %eax
	movl 4(v), %edx
130 131
	subl $1, %eax
	sbbl $0, %edx
132 133
	movl %eax,  (v)
	movl %edx, 4(v)
134
RET_ENDP
135
#undef v
136

137
#define v %esi
138
BEGIN(add_unless)
139
	addl %eax, %ecx
140
	adcl %edx, %edi
141 142
	addl  (v), %eax
	adcl 4(v), %edx
143
	cmpl %eax, %ecx
144 145
	je 3f
1:
146 147
	movl %eax,  (v)
	movl %edx, 4(v)
148
	movl $1, %eax
149
2:
150
	RET
151 152 153
3:
	cmpl %edx, %edi
	jne 1b
154
	xorl %eax, %eax
155
	jmp 2b
156
ENDP
157
#undef v
158

159 160 161 162
#define v %esi
BEGIN(inc_not_zero)
	movl  (v), %eax
	movl 4(v), %edx
163 164 165 166 167
	testl %eax, %eax
	je 3f
1:
	addl $1, %eax
	adcl $0, %edx
168 169
	movl %eax,  (v)
	movl %edx, 4(v)
170
	movl $1, %eax
171
2:
172
	RET
173 174 175 176
3:
	testl %edx, %edx
	jne 1b
	jmp 2b
177
ENDP
178
#undef v
179

180 181 182 183
#define v %esi
BEGIN(dec_if_positive)
	movl  (v), %eax
	movl 4(v), %edx
184 185 186
	subl $1, %eax
	sbbl $0, %edx
	js 1f
187 188
	movl %eax,  (v)
	movl %edx, 4(v)
189
1:
190
RET_ENDP
191
#undef v