/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/*
 * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved
 *
 * HISTORY
 *  20-Apr-92    Bruce Martin (bmartin@next.com)
 *      Created from M68K sources.
 */

/*
 * 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 <architecture/i386/asm_help.h>

#define JB_RBX			0
#define JB_RBP			8
#define JB_RSP			16
#define JB_R12			24
#define JB_R13			32
#define JB_R14			40
#define JB_R15			48
#define JB_RIP			56
#define JB_RFLAGS		64
#define JB_MXCSR		72
#define JB_FPCONTROL	76
#define JB_MASK			80

LEAF(__setjmp, 0)
	// %rdi is a jmp_buf (struct sigcontext *)

	// now build sigcontext
	movq	%rbx, JB_RBX(%rdi)
	movq	%rbp, JB_RBP(%rdi)
	movq	%r12, JB_R12(%rdi)
	movq	%r13, JB_R13(%rdi)
	movq	%r14, JB_R14(%rdi)
	movq	%r15, JB_R15(%rdi)

	// RIP is set to the frame return address value
	movq	(%rsp), %rax
	movq	%rax, JB_RIP(%rdi)
	// RSP is set to the frame return address plus 8
	movq	%rsp, %rax
	addq	$8, %rax
	movq	%rax, JB_RSP(%rdi)

	// save rflags - you can't use movq
	pushfq
	popq	%rax
	movq	%rax, JB_RFLAGS(%rdi)

	// save fp control word
	fnstcw	JB_FPCONTROL(%rdi)

	// save MXCSR
	stmxcsr	JB_MXCSR(%rdi)

	// return 0
	xorq	%rax, %rax
	ret


LEAF(__longjmp, 0)
	fninit			// reset FP coprocessor

	// %rdi is a jmp_buf (struct sigcontext *)
	// %rsi is the return value
	movq	%rsi, %rax
	testq	%rax, %rax
	jnz	1f
	addq	$1, %rax

	// general registers
1:
	movq	JB_RBX(%rdi), %rbx
	movq	JB_RBP(%rdi), %rbp
	movq	JB_RSP(%rdi), %rsp
	movq	JB_R12(%rdi), %r12
	movq	JB_R13(%rdi), %r13
	movq	JB_R14(%rdi), %r14
	movq	JB_R15(%rdi), %r15

	// restore FP control word
	fldcw	JB_FPCONTROL(%rdi)

	// restore MXCSR
	ldmxcsr	JB_MXCSR(%rdi)

	// rflags
	pushq	JB_RFLAGS(%rdi)
	popfq

	jmp		*JB_RIP(%rdi)
