Replace FSF snail mail address with URLs.
[glibc.git] / sysdeps / sparc / sparc32 / __longjmp.S
blob7e05c9524b342d93ad3144c2bc8121aed5796594
1 /* Copyright (C) 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2006
2    Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
21 #include <jmpbuf-offsets.h>
22 #define ENV(base,reg) [%base + (reg * 4)]
23 #define ST_FLUSH_WINDOWS 3
24 #define RW_FP [%fp + 0x48]
26 ENTRY(__longjmp)
27         /* Store our arguments in global registers so we can still
28            use them while unwinding frames and their register windows.  */
30         ld ENV(o0,JB_FP), %g3   /* Cache target FP in register %g3.  */
31 #ifdef PTR_DEMANGLE
32         PTR_DEMANGLE (%g3, %g3, %g4)
33 #endif
34         mov %o0, %g1            /* ENV in %g1 */
35         orcc %o1, %g0, %g2      /* VAL in %g2 */
36         be,a 0f                 /* Branch if zero; else skip delay slot.  */
37          mov 1, %g2             /* Delay slot only hit if zero: VAL = 1.  */
39         xor %fp, %g3, %o0
40         add %fp, 512, %o1
41         andncc %o0, 4095, %o0
42         bne LOC(thread)
43          cmp %o1, %g3
44         bl LOC(thread)
46         /* Now we will loop, unwinding the register windows up the stack
47            until the restored %fp value matches the target value in %g3.  */
49 LOC(loop):
50         cmp %fp, %g3            /* Have we reached the target frame? */
51         bl,a LOC(loop)          /* Loop while current fp is below target.  */
52          restore                /* Unwind register window in delay slot.  */
53         be,a LOC(found)         /* Better have hit it exactly.  */
54          ld ENV(g1,JB_SP), %o0  /* Delay slot: extract target SP.  */
56 LOC(thread):
57         /*
58          * Do a "flush register windows trap".  The trap handler in the
59          * kernel writes all the register windows to their stack slots, and
60          * marks them all as invalid (needing to be sucked up from the
61          * stack when used).  This ensures that all information needed to
62          * unwind to these callers is in memory, not in the register
63          * windows.
64          */
65         ta      ST_FLUSH_WINDOWS
66 #ifdef PTR_DEMANGLE
67         ld      ENV(g1,JB_PC), %g5 /* Set return PC. */
68         ld      ENV(g1,JB_SP), %g1 /* Set saved SP on restore below. */
69         PTR_DEMANGLE2 (%o7, %g5, %g4)
70         PTR_DEMANGLE2 (%fp, %g1, %g4)
71 #else
72         ld      ENV(g1,JB_PC), %o7 /* Set return PC. */
73         ld      ENV(g1,JB_SP), %fp /* Set saved SP on restore below. */
74 #endif
75         sub     %fp, 64, %sp    /* Allocate a register frame. */
76         st      %g3, RW_FP      /* Set saved FP on restore below. */
77         retl
78          restore %g2, 0, %o0    /* Restore values from above register frame. */
80 LOC(found):
81         /* We have unwound register windows so %fp matches the target.  */
82 #ifdef PTR_DEMANGLE
83         PTR_DEMANGLE2 (%sp, %o0, %g4)
84 #else
85         mov %o0, %sp            /* OK, install new SP.  */
86 #endif
88 LOC(sp_ok):
89         ld ENV(g1,JB_PC), %o0   /* Extract target return PC.  */
90 #ifdef PTR_DEMANGLE
91         PTR_DEMANGLE2 (%o0, %o0, %g4)
92 #endif
93         jmp %o0 + 8             /* Return there.  */
94          mov %g2, %o0           /* Delay slot: set return value.  */
96 END(__longjmp)