|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, 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.0 (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: #ifdef KERNEL ! 25: #define OBJC_LOCK_ROUTINE _simple_lock ! 26: #else ! 27: #ifdef DYLIB ! 28: #define OBJC_LOCK_ROUTINE _spin_lock$non_lazy_ptr ! 29: #else ! 30: #define OBJC_LOCK_ROUTINE _spin_lock ! 31: #endif ! 32: #endif /* KERNEL */ ! 33: ! 34: #define isa 0 ! 35: #define cache 32 ! 36: #define mask 0 ! 37: #define buckets 8 ! 38: #define method_name 0 ! 39: #define method_imp 4 ! 40: ! 41: ;; Optimized specifically for HP7100 (Gecko architecture) ! 42: ;; It is assumed, that the cache line containing __objc_multithread_mask ! 43: ;; is not missing. This version has only two (2) back-to-back insn ! 44: ;; output dependencies, of which one is in the inner loop at 2:. ! 45: ;; This version has also no read insns with output dependency on the ! 46: ;; following insn. It is optimized with regard to branch prediction for ! 47: ;; hit in the first probe (average probe length assumed to be .45), that ! 48: ;; is why the final branch is moved before _objc_msgSend. ! 49: ! 50: ;; non-pic: 14 clocks best case, 4 clock / probe ! 51: ;; (4miss + 1hit) + (2hit) / probe ! 52: ! 53: ;; pic: 16 clocks best case, 4 clocks / probe ! 54: ;; (4miss + 2hit) + (2hit) / probe ! 55: ! 56: .text ! 57: .align 2 ! 58: .globl _objc_msgSend ! 59: ! 60: LX0: bv,n 0(%r1) ; goto *imp; (nullify delay) ! 61: _objc_msgSend: ! 62: comib,=,n 0,%r26, Lnull ; <?not taken?> ! 63: #ifdef DYLIB ! 64: bl LX1,%r21 ! 65: ldw isa(0,%r26),%r19 ; class = self->isa; ! 66: LX1: ! 67: depi 0,31,2,%r21 ! 68: addil L`__objc_multithread_mask$non_lazy_ptr-LX1,%r21 ! 69: ldw cache(0,%r19),%r20 ; cache = class->cache ! 70: ldw R`__objc_multithread_mask$non_lazy_ptr-LX1(%r1),%r22 ! 71: ldw mask(0,%r20),%r21 ; mask = cache->mask ! 72: ldw 0(%r22),%r22 ; <indirect non lazy pointer> ! 73: ldo buckets(%r20),%r20 ; buckets = cache->buckets ! 74: comib,=,n 0,%r22, SendLocking ; <?not taken?> ! 75: #else ! 76: ldil L`__objc_multithread_mask,%r1 ! 77: ldw isa(0,%r26),%r19 ; class = self->isa; ! 78: ldw R`__objc_multithread_mask(%r1),%r22 ! 79: ldw cache(0,%r19),%r20 ; cache = class->cache ! 80: comib,=,n 0,%r22, SendLocking ; <?not taken?> ! 81: ldw mask(0,%r20),%r21 ; mask = cache->mask ! 82: ldo buckets(%r20),%r20 ; buckets = cache->buckets ! 83: #endif ! 84: ! 85: and %r21,%r25,%r22 ; index = selector & mask; ! 86: 2: sh3add %r22,%r20,%r1 ; bucket = (index * 4) + buckets ! 87: ldw method_name(0,%r1),%r19 ; op = bucket->selector_name ! 88: ! 89: ldo 1(%r22),%r22 ; index += 1 ! 90: comb,= %r25,%r19,LX0 ; if (selector == op) goto Lexit1 <?taken?> ! 91: ldw method_imp(0,%r1),%r1 ; <delay slot> imp = bucket->selector_imp ! 92: comib,<> 0,%r19,2b ; if (op != 0) goto 2 <?taken?> ! 93: ! 94: and %r22,%r21,%r22 ; <delay slot> index &= mask ! 95: b,n L2 ; else goto cacheMiss ! 96: L2: ! 97: ; We have to save all the register based arguments (including floating ! 98: ; point) before calling _class_lookupMethodAndLoadCache. This is because ! 99: ; we do not know what arguments were passed to us, and the arguments are ! 100: ; not guaranteed to be saved across procedure calls (they are all caller-saved) ! 101: ; We also have to save the return address (since we did not save it on entry). ! 102: ! 103: ! 104: copy %r30,%r19 ! 105: ldo 128(%r30),%r30 ; Allocate space on stack ! 106: stwm %r2,4(0,%r19) ; Save return pointer ! 107: stwm %r23,4(0,%r19) ; Save old args ! 108: stwm %r24,4(0,%r19) ; ! 109: stwm %r25,4(0,%r19) ; ! 110: stwm %r26,4(0,%r19) ; ! 111: #ifndef KERNEL ! 112: fstds,mb %fr4,4(0,%r19) ; Save floating point args ! 113: fstds,mb %fr5,8(0,%r19) ; mb (modify before) is used instead ! 114: fstds,mb %fr6,8(0,%r19) ; of ma (as is implicit in above ! 115: fstds,mb %fr7,8(0,%r19) ; stores) with an initial value of 4 ! 116: ; so that doubles are aligned ! 117: ; to 8 byte boundaries. ! 118: ; Arg 1 (selector) is the same ! 119: #endif /* KERNEL */ ! 120: ! 121: stw %r28,8(0,%r19) ; save return struct ptr ! 122: jbsr __class_lookupMethodAndLoadCache,%r2,0f ! 123: ldw isa(0,%r26),%r26 ; <delay slot> arg 0 = self->isa ! 124: ! 125: ldo -128(%r30),%r30 ; deallocate ! 126: copy %r30,%r19 ; ! 127: ldwm 4(0,%r19),%r2 ; restore everything ! 128: ldwm 4(0,%r19),%r23 ; ! 129: ldwm 4(0,%r19),%r24 ; ! 130: ldwm 4(0,%r19),%r25 ; ! 131: ldwm 4(0,%r19),%r26 ; ! 132: #ifndef KERNEL ! 133: fldds,mb 4(0,%r19),%fr4 ; see comment above about alignment ! 134: fldds,mb 8(0,%r19),%fr5 ; ! 135: fldds,mb 8(0,%r19),%fr6 ; ! 136: fldds,mb 8(0,%r19),%fr7 ; ! 137: #endif /* KERNEL */ ! 138: ldw 8(0,%r19),%r20 ; get ret structure ptr ! 139: ! 140: copy %r28,%r19 ! 141: copy %r20,%r28 ; restore ret structure ptr ! 142: ! 143: bv,n 0(%r19) ; goto *imp (nullify delay) ! 144: ! 145: ; stub for far call ! 146: ! 147: .align 2 ! 148: #ifdef DYLIB ! 149: 0: bl LX5,%r1 ! 150: nop ! 151: LX5: depi 0,31,2,%r1 ! 152: addil L`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX5,%r1 ! 153: ldw R`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX5(%r1),%r1 ! 154: be,n 0(4,%r1) ! 155: #else ! 156: 0: ldil L`__class_lookupMethodAndLoadCache,%r1 ! 157: be,n R`__class_lookupMethodAndLoadCache(4,%r1) ! 158: #endif ! 159: ! 160: .align 2 ! 161: Lnull: ! 162: bv 0(%r2) ; return null ! 163: copy 0,%r28 ; <delay slot> return val = 0 ! 164: ! 165: ! 166: ! 167: ; Locking version of objc_msgSend ! 168: ; uses spin_lock() to lock the mutex. ! 169: ! 170: .align 2 ! 171: SendLocking: ! 172: copy %r30,%r19 ! 173: ldo 128(%r30),%r30 ; Allocate space on stack ! 174: stwm %r2,4(0,%r19) ; Save return pointer ! 175: stwm %r23,4(0,%r19) ; Save old args ! 176: ! 177: stwm %r24,4(0,%r19) ; ! 178: stwm %r25,4(0,%r19) ; ! 179: stwm %r26,4(0,%r19) ; ! 180: stwm %r28,4(0,%r19) ; save return struct ptr ! 181: ! 182: #ifndef KERNEL ! 183: fstds,ma %fr4,8(0,%r19) ; Save floating point args ! 184: fstds,ma %fr5,8(0,%r19) ; ! 185: fstds,ma %fr6,8(0,%r19) ; ! 186: fstds,ma %fr7,8(0,%r19) ; ! 187: #endif /* KERNEL */ ! 188: ! 189: #ifdef DYLIB ! 190: 0: bl LX6,%r24 ! 191: nop ! 192: LX6: depi 0,31,2,%r24 ! 193: addil L`_messageLock$non_lazy_ptr-LX6,%r24 ! 194: ldw R`_messageLock$non_lazy_ptr-LX6(%r1),%r26 ! 195: addil L`OBJC_LOCK_ROUTINE -LX6,%r24 ; call spin_lock() with _messageLock ! 196: ldw R`OBJC_LOCK_ROUTINE -LX6(%r1),%r24 ! 197: ble 0(%sr4,%r24) ! 198: #else ! 199: ldil L`_messageLock,%r1 ! 200: ldo R`_messageLock(%r1),%r26 ! 201: ldil L`OBJC_LOCK_ROUTINE,%r1 ; call spin_lock() with _messageLock ! 202: ble R`OBJC_LOCK_ROUTINE(%sr4,%r1) ! 203: #endif ! 204: ! 205: copy %r31,%r2 ! 206: ldw -112(%r30),%r26 ; restore arg0 ! 207: ldw -108(%r30),%r28 ; and ret0 ! 208: ldw isa(0,%r26),%r19 ; class = self->isa; ! 209: ! 210: ldw cache(0,%r19),%r20 ; cache = class->cache ! 211: ldw mask(0,%r20),%r21 ; mask = cache->mask ! 212: ldo buckets(%r20),%r20 ; buckets = cache->buckets ! 213: and %r21,%r25,%r22 ; index = selector & mask; ! 214: ! 215: LL1: sh3add %r22,%r20,%r1 ; bucket = (index * 4) + buckets ! 216: ldw method_name(0,%r1),%r19 ; op = bucket->selector_name ! 217: ldo 1(%r22),%r22 ; index += 1 ! 218: comb,=,n %r25,%r19,LLhit1 ; if (selector == op) goto LLhit1 ! 219: ! 220: comib,<> 0,%r19,LL1 ; if (op != 0) goto LL1 ! 221: and %r22,%r21,%r22 ; <delay slot> index &= mask ! 222: b,n LL2 ; else goto cacheMiss ! 223: LLhit1: ! 224: ldw method_imp(0,%r1),%r19 ; imp = bucket->selector_imp ! 225: #if KERNEL ! 226: ldil L`_messageLock,%r1 ! 227: ldo R`_messageLock(%r1),%r20 ! 228: addi 0xc,%r20,%r20 ! 229: depi 0,31,4,%r20 ! 230: zdepi 1,31,1,%r1 ! 231: stw %r1,0(0,%r20) ! 232: #else ! 233: #ifdef DYLIB ! 234: bl LX7,%r21 ! 235: nop ! 236: LX7: depi 0,31,2,%r21 ! 237: addil L`_messageLock$non_lazy_ptr-LX7,%r21 ! 238: ldw R`_messageLock$non_lazy_ptr-LX7(%r1),%r21 ! 239: stw %r0,0(%r21) ; unlock the lock ! 240: #else ! 241: ldil L`_messageLock,%r1 ! 242: stw %r0,R`_messageLock(%r1) ; unlock the lock ! 243: #endif ! 244: #endif ! 245: ldwm -128(%r30),%r2 ; restore original rp and deallocate ! 246: bv,n 0(%r19) ; goto *imp; (nullify delay) ! 247: ! 248: LL2: ! 249: jbsr __class_lookupMethodAndLoadCache,%r2,0f ! 250: ldw isa(0,%r26),%r26 ; <delay slot> arg 0 = self->isa ! 251: ! 252: ldo -128(%r30),%r30 ; deallocate ! 253: copy %r30,%r19 ; ! 254: ldwm 4(0,%r19),%r2 ; restore everything ! 255: ldwm 4(0,%r19),%r23 ; ! 256: ldwm 4(0,%r19),%r24 ; ! 257: ldwm 4(0,%r19),%r25 ; ! 258: ldwm 4(0,%r19),%r26 ; ! 259: ldwm 4(0,%r19),%r20 ; get ret structure ptr ! 260: #ifndef KERNEL ! 261: fldds,ma 8(0,%r19),%fr4 ; ! 262: fldds,ma 8(0,%r19),%fr5 ; ! 263: fldds,ma 8(0,%r19),%fr6 ; ! 264: fldds,ma 8(0,%r19),%fr7 ; ! 265: #endif /* KERNEL */ ! 266: ! 267: copy %r28,%r19 ! 268: copy %r20,%r28 ; restore ret structure ptr ! 269: #if KERNEL ! 270: ldil L`_messageLock,%r1 ! 271: ldo R`_messageLock(%r1),%r20 ! 272: addi 0xc,%r20,%r20 ! 273: depi 0,31,4,%r20 ! 274: zdepi 1,31,1,%r1 ! 275: stw %r1,0(0,%r20) ! 276: #else ! 277: #ifdef DYLIB ! 278: bl LX8,%r19 ! 279: nop ! 280: LX8: depi 0,31,2,%r19 ! 281: addil L`_messageLock$non_lazy_ptr-LX8,%r19 ! 282: ldw _messageLock$non_lazy_ptr-LX8(%r1),%r19 ! 283: stw %r0,0(%r19) ; unlock the lock ! 284: #else ! 285: ldil L`_messageLock,%r1 ! 286: stw %r0,R`_messageLock(%r1) ; unlock the lock ! 287: #endif ! 288: #endif ! 289: bv,n 0(%r19) ; goto *imp (nullify delay) ! 290: ! 291: ; stub for far call ! 292: ! 293: .align 2 ! 294: #ifdef DYLIB ! 295: 0: bl LX2,%r1 ! 296: nop ! 297: LX2: depi 0,31,2,%r1 ! 298: addil L`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX2,%r1 ! 299: ldw R`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX2(%r1),%r1 ! 300: be,n 0(4,%r1) ! 301: #else ! 302: 0: ldil L`__class_lookupMethodAndLoadCache,%r1 ! 303: be,n R`__class_lookupMethodAndLoadCache(4,%r1) ! 304: #endif ! 305: ! 306: ! 307: #define receiver 0 ! 308: #define class 4 ! 309: ! 310: .globl _objc_msgSendSuper ! 311: .align 2 ! 312: _objc_msgSendSuper: ! 313: ldil L`__objc_multithread_mask,%r1 ! 314: ldw R`__objc_multithread_mask(%r1),%r19 ! 315: combt,= %r0,%r19,SuperLocking ; ! 316: ldw class(0,%r26),%r19 ; class = caller->class; ! 317: ! 318: ldw cache(0,%r19),%r20 ; cache = class->cache ! 319: ldw mask(0,%r20),%r21 ; mask = cache->mask ! 320: ldo buckets(%r20),%r20 ; buckets = cache->buckets ! 321: and %r21,%r25,%r22 ; index = selector & mask; ! 322: ! 323: LS1: sh3add %r22,%r20,%r1 ; bucket = (index * 4) + buckets ! 324: ldw method_name(0,%r1),%r19 ; op = bucket->selector_name ! 325: ldo 1(%r22),%r22 ; index += 1 ! 326: comb,= %r25,%r19,LShit1 ; if (selector == op) goto LShit1 ! 327: ! 328: ldw method_imp(0,%r1),%r1 ; <delay slot> imp = bucket->selector_imp ! 329: comib,<> 0,%r19,LS1 ; if (op != 0) goto LS1 ! 330: and %r22,%r21,%r22 ; <delay slot> index &= mask ! 331: b,n LS2 ; else goto cacheMiss ! 332: ! 333: LShit1: ! 334: bv 0(%r1) ; goto *imp; (nullify delay) ! 335: ldw receiver(0,%r26),%r26 ; <delay slot> self = caller->receiver; ! 336: ; ! 337: LS2: ; ! 338: copy %r30,%r19 ! 339: ldo 128(%r30),%r30 ; Allocate space on stack ! 340: stwm %r2,4(0,%r19) ; Save return pointer ! 341: stwm %r23,4(0,%r19) ; Save old args ! 342: stwm %r24,4(0,%r19) ; ! 343: stwm %r25,4(0,%r19) ; ! 344: stwm %r26,4(0,%r19) ; ! 345: #ifndef KERNEL ! 346: fstds,mb %fr4,4(0,%r19) ; Save floating point args ! 347: fstds,mb %fr5,8(0,%r19) ; mb (modify before) is used instead ! 348: fstds,mb %fr6,8(0,%r19) ; of ma (as is implicit in above ! 349: fstds,mb %fr7,8(0,%r19) ; stores) with an initial value of 4 ! 350: ; so that doubles are aligned ! 351: ; to 8 byte boundaries. ! 352: ; Arg 1 (selector) is the same ! 353: #endif /* KERNEL */ ! 354: stw %r28,8(0,%r19) ; save return struct ptr ! 355: jbsr __class_lookupMethodAndLoadCache,%r2,0f ! 356: ldw class(0,%r26),%r26 ; <delay slot> arg 0 = caller->class; ! 357: ldo -128(%r30),%r30 ; deallocate ! 358: copy %r30,%r19 ; ! 359: ldwm 4(0,%r19),%r2 ; restore everything ! 360: ldwm 4(0,%r19),%r23 ; ! 361: ldwm 4(0,%r19),%r24 ; ! 362: ldwm 4(0,%r19),%r25 ; ! 363: ldwm 4(0,%r19),%r26 ; ! 364: #ifndef KERNEL ! 365: fldds,mb 4(0,%r19),%fr4 ; see comment above about alignment ! 366: fldds,mb 8(0,%r19),%fr5 ; ! 367: fldds,mb 8(0,%r19),%fr6 ; ! 368: fldds,mb 8(0,%r19),%fr7 ; ! 369: #endif /* KERNEL */ ! 370: ldw 8(0,%r19),%r20 ; get ret structure ptr ! 371: ldw receiver(0,%r26),%r26 ; self = caller->receiver; ! 372: copy %r28,%r19 ! 373: copy %r20,%r28 ! 374: bv,n 0(%r19) ; goto *imp (nullify delay) ! 375: ! 376: ; stub for far call ! 377: ! 378: .align 2 ! 379: #ifdef DYLIB ! 380: 0: bl LX3,%r1 ! 381: nop ! 382: LX3: depi 0,31,2,%r1 ! 383: addil L`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX3,%r1 ! 384: ldw R`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX3(%r1),%r1 ! 385: be,n 0(4,%r1) ! 386: #else ! 387: 0: ldil L`__class_lookupMethodAndLoadCache,%r1 ! 388: be,n R`__class_lookupMethodAndLoadCache(4,%r1) ! 389: #endif ! 390: ! 391: ! 392: ! 393: ! 394: ; locking version of objc_msgSendSuper ! 395: ; uses spin_lock() to lock the lock. ! 396: ! 397: .align 2 ! 398: SuperLocking: ! 399: copy %r30,%r19 ! 400: ldo 128(%r30),%r30 ; Allocate space on stack ! 401: stwm %r2,4(0,%r19) ; Save return pointer ! 402: stwm %r23,4(0,%r19) ; Save old args ! 403: stwm %r24,4(0,%r19) ; ! 404: stwm %r25,4(0,%r19) ; ! 405: stwm %r26,4(0,%r19) ; ! 406: stwm %r28,4(0,%r19) ; save return struct ptr ! 407: #ifndef KERNEL ! 408: fstds,ma %fr4,8(0,%r19) ; Save floating point args ! 409: fstds,ma %fr5,8(0,%r19) ; ! 410: fstds,ma %fr6,8(0,%r19) ; ! 411: fstds,ma %fr7,8(0,%r19) ; ! 412: #endif /* KERNEL */ ! 413: #ifdef DYLIB ! 414: 0: bl LX9,%r24 ! 415: nop ! 416: LX9: depi 0,31,2,%r24 ! 417: addil L`_messageLock$non_lazy_ptr-LX9,%r24 ! 418: ldw R`_messageLock$non_lazy_ptr-LX9(%r1),%r26 ! 419: addil L`OBJC_LOCK_ROUTINE-LX9,%r24 ; call spin_lock() with _messageLock ! 420: ldw R`OBJC_LOCK_ROUTINE-LX9(%r1),%r24 ! 421: ble 0(%sr4,%r24) ! 422: #else ! 423: ldil L`_messageLock,%r1 ! 424: ldo R`_messageLock(%r1),%r26 ! 425: ldil L`OBJC_LOCK_ROUTINE,%r1 ; call spin_lock() with _messageLock ! 426: ble R`OBJC_LOCK_ROUTINE(%sr4,%r1) ! 427: #endif ! 428: copy %r31,%r2 ! 429: ldw -112(%r30),%r26 ; restore arg0 ! 430: ldw -108(%r30),%r28 ; and ret0 (spin_lock doesnt ! 431: ; touch anything else) ! 432: ldw class(0,%r26),%r19 ; class = caller->class; ! 433: ldw cache(0,%r19),%r20 ; cache = class->cache ! 434: ldw mask(0,%r20),%r21 ; mask = cache->mask ! 435: ldo buckets(%r20),%r20 ; buckets = cache->buckets ! 436: and %r21,%r25,%r22 ; index = selector & mask; ! 437: ! 438: LLS1: sh3add %r22,%r20,%r1 ; bucket = (index * 4) + buckets ! 439: ldw method_name(0,%r1),%r19 ; op = bucket->selector_name ! 440: ldo 1(%r22),%r22 ; index += 1 ! 441: comb,=,n %r25,%r19,LLShit1 ; if (selector == op) goto LShit1 ! 442: ! 443: comib,<> 0,%r19,LLS1 ; if (op != 0) goto LS1 ! 444: and %r22,%r21,%r22 ; <delay slot> index &= mask ! 445: b,n LLS2 ; else goto cacheMiss ! 446: ! 447: LLShit1: ! 448: ldw method_imp(0,%r1),%r19 ; imp = bucket->selector_imp ! 449: ldw receiver(0,%r26),%r26 ; self = caller->receiver; ! 450: ! 451: #if KERNEL ! 452: ldil L`_messageLock,%r1 ! 453: ldo R`_messageLock(%r1),%r20 ! 454: addi 0xc,%r20,%r20 ! 455: depi 0,31,4,%r20 ! 456: zdepi 1,31,1,%r1 ! 457: stw %r1,0(0,%r20) ! 458: #else ! 459: #ifdef DYLIB ! 460: bl LX10,%r19 ! 461: nop ! 462: LX10: depi 0,31,2,%r19 ! 463: addil L`_messageLock$non_lazy_ptr-LX10,%r19 ! 464: ldw R`_messageLock$non_lazy_ptr-LX10(%r1),%r19 ! 465: stw %r0,0(%r19) ; unlock the lock ! 466: #else ! 467: ldil L`_messageLock,%r1 ! 468: stw %r0,R`_messageLock(%r1) ; unlock the lock ! 469: #endif ! 470: #endif ! 471: ldwm -128(%r30),%r2 ; restore original rp and deallocate ! 472: bv,n 0(%r19) ; goto *imp; (nullify delay) ! 473: #ifdef MONINIT ! 474: .space 128 ; /* area for moninitobjc to write */ ! 475: #endif ! 476: ! 477: ; ! 478: LLS2: ; ! 479: jbsr __class_lookupMethodAndLoadCache,%r2,0f ! 480: ldw class(0,%r26),%r26 ; <delay slot> arg 0 = caller->class; ! 481: ldo -128(%r30),%r30 ; deallocate ! 482: copy %r30,%r19 ; ! 483: ldwm 4(0,%r19),%r2 ; restore everything ! 484: ldwm 4(0,%r19),%r23 ; ! 485: ldwm 4(0,%r19),%r24 ; ! 486: ldwm 4(0,%r19),%r25 ; ! 487: ldwm 4(0,%r19),%r26 ; ! 488: ldwm 4(0,%r19),%r20 ; get ret structure ptr ! 489: #ifndef KERNEL ! 490: fldds,ma 8(0,%r19),%fr4 ; ! 491: fldds,ma 8(0,%r19),%fr5 ; ! 492: fldds,ma 8(0,%r19),%fr6 ; ! 493: fldds,ma 8(0,%r19),%fr7 ; ! 494: #endif /* KERNEL */ ! 495: ldw receiver(0,%r26),%r26 ; self = caller->receiver; ! 496: copy %r28,%r19 ! 497: copy %r20,%r28 ! 498: #if KERNEL ! 499: ldil L`_messageLock,%r1 ! 500: ldo R`_messageLock(%r1),%r20 ! 501: addi 0xc,%r20,%r20 ! 502: depi 0,31,4,%r20 ! 503: zdepi 1,31,1,%r1 ! 504: stw %r1,0(0,%r20) ! 505: #else ! 506: ldil L`_messageLock,%r1 ! 507: stw %r0,R`_messageLock(%r1) ; unlock the lock ! 508: #endif ! 509: bv,n 0(%r19) ; goto *imp (nullify delay) ! 510: ! 511: ; stub for far call ! 512: ! 513: .align 2 ! 514: #ifdef DYLIB ! 515: 0: bl LX4,%r1 ! 516: nop ! 517: LX4: depi 0,31,2,%r1 ! 518: addil L`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX4,%r1 ! 519: ldw R`__class_lookupMethodAndLoadCache$non_lazy_ptr-LX4(%r1),%r1 ! 520: be,n 0(4,%r1) ! 521: #else ! 522: 0: ldil L`__class_lookupMethodAndLoadCache,%r1 ! 523: be,n R`__class_lookupMethodAndLoadCache(4,%r1) ! 524: #endif ! 525: ! 526: ! 527: .objc_meth_var_names ! 528: L30: .ascii "forward::\0" ! 529: ! 530: .objc_message_refs ! 531: .align 2 ! 532: L31: .long L30 ! 533: ! 534: .cstring ! 535: L32: .ascii "Does not recognize selector %s\0" ! 536: ! 537: .text ! 538: .align 2 ! 539: ; ! 540: ; NOTE: Because the stack grows from low mem to high mem on this machine ! 541: ; and the args go the other way, the marg_list pointer is to the first argument ! 542: ; and subsequent arguments are at NEGATIVE offsets from the marg_list. ! 543: ; This means that marg_getValue() and related macros will have to be adjusted ! 544: ; appropriately. ! 545: ; ! 546: .globl __objc_msgForward ! 547: __objc_msgForward: ! 548: stw %r2,-20(0,%r30) ; save rp ! 549: ldo 64(%r30),%r30 ; create frame area (no locals needed) ! 550: ldil L`L31,%r1 ! 551: ldo R`L31(%r1),%r19 ! 552: ldw 0(0,%r19),%r19 ! 553: combt,=,n %r19, %r25,L34 ; if (sel==@selector(forward::)) ! 554: ldo -112(%r30),%r20 ; ptr to arg3 homing area ! 555: stwm %r23,4(0,%r20) ; Mirror registers onto stack ! 556: stwm %r24,4(0,%r20) ; ! 557: stwm %r25,4(0,%r20) ; ! 558: stwm %r26,4(0,%r20) ; ! 559: ! 560: copy %r25,%r24 ! 561: copy %r19,%r25 ; [self forward:sel :marg_list] ! 562: ! 563: bl _objc_msgSend,%r2 ! 564: copy %r20,%r23 ; <delay slot> copy original sel ! 565: ! 566: ldo -64(%r30),%r30 ; deallocate ! 567: ldw -20(0,%r30),%r2 ; restore rp ! 568: bv,n 0(%r2) ; return ! 569: L34: ! 570: ldil L`L32,%r1 ! 571: ldo R`L32(%r1),%r25 ! 572: ldil L`__objc_error,%r1 ! 573: be R`__objc_error(%sr4,%r1) ; __objc_error never returns, so no ! 574: copy %r19,%r24 ; need to clean up. ! 575: ! 576: ! 577: ; Algorithm is as follows: ! 578: ; . Calculate how much stack size is needed for any arguments not in the ! 579: ; general registers and allocate space on stack. ! 580: ; . Restore general argument regs from the bottom of the marg_list. ! 581: ; . Restore fp argument regs from the same area. ! 582: ; (The first two args in the marg list are always old obj and old SEL.) ! 583: ; . Copy any remaining args from the marg_list to the new frame ! 584: ; . Call the new method. ! 585: .align 2 ! 586: .globl _objc_msgSendv ! 587: _objc_msgSendv: ! 588: ; objc_msgSendv(self, sel, size, margs) ! 589: stw %r2,-20(0,%r30) ; ! 590: copy %r4, %r1 ; stanard prologue ! 591: copy %r30,%r4 ; ! 592: stw %r1,0(0,%r4) ; ! 593: ldo 99(%r24),%r19 ; Calculate frame size, rounded ! 594: depi 0,31,6,%r19 ; up to 64 byte boundary... ! 595: ! 596: add %r19,%r30,%r30 ; Allocate frame area (no locals) ! 597: copy %r24,%r20 ; r20 now holds arg size ! 598: ldo -16(%r23),%r21 ; r21 now holds marg_list+16 ! 599: ldws 0(0,%r21),%r23 ; Get old general register args (dont ! 600: ldws 4(0,%r21),%r24 ; need first two: always self & SEL) ! 601: #ifndef KERNEL ! 602: fldds 0(0,%r21),%fr7 ; Mirror to fp regs ! 603: fldws 4(0,%r21),%fr6 ; ! 604: #endif /* KERNEL */ ! 605: ! 606: ldo -52(%r30),%r22 ; newly allocated stack area. ! 607: ldo -16(%r20),%r20 ; Size -= 16 ! 608: comibf,<,n 0,%r20,L36 ! 609: L35: ldws,mb -4(0,%r21),%r19 ; while(size>0) ! 610: addibf,<= -4,%r20,L35 ; { *(dest--) = *(src--); size-=4; } ! 611: stws,ma %r19,-4(0,%r22) ; <delay slot> ! 612: L36: bl _objc_msgSend,%r2 ! 613: nop ! 614: copy %r4,%r30 ; deallocate ! 615: ldw -20(0,%r30), %r2 ! 616: bv 0(%r2) ! 617: ldw 0(0,%r30), %r4 ! 618: ! 619: #ifdef DYLIB ! 620: .non_lazy_symbol_pointer ! 621: _messageLock$non_lazy_ptr: ! 622: .indirect_symbol _messageLock ! 623: .long 0 ! 624: _spin_lock$non_lazy_ptr: ! 625: .indirect_symbol _spin_lock ! 626: .long 0 ! 627: __objc_multithread_mask$non_lazy_ptr: ! 628: .indirect_symbol __objc_multithread_mask ! 629: .long 0 ! 630: __class_lookupMethodAndLoadCache$non_lazy_ptr: ! 631: .indirect_symbol __class_lookupMethodAndLoadCache ! 632: .long 0 ! 633: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.