|
|
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: ; _objc_entryPoints and _objc_exitPoints are used by moninitobjc() to setup ! 28: ; objective-C messages for profiling. The are made private_externs when in ! 29: ; a shared library. ! 30: .reference _moninitobjc ! 31: .const ! 32: .globl _objc_entryPoints ! 33: _objc_entryPoints: ! 34: .long _objc_msgSend ! 35: .long _objc_msgSendSuper ! 36: .long 0 ! 37: ! 38: .globl _objc_exitPoints ! 39: _objc_exitPoints: ! 40: .long Lexit1 ! 41: .long Lexit5 ! 42: .long 0 ! 43: ! 44: #define OBJC_LOCK_ROUTINE _spin_lock ! 45: #endif /* KERNEL */ ! 46: ! 47: #define isa 0 ! 48: #define cache 32 ! 49: #define mask 0 ! 50: #define buckets 8 ! 51: #define method_name 0 ! 52: #define method_imp 8 ! 53: ! 54: ! 55: ; optimized for hppa: 20? clocks (best case) + 6 clocks / probe ! 56: ! 57: .text ! 58: .align 4 ! 59: .globl _objc_msgSend ! 60: ! 61: _objc_msgSend: ! 62: comib,<>,n 0,%r26,L0 ; if (self) goto normalcase ! 63: nop ! 64: bv 0(%r2) ; else return null ! 65: copy 0,%r28 ; <delay slot> return val = 0 ! 66: L0: ! 67: ldw isa(0,%r26),%r19 ; class = self->isa; ! 68: ldw cache(0,%r19),%r20 ; cache = class->cache ! 69: ldw mask(0,%r20),%r21 ; mask = cache->mask ! 70: ldo buckets(%r20),%r20 ; buckets = cache->buckets ! 71: and %r21,%r25,%r22 ; index = selector & mask; ! 72: L1: ! 73: ldwx,s %r22(0,%r20),%r19 ; method = cache->buckets[index]; ! 74: comib,=,n 0,%r19,cacheMiss ; if (method == NULL) ! 75: ldw method_name(0,%r19),%r1 ; ! 76: addi 1,%r22,%r22 ; ++index ! 77: comb,<> %r1, %r25, L1 ; if (name!=sel) continue loop ! 78: and %r21,%r22,%r22 ; <delay slot> index &=mask ! 79: ldw method_imp(0,%r19),%r19 ! 80: Lexit1: ! 81: bv,n 0(%r19) ; goto *imp; (nullify delay) ! 82: ! 83: #ifdef MONINIT ! 84: .space 128 ; /* area for moninitobjc to write */ ! 85: #endif ! 86: ! 87: cacheMiss: ! 88: ; We have to save all the register based arguments (including floating ! 89: ; point) before calling _class_lookupMethodAndLoadCache. This is because ! 90: ; we do not know what arguments were passed to us, and the arguments are ! 91: ; not guaranteed to be saved across procedure calls (they are all caller-saved) ! 92: ; We also have to save the return address (since we did not save it on entry). ! 93: ! 94: ! 95: copy %r30,%r19 ! 96: ldo 128(%r30),%r30 ; Allocate space on stack ! 97: stwm %r2,4(0,%r19) ; Save return pointer ! 98: stwm %r23,4(0,%r19) ; Save old args ! 99: stwm %r24,4(0,%r19) ; ! 100: stwm %r25,4(0,%r19) ; ! 101: stwm %r26,4(0,%r19) ; ! 102: #ifndef KERNEL ! 103: fstds,mb %fr4,4(0,%r19) ; Save floating point args ! 104: fstds,mb %fr5,8(0,%r19) ; mb (modify before) is used instead ! 105: fstds,mb %fr6,8(0,%r19) ; of ma (as is implicit in above ! 106: fstds,mb %fr7,8(0,%r19) ; stores) with an initial value of 4 ! 107: ; so that doubles are aligned ! 108: ; to 8 byte boundaries. ! 109: ; Arg 1 (selector) is the same ! 110: #endif /* KERNEL */ ! 111: ! 112: stw %r28,8(0,%r19) ; save return struct ptr ! 113: jbsr __class_lookupMethodAndLoadCache,%r2,0f ! 114: ldw isa(0,%r26),%r26 ; <delay slot> arg 0 = self->isa ! 115: ! 116: ldo -128(%r30),%r30 ; deallocate ! 117: copy %r30,%r19 ; ! 118: ldwm 4(0,%r19),%r2 ; restore everything ! 119: ldwm 4(0,%r19),%r23 ; ! 120: ldwm 4(0,%r19),%r24 ; ! 121: ldwm 4(0,%r19),%r25 ; ! 122: ldwm 4(0,%r19),%r26 ; ! 123: #ifndef KERNEL ! 124: fldds,mb 4(0,%r19),%fr4 ; see comment above about alignment ! 125: fldds,mb 8(0,%r19),%fr5 ; ! 126: fldds,mb 8(0,%r19),%fr6 ; ! 127: fldds,mb 8(0,%r19),%fr7 ; ! 128: #endif /* KERNEL */ ! 129: ldw 8(0,%r19),%r20 ; get ret structure ptr ! 130: ! 131: copy %r28,%r19 ! 132: copy %r20,%r28 ; restore ret structure ptr ! 133: Lexit2: ! 134: bv,n 0(%r19) ; goto *imp (nullify delay) ! 135: ! 136: ; stub for far call ! 137: ! 138: 0: ldil L`__class_lookupMethodAndLoadCache,%r1 ! 139: ble,n R`__class_lookupMethodAndLoadCache(4,%r1) ! 140: ! 141: #ifdef MONINIT ! 142: .space 128 ; /* area for moninitobjc to write */ ! 143: #endif ! 144: ! 145: ! 146: ! 147: ! 148: ! 149: #define receiver 0 ! 150: #define class 4 ! 151: ! 152: .globl _objc_msgSendSuper ! 153: _objc_msgSendSuper: ! 154: ldw class(0,%r26),%r19 ; class = caller->class; ! 155: ldw cache(0,%r19),%r20 ; cache = class->cache ! 156: ldw mask(0,%r20),%r21 ; mask = cache->mask ! 157: ldo buckets(%r20),%r20 ; buckets = cache->buckets ! 158: and %r21,%r25,%r22 ; index = selector & mask; ! 159: LS1: ; ! 160: ldwx,s %r22(0,%r20),%r19 ; method = cache->buckets[index]; ! 161: comib,=,n 0,%r19,LS2 ; if (method == NULL) ! 162: ldw method_name(0,%r19),%r1; ! 163: addi 1,%r22,%r22 ; ++index ! 164: comb,<> %r1, %r25, LS1 ; if (name!=sel) continue loop ! 165: and %r21,%r22,%r22 ; <delay slot> index &=mask ! 166: ldw method_imp(0,%r19),%r19 ! 167: ldw receiver(0,%r26),%r26 ; self = caller->receiver; ! 168: Lexit5: ! 169: bv,n 0(%r19) ; goto *imp; (nullify delay) ! 170: #ifdef MONINIT ! 171: .space 128 ; /* area for moninitobjc to write */ ! 172: #endif ! 173: ! 174: ; ! 175: LS2: ; ! 176: copy %r30,%r19 ! 177: ldo 128(%r30),%r30 ; Allocate space on stack ! 178: stwm %r2,4(0,%r19) ; Save return pointer ! 179: stwm %r23,4(0,%r19) ; Save old args ! 180: stwm %r24,4(0,%r19) ; ! 181: stwm %r25,4(0,%r19) ; ! 182: stwm %r26,4(0,%r19) ; ! 183: #ifndef KERNEL ! 184: fstds,mb %fr4,4(0,%r19) ; Save floating point args ! 185: fstds,mb %fr5,8(0,%r19) ; mb (modify before) is used instead ! 186: fstds,mb %fr6,8(0,%r19) ; of ma (as is implicit in above ! 187: fstds,mb %fr7,8(0,%r19) ; stores) with an initial value of 4 ! 188: ; so that doubles are aligned ! 189: ; to 8 byte boundaries. ! 190: ; Arg 1 (selector) is the same ! 191: #endif /* KERNEL */ ! 192: stw %r28,8(0,%r19) ; save return struct ptr ! 193: jbsr __class_lookupMethodAndLoadCache,%r2,0f ! 194: ldw class(0,%r26),%r26 ; <delay slot> arg 0 = caller->class; ! 195: ldo -128(%r30),%r30 ; deallocate ! 196: copy %r30,%r19 ; ! 197: ldwm 4(0,%r19),%r2 ; restore everything ! 198: ldwm 4(0,%r19),%r23 ; ! 199: ldwm 4(0,%r19),%r24 ; ! 200: ldwm 4(0,%r19),%r25 ; ! 201: ldwm 4(0,%r19),%r26 ; ! 202: #ifndef KERNEL ! 203: fldds,mb 4(0,%r19),%fr4 ; see comment above about alignment ! 204: fldds,mb 8(0,%r19),%fr5 ; ! 205: fldds,mb 8(0,%r19),%fr6 ; ! 206: fldds,mb 8(0,%r19),%fr7 ; ! 207: #endif /* KERNEL */ ! 208: ldw 8(0,%r19),%r20 ; get ret structure ptr ! 209: ldw receiver(0,%r26),%r26 ; self = caller->receiver; ! 210: copy %r28,%r19 ! 211: copy %r20,%r28 ! 212: Lexit6: bv,n 0(%r19) ; goto *imp (nullify delay) ! 213: ! 214: ; stub for far call ! 215: ! 216: 0: ldil L`__class_lookupMethodAndLoadCache,%r1 ! 217: ble,n R`__class_lookupMethodAndLoadCache(4,%r1) ! 218: ! 219: #ifdef MONINIT ! 220: .space 128 ; /* area for moninitobjc to write */ ! 221: #endif ! 222: ! 223: ! 224: .objc_meth_var_names ! 225: .align 1 ! 226: L30: .ascii "forward::\0" ! 227: ! 228: .objc_message_refs ! 229: .align 2 ! 230: L31: .long L30 ! 231: ! 232: .cstring ! 233: .align 1 ! 234: L32: .ascii "Does not recognize selector %s\0" ! 235: ! 236: .text ! 237: .align 1 ! 238: ; ! 239: ; NOTE: Because the stack grows from low mem to high mem on this machine ! 240: ; and the args go the other way, the marg_list pointer is to the first argument ! 241: ; and subsequent arguments are at NEGATIVE offsets from the marg_list. ! 242: ; This means that marg_getValue() and related macros will have to be adjusted ! 243: ; appropriately. ! 244: ; ! 245: .globl __objc_msgForward ! 246: __objc_msgForward: ! 247: stw %r2,-20(0,%r30) ; save rp ! 248: ldo 64(%r30),%r30 ; create frame area (no locals needed) ! 249: ldil L`L31,%r1 ! 250: ldo R`L31(%r1),%r19 ! 251: ldw 0(0,%r19),%r19 ! 252: combt,=,n %r19, %r25,L34 ; if (sel==@selector(forward::)) ! 253: ldo -112(%r30),%r20 ; ptr to arg3 homing area ! 254: stwm %r23,4(0,%r20) ; Mirror registers onto stack ! 255: stwm %r24,4(0,%r20) ; ! 256: stwm %r25,4(0,%r20) ; ! 257: stwm %r26,4(0,%r20) ; ! 258: ! 259: copy %r25,%r24 ! 260: copy %r19,%r25 ; [self forward:sel :marg_list] ! 261: ! 262: bl _objc_msgSend,%r2 ! 263: copy %r20,%r23 ; <delay slot> copy original sel ! 264: ! 265: ldo -64(%r30),%r30 ; deallocate ! 266: ldw -20(0,%r30),%r2 ; restore rp ! 267: bv,n 0(%r2) ; return ! 268: L34: ! 269: ldil L`L32,%r1 ! 270: ldo R`L32(%r1),%r25 ! 271: ldil L`__objc_error,%r1 ! 272: be R`__objc_error(%sr4,%r1) ; __objc_error never returns, so no ! 273: copy %r19,%r24 ; need to clean up. ! 274: ! 275: ! 276: ; Algorithm is as follows: ! 277: ; . Calculate how much stack size is needed for any arguments not in the ! 278: ; general registers and allocate space on stack. ! 279: ; . Restore general argument regs from the bottom of the marg_list. ! 280: ; . Restore fp argument regs from the same area. ! 281: ; (The first two args in the marg list are always old obj and old SEL.) ! 282: ; . Call the new method. ! 283: .globl _objc_msgSendv ! 284: _objc_msgSendv: ! 285: ; objc_msgSendv(self, sel, size, margs) ! 286: stw %r2,-20(0,%r30) ; Save rp ! 287: stw %r4,-36(0,%r30) ; Save callee-saved r4 ! 288: copy %r30,%r4 ; Save old sp vale ! 289: ldo 95(%r24),%r19 ; Calculate frame size, rounded ! 290: depi 0,31,6,%r19 ; up to 64 byte boundary... ! 291: ! 292: add %r19,%r30,%r30 ; Allocate frame area (no locals) ! 293: copy %r24,%r20 ; r20 now holds arg size ! 294: ldo -16(%r23),%r21 ; r21 now holds marg_list+16 ! 295: ldws 0(0,%r21),%r23 ; Get old general register args (dont ! 296: ldws 4(0,%r21),%r24 ; need first two: always self & SEL) ! 297: #ifndef KERNEL ! 298: fldds 0(0,%r21),%fr7 ; Mirror to fp regs ! 299: fldws 4(0,%r21),%fr6 ; ! 300: #endif /* KERNEL */ ! 301: ! 302: ldo -52(%r30),%r22 ; newly allocated stack area. ! 303: ldo -8(%r20),%r20 ; Size -= 8 ! 304: comibf,<,n 0,%r20,L36 ! 305: L35: ldws,mb -4(0,%r21),%r19 ; while(size>0) ! 306: addibf,<= -4,%r20,L35 ; { *(dest--) = *(src--); size-=4; } ! 307: stws,ma %r19,-4(0,%r22) ; <delay slot> ! 308: L36: bl _objc_msgSend,%r2 ! 309: nop ! 310: copy %r4,%r30 ; deallocate ! 311: ldw -36(0,%r30), %r4 ! 312: ldw -20(0,%r30), %r2 ! 313: Lexit9: ! 314: bv,n 0(%r2) ! 315: ! 316:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.