Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / tile / dl-start.S
blobd13f6096dc6ed68100987cc8b464b2b4b7fbe811
1 /* Copyright (C) 2011-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
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.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library.  If not, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
21         /* Get address of "sym" in "reg" assuming r51 holds ".Llink". */
22         .macro pic_addr reg, sym
23 #ifdef __tilegx__
24         moveli \reg, hw1_last(\sym - .Llink)
25         shl16insli \reg, \reg, hw0(\sym - .Llink)
26         ADD_PTR \reg, r51, \reg
27 #else
28         ADDLI_PTR \reg, r51, lo16(\sym - .Llink)
29         auli \reg, \reg, ha16(\sym - .Llink)
30 #endif
31         .endm
33         .text
34 ENTRY (_start)
35         /* Linux starts us with sp pointing at the conventional Elf layout,
36            but we need to allow two 'caller' words for our ABI convention.  */
37         {
38          move r52, sp
39          andi sp, sp, -8
40         }
41         cfi_def_cfa_register (r52)
42         {
43          /* Point sp at base of ABI area; point r4 to the caller-sp word. */
44          ADDI_PTR sp, sp, -(2 * REGSIZE)
45          ADDI_PTR r4, sp, -REGSIZE
46         }
47         {
48          /* Save zero for caller sp in our 'caller' save area, and make
49             sure lr has a zero value, to limit backtraces.  */
50          move lr, zero
51          ST r4, zero
52         }
53         {
54          move r0, r52
55          jal _dl_start
56         }
57         /* Save returned start of user program address for later. */
58         move r50, r0
60         /* See if we were invoked explicitly with the dynamic loader,
61            in which case we have to adjust the argument vector.  */
62         lnk r51; .Llink:
63         pic_addr r4, _dl_skip_args
64         LD4U r4, r4
65         BEQZT r4, .Lno_skip
67         /* Load the argc word at the initial sp and adjust it.
68            We basically jump "sp" up over the first few argv entries
69            and write "argc" a little higher up in memory, to be the
70            base of the new kernel-initialized stack area.  */
71         LD_PTR r0, r52
72         {
73          sub r0, r0, r4
74          SHL_PTR_ADD r52, r4, r52
75         }
76         {
77          ST_PTR r52, r0
78          SHL_PTR_ADD sp, r4, sp
79         }
80         andi sp, sp, -8
82 .Lno_skip:
83         /* Call_dl_init (_dl_loaded, argc, argv, envp).  See elf/start.s
84            for the layout of memory here; r52 is pointing to "+0".  */
85         pic_addr r0, _rtld_local
86         {
87          LD_PTR r1, r52  /* load argc in r1 */
88          ADDLI_PTR r2, r52, __SIZEOF_POINTER__  /* point r2 at argv */
89         }
90         {
91          LD_PTR r0, r0    /* yields _rtld_global._ns_loaded */
92          addi r3, r1, 1
93          move lr, zero
94         }
95         {
96          SHL_PTR_ADD r3, r3, r2  /* point r3 at envp */
97          jal _dl_init_internal
98         }
100         /* Call user program whose address we saved in r50.
101            We invoke it just like a static binary, but with _dl_fini
102            in r0 so we can distinguish.  */
104         pic_addr r0, _dl_fini
105         move lr, zero
106         {
107          move sp, r52
108          jr r50
109         }
111         /* Tell backtracer to give up (_start has no caller). */
112         info 2  /* INFO_OP_CANNOT_BACKTRACE */
114 END (_start)