195 lines
2.6 KiB
ArmAsm
195 lines
2.6 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>
|
||
|
#include <asm/dwarf2.h>
|
||
|
|
||
|
/* if you want SMP support, implement these with real spinlocks */
|
||
|
.macro LOCK reg
|
||
|
pushfl_cfi
|
||
|
cli
|
||
|
.endm
|
||
|
|
||
|
.macro UNLOCK reg
|
||
|
popfl_cfi
|
||
|
.endm
|
||
|
|
||
|
#define BEGIN(op) \
|
||
|
.macro endp; \
|
||
|
CFI_ENDPROC; \
|
||
|
ENDPROC(atomic64_##op##_386); \
|
||
|
.purgem endp; \
|
||
|
.endm; \
|
||
|
ENTRY(atomic64_##op##_386); \
|
||
|
CFI_STARTPROC; \
|
||
|
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
|