/*
 * crt0 for VAX
 */

/*
 * Program stack looks like:
 * sp->	argc            argument counter (integer)
 *	argv[0]         program name (pointer)
 *	argv[1...N]     program args (pointers)
 *	argv[argc-1]    end of args (integer)
 *	NULL
 *	env[0...N]      environment variables (pointers)
 *	NULL
 */

#include <features.h>

.text
.align 4

.global __start
__start:
.global _start
_start:
	/* Kernel uses a_interp + 2, so __start isn't exactly CALLSed,	*/
	/* but we need to have two bytes here, so we use NOPs. This	*/
	/* won't hurt, though R0 would be invalid to push, but at	*/
	/* lease this looks like a real function.			*/
	.word	0x0101

	movl	$0, %fp			/* FP = 0, since this is the	*/
					/* top-most stack frame		*/
	movl	%sp, %r0		/* R0 = %sp			*/
	movl	(%sp)+, %r4		/* R4 = argc			*/
	movl	%sp, %r3		/* R3 = argv = &argv[0]		*/

#if (defined L_crt1 || defined L_gcrt1) && defined __UCLIBC_CTOR_DTOR__
	pushl	%r0	/* stack_end					*/
	pushl	$0	/* rtld_fini. This is probably needed for the	*/
			/* case where a dynamic linker is involved. So	*/
			/* this is an open FIXME that needs to be	*/
			/* addressed at some time...			*/
	pushl	$_fini
	pushl	$_init
	pushl	%r3	/* Argument pointer				*/
	pushl	%r4	/* And the argument count			*/
	pushl	$main	/* main()					*/

	/* We need to call __uClibc_main which should not return.
	 * __uClibc_main (int (*main) (int, char **, char **),
	 *                int argc,
	 *                char **argv,
	 *                void (*init) (void),
	 *                void (*fini) (void),
	 *                void (*rtld_fini) (void),
	 *                void *stack_end);
	 */
	calls	$7, __uClibc_main
#else /* FIXME: THIS IS BROKEN!!! */
	/* start to load the arguments from the stack */
	/* arguments are on ap stack */
	pushl	%r2
	pushl	%r3
	pushl	%r4

	calls	$3, __uClibc_main
#endif

	/* The above __uClibc_start_main() shouldn't ever return. If it	*/
	/* does, we just crash.						*/
	halt
.align 2