Blame sysdeps/mips/start.S

Packit 6c4009
/* Startup code compliant to the ELF Mips ABI.
Packit 6c4009
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   In addition to the permissions in the GNU Lesser General Public
Packit 6c4009
   License, the Free Software Foundation gives you unlimited
Packit 6c4009
   permission to link the compiled version of this file with other
Packit 6c4009
   programs, and to distribute those programs without any restriction
Packit 6c4009
   coming from the use of this file. (The GNU Lesser General Public
Packit 6c4009
   License restrictions do apply in other respects; for example, they
Packit 6c4009
   cover modification of the file, and distribution when not linked
Packit 6c4009
   into another program.)
Packit 6c4009
Packit 6c4009
   Note that people who make modified versions of this file are not
Packit 6c4009
   obligated to grant this special exception for their modified
Packit 6c4009
   versions; it is their choice whether to do so. The GNU Lesser
Packit 6c4009
   General Public License gives permission to release a modified
Packit 6c4009
   version without this exception; this exception also makes it
Packit 6c4009
   possible to release a modified version which carries forward this
Packit 6c4009
   exception.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library.  If not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#define __ASSEMBLY__ 1
Packit 6c4009
#include <entry.h>
Packit 6c4009
#include <sgidefs.h>
Packit 6c4009
#include <sys/asm.h>
Packit 6c4009
Packit 6c4009
#ifndef ENTRY_POINT
Packit 6c4009
#error ENTRY_POINT needs to be defined for start.S on MIPS/ELF.
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* This is the canonical entry point, usually the first thing in the text
Packit 6c4009
   segment.  The SVR4/Mips ABI (pages 3-31, 3-32) says that when the entry
Packit 6c4009
   point runs, most registers' values are unspecified, except for:
Packit 6c4009
Packit 6c4009
   v0 ($2)	Contains a function pointer to be registered with `atexit'.
Packit 6c4009
		This is how the dynamic linker arranges to have DT_FINI
Packit 6c4009
		functions called for shared libraries that have been loaded
Packit 6c4009
		before this code runs.
Packit 6c4009
Packit 6c4009
   sp ($29)	The stack contains the arguments and environment:
Packit 6c4009
		0(%esp)			argc
Packit 6c4009
		4(%esp)			argv[0]
Packit 6c4009
		...
Packit 6c4009
		(4*argc)(%esp)		NULL
Packit 6c4009
		(4*(argc+1))(%esp)	envp[0]
Packit 6c4009
		...
Packit 6c4009
					NULL
Packit 6c4009
   ra ($31)	The return address register is set to zero so that programs
Packit 6c4009
		that search backword through stack frames recognize the last
Packit 6c4009
		stack frame.
Packit 6c4009
*/
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* We need to call:
Packit 6c4009
   __libc_start_main (int (*main) (int, char **, char **), int argc,
Packit 6c4009
		      char **argv, void (*init) (void), void (*fini) (void),
Packit 6c4009
		      void (*rtld_fini) (void), void *stack_end)
Packit 6c4009
*/
Packit 6c4009
Packit 6c4009
	.text
Packit 6c4009
	.globl ENTRY_POINT
Packit 6c4009
	.type ENTRY_POINT,@function
Packit 6c4009
#ifndef __mips16
Packit 6c4009
ENTRY_POINT:
Packit 6c4009
# ifdef __PIC__
Packit 6c4009
	SETUP_GPX($0)
Packit 6c4009
	SETUP_GPX64($25,$0)
Packit 6c4009
# else
Packit 6c4009
	PTR_LA $28, _gp		/* Setup GP correctly if we're non-PIC.  */
Packit 6c4009
	move $31, $0
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
	PTR_LA $4, main		/* main */
Packit 6c4009
	PTR_L $5, 0($29)		/* argc */
Packit 6c4009
	PTR_ADDIU $6, $29, PTRSIZE	/* argv  */
Packit 6c4009
Packit 6c4009
	/* Allocate space on the stack for seven arguments (o32 only)
Packit 6c4009
	   and make sure the stack is aligned to double words (8 bytes)
Packit 6c4009
	   on o32 and quad words (16 bytes) on n32 and n64.  */
Packit 6c4009
Packit 6c4009
	and $29, -2 * SZREG
Packit 6c4009
# if _MIPS_SIM == _ABIO32
Packit 6c4009
	PTR_SUBIU $29, 32
Packit 6c4009
# endif
Packit 6c4009
	PTR_LA $7, __libc_csu_init		/* init */
Packit 6c4009
	PTR_LA $8, __libc_csu_fini
Packit 6c4009
# if _MIPS_SIM == _ABIO32
Packit 6c4009
	PTR_S $8, 16($29)		/* fini */
