lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 1 | /* Copyright (C) 2011-2015 Free Software Foundation, Inc. |
| 2 | This file is part of the GNU C Library. |
| 3 | Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. |
| 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 | 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. |
| 14 | |
| 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/>. */ |
| 18 | |
| 19 | #include <sysdep.h> |
| 20 | |
| 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 |
| 32 | |
| 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 |
| 59 | |
| 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 |
| 66 | |
| 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 |
| 81 | |
| 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 |
| 98 | } |
| 99 | |
| 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. */ |
| 103 | |
| 104 | pic_addr r0, _dl_fini |
| 105 | move lr, zero |
| 106 | { |
| 107 | move sp, r52 |
| 108 | jr r50 |
| 109 | } |
| 110 | |
| 111 | /* Tell backtracer to give up (_start has no caller). */ |
| 112 | info 2 /* INFO_OP_CANNOT_BACKTRACE */ |
| 113 | |
| 114 | END (_start) |