forked from 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.
195 lines
2.6 KiB
195 lines
2.6 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.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; \ |
|
SYM_FUNC_END(atomic64_##op##_386); \ |
|
.purgem endp; \ |
|
.endm; \ |
|
SYM_FUNC_START(atomic64_##op##_386); \ |
|
IRQ_SAVE v; |
|
|
|
#define ENDP endp |
|
|
|
#define RET_IRQ_RESTORE \ |
|
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
|
|
|