OSDN Git Service

Initial sparc port, thanks to Mathew Bosworth <mbosworth@metaflow.com>,
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / sparc / __longjmp.S
1 /* Copyright (C) 1991, 93, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13
14    You should have received a copy of the GNU Library General Public
15    License along with the GNU C Library; see the file COPYING.LIB.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18
19 /* Code taken from glibc/sysdeps/sparc/sparc32/  (glibc 2.2.2) */
20
21 //#include "sysdep.h"
22 #include <sysdep.h>
23
24 #define _ASM 1
25 #define _SETJMP_H
26 #include <bits/setjmp.h>
27 #define ENV(base,reg) [%base + (reg * 4)]
28 #define ST_FLUSH_WINDOWS 3
29 #define RW_FP [%fp + 0x48]
30
31 ENTRY(__longjmp)
32         /* Store our arguments in global registers so we can still
33            use them while unwinding frames and their register windows.  */
34
35         ld ENV(o0,JB_FP), %g3   /* Cache target FP in register %g3.  */
36         mov %o0, %g1            /* ENV in %g1 */
37         orcc %o1, %g0, %g2      /* VAL in %g2 */
38         be,a 0f                 /* Branch if zero; else skip delay slot.  */
39          mov 1, %g2             /* Delay slot only hit if zero: VAL = 1.  */
40 0:
41         xor %fp, %g3, %o0
42         add %fp, 512, %o1
43         andncc %o0, 4095, %o0
44         bne thread
45         //bne LOC(thread)
46          cmp %o1, %g3
47         bl thread
48         //bl LOC(thread)
49
50         /* Now we will loop, unwinding the register windows up the stack
51            until the restored %fp value matches the target value in %g3.  */
52
53 //LOC(loop):
54 loop:
55         cmp %fp, %g3            /* Have we reached the target frame? */
56         bl,a loop               /* Loop while current fp is below target.  */
57         //bl,a LOC(loop)        /* Loop while current fp is below target.  */
58          restore                /* Unwind register window in delay slot.  */
59         be,a found              /* Better have hit it exactly.  */
60         //be,a LOC(found)       /* Better have hit it exactly.  */
61          ld ENV(g1,JB_SP), %o0  /* Delay slot: extract target SP.  */
62
63 thread:
64 //LOC(thread):
65         /*
66          * Do a "flush register windows trap".  The trap handler in the
67          * kernel writes all the register windows to their stack slots, and
68          * marks them all as invalid (needing to be sucked up from the
69          * stack when used).  This ensures that all information needed to
70          * unwind to these callers is in memory, not in the register
71          * windows.
72          */
73         ta      ST_FLUSH_WINDOWS
74         ld      ENV(g1,JB_PC), %o7 /* Set return PC. */
75         ld      ENV(g1,JB_SP), %fp /* Set saved SP on restore below. */
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. */
80
81 found:
82 //LOC(found):
83         /* We have unwound register windows so %fp matches the target.  */
84         mov %o0, %sp            /* OK, install new SP.  */
85
86 //LOC(sp_ok):
87 sp_ok:
88         ld ENV(g1,JB_PC), %o0   /* Extract target return PC.  */
89         jmp %o0 + 8             /* Return there.  */
90          mov %g2, %o0           /* Delay slot: set return value.  */
91
92 END(__longjmp)