200 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * 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.h>
 | |
| 
 | |
| /* if you want SMP support, implement these with real spinlocks */
 | |
| .macro IRQ_SAVE reg
 | |
| 	pushfl
 | |
| 	cli
 | |
| .endm
 | |
| 
 | |
| .macro IRQ_RESTORE reg
 | |
| 	popfl
 | |
| .endm
 | |
| 
 | |
| #define BEGIN_IRQ_SAVE(op) \
 | |
| .macro endp; \
 | |
| ENDPROC(atomic64_##op##_386); \
 | |
| .purgem endp; \
 | |
| .endm; \
 | |
| ENTRY(atomic64_##op##_386); \
 | |
| 	IRQ_SAVE v;
 | |
| 
 | |
| #define ENDP endp
 | |
| 
 | |
| #define RET \
 | |
| 	IRQ_RESTORE v; \
 | |
| 	RET
 | |
| 
 | |
| #define v %ecx
 | |
| BEGIN_IRQ_SAVE(read)
 | |
| 	movl  (v), %eax
 | |
| 	movl 4(v), %edx
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %esi
 | |
| BEGIN_IRQ_SAVE(set)
 | |
| 	movl %ebx,  (v)
 | |
| 	movl %ecx, 4(v)
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v  %esi
 | |
| BEGIN_IRQ_SAVE(xchg)
 | |
| 	movl  (v), %eax
 | |
| 	movl 4(v), %edx
 | |
| 	movl %ebx,  (v)
 | |
| 	movl %ecx, 4(v)
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %ecx
 | |
| BEGIN_IRQ_SAVE(add)
 | |
| 	addl %eax,  (v)
 | |
| 	adcl %edx, 4(v)
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %ecx
 | |
| BEGIN_IRQ_SAVE(add_return)
 | |
| 	addl  (v), %eax
 | |
| 	adcl 4(v), %edx
 | |
| 	movl %eax,  (v)
 | |
| 	movl %edx, 4(v)
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %ecx
 | |
| BEGIN_IRQ_SAVE(sub)
 | |
| 	subl %eax,  (v)
 | |
| 	sbbl %edx, 4(v)
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %ecx
 | |
| BEGIN_IRQ_SAVE(sub_return)
 | |
| 	negl %edx
 | |
| 	negl %eax
 | |
| 	sbbl $0, %edx
 | |
| 	addl  (v), %eax
 | |
| 	adcl 4(v), %edx
 | |
| 	movl %eax,  (v)
 | |
| 	movl %edx, 4(v)
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %esi
 | |
| BEGIN_IRQ_SAVE(inc)
 | |
| 	addl $1,  (v)
 | |
| 	adcl $0, 4(v)
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %esi
 | |
| BEGIN_IRQ_SAVE(inc_return)
 | |
| 	movl  (v), %eax
 | |
| 	movl 4(v), %edx
 | |
| 	addl $1, %eax
 | |
| 	adcl $0, %edx
 | |
| 	movl %eax,  (v)
 | |
| 	movl %edx, 4(v)
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %esi
 | |
| BEGIN_IRQ_SAVE(dec)
 | |
| 	subl $1,  (v)
 | |
| 	sbbl $0, 4(v)
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %esi
 | |
| BEGIN_IRQ_SAVE(dec_return)
 | |
| 	movl  (v), %eax
 | |
| 	movl 4(v), %edx
 | |
| 	subl $1, %eax
 | |
| 	sbbl $0, %edx
 | |
| 	movl %eax,  (v)
 | |
| 	movl %edx, 4(v)
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %esi
 | |
| BEGIN_IRQ_SAVE(add_unless)
 | |
| 	addl %eax, %ecx
 | |
| 	adcl %edx, %edi
 | |
| 	addl  (v), %eax
 | |
| 	adcl 4(v), %edx
 | |
| 	cmpl %eax, %ecx
 | |
| 	je 3f
 | |
| 1:
 | |
| 	movl %eax,  (v)
 | |
| 	movl %edx, 4(v)
 | |
| 	movl $1, %eax
 | |
| 2:
 | |
| 	RET_IRQ_RESTORE
 | |
| 3:
 | |
| 	cmpl %edx, %edi
 | |
| 	jne 1b
 | |
| 	xorl %eax, %eax
 | |
| 	jmp 2b
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %esi
 | |
| BEGIN_IRQ_SAVE(inc_not_zero)
 | |
| 	movl  (v), %eax
 | |
| 	movl 4(v), %edx
 | |
| 	testl %eax, %eax
 | |
| 	je 3f
 | |
| 1:
 | |
| 	addl $1, %eax
 | |
| 	adcl $0, %edx
 | |
| 	movl %eax,  (v)
 | |
| 	movl %edx, 4(v)
 | |
| 	movl $1, %eax
 | |
| 2:
 | |
| 	RET_IRQ_RESTORE
 | |
| 3:
 | |
| 	testl %edx, %edx
 | |
| 	jne 1b
 | |
| 	jmp 2b
 | |
| ENDP
 | |
| #undef v
 | |
| 
 | |
| #define v %esi
 | |
| BEGIN_IRQ_SAVE(dec_if_positive)
 | |
| 	movl  (v), %eax
 | |
| 	movl 4(v), %edx
 | |
| 	subl $1, %eax
 | |
| 	sbbl $0, %edx
 | |
| 	js 1f
 | |
| 	movl %eax,  (v)
 | |
| 	movl %edx, 4(v)
 | |
| 1:
 | |
| 	RET_IRQ_RESTORE
 | |
| ENDP
 | |
| #undef v
 |