2 * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <TargetConditionals.h>
26 #include <System/machine/cpu_capabilities.h>
31 #define MH_PARAM_OUT 0
32 #define LP_PARAM_OUT 4
33 #define XMMM0_SAVE 16 /* 16-byte align */
42 #define STACK_SIZE 100 /* must be 4 mod 16 so that stack winds up 16-byte aliged */
43 #define LP_OLD_BP_SAVE 104
46 * sp+4 lazy binding info offset
47 * sp+0 address of ImageLoader cache
51 .globl dyld_stub_binder
52 .globl _misaligned_stack_error
54 subl $STACK_SIZE,%esp # makes stack 16-byte aligned
55 movl %eax,EAX_SAVE(%esp)
56 movl LP_OLD_BP_SAVE(%esp),%eax # get lazy-pointer meta-parameter
57 movl %eax,LP_LOCAL(%esp)
58 movl %ebp,LP_OLD_BP_SAVE(%esp) # store epb back chain
59 movl %esp,%ebp # set epb to be this frame
60 add $LP_OLD_BP_SAVE,%ebp
61 movl %ecx,ECX_SAVE(%esp)
62 movl %edx,EDX_SAVE(%esp)
64 _misaligned_stack_error_:
65 movdqa %xmm0,XMMM0_SAVE(%esp)
66 movdqa %xmm1,XMMM1_SAVE(%esp)
67 movdqa %xmm2,XMMM2_SAVE(%esp)
68 movdqa %xmm3,XMMM3_SAVE(%esp)
70 movl MH_LOCAL(%esp),%eax # call dyld::fastBindLazySymbol(loadercache, lazyinfo)
71 movl %eax,MH_PARAM_OUT(%esp)
72 movl LP_LOCAL(%esp),%eax
73 movl %eax,LP_PARAM_OUT(%esp)
74 call __Z21_dyld_fast_stub_entryPvl
75 movdqa XMMM0_SAVE(%esp),%xmm0 # restore registers
76 movdqa XMMM1_SAVE(%esp),%xmm1
77 movdqa XMMM2_SAVE(%esp),%xmm2
78 movdqa XMMM3_SAVE(%esp),%xmm3
79 movl ECX_SAVE(%esp),%ecx
80 movl EDX_SAVE(%esp),%edx
81 movl %eax,%ebp # move target address to epb
82 movl EAX_SAVE(%esp),%eax # restore eax
83 addl $STACK_SIZE+4,%esp # cut back stack
84 xchg %ebp, (%esp) # restore ebp and set target to top of stack
93 #define RET_ADDR_RBP 24
94 #define LP_PARAM_RBP 16
95 #define MH_PARAM_RBP 8
98 #define RDI_SAVE_RBP -8
99 #define RSI_SAVE_RBP -16
100 #define RDX_SAVE_RBP -24
101 #define RCX_SAVE_RBP -32
102 #define RBX_SAVE_RBP -40
103 #define RAX_SAVE_RBP -48
104 #define R8_SAVE_RBP -56
105 #define R9_SAVE_RBP -64
106 #define STATIC_STACK_SIZE 256 // extra padding to allow it to be 64-byte aligned
108 #define XMM0_SAVE_RSP 0x00
109 #define XMM1_SAVE_RSP 0x10
110 #define XMM2_SAVE_RSP 0x20
111 #define XMM3_SAVE_RSP 0x30
112 #define XMM4_SAVE_RSP 0x40
113 #define XMM5_SAVE_RSP 0x50
114 #define XMM6_SAVE_RSP 0x60
115 #define XMM7_SAVE_RSP 0x70
119 * sp+16 return address
120 * sp+8 lazy binding info offset
121 * sp+0 address of ImageLoader cache
124 .globl dyld_stub_binder
127 test $0xF,%rsp # at this point stack should be 16-byte aligned
128 jne _stack_not_16_byte_aligned_error
130 subq $STATIC_STACK_SIZE,%rsp
131 movq %rdi,RDI_SAVE_RBP(%rbp) # save registers that might be used as parameters
132 movq %rsi,RSI_SAVE_RBP(%rbp)
133 movq %rdx,RDX_SAVE_RBP(%rbp)
134 movq %rcx,RCX_SAVE_RBP(%rbp)
135 movq %rbx,RBX_SAVE_RBP(%rbp)
136 movq %rax,RAX_SAVE_RBP(%rbp)
137 movq %r8, R8_SAVE_RBP(%rbp)
138 movq %r9, R9_SAVE_RBP(%rbp)
140 cmpl $0, _inited(%rip)
143 cpuid # get cpu features to check on xsave instruction support
144 andl $0x08000000,%ecx # check OSXSAVE bit
145 movl %ecx,_hasXSave(%rip)
148 movl $1, _inited(%rip)
154 cpuid # get xsave parameter info
155 movl %eax,_features_lo32(%rip)
156 movl %edx,_features_hi32(%rip)
157 movl %ecx,_bufferSize32(%rip)
158 movl $1, _inited(%rip)
161 cmpl $0, _hasXSave(%rip)
166 movdqa %xmm0, XMM0_SAVE_RSP(%rsp)
167 movdqa %xmm1, XMM1_SAVE_RSP(%rsp)
168 movdqa %xmm2, XMM2_SAVE_RSP(%rsp)
169 movdqa %xmm3, XMM3_SAVE_RSP(%rsp)
170 movdqa %xmm4, XMM4_SAVE_RSP(%rsp)
171 movdqa %xmm5, XMM5_SAVE_RSP(%rsp)
172 movdqa %xmm6, XMM6_SAVE_RSP(%rsp)
173 movdqa %xmm7, XMM7_SAVE_RSP(%rsp)
177 movl _bufferSize32(%rip),%eax
179 subq %rax, %rdi # stack alloc buffer
180 andq $-64, %rdi # 64-byte align stack
182 # xsave requires buffer to be zero'ed out
192 movl _features_lo32(%rip),%eax
193 movl _features_hi32(%rip),%edx
194 # call xsave with buffer on stack and eax:edx flag bits
195 # note: do not use xsaveopt, it assumes you are using the same
196 # buffer as previous xsaves, and this thread is on the same cpu.
200 movq MH_PARAM_RBP(%rbp),%rdi # call fastBindLazySymbol(loadercache, lazyinfo)
201 movq LP_PARAM_RBP(%rbp),%rsi
202 call __Z21_dyld_fast_stub_entryPvl
203 movq %rax,%r11 # copy jump target
205 cmpl $0, _hasXSave(%rip)
208 movdqa XMM0_SAVE_RSP(%rsp),%xmm0
209 movdqa XMM1_SAVE_RSP(%rsp),%xmm1
210 movdqa XMM2_SAVE_RSP(%rsp),%xmm2
211 movdqa XMM3_SAVE_RSP(%rsp),%xmm3
212 movdqa XMM4_SAVE_RSP(%rsp),%xmm4
213 movdqa XMM5_SAVE_RSP(%rsp),%xmm5
214 movdqa XMM6_SAVE_RSP(%rsp),%xmm6
215 movdqa XMM7_SAVE_RSP(%rsp),%xmm7
219 movl _features_lo32(%rip),%eax
220 movl _features_hi32(%rip),%edx
221 # call xsave with buffer on stack and eax:edx flag bits
225 movq RDI_SAVE_RBP(%rbp),%rdi
226 movq RSI_SAVE_RBP(%rbp),%rsi
227 movq RDX_SAVE_RBP(%rbp),%rdx
228 movq RCX_SAVE_RBP(%rbp),%rcx
229 movq RBX_SAVE_RBP(%rbp),%rbx
230 movq RAX_SAVE_RBP(%rbp),%rax
231 movq R8_SAVE_RBP(%rbp),%r8
232 movq R9_SAVE_RBP(%rbp),%r9
235 addq $16,%rsp # remove meta-parameters
236 jmp *%r11 # jmp to target
238 _stack_not_16_byte_aligned_error:
239 movdqa %xmm0, 0(%rsp)
243 # Cached info from cpuid. These must be lazily evaluated.
244 # You cannot initalize these from _dyld_initializer() because
245 # that function is called from another dylib...
247 _features_lo32: .long 0
248 _features_hi32: .long 0
249 _bufferSize32: .long 0
257 * sp+4 lazy binding info offset
258 * sp+0 address of ImageLoader cache
263 .globl dyld_stub_binder
265 stmfd sp!, {r0,r1,r2,r3,r7,lr} // save registers
266 add r7, sp, #16 // point FP to previous FP
268 ldr r0, [sp, #24] // move address ImageLoader cache to 1st parameter
269 ldr r1, [sp, #28] // move lazy info offset 2nd parameter
272 vpush {d0, d1, d2, d3, d4, d5, d6, d7}
273 sub sp, sp, #8 // Align stack to 16 bytes.
275 // call dyld::fastBindLazySymbol(loadercache, lazyinfo)
276 bl __Z21_dyld_fast_stub_entryPvl
277 mov ip, r0 // move the symbol`s address into ip
281 vpop {d0, d1, d2, d3, d4, d5, d6, d7}
284 ldmfd sp!, {r0,r1,r2,r3,r7,lr} // restore registers
285 add sp, sp, #8 // remove meta-parameters
287 bx ip // jump to the symbol`s address that was bound
294 * sp+0 lazy binding info offset
295 * sp+8 address of ImageLoader cache
299 .globl dyld_stub_binder
301 stp fp, lr, [sp, #-16]!
304 stp x0,x1, [fp, #-16] ; x0-x7 are int parameter registers
305 stp x2,x3, [fp, #-32]
306 stp x4,x5, [fp, #-48]
307 stp x6,x7, [fp, #-64]
308 stp x8,x9, [fp, #-80] ; x8 is used for struct returns
309 stp q0,q1, [fp, #-128] ; q0-q7 are vector/fp parameter registers
310 stp q2,q3, [fp, #-160]
311 stp q4,q5, [fp, #-192]
312 stp q6,q7, [fp, #-224]
314 ldr x0, [fp, #24] ; move address ImageLoader cache to 1st parameter
315 ldr x1, [fp, #16] ; move lazy info offset 2nd parameter
316 ; call dyld::fastBindLazySymbol(loadercache, lazyinfo)
317 bl __Z21_dyld_fast_stub_entryPvl
318 mov x16,x0 ; save target function address in lr
320 ; restore parameter registers
321 ldp x0,x1, [fp, #-16]
322 ldp x2,x3, [fp, #-32]
323 ldp x4,x5, [fp, #-48]
324 ldp x6,x7, [fp, #-64]
325 ldp x8,x9, [fp, #-80]
326 ldp q0,q1, [fp, #-128]
327 ldp q2,q3, [fp, #-160]
328 ldp q4,q5, [fp, #-192]
329 ldp q6,q7, [fp, #-224]
332 ldp fp, lr, [sp], #16
333 add sp, sp, #16 ; remove meta-parameters