/*
 * alpha/entry.S
 *
 * kernel entry-points
 */

#include <linux/config.h>
#include <asm/system.h>

#define halt	.long PAL_halt
#define rti	.long PAL_rti
#define SIGCHLD	20

#define NR_SYSCALLS 350
#define osf_vfork sys_fork

/*
 * These offsets must match with "struct hae" in io.h:	
 */
#define HAE_CACHE	0
#define HAE_REG		8

/*
 * stack offsets
 */
#define SP_OFF		184

#define SWITCH_STACK_SIZE 320

/*
 * task structure offsets
 */
#define TASK_STATE	0
#define TASK_COUNTER	8
#define TASK_PRIORITY	16
#define TASK_SIGNAL	24
#define TASK_BLOCKED	32
#define TASK_FLAGS	40

/*
 * task flags (must match include/linux/sched.h):
 */
#define	PF_PTRACED	0x00000010

/*
 * This defines the normal kernel pt-regs layout.
 *
 * regs 9-15 preserved by C code
 * regs 16-18 saved by PAL-code
 * regs 29-30 saved and set up by PAL-code
 * JRP - Save regs 16-18 in a special area of the stack, so that
 * the palcode-provided values are available to the signal handler.
 */
#define SAVE_ALL			\
	subq	$30,184,$30;		\
	stq	$0,0($30);		\
	stq	$1,8($30);		\
	stq	$2,16($30);		\
	stq	$3,24($30);		\
	stq	$4,32($30);		\
	stq	$5,40($30);		\
	stq	$6,48($30);		\
	stq	$7,56($30);		\
	stq	$8,64($30);		\
	stq	$19,72($30);		\
	stq	$20,80($30);		\
	stq	$21,88($30);		\
	stq	$22,96($30);		\
	stq	$23,104($30);		\
	stq	$24,112($30);		\
	stq	$25,120($30);		\
	stq	$26,128($30);		\
	stq	$27,136($30);		\
	stq	$28,144($30);		\
	lda	$2,hae;			\
	ldq	$2,HAE_CACHE($2);	\
	stq	$2,152($30);		\
	stq	$16,160($30);		\
	stq	$17,168($30);		\
	stq	$18,176($30)

#define RESTORE_ALL			\
	lda	$8,hae;			\
	ldq	$7,HAE_CACHE($8);	\
	ldq	$6,152($30);		\
	subq	$7,$6,$5;		\
	beq	$5,99f;			\
	ldq	$7,HAE_REG($8);		\
	addq	$31,7,$16;		\
	call_pal PAL_swpipl;		\
	stq	$6,HAE_CACHE($8);	\
	stq	$6,0($7);		\
	mb;				\
	bis	$0,$0,$16;		\
	call_pal PAL_swpipl;		\
99:;					\
	ldq	$0,0($30);		\
	ldq	$1,8($30);		\
	ldq	$2,16($30);		\
	ldq	$3,24($30);		\
	ldq	$4,32($30);		\
	ldq	$5,40($30);		\
	ldq	$6,48($30);		\
	ldq	$7,56($30);		\
	ldq	$8,64($30);		\
	ldq	$19,72($30);		\
	ldq	$20,80($30);		\
	ldq	$21,88($30);		\
	ldq	$22,96($30);		\
	ldq	$23,104($30);		\
	ldq	$24,112($30);		\
	ldq	$25,120($30);		\
	ldq	$26,128($30);		\
	ldq	$27,136($30);		\
	ldq	$28,144($30);		\
	addq	$30,184,$30

.text
.set noat
#if defined(__linux__) && !defined(__ELF__)
  .set singlegp
#endif

.align 3
.globl	entInt
.ent	entInt
entInt:
	SAVE_ALL
/* start atomic operation with respect to software interrupts */
	lda	$0,intr_count
	ldq	$1,0($0)
	addq	$1,1,$1
	stq	$1,0($0)
/* set up the arguments to the C interrupt handler */
	lda	$27,do_entInt
	jsr	$26,($27),do_entInt
/* ok, return */
	lda	$0,intr_count
	ldq	$1,0($0)
	subq	$1,1,$1
	stq	$1,0($0)
	br	$31,ret_from_sys_call
