2.9
[glibc/nacl-glibc.git] / sysdeps / sparc / sparc32 / __longjmp.S
bloba5453b429419903a9b6fc4fd8fee13870550579a
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, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
20 #include <sysdep.h>
22 #include <jmpbuf-offsets.h>
23 #define ENV(base,reg) [%base + (reg * 4)]
24 #define ST_FLUSH_WINDOWS 3
25 #define RW_FP [%fp + 0x48]
27 ENTRY(__longjmp)
28         /* Store our arguments in global registers so we can still
29            use them while unwinding frames and their register windows.  */
31         ld ENV(o0,JB_FP), %g3   /* Cache target FP in register %g3.  */
32 #ifdef PTR_DEMANGLE
33         PTR_DEMANGLE (%g3, %g3, %g4)
34 #endif
35         mov %o0, %g1            /* ENV in %g1 */
36         orcc %o1, %g0, %g2      /* VAL in %g2 */
37         be,a 0f                 /* Branch if zero; else skip delay slot.  */
38          mov 1, %g2             /* Delay slot only hit if zero: VAL = 1.  */
40         xor %fp, %g3, %o0
41         add %fp, 512, %o1
42         andncc %o0, 4095, %o0
43         bne LOC(thread)
44          cmp %o1, %g3
45         bl LOC(thread)
47         /* Now we will loop, unwinding the register windows up the stack
48            until the restored %fp value matches the target value in %g3.  */
50 LOC(loop):
51         cmp %fp, %g3            /* Have we reached the target frame? */
52         bl,a LOC(loop)          /* Loop while current fp is below target.  */
53          restore                /* Unwind register window in delay slot.  */
54         be,a LOC(found)         /* Better have hit it exactly.  */
55          ld ENV(g1,JB_SP), %o0  /* Delay slot: extract target SP.  */
57 LOC(thread):
58         /*
59          * Do a "flush register windows trap".  The trap handler in the
60          * kernel writes all the register windows to their stack slots, and
61          * marks them all as invalid (needing to be sucked up from the
62          * stack when used).  This ensures that all information needed to
63          * unwind to these callers is in memory, not in the register
64          * windows.
65          */
66         ta      ST_FLUSH_WINDOWS
67 #ifdef PTR_DEMANGLE
68         ld      ENV(g1,JB_PC), %g5 /* Set return PC. */
69         ld      ENV(g1,JB_SP), %g1 /* Set saved SP on restore below. */
70         PTR_DEMANGLE2 (%o7, %g5, %g4)
71         PTR_DEMANGLE2 (%fp, %g1, %g4)
72 #else
73         ld      ENV(g1,JB_PC), %o7 /* Set return PC. */
74         ld      ENV(g1,JB_SP), %fp /* Set saved SP on restore below. */
75 #endif
76         sub     %fp, 64, %sp    /* Allocate a register frame. */
77         st      %g3, RW_FP      /* Set saved FP on restore below. */
78         retl
79          restore %g2, 0, %o0    /* Restore values from above register frame. */
81 LOC(found):
82         /* We have unwound register windows so %fp matches the target.  */
83 #ifdef PTR_DEMANGLE
84         PTR_DEMANGLE2 (%sp, %o0, %g4)
85 #else
86         mov %o0, %sp            /* OK, install new SP.  */
87 #endif
89 LOC(sp_ok):
90         ld ENV(g1,JB_PC), %o0   /* Extract target return PC.  */
91 #ifdef PTR_DEMANGLE
92         PTR_DEMANGLE2 (%o0, %o0, %g4)
93 #endif
94         jmp %o0 + 8             /* Return there.  */
95          mov %g2, %o0           /* Delay slot: set return value.  */
97 END(__longjmp)