Packit 6c4009
	PTR_S $2, 20($29)		/* rtld_fini */
Packit 6c4009
	PTR_S $29, 24($29)		/* stack_end */
Packit 6c4009
# else
Packit 6c4009
	move $9, $2		/* rtld_fini */
Packit 6c4009
	move $10, $29		/* stack_end */
Packit 6c4009
# endif
Packit 6c4009
	PTR_LA $25, __libc_start_main
Packit 6c4009
	jalr   $25
Packit 6c4009
hlt:	b hlt			/* Crash if somehow it does return.  */
Packit 6c4009
Packit 6c4009
#elif _MIPS_SIM == _ABIO32 /* __mips16 */
Packit 6c4009
	/* MIPS16 entry point.  */
Packit 6c4009
	.set	mips16
Packit 6c4009
ENTRY_POINT:
Packit 6c4009
# ifdef __PIC__
Packit 6c4009
	li	$3, %hi(_gp_disp)
Packit 6c4009
	addiu	$4, $pc, %lo(_gp_disp)
Packit 6c4009
	sll	$3, 16
Packit 6c4009
	addu	$3, $4
Packit 6c4009
	move	$gp, $3
Packit 6c4009
# else
Packit 6c4009
	li	$3, %hi(_gp)
Packit 6c4009
	sll	$3, 16
Packit 6c4009
	addiu	$3, %lo(_gp)
Packit 6c4009
	move	$gp, $3
Packit 6c4009
# endif
Packit 6c4009
	/* Tie end of stack frames.  */
Packit 6c4009
	li	$4, 0
Packit 6c4009
	move	$31, $4
Packit 6c4009
	/* Create new SP value in $7, including alignment.  */
Packit 6c4009
	li	$4, 2 * SZREG
Packit 6c4009
	neg	$4, $4
Packit 6c4009
	move	$7, $sp
Packit 6c4009
	and	$7, $4
Packit 6c4009
	addiu	$7, -32
Packit 6c4009
	/* Load arguments with original SP.  */
Packit 6c4009
	lw	$5, 0($sp)
Packit 6c4009
	addiu	$6, $sp, PTRSIZE
Packit 6c4009
	/* Update SP.  */
Packit 6c4009
	move	$sp, $7
Packit 6c4009
	/* Lay out last arguments, and call __libc_start_main().  */
Packit 6c4009
# ifdef __PIC__
Packit 6c4009
	sw	$7, 24($sp)			/* stack_end */
Packit 6c4009
	lw	$4, %got(__libc_csu_fini)($3)
Packit 6c4009
	lw	$7, %got(__libc_csu_init)($3)	/* init */
Packit 6c4009
	sw	$4, 16($sp)			/* fini */
Packit 6c4009
	lw	$4, %got(main)($3)		/* main */
Packit 6c4009
	lw	$3, %call16(__libc_start_main)($3)
Packit 6c4009
	sw	$2, 20($sp)			/* rtld_fini */
Packit 6c4009
	move	$25, $3
Packit 6c4009
	jalr	$3
Packit 6c4009
# else
Packit 6c4009
	lw	$4, 1f
Packit 6c4009
	sw	$7, 24($sp)			/* stack_end */
Packit 6c4009
	lw	$7, 2f				/* init */
Packit 6c4009
	sw	$4, 16($sp)			/* fini */
Packit 6c4009
	lw	$4, 3f				/* main */
Packit 6c4009
	sw	$2, 20($sp)			/* rtld_fini */
Packit 6c4009
	/* Load and call __libc_start_main().  */
Packit 6c4009
	lw	$3, 4f
Packit 6c4009
	jalr	$3
Packit 6c4009
# endif
Packit 6c4009
hlt:	b	hlt		/* Crash if somehow it does return.  */
Packit 6c4009
# ifndef __PIC__
Packit 6c4009
	.align	2
Packit 6c4009
1:	.word	__libc_csu_fini
Packit 6c4009
2:	.word	__libc_csu_init
Packit 6c4009
3:	.word	main
Packit 6c4009
4:	.word	__libc_start_main
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
#else /* __mips16 && _MIPS_SIM != _ABIO32 */
Packit 6c4009
# error "MIPS16 support for N32/N64 not implemented"
Packit 6c4009
Packit 6c4009
#endif /* __mips16 */
Packit 6c4009
Packit 6c4009
/* Define a symbol for the first piece of initialized data.  */
Packit 6c4009
	.data
Packit 6c4009
	.globl __data_start
Packit 6c4009
__data_start:
Packit 6c4009
	.long 0
Packit 6c4009
	.weak data_start
Packit 6c4009
	data_start = __data_start