.end entInt

.align 3
.globl	entMM
.ent	entMM
entMM:
	SAVE_ALL
	lda	$27,do_page_fault
	lda	$26,ret_from_sys_call
	jsr	$31,($27),do_page_fault
.end entMM

.align 3
.globl	entArith
.ent	entArith
entArith:
	SAVE_ALL
	lda	$27,do_entArith
	lda	$26,ret_from_sys_call
	jsr	$31,($27),do_entArith
.end entArith

.align 3
.globl	entIF
.ent	entIF
entIF:
#ifdef CONFIG_KGDB
	bne	$16,1f		/* not a bpt trap -> */
	/*
	 * Call kgdb if it's enabled and if "current" is not being
	 * traced or if we get a bpt in kernel mode (the architecture
	 * manual defines the values of $17 and $18 as "unpredictable",
	 * so they are fair game).
	 */
	lda	$17,kgdb_enabled
	ldl	$17,0($17)
	beq	$17,1f		/* kgdb not enabled -> */

#ifndef CONFIG_ALPHA_CABRIOLET
	/*
	 * MILO on Cabriolet doesn't seem to setup the PS in the
	 * PALframe correctly. (davidm@azstarnet.com)
	 */
	ldq	$18,0($30)	/* get ps */
	and	$18,8,$18
	beq	$18,entKGDB
#endif

	lda	$17,current_set
	ldq	$17,0($17)
	bis	$31,PF_PTRACED,$18
	ldq	$17,TASK_FLAGS($17)
	and	$17,$18,$17
	beq	$17,entKGDB
1:
#endif
	SAVE_ALL
	lda	$27,do_entIF
	lda	$26,ret_from_sys_call
	jsr	$31,($27),do_entIF
.end entIF

/*
 * Fork() is one of the special system calls: it needs to
 * save the callee-saved regs so that the regs can be found
 * for the new process.. We save them in the "context switch"
 * stack format (see arch/alpha/kernel/process.c).
 *
 * Also, for the kernel fork, we need to fake the system call
 * stack buildup, as we can't do system calls from kernel space.
 */
.align 3
.ent	kernel_clone
kernel_clone:
	subq $30,6*8,$30
	stq $31,0($30)
	stq $26,8($30)
	stq $29,16($30)
	stq $16,24($30)
	stq $17,32($30)
	stq $18,40($30)
	bis $31,2,$0	/* Register v0: syscall nr for fork() */
	SAVE_ALL
	lda $27,sys_clone
	jsr $26,($27),sys_clone
	stq $0,0($30)	
	br $31,ret_from_sys_call
.end	kernel_clone

/*
 * __kernel_thread(clone_flags, fn, arg)
 */
.align 3
.globl	__kernel_thread
.ent	__kernel_thread
__kernel_thread:
	subq $30,4*8,$30
	stq $9,0($30)
	stq $10,8($30)
	stq $26,16($30)
	bis $17,$17,$9		/* save fn */
	bis $18,$18,$10		/* save arg */
	bsr $26,kernel_clone
	bne $20,1f		/* $20 is non-zero in child */
	ldq $9,0($30)
	ldq $10,8($30)
	ldq $26,16($30)
	addq $30,4*8,$30
	ret $31,($26),1
/* this is in child: look out as we don't have any stack here.. */
1:	bis $9,$9,$27		/* get fn */
	bis $10,$10,$16		/* get arg */
	jsr $26,($27)
	bis $0,$0,$16
	lda $27,sys_exit
	jsr $26,($27),sys_exit
	call_pal PAL_halt
.end	__kernel_thread

