summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/vax/crt1.S
blob: 70960988d0ea33a5db8de28b86906c6b4425acac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
 * 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