From b8755b6b2ce844996f61e168d08f9746c096022c Mon Sep 17 00:00:00 2001
From: florian <florian@freepascal.org>
Date: Sun, 18 Jun 2017 15:41:25 +0000
Subject: [PATCH] + setjmp/longjmp implementation for sparc64, based on the
 sparc one

git-svn-id: trunk@36513 -
---
 .gitattributes           |  2 +
 rtl/sparc64/setjump.inc  | 92 ++++++++++++++++++++++++++++++++++++++++
 rtl/sparc64/setjumph.inc | 24 +++++++++++
 3 files changed, 118 insertions(+)
 create mode 100644 rtl/sparc64/setjump.inc
 create mode 100644 rtl/sparc64/setjumph.inc

diff --git a/.gitattributes b/.gitattributes
index 13b8e5fe84..084bb4ad56 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -9971,6 +9971,8 @@ 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/setjump.inc svneol=native#text/plain
+rtl/sparc64/setjumph.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
diff --git a/rtl/sparc64/setjump.inc b/rtl/sparc64/setjump.inc
new file mode 100644
index 0000000000..62f8910e79
--- /dev/null
+++ b/rtl/sparc64/setjump.inc
@@ -0,0 +1,92 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2002 by Jonas Maebe and other members of the
+    Free Pascal development team
+
+    SetJmp and LongJmp implementation for exception handling
+
+    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.
+
+ **********************************************************************}
+{#define ENV(base,reg) [%base + (reg * 4)]
+#define ST_FLUSH_WINDOWS 3
+#define RW_FP [%fp + 0x48]
+}
+
+procedure fpc_longjmp(var s : jmp_buf;value:longint);assembler;nostackframe;[Public,alias:'FPC_LONGJMP'];compilerproc;
+  asm
+    // Store our arguments in global registers so we can still
+    // use them while unwinding frames and their register windows.
+
+    ld [%o0+4], %g3         // Cache target FP in register %g3.
+    mov %o0, %g1            // s in %g1
+    orcc %o1, %g0, %g2      // value in %g2
+    be,a .L0                // Branch if zero; else skip delay slot.
+    mov 1, %g2              // Delay slot only hit if zero: VAL = 1.
+.L0:
+    xor %fp, %g3, %o0
+    add %fp, 512, %o1
+    andncc %o0, 4095, %o0
+    bne .Lthread
+    cmp %o1, %g3
+    bl .Lthread
+
+    // Now we will loop, unwinding the register windows up the stack
+    // until the restored %fp value matches the target value in %g3.
+
+.Lloop:
+    cmp %fp, %g3            // Have we reached the target frame?
+    bl,a .Lloop             // Loop while current fp is below target.
+    restore                 // Unwind register window in delay slot.
+    be,a .Lfound            // Better have hit it exactly.
+    ld [%g1], %o0           // Delay slot: extract target SP.
+
+.Lthread:
+    {
+     * Do a "flush register windows trap".  The trap handler in the
+     * kernel writes all the register windows to their stack slots, and
+     * marks them all as invalid (needing to be sucked up from the
+     * stack when used).  This ensures that all information needed to
+     * unwind to these callers is in memory, not in the register
+     * windows.
+    }
+
+    ta      3
+    mov     %g1,%o1         // use %o1, since %g1 will be destroyed by the call below
+
+    ld      [%o1], %fp      // Set saved SP on restore below.
+    sub     %fp, 64, %sp    // Allocate a register frame.
+    st      %g3, [%fp+48]   // Set saved FP on restore below.
+
+    ld      [%o1+8], %o7    // Set return PC.
+
+    retl
+    restore %g2, 0, %o0     // Restore values from above register frame.
+
+.Lfound:
+    // We have unwound register windows so %fp matches the target.
+    mov %o0, %sp            // OK, install new SP.
+
+.Lsp_ok:
+    ld [%g1+8], %o0         // Extract target return PC.
+    jmp %o0+8               // Return there.
+    mov %g2, %o0            // Delay slot: set return value.
+  end;
+
+
+function fpc_setjmp(var S:jmp_buf):longint;assembler;nostackframe;[Public,alias:'FPC_SETJMP'];compilerproc;
+  asm
+    // We don't create a stackframe so we can save PC,SP and FP of the caller
+    st      %o7, [%o0+8]
+    st      %sp, [%o0]
+    st      %fp, [%o0+4]
+
+    ld      [%o0+8], %o7
+    mov     %g0, %o0
+  end;
+
diff --git a/rtl/sparc64/setjumph.inc b/rtl/sparc64/setjumph.inc
new file mode 100644
index 0000000000..3a17376399
--- /dev/null
+++ b/rtl/sparc64/setjumph.inc
@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 1998 the Free Pascal development team
+
+    SetJmp/Longjmp declarations
+
+    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.
+
+ **********************************************************************}
+
+Type
+  jmp_buf = record
+    sp,fp,pc : Pointer;
+  end;
+  PJmp_buf = ^jmp_buf;
+
+Function Setjmp (Var S : Jmp_buf) : longint; [external name 'FPC_SETJMP'];
+Procedure longjmp (Var S : Jmp_buf; value : longint); [external name 'FPC_LONGJMP'];
+