.align 3
.ent	do_switch_stack
do_switch_stack:
	lda $30,-SWITCH_STACK_SIZE($30)
	stq  $9,0($30)
	stq $10,8($30)
	stq $11,16($30)
	stq $12,24($30)
	stq $13,32($30)
	stq $14,40($30)
	stq $15,48($30)
	stq $26,56($30)
	stt $f0,64($30)
	stt $f1,72($30)
	stt $f2,80($30)
	stt $f3,88($30)
	stt $f4,96($30)
	stt $f5,104($30)
	stt $f6,112($30)
	stt $f7,120($30)
	stt $f8,128($30)
	stt $f9,136($30)
	stt $f10,144($30)
	stt $f11,152($30)
	stt $f12,160($30)
	stt $f13,168($30)
	stt $f14,176($30)
	stt $f15,184($30)
	stt $f16,192($30)
	stt $f17,200($30)
	stt $f18,208($30)
	stt $f19,216($30)
	stt $f20,224($30)
	stt $f21,232($30)
	stt $f22,240($30)
	stt $f23,248($30)
	stt $f24,256($30)
	stt $f25,264($30)
	stt $f26,272($30)
	stt $f27,280($30)
	mf_fpcr $f0		# get fpcr
	stt $f28,288($30)
	stt $f29,296($30)
	stt $f30,304($30)
	stt $f0,312($30)	# save fpcr in slot of $f31
	ret $31,($1),1
.end do_switch_stack

.align 3
.ent	undo_switch_stack
undo_switch_stack:
	ldq  $9,0($30)
	ldq $10,8($30)
	ldq $11,16($30)
	ldq $12,24($30)
	ldq $13,32($30)
	ldq $14,40($30)
	ldq $15,48($30)
	ldq $26,56($30)
	ldt $f30,312($30)	# get saved fpcr
	ldt $f0,64($30)
	ldt $f1,72($30)
	ldt $f2,80($30)
	ldt $f3,88($30)
	mt_fpcr $f30		# install saved fpcr
	ldt $f4,96($30)
	ldt $f5,104($30)
	ldt $f6,112($30)
	ldt $f7,120($30)
	ldt $f8,128($30)
	ldt $f9,136($30)
	ldt $f10,144($30)
	ldt $f11,152($30)
	ldt $f12,160($30)
	ldt $f13,168($30)
	ldt $f14,176($30)
	ldt $f15,184($30)
	ldt $f16,192($30)
	ldt $f17,200($30)
	ldt $f18,208($30)
	ldt $f19,216($30)
	ldt $f20,224($30)
	ldt $f21,232($30)
	ldt $f22,240($30)
	ldt $f23,248($30)
	ldt $f24,256($30)
	ldt $f25,264($30)
	ldt $f26,272($30)
	ldt $f27,280($30)
	ldt $f28,288($30)
	ldt $f29,296($30)
	ldt $f30,304($30)
	lda $30,SWITCH_STACK_SIZE($30)
	ret $31,($1),1
.end undo_switch_stack

.align 3
.globl	entUna
.ent	entUna
entUna:
	lda $30,-256($30)
	stq $0,0($30)
	ldq $0,256($30)		/* get PS */
	stq $1,8($30)
	stq $2,16($30)
	stq $3,24($30)
	and $0,8,$0		/* user mode? */
	stq $4,32($30)
	bne $0,entUnaUser	/* yup -> do user-level unaligned fault */
	stq $5,40($30)
	stq $6,48($30)
	stq $7,56($30)
	stq $8,64($30)
	stq $9,72($30)
	stq $10,80($30)
	stq $11,88($30)
	stq $12,96($30)
	stq $13,104($30)
	stq $14,112($30)
	stq $15,120($30)
	/* 16-18 PAL-saved */
	stq $19,152($30)
	stq $20,160($30)
	stq $21,168($30)
	stq $22,176($30)
	stq $23,184($30)
	stq $24,192($30)
	stq $25,200($30)
	stq $26,208($30)
	stq $27,216($30)
	stq $28,224($30)
	stq $29,232($30)
	stq $30,240($30)
	stq $31,248($30)
	lda $27,do_entUna
	jsr $26,($27),do_entUna
	ldq $0,0($30)
	ldq $1,8($30)
	ldq $2,16($30)
	ldq $3,24($30)
	ldq $4,32($30)
	ldq $5,40($30)
	ldq $6,48($30)
	ldq $7,56($30)
	ldq $8,64($30)
	ldq $9,72($30)
	ldq $10,80($30)
	ldq $11,88($30)
	ldq $12,96($30)
	ldq $13,104($30)
	ldq $14,112($30)
	ldq $15,120($30)
	/* 16-18 PAL-saved */
	ldq $19,152($30)
	ldq $20,160($30)
	ldq $21,168($30)
	ldq $22,176($30)
	ldq $23,184($30)
	ldq $24,192($30)
	ldq $25,200($30)
	ldq $26,208($30)
	ldq $27,216($30)
	ldq $28,224($30)
	ldq $29,232($30)
	ldq $30,240($30)
	lda $30,256($30)
	rti
