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