| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732 | {    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);[public, alias: 'FPC_SETFSR'];  begin    DefaultFPUControlWord:=fsr;    asm      ld fsr,%fsr    end;  end;function GetNativeFPUControlWord: TNativeFPUControlWord; {$if defined(SYSTEMINLINE)}inline;{$endif}  begin    result:=get_fsr;  end;procedure SetNativeFPUControlWord(const cw: TNativeFPUControlWord); {$if defined(SYSTEMINLINE)}inline;{$endif}  begin    set_fsr(cw);  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);    softfloat_exception_mask:=[float_flag_underflow,float_flag_overflow,float_flag_inexact,float_flag_denormal];    softfloat_exception_flags:=[];  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:longint);[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;{$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}
 |