.end entUna

.align 3
.ent	entUnaUser
entUnaUser:
	ldq $0,0($30)			/* restore original $0 */
	lda $30,256($30)		/* pop entUna's stack frame */
	SAVE_ALL			/* setup normal kernel stack */
	lda $30,-56($30)
	stq $9,0($30)
	stq $10,8($30)
	stq $11,16($30)
	stq $12,24($30)
	stq $13,32($30)
	stq $14,40($30)
	stq $15,48($30)
	lda $27,do_entUnaUser
	bis $31,$30,$19
	jsr $26,($27),do_entUnaUser
	ldq $9,0($30)
	ldq $10,8($30)
	ldq $11,16($30)
	ldq $12,24($30)
	ldq $13,32($30)
	ldq $14,40($30)
	ldq $15,48($30)
	lda $30,56($30)
	br $31,ret_from_sys_call

.end	entUnaUser

/*
 * A fork is the same as clone(SIGCHLD, 0);
*/
.align 3
.globl	sys_fork
.ent	sys_fork
sys_fork:
	bsr $1,do_switch_stack
	bis $31,SIGCHLD,$16
	bis $31,$31,$17
	bis $30,$30,$18
	lda $27,alpha_clone
	jsr $26,($27),alpha_clone
	bsr $1,undo_switch_stack
	ret $31,($26),1
.end	sys_fork

.align 3
.globl	sys_clone
.ent	sys_clone
sys_clone:
	bsr $1,do_switch_stack
	/* arg1 and arg2 come from the user */
	bis $30,$30,$18
	lda $27,alpha_clone
	jsr $26,($27),alpha_clone
	bsr $1,undo_switch_stack
	ret $31,($26),1
.end	sys_clone

.align 3
.globl  alpha_switch_to
.ent    alpha_switch_to
alpha_switch_to:
	bsr $1,do_switch_stack
	call_pal PAL_swpctx
	bsr $1,undo_switch_stack
	ret $31,($26),1
.end alpha_switch_to

/*
 * Oh, well.. Disassembling OSF/1 binaries to find out how the
 * system calls work isn't much fun.
 *
 * entSys is special in that the PAL-code doesn't save a0-a2, so
 * we start off by doing that by hand.
 */
.align 3
.globl	entSys
.globl	ret_from_sys_call
.ent	entSys
entSys:
	stq	$16,24($30)
	stq	$17,32($30)
	stq	$18,40($30)
	SAVE_ALL
	/* FIXME: optimize */
	lda	$1,current_set
	ldq	$2,0($1)
	ldq	$3,TASK_FLAGS($2)
	and     $3,PF_PTRACED,$3
	bne     $3,strace
	/* end of strace */	
	lda	$1,NR_SYSCALLS($31)
	lda	$2,sys_call_table
	lda	$27,do_entSys
	cmpult	$0,$1,$1
	s8addq	$0,$2,$2
	beq	$1,1f
	ldq	$27,0($2)
1:	jsr	$26,($27),do_entSys
	blt	$0,syscall_error	/* the call failed */
	stq	$0,0($30)
	stq	$31,72($30)		/* a3=0 => no error */

.align 3
ret_from_sys_call:
	cmovne	$26,0,$19		/* $19 = 0 => non-restartable */
	/* check bottom half interrupts */
	lda	$0,intr_count
	ldq	$1,0($0)
	bne	$1,ret_from_handle_bh
	lda	$2,bh_active
	ldq	$3,0($2)
	lda	$2,bh_mask
	ldq	$4,0($2)
	addq	$1,1,$1
	and	$3,$4,$2
	bne	$2,handle_bottom_half	
