/* 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