Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/trunk/src/runtime/mach-dep/SPARC.prim.asm
ViewVC logotype

Annotation of /sml/trunk/src/runtime/mach-dep/SPARC.prim.asm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (view) (download)
Original Path: sml/branches/SMLNJ/src/runtime/mach-dep/SPARC.prim.asm

1 : monnier 2 /* SPARC.prim.asm
2 :     *
3 :     * COPYRIGHT (c) 1992 by AT&T Bell Laboratories.
4 :     *
5 :     * AUTHOR: John Reppy
6 :     * Cornell University
7 :     * Ithaca, NY 14853
8 :     * jhr@cs.cornell.edu
9 :     *
10 :     * SPARC runtime code for ML. Registers are used as follows:
11 :     *
12 :     * %g7 : exception handler continuation
13 :     * %g6 : freespace pointer
14 :     * %g4 : heap limit pointer
15 :     *
16 :     * %i0 = arg
17 :     * %i1 = continuation
18 :     * %i2 = closure; can be ignored because contains no free vars
19 :     * %i3 = base code pointer
20 :     * %g1 = link register (this should be %i4!!!)
21 :     * %i5 = var ptr
22 :     *
23 :     * %o0,o1,%g1-%g3,%l0-%l7,%i4 = misc. registers (contain only pointers or tagged ints)
24 :     * %o5 = pointer temp.
25 :     *
26 :     * %o2,%o3 = used for args to ml_mul & ml_div, also used as temp registers
27 :     * %o4,%o5 = temp registers
28 :     *
29 :     * %o6 = %sp (not used by ML)
30 :     * %i6 = %fp (not used by ML)
31 :     * %i7 = return address to C code (not used by ML)
32 :     * %o7 = not used
33 :     *
34 :     * The root registers in the ML state vector have the following layout,
35 :     * where roots is guaranteed to be 8-byte aligned relative to the start
36 :     * of the ML state vector (see "ml-state.h" and "mlstate-offsets.h"):
37 :     *
38 :     * +-------------------+
39 :     * roots: | ml_arg (%i0) |
40 :     * +-------------------+
41 :     * roots+4: | ml_cont (%i1) |
42 :     * +-------------------+
43 :     * roots+8: | ml_closure (%i2) |
44 :     * +-------------------+
45 :     * roots+12: | ml_baseReg (%i3) |
46 :     * +-------------------+
47 :     * roots+16: | ml_linkReg (%g1) | *** THIS SHOULD BE %i4 ***
48 :     * +-------------------+
49 :     * roots+20: | ml_varReg (%i5) |
50 :     * +-------------------+
51 :     * roots+24: | ml_pc |
52 :     * +-------------------+
53 :     * roots+28: | ml_exncont (%g7) |
54 :     * +-------------------+
55 :     * roots+32: | (%g2-%g3) |
56 :     * +-------------------+
57 :     * roots+40: | (%o0-%o1) |
58 :     * +-------------------+
59 :     * roots+48: | (%l0-%l7) |
60 :     * +-------------------+
61 :     * roots+72: | %i4 |
62 :     * +-------------------+
63 :     */
64 :    
65 :    
66 :     #include "asm-base.h"
67 :     #include "ml-base.h"
68 :     #include "ml-values.h"
69 :     #include "tags.h"
70 :     #include "ml-request.h"
71 :     #include "reg-mask.h"
72 :     #include "ml-limits.h"
73 :     #include "mlstate-offsets.h" /** this file is generated **/
74 :    
75 :    
76 :     /* IMPORTANT NOTE:
77 :     * Many of these registers are in "register pairs", which is used
78 :     * to advantage when loading and storing them from/to the ML State.
79 :     * Beware if you re-arrange these register assignments
80 :     * (look for ldd and std instructions). The same goes for the
81 :     * offsets in the ML state vector
82 :     */
83 :     #define ZERO %g0
84 :     #define EXNCONT %g7 /* exception handler (ml_exncont) */
85 :     #define ALLOCPTR %g6 /* freespace pointer (ml_allocptr) */
86 :     #define STOREPTR %g5 /* store pointer (ml_storeptr) */
87 :     #define LIMITPTR %g4 /* heap limit pointer (ml_limitptr)*/
88 :     #define STDARG %i0 /* standard argument (ml_arg) */
89 :     #define STDCONT %i1 /* standard continuation (ml_cont) */
90 :     #define STDCLOS %i2 /* standard closure (ml_clos) */
91 :     #define BASEPTR %i3 /* base code pointer (ml_roots[]) */
92 :     #define VARPTR %i5 /* var pointer (ml_varptr) */
93 :     #define STDLINK %g1
94 :     #define MISCREG0 %g2 /* miscellaneous registers (ml_roots[]) */
95 :     #define MISCREG1 %g3 /* the first few of these may be callee-save */
96 :     #define MISCREG2 %o0
97 :     #define MISCREG3 %o1
98 :     #define MISCREG4 %l0
99 :     #define MISCREG5 %l1
100 :     #define MISCREG6 %l2
101 :     #define MISCREG7 %l3
102 :     #define MISCREG8 %l4
103 :     #define MISCREG9 %l5
104 :     #define MISCREG10 %l6
105 :     #define MISCREG11 %l7
106 :     #define MISCREG12 %i4
107 :     #define TMPREG1 %o2
108 :     #define TMPREG2 %o3
109 :     #define TMPREG3 %o4
110 :     #define TMPREG4 %o5 /* also used to pass register mask to g.c. */
111 :     #define GCLINK %o7 /* link register for return from g.c. (ml_pc) */
112 :    
113 :     /* %o2 and %o3 are also used as for multiply and divide */
114 :    
115 :     /*
116 :     * %o6 = %sp (not used by ML)
117 :     * %i6 = %fp (not used by ML)
118 :     * %i7 = return address to C code (not used by ML)
119 :     *
120 :     * The ML stack frame has the following layout (set up by restoreregs):
121 :     *
122 :     * +-------------------+
123 :     * %fp = %sp+112: | empty |
124 :     * +-------------------+
125 :     * %sp+108: | pseudo reg 2 |
126 :     * +-------------------+
127 :     * %sp+104: | pseudo reg 1 |
128 :     * +-------------------+
129 :     * %sp+100: | addr of _saveregs |
130 :     * +-------------------+
131 :     * %sp+96: | ptr to MLState |
132 :     * +-------------------+
133 :     * %sp+92: | temp for floor |
134 :     * +-------------------+
135 :     * %sp+88: | temp for cvti2d |
136 :     * +-------------------+
137 :     * %sp+84: | addr of _ml_udiv |
138 :     * +-------------------+
139 :     * %sp+80: | addr of _ml_umul |
140 :     * +-------------------+
141 :     * %sp+76: | addr of _ml_div |
142 :     * +-------------------+
143 :     * %sp+72: | addr of _ml_mul |
144 :     * +-------------------+
145 :     * %sp+68: | saved %g6 |
146 :     * +-------------------+
147 :     * %sp+64: | saved %g7 |
148 :     * +-------------------+
149 :     * | space to save |
150 :     * | in and local |
151 :     * %sp: | registers |
152 :     * +-------------------+
153 :     *
154 :     * Note that this must be a multiple of 8 bytes. The size of the
155 :     * stack frame is:
156 :     */
157 :     #define ML_FRAMESIZE (WINDOWSIZE+48)
158 :    
159 :     #define MUL_OFFSET 72
160 :     #define DIV_OFFSET 76
161 :     #define UMUL_OFFSET 80
162 :     #define UDIV_OFFSET 84
163 :     #define FLOOR_OFFSET 92
164 :     #define MLSTATE_OFFSET 96
165 :     #define STARTGC_OFFSET 100
166 :     #define PSEUDOREG_OFFSET 104
167 :    
168 :     #if (CALLEESAVE > 0)
169 :     #define CONTINUE \
170 :     jmp STDCONT; \
171 :     subcc ALLOCPTR,LIMITPTR,%g0
172 :     #else
173 :     #define CONTINUE \
174 :     ld [STDCONT],STDLINK; \
175 :     jmp STDLINK; \
176 :     subcc ALLOCPTR,LIMITPTR,%g0
177 :     #endif
178 :    
179 :     #define CHECKLIMIT(mask,label) \
180 :     bl label; \
181 :     nop; \
182 :     set mask,TMPREG4; \
183 :     mov STDLINK,GCLINK; \
184 :     ba CSYM(saveregs); \
185 :     nop; \
186 :     label:
187 :    
188 :    
189 :     TEXT
190 :    
191 :     /* sigh_return_a:
192 :     * The return continuation for the ML signal handler.
193 :     */
194 :     ML_CODE_HDR(sigh_return_a)
195 :     set RET_MASK,TMPREG4
196 :     ba set_request
197 :     set REQ_SIG_RETURN,TMPREG3 /* (delay slot) */
198 :    
199 :     /* sigh_resume:
200 :     * Resume execution at the point at which a handler trap occurred. This is a
201 :     * standard two-argument function, thus the closure is in ml_cont (stdcont).
202 :     */
203 :     ENTRY(sigh_resume)
204 :     set FUN_MASK,TMPREG4
205 :     ba set_request
206 :     set REQ_SIG_RESUME,TMPREG3 /* (delay slot) */
207 :    
208 :     /* pollh_return_a:
209 :     * The return continuation for the ML poll handler.
210 :     */
211 :     ML_CODE_HDR(pollh_return_a)
212 :     set RET_MASK,TMPREG4
213 :     ba set_request
214 :     set REQ_POLL_RETURN,TMPREG3 /* (delay slot) */
215 :    
216 :     /* pollh_resume:
217 :     * Resume execution at the point at which a poll event occurred.
218 :     */
219 :     ENTRY(pollh_resume)
220 :     set FUN_MASK,TMPREG4
221 :     ba set_request
222 :     set REQ_POLL_RESUME,TMPREG3 /* (delay slot) */
223 :    
224 :     ML_CODE_HDR(handle_a)
225 :     set EXN_MASK,TMPREG4
226 :     ba set_request
227 :     set REQ_EXN,TMPREG3 /* (delay slot) */
228 :    
229 :     ML_CODE_HDR(return_a)
230 :     set RET_MASK,TMPREG4
231 :     ba set_request
232 :     set REQ_RETURN,TMPREG3 /* (delay slot) */
233 :    
234 :     ENTRY(request_fault)
235 :     set EXN_MASK,TMPREG4
236 :     ba set_request
237 :     set REQ_FAULT,TMPREG3 /* (delay slot) */
238 :    
239 :     /* bind_cfun : (string * string) -> c_function
240 :     */
241 :     ML_CODE_HDR(bind_cfun_a)
242 :     CHECKLIMIT(FUN_MASK,bind_cfun_v_limit)
243 :     set FUN_MASK,TMPREG4
244 :     ba set_request
245 :     set REQ_BIND_CFUN,TMPREG3 /* (delay slot) */
246 :    
247 :     ML_CODE_HDR(build_literals_a)
248 :     CHECKLIMIT(FUN_MASK,build_literals_a_limit)
249 :     set FUN_MASK,TMPREG4
250 :     ba set_request
251 :     set REQ_BUILD_LITERALS,TMPREG3 /* (delay slot) */
252 :    
253 :     ML_CODE_HDR(callc_a)
254 :     CHECKLIMIT(FUN_MASK,callc_a_limit)
255 :     set FUN_MASK,TMPREG4
256 :     set REQ_CALLC,TMPREG3
257 :     /* fall through */
258 :    
259 :     set_request: /* a quick return to run_ml(). TMPREG3 holds */
260 :     /* the request code. */
261 :     ld [%sp+MLSTATE_OFFSET],TMPREG2 /* get MLState ptr from stack */
262 :     ld [TMPREG2+VProcOffMSP],TMPREG1 /* TMPREG1 := VProcPtr */
263 :     st TMPREG4,[TMPREG2+MaskOffMSP] /* save the register mask */
264 :     st %g0,[TMPREG1+InMLOffVSP] /* note that we have left ML code */
265 :     st ALLOCPTR,[TMPREG2+AllocPtrOffMSP]
266 :     st STOREPTR,[TMPREG2+StorePtrOffMSP]/* save storeptr */
267 :     st STDLINK,[TMPREG2+LinkRegOffMSP]
268 :     st STDLINK,[TMPREG2+PCOffMSP] /* PC of called function */
269 :     std STDARG,[TMPREG2+StdArgOffMSP] /* save STDARG, stdcont */
270 :     st STDCLOS,[TMPREG2+StdClosOffMSP] /* save closure */
271 :     st VARPTR,[TMPREG2+VarPtrOffMSP] /* save varptr */
272 :     st EXNCONT,[TMPREG2+ExnPtrOffMSP] /* save exncont */
273 :    
274 :     #if (CALLEESAVE > 0)
275 :     std MISCREG0,[TMPREG2+MiscRegOffMSP(0)]
276 :     #if (CALLEESAVE > 2)
277 :     std MISCREG2,[TMPREG2+MiscRegOffMSP(2)]
278 :     #if (CALLEESAVE > 4)
279 :     std MISCREG4,[TMPREG2+MiscRegOffMSP(4)]
280 :     #if (CALLEESAVE > 6)
281 :     std MISCREG6,[TMPREG2+MiscRegOffMSP(6)]
282 :     #if (CALLEESAVE > 8)
283 :     std MISCREG8,[TMPREG2+MiscRegOffMSP(8)]
284 :     #endif
285 :     #endif
286 :     #endif
287 :     #endif
288 :     #endif
289 :     ld [%sp+PSEUDOREG_OFFSET],%g6 /* save pseduo registers */
290 :     ld [%sp+PSEUDOREG_OFFSET+4],%g7
291 :     st %g6,[TMPREG2+PseudoReg1OffMSP]
292 :     st %g7,[TMPREG2+PseudoReg2OffMSP]
293 :     ldd [%sp+64],%g6 /* restore C registers %g6 & %g7.*/
294 :    
295 :     mov TMPREG3,%i0 /* return request code */
296 :     ret
297 :     restore /* restore C register window (delay slot) */
298 :    
299 :     ENTRY(saveregs)
300 :     ld [%sp+MLSTATE_OFFSET],TMPREG2 /* get MLState ptr from stack */
301 :     st TMPREG4,[TMPREG2+MaskOffMSP] /* save register mask */
302 :     #ifdef SOFT_POLL
303 :     /* free some regs */
304 :     std MISCREG0,[TMPREG2+MiscRegOffMSP(0)] /* save miscreg0,misreg1 */
305 :     #define p0 MISCREG0
306 :     #define p1 MISCREG1
307 :     #define pfreq TMPREG4
308 :     /* check if polling enabled (poll_freq > 0) */
309 :     set CSYM(_PollFreq0),pfreq
310 :     ld [pfreq+4],pfreq
311 :     srl pfreq,1,pfreq /* strip integer tag */
312 :     tst pfreq
313 :     be check_for_gc /* go check for real gc */
314 :     nop /* (delay slot) */
315 :     ld [TMPREG2+InPollHandlerOffMSP],p0 /* if we're in the handler */
316 :     tst p0
317 :     bne reset_limit /* ignore poll events */
318 :     nop /* (delay slot) */
319 :     set CSYM(_PollEvent0),p0 /* load contents of ref */
320 :     ld [p0+4],p0
321 :     srl p0,1,p0
322 :     tst p0
323 :     be reset_limit
324 :     nop /* (delay slot) */
325 :     /* event occurred, so set ml_pollHandlerPending */
326 :     set 1,p0
327 :     st p0,[TMPREG2+PollPendingOffMSP]
328 :     ba do_gc /* and handle event in the C runtime */
329 :    
330 :     reset_limit: /* reset limit ptr */
331 :     sll pfreq,POLL_GRAIN_BITS,pfreq /* mult by POLL_GRAIN_CPSI */
332 :     add pfreq,ALLOCPTR,LIMITPTR /* overflow handled below */
333 :    
334 :     check_for_gc:
335 :     /* ensure real limit is >= limit */
336 :     ld [TMPREG2+RealLimitOffMSP],p0
337 :     sub p0,LIMITPTR,p1
338 :     tst p1
339 :     bge ok_limit
340 :     nop /* (delay slot) */
341 :     mov p0,LIMITPTR
342 :     ok_limit:
343 :     add p0,-4096,LIMITPTR
344 :     /* cmp p0,ALLOCPTR */
345 :     cmp LIMITPTR,ALLOCPTR
346 :     ble do_gc /* gc *//* should be a common case */
347 :     nop /* (delay slot) */
348 :     /* since a signal also sets limitptr == allocptr to force a trap, */
349 :     /* we need to disambiguate poll-events/signals here */
350 :     #undef pfreq
351 :     #define vsp TMPREG4
352 :     ld [TMPREG2+VProcOffMSP],vsp
353 :     ld [TMPREG2+PollPendingOffMSP],p0
354 :     ld [vsp+NPendingOffVSP],p1
355 :     add p0,p1,p0
356 :     ld [vsp+NPendingSysOffVSP],p1
357 :     add p0,p1,p0
358 :     tst p0
359 :     bne do_gc
360 :     nop /* (delay slot) */
361 :    
362 :     no_gc: /* an uneventful poll check, back to ML */
363 :     ldd [TMPREG2+MiscRegOffMSP(0)],MISCREG0 /* reload miscregs */
364 :     jmp GCLINK
365 :     subcc ALLOCPTR,LIMITPTR,%g0 /* Heap limit test (delay slot) */
366 :    
367 :     do_gc:
368 :     st LIMITPTR,[TMPREG2+LimitPtrOffMSP]
369 :    
370 :     #undef vsp
371 :     #undef p0
372 :     #undef p1
373 :     #endif /* SOFT_POLL */
374 :    
375 :     ld [TMPREG2+VProcOffMSP],TMPREG1 /* TMPREG1 := VProcPtr */
376 :     st %g0,[TMPREG1+InMLOffVSP] /* note that we have left ML code */
377 :     st GCLINK,[TMPREG2+PCOffMSP] /* resume pc */
378 :     add BASEPTR,-4096,BASEPTR /* adjust the base code ptr (sub 4096) */
379 :     st ALLOCPTR,[TMPREG2+AllocPtrOffMSP] /* save allocptr */
380 :     st STOREPTR,[TMPREG2+StorePtrOffMSP] /* save storeptr */
381 :     std STDARG,[TMPREG2+StdArgOffMSP] /* save STDARG, stdcont */
382 :     std STDCLOS,[TMPREG2+StdClosOffMSP] /* save stdclos, baseptr */
383 :     st VARPTR,[TMPREG2+VarPtrOffMSP]
384 :     st STDLINK,[TMPREG2+LinkRegOffMSP]
385 :     st EXNCONT,[TMPREG2+ExnPtrOffMSP]
386 :     #ifndef SOFT_POLL /* miscreg0 & miscreg1 saved above for SOFT_POLL */
387 :     std MISCREG0,[TMPREG2+MiscRegOffMSP(0)]
388 :     #endif
389 :     std MISCREG2,[TMPREG2+MiscRegOffMSP(2)]
390 :     std MISCREG4,[TMPREG2+MiscRegOffMSP(4)]
391 :     std MISCREG6,[TMPREG2+MiscRegOffMSP(6)]
392 :     std MISCREG8,[TMPREG2+MiscRegOffMSP(8)]
393 :     std MISCREG10,[TMPREG2+MiscRegOffMSP(10)]
394 :     st MISCREG12,[TMPREG2+MiscRegOffMSP(12)]
395 :     ld [%sp+PSEUDOREG_OFFSET],%g6 /* save pseduo registers */
396 :     ld [%sp+PSEUDOREG_OFFSET+4],%g7
397 :     st %g6,[TMPREG2+PseudoReg1OffMSP]
398 :     st %g7,[TMPREG2+PseudoReg2OffMSP]
399 :     ldd [%sp+64],%g6 /* restore C registers %g6 & %g7. */
400 :     set REQ_GC,%i0 /* request GC */
401 :     ret
402 :     restore /* restore C register window (delay slot) */
403 :    
404 :     ENTRY(restoreregs)
405 :     save %sp,-SA(ML_FRAMESIZE),%sp
406 :     st %i0,[%sp+MLSTATE_OFFSET] /* save MLState ptr on stack */
407 :     set CSYM(saveregs),TMPREG2
408 :     st TMPREG2,[%sp+STARTGC_OFFSET]
409 :     mov %i0,TMPREG2 /* transfer MLState ptr to tmpreg2 */
410 :     std ALLOCPTR,[%sp+64] /* save C registers %g6 & %g7 */
411 :     set _ml_mul,TMPREG1 /* set pointer to ml_mul */
412 :     st TMPREG1,[%sp+MUL_OFFSET]
413 :     set _ml_div,TMPREG1 /* set pointer to ml_div */
414 :     st TMPREG1,[%sp+DIV_OFFSET]
415 :     set _ml_umul,TMPREG1 /* set pointer to ml_umul */
416 :     st TMPREG1,[%sp+UMUL_OFFSET]
417 :     set _ml_udiv,TMPREG1 /* set pointer to ml_udiv */
418 :     st TMPREG1,[%sp+UDIV_OFFSET]
419 :     ld [TMPREG2+AllocPtrOffMSP],ALLOCPTR
420 :     ld [TMPREG2+LimitPtrOffMSP],LIMITPTR
421 :     ld [TMPREG2+StorePtrOffMSP],STOREPTR
422 :     ld [TMPREG2+PCOffMSP],GCLINK
423 :     ldd [TMPREG2+StdArgOffMSP],STDARG /* stdarg and stdcont */
424 :     ldd [TMPREG2+StdClosOffMSP],STDCLOS /* stdclos and baseptr */
425 :     ld [TMPREG2+VarPtrOffMSP],VARPTR
426 :     ld [TMPREG2+LinkRegOffMSP],STDLINK
427 :     ld [TMPREG2+ExnPtrOffMSP],EXNCONT /* restore exnptr */
428 :     ld [TMPREG2+PseudoReg1OffMSP],MISCREG2 /* save pseduo registers */
429 :     ld [TMPREG2+PseudoReg2OffMSP],MISCREG3
430 :     st MISCREG2,[%sp+PSEUDOREG_OFFSET]
431 :     st MISCREG3,[%sp+PSEUDOREG_OFFSET+4]
432 :     ldd [TMPREG2+MiscRegOffMSP(0)],MISCREG0
433 :     ldd [TMPREG2+MiscRegOffMSP(2)],MISCREG2
434 :     ldd [TMPREG2+MiscRegOffMSP(4)],MISCREG4
435 :     ldd [TMPREG2+MiscRegOffMSP(6)],MISCREG6
436 :     ldd [TMPREG2+MiscRegOffMSP(8)],MISCREG8
437 :     ldd [TMPREG2+MiscRegOffMSP(10)],MISCREG10
438 :     ld [TMPREG2+MiscRegOffMSP(12)],MISCREG12
439 :    
440 :     sub BASEPTR,-4096,BASEPTR /* adjust the base code ptr (add 4096) */
441 :     ld [TMPREG2+VProcOffMSP],TMPREG1 /* TMPREG1 := VProcPtr */
442 :     set 1,TMPREG2 /* note that we have entered ML code */
443 :     st TMPREG2,[TMPREG1+InMLOffVSP]
444 :     ld [TMPREG1+NPendingSysOffVSP],TMPREG2 /* check for pending signals */
445 :     ld [TMPREG1+NPendingOffVSP],TMPREG3
446 :     addcc TMPREG2,TMPREG3,%g0
447 :     bne pending_sigs
448 :     nop
449 :     CSYM(ml_go): /* invoke the ML code */
450 :     jmp GCLINK
451 :     subcc ALLOCPTR,LIMITPTR,%g0 /* Heap limit test (delay slot) */
452 :    
453 :     pending_sigs: /* there are pending signals */
454 :     /* check if we are currently handling a signal */
455 :     ld [TMPREG1+InSigHandlerOffVSP],TMPREG2
456 :     tst TMPREG2
457 :     bne CSYM(ml_go)
458 :     set 1,TMPREG2 /* (delay slot) */
459 :     /* note that a handler trap is pending */
460 :     st TMPREG2,[TMPREG1+HandlerPendingOffVSP]
461 :     ba CSYM(ml_go)
462 :     mov ALLOCPTR,LIMITPTR /* (delay slot) */
463 :    
464 :    
465 :     #if defined(OPSYS_SUNOS) || defined(OPSYS_NEXTSTEP)
466 :     /* ZeroLimitPtr:
467 :     *
468 :     * Zero the heap limit pointer so that a trap will be generated on the next limit
469 :     * check and then continue executing ML code.
470 :     * NOTE: this code cannot trash any registers (other than limitptr) or the condition
471 :     * code. To achieve this we work inside a new register window.
472 :     * Also note that this code is not needed under SOLARIS 2.x, since we can
473 :     * directly change the register from C.
474 :     */
475 :     TEXT
476 :     ENTRY(ZeroLimitPtr)
477 :     save %sp,-SA(WINDOWSIZE),%sp
478 :     sethi %hi(CSYM(SavedPC)),%l1
479 :     ld [%l1+%lo(CSYM(SavedPC))],%o0
480 :     set 0,LIMITPTR
481 :     jmp %o0
482 :     restore /* (delay slot) */
483 :     #endif /* OPSYS_SUNOS */
484 :    
485 :    
486 :     /* array : (int * 'a) -> 'a array
487 :     * Allocate and initialize a new array. This can cause GC.
488 :     */
489 :     ML_CODE_HDR(array_a)
490 :     CHECKLIMIT(FUN_MASK,array_a_limit)
491 :     ld [STDARG],TMPREG1 /* tmp1 = length in words */
492 :     sra TMPREG1,1,TMPREG1 /* convert to sparc int */
493 :     cmp TMPREG1,SMALL_OBJ_SZW /* is this a small object? */
494 :     bgt 3f
495 :     nop
496 :     ld [STDARG+4],TMPREG3 /* tmp3 = initial value */
497 :     sll TMPREG1,TAG_SHIFTW,TMPREG2 /* build descriptor in TMPREG2 */
498 :     or TMPREG2,MAKE_TAG(DTAG_array),TMPREG2
499 :     st TMPREG2,[ALLOCPTR] /* store the descriptor */
500 :     inc 4,ALLOCPTR /* allocptr++ */
501 :     mov ALLOCPTR,STDARG /* result = object addr. */
502 :     1:
503 :     st TMPREG3,[ALLOCPTR]
504 :     deccc 1,TMPREG1 /* if (--length > 0) */
505 :     bgt 1b /* then continue */
506 :     inc 4,ALLOCPTR /* allocptr++ (delay slot) */
507 :     /* end loop */
508 :     CONTINUE
509 :    
510 :     3: /* here we do off-line allocation for big arrays */
511 :     set FUN_MASK,TMPREG4
512 :     ba set_request
513 :     set REQ_ALLOC_ARRAY,TMPREG3 /* (delayslot) */
514 :    
515 :     /* create_r : int -> realarray
516 :     * Create a new realarray.
517 :     */
518 :     ML_CODE_HDR(create_r_a)
519 :     CHECKLIMIT(FUN_MASK,create_r_a_limit)
520 :     sra STDARG,1,TMPREG2 /* tmp2 = length (untagged int) */
521 :     sll TMPREG2,2,TMPREG3 /* tmpreg3 = length in words */
522 :     cmp TMPREG3,SMALL_OBJ_SZW /* is this a small object? */
523 :     bgt 1f
524 :     nop
525 :     sll TMPREG2,TAG_SHIFTW,TMPREG1 /* build descriptor in tmpreg1 */
526 :     or TMPREG1,MAKE_TAG(DTAG_realdarray),TMPREG1
527 :     #ifdef ALIGN_REALDS
528 :     or ALLOCPTR,0x4,ALLOCPTR /* desc is unaliged */
529 :     #endif
530 :     st TMPREG1,[ALLOCPTR] /* store the descriptor */
531 :     inc 4,ALLOCPTR /* allocptr++ */
532 :     mov ALLOCPTR,STDARG /* stdarg = realarray */
533 :     sll TMPREG3,2,TMPREG3 /* tmpreg3 = length (in bytes) */
534 :     add ALLOCPTR,TMPREG3,ALLOCPTR /* ALLOCPTR += length */
535 :     CONTINUE
536 :    
537 :     1: /* off-line allocation of big realarrays */
538 :     set FUN_MASK,TMPREG4
539 :     ba set_request
540 :     set REQ_ALLOC_REALDARRAY,TMPREG3 /* (delayslot) */
541 :    
542 :     /* create_b : int -> bytearray
543 :     * Create a bytearray of the given length.
544 :     */
545 :     ML_CODE_HDR(create_b_a)
546 :     CHECKLIMIT(FUN_MASK,create_b_a_limit)
547 :     sra STDARG,1,TMPREG2 /* tmpreg2 = length (sparc int) */
548 :     add TMPREG2,3,TMPREG3 /* tmpreg3 = length in words */
549 :     sra TMPREG3,2,TMPREG3
550 :     cmp TMPREG3,SMALL_OBJ_SZW /* is this a small object? */
551 :     bgt 1f
552 :     nop
553 :     sll TMPREG2,TAG_SHIFTW,TMPREG1 /* tmpreg1 is descriptor */
554 :     or TMPREG1,MAKE_TAG(DTAG_bytearray),TMPREG1
555 :     st TMPREG1,[ALLOCPTR] /* store the tag */
556 :     inc 4,ALLOCPTR /* allocptr++ */
557 :     sll TMPREG3,2,TMPREG2 /* tmpreg2 = length in bytes (no tag) */
558 :     mov ALLOCPTR,STDARG /* result = object addr */
559 :     add ALLOCPTR,TMPREG2,ALLOCPTR /* allocptr += length */
560 :     CONTINUE
561 :    
562 :     1: /* here we do off-line allocation for big bytearrays */
563 :     set FUN_MASK,TMPREG4
564 :     ba set_request
565 :     set REQ_ALLOC_BYTEARRAY,TMPREG3 /* (delayslot) */
566 :    
567 :     /* create_s : int -> string
568 :     * Create a string of the given length.
569 :     */
570 :     ML_CODE_HDR(create_s_a)
571 :     CHECKLIMIT(FUN_MASK,create_s_a_limit)
572 :     sra STDARG,1,TMPREG2 /* tmpreg2 = length (sparc int) */
573 :     add TMPREG2,4,TMPREG3 /* tmpreg3 = length in words */
574 :     sra TMPREG3,2,TMPREG3
575 :     cmp TMPREG3,SMALL_OBJ_SZW /* is this a small object? */
576 :     bgt 1f
577 :     nop
578 :     sll TMPREG2,TAG_SHIFTW,TMPREG1 /* tmpreg1 is descriptor */
579 :     or TMPREG1,MAKE_TAG(DTAG_string),TMPREG1
580 :     st TMPREG1,[ALLOCPTR] /* store the tag */
581 :     inc 4,ALLOCPTR /* allocptr++ */
582 :     sll TMPREG3,2,TMPREG2 /* tmpreg2 = length in bytes (no tag) */
583 :     mov ALLOCPTR,STDARG /* result = object addr */
584 :     add ALLOCPTR,TMPREG2,ALLOCPTR /* allocptr += length */
585 :     st ZERO,[ALLOCPTR-4] /* store 0 in last word */
586 :     CONTINUE
587 :    
588 :     1: /* here we do off-line allocation for big strings */
589 :     set FUN_MASK,TMPREG4
590 :     ba set_request
591 :     set REQ_ALLOC_STRING,TMPREG3 /* (delayslot) */
592 :    
593 :     /* create_v_a : (int * 'a list) -> 'a vector
594 :     * Create a vector with elements taken from a list.
595 :     * NOTE: the front-end ensures that list cannot be nil.
596 :     */
597 :     ML_CODE_HDR(create_v_a)
598 :     CHECKLIMIT(FUN_MASK,create_v_a_limit)
599 :     ld [STDARG],TMPREG1 /* tmpreg1 = length (tagged int) */
600 :     sra TMPREG1,1,TMPREG1 /* tmpreg1 = length (untagged int) */
601 :     cmp TMPREG1,SMALL_OBJ_SZW /* is this a small object? */
602 :     bgt 1f
603 :     nop
604 :     sll TMPREG1,TAG_SHIFTW,TMPREG2 /* build descriptor in tmpreg2 */
605 :     or TMPREG2,MAKE_TAG(DTAG_vector),TMPREG2
606 :     st TMPREG2,[ALLOCPTR] /* store descriptor */
607 :     inc 4,ALLOCPTR /* allocptr++ */
608 :     ld [STDARG+4],TMPREG2 /* tmpreg2 := list */
609 :     mov ALLOCPTR,STDARG /* stdarg := vector */
610 :     2: /* loop */
611 :     ld [TMPREG2],TMPREG1 /* tmpreg1 = hd(tmpreg2) */
612 :     ld [TMPREG2+4],TMPREG2 /* tmpreg2 = tl(tmpreg2) */
613 :     st TMPREG1,[ALLOCPTR] /* store element */
614 :     cmp TMPREG2,ML_nil /* if (tmpreg2 <> nil) goto loop */
615 :     bne 2b
616 :     inc 4,ALLOCPTR /* allocptr++ (delay slot) */
617 :     /* end loop */
618 :     CONTINUE
619 :    
620 :     1: /* off-line allocation of big vectors */
621 :     set FUN_MASK,TMPREG4
622 :     ba set_request
623 :     set REQ_ALLOC_VECTOR,TMPREG3 /* (delayslot) */
624 :    
625 :    
626 :     /* floor : real -> int
627 :     * Return the floor of the argument or else raise Float("floor") if out of range.
628 :     * We implement the range check by using an integer comparison with the high 32
629 :     * bits of the real value (which contains the biased exponent).
630 :     * (double)(2^30) == [0x41d00000, 0x0]
631 :     * (double)(-2^30) == [0xc1d00000, 0x0]
632 :     */
633 :     ML_CODE_HDR(floor_a)
634 :     ld [STDARG],%f0 /* fetch arg into %f0, %f1. */
635 :     ld [STDARG+4],%f1
636 :     ld [STDARG],TMPREG2 /* tmpreg2 gets high word. */
637 :     tst TMPREG2 /* negative ? */
638 :     blt 1f
639 :     nop
640 :     /* handle positive case */
641 :     set 0x41d00000,TMPREG3 /* tmpreg3 = 2^30 */
642 :     cmp TMPREG2,TMPREG3 /* if tmpreg2 >= 2^30 then range error */
643 :     bge out_of_range
644 :     nop
645 :     fdtoi %f0,%f2 /* cvt to int (round towards 0) */
646 :     st %f2,[%sp+FLOOR_OFFSET]
647 :     ld [%sp+FLOOR_OFFSET],TMPREG2 /* tmpreg2 gets int result (via stack temp). */
648 :     ba 2f
649 :     nop
650 :     1: /* handle negative case. */
651 :     set 0xc1d00000,TMPREG3 /* tmpreg3 = -2^30 */
652 :     cmp TMPREG2,TMPREG3 /* if tmpreg2 < -2^30 then range error */
653 :     bge out_of_range /* not bl because of sign. */
654 :     nop
655 :     fdtoi %f0,%f2 /* cvt to int (round towards 0) */
656 :     st %f2,[%sp+FLOOR_OFFSET]
657 :     fitod %f2,%f4 /* cvt back to real to check for fraction */
658 :     fcmpd %f0,%f4 /* same value? */
659 :     ld [%sp+FLOOR_OFFSET],TMPREG2 /* tmpreg2 gets int result (via stack temp). */
660 :     fbe 2f /* check result of fcmpd */
661 :     nop
662 :     dec TMPREG2 /* push one lower */
663 :     2: /* cvt result to ML int, and continue */
664 :     add TMPREG2,TMPREG2,TMPREG2
665 :     add TMPREG2,1,STDARG
666 :     CONTINUE
667 :    
668 :     out_of_range: /* out of range */
669 :     t ST_INT_OVERFLOW /* generate an Overflow exn. We do this */
670 :     /* via a trap to produce a SIGOVFL */
671 :    
672 :    
673 :     /* logb : real -> int
674 :     * Extract and unbias the exponent.
675 :     * The IEEE bias is 1023.
676 :     */
677 :     ML_CODE_HDR(logb_a)
678 :     ld [STDARG],TMPREG2 /* extract exponent. */
679 :     srl TMPREG2,19,TMPREG2
680 :     and TMPREG2,2047*2,TMPREG2 /* unbias and cvt to ML int. */
681 :     sub TMPREG2,2045,STDARG /* 2(n-1023)+1 == 2n-2045. */
682 :     CONTINUE
683 :    
684 :    
685 :     /* scalb : (real * int) -> real
686 :     * Scale the first argument by 2 raised to the second argument. Raise
687 :     * Float("underflow") or Float("overflow") as appropriate.
688 :     */
689 :     ML_CODE_HDR(scalb_a)
690 :     CHECKLIMIT(FUN_MASK,scalb_a_limit)
691 :     ld [STDARG+4],TMPREG1 /* tmpreg1 gets scale (second arg) */
692 :     sra TMPREG1,1,TMPREG1 /* cvt scale to sparc int */
693 :     ld [STDARG],STDARG /* stdarg gets real (first arg) */
694 :     ld [STDARG],TMPREG4 /* tmpreg4 gets high word of real value. */
695 :     set 0x7ff00000,TMPREG2 /* tmpreg2 gets exponent mask. */
696 :     andcc TMPREG4,TMPREG2,TMPREG3 /* extract exponent into tmpreg3. */
697 :     be 1f /* if 0 then return same */
698 :     nop
699 :     srl TMPREG3,20,TMPREG3 /* cvt exp to int (delay slot). */
700 :     addcc TMPREG3,TMPREG1,TMPREG1 /* tmpreg1 = exp + scale */
701 :     ble under /* if new exp <= 0 then underflow */
702 :     nop
703 :     cmp TMPREG1,2047 /* if new exp >= 2047 then overflow */
704 :     bge over
705 :     nop
706 :     andn TMPREG4,TMPREG2,TMPREG4 /* mask out old exponent. */
707 :     sll TMPREG1,20,TMPREG1 /* shift new exp to exponent position. */
708 :     or TMPREG4,TMPREG1,TMPREG4 /* set new exponent. */
709 :     ld [STDARG+4],TMPREG1 /* tmpreg1 gets low word of real value. */
710 :     7:
711 :     #ifdef ALIGN_REALDS
712 :     or ALLOCPTR,0x4,ALLOCPTR /* desc is unaliged */
713 :     #endif
714 :     st TMPREG4,[ALLOCPTR+4] /* allocate the new real value */
715 :     st TMPREG1,[ALLOCPTR+8]
716 :     set DESC_reald,TMPREG1
717 :     st TMPREG1,[ALLOCPTR]
718 :     add ALLOCPTR,4,STDARG /* set result. */
719 :     inc 12,ALLOCPTR /* allocptr += 3 */
720 :     1: CONTINUE
721 :    
722 :     over: /* handle overflow */
723 :     t ST_INT_OVERFLOW /* generate an Overflow exn. We do this */
724 :     /* never get here */ /* via a trap to produce a SIGOVFL */
725 :    
726 :     under: /* handle underflow */
727 :     set 0,TMPREG4
728 :     set 0,TMPREG1
729 :     ba 7b
730 :     nop
731 :    
732 :     /** Integer multiplication and division routines **/
733 :     .global .mul, .div, .umul, .udiv
734 :    
735 :     /* ml_mul:
736 :     * multiply %o2 by %o3, returning the result in %o2
737 :     * Note: this code assumes that .mul doesn't trash any global or input
738 :     * registers.
739 :     */
740 :     _ml_mul:
741 :     save %sp,-SA(WINDOWSIZE),%sp
742 :     /** NOTE: if %g1, %g2, %g3 are not callee save, then this can be avoided **/
743 :     /** NOTE: .mul doesn't use %g2, %g3, but the dynamic linking initialization
744 :     ** does.
745 :     **/
746 :     mov %g1,%l1 /* save %g1 which may get trashed */
747 :     mov %g2,%l2
748 :     mov %g3,%l3
749 :     mov %i2,%o0
750 :     call .mul
751 :     mov %i3,%o1 /* (delay slot) */
752 :     mov %l1,%g1 /* restore %g1 */
753 :     mov %l2,%g2
754 :     mov %l3,%g3
755 :     bnz 1f /* if z is clear, then overflow */
756 :     restore %o0,0,%o2 /* result in %o2 (delay slot) */
757 :     retl
758 :     nop
759 :     1: /* handle overflow. */
760 :     t ST_INT_OVERFLOW /* generate an Overflow exn. We do this */
761 :     /* via a trap to produce a SIGOVFL */
762 :    
763 :     /* ml_div:
764 :     * divide %o2 by %o3, returning the result in %o2.
765 :     * Note: .div uses %g1, %g2 and %g3, so we must save them. We do this using the
766 :     * locals of the new window, since .div is a leaf routine.
767 :     */
768 :     _ml_div:
769 :     save %sp,-SA(WINDOWSIZE),%sp
770 :     addcc %i3,%g0,%o1 /* %o1 is divisor (and check for zero) */
771 :     bz 1f
772 :     /* save %g1, %g2 and %g3 (using new window) */
773 :     /** NOTE: if %g1, %g2, %g3 are not callee save, then this can be avoided **/
774 :     mov %g1,%l1 /* (delay slot) */
775 :     mov %g2,%l2
776 :     mov %g3,%l3
777 :     call .div
778 :     mov %i2,%o0 /* (delay slot) */
779 :     /* restore %g1, %g2 and %g3 */
780 :     mov %l3,%g3
781 :     mov %l2,%g2
782 :     mov %l1,%g1
783 :     ret
784 :     restore %o0,0,%o2 /* result in %o2 (delay slot) */
785 :     1: /* handle zero divide */
786 :     restore /* restore ML window */
787 :     t ST_DIV0 /* generate a Div exn. We do this via a */
788 :     /* trap to produce a SIGDIV */
789 :    
790 :     /* ml_umul:
791 :     * multiply %o2 by %o3 (unsigned), returning the result in %o2. This does
792 :     * raise Overflow.
793 :     * Note: this code assumes that .mul doesn't trash any global or input
794 :     * registers.
795 :     */
796 :     _ml_umul:
797 :     save %sp,-SA(WINDOWSIZE),%sp
798 :     /** NOTE: if %g1, %g2, %g3 are not callee save, then this can be avoided **/
799 :     /** NOTE: .mul doesn't use %g2, %g3, but the dynamic linking initialization
800 :     ** does.
801 :     **/
802 :     mov %g1,%l1 /* save %g1 which may get trashed */
803 :     mov %g2,%l2
804 :     mov %g3,%l3
805 :     mov %i2,%o0
806 :     call .umul
807 :     mov %i3,%o1 /* (delay slot) */
808 :     mov %l1,%g1 /* restore %g1 */
809 :     mov %l2,%g2
810 :     mov %l3,%g3
811 :     ret
812 :     restore %o0,0,%o2 /* result in %o2 (delay slot) */
813 :    
814 :    
815 :     /* ml_udiv:
816 :     * divide %o2 by %o3 (unsigned), returning the result in %o2.
817 :     * Note: .udiv uses %g1, %g2 and %g3, so we must save them. We do this using the
818 :     * locals of the new window, since .div is a leaf routine.
819 :     */
820 :     _ml_udiv:
821 :     save %sp,-SA(WINDOWSIZE),%sp
822 :     addcc %i3,%g0,%o1 /* %o1 is divisor (and check for zero) */
823 :     bz 1f
824 :     /* save %g1, %g2 and %g3 (using new window) */
825 :     /** NOTE: if %g1, %g2, %g3 are not callee save, then this can be avoided **/
826 :     mov %g1,%l1 /* (delay slot) */
827 :     mov %g2,%l2
828 :     mov %g3,%l3
829 :     call .udiv
830 :     mov %i2,%o0 /* (delay slot) */
831 :     /* restore %g1, %g2 and %g3 */
832 :     mov %l3,%g3
833 :     mov %l2,%g2
834 :     mov %l1,%g1
835 :     ret
836 :     restore %o0,0,%o2 /* result in %o2 (delay slot) */
837 :     1: /* handle zero divide */
838 :     restore /* restore ML window */
839 :     t ST_DIV0 /* generate a Div exn. We do this via a */
840 :     /* trap to produce a SIGDIV */
841 :    
842 :    
843 :     /* try_lock : spin_lock -> bool
844 :     * low-level test-and-set style primitive for mutual-exclusion among
845 :     * processors.
846 :     */
847 :     ML_CODE_HDR(try_lock_a)
848 :     #if (MAX_PROCS > 1)
849 :     ???
850 :     #else (MAX_PROCS == 1)
851 :     ld [STDARG],TMPREG1 /* load previous value into tmpreg1 */
852 :     set ML_false,TMPREG2 /* ML_false */
853 :     st TMPREG2,[STDARG] /* store ML_false into the lock */
854 :     mov TMPREG1,STDARG /* return previous value of lock */
855 :     CONTINUE
856 :     #endif
857 :    
858 :     /* unlock : releases a spin lock
859 :     */
860 :     ML_CODE_HDR(unlock_a)
861 :     #if (MAX_PROCS > 1)
862 :     ???
863 :     #else (MAX_PROCS == 1)
864 :     set ML_true,TMPREG1 /* store ML_true ... */
865 :     st TMPREG1,[STDARG] /* into the lock */
866 :     set ML_unit,STDARG /* return unit */
867 :     CONTINUE
868 :     #endif
869 :    
870 :    
871 :     /* SetFSR:
872 :     * Load the floating-point status register with the given word.
873 :     */
874 :     ENTRY(SetFSR)
875 :     set fsrtmp,%o1
876 :     st %o0,[%o1]
877 :     retl
878 :     ld [%o1],%fsr /* (delay slot) */
879 :     DATA
880 :     fsrtmp: .word 0
881 :     TEXT
882 :    
883 :    
884 :     /* void FlushICache (char *addr, int nbytes)
885 :     */
886 :     ENTRY(FlushICache)
887 :     and %o1,0x1F,%o2 /* m <- (nbytes % (32-1)) >> 2 (use %o2 for m) */
888 :     srl %o2,2,%o2
889 :     srl %o1,5,%o1 /* i <- (nbytes >> 5) */
890 :     /* FLUSH4 implements: if (m > 0) { FLUSH addr; addr += 4; m--;} else goto L_test */
891 :     #define FLUSH4 \
892 :     tst %o2; \
893 :     ble L_test; \
894 :     nop; \
895 :     iflush %o0; \
896 :     inc 4,%o0; \
897 :     dec 1,%o2
898 :     FLUSH4
899 :     FLUSH4
900 :     FLUSH4
901 :     FLUSH4
902 :     FLUSH4
903 :     FLUSH4
904 :     FLUSH4
905 :     /* addr is 32-byte aligned here */
906 :     L_test:
907 :     tst %o1
908 :     be L_exit
909 :     nop
910 :     L_loop: /* flush 32 bytes per iteration */
911 :     iflush %o0
912 :     iflush %o0+8
913 :     iflush %o0+16
914 :     iflush %o0+24
915 :     deccc 1,%o1 /* if (--i > 0) goto L_loop */
916 :     bg L_loop
917 :     inc 32,%o0 /* addr += 32 (delay slot) */
918 :     L_exit:
919 :     retl
920 :     nop

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0