ret_from_handle_bh:
	ldq	$0,SP_OFF($30)
	and	$0,8,$0
	beq	$0,restore_all
ret_from_reschedule:
	lda	$0,need_resched
	lda	$1,current_set
	ldl	$2,0($0)
	lda	$4,init_task
	ldq	$3,0($1)
	bne	$2,reschedule
	subq	$4,$3,$4
	beq	$4,restore_all
	ldq	$4,TASK_SIGNAL($3)
	ldq	$16,TASK_BLOCKED($3)
	bic	$4,$16,$4
	bne	$4,signal_return
restore_all:
	RESTORE_ALL
	rti
	
	
/* PTRACE syscall handler */	
.align 3
strace:
	/* set up signal stack, call syscall_trace */
	bsr	$1,do_switch_stack
	lda     $27,syscall_trace
	jsr     $26,($27),syscall_trace
	bsr	$1,undo_switch_stack

	/* get the system call number and the arguments back.. */
	ldq     $0,0($30)
	ldq     $16,SP_OFF+24($30)
	ldq     $17,SP_OFF+32($30)
	ldq     $18,SP_OFF+40($30)
	ldq     $19,72($30)
	ldq     $20,80($30)
	ldq     $21,88($30)

	/* get the system call pointer.. */
	lda	$1,NR_SYSCALLS($31)
	lda	$2,sys_call_table
	lda	$27,do_entSys
	cmpult	$0,$1,$1
	s8addq	$0,$2,$2
	beq	$1,1f
	ldq	$27,0($2)
1:	jsr	$26,($27),do_entSys

	/* check return.. */
	blt	$0,strace_error	/* the call failed */
	stq	$31,72($30)		/* a3=0 => no error */
strace_success:
	stq	$0,0($30)		/* save return value */

	bsr	$1,do_switch_stack
	lda     $27,syscall_trace
	jsr     $26,($27),syscall_trace
	bsr	$1,undo_switch_stack
	br	$31,ret_from_sys_call

	.align  3
strace_error:
	ldq	$19,0($30)	/* old syscall nr (zero if success) */
	beq	$19,strace_success
	ldq	$20,72($30)	/* .. and this a3 */

	subq	$31,$0,$0	/* with error in v0 */
	addq	$31,1,$1	/* set a3 for errno return */
	stq	$0,0($30)
	stq	$1,72($30)	/* a3 for return */

	bsr	$1,do_switch_stack
	bis	$19,$19,$9	/* save old syscall number */
	bis	$20,$20,$10	/* save old a3 */
	lda     $27,syscall_trace
	jsr     $26,($27),syscall_trace
	bis	$9,$9,$19
	bis	$10,$10,$20	
	bsr	$1,undo_switch_stack

	bis	$31,$31,$26	/* tell "ret_from_sys_call" that we can restart */
	br	$31,ret_from_sys_call

	.align 3
handle_bottom_half:
	/*
	 * We're called with $0 containing the address of
	 * 'intr_count' and $1 containing 'intr_count+1'
	 */
	stq	$1,0($0)	/* intr_count = 1 */
	subq	$30,16,$30
	stq	$19,0($30)	/* save syscall nr */
	stq	$20,8($30)	/* and error indication (a3) */
	lda	$27,do_bottom_half
	jsr	$26,($27),do_bottom_half
	lda	$0,intr_count
	ldq	$19,0($30)
	ldq	$20,8($30)
	addq	$30,16,$30
	stq	$31,0($0)	/* intr_count = 0 */
	br	$31,ret_from_handle_bh

	.align 3
syscall_error:
	/*
	 * Some system calls (e.g., ptrace) can return arbitrary
	 * values which might normally be mistaken as error numbers.
	 * Those functions must zero $0 (v0) directly in the stack
	 * frame to indicate that a negative return value wasn't an
	 * error number..
	 */
	ldq	$19,0($30)	/* old syscall nr (zero if success) */
	beq	$19,ret_success

	ldq	$20,72($30)	/* .. and this a3 */
	subq	$31,$0,$0	/* with error in v0 */
	addq	$31,1,$1	/* set a3 for errno return */
	bis	$31,$31,$26	/* tell "ret_from_sys_call" that we can restart */
	stq	$1,72($30)	/* a3 for return */
