Browse Source

+ atomic operations for RV32

florian 6 months ago
parent
commit
cd76562339
3 changed files with 116 additions and 40 deletions
  1. 21 0
      rtl/riscv/riscv.inc
  2. 90 25
      rtl/riscv32/riscv32.inc
  3. 5 15
      rtl/riscv64/riscv64.inc

+ 21 - 0
rtl/riscv/riscv.inc

@@ -15,6 +15,10 @@
 
  **********************************************************************}
 
+{****************************************************************************
+                       stack frame related stuff
+****************************************************************************}
+
 {$IFNDEF INTERNAL_BACKTRACE}
 {$define FPC_SYSTEM_HAS_GET_FRAME}
 function get_frame:pointer;assembler;nostackframe;
@@ -197,3 +201,20 @@ procedure WriteBarrier; assembler; nostackframe;
   asm
     fence ow, ow
   end;
+
+{****************************************************************************
+                       atomic operations
+****************************************************************************}
+
+{$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
+  function declocked(var l: longint) : boolean; inline;
+  begin
+    Result:=InterLockedDecrement(l) = 0;
+  end;
+
+
+{$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
+  procedure inclocked(var l: longint); inline;
+  begin
+    InterLockedIncrement(l);
+  end;

+ 90 - 25
rtl/riscv32/riscv32.inc

@@ -18,6 +18,9 @@
 { Common RiscV stuff }
 {$I ../riscv/riscv.inc}
 
+{****************************************************************************
+                       stack frame related stuff
+****************************************************************************}
 
 {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
 function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;
@@ -32,47 +35,109 @@ function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;
     lw a0, -4*2(a0)
   end;
 
+{****************************************************************************
+                       atomic operations
+****************************************************************************}
 
-{$ifdef VER3_2}
-function InterLockedDecrement (var Target: longint) : longint;
-  begin
-    dec(Target);
-    Result:=Target;
-  end;
 
+{ while some of the functions below could be shared with RiscV 64, this makes no sense imo
+  to scatter those functions around }
 
-function InterLockedIncrement (var Target: longint) : longint;
-  begin
-    inc(Target);
-    Result:=Target;
+{$ifdef VER3_2}
+function InterLockedDecrement (var Target: longint) : longint; assembler; nostackframe;
+{$else VER3_2}
+{$define FPC_SYSTEM_HAS_ATOMIC_DEC_32}
+function fpc_atomic_dec_32 (var Target: longint) : longint; assembler; nostackframe;
+{$endif VER3_2}
+  asm
+{$ifdef CPURV_HAS_ATOMIC}
+    addi a1, x0, -1
+    amoadd.w a0, a1, (a0)
+    add a0, a0, a1
+{$else CPURV_HAS_ATOMIC}
+    lw a1, 0(a0)
+    addi a1, a1, -1
+    sw a1, 0(a0)
+    addi a0, a1, 0
+{$endif CPURV_HAS_ATOMIC}
   end;
 
 
-function InterLockedExchange (var Target: longint;Source : longint) : longint;
-  begin
-    Result:=Target;
-    Target:=Source;
+{$ifdef VER3_2}
+function InterLockedIncrement (var Target: longint) : longint; assembler; nostackframe;
+{$else VER3_2}
+{$define FPC_SYSTEM_HAS_ATOMIC_INC_32}
+function fpc_atomic_inc_32 (var Target: longint) : longint; assembler; nostackframe;
+{$endif VER3_2}
+  asm
+{$ifdef CPURV_HAS_ATOMIC}
+    addi a1, x0, 1
+    amoadd.w a0, a1, (a0)
+    add a0, a0, a1
+{$else CPURV_HAS_ATOMIC}
+    lw a1, 0(a0)
+    addi a1, a1, 1
+    sw a1, 0(a0)
+    addi a0, a1, 0
+{$endif CPURV_HAS_ATOMIC}
   end;
 
 
-function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint;
-  begin
-    Result:=Target;
-    inc(Target,Source);
+{$ifdef VER3_2}
+function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler; nostackframe;
+{$else VER3_2}
+{$define FPC_SYSTEM_HAS_ATOMIC_XCHG_32}
+function fpc_atomic_xchg_32 (var Target: longint;Source : longint) : longint; assembler; nostackframe;
+{$endif VER3_2}
+  asm
+{$ifdef CPURV_HAS_ATOMIC}
+    amoswap.w a0, a1, (a0)
+{$else CPURV_HAS_ATOMIC}
+    lw a2, 0(a0)
+    sw a1, 0(a0)
+    addi a0, a2, 0
+{$endif CPURV_HAS_ATOMIC}
   end;
-{$endif}
 
 
 {$ifdef VER3_2}
-function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint;
+function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler; nostackframe;
 {$else VER3_2}
 {$define FPC_SYSTEM_HAS_ATOMIC_CMP_XCHG_32}
-function fpc_atomic_cmp_xchg_32 (var Target: longint; NewValue: longint; Comparand: longint) : longint; [public,alias:'FPC_ATOMIC_CMP_XCHG_32'];
+function fpc_atomic_cmp_xchg_32 (var Target: longint; NewValue: longint; Comparand: longint) : longint; [public,alias:'FPC_ATOMIC_CMP_XCHG_32']; assembler; nostackframe;
 {$endif VER3_2}
-  begin
-    Result:=Target;
-    if Target={$ifdef VER3_2}Comperand{$else}Comparand{$endif} then
-      Target:=NewValue;
+  asm
+{$ifdef CPURV_HAS_ATOMIC}
+  .LLoop:
+    lr.w a3, 0(a0)
+    bne a3, a2, .LFail
+    sc.w a4, a1, 0(a0)
+    bne a4, x0, .LLoop
+  .LFail:
+    addi a0, a3, 0
+{$else CPURV_HAS_ATOMIC}
+    lw a3, 0(a0)
+    bne a3, a2, .LFail
+    sw a1, 0(a0)
+  .LFail:
+    addi a0, a3, 0
+{$endif CPURV_HAS_ATOMIC}
   end;
 
 
+{$ifdef VER3_2}
+function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler; nostackframe;
+{$else VER3_2}
+{$define FPC_SYSTEM_HAS_ATOMIC_ADD_32}
+function fpc_atomic_add_32 (var Target: longint;Value: longint) : longint; assembler; nostackframe;
+{$endif VER3_2}
+  asm
+{$ifdef CPURV_HAS_ATOMIC}
+    amoadd.w a0, a1, (a0)
+{$else CPURV_HAS_ATOMIC}
+    lw a2, 0(a0)
+    add a2, a2, a1
+    sw a2, 0(a0)
+    addi a0, a2, 0
+{$endif CPURV_HAS_ATOMIC}
+  end;

+ 5 - 15
rtl/riscv64/riscv64.inc

@@ -18,6 +18,10 @@
 { Common RiscV stuff }
 {$I ../riscv/riscv.inc}
 
+{****************************************************************************
+                       stack frame related stuff
+****************************************************************************}
+
 {$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
 function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;
   asm
@@ -32,7 +36,7 @@ function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;
   end;
 
 {****************************************************************************
-                       stack frame related stuff
+                       atomic operations
 ****************************************************************************}
 
 {$ifdef VER3_2}
@@ -235,20 +239,6 @@ function fpc_atomic_add_64 (var Target: int64;Value : int64) : int64; assembler;
   end;
 
 
-{$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
-  function declocked(var l: longint) : boolean; inline;
-  begin
-    Result:=InterLockedDecrement(l) = 0;
-  end;
-
-
-{$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
-  procedure inclocked(var l: longint); inline;
-  begin
-    InterLockedIncrement(l);
-  end;
-
-
 {$define FPC_SYSTEM_HAS_DECLOCKED_INT64}
 function declocked(var l:int64):boolean;
   begin