summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/powerpc/crt1.S
blob: 3ac32636cd9370aa0599f5409af9820714ce04c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * Copyright (C) 2003 by Erik Andersen
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Library General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program 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 Library General Public License
 * along with this program; see the file COPYING.LIB.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include <features.h>
/* Integer registers.  */
#define r0      0
#define r1      1
#define r2      2
#define r3      3
#define r4      4
#define r5      5
#define r6      6
#define r7      7
#define r8      8
#define r9      9
#define r10     10
#define r13     13
#define r31     31

.text
	.globl	_start
	.type	_start,%function
	.type	_init,%function
	.type	_fini,%function
#ifndef __UCLIBC_CTOR_DTOR__
	.weak _init
	.weak _fini
#endif
#ifdef L_rcrt1
	.type reloc_static_pie,%function
#endif
	.type	main,%function
	.type	__uClibc_main,%function

_start:
	mr	r9,r1 	/* Save the stack pointer and pass it to __uClibc_main */
	clrrwi	r1,r1,4	/* Align stack ptr to 16 bytes */
#ifdef __PIC__
# ifdef HAVE_ASM_PPC_REL16
	bcl	20,31,1f
1:	mflr	r31
	addis	r31,r31,_GLOBAL_OFFSET_TABLE_-1b@ha
	addi	r31,r31,_GLOBAL_OFFSET_TABLE_-1b@l
# else
	bl	_GLOBAL_OFFSET_TABLE_-4@local
	mflr	r31
# endif
	/* in PIC/PIE, plt stubs need r30 to point to the GOT if using secure-plt */
# ifdef PPC_HAS_SECUREPLT
	mr	30,31
# endif
#ifdef L_rcrt1
	stwu r3, -4(r1)					/* Save r3 */
	stwu r9, -16(r1)				/* Save r9 */
	bcl 20,31,2f					/* Jump to label 2 */
2:	mflr r3							/* Load lr into r3 */
	addis r3, r3, _DYNAMIC-2b@ha	/* Add high half of _DYNAMIC to r3 */
	addi r3,r3,_DYNAMIC-2b@l		/* Add low half of _DYNAMIC */
	lwz r4, 0(r31)					/* load _DYNAMIC from the GOT */
	subf r3, r4, r3					/* sub _DYNAMIC@got and it's actual address */
	bl reloc_static_pie				/* Call reloc_static_pie */
	lwzu r9, 0(r1)					/* restore r9 */
	addi r1, r1, 16					/* update stack pointer */
	lwzu r3, 0(r1)					/* restore r3 */
	addi r1, r1, 4					/* update stack pointer */
	li r5, 0						/* zero r5 */
#endif
#endif
	/* Set up the small data pointer in r13.  */
#ifdef __PIC__
	lwz	r13,_SDA_BASE_@got(r31)
#else
	lis	r13,_SDA_BASE_@ha
	addi	r13,r13,_SDA_BASE_@l
#endif
	/* Set up an initial stack frame, and clear the LR.  */
	li	r0,0
	stwu	r1,-16(r1)
	mtlr	r0
	stw	r0,0(r1)
	/* find argc from the stack pointer */
	lwz	r4,0(r9)
	/* find argv one word offset from the stack pointer */
	addi	r5,r9,4
	mr	r8,r3 /* Pass _dl_fini from ldso or NULL if statically linked */
		      /* Note: PPC depends on the kernel to zero r3 before */
		      /* handing over to user space, otherwise static apps */
		      /* will SEGV during exit() */

	/* Ok, now run uClibc's main() -- shouldn't return */
#ifdef __PIC__
	lwz	r6,_init@got(r31)
	lwz	r7,_fini@got(r31)
	lwz	r3,main@got(r31)
	b	__uClibc_main@plt
#else
	lis     r6,_init@ha	# load top 16 bits
	addi    r6,r6,_init@l	# load bottom 16 bits
	lis     r7,_fini@ha	# load top 16 bits
	addi    r7,r7,_fini@l	# load bottom 16 bits
	lis     r3,main@ha	# load top 16 bits
	addi    r3,r3,main@l	# load bottom 16 bits
	b	__uClibc_main
#endif

.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