]>
Commit | Line | Data |
---|---|---|
b3962a83 A |
1 | /* |
2 | * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
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 | |
11 | * file. | |
12 | * | |
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. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
7af964d1 | 23 | |
8070259c | 24 | #include <TargetConditionals.h> |
c1e772c4 | 25 | #if __x86_64__ && !TARGET_OS_SIMULATOR |
7af964d1 | 26 | |
b3962a83 A |
27 | /******************************************************************** |
28 | ******************************************************************** | |
29 | ** | |
30 | ** objc-msg-x86_64.s - x86-64 code to support objc messaging. | |
31 | ** | |
32 | ******************************************************************** | |
33 | ********************************************************************/ | |
34 | ||
b3962a83 | 35 | .data |
b3962a83 A |
36 | |
37 | // _objc_entryPoints and _objc_exitPoints are used by objc | |
38 | // to get the critical regions for which method caches | |
39 | // cannot be garbage collected. | |
40 | ||
31875a97 | 41 | .align 4 |
8972963c | 42 | .private_extern _objc_entryPoints |
b3962a83 | 43 | _objc_entryPoints: |
7257e56c | 44 | .quad _cache_getImp |
b3962a83 A |
45 | .quad _objc_msgSend |
46 | .quad _objc_msgSend_fpret | |
47 | .quad _objc_msgSend_fp2ret | |
48 | .quad _objc_msgSend_stret | |
49 | .quad _objc_msgSendSuper | |
50 | .quad _objc_msgSendSuper_stret | |
8972963c A |
51 | .quad _objc_msgSendSuper2 |
52 | .quad _objc_msgSendSuper2_stret | |
c1e772c4 A |
53 | .quad _objc_msgLookup |
54 | .quad _objc_msgLookup_fpret | |
55 | .quad _objc_msgLookup_fp2ret | |
56 | .quad _objc_msgLookup_stret | |
57 | .quad _objc_msgLookupSuper2 | |
58 | .quad _objc_msgLookupSuper2_stret | |
b3962a83 A |
59 | .quad 0 |
60 | ||
8972963c | 61 | .private_extern _objc_exitPoints |
b3962a83 | 62 | _objc_exitPoints: |
7257e56c | 63 | .quad LExit_cache_getImp |
8972963c A |
64 | .quad LExit_objc_msgSend |
65 | .quad LExit_objc_msgSend_fpret | |
66 | .quad LExit_objc_msgSend_fp2ret | |
67 | .quad LExit_objc_msgSend_stret | |
68 | .quad LExit_objc_msgSendSuper | |
69 | .quad LExit_objc_msgSendSuper_stret | |
70 | .quad LExit_objc_msgSendSuper2 | |
71 | .quad LExit_objc_msgSendSuper2_stret | |
c1e772c4 A |
72 | .quad LExit_objc_msgLookup |
73 | .quad LExit_objc_msgLookup_fpret | |
74 | .quad LExit_objc_msgLookup_fp2ret | |
75 | .quad LExit_objc_msgLookup_stret | |
76 | .quad LExit_objc_msgLookupSuper2 | |
77 | .quad LExit_objc_msgLookupSuper2_stret | |
b3962a83 A |
78 | .quad 0 |
79 | ||
80 | ||
7257e56c A |
81 | /******************************************************************** |
82 | * List every exit insn from every messenger for debugger use. | |
83 | * Format: | |
84 | * ( | |
85 | * 1 word instruction's address | |
86 | * 1 word type (ENTER or FAST_EXIT or SLOW_EXIT or NIL_EXIT) | |
87 | * ) | |
88 | * 1 word zero | |
89 | * | |
90 | * ENTER is the start of a dispatcher | |
91 | * FAST_EXIT is method dispatch | |
92 | * SLOW_EXIT is uncached method lookup | |
93 | * NIL_EXIT is returning zero from a message sent to nil | |
94 | * These must match objc-gdb.h. | |
95 | ********************************************************************/ | |
96 | ||
97 | #define ENTER 1 | |
98 | #define FAST_EXIT 2 | |
99 | #define SLOW_EXIT 3 | |
100 | #define NIL_EXIT 4 | |
101 | ||
102 | .section __DATA,__objc_msg_break | |
103 | .globl _gdb_objc_messenger_breakpoints | |
104 | _gdb_objc_messenger_breakpoints: | |
105 | // contents populated by the macros below | |
106 | ||
107 | .macro MESSENGER_START | |
108 | 4: | |
109 | .section __DATA,__objc_msg_break | |
110 | .quad 4b | |
111 | .quad ENTER | |
112 | .text | |
113 | .endmacro | |
114 | .macro MESSENGER_END_FAST | |
115 | 4: | |
116 | .section __DATA,__objc_msg_break | |
117 | .quad 4b | |
118 | .quad FAST_EXIT | |
119 | .text | |
120 | .endmacro | |
121 | .macro MESSENGER_END_SLOW | |
122 | 4: | |
123 | .section __DATA,__objc_msg_break | |
124 | .quad 4b | |
125 | .quad SLOW_EXIT | |
126 | .text | |
127 | .endmacro | |
128 | .macro MESSENGER_END_NIL | |
129 | 4: | |
130 | .section __DATA,__objc_msg_break | |
131 | .quad 4b | |
132 | .quad NIL_EXIT | |
133 | .text | |
134 | .endmacro | |
135 | ||
136 | ||
b3962a83 | 137 | /******************************************************************** |
8972963c A |
138 | * Recommended multi-byte NOP instructions |
139 | * (Intel 64 and IA-32 Architectures Software Developer's Manual Volume 2B) | |
140 | ********************************************************************/ | |
141 | #define nop1 .byte 0x90 | |
142 | #define nop2 .byte 0x66,0x90 | |
143 | #define nop3 .byte 0x0F,0x1F,0x00 | |
144 | #define nop4 .byte 0x0F,0x1F,0x40,0x00 | |
145 | #define nop5 .byte 0x0F,0x1F,0x44,0x00,0x00 | |
146 | #define nop6 .byte 0x66,0x0F,0x1F,0x44,0x00,0x00 | |
147 | #define nop7 .byte 0x0F,0x1F,0x80,0x00,0x00,0x00,0x00 | |
148 | #define nop8 .byte 0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00 | |
149 | #define nop9 .byte 0x66,0x0F,0x1F,0x84,0x00,0x00,0x00,0x00,0x00 | |
150 | ||
151 | ||
7257e56c A |
152 | /******************************************************************** |
153 | * Harmless branch prefix hint for instruction alignment | |
154 | ********************************************************************/ | |
155 | ||
156 | #define PN .byte 0x2e | |
157 | ||
158 | ||
8972963c | 159 | /******************************************************************** |
b3962a83 | 160 | * Names for parameter registers. |
b3962a83 A |
161 | ********************************************************************/ |
162 | ||
8972963c A |
163 | #define a1 rdi |
164 | #define a1d edi | |
165 | #define a1b dil | |
166 | #define a2 rsi | |
167 | #define a2d esi | |
168 | #define a2b sil | |
169 | #define a3 rdx | |
170 | #define a3d edx | |
171 | #define a4 rcx | |
172 | #define a4d ecx | |
173 | #define a5 r8 | |
174 | #define a5d r8d | |
175 | #define a6 r9 | |
b3962a83 A |
176 | #define a6d r9d |
177 | ||
178 | ||
8972963c A |
179 | /******************************************************************** |
180 | * Names for relative labels | |
181 | * DO NOT USE THESE LABELS ELSEWHERE | |
8070259c | 182 | * Reserved labels: 6: 7: 8: 9: |
8972963c | 183 | ********************************************************************/ |
8070259c A |
184 | #define LCacheMiss 6 |
185 | #define LCacheMiss_f 6f | |
186 | #define LCacheMiss_b 6b | |
8972963c A |
187 | #define LNilTestSlow 7 |
188 | #define LNilTestSlow_f 7f | |
189 | #define LNilTestSlow_b 7b | |
190 | #define LGetIsaDone 8 | |
191 | #define LGetIsaDone_f 8f | |
192 | #define LGetIsaDone_b 8b | |
193 | #define LGetIsaSlow 9 | |
194 | #define LGetIsaSlow_f 9f | |
195 | #define LGetIsaSlow_b 9b | |
196 | ||
197 | /******************************************************************** | |
198 | * Macro parameters | |
199 | ********************************************************************/ | |
200 | ||
8972963c A |
201 | #define NORMAL 0 |
202 | #define FPRET 1 | |
203 | #define FP2RET 2 | |
c1e772c4 A |
204 | #define STRET 3 |
205 | ||
206 | #define CALL 100 | |
207 | #define GETIMP 101 | |
208 | #define LOOKUP 102 | |
209 | ||
8972963c | 210 | |
b3962a83 A |
211 | /******************************************************************** |
212 | * | |
213 | * Structure definitions. | |
214 | * | |
215 | ********************************************************************/ | |
216 | ||
217 | // objc_super parameter to sendSuper | |
8972963c A |
218 | #define receiver 0 |
219 | #define class 8 | |
b3962a83 A |
220 | |
221 | // Selected field offsets in class structure | |
8972963c | 222 | // #define isa 0 USE GetIsa INSTEAD |
b3962a83 A |
223 | |
224 | // Method descriptor | |
8972963c A |
225 | #define method_name 0 |
226 | #define method_imp 16 | |
b3962a83 | 227 | |
b3962a83 | 228 | |
b3962a83 A |
229 | ////////////////////////////////////////////////////////////////////// |
230 | // | |
231 | // ENTRY functionName | |
232 | // | |
233 | // Assembly directives to begin an exported function. | |
234 | // | |
235 | // Takes: functionName - name of the exported function | |
236 | ////////////////////////////////////////////////////////////////////// | |
237 | ||
238 | .macro ENTRY | |
239 | .text | |
240 | .globl $0 | |
8972963c A |
241 | .align 6, 0x90 |
242 | $0: | |
243 | .endmacro | |
244 | ||
245 | .macro STATIC_ENTRY | |
246 | .text | |
247 | .private_extern $0 | |
b3962a83 A |
248 | .align 2, 0x90 |
249 | $0: | |
250 | .endmacro | |
251 | ||
252 | ////////////////////////////////////////////////////////////////////// | |
253 | // | |
254 | // END_ENTRY functionName | |
255 | // | |
256 | // Assembly directives to end an exported function. Just a placeholder, | |
257 | // a close-parenthesis for ENTRY, until it is needed for something. | |
258 | // | |
259 | // Takes: functionName - name of the exported function | |
260 | ////////////////////////////////////////////////////////////////////// | |
261 | ||
262 | .macro END_ENTRY | |
8070259c | 263 | LExit$0: |
b3962a83 A |
264 | .endmacro |
265 | ||
266 | ||
c1e772c4 A |
267 | /******************************************************************** |
268 | * UNWIND name, flags | |
269 | * Unwind info generation | |
270 | ********************************************************************/ | |
271 | .macro UNWIND | |
272 | .section __LD,__compact_unwind,regular,debug | |
273 | .quad $0 | |
274 | .set LUnwind$0, LExit$0 - $0 | |
275 | .long LUnwind$0 | |
276 | .long $1 | |
277 | .quad 0 /* no personality */ | |
278 | .quad 0 /* no LSDA */ | |
279 | .text | |
b3962a83 A |
280 | .endmacro |
281 | ||
c1e772c4 A |
282 | #define NoFrame 0x02010000 // no frame, no SP adjustment except return address |
283 | #define FrameWithNoSaves 0x01000000 // frame, no non-volatile saves | |
b3962a83 A |
284 | |
285 | ||
286 | ///////////////////////////////////////////////////////////////////// | |
287 | // | |
cd5f04f5 | 288 | // CacheLookup return-type, caller |
b3962a83 | 289 | // |
7257e56c | 290 | // Locate the implementation for a class in a selector's method cache. |
b3962a83 A |
291 | // |
292 | // Takes: | |
c1e772c4 A |
293 | // $0 = NORMAL, FPRET, FP2RET, STRET |
294 | // $1 = CALL, LOOKUP, GETIMP | |
295 | // a1 or a2 (STRET) = receiver | |
296 | // a2 or a3 (STRET) = selector | |
297 | // r10 = class to search | |
b3962a83 | 298 | // |
7257e56c | 299 | // On exit: r10 clobbered |
c1e772c4 A |
300 | // (found) calls or returns IMP in r11, eq/ne set for forwarding |
301 | // (not found) jumps to LCacheMiss, class still in r10 | |
8972963c | 302 | // |
b3962a83 A |
303 | ///////////////////////////////////////////////////////////////////// |
304 | ||
7257e56c | 305 | .macro CacheHit |
b3962a83 | 306 | |
7257e56c A |
307 | // CacheHit must always be preceded by a not-taken `jne` instruction |
308 | // in order to set the correct flags for _objc_msgForward_impcache. | |
309 | ||
c1e772c4 | 310 | // r11 = found bucket |
cd5f04f5 | 311 | |
c1e772c4 A |
312 | .if $1 == GETIMP |
313 | movq 8(%r11), %rax // return imp | |
314 | ret | |
315 | ||
316 | .else | |
317 | ||
318 | .if $0 != STRET | |
7257e56c | 319 | // eq already set for forwarding by `jne` |
c1e772c4 A |
320 | .else |
321 | test %r11, %r11 // set ne for stret forwarding | |
322 | .endif | |
323 | ||
324 | .if $1 == CALL | |
7257e56c | 325 | MESSENGER_END_FAST |
c1e772c4 | 326 | jmp *8(%r11) // call imp |
7257e56c | 327 | |
c1e772c4 A |
328 | .elseif $1 == LOOKUP |
329 | movq 8(%r11), %r11 // return imp | |
330 | ret | |
7257e56c | 331 | |
8972963c | 332 | .else |
7257e56c | 333 | .abort oops |
8972963c | 334 | .endif |
c1e772c4 A |
335 | |
336 | .endif | |
337 | ||
7257e56c A |
338 | .endmacro |
339 | ||
8070259c | 340 | |
7257e56c | 341 | .macro CacheLookup |
c1e772c4 A |
342 | .if $0 != STRET |
343 | movq %a2, %r11 // r11 = _cmd | |
7257e56c | 344 | .else |
c1e772c4 | 345 | movq %a3, %r11 // r11 = _cmd |
7257e56c | 346 | .endif |
c1e772c4 A |
347 | andl 24(%r10), %r11d // r11 = _cmd & class->cache.mask |
348 | shlq $$4, %r11 // r11 = offset = (_cmd & mask)<<4 | |
349 | addq 16(%r10), %r11 // r11 = class->cache.buckets + offset | |
7257e56c | 350 | |
c1e772c4 A |
351 | .if $0 != STRET |
352 | cmpq (%r11), %a2 // if (bucket->sel != _cmd) | |
7257e56c | 353 | .else |
c1e772c4 | 354 | cmpq (%r11), %a3 // if (bucket->sel != _cmd) |
7257e56c A |
355 | .endif |
356 | jne 1f // scan more | |
357 | // CacheHit must always be preceded by a not-taken `jne` instruction | |
c1e772c4 | 358 | CacheHit $0, $1 // call or return imp |
7257e56c | 359 | |
8972963c | 360 | 1: |
7257e56c | 361 | // loop |
c1e772c4 | 362 | cmpq $$1, (%r11) |
31875a97 | 363 | jbe 3f // if (bucket->sel <= 1) wrap or miss |
7257e56c | 364 | |
c1e772c4 | 365 | addq $$16, %r11 // bucket++ |
8070259c | 366 | 2: |
c1e772c4 A |
367 | .if $0 != STRET |
368 | cmpq (%r11), %a2 // if (bucket->sel != _cmd) | |
8972963c | 369 | .else |
c1e772c4 | 370 | cmpq (%r11), %a3 // if (bucket->sel != _cmd) |
8972963c | 371 | .endif |
7257e56c A |
372 | jne 1b // scan more |
373 | // CacheHit must always be preceded by a not-taken `jne` instruction | |
c1e772c4 | 374 | CacheHit $0, $1 // call or return imp |
b3962a83 | 375 | |
7257e56c | 376 | 3: |
31875a97 A |
377 | // wrap or miss |
378 | jb LCacheMiss_f // if (bucket->sel < 1) cache miss | |
7257e56c | 379 | // wrap |
c1e772c4 | 380 | movq 8(%r11), %r11 // bucket->imp is really first bucket |
7257e56c | 381 | jmp 2f |
8972963c | 382 | |
31875a97 A |
383 | // Clone scanning loop to miss instead of hang when cache is corrupt. |
384 | // The slow path may detect any corruption and halt later. | |
7257e56c A |
385 | |
386 | 1: | |
387 | // loop | |
c1e772c4 | 388 | cmpq $$1, (%r11) |
31875a97 | 389 | jbe 3f // if (bucket->sel <= 1) wrap or miss |
7257e56c | 390 | |
c1e772c4 | 391 | addq $$16, %r11 // bucket++ |
7257e56c | 392 | 2: |
c1e772c4 A |
393 | .if $0 != STRET |
394 | cmpq (%r11), %a2 // if (bucket->sel != _cmd) | |
8972963c | 395 | .else |
c1e772c4 | 396 | cmpq (%r11), %a3 // if (bucket->sel != _cmd) |
8972963c | 397 | .endif |
7257e56c A |
398 | jne 1b // scan more |
399 | // CacheHit must always be preceded by a not-taken `jne` instruction | |
c1e772c4 | 400 | CacheHit $0, $1 // call or return imp |
b3962a83 | 401 | |
7257e56c | 402 | 3: |
31875a97 A |
403 | // double wrap or miss |
404 | jmp LCacheMiss_f | |
8070259c | 405 | |
b3962a83 A |
406 | .endmacro |
407 | ||
408 | ||
409 | ///////////////////////////////////////////////////////////////////// | |
410 | // | |
c1e772c4 | 411 | // MethodTableLookup NORMAL|STRET |
b3962a83 | 412 | // |
c1e772c4 A |
413 | // Takes: a1 or a2 (STRET) = receiver |
414 | // a2 or a3 (STRET) = selector to search for | |
415 | // r10 = class to search | |
b3962a83 | 416 | // |
c1e772c4 | 417 | // On exit: imp in %r11, eq/ne set for forwarding |
b3962a83 A |
418 | // |
419 | ///////////////////////////////////////////////////////////////////// | |
c1e772c4 | 420 | |
b3962a83 | 421 | .macro MethodTableLookup |
7257e56c | 422 | |
c1e772c4 A |
423 | push %rbp |
424 | mov %rsp, %rbp | |
cd5f04f5 | 425 | |
c1e772c4 A |
426 | sub $$0x80+8, %rsp // +8 for alignment |
427 | ||
428 | movdqa %xmm0, -0x80(%rbp) | |
429 | push %rax // might be xmm parameter count | |
430 | movdqa %xmm1, -0x70(%rbp) | |
431 | push %a1 | |
432 | movdqa %xmm2, -0x60(%rbp) | |
433 | push %a2 | |
434 | movdqa %xmm3, -0x50(%rbp) | |
435 | push %a3 | |
436 | movdqa %xmm4, -0x40(%rbp) | |
437 | push %a4 | |
438 | movdqa %xmm5, -0x30(%rbp) | |
439 | push %a5 | |
440 | movdqa %xmm6, -0x20(%rbp) | |
441 | push %a6 | |
442 | movdqa %xmm7, -0x10(%rbp) | |
b3962a83 | 443 | |
8972963c | 444 | // _class_lookupMethodAndLoadCache3(receiver, selector, class) |
b3962a83 | 445 | |
c1e772c4 A |
446 | .if $0 == NORMAL |
447 | // receiver already in a1 | |
448 | // selector already in a2 | |
449 | .else | |
450 | movq %a2, %a1 | |
451 | movq %a3, %a2 | |
452 | .endif | |
453 | movq %r10, %a3 | |
8972963c | 454 | call __class_lookupMethodAndLoadCache3 |
b3962a83 A |
455 | |
456 | // IMP is now in %rax | |
457 | movq %rax, %r11 | |
458 | ||
c1e772c4 A |
459 | movdqa -0x80(%rbp), %xmm0 |
460 | pop %a6 | |
461 | movdqa -0x70(%rbp), %xmm1 | |
462 | pop %a5 | |
463 | movdqa -0x60(%rbp), %xmm2 | |
464 | pop %a4 | |
465 | movdqa -0x50(%rbp), %xmm3 | |
466 | pop %a3 | |
467 | movdqa -0x40(%rbp), %xmm4 | |
468 | pop %a2 | |
469 | movdqa -0x30(%rbp), %xmm5 | |
470 | pop %a1 | |
471 | movdqa -0x20(%rbp), %xmm6 | |
472 | pop %rax | |
473 | movdqa -0x10(%rbp), %xmm7 | |
474 | ||
475 | .if $0 == NORMAL | |
476 | cmp %r11, %r11 // set eq for nonstret forwarding | |
477 | .else | |
478 | test %r11, %r11 // set ne for stret forwarding | |
479 | .endif | |
480 | ||
481 | leave | |
b3962a83 A |
482 | |
483 | .endmacro | |
484 | ||
c1e772c4 | 485 | |
8972963c A |
486 | ///////////////////////////////////////////////////////////////////// |
487 | // | |
8972963c A |
488 | // GetIsaFast return-type |
489 | // GetIsaSupport return-type | |
490 | // | |
c1e772c4 | 491 | // Sets r10 = obj->isa. Consults the tagged isa table if necessary. |
8972963c A |
492 | // |
493 | // Takes: $0 = NORMAL or FPRET or FP2RET or STRET | |
494 | // a1 or a2 (STRET) = receiver | |
495 | // | |
c1e772c4 A |
496 | // On exit: r10 = receiver->isa |
497 | // r11 is clobbered | |
8972963c A |
498 | // |
499 | ///////////////////////////////////////////////////////////////////// | |
8972963c A |
500 | |
501 | .macro GetIsaFast | |
502 | .if $0 != STRET | |
503 | testb $$1, %a1b | |
7257e56c | 504 | PN |
8972963c | 505 | jnz LGetIsaSlow_f |
c1e772c4 A |
506 | movq $$0x00007ffffffffff8, %r10 |
507 | andq (%a1), %r10 | |
8972963c A |
508 | .else |
509 | testb $$1, %a2b | |
7257e56c | 510 | PN |
8972963c | 511 | jnz LGetIsaSlow_f |
c1e772c4 A |
512 | movq $$0x00007ffffffffff8, %r10 |
513 | andq (%a2), %r10 | |
8972963c A |
514 | .endif |
515 | LGetIsaDone: | |
516 | .endmacro | |
517 | ||
c1e772c4 | 518 | .macro GetIsaSupport |
8972963c | 519 | LGetIsaSlow: |
8972963c | 520 | .if $0 != STRET |
c1e772c4 | 521 | movl %a1d, %r11d |
8972963c | 522 | .else |
c1e772c4 | 523 | movl %a2d, %r11d |
8972963c | 524 | .endif |
c1e772c4 A |
525 | andl $$0xF, %r11d |
526 | cmp $$0xF, %r11d | |
527 | je 1f | |
528 | // basic tagged | |
529 | leaq _objc_debug_taggedpointer_classes(%rip), %r10 | |
530 | movq (%r10, %r11, 8), %r10 // read isa from table | |
531 | jmp LGetIsaDone_b | |
532 | 1: | |
533 | // extended tagged | |
534 | .if $0 != STRET | |
535 | movl %a1d, %r11d | |
536 | .else | |
537 | movl %a2d, %r11d | |
538 | .endif | |
539 | shrl $$4, %r11d | |
540 | andl $$0xFF, %r11d | |
541 | leaq _objc_debug_taggedpointer_ext_classes(%rip), %r10 | |
542 | movq (%r10, %r11, 8), %r10 // read isa from table | |
8972963c | 543 | jmp LGetIsaDone_b |
7257e56c A |
544 | .endmacro |
545 | ||
8972963c A |
546 | |
547 | ///////////////////////////////////////////////////////////////////// | |
548 | // | |
549 | // NilTest return-type | |
550 | // | |
551 | // Takes: $0 = NORMAL or FPRET or FP2RET or STRET | |
552 | // %a1 or %a2 (STRET) = receiver | |
553 | // | |
c1e772c4 A |
554 | // On exit: Loads non-nil receiver in %a1 or %a2 (STRET) |
555 | // or returns. | |
8972963c | 556 | // |
c1e772c4 | 557 | // NilTestReturnZero return-type |
8972963c A |
558 | // |
559 | // Takes: $0 = NORMAL or FPRET or FP2RET or STRET | |
560 | // %a1 or %a2 (STRET) = receiver | |
561 | // | |
c1e772c4 A |
562 | // On exit: Loads non-nil receiver in %a1 or %a2 (STRET) |
563 | // or returns zero. | |
564 | // | |
565 | // NilTestReturnIMP return-type | |
566 | // | |
567 | // Takes: $0 = NORMAL or FPRET or FP2RET or STRET | |
568 | // %a1 or %a2 (STRET) = receiver | |
569 | // | |
570 | // On exit: Loads non-nil receiver in %a1 or %a2 (STRET) | |
571 | // or returns an IMP in r11 that returns zero. | |
8972963c A |
572 | // |
573 | ///////////////////////////////////////////////////////////////////// | |
574 | ||
c1e772c4 A |
575 | .macro ZeroReturn |
576 | xorl %eax, %eax | |
577 | xorl %edx, %edx | |
578 | xorps %xmm0, %xmm0 | |
579 | xorps %xmm1, %xmm1 | |
580 | .endmacro | |
581 | ||
582 | .macro ZeroReturnFPRET | |
583 | fldz | |
584 | ZeroReturn | |
585 | .endmacro | |
7257e56c | 586 | |
c1e772c4 A |
587 | .macro ZeroReturnFP2RET |
588 | fldz | |
589 | fldz | |
590 | ZeroReturn | |
591 | .endmacro | |
592 | ||
593 | .macro ZeroReturnSTRET | |
594 | // rax gets the struct-return address as passed in rdi | |
595 | movq %rdi, %rax | |
596 | .endmacro | |
597 | ||
598 | STATIC_ENTRY __objc_msgNil | |
599 | ZeroReturn | |
600 | ret | |
601 | END_ENTRY __objc_msgNil | |
602 | ||
603 | STATIC_ENTRY __objc_msgNil_fpret | |
604 | ZeroReturnFPRET | |
605 | ret | |
606 | END_ENTRY __objc_msgNil_fpret | |
607 | ||
608 | STATIC_ENTRY __objc_msgNil_fp2ret | |
609 | ZeroReturnFP2RET | |
610 | ret | |
611 | END_ENTRY __objc_msgNil_fp2ret | |
612 | ||
613 | STATIC_ENTRY __objc_msgNil_stret | |
614 | ZeroReturnSTRET | |
615 | ret | |
616 | END_ENTRY __objc_msgNil_stret | |
617 | ||
618 | ||
619 | .macro NilTest | |
8972963c A |
620 | .if $0 != STRET |
621 | testq %a1, %a1 | |
622 | .else | |
623 | testq %a2, %a2 | |
624 | .endif | |
7257e56c | 625 | PN |
8972963c | 626 | jz LNilTestSlow_f |
8972963c A |
627 | .endmacro |
628 | ||
c1e772c4 A |
629 | |
630 | .macro NilTestReturnZero | |
8972963c A |
631 | .align 3 |
632 | LNilTestSlow: | |
c1e772c4 A |
633 | |
634 | .if $0 == NORMAL | |
635 | ZeroReturn | |
636 | .elseif $0 == FPRET | |
637 | ZeroReturnFPRET | |
8972963c | 638 | .elseif $0 == FP2RET |
c1e772c4 A |
639 | ZeroReturnFP2RET |
640 | .elseif $0 == STRET | |
641 | ZeroReturnSTRET | |
7257e56c | 642 | .else |
c1e772c4 | 643 | .abort oops |
8972963c | 644 | .endif |
7257e56c | 645 | MESSENGER_END_NIL |
c1e772c4 A |
646 | ret |
647 | .endmacro | |
648 | ||
649 | ||
650 | .macro NilTestReturnIMP | |
651 | .align 3 | |
652 | LNilTestSlow: | |
653 | ||
654 | .if $0 == NORMAL | |
655 | leaq __objc_msgNil(%rip), %r11 | |
656 | .elseif $0 == FPRET | |
657 | leaq __objc_msgNil_fpret(%rip), %r11 | |
658 | .elseif $0 == FP2RET | |
659 | leaq __objc_msgNil_fp2ret(%rip), %r11 | |
660 | .elseif $0 == STRET | |
661 | leaq __objc_msgNil_stret(%rip), %r11 | |
662 | .else | |
663 | .abort oops | |
664 | .endif | |
8972963c A |
665 | ret |
666 | .endmacro | |
b3962a83 A |
667 | |
668 | ||
669 | /******************************************************************** | |
7257e56c | 670 | * IMP cache_getImp(Class cls, SEL sel) |
b3962a83 A |
671 | * |
672 | * On entry: a1 = class whose cache is to be searched | |
673 | * a2 = selector to search for | |
674 | * | |
675 | * If found, returns method implementation. | |
676 | * If not found, returns NULL. | |
677 | ********************************************************************/ | |
678 | ||
7257e56c | 679 | STATIC_ENTRY _cache_getImp |
b3962a83 A |
680 | |
681 | // do lookup | |
c1e772c4 A |
682 | movq %a1, %r10 // move class to r10 for CacheLookup |
683 | CacheLookup NORMAL, GETIMP // returns IMP on success | |
b3962a83 | 684 | |
8972963c | 685 | LCacheMiss: |
b3962a83 | 686 | // cache miss, return nil |
8972963c | 687 | xorl %eax, %eax |
b3962a83 A |
688 | ret |
689 | ||
c1e772c4 | 690 | END_ENTRY _cache_getImp |
b3962a83 A |
691 | |
692 | ||
693 | /******************************************************************** | |
694 | * | |
695 | * id objc_msgSend(id self, SEL _cmd,...); | |
c1e772c4 A |
696 | * IMP objc_msgLookup(id self, SEL _cmd, ...); |
697 | * | |
698 | * objc_msgLookup ABI: | |
699 | * IMP returned in r11 | |
700 | * Forwarding returned in Z flag | |
701 | * r10 reserved for our use but not used | |
b3962a83 A |
702 | * |
703 | ********************************************************************/ | |
704 | ||
8972963c A |
705 | .data |
706 | .align 3 | |
7257e56c A |
707 | .globl _objc_debug_taggedpointer_classes |
708 | _objc_debug_taggedpointer_classes: | |
8972963c | 709 | .fill 16, 8, 0 |
c1e772c4 A |
710 | .globl _objc_debug_taggedpointer_ext_classes |
711 | _objc_debug_taggedpointer_ext_classes: | |
712 | .fill 256, 8, 0 | |
8972963c | 713 | |
c1e772c4 A |
714 | ENTRY _objc_msgSend |
715 | UNWIND _objc_msgSend, NoFrame | |
7257e56c | 716 | MESSENGER_START |
b3962a83 | 717 | |
8972963c | 718 | NilTest NORMAL |
b3962a83 | 719 | |
c1e772c4 A |
720 | GetIsaFast NORMAL // r10 = self->isa |
721 | CacheLookup NORMAL, CALL // calls IMP on success | |
b3962a83 | 722 | |
c1e772c4 | 723 | NilTestReturnZero NORMAL |
b3962a83 | 724 | |
c1e772c4 | 725 | GetIsaSupport NORMAL |
b3962a83 | 726 | |
8972963c A |
727 | // cache miss: go search the method lists |
728 | LCacheMiss: | |
c1e772c4 A |
729 | // isa still in r10 |
730 | MESSENGER_END_SLOW | |
731 | jmp __objc_msgSend_uncached | |
b3962a83 | 732 | |
c1e772c4 A |
733 | END_ENTRY _objc_msgSend |
734 | ||
735 | ||
736 | ENTRY _objc_msgLookup | |
737 | ||
738 | NilTest NORMAL | |
739 | ||
740 | GetIsaFast NORMAL // r10 = self->isa | |
741 | CacheLookup NORMAL, LOOKUP // returns IMP on success | |
742 | ||
743 | NilTestReturnIMP NORMAL | |
744 | ||
745 | GetIsaSupport NORMAL | |
746 | ||
747 | // cache miss: go search the method lists | |
748 | LCacheMiss: | |
749 | // isa still in r10 | |
750 | jmp __objc_msgLookup_uncached | |
751 | ||
752 | END_ENTRY _objc_msgLookup | |
b3962a83 | 753 | |
8972963c | 754 | |
7257e56c A |
755 | ENTRY _objc_msgSend_fixup |
756 | int3 | |
757 | END_ENTRY _objc_msgSend_fixup | |
b3962a83 | 758 | |
b3962a83 | 759 | |
8972963c | 760 | STATIC_ENTRY _objc_msgSend_fixedup |
b3962a83 A |
761 | // Load _cmd from the message_ref |
762 | movq 8(%a2), %a2 | |
763 | jmp _objc_msgSend | |
764 | END_ENTRY _objc_msgSend_fixedup | |
b3962a83 A |
765 | |
766 | ||
767 | /******************************************************************** | |
768 | * | |
769 | * id objc_msgSendSuper(struct objc_super *super, SEL _cmd,...); | |
770 | * | |
771 | * struct objc_super { | |
772 | * id receiver; | |
773 | * Class class; | |
774 | * }; | |
775 | ********************************************************************/ | |
776 | ||
c1e772c4 A |
777 | ENTRY _objc_msgSendSuper |
778 | UNWIND _objc_msgSendSuper, NoFrame | |
7257e56c A |
779 | MESSENGER_START |
780 | ||
b3962a83 | 781 | // search the cache (objc_super in %a1) |
c1e772c4 A |
782 | movq class(%a1), %r10 // class = objc_super->class |
783 | movq receiver(%a1), %a1 // load real receiver | |
784 | CacheLookup NORMAL, CALL // calls IMP on success | |
b3962a83 A |
785 | |
786 | // cache miss: go search the method lists | |
8972963c | 787 | LCacheMiss: |
c1e772c4 A |
788 | // class still in r10 |
789 | MESSENGER_END_SLOW | |
790 | jmp __objc_msgSend_uncached | |
b3962a83 | 791 | |
c1e772c4 | 792 | END_ENTRY _objc_msgSendSuper |
b3962a83 | 793 | |
8972963c A |
794 | |
795 | /******************************************************************** | |
796 | * id objc_msgSendSuper2 | |
797 | ********************************************************************/ | |
798 | ||
7af964d1 | 799 | ENTRY _objc_msgSendSuper2 |
c1e772c4 | 800 | UNWIND _objc_msgSendSuper2, NoFrame |
7257e56c A |
801 | MESSENGER_START |
802 | ||
7af964d1 | 803 | // objc_super->class is superclass of class to search |
8972963c A |
804 | |
805 | // search the cache (objc_super in %a1) | |
c1e772c4 A |
806 | movq class(%a1), %r10 // cls = objc_super->class |
807 | movq receiver(%a1), %a1 // load real receiver | |
808 | movq 8(%r10), %r10 // cls = class->superclass | |
809 | CacheLookup NORMAL, CALL // calls IMP on success | |
8972963c A |
810 | |
811 | // cache miss: go search the method lists | |
812 | LCacheMiss: | |
c1e772c4 A |
813 | // superclass still in r10 |
814 | MESSENGER_END_SLOW | |
815 | jmp __objc_msgSend_uncached | |
816 | ||
817 | END_ENTRY _objc_msgSendSuper2 | |
818 | ||
819 | ||
820 | ENTRY _objc_msgLookupSuper2 | |
821 | ||
822 | // objc_super->class is superclass of class to search | |
8972963c | 823 | |
c1e772c4 A |
824 | // search the cache (objc_super in %a1) |
825 | movq class(%a1), %r10 // cls = objc_super->class | |
826 | movq receiver(%a1), %a1 // load real receiver | |
827 | movq 8(%r10), %r10 // cls = class->superclass | |
828 | CacheLookup NORMAL, LOOKUP // returns IMP on success | |
7257e56c | 829 | |
c1e772c4 A |
830 | // cache miss: go search the method lists |
831 | LCacheMiss: | |
832 | // superclass still in r10 | |
833 | jmp __objc_msgLookup_uncached | |
7257e56c | 834 | |
c1e772c4 A |
835 | END_ENTRY _objc_msgLookupSuper2 |
836 | ||
837 | ||
7257e56c A |
838 | ENTRY _objc_msgSendSuper2_fixup |
839 | int3 | |
840 | END_ENTRY _objc_msgSendSuper2_fixup | |
841 | ||
842 | ||
843 | STATIC_ENTRY _objc_msgSendSuper2_fixedup | |
844 | // Load _cmd from the message_ref | |
845 | movq 8(%a2), %a2 | |
846 | jmp _objc_msgSendSuper2 | |
847 | END_ENTRY _objc_msgSendSuper2_fixedup | |
b3962a83 A |
848 | |
849 | ||
850 | /******************************************************************** | |
851 | * | |
852 | * double objc_msgSend_fpret(id self, SEL _cmd,...); | |
853 | * Used for `long double` return only. `float` and `double` use objc_msgSend. | |
854 | * | |
855 | ********************************************************************/ | |
856 | ||
c1e772c4 A |
857 | ENTRY _objc_msgSend_fpret |
858 | UNWIND _objc_msgSend_fpret, NoFrame | |
7257e56c A |
859 | MESSENGER_START |
860 | ||
8972963c | 861 | NilTest FPRET |
b3962a83 | 862 | |
c1e772c4 A |
863 | GetIsaFast FPRET // r10 = self->isa |
864 | CacheLookup FPRET, CALL // calls IMP on success | |
b3962a83 | 865 | |
c1e772c4 | 866 | NilTestReturnZero FPRET |
b3962a83 | 867 | |
c1e772c4 | 868 | GetIsaSupport FPRET |
b3962a83 | 869 | |
8972963c A |
870 | // cache miss: go search the method lists |
871 | LCacheMiss: | |
c1e772c4 A |
872 | // isa still in r10 |
873 | MESSENGER_END_SLOW | |
874 | jmp __objc_msgSend_uncached | |
875 | ||
876 | END_ENTRY _objc_msgSend_fpret | |
b3962a83 | 877 | |
c1e772c4 A |
878 | |
879 | ENTRY _objc_msgLookup_fpret | |
880 | ||
881 | NilTest FPRET | |
882 | ||
883 | GetIsaFast FPRET // r10 = self->isa | |
884 | CacheLookup FPRET, LOOKUP // returns IMP on success | |
885 | ||
886 | NilTestReturnIMP FPRET | |
887 | ||
888 | GetIsaSupport FPRET | |
889 | ||
890 | // cache miss: go search the method lists | |
891 | LCacheMiss: | |
892 | // isa still in r10 | |
893 | jmp __objc_msgLookup_uncached | |
894 | ||
895 | END_ENTRY _objc_msgLookup_fpret | |
7257e56c | 896 | |
b3962a83 | 897 | |
b3962a83 | 898 | ENTRY _objc_msgSend_fpret_fixup |
7257e56c A |
899 | int3 |
900 | END_ENTRY _objc_msgSend_fpret_fixup | |
b3962a83 | 901 | |
b3962a83 | 902 | |
8972963c | 903 | STATIC_ENTRY _objc_msgSend_fpret_fixedup |
b3962a83 A |
904 | // Load _cmd from the message_ref |
905 | movq 8(%a2), %a2 | |
906 | jmp _objc_msgSend_fpret | |
907 | END_ENTRY _objc_msgSend_fpret_fixedup | |
b3962a83 A |
908 | |
909 | ||
910 | /******************************************************************** | |
911 | * | |
912 | * double objc_msgSend_fp2ret(id self, SEL _cmd,...); | |
913 | * Used for `complex long double` return only. | |
914 | * | |
915 | ********************************************************************/ | |
916 | ||
c1e772c4 A |
917 | ENTRY _objc_msgSend_fp2ret |
918 | UNWIND _objc_msgSend_fp2ret, NoFrame | |
7257e56c A |
919 | MESSENGER_START |
920 | ||
8972963c | 921 | NilTest FP2RET |
b3962a83 | 922 | |
c1e772c4 A |
923 | GetIsaFast FP2RET // r10 = self->isa |
924 | CacheLookup FP2RET, CALL // calls IMP on success | |
b3962a83 | 925 | |
c1e772c4 | 926 | NilTestReturnZero FP2RET |
8972963c | 927 | |
c1e772c4 | 928 | GetIsaSupport FP2RET |
8972963c | 929 | |
b3962a83 | 930 | // cache miss: go search the method lists |
8972963c | 931 | LCacheMiss: |
c1e772c4 A |
932 | // isa still in r10 |
933 | MESSENGER_END_SLOW | |
934 | jmp __objc_msgSend_uncached | |
935 | ||
936 | END_ENTRY _objc_msgSend_fp2ret | |
937 | ||
938 | ||
939 | ENTRY _objc_msgLookup_fp2ret | |
940 | ||
941 | NilTest FP2RET | |
b3962a83 | 942 | |
c1e772c4 A |
943 | GetIsaFast FP2RET // r10 = self->isa |
944 | CacheLookup FP2RET, LOOKUP // returns IMP on success | |
945 | ||
946 | NilTestReturnIMP FP2RET | |
947 | ||
948 | GetIsaSupport FP2RET | |
949 | ||
950 | // cache miss: go search the method lists | |
951 | LCacheMiss: | |
952 | // isa still in r10 | |
953 | jmp __objc_msgLookup_uncached | |
954 | ||
955 | END_ENTRY _objc_msgLookup_fp2ret | |
b3962a83 | 956 | |
b3962a83 | 957 | |
7257e56c A |
958 | ENTRY _objc_msgSend_fp2ret_fixup |
959 | int3 | |
960 | END_ENTRY _objc_msgSend_fp2ret_fixup | |
b3962a83 | 961 | |
b3962a83 | 962 | |
8972963c | 963 | STATIC_ENTRY _objc_msgSend_fp2ret_fixedup |
b3962a83 A |
964 | // Load _cmd from the message_ref |
965 | movq 8(%a2), %a2 | |
966 | jmp _objc_msgSend_fp2ret | |
967 | END_ENTRY _objc_msgSend_fp2ret_fixedup | |
b3962a83 A |
968 | |
969 | ||
970 | /******************************************************************** | |
971 | * | |
972 | * void objc_msgSend_stret(void *st_addr, id self, SEL _cmd, ...); | |
973 | * | |
974 | * objc_msgSend_stret is the struct-return form of msgSend. | |
975 | * The ABI calls for %a1 to be used as the address of the structure | |
976 | * being returned, with the parameters in the succeeding locations. | |
977 | * | |
978 | * On entry: %a1 is the address where the structure is returned, | |
979 | * %a2 is the message receiver, | |
980 | * %a3 is the selector | |
981 | ********************************************************************/ | |
982 | ||
c1e772c4 A |
983 | ENTRY _objc_msgSend_stret |
984 | UNWIND _objc_msgSend_stret, NoFrame | |
7257e56c A |
985 | MESSENGER_START |
986 | ||
8972963c A |
987 | NilTest STRET |
988 | ||
c1e772c4 A |
989 | GetIsaFast STRET // r10 = self->isa |
990 | CacheLookup STRET, CALL // calls IMP on success | |
8972963c | 991 | |
c1e772c4 | 992 | NilTestReturnZero STRET |
8972963c | 993 | |
c1e772c4 | 994 | GetIsaSupport STRET |
b3962a83 A |
995 | |
996 | // cache miss: go search the method lists | |
8972963c | 997 | LCacheMiss: |
c1e772c4 A |
998 | // isa still in r10 |
999 | MESSENGER_END_SLOW | |
1000 | jmp __objc_msgSend_stret_uncached | |
1001 | ||
1002 | END_ENTRY _objc_msgSend_stret | |
1003 | ||
b3962a83 | 1004 | |
c1e772c4 A |
1005 | ENTRY _objc_msgLookup_stret |
1006 | ||
1007 | NilTest STRET | |
1008 | ||
1009 | GetIsaFast STRET // r10 = self->isa | |
1010 | CacheLookup STRET, LOOKUP // returns IMP on success | |
1011 | ||
1012 | NilTestReturnIMP STRET | |
1013 | ||
1014 | GetIsaSupport STRET | |
1015 | ||
1016 | // cache miss: go search the method lists | |
1017 | LCacheMiss: | |
1018 | // isa still in r10 | |
1019 | jmp __objc_msgLookup_stret_uncached | |
1020 | ||
1021 | END_ENTRY _objc_msgLookup_stret | |
b3962a83 | 1022 | |
b3962a83 | 1023 | |
7257e56c A |
1024 | ENTRY _objc_msgSend_stret_fixup |
1025 | int3 | |
1026 | END_ENTRY _objc_msgSend_stret_fixup | |
b3962a83 A |
1027 | |
1028 | ||
8972963c | 1029 | STATIC_ENTRY _objc_msgSend_stret_fixedup |
b3962a83 A |
1030 | // Load _cmd from the message_ref |
1031 | movq 8(%a3), %a3 | |
1032 | jmp _objc_msgSend_stret | |
1033 | END_ENTRY _objc_msgSend_stret_fixedup | |
b3962a83 A |
1034 | |
1035 | ||
1036 | /******************************************************************** | |
1037 | * | |
1038 | * void objc_msgSendSuper_stret(void *st_addr, struct objc_super *super, SEL _cmd, ...); | |
1039 | * | |
1040 | * struct objc_super { | |
1041 | * id receiver; | |
1042 | * Class class; | |
1043 | * }; | |
1044 | * | |
1045 | * objc_msgSendSuper_stret is the struct-return form of msgSendSuper. | |
1046 | * The ABI calls for (sp+4) to be used as the address of the structure | |
1047 | * being returned, with the parameters in the succeeding registers. | |
1048 | * | |
1049 | * On entry: %a1 is the address where the structure is returned, | |
1050 | * %a2 is the address of the objc_super structure, | |
1051 | * %a3 is the selector | |
1052 | * | |
1053 | ********************************************************************/ | |
1054 | ||
c1e772c4 A |
1055 | ENTRY _objc_msgSendSuper_stret |
1056 | UNWIND _objc_msgSendSuper_stret, NoFrame | |
7257e56c A |
1057 | MESSENGER_START |
1058 | ||
b3962a83 | 1059 | // search the cache (objc_super in %a2) |
c1e772c4 A |
1060 | movq class(%a2), %r10 // class = objc_super->class |
1061 | movq receiver(%a2), %a2 // load real receiver | |
1062 | CacheLookup STRET, CALL // calls IMP on success | |
b3962a83 A |
1063 | |
1064 | // cache miss: go search the method lists | |
8972963c | 1065 | LCacheMiss: |
c1e772c4 A |
1066 | // class still in r10 |
1067 | MESSENGER_END_SLOW | |
1068 | jmp __objc_msgSend_stret_uncached | |
1069 | ||
1070 | END_ENTRY _objc_msgSendSuper_stret | |
b3962a83 | 1071 | |
8972963c A |
1072 | |
1073 | /******************************************************************** | |
1074 | * id objc_msgSendSuper2_stret | |
1075 | ********************************************************************/ | |
1076 | ||
c1e772c4 A |
1077 | ENTRY _objc_msgSendSuper2_stret |
1078 | UNWIND _objc_msgSendSuper2_stret, NoFrame | |
7257e56c A |
1079 | MESSENGER_START |
1080 | ||
8972963c | 1081 | // search the cache (objc_super in %a2) |
c1e772c4 A |
1082 | movq class(%a2), %r10 // class = objc_super->class |
1083 | movq receiver(%a2), %a2 // load real receiver | |
1084 | movq 8(%r10), %r10 // class = class->superclass | |
1085 | CacheLookup STRET, CALL // calls IMP on success | |
8972963c A |
1086 | |
1087 | // cache miss: go search the method lists | |
1088 | LCacheMiss: | |
c1e772c4 A |
1089 | // superclass still in r10 |
1090 | MESSENGER_END_SLOW | |
1091 | jmp __objc_msgSend_stret_uncached | |
1092 | ||
1093 | END_ENTRY _objc_msgSendSuper2_stret | |
1094 | ||
1095 | ||
1096 | ENTRY _objc_msgLookupSuper2_stret | |
1097 | ||
1098 | // search the cache (objc_super in %a2) | |
1099 | movq class(%a2), %r10 // class = objc_super->class | |
8972963c | 1100 | movq receiver(%a2), %a2 // load real receiver |
c1e772c4 A |
1101 | movq 8(%r10), %r10 // class = class->superclass |
1102 | CacheLookup STRET, LOOKUP // returns IMP on success | |
1103 | ||
1104 | // cache miss: go search the method lists | |
1105 | LCacheMiss: | |
1106 | // superclass still in r10 | |
1107 | jmp __objc_msgLookup_stret_uncached | |
8972963c | 1108 | |
c1e772c4 | 1109 | END_ENTRY _objc_msgLookupSuper2_stret |
7257e56c A |
1110 | |
1111 | ||
1112 | ENTRY _objc_msgSendSuper2_stret_fixup | |
1113 | int3 | |
1114 | END_ENTRY _objc_msgSendSuper2_stret_fixup | |
1115 | ||
1116 | ||
1117 | STATIC_ENTRY _objc_msgSendSuper2_stret_fixedup | |
1118 | // Load _cmd from the message_ref | |
1119 | movq 8(%a3), %a3 | |
1120 | jmp _objc_msgSendSuper2_stret | |
1121 | END_ENTRY _objc_msgSendSuper2_stret_fixedup | |
b3962a83 A |
1122 | |
1123 | ||
7257e56c A |
1124 | /******************************************************************** |
1125 | * | |
7257e56c A |
1126 | * _objc_msgSend_uncached |
1127 | * _objc_msgSend_stret_uncached | |
c1e772c4 A |
1128 | * _objc_msgLookup_uncached |
1129 | * _objc_msgLookup_stret_uncached | |
1130 | * | |
1131 | * The uncached method lookup. | |
7257e56c A |
1132 | * |
1133 | ********************************************************************/ | |
7257e56c A |
1134 | |
1135 | STATIC_ENTRY __objc_msgSend_uncached | |
c1e772c4 A |
1136 | UNWIND __objc_msgSend_uncached, FrameWithNoSaves |
1137 | ||
7257e56c | 1138 | // THIS IS NOT A CALLABLE C FUNCTION |
c1e772c4 | 1139 | // Out-of-band r10 is the searched class |
7257e56c | 1140 | |
c1e772c4 A |
1141 | // r10 is already the class to search |
1142 | MethodTableLookup NORMAL // r11 = IMP | |
7257e56c A |
1143 | jmp *%r11 // goto *imp |
1144 | ||
7257e56c A |
1145 | END_ENTRY __objc_msgSend_uncached |
1146 | ||
1147 | ||
1148 | STATIC_ENTRY __objc_msgSend_stret_uncached | |
c1e772c4 A |
1149 | UNWIND __objc_msgSend_stret_uncached, FrameWithNoSaves |
1150 | ||
7257e56c | 1151 | // THIS IS NOT A CALLABLE C FUNCTION |
c1e772c4 | 1152 | // Out-of-band r10 is the searched class |
7257e56c | 1153 | |
c1e772c4 A |
1154 | // r10 is already the class to search |
1155 | MethodTableLookup STRET // r11 = IMP | |
7257e56c A |
1156 | jmp *%r11 // goto *imp |
1157 | ||
7257e56c A |
1158 | END_ENTRY __objc_msgSend_stret_uncached |
1159 | ||
1160 | ||
c1e772c4 A |
1161 | STATIC_ENTRY __objc_msgLookup_uncached |
1162 | UNWIND __objc_msgLookup_uncached, FrameWithNoSaves | |
1163 | ||
1164 | // THIS IS NOT A CALLABLE C FUNCTION | |
1165 | // Out-of-band r10 is the searched class | |
1166 | ||
1167 | // r10 is already the class to search | |
1168 | MethodTableLookup NORMAL // r11 = IMP | |
1169 | ret | |
1170 | ||
1171 | END_ENTRY __objc_msgLookup_uncached | |
1172 | ||
1173 | ||
1174 | STATIC_ENTRY __objc_msgLookup_stret_uncached | |
1175 | UNWIND __objc_msgLookup_stret_uncached, FrameWithNoSaves | |
1176 | ||
1177 | // THIS IS NOT A CALLABLE C FUNCTION | |
1178 | // Out-of-band r10 is the searched class | |
1179 | ||
1180 | // r10 is already the class to search | |
1181 | MethodTableLookup STRET // r11 = IMP | |
1182 | ret | |
1183 | ||
1184 | END_ENTRY __objc_msgLookup_stret_uncached | |
1185 | ||
1186 | ||
b3962a83 | 1187 | /******************************************************************** |
8070259c A |
1188 | * |
1189 | * id _objc_msgForward(id self, SEL _cmd,...); | |
1190 | * | |
1191 | * _objc_msgForward and _objc_msgForward_stret are the externally-callable | |
1192 | * functions returned by things like method_getImplementation(). | |
1193 | * _objc_msgForward_impcache is the function pointer actually stored in | |
1194 | * method caches. | |
1195 | * | |
1196 | ********************************************************************/ | |
b3962a83 | 1197 | |
c1e772c4 | 1198 | STATIC_ENTRY __objc_msgForward_impcache |
7af964d1 A |
1199 | // Method cache version |
1200 | ||
1201 | // THIS IS NOT A CALLABLE C FUNCTION | |
1202 | // Out-of-band condition register is NE for stret, EQ otherwise. | |
b3962a83 | 1203 | |
7257e56c A |
1204 | MESSENGER_START |
1205 | nop | |
1206 | MESSENGER_END_SLOW | |
1207 | ||
7af964d1 A |
1208 | jne __objc_msgForward_stret |
1209 | jmp __objc_msgForward | |
1210 | ||
c1e772c4 | 1211 | END_ENTRY __objc_msgForward_impcache |
7af964d1 A |
1212 | |
1213 | ||
c1e772c4 | 1214 | ENTRY __objc_msgForward |
7af964d1 | 1215 | // Non-stret version |
b3962a83 | 1216 | |
b3962a83 | 1217 | movq __objc_forward_handler(%rip), %r11 |
8070259c | 1218 | jmp *%r11 |
b3962a83 | 1219 | |
c1e772c4 | 1220 | END_ENTRY __objc_msgForward |
b3962a83 A |
1221 | |
1222 | ||
c1e772c4 | 1223 | ENTRY __objc_msgForward_stret |
7af964d1 | 1224 | // Struct-return version |
b3962a83 | 1225 | |
8070259c A |
1226 | movq __objc_forward_stret_handler(%rip), %r11 |
1227 | jmp *%r11 | |
b3962a83 | 1228 | |
c1e772c4 | 1229 | END_ENTRY __objc_msgForward_stret |
b3962a83 A |
1230 | |
1231 | ||
8972963c A |
1232 | ENTRY _objc_msgSend_debug |
1233 | jmp _objc_msgSend | |
1234 | END_ENTRY _objc_msgSend_debug | |
1235 | ||
1236 | ENTRY _objc_msgSendSuper2_debug | |
1237 | jmp _objc_msgSendSuper2 | |
1238 | END_ENTRY _objc_msgSendSuper2_debug | |
1239 | ||
1240 | ENTRY _objc_msgSend_stret_debug | |
1241 | jmp _objc_msgSend_stret | |
1242 | END_ENTRY _objc_msgSend_stret_debug | |
1243 | ||
1244 | ENTRY _objc_msgSendSuper2_stret_debug | |
1245 | jmp _objc_msgSendSuper2_stret | |
1246 | END_ENTRY _objc_msgSendSuper2_stret_debug | |
1247 | ||
1248 | ENTRY _objc_msgSend_fpret_debug | |
1249 | jmp _objc_msgSend_fpret | |
1250 | END_ENTRY _objc_msgSend_fpret_debug | |
1251 | ||
1252 | ENTRY _objc_msgSend_fp2ret_debug | |
1253 | jmp _objc_msgSend_fp2ret | |
1254 | END_ENTRY _objc_msgSend_fp2ret_debug | |
1255 | ||
1256 | ||
1257 | ENTRY _objc_msgSend_noarg | |
1258 | jmp _objc_msgSend | |
1259 | END_ENTRY _objc_msgSend_noarg | |
1260 | ||
1261 | ||
b3962a83 A |
1262 | ENTRY _method_invoke |
1263 | ||
1264 | movq method_imp(%a2), %r11 | |
1265 | movq method_name(%a2), %a2 | |
1266 | jmp *%r11 | |
1267 | ||
1268 | END_ENTRY _method_invoke | |
1269 | ||
1270 | ||
1271 | ENTRY _method_invoke_stret | |
1272 | ||
1273 | movq method_imp(%a3), %r11 | |
1274 | movq method_name(%a3), %a3 | |
1275 | jmp *%r11 | |
1276 | ||
1277 | END_ENTRY _method_invoke_stret | |
7af964d1 | 1278 | |
8972963c | 1279 | |
7257e56c A |
1280 | .section __DATA,__objc_msg_break |
1281 | .quad 0 | |
1282 | .quad 0 | |
7af964d1 A |
1283 | |
1284 | #endif |