Просмотр исходного кода

+ SPARC64 specific system unit code, derived from SPARC32, needs still to be adapted

git-svn-id: trunk@36433 -
florian 8 лет назад
Родитель
Сommit
053124f78a
2 измененных файлов с 971 добавлено и 0 удалено
  1. 1 0
      .gitattributes
  2. 970 0
      rtl/sparc64/sparc64.inc

+ 1 - 0
.gitattributes

@@ -9956,6 +9956,7 @@ rtl/sparc64/int64p.inc svneol=native#text/plain
 rtl/sparc64/makefile.cpu svneol=native#text/plain
 rtl/sparc64/math.inc svneol=native#text/plain
 rtl/sparc64/set.inc svneol=native#text/plain
+rtl/sparc64/sparc64.inc svneol=native#text/plain
 rtl/symbian/Makefile svneol=native#text/plain
 rtl/symbian/Makefile.fpc svneol=native#text/plain
 rtl/symbian/bindings/pbeexe.cpp -text

+ 970 - 0
rtl/sparc64/sparc64.inc

@@ -0,0 +1,970 @@
+{
+
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2002-2004 by the Free Pascal development team.
+
+    Processor dependent implementation for the system unit for
+    Sparc
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+
+{****************************************************************************
+                           SPARC specific stuff
+****************************************************************************}
+function get_fsr : dword;assembler;[public, alias: 'FPC_GETFSR'];
+  var
+    fsr : dword;
+  asm
+    st %fsr,fsr
+    ld fsr,%l0
+    st %l0,__result
+  end;
+
+
+procedure set_fsr(fsr : dword);assembler;[public, alias: 'FPC_SETFSR'];
+  var
+    _fsr : dword;
+  asm
+    // force memory location
+    st fsr,_fsr
+    ld _fsr,%fsr
+  end;
+
+
+function get_got : pointer;assembler;nostackframe;[public, alias: 'FPC_GETGOT'];
+  asm
+    retl
+    add %o7,%l7,%l7
+  end;
+
+
+{$define FPC_SYSTEM_HAS_SYSINITFPU}
+Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
+  begin
+    { enable div by 0 and invalid operation fpu exceptions
+      round towards zero; ieee compliant arithmetics }
+    set_fsr((get_fsr and $3fbfffff) or $09000000);
+  end;
+
+{$define FPC_SYSTEM_HAS_SYSRESETFPU}
+Procedure SysResetFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
+  begin
+  end;
+
+
+procedure fpc_cpuinit;
+  begin
+    SysResetFPU;
+    if not(IsLibrary) then
+      SysInitFPU;
+  end;
+
+
+{$define FPC_SYSTEM_HAS_GET_FRAME}
+function get_frame:pointer;assembler;nostackframe;
+  asm
+    mov %fp,%o0
+  end;
+
+
+{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
+function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
+  asm
+    { framebp = %o0 }
+    subcc   %o0,0,%o0
+    be      .Lframezero
+    nop
+    { flush register windows, so they are stored in the stack }
+    ta      3
+    ld [%o0+60],%o0
+    { check if new %o0 register is zero }
+    subcc   %o0,0,%o0
+    be      .Lframezero
+    nop
+    { if not zero, add 8 to skip jmpl and delay slot }
+    add %o0,8,%o0
+.Lframezero:
+  end;
+
+
+{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
+function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
+  asm
+    { framebp = %o0 }
+    subcc   %o0,0,%o0
+    be      .Lframezero
+    nop
+    { flush register windows, so they are stored in the stack }
+    ta      3
+    ld [%o0+56],%o0
+.Lframezero:
+  end;
+
+
+{$define FPC_SYSTEM_HAS_SPTR}
+function Sptr:Pointer;assembler;nostackframe;
+  asm
+    mov %sp,%o0
+  end;
+
+
+{$ifndef FPC_SYSTEM_HAS_MOVE}
+{$define FPC_SYSTEM_HAS_MOVE}
+procedure Move(const source;var dest;count:{$ifdef MOVE_HAS_SIZEUINT_COUNT}SizeUInt{$else}SizeInt{$endif});[public, alias: 'FPC_MOVE'];assembler;
+{
+  Registers:
+    %l0 temp. to do copying
+    %l1 inc/decrement
+    %l2/l3/l4/l5 qword move
+}
+  asm
+    // count < 0 ?
+    cmp %g0,%i2
+    bge .Lmoveexit
+    nop
+
+    // possible overlap?
+    cmp %i0,%i1
+    bcc .Lnopossibleoverlap
+    nop
+    // source < dest ....
+    add %i0,%i2,%l0
+    // overlap?
+    cmp %l0,%i1
+    // source+count < dest ?
+    bcs .Lnopossibleoverlap
+    nop
+
+  .Lcopybackward:
+    // check alignment of source and dest
+    or %i0,%i1,%l0
+
+    // move src and dest to the end of the blocks
+    // assuming 16 byte block size
+    sub %i2,1,%l1
+    add %i0,%l1,%i0
+    add %i1,%l1,%i1
+{
+    // everything 16 byte aligned ?
+    andcc %l0,15,%l0
+    be .Lmovetwordwise
+    // load direction in delay slot
+    mov -16,%l1
+
+    // adjust according to block size
+    add %i0,8,%i0
+    add %i1,8,%i1
+    andcc %l0,7,%l0
+    be .Lmoveqwordwise
+    mov -8,%l1
+
+// adjust according to block size
+    add %i0,4,%i0
+    add %i1,4,%i1
+    andcc %l0,3,%l0
+    be .Lmovedwordwise
+    mov -4,%l1
+
+// adjust according to block size
+    add %i0,2,%i0
+    add %i1,2,%i1
+    andcc %l0,1,%l0
+    be .Lmovewordwise
+    mov -2,%l1
+
+// adjust according to block size
+    add %i0,1,%i0
+    add %i1,1,%i1
+}
+    ba .Lmovebytewise
+    mov -1,%l1
+
+  .Lnopossibleoverlap:
+    // check alignment of source and dest
+    or %i0,%i1,%l0
+
+    // everything 16 byte aligned ?
+    andcc %l0,15,%l0
+    be .Lmovetwordwise
+    // load direction in delay slot
+    mov 16,%l1
+    andcc %l0,7,%l0
+    be .Lmoveqwordwise
+    mov 8,%l1
+    andcc %l0,3,%l0
+    be .Lmovedwordwise
+    mov 4,%l1
+    andcc %l0,1,%l0
+    be .Lmovewordwise
+    mov 2,%l1
+    ba .Lmovebytewise
+    mov 1,%l1
+
+  .Lmovetwordwise:
+    srl %i2,4,%l6
+    cmp %g0,%l6
+    sll %l6,4,%l7
+    be .Lmoveqwordwise_shift
+    nop
+
+  .Lmovetwordwise_loop:
+    ld [%i0],%l2
+    ld [%i0+4],%l3
+    subcc %l6,1,%l6
+    ld [%i0+8],%l4
+    ld [%i0+12],%l5
+    add %i0,%l1,%i0
+    st  %l2,[%i1]
+    st  %l3,[%i1+4]
+    st  %l4,[%i1+8]
+    st  %l5,[%i1+12]
+    add %i1,%l1,%i1
+    bne .Lmovetwordwise_loop
+    nop
+    subcc %i2,%l7,%i2
+    be .Lmoveexit
+    nop
+
+  .Lmoveqwordwise_shift:
+    sra %l1,1,%l1
+  .Lmoveqwordwise:
+    srl %i2,3,%l6
+    cmp %g0,%l6
+    sll %l6,3,%l7
+    be .Lmovedwordwise_shift
+    nop
+
+  .Lmoveqwordwise_loop:
+    ld [%i0],%l2
+    ld [%i0+4],%l3
+    subcc %l6,1,%l6
+    add %i0,%l1,%i0
+    st  %l2,[%i1]
+    st  %l3,[%i1+4]
+    add %i1,%l1,%i1
+    bne .Lmoveqwordwise_loop
+    nop
+    subcc %i2,%l7,%i2
+    be .Lmoveexit
+    nop
+
+  .Lmovedwordwise_shift:
+    sra %l1,1,%l1
+  .Lmovedwordwise:
+    srl %i2,2,%l6
+    cmp %g0,%l6
+    sll %l6,2,%l7
+    be .Lmovewordwise_shift
+    nop
+
+  .Lmovedwordwise_loop:
+    ld [%i0],%l0
+    subcc %l6,1,%l6
+    add %i0,%l1,%i0
+    st %l0,[%i1]
+    add %i1,%l1,%i1
+    bne .Lmovedwordwise_loop
+    nop
+    subcc %i2,%l7,%i2
+    be .Lmoveexit
+    nop
+
+  .Lmovewordwise_shift:
+    sra %l1,1,%l1
+  .Lmovewordwise:
+    srl %i2,1,%l6
+    cmp %g0,%l6
+    sll %l6,1,%l7
+    be .Lmovebytewise_shift
+    nop
+
+  .Lmovewordwise_loop:
+    lduh [%i0],%l0
+    subcc %l6,1,%l6
+    add %i0,%l1,%i0
+    sth %l0,[%i1]
+    add %i1,%l1,%i1
+    bne .Lmovewordwise_loop
+    nop
+    subcc %i2,%l7,%i2
+    be .Lmoveexit
+    nop
+
+  .Lmovebytewise_shift:
+    sra %l1,1,%l1
+  .Lmovebytewise:
+    cmp %g0,%i2
+    be .Lmoveexit
+    nop
+
+    ldub [%i0],%l0
+    subcc %i2,1,%i2
+    add %i0,%l1,%i0
+    stb %l0,[%i1]
+    add %i1,%l1,%i1
+    bne .Lmovebytewise
+    nop
+  .Lmoveexit:
+  end;
+{$endif FPC_SYSTEM_HAS_MOVE}
+
+
+{****************************************************************************
+                               Integer math
+****************************************************************************}
+
+var
+  fpc_system_lock : byte;export name 'fpc_system_lock';
+
+
+{$define FPC_SYSTEM_HAS_DECLOCKED_LONGINT}
+function declocked(var l : longint) : boolean;assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.Ldeclocked1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .Ldeclocked1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  sub %g1,1,%g1
+  st %g1,[%i0]
+
+  subcc %g1,1,%g0
+  addx %g0,%g0,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  sub %g1,1,%g1
+  st %g1,[%o0]
+
+  subcc %g1,1,%g0
+  addx %g0,%g0,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+
+{$define FPC_SYSTEM_HAS_INCLOCKED_LONGINT}
+procedure inclocked(var l : longint);assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.Linclocked1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .Linclocked1
+  nop
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  add %g1,1,%g1
+  st %g1,[%i0]
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  add %g1,1,%g1
+  st %g1,[%o0]
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+
+function InterLockedDecrement (var Target: longint) : longint; assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.LInterLockedDecrement1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .LInterLockedDecrement1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  sub %g1,1,%g1
+  st %g1,[%i0]
+
+  mov %g1,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  sub %g1,1,%g1
+  st %g1,[%o0]
+
+  mov %g1,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+function InterLockedIncrement (var Target: longint) : longint; assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.LInterLockedIncrement1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .LInterLockedIncrement1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  add %g1,1,%g1
+  st %g1,[%i0]
+
+  mov %g1,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  add %g1,1,%g1
+  st %g1,[%o0]
+
+  mov %g1,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+
+function InterLockedExchange (var Target: longint;Source : longint) : longint; assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.LInterLockedExchange1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .LInterLockedExchange1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  st %i1,[%i0]
+
+  mov %g1,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  st %o1,[%o0]
+
+  mov %g1,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+
+function InterLockedExchangeAdd (var Target: longint;Source : longint) : longint; assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.LInterLockedExchangeAdd1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .LInterLockedExchangeAdd1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  add %g1,%i1,%i1
+  st %i1,[%i0]
+
+  mov %g1,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  add %g1,%o1,%o1
+  st %o1,[%o0]
+
+  mov %g1,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+
+function InterlockedCompareExchange(var Target: longint; NewValue: longint; Comperand: longint): longint; assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{ input:  address of target in o0, newvalue in o1, comparand in o2 }
+{ output: value stored in target before entry of the function      }
+{ side-effect: NewValue stored in target if (target = comparand)   }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.LInterlockedCompareExchange1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .LInterlockedCompareExchange1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  cmp %g1,%i2
+  bne  .LInterlockedCompareExchange2
+  nop
+  st %i1,[%i0]
+.LInterlockedCompareExchange2:
+  mov %g1,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  cmp %g1,%o2
+  bne  .LInterlockedCompareExchange2
+  nop
+  st %o1,[%o0]
+.LInterlockedCompareExchange2:
+  mov %g1,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+function InterLockedDecrement64(var Target: Int64) : Int64; assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.LInterLockedDecrement1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .LInterLockedDecrement1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  sub %g1,1,%g1
+  st %g1,[%i0]
+
+  mov %g1,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  sub %g1,1,%g1
+  st %g1,[%o0]
+
+  mov %g1,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+function InterLockedIncrement64(var Target: Int64) : Int64; assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.LInterLockedIncrement1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .LInterLockedIncrement1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  add %g1,1,%g1
+  st %g1,[%i0]
+
+  mov %g1,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  add %g1,1,%g1
+  st %g1,[%o0]
+
+  mov %g1,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+
+function InterLockedExchange64(var Target: Int64;Source : Int64) : Int64; assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.LInterLockedExchange1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .LInterLockedExchange1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  st %i1,[%i0]
+
+  mov %g1,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  st %o1,[%o0]
+
+  mov %g1,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+
+function InterLockedExchangeAdd64(var Target: Int64;Source : Int64) : Int64; assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.LInterLockedExchangeAdd1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .LInterLockedExchangeAdd1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  add %g1,%i1,%i1
+  st %i1,[%i0]
+
+  mov %g1,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  add %g1,%o1,%o1
+  st %o1,[%o0]
+
+  mov %g1,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+
+function InterlockedCompareExchange64(var Target: Int64; NewValue: Int64; Comperand: Int64): Int64; assembler;
+{$ifndef FPC_PIC}nostackframe;{$endif}
+asm
+  { usually, we shouldn't lock here so saving the stack frame for these extra intructions is
+    worse the effort, especially while waiting :)
+  }
+{ input:  address of target in o0, newvalue in o1, comparand in o2 }
+{ output: value stored in target before entry of the function      }
+{ side-effect: NewValue stored in target if (target = comparand)   }
+{$ifdef FPC_PIC}
+  sethi %hi(_GLOBAL_OFFSET_TABLE_ -8),%l7
+  or %l7,%lo(_GLOBAL_OFFSET_TABLE_ -4),%l7
+  call get_got
+  nop
+{$endif FPC_PIC}
+.LInterlockedCompareExchange1:
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  ldstub [%g1],%g1
+  cmp %g1,0
+  bne .LInterlockedCompareExchange1
+  nop
+
+{$ifdef FPC_PIC}
+  ld [%i0],%g1
+  cmp %g1,%i2
+  bne  .LInterlockedCompareExchange2
+  nop
+  st %i1,[%i0]
+.LInterlockedCompareExchange2:
+  mov %g1,%i0
+{$else not FPC_PIC}
+  ld [%o0],%g1
+  cmp %g1,%o2
+  bne  .LInterlockedCompareExchange2
+  nop
+  st %o1,[%o0]
+.LInterlockedCompareExchange2:
+  mov %g1,%o0
+{$endif FPC_PIC}
+
+  { unlock }
+  sethi %hi(fpc_system_lock), %g1
+  or %g1,%lo(fpc_system_lock), %g1
+{$ifdef FPC_PIC}
+  ld [%g1+%l7],%g1
+{$endif FPC_PIC}
+  stb %g0,[%g1]
+end;
+
+{$ifndef FPC_SYSTEM_HAS_MEM_BARRIER}
+{$define FPC_SYSTEM_HAS_MEM_BARRIER}
+
+const
+  LoadLoad   = $01;
+  StoreLoad  = $02;
+  LoadStore  = $04;
+  StoreStore = $08;
+  LookAside  = $10;
+  MemIssue   = $20;
+  Sync       = $40;
+
+{$if not(defined(SPARCV7)) and not(defined(SPARCV8))}
+{$define CPUSPARC_HAS_MEMBAR}
+{$endif}
+
+procedure ReadBarrier;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
+asm
+{$ifdef CPUSPARC_HAS_MEMBAR}
+  ba,pt .L1
+  membar LoadLoad
+.L1:
+{$endif}
+end;
+
+procedure ReadDependencyBarrier;{$ifdef SYSTEMINLINE}inline;{$endif}
+begin
+  { reads imply barrier on earlier reads depended on }
+end;
+
+procedure ReadWriteBarrier;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
+asm
+{$ifdef CPUSPARC_HAS_MEMBAR}
+  ba,pt .L1
+  membar LoadLoad + LoadStore + StoreLoad + StoreStore
+.L1:
+{$endif}
+end;
+
+procedure WriteBarrier;assembler;nostackframe;{$ifdef SYSTEMINLINE}inline;{$endif}
+asm
+{$ifdef CPUSPARC_HAS_MEMBAR}
+  ba,pt .L1
+  stbar
+.L1:
+{$endif}
+end;
+
+{$endif}
+
+{$ifndef FPC_SYSTEM_HAS_SAR_QWORD}
+{$define FPC_SYSTEM_HAS_SAR_QWORD}
+function fpc_SarInt64(Const AValue : Int64;const Shift : Byte): Int64; [Public,Alias:'FPC_SARINT64']; compilerproc; assembler; nostackframe;
+asm
+{ %o0=high(AValue) %o1=low(AValue), result: %o0:%o1 }
+    and    %o2,63,%o2
+    subcc  %o2,32,%g0
+    bcc    .L1
+    nop
+    srl    %o1,%o2,%o1
+    subcc  %o2,%g0,%g0
+    be     .Lexit
+    sra    %o0,%o2,%o0
+    sub    %g0,%o2,%o3
+    sll    %o0,%o3,%o3
+    ba     .Lexit
+    or     %o3,%o1,%o1
+.L1:
+    sra    %o0,%o2,%o1
+    sra    %o0,31,%o0
+.Lexit:
+end;
+{$endif FPC_SYSTEM_HAS_SAR_QWORD}
+