1/*
2 * Copyright (c) 1999-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
7 * Reserved.  This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License").  You may not use this file
10 * except in compliance with the License.  Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25
26#if __ppc__ && __DYNAMIC__
27//
28// Force stub section next to __text section to minimize chance that
29// a bl to a stub will be out of range.
30//
31	.text
32	.symbol_stub
33	.picsymbol_stub
34#endif
35
36/*
37 * C runtime startup for ppc, ppc64, i386, x86_64
38 *
39 * Kernel sets up stack frame to look like:
40 *
41 *	       :
42 *	| STRING AREA |
43 *	+-------------+
44 *	|      0      |
45 *	+-------------+
46 *	|  exec_path  | extra "apple" parameters start after NULL terminating env array
47 *	+-------------+
48 *	|      0      |
49 *	+-------------+
50 *	|    env[n]   |
51 *	+-------------+
52 *	       :
53 *	       :
54 *	+-------------+
55 *	|    env[0]   |
56 *	+-------------+
57 *	|      0      |
58 *	+-------------+
59 *	| arg[argc-1] |
60 *	+-------------+
61 *	       :
62 *	       :
63 *	+-------------+
64 *	|    arg[0]   |
65 *	+-------------+
66 *	|     argc    | argc is always 4 bytes long, even in 64-bit architectures
67 *	+-------------+ <- sp
68 *
69 *	Where arg[i] and env[i] point into the STRING AREA
70 */
71
72	.text
73	.globl start
74	.align 2
75
76#if __ppc__
77start:	mr      r26,r1              ; save original stack pointer into r26
78	subi	r1,r1,4		    ; make space for linkage
79	clrrwi	r1,r1,5             ; align to 32 bytes (good enough for 32- and 64-bit APIs)
80	li      r0,0                ; load 0 into r0
81	stw     r0,0(r1)            ; terminate initial stack frame
82	stwu	r1,-64(r1)	    ; allocate minimal stack frame
83	lwz     r3,0(r26)           ; get argc into r3
84	addi    r4,r26,4	    ; get argv into r4
85	addi	r27,r3,1            ; calculate argc + 1 into r27
86	slwi	r27,r27,2	    ; calculate (argc + 1) * sizeof(char *) into r27
87	add     r5,r4,r27           ; get address of env[0] into r5
88#if OLD_LIBSYSTEM_SUPPORT
89	bl	__start		    ; 24-bt branch to __start.  ld64 will make a branch island if needed
90	trap                        ; should never return
91#else
92	mr	r6,r5
93Lapple:	lwz	r0,0(r6)	    ; look for NULL ending env[] array
94	addi	r6,r6,4
95	cmpwi	r0,0
96	bne	Lapple		    ; once found, next pointer is "apple" parameter now in r6
97	bl	_main
98	b	_exit		    ; pass result from main() to exit()
99#endif
100#endif // __ppc__
101
102
103#if __ppc64__
104start:	mr      r26,r1              ; save original stack pointer into r26
105	subi	r1,r1,8		    ; make space for linkage
106	clrrdi	r1,r1,5             ; align to 32 bytes (good enough for 32- and 64-bit APIs)
107	li      r0,0                ; load 0 into r0
108	std     r0,0(r1)            ; terminate initial stack frame
109	stdu	r1,-128(r1)	    ; allocate minimal stack frame
110	lwz     r3,0(r26)           ; get argc into r3
111	addi    r4,r26,8	    ; get argv into r4
112	addi	r27,r3,1            ; calculate argc + 1 into r27
113	sldi	r27,r27,3	    ; calculate (argc + 1) * sizeof(char *) into r27
114	add     r5,r4,r27           ; get address of env[0] into r5
115#if OLD_LIBSYSTEM_SUPPORT
116	bl	__start		    ; 24-bt branch to __start.  ld64 will make a branch island if needed
117	trap                        ; should never return
118#else
119	mr	r6,r5
120Lapple:	ld	r0,0(r6)	    ; look for NULL ending env[] array
121	addi	r6,r6,8
122	cmpdi	r0,0
123	bne	Lapple		    ; once found, next pointer is "apple" parameter now in r6
124	bl	_main
125	b	_exit		    ; pass result from main() to exit()
126#endif
127#endif	// __ppc64__
128
129
130#if __i386__
131start:	pushl	$0		    # push a zero for debugger end of frames marker
132	movl	%esp,%ebp	    # pointer to base of kernel frame
133	andl    $-16,%esp	    # force SSE alignment
134	subl    $16,%esp	    # room for new argc, argv, & envp, SSE aligned
135	movl	4(%ebp),%ebx	    # pickup argc in %ebx
136	movl	%ebx,0(%esp)	    # argc to reserved stack word
137	lea	8(%ebp),%ecx	    # addr of arg[0], argv, into %ecx
138	movl	%ecx,4(%esp)	    # argv to reserved stack word
139	addl	$1,%ebx		    # argc + 1 for zero word
140	sall	$2,%ebx		    # * sizeof(char *)
141	addl	%ecx,%ebx	    # addr of env[0], envp, into %ebx
142	movl	%ebx,8(%esp)	    # envp to reserved stack word
143#if OLD_LIBSYSTEM_SUPPORT
144	call	__start		    # call _start(argc, argv, envp)
145	hlt			    # should never return
146#else
147Lapple:	movl	(%ebx),%eax	    # look for NULL ending env[] array
148	add	$4,%ebx
149	testl	%eax,%eax
150	jne	Lapple		    # once found, next pointer is "apple" parameter now in %ebx
151	movl	%ebx,12(%esp)	    # apple to reserved stack word
152	call	_main
153	movl	%eax, 0(%esp)	    # pass result from main() to exit()
154	call	_exit		    # need to use call to keep stack aligned
155	hlt
156#endif
157#endif // __i386__
158
159
160
161#if __x86_64__
162start:	pushq	$0		    # push a zero for debugger end of frames marker
163	movq	%rsp,%rbp	    # pointer to base of kernel frame
164	andq    $-16,%rsp	    # force SSE alignment
165	movq	8(%rbp),%rdi	    # put argc in %rdi
166	leaq	16(%rbp),%rsi	    # addr of arg[0], argv, into %rsi
167	movl	%edi,%edx	    # copy argc into %rdx
168	addl	$1,%edx		    # argc + 1 for zero word
169	sall	$3,%edx		    # * sizeof(char *)
170	addq	%rsi,%rdx	    # addr of env[0], envp, into %rdx
171#if OLD_LIBSYSTEM_SUPPORT
172	call	__start		    # call _start(argc, argv, envp)
173	hlt			    # should never return
174#else
175	movq	%rdx,%rcx
176	jmp	Lapple2
177Lapple:	add	$8,%rcx
178Lapple2:cmpq	$0,(%rcx)	    # look for NULL ending env[] array
179	jne	Lapple
180	add	$8,%rcx		    # once found, next pointer is "apple" parameter now in %rcx
181	call	_main
182	movl	%eax,%edi	    # pass result from main() to exit()
183	call	_exit		    # need to use call to keep stack aligned
184	hlt
185#endif
186#endif // __x86_64__
187
188#ifdef __arm__
189start:
190	ldr	r0, [sp]		// get argc into r0
191	add	r1, sp, #4		// get argv into r1
192	add	r4, r0, #1		// calculate argc + 1 into r4
193	add	r2, r1, r4, lsl #2	// get address of env[0] into r2
194	bic	sp, sp, #7		// force eight-byte alignment
195#if OLD_LIBSYSTEM_SUPPORT
196	bl	__start
197	.long	0xe1200070		// should never return
198#else
199	mov	r3, r2
200Lapple:
201	ldr	r4, [r3], #4		// look for NULL ending env[] array
202	cmp	r4, #0
203	bne	Lapple
204					// "apple" param now in r3
205#if __STATIC__
206	bl	_main
207	b	_exit
208#else
209// use -mlong-branch style call sites so that main executable can be >32MB
210	ldr	ip, L4
211L2:	add	ip, pc, ip
212	ldr	ip, [ip, #0]
213#if __ARM_ARCH_4T__
214	mov lr, pc		// blx not supported, so simulate it in two steps
215	bx  ip
216#else
217	blx	ip			// call main()
218#endif
219
220	ldr	ip, L5
221L3:	add	ip, pc, ip
222	ldr	ip, [ip, #0]
223	bx	ip			// jmp exit()
224
225L4:	.long	L_main$non_lazy_ptr-(L2+8)
226L5:	.long	L_exit$non_lazy_ptr-(L3+8)
227
228	.non_lazy_symbol_pointer
229L_main$non_lazy_ptr:
230	.indirect_symbol _main
231	.long	0
232L_exit$non_lazy_ptr:
233	.indirect_symbol _exit
234	.long	0
235#endif
236
237
238#endif
239#endif /* __arm__ */
240
241// This code has be written to allow dead code stripping
242	.subsections_via_symbols
243