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/branches/SMLNJ/src/runtime/mach-dep/X86.prim.asm
ViewVC logotype

Annotation of /sml/branches/SMLNJ/src/runtime/mach-dep/X86.prim.asm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8 - (view) (download)

1 : monnier 2 /* X86.prim.asm
2 :     *
3 :     * COPYRIGHT (c) 1995 AT&T Bell Laboratories.
4 :     *
5 :     * This was derived from I386.prim.s, by Mark Leone (mleone@cs.cmu.edu)
6 :     */
7 :    
8 :     #include "ml-base.h"
9 :     #include "asm-base.h"
10 :     #include "ml-values.h"
11 :     #include "tags.h"
12 :     #include "ml-request.h"
13 :     #include "reg-mask.h"
14 :     #include "ml-limits.h"
15 :    
16 :     /* enable/disable virtual (memory-based) registers.
17 :     * the number of vregs, etc. must concur with:
18 :     * src/runtime/include/ml-state.h
19 :     * src/runtime/kernel/ml-state.c
20 :     * src/sml-nj/x86/x86.sml
21 :     */
22 :    
23 :     #ifndef VREGS
24 :     # define VREGS
25 :     #endif
26 :    
27 :     /*
28 :     *
29 :     * The 386 registers are used as follows:
30 :     *
31 :     * EAX - temp1 (see the code generator, x86/x86.sml)
32 :     * EBX - misc1
33 :     * ECX - misc2
34 :     * EDX - misc3
35 :     * ESI - standard continuation (ml_cont, see ml_state.h)
36 :     * EBP - standard argument (ml_arg)
37 :     * EDI - free space pointer (ml_allocptr)
38 :     * ESP - stack pointer
39 :     * EIP - program counter (ml_pc)
40 :     */
41 :    
42 :     /* Registers (see x86/x86.sml): */
43 :     #define temp %eax
44 :     #define misc1 %ebx
45 :     #define misc2 %ecx
46 :     #define misc3 %edx
47 :     #define stdcont %esi
48 :     #define stdarg %ebp
49 :     #define allocptr %edi
50 :    
51 :     /* other reg uses */
52 :     #define creturn %eax
53 :    
54 :     /*
55 :     * Other values, which on most architectures would reside in registers,
56 :     * are stored on the stack:
57 :     *
58 :     * 0(ESP) - tempmem (used by the X86 code generator)
59 :     * 4(ESP) - tempmem2 (used by the X86 code generator)
60 :     * 8(ESP) - exception handler continuation (ml_exncont)
61 :     * 12(ESP) - data limit (ml_limitptr)
62 :     * 16(ESP) - standard closure (ml_closure)
63 :     * 20(ESP) - link register (ml_linkreg)
64 :     * 24(ESP) - store pointer (ml_storeptr)
65 :     * 28(ESP) - var pointer (ml_varptr)
66 :     *
67 :     */
68 :    
69 :     /* Stack frame (see x86/x86.sml): */
70 :     #define tempmem 0(%esp)
71 :     #define tempmem2 4(%esp)
72 :     #define exncont 8(%esp)
73 :     #define limitptr 12(%esp)
74 :     #define stdclos 16(%esp)
75 :     #define stdlink 20(%esp)
76 :     #define storeptr 24(%esp)
77 :     #define varptr 28(%esp)
78 :     #define start_gc 32(%esp)
79 :     #define mask 36(%esp)
80 :     #define vreg0 40(%esp)
81 :     #define vreg1 44(%esp)
82 :     #define vreg2 48(%esp)
83 :     #define vreg3 52(%esp)
84 :     #define vreg4 56(%esp)
85 :     #define vreg5 60(%esp)
86 :     #define vreg6 64(%esp)
87 :     #define vreg7 68(%esp)
88 :     #define vreg8 72(%esp)
89 :     #define vreg9 76(%esp)
90 :     #define vreg10 80(%esp)
91 :     #define vreg11 84(%esp)
92 :     #define vreg12 88(%esp) /* unused */ /* used as pseudo reg */
93 :     #define vreg13 92(%esp) /* unused */ /* used as pseudo reg */
94 :     #define vreg14 96(%esp) /* unused */
95 :     #define vreg15 100(%esp) /* unused */
96 :     #define mlstate_ptr 104(%esp)
97 :     #define ML_STATE_OFFSET 104
98 :     #define ML_FRAME_SIZE (ML_STATE_OFFSET+4)
99 :    
100 :    
101 :     #define PSEUDOREG_1 vreg12
102 :     #define PSEUDOREG_2 vreg13
103 :    
104 :     #define via
105 :    
106 :    
107 :     DATA
108 :     ALIGN4
109 :     tempmem_w: /* temp word for the code generator */
110 :     .long 0
111 :     tempmem2_w: /* another temp word for the code generator */
112 :     .long 0
113 :     request_w: /* place to put the request code */
114 :     .long 0
115 :     GLOBAL(ML_X86Frame)
116 :     LABEL(CSYM(ML_X86Frame)) /* ptr to the ml frame (gives C access to limitptr) */
117 :     .long 0
118 :    
119 :     /*
120 :     * Note that the garbage collector only preserves root registers
121 :     * (EBX, ECX, EDX, ESI, EBP, EIP).
122 :     */
123 :    
124 :    
125 :     #include "mlstate-offsets.h" /** this file is generated **/
126 :    
127 :    
128 :     /*
129 :     * 386 function call conventions:
130 :     * [true for gcc and dynix3 cc; untested for others]
131 :     *
132 :     * Caller save registers: eax, ecx, edx
133 :     * Callee save registers: ebx, esi, edi, and ebp.
134 :     * Floating point state is caller-save.
135 :     * Arguments passed on stack. Rightmost argument pushed first.
136 :     * Word-sized result returned in %eax.
137 :     */
138 :    
139 :     #define cresult %eax
140 :    
141 :     #define CALLEE_SAVE \
142 :     pushl %ebx; \
143 :     pushl %esi; \
144 :     pushl %edi; \
145 :     pushl %ebp
146 :    
147 :     #define CALLEE_RESTORE \
148 :     popl %ebp; \
149 :     popl %edi; \
150 :     popl %esi; \
151 :     popl %ebx
152 :    
153 :     /* MOVE copies one memory location to another, using a specified temporary. */
154 :    
155 :     #define MOVE(src,tmp,dest) \
156 :     movl src, tmp; \
157 :     movl tmp, dest
158 :    
159 :     #if (CALLEESAVE > 0)
160 :     #define CONTINUE \
161 :     cmpl limitptr, allocptr; \
162 :     jmp via stdcont
163 :     #else
164 :     #define CONTINUE \
165 :     movl (stdcont), temp; \
166 :     movl temp, stdlink; /* Not really a register */ \
167 :     cmpl limitptr, allocptr; \
168 :     jmp via temp
169 :     #endif
170 :    
171 :     #define CHECKLIMIT(maskval) \
172 :     1:; \
173 :     jb 9f; \
174 :     lea 1b, temp; /* temp holds resume address */ \
175 :     movl $maskval, mask; \
176 :     jmp via CSYM(saveregs); \
177 :     9:
178 :    
179 :     /**********************************************************************/
180 :     TEXT
181 :     ALIGN4
182 :    
183 :     ML_CODE_HDR(sigh_return_a)
184 :     movl mlstate_ptr, temp
185 :     movl $REQ_SIG_RETURN, request_w
186 :     movl $RET_MASK, mask
187 :     jmp CSYM(set_request)
188 :    
189 :     /* sigh_resume:
190 :     * Resume execution at the point at which a handler trap occurred. This is a
191 :     * standard two-argument function, thus the closure is in ml_cont.
192 :     */
193 :    
194 :     ENTRY(sigh_resume)
195 :     movl mlstate_ptr, temp
196 :     movl $REQ_SIG_RESUME, request_w
197 :     /* movl $RET_MASK, mask
198 :     */
199 :     movl $FUN_MASK, mask
200 :     jmp CSYM(set_request)
201 :    
202 :     /* pollh_return_a:
203 :     * The return continuation for the ML poll handler.
204 :     */
205 :     ML_CODE_HDR(pollh_return_a)
206 :     movl mlstate_ptr, temp
207 :     movl $REQ_POLL_RETURN, request_w
208 :     movl $RET_MASK, mask
209 :     jmp CSYM(set_request)
210 :    
211 :     /* pollh_resume:
212 :     * Resume execution at the point at which a poll event occurred.
213 :     */
214 :     ENTRY(pollh_resume)
215 :     movl mlstate_ptr, temp
216 :     movl $REQ_POLL_RESUME, request_w
217 :     /* movl $RET_MASK, mask
218 :     */
219 :     movl $FUN_MASK, mask
220 :     jmp CSYM(set_request)
221 :    
222 :     ML_CODE_HDR(handle_a)
223 :     movl mlstate_ptr, temp
224 :     movl $REQ_EXN, request_w
225 :     movl $EXN_MASK, mask
226 :     jmp CSYM(set_request)
227 :    
228 :     ML_CODE_HDR(return_a)
229 :     movl mlstate_ptr, temp
230 :     movl $REQ_RETURN, request_w
231 :     movl $RET_MASK, mask
232 :     jmp CSYM(set_request)
233 :    
234 :     /* Request a fault. The floating point coprocessor must be reset
235 :     * (thus trashing the FP registers) since we don't know whether a
236 :     * value has been pushed into the temporary "register". This is OK
237 :     * because no floating point registers will be live at the start of
238 :     * the exception handler.
239 :     */
240 :     ENTRY(request_fault)
241 :     call CSYM(FPEEnable) /* Doesn't trash any general regs. */
242 :     movl mlstate_ptr, temp
243 :     movl $REQ_FAULT, request_w
244 :     movl $EXN_MASK, mask
245 :     jmp CSYM(set_request)
246 :    
247 :     /* bind_cfun : (string * string) -> c_function
248 :     */
249 :     ML_CODE_HDR(bind_cfun_a)
250 :     CHECKLIMIT(FUN_MASK)
251 :     movl mlstate_ptr, temp
252 :     movl $REQ_BIND_CFUN, request_w
253 :     movl $FUN_MASK, mask
254 :     jmp CSYM(set_request)
255 :    
256 :     ML_CODE_HDR(build_literals_a)
257 :     CHECKLIMIT(FUN_MASK)
258 :     movl mlstate_ptr, temp
259 :     movl $REQ_BUILD_LITERALS, request_w
260 :     movl $FUN_MASK, mask
261 :     jmp CSYM(set_request)
262 :    
263 :     ML_CODE_HDR(callc_a)
264 :     CHECKLIMIT(FUN_MASK)
265 :     movl mlstate_ptr, temp
266 :     movl $REQ_CALLC, request_w
267 :     movl $FUN_MASK, mask
268 :     /* fall into set_request */
269 :    
270 :     ENTRY(set_request)
271 :     /* temp holds mlstate_ptr, valid request in request_w */
272 :     /* Save registers */
273 :     movl allocptr,AllocPtrOffMSP(temp)
274 :     movl stdarg,StdArgOffMSP(temp)
275 :     movl stdcont,StdContOffMSP(temp)
276 :    
277 :     #define temp2 allocptr
278 :     /* note that we have left ML code */
279 :     movl VProcOffMSP(temp),temp2
280 :     movl $0, InMLOffVSP(temp2)
281 :    
282 :     #if (CALLEESAVE > 0)
283 :     movl misc1, MiscRegOffMSP(0)(temp)
284 :     #if (CALLEESAVE > 1)
285 :     movl misc2, MiscRegOffMSP(1)(temp)
286 :     #if (CALLEESAVE > 2)
287 :     movl misc3, MiscRegOffMSP(2)(temp)
288 :    
289 :     /* Save vregs before the stack frame is popped. */
290 :    
291 :     #if (CALLEESAVE > 3)
292 :     MOVE(vreg0, temp2, MiscRegOffMSP(3)(temp))
293 :     #if (CALLEESAVE > 4)
294 :     MOVE(vreg1, temp2, MiscRegOffMSP(4)(temp))
295 :     #if (CALLEESAVE > 5)
296 :     MOVE(vreg2, temp2, MiscRegOffMSP(5)(temp))
297 :     #if (CALLEESAVE > 6)
298 :     MOVE(vreg3, temp2, MiscRegOffMSP(6)(temp))
299 :     #if (CALLEESAVE > 7)
300 :     MOVE(vreg4, temp2, MiscRegOffMSP(7)(temp))
301 :     #if (CALLEESAVE > 8)
302 :     MOVE(vreg5, temp2, MiscRegOffMSP(8)(temp))
303 :     #endif
304 :     #endif
305 :     #endif
306 :     #endif
307 :     #endif
308 :     #endif
309 :     #endif
310 :     #endif
311 :     #endif
312 :    
313 :     MOVE(tempmem, temp2, tempmem_w)
314 :     MOVE(tempmem2,temp2, tempmem2_w)
315 :     MOVE(limitptr,temp2, LimitPtrOffMSP(temp))
316 :     MOVE(exncont, temp2, ExnPtrOffMSP(temp))
317 :     MOVE(stdclos, temp2, StdClosOffMSP(temp))
318 :     MOVE(stdlink, temp2, LinkRegOffMSP(temp))
319 :     MOVE(stdlink, temp2, PCOffMSP(temp))
320 :     MOVE(storeptr,temp2, StorePtrOffMSP(temp))
321 :     MOVE(varptr, temp2, VarPtrOffMSP(temp))
322 :     MOVE(mask, temp2, MaskOffMSP(temp))
323 :    
324 :     /* pseudo regs */
325 :     MOVE(PSEUDOREG_1,temp2,PseudoReg1OffMSP(temp))
326 :     MOVE(PSEUDOREG_2,temp2,PseudoReg2OffMSP(temp))
327 :     #undef temp2
328 :    
329 :     /* return val of function is request code */
330 :     movl request_w,creturn
331 :    
332 :     /* Pop the stack frame and return to run_ml(). */
333 :     addl $ML_FRAME_SIZE, %esp
334 :     CALLEE_RESTORE
335 :     ret
336 :    
337 :     TEXT
338 :     ALIGN4
339 :    
340 :     ENTRY(saveregs)
341 :     pushl temp /* Contains "resume" address. */
342 :     movl ML_STATE_OFFSET+4(%esp), temp
343 :     popl PCOffMSP(temp)
344 :    
345 :     #ifdef SOFT_POLL
346 :     /* free some regs */
347 :     movl misc1, MiscRegOffMSP(0)(temp)
348 :     movl misc2, MiscRegOffMSP(1)(temp)
349 :     #define tmpR misc1
350 :     #define pfreq misc2
351 :     /* check if polling enabled (PollFreq > 0) */
352 :     lea CSYM(_PollFreq0),pfreq /* load contents of ref */
353 :     movl 4(pfreq),pfreq
354 :     shrl $1,pfreq /* strip integer tag */
355 :     jz check_for_gc /* go check for real gc */
356 :     cmpl $0,InPollHandlerOffMSP(temp) /* if we're in the handler */
357 :     jne reset_limit /* ignore poll events */
358 :     lea CSYM(_PollEvent0),tmpR /* load contents of ref */
359 :     movl 4(tmpR),tmpR
360 :     shrl $1,tmpR
361 :     jz reset_limit /* check for poll event */
362 :     /* event occurred, so set ml_pollHandlerPending */
363 :     movl $1,PollPendingOffMSP(temp)
364 :     jmp do_gc /* and handle event in the C runtime */
365 :    
366 :     reset_limit: /* reset limit ptr */
367 :     shll $POLL_GRAIN_BITS,pfreq /* mult by POLL_GRAIN_CPSI */
368 :     movl allocptr,limitptr
369 :     addl pfreq,limitptr
370 :     #undef pfreq
371 :    
372 :     check_for_gc:
373 :     /* ensure real limit is >= limit */
374 :     movl RealLimitOffMSP(temp),tmpR
375 :     cmpl limitptr,tmpR
376 :     ja ok_limit
377 :     movl tmpR,limitptr
378 :     ok_limit:
379 :     addl $-4096,limitptr
380 :     cmpl limitptr,allocptr
381 :     jge do_gc /* gc *//* should be a common case */
382 :     addl $4096,limitptr
383 :     /* since a signal also sets limitptr == allocptr to force a trap, */
384 :     /* we need to disambiguate poll-events/signals here */
385 :     #define vsp misc2
386 :     movl $0,tmpR
387 :     addl PollPendingOffMSP(temp),tmpR
388 :     movl VProcOffMSP(temp),vsp
389 :     addl NPendingOffVSP(vsp),tmpR
390 :     addl NPendingSysOffVSP(vsp),tmpR
391 :     jnz do_gc
392 :     #undef vsp
393 :    
394 :     no_gc: /* an uneventful poll check, back to ML */
395 :     movl MiscRegOffMSP(0)(temp),misc1
396 :     movl MiscRegOffMSP(1)(temp),misc2
397 :     movl PCOffMSP(temp),temp
398 :     cmpl limitptr, allocptr
399 :     jmpl temp
400 :    
401 :     do_gc:
402 :     /* limitptr saved below */
403 :    
404 :     #undef tmpR
405 :     #endif /* SOFT_POLL */
406 :    
407 :    
408 :     /* Save registers. */
409 :     movl allocptr, AllocPtrOffMSP(temp)
410 :     movl stdarg, StdArgOffMSP(temp)
411 :     movl stdcont, StdContOffMSP(temp)
412 :     #ifndef SOFT_POLL /* misc1 & misc2 saved above for SOFT_POLL */
413 :     movl misc1, MiscRegOffMSP(0)(temp)
414 :     movl misc2, MiscRegOffMSP(1)(temp)
415 :     #endif
416 :     movl misc3, MiscRegOffMSP(2)(temp)
417 :    
418 :     #define temp2 allocptr
419 :    
420 :     /* note that we have left ML code */
421 :     movl VProcOffMSP(temp),temp2
422 :     movl $0, InMLOffVSP(temp2)
423 :    
424 :     /* vregs */
425 :     #ifdef VREGS
426 :     MOVE(vreg0, temp2, MiscRegOffMSP(3)(temp))
427 :     MOVE(vreg1, temp2, MiscRegOffMSP(4)(temp))
428 :     MOVE(vreg2, temp2, MiscRegOffMSP(5)(temp))
429 :     MOVE(vreg3, temp2, MiscRegOffMSP(6)(temp))
430 :     MOVE(vreg4, temp2, MiscRegOffMSP(7)(temp))
431 :     MOVE(vreg5, temp2, MiscRegOffMSP(8)(temp))
432 :     MOVE(vreg6, temp2, MiscRegOffMSP(9)(temp))
433 :     MOVE(vreg7, temp2, MiscRegOffMSP(10)(temp))
434 :     MOVE(vreg8, temp2, MiscRegOffMSP(11)(temp))
435 :     MOVE(vreg9, temp2, MiscRegOffMSP(12)(temp))
436 :     MOVE(vreg10, temp2, MiscRegOffMSP(13)(temp))
437 :     MOVE(vreg11, temp2, MiscRegOffMSP(14)(temp))
438 :     #endif
439 :    
440 :     MOVE(tempmem, temp2, tempmem_w)
441 :     MOVE(tempmem2,temp2, tempmem2_w)
442 :     MOVE(exncont, temp2, ExnPtrOffMSP(temp))
443 :     MOVE(stdclos, temp2, StdClosOffMSP(temp))
444 :     MOVE(stdlink, temp2, LinkRegOffMSP(temp))
445 :     MOVE(storeptr,temp2, StorePtrOffMSP(temp))
446 :     MOVE(limitptr,temp2, LimitPtrOffMSP(temp))
447 :     MOVE(varptr, temp2, VarPtrOffMSP(temp))
448 :     MOVE(mask, temp2, MaskOffMSP(temp))
449 :    
450 :     /* pseudo regs */
451 :     MOVE(PSEUDOREG_1,temp2,PseudoReg1OffMSP(temp))
452 :     MOVE(PSEUDOREG_2,temp2,PseudoReg2OffMSP(temp))
453 :     #undef temp2
454 :    
455 :     /* Pop the stack frame and return to run_ml(). */
456 :     movl $REQ_GC,creturn
457 :     addl $ML_FRAME_SIZE, %esp
458 :     CALLEE_RESTORE
459 :     ret
460 :    
461 :     ENTRY(restoreregs)
462 :     movl 4(%esp), temp /* Get argument (MLState ptr). */
463 :     CALLEE_SAVE
464 :    
465 :     #define temp2 %ebx
466 :     /* Allocate and initialize the ML stack frame. */
467 :     subl $ML_FRAME_SIZE, %esp
468 :     MOVE( tempmem_w, temp2, tempmem)
469 :     MOVE( tempmem2_w, temp2, tempmem2)
470 :     MOVE( ExnPtrOffMSP(temp), temp2, exncont)
471 :     MOVE( LimitPtrOffMSP(temp), temp2, limitptr)
472 :     MOVE( StdClosOffMSP(temp), temp2, stdclos)
473 :     MOVE( LinkRegOffMSP(temp), temp2, stdlink)
474 :     MOVE( StorePtrOffMSP(temp), temp2, storeptr)
475 :     MOVE( VarPtrOffMSP(temp), temp2, varptr)
476 :     MOVE( MaskOffMSP(temp), temp2, mask)
477 :     lea CSYM(saveregs), temp2
478 :     movl temp2,start_gc
479 :     movl temp, mlstate_ptr
480 :    
481 :     /* vregs */
482 :     #ifdef VREGS
483 :     MOVE(MiscRegOffMSP(3)(temp),temp2,vreg0)
484 :     MOVE(MiscRegOffMSP(4)(temp),temp2,vreg1)
485 :     MOVE(MiscRegOffMSP(5)(temp),temp2,vreg2)
486 :     MOVE(MiscRegOffMSP(6)(temp),temp2,vreg3)
487 :     MOVE(MiscRegOffMSP(7)(temp), temp2, vreg4)
488 :     MOVE(MiscRegOffMSP(8)(temp), temp2, vreg5)
489 :     MOVE(MiscRegOffMSP(9)(temp), temp2, vreg6)
490 :     MOVE(MiscRegOffMSP(10)(temp), temp2, vreg7)
491 :     MOVE(MiscRegOffMSP(11)(temp), temp2, vreg8)
492 :     MOVE(MiscRegOffMSP(12)(temp), temp2, vreg9)
493 :     MOVE(MiscRegOffMSP(13)(temp), temp2, vreg10)
494 :     MOVE(MiscRegOffMSP(14)(temp), temp2, vreg11)
495 :     #endif
496 :     /* pseudo regs */
497 :     MOVE(PseudoReg1OffMSP(temp),temp2,PSEUDOREG_1)
498 :     MOVE(PseudoReg2OffMSP(temp),temp2,PSEUDOREG_2)
499 :    
500 :     #undef temp2
501 :    
502 :     /* Load ML registers. */
503 :     movl AllocPtrOffMSP(temp), allocptr
504 :     movl StdContOffMSP(temp), stdcont
505 :     movl StdArgOffMSP(temp), stdarg
506 :     movl MiscRegOffMSP(0)(temp), misc1
507 :     movl MiscRegOffMSP(1)(temp), misc2
508 :     movl MiscRegOffMSP(2)(temp), misc3
509 :    
510 :     movl %esp,CSYM(ML_X86Frame) /* frame ptr for signal handler. */
511 :    
512 :     pushl misc2 /* free up a register */
513 :     pushl temp /* save msp temporarily */
514 :    
515 :     #define tmpreg misc2
516 :    
517 :     /* note that we're entering ML */
518 :     movl VProcOffMSP(temp),temp /* temp is now vsp */
519 :     #define vsp temp
520 :     movl $1,InMLOffVSP(vsp)
521 :    
522 :     /* handle signals */
523 :     movl NPendingSysOffVSP(vsp),tmpreg
524 :     addl NPendingOffVSP(vsp),tmpreg
525 :     cmpl $0,tmpreg
526 :     #undef tmpreg
527 :     jne pending
528 :    
529 :     restore_and_jmp_ml:
530 :     popl temp /* restore temp to msp */
531 :     popl misc2
532 :    
533 :     jmp_ml:
534 :     movl PCOffMSP(temp),temp
535 :     cmpl limitptr, allocptr
536 :     jmpl temp /* Jump to ML code. */
537 :    
538 :     pending:
539 :     cmpl $0,InSigHandlerOffVSP(vsp) /* Currently handling signal? */
540 :     jne restore_and_jmp_ml
541 :     movl $1,HandlerPendingOffVSP(vsp) /* handler trap is now pending */
542 :    
543 :     /* must restore here because limitptr is on stack */
544 :     popl temp /* restore temp to msp */
545 :     popl misc2
546 :    
547 :     movl allocptr,limitptr
548 :     jmp jmp_ml /* Jump to ML code. */
549 :    
550 :     #undef vsp
551 :    
552 :     /* ----------------------------------------------------------------------
553 :     * array : (int * 'a) -> 'a array
554 :     * Allocate and initialize a new array. This can cause GC.
555 :     */
556 :    
557 :     ML_CODE_HDR(array_a)
558 :     CHECKLIMIT(FUN_MASK)
559 :     movl 0(stdarg),temp /* desired length into temp */
560 :     sarl $1,temp /* untagged */
561 :     cmpl $SMALL_OBJ_SZW,temp
562 :     jge 3f
563 :    
564 :     #define tmpreg misc1
565 :     pushl tmpreg
566 :    
567 :     movl temp,tmpreg /* build descriptor in tmpreg */
568 :     sall $TAG_SHIFTW,tmpreg
569 :     orl $MAKE_TAG(DTAG_array),tmpreg
570 :     movl tmpreg,0(allocptr) /* write descriptor */
571 :     addl $4,allocptr
572 :     movl 4(stdarg),tmpreg /* initial values */
573 :     movl allocptr,stdarg /* stdarg gets ptr to new array */
574 :     sall $2,temp /* length in bytes */
575 :     addl allocptr,temp
576 :     xchgl tmpreg,temp /* tmpreg is end of array */
577 :     2: /* loop: */
578 :     stosl /* 0(allocptr++) <- temp */
579 :     cmpl allocptr,tmpreg /* check for end of array */
580 :     jne 2b
581 :    
582 :     popl tmpreg
583 :     #undef tmpreg
584 :    
585 :     CONTINUE
586 :     3:
587 :     movl mlstate_ptr, temp
588 :     movl $REQ_ALLOC_ARRAY, request_w
589 :     movl $FUN_MASK, mask
590 :     jmp CSYM(set_request)
591 :    
592 :    
593 :     /* create_r : int -> realarray */
594 :     ML_CODE_HDR(create_r_a)
595 :     CHECKLIMIT(FUN_MASK)
596 :     movl stdarg,temp /* desired length into temp */
597 :     sarl $1,temp /* untagged */
598 :     shll $1,temp /* size in words */
599 :     cmpl $SMALL_OBJ_SZW,temp
600 :     jge 2f
601 :    
602 :     #define tmpreg misc1
603 :     pushl tmpreg
604 :    
605 :     shrl $1,temp /* size in reals */
606 :     movl temp,tmpreg /* build descriptor in tmpreg */
607 :     sall $TAG_SHIFTW,tmpreg
608 :     orl $MAKE_TAG(DTAG_realdarray),tmpreg
609 :     movl tmpreg,0(allocptr) /* write descriptor */
610 :     addl $4,allocptr
611 :     movl allocptr,stdarg /* stdarg gets ptr to new array */
612 :     sall $3,temp /* length in bytes */
613 :     addl temp,allocptr /* adjust allocptr past array */
614 :    
615 :     popl tmpreg
616 :     #undef tmpreg
617 :     CONTINUE
618 :     2:
619 :     movl mlstate_ptr, temp
620 :     movl $REQ_ALLOC_REALDARRAY, request_w
621 :     movl $FUN_MASK, mask
622 :     jmp CSYM(set_request)
623 :    
624 :    
625 :     /* create_b : int -> bytearray */
626 :     ML_CODE_HDR(create_b_a)
627 :     CHECKLIMIT(FUN_MASK)
628 :     movl stdarg,temp /* the length */
629 :     sarl $1,temp /* untagged */
630 :     addl $3,temp /* round */
631 :     sarl $2,temp /* to words */
632 :     cmpl $SMALL_OBJ_SZW,temp
633 :     jge 2f
634 :    
635 :     #define tmpreg misc1
636 :     pushl tmpreg
637 :    
638 :     movl stdarg,tmpreg /* build descriptor in tmpreg */
639 :     sarl $1,tmpreg
640 :     sall $TAG_SHIFTW,tmpreg
641 :     orl $MAKE_TAG(DTAG_bytearray),tmpreg
642 :     movl tmpreg,0(allocptr) /* write descriptor */
643 :     addl $4,allocptr
644 :     movl allocptr,stdarg /* stdarg gets ptr to new str */
645 :     sall $2,temp /* length in bytes (untagged) */
646 :     addl temp,allocptr /* allocptr += total length */
647 :    
648 :     popl tmpreg
649 :     #undef tmpreg
650 :    
651 :     CONTINUE
652 :     2:
653 :     movl mlstate_ptr, temp
654 :     movl $REQ_ALLOC_BYTEARRAY, request_w
655 :     movl $FUN_MASK, mask
656 :     jmp CSYM(set_request)
657 :    
658 :    
659 :     /* create_s : int -> string */
660 :     ML_CODE_HDR(create_s_a)
661 :     CHECKLIMIT(FUN_MASK)
662 :     movl stdarg,temp /* the length */
663 :     sarl $1,temp /* untagged */
664 :     addl $4,temp /* round */
665 :     sarl $2,temp /* to words */
666 :     cmpl $SMALL_OBJ_SZW,temp
667 :     jge 2f
668 :    
669 :     #define tmpreg misc1
670 :     pushl tmpreg
671 :    
672 :     movl stdarg,tmpreg /* build descriptor in tmpreg */
673 :     sarl $1,tmpreg
674 :     sall $TAG_SHIFTW,tmpreg
675 :     orl $MAKE_TAG(DTAG_string),tmpreg
676 :     movl tmpreg,0(allocptr) /* write descriptor */
677 :     addl $4,allocptr
678 :     movl allocptr,stdarg /* stdarg gets ptr to new str */
679 :     sall $2,temp /* length in bytes (untagged) */
680 :     addl temp,allocptr /* allocptr += total length */
681 :     movl $0,-4(allocptr) /* for fast strcmp */
682 :    
683 :     popl tmpreg
684 :     #undef tmpreg
685 :    
686 :     CONTINUE
687 :     2:
688 :     movl mlstate_ptr, temp
689 :     movl $REQ_ALLOC_STRING, request_w
690 :     movl $FUN_MASK, mask
691 :     jmp CSYM(set_request)
692 :    
693 :     /* create_v_a : int * 'a list -> 'a vector
694 :     * creates a vector with elements taken from a list.
695 :     * n.b. The frontend ensures that list cannot be nil.
696 :     */
697 :     ML_CODE_HDR(create_v_a)
698 :     CHECKLIMIT(FUN_MASK)
699 :     movl 0(stdarg),temp /* desired length into temp */
700 :     sarl $1,temp /* untagged */
701 :     cmpl $SMALL_OBJ_SZW,temp
702 :     jge 3f
703 :    
704 :     #define tmpreg misc1
705 :     pushl tmpreg
706 :    
707 :     movl temp,tmpreg /* build descriptor in tmpreg */
708 :     sall $TAG_SHIFTW,tmpreg
709 :     orl $MAKE_TAG(DTAG_vector),tmpreg
710 :     movl tmpreg,0(allocptr) /* write descriptor */
711 :     addl $4,allocptr
712 :     movl 4(stdarg),tmpreg /* list of initial values */
713 :     movl allocptr,stdarg /* stdarg gets ptr to new array */
714 :     2: /* loop: */
715 :     movl 0(tmpreg),temp /* temp <- hd(tmpreg) */
716 :     stosl /* 0(allocptr++) <- temp */
717 :     movl 4(tmpreg),tmpreg /* tmpreg <- tl(tmpreg) */
718 :     cmpl $ML_nil,tmpreg /* end of list */
719 :     jne 2b
720 :    
721 :     popl tmpreg
722 :     #undef tmpreg
723 :    
724 :     CONTINUE
725 :     3:
726 :     movl mlstate_ptr, temp
727 :     movl $REQ_ALLOC_VECTOR, request_w
728 :     movl $FUN_MASK, mask
729 :     jmp CSYM(set_request)
730 :    
731 :     /* try_lock: spin_lock -> bool.
732 :     * low-level test-and-set style primitive for mutual-exclusion among
733 :     * processors. For now, we only provide a uni-processor trivial version.
734 :     */
735 :     ML_CODE_HDR(try_lock_a)
736 :     #if (MAX_PROCS > 1)
737 :     # error multiple processors not supported
738 :     #else /* (MAX_PROCS == 1) */
739 :     movl (stdarg), temp /* Get old value of lock. */
740 :     movl $1, (stdarg) /* Set the lock to ML_false. */
741 :     movl temp, stdarg /* Return old value of lock. */
742 :     CONTINUE
743 :     #endif
744 :    
745 :     /* unlock : releases a spin lock
746 :     */
747 :     ML_CODE_HDR(unlock_a)
748 :     #if (MAX_PROCS > 1)
749 :     # error multiple processors not supported
750 :     #else /* (MAX_PROCS == 1) */
751 :     movl $3, (stdarg) /* Store ML_true into lock. */
752 :     movl $1, stdarg /* Return unit. */
753 :     CONTINUE
754 :     #endif
755 :    
756 :    
757 :     /********************* Floating point functions. *********************/
758 :    
759 :     #define FPOP fstp %st /* Pop the floating point register stack. */
760 :    
761 :    
762 :     /* Temporary storage for the old and new floating point control
763 :     word. We don't use the stack to for this, since doing so would
764 :     change the offsets of the pseudo-registers. */
765 : monnier 8 DATA
766 :     ALIGN4
767 : monnier 2 old_controlwd:
768 :     .word 0
769 :     new_controlwd:
770 :     .word 0
771 :     TEXT
772 :     ALIGN4
773 :    
774 :     /*
775 :     * Initialize the 80387 floating point coprocessor. First, the floating
776 :     * point control word is initialized (undefined fields are left
777 :     * unchanged). Rounding control is set to "nearest" (although floor_a
778 :     * needs "toward negative infinity"). Precision control is set to
779 :     * "double". The precision, underflow, denormal
780 :     * overflow, zero divide, and invalid operation exceptions
781 :     * are masked. Next, seven of the eight available entries on the
782 :     * floating point register stack are claimed (see x86/x86.sml).
783 :     *
784 :     * NB: this cannot trash any registers because it's called from request_fault.
785 :     */
786 :     ENTRY(FPEEnable)
787 :     finit
788 :     subl $4, %esp /* Temp space. Keep stack aligned. */
789 :     fstcw (%esp) /* Store FP control word. */
790 :     andw $0xf0c0, (%esp) /* Keep undefined fields, clear others. */
791 :     orw $0x023f, (%esp) /* Set fields (see above). */
792 :     fldcw (%esp) /* Install new control word. */
793 :     addl $4, %esp
794 :     fldz /* Push a zero onto the register stack. */
795 :     fld %st /* Copy it 6 times. */
796 :     fld %st
797 :     fld %st
798 :     fld %st
799 :     fld %st
800 :     fld %st
801 :     ret
802 :    
803 :     #if (defined(OPSYS_LINUX) || defined(OPSYS_SOLARIS))
804 :     ENTRY(fegetround)
805 :     subl $4, %esp /* allocate temporary space */
806 :     fstcw (%esp) /* store fp control word */
807 :     sarl $10,(%esp) /* rounding mode is at bit 10 and 11 */
808 :     andl $3, (%esp) /* mask two bits */
809 :     movl (%esp),%eax /* return rounding mode */
810 :     addl $4, %esp /* deallocate space */
811 :     ret
812 :    
813 :     ENTRY(fesetround)
814 :     subl $4, %esp /* allocate temporary space */
815 :     fstcw (%esp) /* store fp control word */
816 :     andw $0xf3ff, (%esp) /* Clear rounding field. */
817 :     movl 8(%esp), %eax /* new rounding mode */
818 :     sall $10, %eax /* move to right place */
819 :     orl %eax,(%esp) /* new control word */
820 :     fldcw (%esp) /* load new control word */
821 :     addl $4, %esp /* deallocate space */
822 :     ret
823 :     #endif
824 :    
825 :     /* Save the state of the floating point unit. */
826 :     ENTRY(savefpregs)
827 :     movl 4(%esp), temp /* Get pointer argument. */
828 :     fsave (temp)
829 :     ret
830 :    
831 :     /* Restore the state of the floating point unit. */
832 :     ENTRY(restorefpregs)
833 :     movl 4(%esp), temp /* Arg is an ML string. */
834 :     frstor (temp)
835 :     ret
836 :    
837 :     /* floor : real -> int
838 : monnier 8 Return the nearest integer that is less or equal to the argument.
839 :     Caller's responsibility to make sure arg is in range. */
840 : monnier 2
841 :     ML_CODE_HDR(floor_a)
842 :     fstcw old_controlwd /* Get FP control word. */
843 :     movw old_controlwd, %ax
844 :     andw $0xf3ff, %ax /* Clear rounding field. */
845 :     orw $0x0400, %ax /* Round towards neg. infinity. */
846 :     movw %ax, new_controlwd
847 :     fldcw new_controlwd /* Install new control word. */
848 :    
849 :     fldl (stdarg) /* Load argument. */
850 :     subl $4, %esp
851 :     fistpl (%esp) /* Round, store, and pop. */
852 :     popl stdarg
853 :     sall $1, stdarg /* Tag the resulting integer. */
854 :     incl stdarg
855 :    
856 :     fldcw old_controlwd /* Restore old FP control word. */
857 :     CONTINUE
858 :    
859 :     /* logb : real -> int
860 :     * Extract the unbiased exponent pointed to by stdarg.
861 :     * Note: Using fxtract, and fistl does not work for inf's and nan's.
862 :     */
863 :     ML_CODE_HDR(logb_a)
864 :     movl 4(stdarg),temp /* msb for little endian arch */
865 :     sarl $20, temp /* throw out 20 bits */
866 :     andl $0x7ff,temp /* clear all but 11 low bits */
867 :     subl $1023, temp /* unbias */
868 :     sall $1, temp /* room for tag bit */
869 :     addl $1, temp /* tag bit */
870 :     movl temp, stdarg
871 :     CONTINUE
872 :    
873 :    
874 :     /* scalb : (real * int) -> real
875 :     * Scale the first argument by 2 raised to the second argument. Raise
876 :     * Float("underflow") or Float("overflow") as appropriate.
877 :     * NB: We assume the first floating point "register" is
878 :     * caller-save, so we can use it here (see x86/x86.sml). */
879 :    
880 :     ML_CODE_HDR(scalb_a)
881 :     CHECKLIMIT(FUN_MASK)
882 :     pushl 4(stdarg) /* Get copy of scalar. */
883 :     sarl $1, (%esp) /* Untag it. */
884 :     fildl (%esp) /* Load it ... */
885 :     fstp %st(1) /* ... into 1st FP reg. */
886 :     addl $4, %esp /* Discard copy of scalar. */
887 :    
888 :     movl (stdarg), temp /* Get pointer to real. */
889 :     fldl (temp) /* Load it into temp. */
890 :    
891 :     fscale /* Multiply exponent by scalar. */
892 :     movl $DESC_reald, (allocptr)
893 :     fstpl 4(allocptr) /* Store resulting float. */
894 :     addl $4, allocptr /* Allocate word for tag. */
895 :     movl allocptr, stdarg /* Return a pointer to the float. */
896 :     addl $8, allocptr /* Allocate room for float. */
897 :     CONTINUE
898 :    
899 :     /* end of X86.prim.asm */

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