/*
 * |-----------------------------------------------------------|
 * | Copyright (c) 1991, 1990 MIPS Computer Systems, Inc.      |
 * | All Rights Reserved                                       |
 * |-----------------------------------------------------------|
 * |          Restricted Rights Legend                         |
 * | Use, duplication, or disclosure by the Government is      |
 * | subject to restrictions as set forth in                   |
 * | subparagraph (c)(1)(ii) of the Rights in Technical        |
 * | Data and Computer Software Clause of DFARS 252.227-7013.  |
 * |         MIPS Computer Systems, Inc.                       |
 * |         950 DeGuigne Avenue                               |
 * |         Sunnyvale, California 94088-3650, USA             |
 * |-----------------------------------------------------------|
 */
/* $Header: setjmp.s,v 1.16.2.1 92/06/24 13:59:33 marker Exp $ */

/*
 * C library -- setjmp, longjmp
 *
 *	longjmp(a,v)
 * will generate a "return(v)" from
 * the last call to
 *	setjmp(a)
 * by restoring registers from the stack,
 * The previous signal state is NOT restored.
 */

#include <sys/regdef.h>
#include <sys/asm.h>
#include <setjmp.h>
#include <sys/fpu.h>

#if (defined(__STDC__) || defined(__SVR4__STDC))
#ifdef MIPSEB
#   define LDFP(reg,reg2)       lwc1 $f ## reg2,+JB_F20*4+(reg-20)*4+0(a0);  \
                                lwc1 $f ## reg, +JB_F20*4+(reg-20)*4+4(a0)
#   define SDFP(reg,reg2)       swc1 $f ## reg2,+JB_F20*4+(reg-20)*4+0(a0);  \
                                swc1 $f ## reg, +JB_F20*4+(reg-20)*4+4(a0)
#else /* !MIPSEB */
#   define LDFP(reg,reg2)       lwc1 $f ## reg, +JB_F20*4+(reg-20)*4+0(a0);  \
                                lwc1 $f ## reg2,+JB_F20*4+(reg-20)*4+4(a0)
#   define SDFP(reg,reg2)       swc1 $f ## reg, +JB_F20*4+(reg-20)*4+0(a0);  \
                                swc1 $f ## reg2,+JB_F20*4+(reg-20)*4+4(a0)
#endif /* MIPSEB */
#else /* __STDC__ || __SVR4__STDC */
#ifdef MIPSEB
#   define LDFP(reg,reg2)       lwc1 $f/**/reg2,+JB_F20*4+(reg-20)*4+0(a0);  \
                                lwc1 $f/**/reg, +JB_F20*4+(reg-20)*4+4(a0)
#   define SDFP(reg,reg2)       swc1 $f/**/reg2,+JB_F20*4+(reg-20)*4+0(a0);  \
                                swc1 $f/**/reg, +JB_F20*4+(reg-20)*4+4(a0)
#else /* !MIPSEB */
#   define LDFP(reg,reg2)       lwc1 $f/**/reg, +JB_F20*4+(reg-20)*4+0(a0);  \
                                lwc1 $f/**/reg2,+JB_F20*4+(reg-20)*4+4(a0)
#   define SDFP(reg,reg2)       swc1 $f/**/reg, +JB_F20*4+(reg-20)*4+0(a0);  \
                                swc1 $f/**/reg2,+JB_F20*4+(reg-20)*4+4(a0)
#endif /* MIPSEB */
#endif /* __STDC__ || __SVR4__STDC */

LEAF(setjmp)
	sw	ra,JB_PC*4(a0)
	sw	sp,JB_SP*4(a0)
	sw	fp,JB_FP*4(a0)
	sw	s0,JB_S0*4(a0)
	sw	s1,JB_S1*4(a0)
	sw	s2,JB_S2*4(a0)
	sw	s3,JB_S3*4(a0)
	sw	s4,JB_S4*4(a0)
	sw	s5,JB_S5*4(a0)
	sw	s6,JB_S6*4(a0)
	sw	s7,JB_S7*4(a0)
	cfc1	v0,fpc_csr
	sw	v0,+JB_FPC_CSR*4(a0)
	SDFP(20,21)
	SDFP(22,23)
	SDFP(24,25)
	SDFP(26,27)
	SDFP(28,29)
	SDFP(30,31)
	move	v0,zero
	j	ra
END(setjmp)

/*
 * longjmp(jmp_buf, retval)
 */
LEAF(longjmp)
	lw	ra,JB_PC*4(a0)
	lw	sp,JB_SP*4(a0)
	lw	fp,JB_FP*4(a0)
	lw	s0,JB_S0*4(a0)
	lw	s1,JB_S1*4(a0)
	lw	s2,JB_S2*4(a0)
	lw	s3,JB_S3*4(a0)
	lw	s4,JB_S4*4(a0)
	lw	s5,JB_S5*4(a0)
	lw	s6,JB_S6*4(a0)
	lw	s7,JB_S7*4(a0)
	lw	v0,+JB_FPC_CSR*4(a0)
	LDFP(20,21)
	LDFP(22,23)
	LDFP(24,25)
	LDFP(26,27)
	LDFP(28,29)
	LDFP(30,31)
	ctc1	v0,fpc_csr
	move	v0,a1			/* return retval */
	bnez	v0,1f			/* unless retval==0 */
	li	v0,1			/* in which case return 1 */
1:	j	ra
END(longjmp)
