|
|
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.