| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | /* | 
					
						
							|  |  |  |  * 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> | 
					
						
							|  |  |  | #include <asm/dwarf2.h> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* if you want SMP support, implement these with real spinlocks */ | 
					
						
							|  |  |  | .macro LOCK reg | 
					
						
							| 
									
										
										
										
											2011-02-28 15:54:40 +00:00
										 |  |  | 	pushfl_cfi | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 	cli | 
					
						
							|  |  |  | .endm | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .macro UNLOCK reg | 
					
						
							| 
									
										
										
										
											2011-02-28 15:54:40 +00:00
										 |  |  | 	popfl_cfi | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | .endm | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #define BEGIN(op) \ | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | .macro endp; \
 | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	CFI_ENDPROC; \
 | 
					
						
							|  |  |  | ENDPROC(atomic64_##op##_386); \
 | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | .purgem endp; \
 | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | .endm; \
 | 
					
						
							|  |  |  | ENTRY(atomic64_##op##_386); \
 | 
					
						
							|  |  |  | 	CFI_STARTPROC; \
 | 
					
						
							|  |  |  | 	LOCK v;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | #define ENDP endp | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #define RET \ | 
					
						
							|  |  |  | 	UNLOCK v; \
 | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 	ret | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | #define RET_ENDP \ | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	RET; \
 | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | 	ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define v %ecx | 
					
						
							|  |  |  | BEGIN(read) | 
					
						
							|  |  |  | 	movl  (v), %eax | 
					
						
							|  |  |  | 	movl 4(v), %edx | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define v %esi | 
					
						
							|  |  |  | BEGIN(set) | 
					
						
							|  |  |  | 	movl %ebx,  (v) | 
					
						
							|  |  |  | 	movl %ecx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define v  %esi | 
					
						
							|  |  |  | BEGIN(xchg) | 
					
						
							|  |  |  | 	movl  (v), %eax | 
					
						
							|  |  |  | 	movl 4(v), %edx | 
					
						
							|  |  |  | 	movl %ebx,  (v) | 
					
						
							|  |  |  | 	movl %ecx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define v %ecx | 
					
						
							|  |  |  | BEGIN(add) | 
					
						
							|  |  |  | 	addl %eax,  (v) | 
					
						
							|  |  |  | 	adcl %edx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define v %ecx | 
					
						
							|  |  |  | BEGIN(add_return) | 
					
						
							|  |  |  | 	addl  (v), %eax | 
					
						
							|  |  |  | 	adcl 4(v), %edx | 
					
						
							|  |  |  | 	movl %eax,  (v) | 
					
						
							|  |  |  | 	movl %edx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define v %ecx | 
					
						
							|  |  |  | BEGIN(sub) | 
					
						
							|  |  |  | 	subl %eax,  (v) | 
					
						
							|  |  |  | 	sbbl %edx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define v %ecx | 
					
						
							|  |  |  | BEGIN(sub_return) | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 	negl %edx | 
					
						
							|  |  |  | 	negl %eax | 
					
						
							|  |  |  | 	sbbl $0, %edx | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	addl  (v), %eax | 
					
						
							|  |  |  | 	adcl 4(v), %edx | 
					
						
							|  |  |  | 	movl %eax,  (v) | 
					
						
							|  |  |  | 	movl %edx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define v %esi | 
					
						
							|  |  |  | BEGIN(inc) | 
					
						
							|  |  |  | 	addl $1,  (v) | 
					
						
							|  |  |  | 	adcl $0, 4(v) | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define v %esi | 
					
						
							|  |  |  | BEGIN(inc_return) | 
					
						
							|  |  |  | 	movl  (v), %eax | 
					
						
							|  |  |  | 	movl 4(v), %edx | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 	addl $1, %eax | 
					
						
							|  |  |  | 	adcl $0, %edx | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	movl %eax,  (v) | 
					
						
							|  |  |  | 	movl %edx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define v %esi | 
					
						
							|  |  |  | BEGIN(dec) | 
					
						
							|  |  |  | 	subl $1,  (v) | 
					
						
							|  |  |  | 	sbbl $0, 4(v) | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define v %esi | 
					
						
							|  |  |  | BEGIN(dec_return) | 
					
						
							|  |  |  | 	movl  (v), %eax | 
					
						
							|  |  |  | 	movl 4(v), %edx | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 	subl $1, %eax | 
					
						
							|  |  |  | 	sbbl $0, %edx | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	movl %eax,  (v) | 
					
						
							|  |  |  | 	movl %edx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-20 16:22:04 +00:00
										 |  |  | #define v %esi | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | BEGIN(add_unless) | 
					
						
							| 
									
										
										
										
											2012-01-20 16:22:04 +00:00
										 |  |  | 	addl %eax, %ecx | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 	adcl %edx, %edi | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	addl  (v), %eax | 
					
						
							|  |  |  | 	adcl 4(v), %edx | 
					
						
							| 
									
										
										
										
											2012-01-20 16:22:04 +00:00
										 |  |  | 	cmpl %eax, %ecx | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 	je 3f | 
					
						
							|  |  |  | 1: | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	movl %eax,  (v) | 
					
						
							|  |  |  | 	movl %edx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-03-01 19:55:46 +01:00
										 |  |  | 	movl $1, %eax | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 2: | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	RET | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 3: | 
					
						
							|  |  |  | 	cmpl %edx, %edi | 
					
						
							|  |  |  | 	jne 1b | 
					
						
							| 
									
										
										
										
											2010-03-01 19:55:46 +01:00
										 |  |  | 	xorl %eax, %eax | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 	jmp 2b | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #define v %esi | 
					
						
							|  |  |  | BEGIN(inc_not_zero) | 
					
						
							|  |  |  | 	movl  (v), %eax | 
					
						
							|  |  |  | 	movl 4(v), %edx | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 	testl %eax, %eax | 
					
						
							|  |  |  | 	je 3f | 
					
						
							|  |  |  | 1: | 
					
						
							|  |  |  | 	addl $1, %eax | 
					
						
							|  |  |  | 	adcl $0, %edx | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	movl %eax,  (v) | 
					
						
							|  |  |  | 	movl %edx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-03-01 19:55:49 +01:00
										 |  |  | 	movl $1, %eax | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 2: | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	RET | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 3: | 
					
						
							|  |  |  | 	testl %edx, %edx | 
					
						
							|  |  |  | 	jne 1b | 
					
						
							|  |  |  | 	jmp 2b | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #define v %esi | 
					
						
							|  |  |  | BEGIN(dec_if_positive) | 
					
						
							|  |  |  | 	movl  (v), %eax | 
					
						
							|  |  |  | 	movl 4(v), %edx | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 	subl $1, %eax | 
					
						
							|  |  |  | 	sbbl $0, %edx | 
					
						
							|  |  |  | 	js 1f | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | 	movl %eax,  (v) | 
					
						
							|  |  |  | 	movl %edx, 4(v) | 
					
						
							| 
									
										
										
										
											2010-02-24 10:54:25 +01:00
										 |  |  | 1: | 
					
						
							| 
									
										
										
										
											2010-08-12 07:00:35 -07:00
										 |  |  | RET_ENDP | 
					
						
							| 
									
										
										
										
											2010-08-06 04:04:38 +02:00
										 |  |  | #undef v |