ret_success:
	stq	$0,0($30)
	br	$31,ret_from_sys_call

.align 3
signal_return:
	bis	$30,$30,$17
	br	$1,do_switch_stack
	bis	$30,$30,$18
	lda	$27,do_signal
	jsr	$26,($27),do_signal
	lda	$30,SWITCH_STACK_SIZE($30)
	br	$31,restore_all
.end entSys

.align 3
.ent reschedule
reschedule:
	subq	$30,16,$30
	stq	$19,0($30)	/* save syscall nr */
	stq	$20,8($30)	/* and error indication (a3) */
	lda	$27,schedule
	jsr	$26,($27),schedule
	ldq	$19,0($30)
	ldq	$20,8($30)
	addq	$30,16,$30
	br	$31,ret_from_reschedule
.end reschedule

.align 3
.ent sys_sigreturn
sys_sigreturn:
	bis	$30,$30,$17
	lda	$30,-SWITCH_STACK_SIZE($30)
	bis	$30,$30,$18
	lda	$27,do_sigreturn
	jsr	$26,($27),do_sigreturn
	br	$1,undo_switch_stack
	br	$31,ret_from_sys_call
.end sys_sigreturn

.align 3
.ent sys_sigsuspend
sys_sigsuspend:
	bis	$30,$30,$17
	br	$1,do_switch_stack
	bis	$30,$30,$18
	lda	$27,do_sigsuspend
	jsr	$26,($27),do_sigsuspend
	lda	$30,SWITCH_STACK_SIZE($30)
	br	$31,ret_from_sys_call
.end sys_sigsuspend

	.align 3
	.globl sys_call_table
sys_call_table:
/*0*/	.quad do_entSys, sys_exit, sys_fork, sys_read, sys_write
	.quad do_entSys, sys_close, sys_wait4, do_entSys, sys_link
	.quad sys_unlink, do_entSys, sys_chdir, sys_fchdir, sys_mknod
	.quad sys_chmod, sys_chown, sys_brk, do_entSys, sys_lseek
	.quad sys_getxpid, osf_mount, osf_umount, sys_setuid, sys_getxuid
	.quad do_entSys, sys_ptrace, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, sys_access, do_entSys
	.quad do_entSys, sys_sync, sys_kill, do_entSys, sys_setpgid
	.quad do_entSys, sys_dup, sys_pipe, do_entSys, do_entSys
	.quad sys_open, do_entSys, sys_getxgid, osf_sigprocmask, do_entSys
/*50*/	.quad do_entSys, sys_acct, sys_sigpending, do_entSys, sys_ioctl
	.quad do_entSys, do_entSys, sys_symlink, sys_readlink, sys_execve
	.quad sys_umask, sys_chroot, do_entSys, sys_getpgrp, sys_getpagesize
	.quad do_entSys, osf_vfork, sys_newstat, sys_newlstat, do_entSys
	.quad do_entSys, osf_mmap, do_entSys, sys_munmap, sys_mprotect
	.quad sys_madvise, sys_vhangup, do_entSys, do_entSys, sys_getgroups
	/* map BSD's setpgrp to sys_setpgid for binary compatibility: */
	.quad sys_setgroups, do_entSys, sys_setpgid, sys_setitimer, do_entSys
	.quad do_entSys, sys_getitimer, sys_gethostname, sys_sethostname, sys_getdtablesize
	.quad sys_dup2, sys_newfstat, sys_fcntl, sys_select, do_entSys
	.quad sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept
/*100*/	.quad osf_getpriority, sys_send, sys_recv, sys_sigreturn, sys_bind
	.quad sys_setsockopt, sys_listen, do_entSys, do_entSys, do_entSys
	.quad do_entSys, sys_sigsuspend, do_entSys, sys_recvmsg, sys_sendmsg
	.quad do_entSys, sys_gettimeofday, sys_getrusage, sys_getsockopt, do_entSys
	.quad sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
	.quad sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate
	.quad sys_ftruncate, sys_flock, sys_setgid, sys_sendto, sys_shutdown
	.quad sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, do_entSys
	.quad do_entSys, sys_getpeername, do_entSys, do_entSys, sys_getrlimit
	.quad sys_setrlimit, do_entSys, sys_setsid, sys_quotactl, do_entSys
