/* Copyright (C) 1991, 1992, 2003 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. 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 .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 /* Stick in a dummy reference to main(), so that if an application * is linking when the main() function is in a static library (.a) * we can be sure that main() actually gets linked in */ .type main,%function _start: /* 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 @(sp, gr0), gr8 slli gr8, #2, gr10 add sp, gr10, gr10 addi.p sp, #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_gcrt1 || 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 #if defined L_gcrt1 && defined __UCLIBC_PROFILING__ # include "./gmon-start.S" #endif /* 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