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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/* Copyright (C) 1991, 1992, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
/* Based on ../i386/crt0.S and newlib's libgloss/frv/crt0.S */
/*
When we enter this piece of code, the program stack looks like this:
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
Also, GR16 holds a pointer to a memory map. */
#include <features.h>
.text
.global _start
.type _start,%function
#if defined L_crt0 || defined L_Scrt0 || ! defined __UCLIBC_CTOR_DTOR__
.type __uClibc_main,%function
#else
.weak _init
.weak _fini
.type __uClibc_start_main,%function
#endif
_start:
/* Make sure the stack pointer is properly aligned. Save the
original value in gr21 such that we can get to arguments and
such from there. */
mov.p sp, gr21
andi sp, #-8, sp
/* At program start-up, gr16 contains a pointer to a memory
map, that we use to relocate addresses. */
call .Lcall
.Lcall:
movsg lr, gr4
sethi.p #gprelhi(.Lcall), gr5
setlo #gprello(.Lcall), gr5
sub.p gr4, gr5, gr4
/* gr4 now holds the _gp address. */
mov gr16, gr8
sethi.p #gprelhi(__ROFIXUP_LIST__), gr9
sethi #gprelhi(__ROFIXUP_END__), gr10
setlo.p #gprello(__ROFIXUP_LIST__), gr9
setlo #gprello(__ROFIXUP_END__), gr10
add.p gr9, gr4, gr9
add gr10, gr4, gr10
call __self_reloc
mov.p gr8, gr17
mov gr8, gr15
/* gr17 now holds the self-relocated _GLOBAL_OFFSET_TABLE_
address, because the linker added its unrelocated address as
the last entry in the ROFIXUP list, and __self_reloc returns
the last entry, relocated. */
/* Prepare arguments for uClibc main. */
ld @(gr21, gr0), gr8
slli gr8, #2, gr10
add gr21, gr10, gr10
addi.p gr21, #4, gr9
addi gr10, #8, gr10
/* Set up an invalid (NULL return address, NULL frame pointer)
callers stack frame so anybody unrolling the stack knows where
to stop */
mov gr0, fp
movgs gr0, lr
#if (defined L_crt1 || defined L_Scrt1) && defined __UCLIBC_CTOR_DTOR__
/* Pass .init and .fini arguments to __uClibc_start_main(). */
sethi.p #gotfuncdeschi(_init), gr11
sethi #gotfuncdeschi(_fini), gr12
setlo.p #gotfuncdesclo(_init), gr11
setlo #gotfuncdesclo(_fini), gr12
ld.p @(gr11, gr17), gr11
mov gr17, gr15
ld.p @(gr12, gr17), gr12
call __uClibc_start_main
#else
mov.p gr17, gr15
call __uClibc_main
#endif
/* Crash if somehow `exit' returns anyways. */
jmpl @(gr0,gr0)
.size _start,.-_start
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start
|