1 | /* Startup code for Nios II |
2 | Copyright (C) 1995-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | In addition to the permissions in the GNU Lesser General Public |
11 | License, the Free Software Foundation gives you unlimited |
12 | permission to link the compiled version of this file with other |
13 | programs, and to distribute those programs without any restriction |
14 | coming from the use of this file. (The GNU Lesser General Public |
15 | License restrictions do apply in other respects; for example, they |
16 | cover modification of the file, and distribution when not linked |
17 | into another program.) |
18 | |
19 | Note that people who make modified versions of this file are not |
20 | obligated to grant this special exception for their modified |
21 | versions; it is their choice whether to do so. The GNU Lesser |
22 | General Public License gives permission to release a modified |
23 | version without this exception; this exception also makes it |
24 | possible to release a modified version which carries forward this |
25 | exception. |
26 | |
27 | The GNU C Library is distributed in the hope that it will be useful, |
28 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
30 | Lesser General Public License for more details. |
31 | |
32 | You should have received a copy of the GNU Lesser General Public |
33 | License along with the GNU C Library. If not, see |
34 | <https://www.gnu.org/licenses/>. */ |
35 | |
36 | /* This is the canonical entry point, usually the first thing in the text |
37 | segment. |
38 | |
39 | Note that the code in the .init section has already been run. |
40 | This includes _init and _libc_init |
41 | |
42 | The stack pointer, sp, will point to the argument count on the stack. |
43 | The initial state of the stack when a userspace process is started is: |
44 | |
45 | Purpose Start Address Length |
46 | Unspecified High Addresses |
47 | Referenced strings, etc. Varies |
48 | Unspecified |
49 | Null auxilliary vector entry 4bytes |
50 | Auxilliary vector entries 8bytes each |
51 | NULL terminator for envp 4bytes |
52 | Environment pointers sp+8+4*argc 4bytes each |
53 | NULL terminator for argv sp+4+4*argc 4bytes |
54 | Argument pointers sp+4 4bytes each |
55 | Argument count sp 4bytes |
56 | Unspecified Low Addresses |
57 | |
58 | If the application should register a destructor function with atexit, |
59 | the pointer will be placed in r4. Otherwise r4 will be zero. |
60 | |
61 | The contents of all other registers are unspecified. User code should |
62 | set fp to zero to mark the end of the frame chain. |
63 | |
64 | The auxilliary vector is a series of pairs of 32-bit tag and 32-bit |
65 | value, terminated by an AT_NULL tag. |
66 | */ |
67 | |
68 | .text |
69 | .globl _start |
70 | .type _start,%function |
71 | _start: |
72 | /* Set up the global pointer. */ |
73 | movhi gp, %hiadj(_gp) |
74 | addi gp, gp, %lo(_gp) |
75 | |
76 | /* Save the stack pointer. */ |
77 | mov r2, sp |
78 | |
79 | /* Create room on the stack for the fini, rtld_fini and stack_end args |
80 | to __libc_start_main. */ |
81 | subi sp, sp, 12 |
82 | |
83 | /* Push stack_end */ |
84 | stw r2, 8(sp) |
85 | |
86 | /* Push rtld_fini */ |
87 | stw r4, 4(sp) |
88 | |
89 | /* Set up the GOT pointer. */ |
90 | nextpc r22 |
91 | 1: movhi r2, %hiadj(_gp_got - 1b) |
92 | addi r2, r2, %lo(_gp_got - 1b) |
93 | add r22, r22, r2 |
94 | |
95 | /* Used to be fini. */ |
96 | stw zero, 0(sp) |
97 | |
98 | /* Used to be init. */ |
99 | mov r7, zero |
100 | |
101 | /* r6 == argv */ |
102 | addi r6, sp, 16 |
103 | |
104 | /* r5 == argc */ |
105 | ldw r5, 12(sp) |
106 | |
107 | /* r4 == main */ |
108 | movhi r4, %call_hiadj(main) |
109 | addi r4, r4, %call_lo(main) |
110 | add r4, r4, r22 |
111 | ldw r4, 0(r4) |
112 | |
113 | /* fp == 0 */ |
114 | mov fp, zero |
115 | |
116 | /* __libc_start_main (main, argc, argv, init, fini, rtld_fini, |
117 | stack_end) */ |
118 | |
119 | /* Let the libc call main and exit with its return code. */ |
120 | movhi r2, %call_hiadj(__libc_start_main) |
121 | addi r2, r2, %call_lo(__libc_start_main) |
122 | add r2, r2, r22 |
123 | ldw r2, 0(r2) |
124 | callr r2 |
125 | |
126 | /* should never get here....*/ |
127 | movhi r2, %call_hiadj(abort) |
128 | addi r2, r2, %call_lo(abort) |
129 | add r2, r2, r22 |
130 | ldw r2, 0(r2) |
131 | callr r2 |
132 | |
133 | /* Define a symbol for the first piece of initialized data. */ |
134 | .data |
135 | .globl __data_start |
136 | __data_start: |
137 | .long 0 |
138 | .weak data_start |
139 | data_start = __data_start |
140 | |