mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
2.3 KiB
187 lines
2.3 KiB
/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|
/* |
|
* atomic64_t for 386/486 |
|
* |
|
* Copyright © 2010 Luca Barbieri |
|
*/ |
|
|
|
#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; \ |
|
SYM_FUNC_END(atomic64_##op##_386); \ |
|
.purgem endp; \ |
|
.endm; \ |
|
SYM_FUNC_START(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
|
|
|