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 8 - (view) (download)
Original Path: sml/branches/SMLNJ/src/runtime/mach-dep/MIPS.prim.asm

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

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