Browse Source

Add more specialized atomics for i386 and x86-64.

Rika Ichinose 8 months ago
parent
commit
bb43afd26d
2 changed files with 166 additions and 0 deletions
  1. 129 0
      rtl/i386/i386.inc
  2. 37 0
      rtl/x86_64/x86_64.inc

+ 129 - 0
rtl/i386/i386.inc

@@ -2523,6 +2523,135 @@ begin
 end;
 end;
 
 
 
 
+{$ifndef VER3_2}
+{$define FPC_SYSTEM_HAS_ATOMIC_CMP_XCHG_8}
+function fpc_atomic_cmp_xchg_8(var Target: shortint; NewValue: shortint; Comparand: shortint): shortint; assembler; nostackframe;
+asm
+        xchgl    %eax,%ecx
+        lock
+        cmpxchgb %dl,(%ecx)
+end;
+
+{$define FPC_SYSTEM_HAS_ATOMIC_CMP_XCHG_16}
+function fpc_atomic_cmp_xchg_16(var Target: smallint; NewValue: smallint; Comparand: smallint): smallint; assembler; nostackframe;
+asm
+        xchgl    %eax,%ecx
+        lock
+        cmpxchgw %dx,(%ecx)
+end;
+
+{$define FPC_SYSTEM_HAS_ATOMIC_XCHG_64}
+function fpc_atomic_xchg_64(var Target: int64; Source: int64): int64; assembler; nostackframe;
+{ eax = Target, [esp + 4] = Source. }
+asm
+        pushl       %ebx
+        pushl       %edi
+        movl        %eax,%edi
+        movl        8+4(%esp),%ebx
+        movl        8+8(%esp),%ecx
+.LAgain:
+        movl        (%edi),%eax
+        movl        4(%edi),%edx
+        lock cmpxchg8b (%edi)
+        jne         .LAgain
+        pop         %edi
+        pop         %ebx
+end;
+
+{$define FPC_SYSTEM_HAS_ATOMIC_SUB_32}
+function fpc_atomic_sub_32(var Target: longint; Value: longint): longint; assembler; nostackframe;
+asm
+        neg     %edx
+        lock
+        xaddl   %edx, (%eax)
+        movl    %edx,%eax
+end;
+
+{$define FPC_SYSTEM_HAS_ATOMIC_INC_64}
+function fpc_atomic_inc_64(var Target: int64): int64; assembler; nostackframe;
+{ eax = Target. }
+asm
+        pushl       %ebx
+        pushl       %edi
+        movl        %eax,%edi
+.LAgain:
+        movl        (%edi),%eax
+        movl        4(%edi),%edx
+        movl        %eax,%ebx { ecx:ebx := edx:eax + 1. }
+        movl        %edx,%ecx
+        addl        $1,%ebx
+        adcl        $0,%ecx
+        lock cmpxchg8b (%edi)
+        jne         .LAgain
+        movl        %ebx,%eax
+        movl        %ecx,%edx
+        pop         %edi
+        pop         %ebx
+end;
+
+{$define FPC_SYSTEM_HAS_ATOMIC_DEC_64}
+function fpc_atomic_dec_64(var Target: int64): int64; assembler; nostackframe;
+{ eax = Target. }
+asm
+        pushl       %ebx
+        pushl       %edi
+        movl        %eax,%edi
+.LAgain:
+        movl        (%edi),%eax
+        movl        4(%edi),%edx
+        movl        %eax,%ebx { ecx:ebx := edx:eax - 1. }
+        movl        %edx,%ecx
+        subl        $1,%ebx
+        sbbl        $0,%ecx
+        lock cmpxchg8b (%edi)
+        jne         .LAgain
+        movl        %ebx,%eax
+        movl        %ecx,%edx
+        pop         %edi
+        pop         %ebx
+end;
+
+{$define FPC_SYSTEM_HAS_ATOMIC_ADD_64}
+function fpc_atomic_add_64(var Target: int64; Value: int64): int64; assembler; nostackframe;
+{ eax = Target, [esp + 4] = Value. }
+asm
+        pushl       %ebx
+        pushl       %edi
+        movl        %eax,%edi
+.LAgain:
+        movl        (%edi),%eax
+        movl        4(%edi),%edx
+        movl        %eax,%ebx { ecx:ebx := edx:eax + Value. }
+        movl        %edx,%ecx
+        addl        8+4(%esp),%ebx
+        adcl        8+8(%esp),%ecx
+        lock cmpxchg8b (%edi)
+        jne         .LAgain
+        pop         %edi
+        pop         %ebx
+end;
+
+{$define FPC_SYSTEM_HAS_ATOMIC_SUB_64}
+function fpc_atomic_sub_64(var Target: int64; Value: int64): int64; assembler; nostackframe;
+{ eax = Target, [esp + 4] = Value. }
+asm
+        pushl       %ebx
+        pushl       %edi
+        movl        %eax,%edi
+.LAgain:
+        movl        (%edi),%eax
+        movl        4(%edi),%edx
+        movl        %eax,%ebx { ecx:ebx := edx:eax - Value. }
+        movl        %edx,%ecx
+        subl        8+4(%esp),%ebx
+        sbbl        8+8(%esp),%ecx
+        lock cmpxchg8b (%edi)
+        jne         .LAgain
+        pop         %edi
+        pop         %ebx
+end;
+{$endif VER3_2}
+
 {$ifdef VER3_2}
 {$ifdef VER3_2}
 function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
 function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
 {$else VER3_2}
 {$else VER3_2}

+ 37 - 0
rtl/x86_64/x86_64.inc

@@ -1417,6 +1417,43 @@ procedure inclocked(var l : int64);assembler; nostackframe;
   end;
   end;
 
 
 
 
+{$ifndef VER3_2}
+{$define FPC_SYSTEM_HAS_ATOMIC_CMP_XCHG_8}
+function fpc_atomic_cmp_xchg_8(var Target: shortint; NewValue: shortint; Comparand: shortint): shortint; assembler; nostackframe;
+asm
+        movl            {$ifdef win64} %r8d {$else} %edx {$endif},%eax
+        lock
+        cmpxchgb        NewValue,({$ifdef win64} %rcx {$else} %rdi {$endif})
+end;
+
+{$define FPC_SYSTEM_HAS_ATOMIC_CMP_XCHG_16}
+function fpc_atomic_cmp_xchg_16(var Target: smallint; NewValue: smallint; Comparand: smallint): smallint; assembler; nostackframe;
+asm
+        movl            {$ifdef win64} %r8d {$else} %edx {$endif},%eax
+        lock
+        cmpxchgw        NewValue,({$ifdef win64} %rcx {$else} %rdi {$endif})
+end;
+
+{$define FPC_SYSTEM_HAS_ATOMIC_SUB_32}
+function fpc_atomic_sub_32(var Target: longint; Value: longint): longint; assembler; nostackframe;
+asm
+        negl    Value
+        lock
+        xaddl   Value,({$ifdef win64} %rcx {$else} %rdi {$endif})
+        movl    Value,%eax
+end;
+
+{$define FPC_SYSTEM_HAS_ATOMIC_SUB_64}
+function fpc_atomic_sub_64(var Target: int64; Value: int64): int64; assembler; nostackframe;
+asm
+        negq    Value
+        lock
+        xaddq   Value,({$ifdef win64} %rcx {$else} %rdi {$endif})
+        movq    Value,%rax
+end;
+{$endif VER3_2}
+
+
 {$ifdef VER3_2}
 {$ifdef VER3_2}
 function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
 function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
 {$else VER3_2}
 {$else VER3_2}