/*150*/	.quad sys_getsockname, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, sys_sigaction, do_entSys, do_entSys, osf_getdirentries
	.quad osf_statfs, osf_fstatfs, do_entSys, do_entSys, do_entSys
	.quad osf_getdomainname, sys_setdomainname, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, osf_swapon
/*200*/	.quad sys_msgctl, sys_msgget, sys_msgrcv, sys_msgsnd, sys_semctl
	.quad sys_semget, sys_semop, osf_utsname, do_entSys, osf_shmat
	.quad sys_shmctl, sys_shmdt, sys_shmget, do_entSys, do_entSys
	.quad do_entSys, do_entSys, sys_msync, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, sys_getpgid, sys_getsid
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, osf_proplist_syscall
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
/*250*/	.quad do_entSys, osf_usleep_thread, do_entSys, do_entSys, sys_sysfs
	.quad do_entSys, osf_getsysinfo, osf_setsysinfo, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
/* linux-specific system calls start at 300 */
/*300*/	.quad sys_bdflush, sys_sethae, sys_mount, sys_adjtimex, sys_swapoff
	.quad sys_getdents, alpha_create_module, sys_init_module, sys_delete_module, sys_get_kernel_syms
	.quad sys_syslog, sys_reboot, sys_clone, sys_uselib, sys_mlock
	.quad sys_munlock, sys_mlockall, sys_munlockall, sys_sysinfo, sys_sysctl
	.quad sys_idle, sys_umount, sys_swapon, sys_times, sys_personality
	.quad sys_setfsuid, sys_setfsgid, sys_ustat, sys_statfs, sys_fstatfs
	.quad sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler, sys_sched_yield
	.quad sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, do_entSys /* sys_afs_syscall */, sys_newuname
	.quad sys_nanosleep, sys_mremap, do_entSys, do_entSys, do_entSys
	.quad sys_pciconfig_read, sys_pciconfig_write, do_entSys, do_entSys, do_entSys


#ifdef CONFIG_KGDB

#define KGDB_STACK_SIZE	(8*1024)

	.lcomm	kgdb_stack_bottom, KGDB_STACK_SIZE

/*
 * The following is the nasty part of entering KGDB.  GDB assumes that
 * it can access the memory below the interrupted thread's stack
 * pointer (SP).  This means that the stub cannot run on this stack
 * (interrupts could overwrite changes made by GDB).  Similarly, we do
 * not want to bother the GDB user with the call chain leading from
 * the interrupt handler to this function.  That is, the SP reported
 * to GDB should be the thread's SP at the point it was interrupted.  We
 * achieve all this by switching to KGDB's own stack before saving any
 * registers (of course, the PAL-generated frame is already on the stack and
 * we copy that part explicitly).  GDB does whatever it wants to the
 * thread's stack; and when it continues execution, we restore the
 * registers from the private stack and return from the interrupt.
 *
 * This is not re-entrant---gdb on the host probably would get confused
 * anyway, but we probably ought to detect that case at the least...
 */
