1/* Copyright (C) 1991, 1992, 2003, 2004 Free Software Foundation, Inc.
2This file is part of the GNU C Library.
3
4The GNU C Library is free software; you can redistribute it and/or
5modify it under the terms of the GNU Lesser General Public License as
6published by the Free Software Foundation; either version 2.1 of the
7License, or (at your option) any later version.
8
9The GNU C Library is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12Library General Public License for more details.
13
14In addition to the permissions in the GNU Lesser General Public
15License, the Free Software Foundation gives you unlimited
16permission to link the compiled version of this file with other
17programs, and to distribute those programs without any restriction
18coming from the use of this file.  (The GNU Lesser General Public
19License restrictions do apply in other respects; for example, they
20cover modification of the file, and distribution when not linked
21into another program.)
22
23You should have received a copy of the GNU Lesser General Public
24License along with the GNU C Library; see the file COPYING.LIB.  If
25not, see <http://www.gnu.org/licenses/>.  */
26
27
28/*  Based on ../i386/crt0.S and newlib's libgloss/frv/crt0.S  */
29
30/*
31    When we enter this piece of code, the program stack looks like this:
32        argc            argument counter (integer)
33        argv[0]         program name (pointer)
34        argv[1...N]     program args (pointers)
35        argv[argc-1]    end of args (integer)
36	NULL
37        env[0...N]      environment variables (pointers)
38        NULL
39
40    Also, GR16 holds a pointer to a memory map.  */
41
42#include <features.h>
43
44	.text
45	.global _start
46	.type	_start,%function
47	.weak	_init
48	.weak	_fini
49	.type	__uClibc_main,%function
50
51_start:
52	/* Make sure the stack pointer is properly aligned.  Save the
53	   original value in gr21 such that we can get to arguments and
54	   such from there.  */
55	mov.p	sp, gr21
56	andi	sp, #-8, sp
57	/* At program start-up, gr16 contains a pointer to a memory
58	   map, that we use to relocate addresses.  */
59	call	.Lcall
60.Lcall:
61	movsg	lr, gr4
62	sethi.p	#gprelhi(.Lcall), gr5
63	setlo	#gprello(.Lcall), gr5
64	sub.p	gr4, gr5, gr4
65	/* gr4 now holds the _gp address.  */
66
67	mov	gr16, gr8
68	sethi.p #gprelhi(__ROFIXUP_LIST__), gr9
69	sethi	#gprelhi(__ROFIXUP_END__), gr10
70	setlo.p #gprello(__ROFIXUP_LIST__), gr9
71	setlo	#gprello(__ROFIXUP_END__), gr10
72	add.p	gr9, gr4, gr9
73	add	gr10, gr4, gr10
74	call	__self_reloc
75	mov.p	gr8, gr17
76	mov	gr8, gr15
77	/* gr17 now holds the self-relocated _GLOBAL_OFFSET_TABLE_
78	address, because the linker added its unrelocated address as
79	the last entry in the ROFIXUP list, and __self_reloc returns
80	the last entry, relocated.  */
81
82	/* Prepare arguments for uClibc main.  */
83	ld	@(gr21, gr0), gr8
84	slli	gr8, #2, gr10
85	add	gr21, gr10, gr10
86	addi.p	gr21, #4, gr9
87	addi	gr10, #8, gr10
88
89	/* Set up an invalid (NULL return address, NULL frame pointer)
90	   callers stack frame so anybody unrolling the stack knows where
91	   to stop */
92	mov	gr0, fp
93	movgs	gr0, lr
94
95#if (defined L_crt1 || defined L_Scrt1) && defined __UCLIBC_CTOR_DTOR__
96	/* Pass .init and .fini arguments to __uClibc_start_main().  */
97	sethi.p	#gotfuncdeschi(_init), gr11
98	sethi	#gotfuncdeschi(_fini), gr12
99	setlo.p	#gotfuncdesclo(_init), gr11
100	setlo	#gotfuncdesclo(_fini), gr12
101	ld.p	@(gr11, gr17), gr11
102	mov	gr17, gr15
103	ld.p	@(gr12, gr17), gr12
104	call	__uClibc_main
105#else
106	mov.p	gr17, gr15
107	call	__uClibc_main
108#endif
109
110	/* Crash if somehow `exit' returns anyways.  */
111	jmpl	@(gr0,gr0)
112.size _start,.-_start
113
114/* Define a symbol for the first piece of initialized data.  */
115	.data
116	.globl __data_start
117__data_start:
118	.long 0
119	.weak data_start
120	data_start = __data_start
121
122