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