.align 3
.globl	entKGDB
.ent	entKGDB
entKGDB:
	lda	$16,kgdb_stack_bottom
	lda	$16,(KGDB_STACK_SIZE-48)($16)
	bis	$31,$30,$17	/* save real sp in a1 */
	bis	$31,$16,$30	/* update sp atomically! */
	SAVE_ALL		/* save regular stuff */
	/*
	 * Only now can we disable interrupts (swpipl may step on
	 * t0,t8..t11, and a0):
	 */
	bis	$31,7,$16
	call_pal PAL_swpipl

	/* copy PAL frame to kgdb stack: */

	ldq	$1,0($17)
	ldq	$2,8($17)
	ldq	$3,16($17)
	ldq	$4,24($17)
	ldq	$5,32($17)
	ldq	$6,40($17)

	stq	$1,0+184($30)
	stq	$2,8+184($30)
	stq	$3,16+184($30)
	stq	$4,24+184($30)
	stq	$5,32+184($30)
	stq	$6,40+184($30)

	/* allocate space for and save caller saved regs as well as orig sp: */

	lda	$30,-320($30)
	addq	$17,48,$17	/* pop PAL frame */
	stq	$17,0($30)	/* save original sp */

	stq	 $9,0x08($30); stq $10,0x10($30); stq $11,0x18($30)
	stq	$12,0x20($30); stq $13,0x28($30); stq $14,0x30($30)
	stq	$15,0x38($30)

	stt	$f0,0x40($30);   stt $f1,0x48($30);   stt $f2,0x50($30);   stt $f3,0x58($30)
	stt	$f4,0x60($30);   stt $f5,0x68($30);   stt $f6,0x70($30);   stt $f7,0x78($30)
	stt	$f8,0x80($30);   stt $f9,0x88($30);   stt $f10,0x90($30);  stt $f11,0x98($30)
	stt	$f12,0xa0($30);  stt $f13,0xa8($30);  stt $f14,0xb0($30);  stt $f15,0xb8($30)
	stt	$f16,0xc0($30);  stt $f17,0xc8($30);  stt $f18,0xd0($30);  stt $f19,0xd8($30)
	stt	$f20,0xe0($30);  stt $f21,0xe8($30);  stt $f22,0xf0($30);  stt $f23,0xf8($30)
	stt	$f24,0x100($30); stt $f25,0x108($30); stt $f26,0x110($30); stt $f27,0x118($30)
	stt	$f28,0x120($30); stt $f29,0x128($30); stt $f30,0x130($30); stt $f31,0x138($30)

	bis	$31,$30,$16

	lda	$27,kgdb_handle_exception
	jsr	$26,($27),kgdb_handle_exception

	ldq	$17,0($30)	/* load new sp and caller-saved registers */

	ldq	 $9,0x08($30); ldq $10,0x10($30); ldq $11,0x18($30)
	ldq	$12,0x20($30); ldq $13,0x28($30); ldq $14,0x30($30)
	ldq	$15,0x38($30)

	ldt	$f0,0x40($30);   ldt $f1,0x48($30);   ldt $f2,0x50($30);   ldt $f3,0x58($30)
	ldt	$f4,0x60($30);   ldt $f5,0x68($30);   ldt $f6,0x70($30);   ldt $f7,0x78($30)
	ldt	$f8,0x80($30);   ldt $f9,0x88($30);   ldt $f10,0x90($30);  ldt $f11,0x98($30)
	ldt	$f12,0xa0($30);  ldt $f13,0xa8($30);  ldt $f14,0xb0($30);  ldt $f15,0xb8($30)
	ldt	$f16,0xc0($30);  ldt $f17,0xc8($30);  ldt $f18,0xd0($30);  ldt $f19,0xd8($30)
	ldt	$f20,0xe0($30);  ldt $f21,0xe8($30);  ldt $f22,0xf0($30);  ldt $f23,0xf8($30)
	ldt	$f24,0x100($30); ldt $f25,0x108($30); ldt $f26,0x110($30); ldt $f27,0x118($30)
	ldt	$f28,0x120($30); ldt $f29,0x128($30); ldt $f30,0x130($30); ldt $f31,0x138($30)
	lda	$30,320($30)	/* pop extra register frame */

	/*
	 * Copy PAL frame from kgdb stack to new stack so we can rti
	 * to it:
	 */
	ldq	$1,0+184($30)
	ldq	$2,8+184($30)
	ldq	$3,16+184($30)
	ldq	$4,24+184($30)
	ldq	$5,32+184($30)
	ldq	$6,40+184($30)

	subq	$17,48,$17	/* alloc space for PAL frame on new stack */

	stq	$1,0($17)
	stq	$2,8($17)
	stq	$3,16($17)
	stq	$4,24($17)
	stq	$5,32($17)
	stq	$6,40($17)

	RESTORE_ALL
	bis	$31,$17,$30	/* establish new sp */
	rti

.end entKGDB

#endif /* CONFIG_KGDB */
