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/MIPS.prim.asm
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (view) (download)

1 : monnier 2 /* MIPS.prim.asm
2 :     *
3 :     * COPYRIGHT (c) 1992 by AT&T Bell Laboratories.
4 :     */
5 :    
6 :     #define _MIPS_SIM 1 /* IRIX 5.x needs this in <regdef.h> */
7 :    
8 :     #ifndef OPSYS_MACH
9 :     #include <regdef.h>
10 :     #endif
11 :    
12 :     #include "ml-base.h"
13 :     #include "asm-base.h"
14 :     #include "ml-values.h"
15 :     #include "tags.h"
16 :     #include "ml-request.h"
17 :     #include "reg-mask.h"
18 :     #include "ml-limits.h"
19 :     #include "mlstate-offsets.h" /** this file is generated **/
20 :    
21 :     /* MIPS runtime code for ML. The MIPS registers are used as follows; the names
22 :     * in parentheses are the MLState field names (see ml_state.h):
23 :     *
24 :     * register C callee ML use
25 :     * save?
26 :     * -------- --------- -------
27 :     * $1 no assembler temporary
28 :     * $2 no standard arg
29 :     * $3 no standard continuation
30 :     * $4 no standard closure
31 :     * $5 no standard link register
32 :     * $6-$15 no miscellaneous registers
33 :     * $16-$18 yes miscellaneous registers
34 :     * $19 yes heap limit pointer
35 :     * $20 yes var pointer
36 :     * $21 yes heap-limit comparison flag, and arith temporary
37 :     * $22 yes store list pointer
38 :     * $23 yes allocation pointer
39 :     * $24 no base address register
40 :     * $25 - internal temporary (ptrtmp)
41 :     * $26 - reserved for operating system
42 :     * $27 - reserved for operating system
43 :     * $28 - reserved for C (global pointer)
44 :     * $29 - reserved for C (stack pointer)
45 :     * $30 yes exception continuation
46 :     * $31 no gc link register
47 :     */
48 :     /* assembler-temp $1 */
49 :     #define stdarg $2 /* standard arg (ml_arg) */
50 :     #define stdcont $3 /* standard continuation (ml_cont) */
51 :     #define stdclos $4 /* standard closure (ml_closure) */
52 :     #define stdlink $5 /* ptr to just-entered std function (ml_link) */
53 :     #define miscreg0 $6 /* miscellaneous registers, 0..12 (ml_roots[]) */
54 :     #define miscreg1 $7
55 :     #define miscreg2 $8
56 :     #define miscreg3 $9
57 :     #define miscreg4 $10
58 :     #define miscreg5 $11
59 :     #define miscreg6 $12
60 :     #define miscreg7 $13
61 :     #define miscreg8 $14
62 :     #define miscreg9 $15
63 :     #define miscreg10 $16
64 :     #define miscreg11 $17
65 :     #define miscreg12 $18
66 :     #define limit $19 /* end of heap - 4096 (ml_limitptr) */
67 :     #define varptr $20 /* per-thread var pointer (ml_varptr) */
68 :     #define exhausted $21 /* arith temp; also, heap-limit comparison flag */
69 :     #define storeptr $22 /* store pointer (ml_storeptr) */
70 :     #define allocptr $23 /* freespace pointer (ml_allocptr) */
71 :     #define basereg $24 /* pointer to base of code object+32764 (ml_roots[]) */
72 :     #define ptrtmp $25 /* internal temporary */
73 :     /* $26 reserved for operating system */
74 :     /* $27 reserved for operating system */
75 :     /* globalptr $28 reserved for C and assembler */
76 :     /* stackptr $29 stack pointer */
77 :     #define exncont $30 /* exception handler (ml_exncont) */
78 :     #define gclink $31 /* resumption point for restoreregs (ml_pc) */
79 :    
80 :     #define atmp1 miscreg9
81 :     #define atmp2 miscreg10
82 :     #define atmp3 miscreg11
83 :     #define atmp4 miscreg12
84 :    
85 :     /** register names for polling **/
86 :     #define pfreq exhausted
87 :     #define pevent miscreg0
88 :     #define ptmp miscreg1
89 :    
90 :     #define cresult $2
91 :     #define carg0 $4
92 :     #define carg1 $5
93 :    
94 :     /* The root registers in the ML state vector have the following layout,
95 :     * where roots is guaranteed to be 8-byte aligned relative to the start
96 :     * of the ML state vector (see "ml-state.h" and "mlstate-offsets.h"):
97 :     *
98 :     * +-------------------+
99 :     * roots: | ml_arg ($2) |
100 :     * +-------------------+
101 :     * roots+4: | ml_cont ($3) |
102 :     * +-------------------+
103 :     * roots+8: | ml_closure ($4) |
104 :     * +-------------------+
105 :     * roots+12: | ml_exncont ($30) |
106 :     * +-------------------+
107 :     * roots+16: | ml_pc |
108 :     * +-------------------+
109 :     * roots+20: | ml_linkReg (%5) |
110 :     * +-------------------+
111 :     * roots+24: | ($6-$18) |
112 :     * +-------------------+
113 :     * roots+76: | ml_varReg ($20) |
114 :     * +-------------------+
115 :     * roots+48: | ml_baseReg ($24) |
116 :     * +-------------------+
117 :     */
118 :    
119 :    
120 :     /* The ML stack frame has the following layout (set up by restoreregs):
121 :     * NOTE: this is backwards from the MIPS convention, the register save
122 :     * area should be below the locals!!!
123 :     *
124 :     * NOTE: the offset info for pseudo regs and saveregs is used in
125 :     * mips/mips.sml
126 :     *
127 :     * +-------------------+
128 :     * sp+60: | saved $31 |
129 :     * +-------------------+
130 :     * sp+56: | saved $30 |
131 :     * +-------------------+
132 :     * sp+52: | saved $23 |
133 :     * +-------------------+
134 :     * sp+48: | saved $22 |
135 :     * +-------------------+
136 :     * sp+44: | saved $21 |
137 :     * +-------------------+
138 :     * sp+40: | saved $20 |
139 :     * +-------------------+
140 :     * sp+36: | saved $19 |
141 :     * +-------------------+
142 :     * sp+32: | saved $18 |
143 :     * +-------------------+
144 :     * sp+28: | saved $17 |
145 :     * +-------------------+
146 :     * sp+24: | saved $16 |
147 :     * +-------------------+
148 :     * sp+20: | pseudo reg 2 |
149 :     * +-------------------+
150 :     * sp+16: | pseudo reg 1 |
151 :     * +-------------------+
152 :     * sp+8: | unused |
153 :     * +-------------------+
154 :     * sp+4: | addr of saveregs |
155 :     * +-------------------+
156 :     * sp: | ptr to MLState |
157 :     * +-------------------+
158 :     */
159 :    
160 :     #define MLSTATE_OFFSET 0
161 :     #define STARTGC_OFFSET 4
162 :     #define REGSAVE_OFFSET 24
163 :     #define PSEUDOREG_OFFSET 16
164 :     #define ML_FRAMESIZE 4096
165 :    
166 :    
167 :     #ifdef MIPS2
168 :     # define LOAD_DELAY_SLOT
169 :     #else
170 :     # define LOAD_DELAY_SLOT nop
171 :     #endif
172 :    
173 :    
174 :     #if (CALLEESAVE > 0)
175 :     #define CONTINUE \
176 :     sltu exhausted,allocptr,limit; \
177 :     j stdcont;
178 :     #else
179 :     #define CONTINUE \
180 :     lw stdlink,0(stdcont); \
181 :     sltu exhausted,allocptr,limit; \
182 :     j stdlink
183 :     #endif
184 :    
185 :     #define CHECKLIMIT(mask) \
186 :     bnez exhausted,3f; \
187 :     li ptrtmp,mask; \
188 :     move gclink,stdlink; \
189 :     b saveregs; \
190 :     3:
191 :    
192 :    
193 :     .text
194 :    
195 :     /* sigh_return_a:
196 :     * The return continuation for the ML signal handler.
197 :     */
198 :     ML_CODE_HDR(sigh_return_a)
199 :     li ptrtmp,RET_MASK
200 :     li atmp1,REQ_SIG_RETURN
201 :     b set_request
202 :    
203 :     /* sigh_resume:
204 :     * Resume execution at the point at which a handler trap occurred. This is a
205 :     * standard two-argument function, thus the closure is in ml_cont (%stdcont).
206 :     */
207 :     ENTRY(sigh_resume)
208 :     li ptrtmp,RET_MASK
209 :     li atmp1,REQ_SIG_RESUME
210 :     b set_request
211 :    
212 :     /* pollh_return_a:
213 :     * The return continuation for the ML poll handler.
214 :     */
215 :     ML_CODE_HDR(pollh_return_a)
216 :     li ptrtmp,RET_MASK
217 :     li atmp1,REQ_POLL_RETURN
218 :     b set_request
219 :    
220 :     /* pollh_resume:
221 :     * Resume execution at the point at which a poll event occurred.
222 :     */
223 :     ENTRY(pollh_resume)
224 :     li ptrtmp,RET_MASK
225 :     li atmp1,REQ_POLL_RESUME
226 :     b set_request
227 :    
228 :     ML_CODE_HDR(handle_a)
229 :     li ptrtmp,EXN_MASK
230 :     li atmp1,REQ_EXN
231 :     b set_request
232 :    
233 :     ML_CODE_HDR(return_a)
234 :     li ptrtmp,RET_MASK
235 :     li atmp1,REQ_RETURN
236 :     b set_request
237 :    
238 :     ENTRY(request_fault)
239 :     li ptrtmp,EXN_MASK
240 :     li atmp1,REQ_FAULT
241 :     b set_request
242 :    
243 :     /* bind_cfun : (string * string) -> c_function
244 :     */
245 :     ML_CODE_HDR(bind_cfun_a)
246 :     CHECKLIMIT(FUN_MASK)
247 :     li ptrtmp,FUN_MASK
248 :     li atmp1,REQ_BIND_CFUN
249 :     b set_request
250 :    
251 :     ML_CODE_HDR(build_literals_a)
252 :     CHECKLIMIT(FUN_MASK)
253 :     li ptrtmp,FUN_MASK
254 :     li atmp1,REQ_BUILD_LITERALS
255 :     b set_request
256 :    
257 :     ML_CODE_HDR(callc_a)
258 :     CHECKLIMIT(FUN_MASK)
259 :     li ptrtmp,FUN_MASK
260 :     li atmp1,REQ_CALLC
261 :     /* fall through */
262 :    
263 :     set_request: /* a quick return to run_ml(), ptrtmp holds */
264 :     /* the request code, and atmp1 holds the */
265 :     /* live register mask. */
266 :    
267 :     move exhausted,ptrtmp /* save the register mask */
268 :     lw ptrtmp,MLSTATE_OFFSET(sp) /* get the ML state ptr from the stack */
269 :     sw exhausted,MaskOffMSP(ptrtmp)
270 :     lw exhausted,VProcOffMSP(ptrtmp) /* fetch the VProc state ptr */
271 :     sw zero,InMLOffVSP(exhausted) /* note that we have left ML */
272 :     sw allocptr,AllocPtrOffMSP(ptrtmp)
273 :     sw storeptr,StorePtrOffMSP(ptrtmp)
274 :     sw stdlink,LinkRegOffMSP(ptrtmp)
275 :     sw stdlink,PCOffMSP(ptrtmp) /* address of called function */
276 :     sw stdarg,StdArgOffMSP(ptrtmp)
277 :     sw stdclos,StdClosOffMSP(ptrtmp)
278 :     sw stdcont,StdContOffMSP(ptrtmp)
279 :     sw varptr,VarPtrOffMSP(ptrtmp)
280 :     sw exncont,ExnPtrOffMSP(ptrtmp)
281 :     move cresult,atmp1 /* return request */
282 :     #if (CALLEESAVE > 0)
283 :     sw miscreg0,MiscRegOffMSP(0)(ptrtmp)
284 :     #if (CALLEESAVE > 1)
285 :     sw miscreg1,MiscRegOffMSP(1)(ptrtmp)
286 :     #if (CALLEESAVE > 2)
287 :     sw miscreg2,MiscRegOffMSP(2)(ptrtmp)
288 :     #if (CALLEESAVE > 3)
289 :     sw miscreg3,MiscRegOffMSP(3)(ptrtmp)
290 :     #if (CALLEESAVE > 4)
291 :     sw miscreg4,MiscRegOffMSP(4)(ptrtmp)
292 :     #if (CALLEESAVE > 5)
293 :     sw miscreg5,MiscRegOffMSP(5)(ptrtmp)
294 :     #if (CALLEESAVE > 6)
295 :     sw miscreg6,MiscRegOffMSP(6)(ptrtmp)
296 :     #if (CALLEESAVE > 7)
297 :     sw miscreg7,MiscRegOffMSP(7)(ptrtmp)
298 :     #if (CALLEESAVE > 8)
299 :     sw miscreg8,MiscRegOffMSP(8)(ptrtmp)
300 :     #endif
301 :     #endif
302 :     #endif
303 :     #endif
304 :     #endif
305 :     #endif
306 :     #endif
307 :     #endif
308 :     #endif
309 :     /* restore callee-sace C registers */
310 :     restore_c_regs:
311 :     lw atmp1,PSEUDOREG_OFFSET(sp)
312 :     lw atmp2,PSEUDOREG_OFFSET+4(sp)
313 :     sw atmp1,PseudoReg1OffMSP(ptrtmp)
314 :     sw atmp2,PseudoReg2OffMSP(ptrtmp)
315 :     lw $31,REGSAVE_OFFSET+36(sp)
316 :     lw $30,REGSAVE_OFFSET+32(sp)
317 :     lw $23,REGSAVE_OFFSET+28(sp)
318 :     lw $22,REGSAVE_OFFSET+24(sp)
319 :     lw $21,REGSAVE_OFFSET+20(sp)
320 :     lw $20,REGSAVE_OFFSET+16(sp)
321 :     lw $19,REGSAVE_OFFSET+12(sp)
322 :     lw $18,REGSAVE_OFFSET+8(sp)
323 :     lw $17,REGSAVE_OFFSET+4(sp)
324 :     lw $16,REGSAVE_OFFSET(sp)
325 :     addu sp,ML_FRAMESIZE /* discard the stack frame */
326 :     j $31 /* return to run_ml() */
327 :    
328 :     BEGIN_PROC(saveregs)
329 :     ENTRY(saveregs)
330 :     move exhausted,ptrtmp /* save the register mask */
331 :     lw ptrtmp,MLSTATE_OFFSET(sp) /* use ptrtmp to access ML state */
332 :     sw exhausted,MaskOffMSP(ptrtmp)
333 :    
334 :     #ifdef SOFT_POLL
335 :     /** NOTE: why not use tmp registers here instead of misc regs?? **/
336 :     /* free some regs */
337 :     sw miscreg0,MiscRegOffMSP(0)(ptrtmp) /* use as tmp */
338 :     sw miscreg1,MiscRegOffMSP(1)(ptrtmp) /* use as tmp */
339 :     #define pfreq exhausted
340 :     #define pevent miscreg0
341 :     #define tmp miscreg1
342 :    
343 :     /* check if polling enabled (poll_freq > 0) */
344 :     la pfreq,CSYM(_PollFreq0) /* load contents of ref */
345 :     lw pfreq,4(pfreq)
346 :     srl pfreq,1 /* strip integer tag */
347 :     beqz pfreq,check_for_gc /* go check for real gc */
348 :     lw tmp,InPollHandlerOffMSP(ptrtmp) /* if we're in the handler */
349 :     bnez tmp,reset_limit /* ignore poll events */
350 :     la tmp,CSYM(_PollEvent0) /* load contents of ref */
351 :     lw pevent,4(tmp)
352 :     srl pevent,1
353 :     beqz pevent,reset_limit
354 :     /* event occurred, so set ml_pollHandlerPending */
355 :     li tmp,1
356 :     sw tmp,PollPendingOffMSP(ptrtmp)
357 :     b do_gc /* and handle event in the C runtime */
358 :    
359 :     reset_limit: /* reset limit ptr */
360 :     sll pfreq,POLL_GRAIN_BITS /* mult by POLL_GRAIN_CPSI */
361 :     addu limit,pfreq,allocptr /* overflow handled below */
362 :    
363 :     check_for_gc:
364 :     #define tmp2 pfreq
365 :     #define vsp pevent
366 :     /* ensure real limit is >= limit */
367 :     lw tmp,RealLimitOffMSP(ptrtmp)
368 :     sltu tmp2,tmp,limit
369 :     beqz tmp2,ok_limit /* (tmp >= limit) */
370 :     move limit,tmp
371 :     ok_limit:
372 :     subu tmp,limit,allocptr
373 :     slt tmp,tmp,4096
374 :     bnez tmp,do_gc /* gc *//* should be a common case */
375 :     /* since a signal also sets limitptr == allocptr to force a trap, */
376 :     /* we need to disambiguate poll-events/signals here */
377 :     lw vsp,VProcOffMSP(ptrtmp)
378 :     lw tmp,PollPendingOffMSP(ptrtmp)
379 :     lw tmp2,NPendingOffVSP(vsp)
380 :     add tmp,tmp,tmp2
381 :     lw tmp2,NPendingSysOffVSP(vsp)
382 :     add tmp,tmp,tmp2
383 :     bnez tmp2,do_gc
384 :     #undef pfreq
385 :     #undef pevent
386 :     #undef vsp
387 :     #undef tmp2
388 :    
389 :     no_gc: /* an uneventful poll check, back to ML */
390 :     lw miscreg0,MiscRegOffMSP(0)(ptrtmp) /* reload miscregs */
391 :     lw miscreg1,MiscRegOffMSP(1)(ptrtmp)
392 :     .set noreorder
393 :     j gclink
394 :     sltu exhausted,allocptr,limit /* (delay slot) */
395 :     .set reorder
396 :    
397 :     do_gc:
398 :     sw limit,LimitPtrOffMSP(ptrtmp)
399 :     #endif /* SOFT_POLL */
400 :    
401 :     lw exhausted,VProcOffMSP(ptrtmp)
402 :     sw zero,InMLOffVSP(exhausted) /* note that we have left ML */
403 :     sub basereg,32764 /* adjust baseReg */
404 :     sw allocptr,AllocPtrOffMSP(ptrtmp)
405 :     sw storeptr,StorePtrOffMSP(ptrtmp)
406 :     sw stdarg,StdArgOffMSP(ptrtmp)
407 :     sw stdcont,StdContOffMSP(ptrtmp)
408 :     sw stdclos,StdClosOffMSP(ptrtmp)
409 :     sw gclink,PCOffMSP(ptrtmp)
410 :     sw exncont,ExnPtrOffMSP(ptrtmp)
411 :     /* save misc. roots */
412 :     #ifndef SOFT_POLL /* miscreg0 & miscreg1 saved above for SOFT_POLL */
413 :     sw miscreg0,MiscRegOffMSP(0)(ptrtmp)
414 :     sw miscreg1,MiscRegOffMSP(1)(ptrtmp)
415 :     #endif
416 :     sw miscreg2,MiscRegOffMSP(2)(ptrtmp)
417 :     sw miscreg3,MiscRegOffMSP(3)(ptrtmp)
418 :     sw miscreg4,MiscRegOffMSP(4)(ptrtmp)
419 :     sw miscreg5,MiscRegOffMSP(5)(ptrtmp)
420 :     sw miscreg6,MiscRegOffMSP(6)(ptrtmp)
421 :     sw miscreg7,MiscRegOffMSP(7)(ptrtmp)
422 :     sw miscreg8,MiscRegOffMSP(8)(ptrtmp)
423 :     sw miscreg9,MiscRegOffMSP(9)(ptrtmp)
424 :     sw miscreg10,MiscRegOffMSP(10)(ptrtmp)
425 :     sw miscreg11,MiscRegOffMSP(11)(ptrtmp)
426 :     sw miscreg12,MiscRegOffMSP(12)(ptrtmp)
427 :     sw stdlink,LinkRegOffMSP(ptrtmp)
428 :     sw basereg,BasePtrOffMSP(ptrtmp) /* base reg */
429 :     sw varptr,VarPtrOffMSP(ptrtmp)
430 :     li cresult,REQ_GC
431 :     b restore_c_regs
432 :     .end saveregs
433 :    
434 :    
435 :     BEGIN_PROC(restoreregs)
436 :     ENTRY(restoreregs)
437 :     subu sp,ML_FRAMESIZE /* allocate a stack frame */
438 :     .frame sp,ML_FRAMESIZE,zero
439 :     .mask 0xc0ff0000,0
440 :     /* save the C registers */
441 :     la $5,saveregs
442 :     sw carg0,MLSTATE_OFFSET(sp) /* save MLState ptr for return to C */
443 :     sw $5,STARTGC_OFFSET(sp) /* so ML can find saveregs! */
444 :     sw $31,REGSAVE_OFFSET+36(sp)
445 :     sw $30,REGSAVE_OFFSET+32(sp)
446 :     sw $23,REGSAVE_OFFSET+28(sp)
447 :     sw $22,REGSAVE_OFFSET+24(sp)
448 :     sw $21,REGSAVE_OFFSET+20(sp)
449 :     sw $20,REGSAVE_OFFSET+16(sp)
450 :     sw $19,REGSAVE_OFFSET+12(sp)
451 :     sw $18,REGSAVE_OFFSET+8(sp)
452 :     sw $17,REGSAVE_OFFSET+4(sp)
453 :     sw $16,REGSAVE_OFFSET(sp)
454 :     move ptrtmp,carg0 /* put MLState ptr in ptrtmp */
455 :    
456 :     lw atmp1,PseudoReg1OffMSP(ptrtmp) /* save pseudo registers */
457 :     lw atmp2,PseudoReg2OffMSP(ptrtmp)
458 :     sw atmp1,PSEUDOREG_OFFSET(sp)
459 :     sw atmp2,PSEUDOREG_OFFSET+4(sp)
460 :    
461 :     lw allocptr,AllocPtrOffMSP(ptrtmp)
462 :     lw limit,LimitPtrOffMSP(ptrtmp)
463 :     lw storeptr,StorePtrOffMSP(ptrtmp)
464 :     li atmp1,1
465 :     lw exhausted,VProcOffMSP(ptrtmp)
466 :     .set noreorder /* the order here is important */
467 :     sw atmp1,InMLOffVSP(exhausted) /* note that we are entering ML code */
468 :     lw stdarg,StdArgOffMSP(ptrtmp)
469 :     lw stdcont,StdContOffMSP(ptrtmp)
470 :     lw stdclos,StdClosOffMSP(ptrtmp)
471 :     lw exncont,ExnPtrOffMSP(ptrtmp)
472 :     lw miscreg0,MiscRegOffMSP(0)(ptrtmp)
473 :     lw miscreg1,MiscRegOffMSP(1)(ptrtmp)
474 :     lw miscreg2,MiscRegOffMSP(2)(ptrtmp)
475 :     lw miscreg3,MiscRegOffMSP(3)(ptrtmp)
476 :     lw miscreg4,MiscRegOffMSP(4)(ptrtmp)
477 :     lw miscreg5,MiscRegOffMSP(5)(ptrtmp)
478 :     lw miscreg6,MiscRegOffMSP(6)(ptrtmp)
479 :     lw miscreg7,MiscRegOffMSP(7)(ptrtmp)
480 :     lw miscreg8,MiscRegOffMSP(8)(ptrtmp)
481 :     lw miscreg9,MiscRegOffMSP(9)(ptrtmp)
482 :     lw miscreg10,MiscRegOffMSP(10)(ptrtmp)
483 :     lw miscreg11,MiscRegOffMSP(11)(ptrtmp)
484 :     lw miscreg12,MiscRegOffMSP(12)(ptrtmp)
485 :     lw stdlink,LinkRegOffMSP(ptrtmp)
486 :     lw varptr,VarPtrOffMSP(ptrtmp)
487 :     lw basereg,BasePtrOffMSP(ptrtmp)
488 :     lw gclink,PCOffMSP(ptrtmp)
489 :     add basereg,32764 /* adjust baseReg */
490 :     /* check for pending signals */
491 :     lw ptrtmp,NPendingSysOffVSP(exhausted)
492 :     .set noat
493 :     lw $1,NPendingOffVSP(exhausted)
494 :     LOAD_DELAY_SLOT
495 :     add ptrtmp,ptrtmp,$1
496 :     .set at
497 :     bnez ptrtmp,pending_sigs
498 :     nop /* (branch delay slot) */
499 :     .end restoreregs
500 :     .ent ml_go
501 :     ENTRY(ml_go)
502 :     j gclink /* jump to ML code */
503 :     sltu ptrtmp,allocptr,limit /* (delay slot) */
504 :     .end ml_go
505 :    
506 :     pending_sigs: /* there are pending signals */
507 :     /* check if we are currently handling a signal */
508 :     lw ptrtmp,InSigHandlerOffVSP(exhausted)
509 :     LOAD_DELAY_SLOT
510 :     bnez ptrtmp,ml_go
511 :     /* note that a handler trap is pending */
512 :     li ptrtmp,1
513 :     sw ptrtmp,HandlerPendingOffVSP(exhausted)
514 :     b ml_go
515 :     move limit,allocptr /* (delay slot) */
516 :     .set reorder
517 :    
518 :    
519 :     /* SaveFPRegs:
520 :     *
521 :     * void SaveFPRegs (Word_t *p)
522 :     *
523 :     * Save the Callee-save FP registers starting at the given address.
524 :     */
525 :     TEXT
526 :     BEGIN_PROC(SaveFPRegs)
527 :     ENTRY(SaveFPRegs)
528 :     swc1 $f20,4(a0) /* fpr20 */
529 :     swc1 $f21,8(a0)
530 :     swc1 $f22,12(a0) /* fpr22 */
531 :     swc1 $f23,16(a0)
532 :     swc1 $f24,20(a0) /* fpr24 */
533 :     swc1 $f25,24(a0)
534 :     swc1 $f26,28(a0) /* fpr26 */
535 :     swc1 $f27,32(a0)
536 :     swc1 $f28,36(a0) /* fpr28 */
537 :     swc1 $f29,40(a0)
538 :     j ra /* return */
539 :     END_PROC(SaveFPRegs)
540 :    
541 :     /* RestoreFPRegs:
542 :     *
543 :     * void RestoreFPRegs (Word_t *p)
544 :     *
545 :     * Restore the callee-save FP registers from the given address.
546 :     */
547 :     BEGIN_PROC(RestoreFPRegs)
548 :     ENTRY(RestoreFPRegs) /* floats address passed as parm */
549 :     lwc1 $f20,0(a0) /* retrieve float registers */
550 :     lwc1 $f21,4(a0)
551 :     lwc1 $f22,8(a0)
552 :     lwc1 $f23,12(a0)
553 :     lwc1 $f24,16(a0)
554 :     lwc1 $f25,20(a0)
555 :     lwc1 $f26,24(a0)
556 :     lwc1 $f27,28(a0)
557 :     lwc1 $f28,32(a0)
558 :     lwc1 $f29,36(a0)
559 :     j ra
560 :     END_PROC(RestoreFPRegs)
561 :    
562 :    
563 :     /** Primitive object allocation routines **/
564 :    
565 :     /* array : (int * 'a) -> 'a array
566 :     * Allocate and initialize a new array. This can cause GC.
567 :     */
568 :     ML_CODE_HDR(array_a)
569 :     CHECKLIMIT(FUN_MASK)
570 :     lw atmp1,0(stdarg) /* atmp1 := length (tagged int) */
571 :     sra atmp1,1 /* atmp1 := length (untagged int) */
572 :     bgt atmp1,SMALL_OBJ_SZW,1f /* is this a small object? */
573 :     sll atmp3,atmp1,TAG_SHIFTW /* build descriptor in atmp3 */
574 :     ori atmp3,MAKE_TAG(DTAG_array)
575 :     sw atmp3,0(allocptr) /* store descriptor */
576 :     addi allocptr,4 /* allocptr++ */
577 :     lw atmp2,4(stdarg) /* atmp2 := initial value */
578 :     move stdarg,allocptr
579 :     sll atmp1,2 /* atmp1 := length in bytes */
580 :     add atmp1,allocptr /* atmp1 is end of array */
581 :     2: /* loop: */
582 :     sw atmp2,0(allocptr) /* store next element */
583 :     addi allocptr,4 /* allocptr++ */
584 :     bne allocptr,atmp1,2b /* if (allocptr != end) goto loop */
585 :     /* end loop */
586 :     CONTINUE
587 :    
588 :     1: /* off-line allocation of big arrays */
589 :     li ptrtmp,FUN_MASK
590 :     li atmp1,REQ_ALLOC_ARRAY
591 :     b set_request
592 :    
593 :     /* create_r : int -> realarray
594 :     * Create a new realarray.
595 :     */
596 :     ML_CODE_HDR(create_r_a)
597 :     CHECKLIMIT(FUN_MASK)
598 :     sra atmp1,stdarg,1 /* atmp1 = length (untagged int) */
599 :     sll atmp2,atmp1,1 /* atmp1 = length in words */
600 :     bgt atmp2,SMALL_OBJ_SZW,1f /* is this a small object? */
601 :     sll atmp3,atmp1,TAG_SHIFTW /* build descriptor in atmp3 */
602 :     ori atmp3,atmp3,MAKE_TAG(DTAG_realdarray)
603 :     #ifdef ALIGN_REALDS
604 :     ori allocptr,4 /* tag is unaligned, so that the */
605 :     /* first element is 8-byte aligned */
606 :     #endif
607 :     sw atmp3,0(allocptr)
608 :     addi stdarg,allocptr,4 /* pointer to new realarray */
609 :     sll atmp2,2 /* atmp2 = length in bytes (no tag) */
610 :     addi atmp2,4 /* plus tag */
611 :     add allocptr,atmp2 /* allocptr += total length */
612 :     CONTINUE
613 :    
614 :     1: /* off-line allocation of big realarrays */
615 :     li ptrtmp,FUN_MASK
616 :     li atmp1,REQ_ALLOC_REALDARRAY
617 :     b set_request
618 :    
619 :     /* create_b : int -> bytearray
620 :     * Create a bytearray of the given length.
621 :     */
622 :     ML_CODE_HDR(create_b_a)
623 :     CHECKLIMIT(FUN_MASK)
624 :     sra atmp1,stdarg,1 /* atmp1 = length (untagged int) */
625 :     addi atmp2,atmp1,3 /* atmp2 = length in words */
626 :     sra atmp2,2
627 :     bgt atmp2,SMALL_OBJ_SZW,1f /* is this a small object? */
628 :     sll atmp3,atmp1,TAG_SHIFTW /* build descriptor in atmp3 */
629 :     ori atmp3,atmp3,MAKE_TAG(DTAG_bytearray)
630 :     sw atmp3,0(allocptr)
631 :     addi stdarg,allocptr,4 /* pointer to new bytearray */
632 :     sll atmp2,2 /* atmp2 = length in bytes (no tag) */
633 :     addi atmp2,4 /* plus tag */
634 :     add allocptr,atmp2 /* allocptr += total length */
635 :     CONTINUE
636 :     1: /* off-line allocation of big bytearrays */
637 :     li ptrtmp,FUN_MASK
638 :     li atmp1,REQ_ALLOC_BYTEARRAY
639 :     b set_request
640 :    
641 :     /* create_s : int -> string
642 :     * Create a string of the given length (assume length >0); the string
643 :     * is guaranteed to have at least one 0 byte as termination (which is
644 :     * not counted in its length).
645 :     */
646 :     ML_CODE_HDR(create_s_a)
647 :     CHECKLIMIT(FUN_MASK)
648 :     sra atmp1,stdarg,1 /* atmp1 = length (untagged int) */
649 :     addi atmp2,atmp1,4 /* atmp2 = length in words */
650 :     sra atmp2,2
651 :     bgt atmp2,SMALL_OBJ_SZW,1f /* is this a small object? */
652 :     sll atmp3,atmp1,TAG_SHIFTW /* build descriptor in atmp3 */
653 :     ori atmp3,atmp3,MAKE_TAG(DTAG_string)
654 :     sw atmp3,0(allocptr)
655 :     addi stdarg,allocptr,4 /* pointer to new string */
656 :     sll atmp2,2 /* atmp2 = length in bytes (no tag) */
657 :     addi atmp2,4 /* plus tag */
658 :     add allocptr,atmp2 /* allocptr += total length */
659 :     sw zero,-4(allocptr) /* store zero in last word */
660 :     CONTINUE
661 :     1: /* off-line allocation of big strings */
662 :     li ptrtmp,FUN_MASK
663 :     li atmp1,REQ_ALLOC_STRING
664 :     b set_request
665 :    
666 :     /* create_v_a : (int * 'a list) -> 'a vector
667 :     * Create a vector with elements taken from a list.
668 :     * NOTE: the front-end ensures that list cannot be nil.
669 :     */
670 :     ML_CODE_HDR(create_v_a)
671 :     CHECKLIMIT(FUN_MASK)
672 :     lw atmp1,0(stdarg) /* atmp1 := length (tagged int) */
673 :     sra atmp1,1 /* atmp1 := length (untagged) */
674 :     bgt atmp1,SMALL_OBJ_SZW,1f /* is this a small object? */
675 :     sll atmp2,atmp1,TAG_SHIFTW /* build descriptor in atmp2 */
676 :     ori atmp2,MAKE_TAG(DTAG_vector)
677 :     sw atmp2,0(allocptr) /* store descriptor */
678 :     addi allocptr,4 /* allocptr++ */
679 :     lw atmp2,4(stdarg) /* atmp2 := list */
680 :     move stdarg,allocptr /* stdarg := vector */
681 :     li atmp3,ML_nil
682 :     2: /* loop: */
683 :     lw atmp1,0(atmp2) /* atmp1 := hd(atmp2) */
684 :     lw atmp2,4(atmp2) /* atmp2 := tl(atmp2) */
685 :     sw atmp1,0(allocptr) /* store word in vector */
686 :     addi allocptr,4 /* allocptr++ */
687 :     bne atmp2,atmp3,2b /* if (atmp2 <> nil) goto loop */
688 :     /* end loop */
689 :     CONTINUE
690 :    
691 :     1: /* off-line allocation for large vectors */
692 :     li ptrtmp,FUN_MASK
693 :     li atmp1,REQ_ALLOC_VECTOR
694 :     b set_request
695 :    
696 :     #ifdef MIPSEL
697 :     #define BIGPART 4
698 :     #else
699 :     #define BIGPART 0
700 :     #endif
701 :     #define LITTLEPART (4-BIGPART)
702 :    
703 :     /* Floating exceptions raised (assuming ROP's are never passed to functions):
704 :     * DIVIDE BY ZERO - (div)
705 :     * OVERFLOW/UNDERFLOW - (add,div,sub,mul) as appropriate
706 :     *
707 :     * floor raises integer overflow if the float is out of 32-bit range,
708 :     * so the float is tested before conversion, to make sure it is in (31-bit)
709 :     * range */
710 :     ML_CODE_HDR(floor_a)
711 :     CHECKLIMIT(FUN_MASK)
712 :     lwc1 $f4,LITTLEPART(stdarg) /* get least significant word */
713 :     lwc1 $f5,BIGPART(stdarg) /* get most significant word */
714 :     mtc1 zero,$f2 /* ($f2,$f3) := maxint */
715 :     lui atmp3,0x41d0
716 :     mtc1 atmp3,$f3
717 :     abs.d $f6,$f4
718 :     c.le.d $f6,$f2
719 :     cfc1 atmp3,$31 /* grab fpa control register */
720 :     bc1f over
721 :     ori atmp2,atmp3,0x03 /* set rounding bits to 11 */
722 :     ctc1 atmp2,$31 /* return fpa control register */
723 :     cvt.w.d $f6,$f4 /* convert to integer */
724 :     ctc1 atmp3,$31 /* return fpa control register */
725 :     mfc1 stdarg,$f6 /* get in std argument register */
726 :     add stdarg,stdarg /* make room for tag bit */
727 :     add stdarg,1 /* add the tag bit */
728 :     CONTINUE
729 :    
730 :    
731 :     ML_CODE_HDR(logb_a)
732 :     CHECKLIMIT(FUN_MASK)
733 :     lw stdarg,BIGPART(stdarg) /* most significant part */
734 :     srl stdarg,20 /* throw out 20 low bits */
735 :     andi stdarg,0x07ff /* clear all but 11 low bits */
736 :     sub stdarg,1023 /* subtract 1023 */
737 :     sll stdarg,1 /* make room for tag bit */
738 :     add stdarg,1 /* add the tag bit */
739 :     CONTINUE
740 :    
741 :     ML_CODE_HDR(scalb_a)
742 :     CHECKLIMIT(FUN_MASK)
743 :     lw atmp1,4(stdarg) /* get tagged n */
744 :     sra atmp1,1 /* get real n */
745 :     beqz atmp1,9f /* if zero, return the old float */
746 :     lw ptrtmp,0(stdarg) /* get pointer to float */
747 :     lw atmp2,BIGPART(ptrtmp) /* most significant part */
748 :     srl atmp2,20 /* throw out 20 low bits */
749 :     andi atmp2,0x07ff /* clear all but 11 low bits */
750 :     add atmp3,atmp2,atmp1 /* new := old + n */
751 :     blt atmp3,1,under /* punt if underflow */
752 :     bgt atmp3,2046,over /* or overflow */
753 :     xor atmp3,atmp2 /* at3 = new xor old */
754 :     sll atmp3,20 /* put exponent in right position */
755 :     lw atmp2,BIGPART(ptrtmp) /* most significant word */
756 :     xor atmp2,atmp3 /* change to new exponent */
757 :     sw atmp2,BIGPART+4(allocptr) /* save */
758 :     lw atmp2,LITTLEPART(ptrtmp) /* get least significant word */
759 :     sw atmp2,LITTLEPART+4(allocptr) /* save lsw */
760 :     8: li atmp4,DESC_reald /* make descriptor */
761 :     sw atmp4,0(allocptr) /* save descriptor */
762 :     add stdarg,allocptr,4 /* get pointer to new float */
763 :     add allocptr,12 /* point to new free word */
764 :     CONTINUE
765 :    
766 :     9: lw stdarg,0(stdarg) /* get old float */
767 :     CONTINUE
768 :    
769 :     over: li atmp3,0x7fffffff
770 :     add atmp3,atmp3 /* generate overflow exception */
771 :    
772 :     under: sw zero,4(allocptr) /* return 0.0 */
773 :     sw zero,8(allocptr)
774 :     b 8b
775 :    
776 :     /* try_lock : spin_lock -> bool
777 :     * low-level test-and-set style primitive for mutual-exclusion among
778 :     * processors.
779 :     */
780 :     ML_CODE_HDR(try_lock_a)
781 :     CHECKLIMIT(FUN_MASK)
782 :     #ifdef MP_SUPPORT
783 :     # if defined(OPSYS_IRIX5)
784 :     ll atmp1,0(stdarg)
785 :     srl atmp1,1
786 :     bnez atmp1,isset
787 :     li atmp2,ML_true
788 :     sc atmp2,0(stdarg)
789 :     beqz atmp2,isset
790 :     li stdarg,ML_true
791 :     1:
792 :     CONTINUE
793 :     isset:
794 :     li stdarg,ML_false
795 :     b 1b
796 :     # else
797 :     # error no MP support for this system
798 :     # endif
799 :     #else /* ! MP_SUPPORT */
800 :     lw atmp1,0(stdarg)
801 :     li atmp2,ML_true
802 :     sw atmp2,0(stdarg)
803 :     move stdarg,atmp2
804 :     CONTINUE
805 :     #endif
806 :    
807 :     /* unlock : spin_lock -> unit
808 :     * Release an ML spin lock.
809 :     */
810 :     ML_CODE_HDR(unlock_a)
811 :     CHECKLIMIT(FUN_MASK)
812 :     li atmp1,ML_false
813 :     sw atmp1,0(stdarg)
814 :     li stdarg,ML_unit
815 :     CONTINUE
816 :    
817 :     /** C callable routines for managing ML locks **/
818 :     #ifdef MP_SUPPORT
819 :     # ifdef OPSYS_IRIX5
820 :     /* LOCK_Lock:
821 :     *
822 :     * bool_t LOCK_Lock (ml_state_t *msp, ml_val_t lock)
823 :     */
824 :     BEGIN_PROC(LOCK_Lock)
825 :     ENTRY(LOCK_Lock)
826 :     ll t0,0(carg1)
827 :     srl t0,1
828 :     bnez t0,1f
829 :     li t1,ML_true
830 :     sc t1,0(carg1)
831 :     beqz t1,1f
832 :     li cresult,TRUE
833 :     j ra
834 :     1:
835 :     li cresult,FALSE
836 :     j ra
837 :     END_PROC(LOCK_Lock)
838 :    
839 :     /* LOCK_Unlock:
840 :     *
841 :     * void LOCK_Unlock (ml_state_t *msp, ml_val_t lock)
842 :     */
843 :     BEGIN_PROC(LOCK_Unlock)
844 :     ENTRY(LOCK_Unlock)
845 :     li t0,ML_false
846 :     sw t0,0(carg1)
847 :     j ra
848 :     END_PROC(LOCK_Unlock)
849 :     # else
850 :     # error MP not supported for system
851 :     # endif
852 :     #endif /* MP_SUPPORT */
853 :    
854 :     /* SetFSR:
855 :     * Turn on floating-point overflow, underflow and zero-divide exceptions.
856 :     */
857 :     BEGIN_PROC(SetFSR)
858 :     ENTRY(SetFSR)
859 :     cfc1 t0,$31 /* grab fpa control register */
860 :     ori t0,t0,0x00 /* disable all flags */
861 :     ctc1 t0,$31 /* return fpa control register */
862 :     j ra
863 :     END_PROC(SetFSR)
864 :    
865 :    
866 :     #ifdef OPSYS_MACH
867 :    
868 :     /* ReenableFP:
869 :     * MACH based DECstations .don not handle SIGFPE correctly, so we have to
870 :     * execute a FP instruction to clear things up.
871 :     */
872 :     BEGIN_PROC(ReenableFP)
873 :     ENTRY(ReenableFP)
874 :     mfc1 atmp1,$f1
875 :     j $31
876 :     END_PROC(ReenableFP)
877 :    
878 :     #endif /* OPSYS_MACH */

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