/* * 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 #include #include /* if you want SMP support, implement these with real spinlocks */ .macro LOCK reg pushfl CFI_ADJUST_CFA_OFFSET 4 cli .endm .macro UNLOCK reg popfl CFI_ADJUST_CFA_OFFSET -4 .endm .macro BEGIN func reg $v = \reg ENTRY(atomic64_\func\()_386) CFI_STARTPROC LOCK $v .macro RETURN UNLOCK $v ret .endm .macro END_ CFI_ENDPROC ENDPROC(atomic64_\func\()_386) .purgem RETURN .purgem END_ .purgem END .endm .macro END RETURN END_ .endm .endm BEGIN read %ecx movl ($v), %eax movl 4($v), %edx END BEGIN set %esi movl %ebx, ($v) movl %ecx, 4($v) END BEGIN xchg %esi movl ($v), %eax movl 4($v), %edx movl %ebx, ($v) movl %ecx, 4($v) END BEGIN add %ecx addl %eax, ($v) adcl %edx, 4($v) END BEGIN add_return %ecx addl ($v), %eax adcl 4($v), %edx movl %eax, ($v) movl %edx, 4($v) END BEGIN sub %ecx subl %eax, ($v) sbbl %edx, 4($v) END BEGIN sub_return %ecx negl %edx negl %eax sbbl $0, %edx addl ($v), %eax adcl 4($v), %edx movl %eax, ($v) movl %edx, 4($v) END BEGIN inc %esi addl $1, ($v) adcl $0, 4($v) END BEGIN inc_return %esi movl ($v), %eax movl 4($v), %edx addl $1, %eax adcl $0, %edx movl %eax, ($v) movl %edx, 4($v) END BEGIN dec %esi subl $1, ($v) sbbl $0, 4($v) END BEGIN dec_return %esi movl ($v), %eax movl 4($v), %edx subl $1, %eax sbbl $0, %edx movl %eax, ($v) movl %edx, 4($v) END BEGIN add_unless %ecx addl %eax, %esi adcl %edx, %edi addl ($v), %eax adcl 4($v), %edx cmpl %eax, %esi je 3f 1: movl %eax, ($v) movl %edx, 4($v) movl $1, %eax 2: RETURN 3: cmpl %edx, %edi jne 1b xorl %eax, %eax jmp 2b END_ BEGIN inc_not_zero %esi 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: RETURN 3: testl %edx, %edx jne 1b jmp 2b END_ BEGIN dec_if_positive %esi movl ($v), %eax movl 4($v), %edx subl $1, %eax sbbl $0, %edx js 1f movl %eax, ($v) movl %edx, 4($v) 1: END