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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 244 - (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 : monnier 243 *
7 :     * Heavily modified and changed to use assyntax.h, by Lal George.
8 : monnier 2 */
9 :    
10 :     #include "ml-base.h"
11 :     #include "asm-base.h"
12 :     #include "ml-values.h"
13 :     #include "tags.h"
14 :     #include "ml-request.h"
15 :     #include "ml-limits.h"
16 :    
17 :     /* enable/disable virtual (memory-based) registers.
18 :     * the number of vregs, etc. must concur with:
19 :     * src/runtime/include/ml-state.h
20 :     * src/runtime/kernel/ml-state.c
21 :     * src/sml-nj/x86/x86.sml
22 :     */
23 :    
24 : monnier 243 /* XXX: May no longer be needed */
25 : monnier 2 #ifndef VREGS
26 :     # define VREGS
27 :     #endif
28 :    
29 :     /*
30 :     *
31 :     * The 386 registers are used as follows:
32 :     *
33 :     * EAX - temp1 (see the code generator, x86/x86.sml)
34 : monnier 243 * EBX - misc0
35 :     * ECX - misc1
36 :     * EDX - misc2
37 : monnier 2 * ESI - standard continuation (ml_cont, see ml_state.h)
38 :     * EBP - standard argument (ml_arg)
39 :     * EDI - free space pointer (ml_allocptr)
40 :     * ESP - stack pointer
41 :     * EIP - program counter (ml_pc)
42 : monnier 243 */
43 : monnier 2
44 :     /* Registers (see x86/x86.sml): */
45 :     #define temp %eax
46 : monnier 243 #define misc0 %ebx
47 :     #define misc1 %ecx
48 :     #define misc2 %edx
49 : monnier 2 #define stdcont %esi
50 :     #define stdarg %ebp
51 :     #define allocptr %edi
52 : monnier 243 #define stackptr %esp
53 : monnier 2
54 :     /* other reg uses */
55 :     #define creturn %eax
56 :    
57 : monnier 243 /* Stack frame */
58 : monnier 2 #define tempmem 0(%esp)
59 : monnier 243 #define baseptr 4(%esp)
60 : monnier 2 #define exncont 8(%esp)
61 :     #define limitptr 12(%esp)
62 : monnier 243 #define pc 16(%esp)
63 :     #define unused_1 20(%esp)
64 : monnier 2 #define storeptr 24(%esp)
65 :     #define varptr 28(%esp)
66 :     #define start_gc 32(%esp)
67 : monnier 243 #define unused_2 36(%esp)
68 :     #define eaxSpill 40(%esp) /* eax=0 */
69 :     #define ecxSpill 44(%esp) /* ecx=1 */
70 :     #define edxSpill 48(%esp) /* edx=2 */
71 :     #define ebxSpill 52(%esp) /* ebx=3 */
72 :     #define espSpill 56(%esp) /* esp=4 */
73 :     #define ebpSpill 60(%esp) /* ebp=5 */
74 :     #define esiSpill 64(%esp) /* esi=6 */
75 :     #define ediSpill 68(%esp) /* edi=7 */
76 :     #define stdlink 72(%esp)
77 :     #define stdclos 76(%esp)
78 : monnier 2
79 : monnier 243 #define ML_STATE_OFFSET 176
80 :     #define mlstate_ptr ML_STATE_OFFSET(%esp)
81 :     #define freg8 184 /* double word aligned */
82 :     #define freg9 192
83 :     #define freg31 368 /* 152 + (31-8)*8 */
84 :     #define fpTempMem 376 /* freg31 + 8 */
85 :     #define SpillAreaStart 512 /* starting offset */
86 :     #define ML_FRAME_SIZE (8192)
87 : monnier 2
88 :     #define via
89 :    
90 :     DATA
91 :     ALIGN4
92 :     request_w: /* place to put the request code */
93 :     .long 0
94 :     GLOBAL(ML_X86Frame)
95 :     LABEL(CSYM(ML_X86Frame)) /* ptr to the ml frame (gives C access to limitptr) */
96 :     .long 0
97 :    
98 : monnier 243 SavedSP:
99 :     .long 0 /* Value of stack pointer to restore */
100 : monnier 2
101 :    
102 :     #include "mlstate-offsets.h" /** this file is generated **/
103 :    
104 :    
105 :     /*
106 :     * 386 function call conventions:
107 :     * [true for gcc and dynix3 cc; untested for others]
108 :     *
109 :     * Caller save registers: eax, ecx, edx
110 :     * Callee save registers: ebx, esi, edi, and ebp.
111 :     * Floating point state is caller-save.
112 :     * Arguments passed on stack. Rightmost argument pushed first.
113 :     * Word-sized result returned in %eax.
114 :     */
115 :    
116 :     #define cresult %eax
117 :    
118 :     #define CALLEE_SAVE \
119 :     pushl %ebx; \
120 :     pushl %esi; \
121 :     pushl %edi; \
122 :     pushl %ebp
123 :    
124 :     #define CALLEE_RESTORE \
125 :     popl %ebp; \
126 :     popl %edi; \
127 :     popl %esi; \
128 :     popl %ebx
129 :    
130 :     /* MOVE copies one memory location to another, using a specified temporary. */
131 :    
132 :     #define MOVE(src,tmp,dest) \
133 :     movl src, tmp; \
134 :     movl tmp, dest
135 :    
136 : monnier 243 #define CONTINUE \
137 : monnier 2 jmp via stdcont
138 :    
139 : monnier 243 #define CHECKLIMIT \
140 :     1:; \
141 :     MOVE(stdlink, temp, pc) ; \
142 :     cmpl limitptr, allocptr; \
143 :     jb 9f; \
144 :     call via CSYM(saveregs); \
145 :     jmp via 1b; \
146 : monnier 2 9:
147 :    
148 :     /**********************************************************************/
149 :     TEXT
150 :     ALIGN4
151 :    
152 :     ML_CODE_HDR(sigh_return_a)
153 : monnier 243 movl IMMED(ML_unit),stdlink
154 :     movl IMMED(ML_unit),stdclos
155 :     movl IMMED(ML_unit),pc
156 : monnier 29 movl IMMED(REQ_SIG_RETURN), request_w
157 : monnier 2 jmp CSYM(set_request)
158 :    
159 :     /* sigh_resume:
160 :     * Resume execution at the point at which a handler trap occurred. This is a
161 :     * standard two-argument function, thus the closure is in ml_cont.
162 :     */
163 :    
164 :     ENTRY(sigh_resume)
165 : monnier 29 movl IMMED(REQ_SIG_RESUME), request_w
166 : monnier 243 movl IMMED(ML_unit),stdlink
167 :     movl IMMED(ML_unit),stdclos
168 :     movl IMMED(ML_unit),pc
169 : monnier 2 jmp CSYM(set_request)
170 :    
171 :     /* pollh_return_a:
172 :     * The return continuation for the ML poll handler.
173 :     */
174 :     ML_CODE_HDR(pollh_return_a)
175 : monnier 29 movl IMMED(REQ_POLL_RETURN), request_w
176 : monnier 243 movl IMMED(ML_unit),stdlink
177 :     movl IMMED(ML_unit),stdclos
178 :     movl IMMED(ML_unit),pc
179 : monnier 2 jmp CSYM(set_request)
180 :    
181 :     /* pollh_resume:
182 :     * Resume execution at the point at which a poll event occurred.
183 :     */
184 :     ENTRY(pollh_resume)
185 : monnier 29 movl IMMED(REQ_POLL_RESUME), request_w
186 : monnier 243 movl IMMED(ML_unit),stdlink
187 :     movl IMMED(ML_unit),stdclos
188 :     movl IMMED(ML_unit),pc
189 : monnier 2 jmp CSYM(set_request)
190 :    
191 :     ML_CODE_HDR(handle_a)
192 : monnier 29 movl IMMED(REQ_EXN), request_w
193 : monnier 243 MOVE (stdlink,temp,pc)
194 : monnier 2 jmp CSYM(set_request)
195 :    
196 :     ML_CODE_HDR(return_a)
197 : monnier 29 movl IMMED(REQ_RETURN), request_w
198 : monnier 243 movl IMMED(ML_unit),stdlink
199 :     movl IMMED(ML_unit),stdclos
200 :     movl IMMED(ML_unit),pc
201 : monnier 2 jmp CSYM(set_request)
202 :    
203 :     /* Request a fault. The floating point coprocessor must be reset
204 :     * (thus trashing the FP registers) since we don't know whether a
205 :     * value has been pushed into the temporary "register". This is OK
206 :     * because no floating point registers will be live at the start of
207 :     * the exception handler.
208 :     */
209 :     ENTRY(request_fault)
210 :     call CSYM(FPEEnable) /* Doesn't trash any general regs. */
211 : monnier 29 movl IMMED(REQ_FAULT), request_w
212 : monnier 243 MOVE (stdlink,temp,pc)
213 : monnier 2 jmp CSYM(set_request)
214 :    
215 :     /* bind_cfun : (string * string) -> c_function
216 :     */
217 :     ML_CODE_HDR(bind_cfun_a)
218 : monnier 243 CHECKLIMIT
219 : monnier 29 movl IMMED(REQ_BIND_CFUN), request_w
220 : monnier 2 jmp CSYM(set_request)
221 :    
222 :     ML_CODE_HDR(build_literals_a)
223 : monnier 243 CHECKLIMIT
224 : monnier 29 movl IMMED(REQ_BUILD_LITERALS), request_w
225 : monnier 2 jmp CSYM(set_request)
226 :    
227 :     ML_CODE_HDR(callc_a)
228 : monnier 243 CHECKLIMIT
229 : monnier 29 movl IMMED(REQ_CALLC), request_w
230 : monnier 243 jmp CSYM(set_request)
231 :    
232 :     ENTRY(saveregs)
233 :     popl pc
234 :     movl IMMED(REQ_GC), request_w
235 : monnier 2 /* fall into set_request */
236 :    
237 :     ENTRY(set_request)
238 :     /* temp holds mlstate_ptr, valid request in request_w */
239 :     /* Save registers */
240 : monnier 243 movl mlstate_ptr, temp
241 : monnier 2 movl allocptr,AllocPtrOffMSP(temp)
242 :     movl stdarg,StdArgOffMSP(temp)
243 :     movl stdcont,StdContOffMSP(temp)
244 :    
245 :     #define temp2 allocptr
246 :     /* note that we have left ML code */
247 :     movl VProcOffMSP(temp),temp2
248 : monnier 29 movl IMMED(0), InMLOffVSP(temp2)
249 : monnier 2
250 : monnier 243 movl misc0, Misc0OffMSP(temp)
251 :     movl misc1, Misc1OffMSP(temp)
252 :     movl misc2, Misc2OffMSP(temp)
253 : monnier 2
254 :     /* Save vregs before the stack frame is popped. */
255 :     MOVE(limitptr,temp2, LimitPtrOffMSP(temp))
256 :     MOVE(exncont, temp2, ExnPtrOffMSP(temp))
257 :     MOVE(stdclos, temp2, StdClosOffMSP(temp))
258 :     MOVE(stdlink, temp2, LinkRegOffMSP(temp))
259 : monnier 243 MOVE(pc, temp2, PCOffMSP(temp))
260 : monnier 2 MOVE(storeptr,temp2, StorePtrOffMSP(temp))
261 :     MOVE(varptr, temp2, VarPtrOffMSP(temp))
262 :     #undef temp2
263 :    
264 :     /* return val of function is request code */
265 :     movl request_w,creturn
266 :    
267 :     /* Pop the stack frame and return to run_ml(). */
268 : monnier 243 movl SavedSP, %esp
269 : monnier 2 CALLEE_RESTORE
270 :     ret
271 :    
272 :     TEXT
273 :     ALIGN4
274 :     ENTRY(restoreregs)
275 :     movl 4(%esp), temp /* Get argument (MLState ptr). */
276 :     CALLEE_SAVE
277 :    
278 : monnier 243 movl %esp, SavedSP /* save stack pointer */
279 :    
280 :     /* Align on 8 byte boundary. Assumes that the stack
281 :     * starts out being at least word aligned. But who knows ...
282 :     */
283 :     orl IMMED(4), %esp
284 :     subl IMMED(4), %esp /* stack grows from high to low */
285 :    
286 : monnier 2 #define temp2 %ebx
287 :     /* Allocate and initialize the ML stack frame. */
288 : monnier 29 subl IMMED(ML_FRAME_SIZE), %esp
289 : monnier 243 MOVE (ExnPtrOffMSP(temp), temp2, exncont)
290 :     MOVE (LimitPtrOffMSP(temp), temp2, limitptr)
291 :     MOVE (StorePtrOffMSP(temp), temp2, storeptr)
292 :     MOVE (VarPtrOffMSP(temp), temp2, varptr)
293 : monnier 2 lea CSYM(saveregs), temp2
294 :     movl temp2,start_gc
295 :     movl temp, mlstate_ptr
296 :    
297 :     /* vregs */
298 : monnier 243 MOVE (LinkRegOffMSP(temp), temp2, stdlink)
299 :     MOVE (StdClosOffMSP(temp), temp2, stdclos)
300 : monnier 2 #undef temp2
301 :    
302 :     /* Load ML registers. */
303 :     movl AllocPtrOffMSP(temp), allocptr
304 :     movl StdContOffMSP(temp), stdcont
305 :     movl StdArgOffMSP(temp), stdarg
306 : monnier 243 movl Misc0OffMSP(temp), misc0
307 :     movl Misc1OffMSP(temp), misc1
308 :     movl Misc2OffMSP(temp), misc2
309 : monnier 2
310 :     movl %esp,CSYM(ML_X86Frame) /* frame ptr for signal handler. */
311 :    
312 :     pushl misc2 /* free up a register */
313 :     pushl temp /* save msp temporarily */
314 :    
315 :     #define tmpreg misc2
316 :    
317 :     /* note that we're entering ML */
318 :     movl VProcOffMSP(temp),temp /* temp is now vsp */
319 :     #define vsp temp
320 : monnier 29 movl IMMED(1),InMLOffVSP(vsp)
321 : monnier 2
322 :     /* handle signals */
323 :     movl NPendingSysOffVSP(vsp),tmpreg
324 :     addl NPendingOffVSP(vsp),tmpreg
325 : monnier 29 cmpl IMMED(0),tmpreg
326 : monnier 2 #undef tmpreg
327 :     jne pending
328 :    
329 :     restore_and_jmp_ml:
330 :     popl temp /* restore temp to msp */
331 :     popl misc2
332 :    
333 :     jmp_ml:
334 :     cmpl limitptr, allocptr
335 : monnier 243 jmpl PCOffMSP(temp) /* Jump to ML code. */
336 : monnier 2
337 : monnier 243
338 : monnier 2 pending:
339 : monnier 29 cmpl IMMED(0),InSigHandlerOffVSP(vsp) /* Currently handling signal? */
340 : monnier 2 jne restore_and_jmp_ml
341 : monnier 29 movl IMMED(1),HandlerPendingOffVSP(vsp) /* handler trap is now pending */
342 : monnier 2
343 : monnier 243 /* must restore here because limitptr is on stack */ /* XXX */
344 : monnier 2 popl temp /* restore temp to msp */
345 :     popl misc2
346 :    
347 :     movl allocptr,limitptr
348 :     jmp jmp_ml /* Jump to ML code. */
349 :     #undef vsp
350 :    
351 :     /* ----------------------------------------------------------------------
352 :     * array : (int * 'a) -> 'a array
353 :     * Allocate and initialize a new array. This can cause GC.
354 :     */
355 :     ML_CODE_HDR(array_a)
356 : monnier 243 CHECKLIMIT
357 :     movl 0(stdarg),temp /* temp := length in words */
358 :     sarl IMMED(1),temp /* temp := length untagged */
359 :     cmpl IMMED(SMALL_OBJ_SZW),temp /* is this a small object */
360 : monnier 2 jge 3f
361 :    
362 : monnier 243 #define temp1 misc0
363 :     #define temp2 misc1
364 :     pushl misc0 /* save misc0 */
365 :     pushl misc1 /* save misc1 */
366 :    
367 :     movl temp, temp1
368 :     sall IMMED(TAG_SHIFTW),temp1 /* build descriptor in temp1 */
369 :     orl IMMED(MAKE_TAG(DTAG_arr_data)),temp1
370 :     movl temp1,0(allocptr) /* store descriptor */
371 :     addl IMMED(4),allocptr /* allocptr++ */
372 :     movl allocptr, temp1 /* temp1 := array data ptr */
373 :     movl 4(stdarg), temp2 /* temp2 := initial value */
374 :     2:
375 :     movl temp2,0(allocptr) /* initialize array */
376 :     addl IMMED(4), allocptr
377 :     subl IMMED(1), temp
378 : monnier 2 jne 2b
379 :    
380 : monnier 243 /* Allocate array header */
381 :     movl IMMED(DESC_polyarr),0(allocptr) /* descriptor in temp */
382 :     addl IMMED(4), allocptr /* allocptr++ */
383 :     movl 0(stdarg), temp /* temp := length */
384 :     movl allocptr, stdarg /* result = header addr */
385 :     movl temp1, 0(allocptr) /* store pointer to data */
386 :     movl temp, 4(allocptr) /* store length */
387 :     addl IMMED(8), allocptr
388 : monnier 2
389 : monnier 243 popl misc1
390 :     popl misc0
391 : monnier 2 CONTINUE
392 : monnier 243 #undef temp1
393 :     #undef temp2
394 : monnier 2 3:
395 : monnier 29 movl IMMED(REQ_ALLOC_ARRAY), request_w
396 : monnier 243 MOVE (stdlink, temp, pc)
397 : monnier 2 jmp CSYM(set_request)
398 :    
399 :    
400 :     /* create_r : int -> realarray */
401 :     ML_CODE_HDR(create_r_a)
402 : monnier 243 CHECKLIMIT
403 :     #define temp1 misc0
404 :     push misc0 /* free temp1 */
405 :     movl stdarg,temp /* temp := length */
406 :     sarl IMMED(1),temp /* temp := untagged length */
407 :     shll IMMED(1),temp /* temp := length in words */
408 : monnier 29 cmpl IMMED(SMALL_OBJ_SZW),temp
409 : monnier 2 jge 2f
410 :    
411 : monnier 243 orl IMMED(4),allocptr /* align allocptr */
412 : monnier 2
413 : monnier 243 /* allocate the data object */
414 :     movl temp, temp1
415 :     shll IMMED(TAG_SHIFTW),temp1 /* temp1 := descriptor */
416 :     orl IMMED(MAKE_TAG(DTAG_raw64)),temp1
417 :     movl temp1,0(allocptr) /* store descriptor */
418 :     addl IMMED(4), allocptr /* allocptr++ */
419 :     movl allocptr, temp1 /* temp1 := data object */
420 :     shll IMMED(2),temp /* temp := length in bytes */
421 :     addl temp, allocptr /* allocptr += length */
422 : monnier 2
423 : monnier 243 /* allocate the header object */
424 :     movl IMMED(DESC_real64arr),0(allocptr)/* header descriptor */
425 :     addl IMMED(4), allocptr /* allocptr++ */
426 :     movl temp1, 0(allocptr) /* header data field */
427 :     movl stdarg, 4(allocptr) /* header length field */
428 :     movl allocptr, stdarg /* stdarg := header object */
429 :     addl IMMED(8), allocptr /* allocptr += 2 */
430 :    
431 :     popl misc0 /* restore temp1 */
432 : monnier 2 CONTINUE
433 : monnier 243
434 : monnier 2 2:
435 : monnier 243 popl misc0 /* restore temp1 */
436 : monnier 29 movl IMMED(REQ_ALLOC_REALDARRAY), request_w
437 : monnier 243 MOVE (stdlink, temp, pc)
438 : monnier 2 jmp CSYM(set_request)
439 : monnier 243 #undef temp1
440 : monnier 2
441 :    
442 :     /* create_b : int -> bytearray */
443 :     ML_CODE_HDR(create_b_a)
444 : monnier 243 CHECKLIMIT
445 :     movl stdarg,temp /* temp := length(tagged int) */
446 :     sarl IMMED(1),temp /* temp := length(untagged) */
447 :     addl IMMED(3),temp
448 :     sarl IMMED(2),temp /* temp := length(words) */
449 :     cmpl IMMED(SMALL_OBJ_SZW),temp /* small object? */
450 :     jmp 2f
451 : monnier 2 jge 2f
452 :    
453 : monnier 243 #define temp1 misc0
454 :     pushl misc0
455 : monnier 2
456 : monnier 243 /* allocate teh data object */
457 :     movl temp, temp1 /* temp1 := descriptor */
458 :     shll IMMED(TAG_SHIFTW),temp1
459 :     orl IMMED(MAKE_TAG(DTAG_raw32)),temp1
460 :     movl temp1, 0(allocptr) /* store descriptor */
461 :     addl IMMED(4), allocptr /* allocptr++ */
462 :     movl allocptr, temp1 /* temp1 := data object */
463 :     shll IMMED(2), temp /* temp := length in bytes */
464 :     addl temp, allocptr /* allocptr += length */
465 : monnier 2
466 : monnier 243 /* allocate the header object */
467 :     movl IMMED(DESC_word8arr), 0(allocptr)/* header descriptor */
468 :     addl IMMED(4),allocptr /* allocptr++ */
469 :     movl temp1, 0(allocptr) /* header data field */
470 :     movl stdarg,4(allocptr) /* header length field */
471 :     movl allocptr, stdarg /* stdarg := header object */
472 :     addl IMMED(8),allocptr /* allocptr := 2 */
473 :     popl misc0
474 : monnier 2 CONTINUE
475 : monnier 243 #undef temp1
476 : monnier 2 2:
477 : monnier 29 movl IMMED(REQ_ALLOC_BYTEARRAY), request_w
478 : monnier 243 MOVE (stdlink, temp, pc)
479 : monnier 2 jmp CSYM(set_request)
480 :    
481 :    
482 :     /* create_s : int -> string */
483 :     ML_CODE_HDR(create_s_a)
484 : monnier 243 CHECKLIMIT
485 :     movl stdarg,temp
486 :     sarl IMMED(1),temp /* temp := length(untagged) */
487 :     addl IMMED(4),temp
488 :     sarl IMMED(2),temp /* temp := length(words) */
489 : monnier 29 cmpl IMMED(SMALL_OBJ_SZW),temp
490 : monnier 2 jge 2f
491 :    
492 : monnier 243 pushl misc0 /* free misc0 */
493 :     #define temp1 misc0
494 : monnier 2
495 : monnier 243 movl temp, temp1
496 :     shll IMMED(TAG_SHIFTW),temp1 /* build descriptor in temp1 */
497 :     orl IMMED(MAKE_TAG(DTAG_raw32)), temp1
498 :     movl temp1, 0(allocptr) /* store the data pointer */
499 :     addl IMMED(4),allocptr /* allocptr++ */
500 : monnier 2
501 : monnier 243 movl allocptr, temp1 /* temp1 := data object */
502 :     shll IMMED(2),temp /* temp := length in bytes */
503 :     addl temp, allocptr /* allocptr += length */
504 :     movl IMMED(0),-4(allocptr) /* zero out the last word */
505 : monnier 2
506 : monnier 243 /* allocate the header object */
507 :     movl IMMED(DESC_string), temp /* header descriptor */
508 :     movl temp, 0(allocptr)
509 :     addl IMMED(4), allocptr /* allocptr++ */
510 :     movl temp1, 0(allocptr) /* header data field */
511 :     movl stdarg, 4(allocptr) /* header length field */
512 :     movl allocptr, stdarg /* stdarg := header object */
513 :     addl IMMED(8), allocptr
514 :    
515 :     popl misc0 /* restore misc0 */
516 :     #undef temp1
517 : monnier 2 CONTINUE
518 :     2:
519 : monnier 29 movl IMMED(REQ_ALLOC_STRING), request_w
520 : monnier 243 MOVE (stdlink, temp, pc)
521 : monnier 2 jmp CSYM(set_request)
522 :    
523 :     /* create_v_a : int * 'a list -> 'a vector
524 :     * creates a vector with elements taken from a list.
525 :     * n.b. The frontend ensures that list cannot be nil.
526 :     */
527 :     ML_CODE_HDR(create_v_a)
528 : monnier 243 CHECKLIMIT
529 :     pushl misc0
530 :     pushl misc1
531 :     #define temp1 misc0
532 :     #define temp2 misc1
533 :     movl 0(stdarg),temp /* temp := length(tagged) */
534 :     movl temp, temp1
535 :     sarl IMMED(1),temp1 /* temp1 := length(untagged) */
536 :     cmpl IMMED(SMALL_OBJ_SZW),temp1
537 : monnier 2 jge 3f
538 :    
539 :    
540 : monnier 243 shll IMMED(TAG_SHIFTW),temp1 /* build descriptor in temp1 */
541 :     orl IMMED(MAKE_TAG(DTAG_vec_data)),temp1
542 :     movl temp1,0(allocptr) /* store descriptor */
543 :     addl IMMED(4),allocptr /* allocptr++ */
544 :     movl 4(stdarg),temp1 /* temp1 := list */
545 :     movl allocptr,stdarg /* stdarg := vector */
546 :    
547 :     2:
548 :     movl 0(temp1),temp2 /* temp2 := hd(temp1) */
549 :     movl temp2, 0(allocptr) /* store word in vector */
550 :     addl IMMED(4), allocptr /* allocptr++ */
551 :     movl 4(temp1),temp1 /* temp1 := tl(temp1) */
552 :     cmpl IMMED(ML_nil),temp1 /* temp1 = nil? */
553 : monnier 2 jne 2b
554 :    
555 : monnier 243 /* allocate header object */
556 :     movl IMMED(DESC_polyvec),temp1/* descriptor in temp1 */
557 :     movl temp1, 0(allocptr) /* store descriptor */
558 :     addl IMMED(4),allocptr /* allocptr++ */
559 :     movl stdarg, 0(allocptr) /* header data field */
560 :     movl temp, 4(allocptr) /* header length */
561 :     movl allocptr, stdarg /* result = header object */
562 :     addl IMMED(8),allocptr /* allocptr += 2 */
563 : monnier 2
564 : monnier 243 popl misc1
565 :     popl misc0
566 : monnier 2 CONTINUE
567 :     3:
568 : monnier 243 popl misc1
569 :     popl misc0
570 : monnier 29 movl IMMED(REQ_ALLOC_VECTOR), request_w
571 : monnier 243 MOVE (stdlink, temp, pc)
572 : monnier 2 jmp CSYM(set_request)
573 : monnier 243 #undef temp1
574 :     #undef temp2
575 : monnier 2
576 :     /* try_lock: spin_lock -> bool.
577 :     * low-level test-and-set style primitive for mutual-exclusion among
578 :     * processors. For now, we only provide a uni-processor trivial version.
579 :     */
580 :     ML_CODE_HDR(try_lock_a)
581 :     #if (MAX_PROCS > 1)
582 :     # error multiple processors not supported
583 :     #else /* (MAX_PROCS == 1) */
584 :     movl (stdarg), temp /* Get old value of lock. */
585 : monnier 243 movl IMMED(1), (stdarg) /* Set the lock to ML_false. */
586 : monnier 2 movl temp, stdarg /* Return old value of lock. */
587 :     CONTINUE
588 :     #endif
589 :    
590 :     /* unlock : releases a spin lock
591 :     */
592 :     ML_CODE_HDR(unlock_a)
593 :     #if (MAX_PROCS > 1)
594 :     # error multiple processors not supported
595 :     #else /* (MAX_PROCS == 1) */
596 : monnier 29 movl IMMED(3), (stdarg) /* Store ML_true into lock. */
597 :     movl IMMED(1), stdarg /* Return unit. */
598 : monnier 2 CONTINUE
599 :     #endif
600 :    
601 :    
602 :     /********************* Floating point functions. *********************/
603 :    
604 :     #define FPOP fstp %st /* Pop the floating point register stack. */
605 :    
606 :    
607 :     /* Temporary storage for the old and new floating point control
608 :     word. We don't use the stack to for this, since doing so would
609 :     change the offsets of the pseudo-registers. */
610 : monnier 8 DATA
611 :     ALIGN4
612 : monnier 2 old_controlwd:
613 :     .word 0
614 :     new_controlwd:
615 :     .word 0
616 :     TEXT
617 :     ALIGN4
618 :    
619 :     /*
620 :     * Initialize the 80387 floating point coprocessor. First, the floating
621 :     * point control word is initialized (undefined fields are left
622 :     * unchanged). Rounding control is set to "nearest" (although floor_a
623 :     * needs "toward negative infinity"). Precision control is set to
624 :     * "double". The precision, underflow, denormal
625 :     * overflow, zero divide, and invalid operation exceptions
626 :     * are masked. Next, seven of the eight available entries on the
627 :     * floating point register stack are claimed (see x86/x86.sml).
628 :     *
629 :     * NB: this cannot trash any registers because it's called from request_fault.
630 :     */
631 :     ENTRY(FPEEnable)
632 :     finit
633 : monnier 29 subl IMMED(4), %esp /* Temp space. Keep stack aligned. */
634 : monnier 2 fstcw (%esp) /* Store FP control word. */
635 : monnier 29 andw IMMED(0xf0c0), (%esp) /* Keep undefined fields, clear others. */
636 :     orw IMMED(0x023f), (%esp) /* Set fields (see above). */
637 : monnier 2 fldcw (%esp) /* Install new control word. */
638 : monnier 29 addl IMMED(4), %esp
639 : monnier 2 ret
640 :    
641 :     #if (defined(OPSYS_LINUX) || defined(OPSYS_SOLARIS))
642 :     ENTRY(fegetround)
643 : monnier 29 subl IMMED(4), %esp /* allocate temporary space */
644 : monnier 2 fstcw (%esp) /* store fp control word */
645 : monnier 243 sarl IMMED(10),(%esp)/* rounding mode is at bit 10 and 11 */
646 :     andl IMMED(3), (%esp)/* mask two bits */
647 : monnier 2 movl (%esp),%eax /* return rounding mode */
648 : monnier 29 addl IMMED(4), %esp /* deallocate space */
649 : monnier 2 ret
650 :    
651 :     ENTRY(fesetround)
652 : monnier 29 subl IMMED(4), %esp /* allocate temporary space */
653 : monnier 2 fstcw (%esp) /* store fp control word */
654 : monnier 29 andw IMMED(0xf3ff), (%esp) /* Clear rounding field. */
655 : monnier 2 movl 8(%esp), %eax /* new rounding mode */
656 : monnier 29 sall IMMED(10), %eax /* move to right place */
657 : monnier 2 orl %eax,(%esp) /* new control word */
658 :     fldcw (%esp) /* load new control word */
659 : monnier 29 addl IMMED(4), %esp /* deallocate space */
660 : monnier 2 ret
661 :     #endif
662 :    
663 :     /* Save the state of the floating point unit. */
664 :     ENTRY(savefpregs)
665 :     movl 4(%esp), temp /* Get pointer argument. */
666 :     fsave (temp)
667 :     ret
668 :    
669 :     /* Restore the state of the floating point unit. */
670 :     ENTRY(restorefpregs)
671 :     movl 4(%esp), temp /* Arg is an ML string. */
672 :     frstor (temp)
673 :     ret
674 :    
675 :     /* floor : real -> int
676 : monnier 8 Return the nearest integer that is less or equal to the argument.
677 :     Caller's responsibility to make sure arg is in range. */
678 : monnier 2
679 :     ML_CODE_HDR(floor_a)
680 :     fstcw old_controlwd /* Get FP control word. */
681 :     movw old_controlwd, %ax
682 : monnier 243 andw IMMED(0xf3ff), %ax /* Clear rounding field. */
683 :     orw IMMED(0x0400), %ax /* Round towards neg. infinity. */
684 : monnier 2 movw %ax, new_controlwd
685 :     fldcw new_controlwd /* Install new control word. */
686 :    
687 :     fldl (stdarg) /* Load argument. */
688 : monnier 29 subl IMMED(4), %esp
689 : monnier 2 fistpl (%esp) /* Round, store, and pop. */
690 :     popl stdarg
691 : monnier 29 sall IMMED(1), stdarg /* Tag the resulting integer. */
692 : monnier 2 incl stdarg
693 :    
694 :     fldcw old_controlwd /* Restore old FP control word. */
695 :     CONTINUE
696 :    
697 :     /* logb : real -> int
698 :     * Extract the unbiased exponent pointed to by stdarg.
699 :     * Note: Using fxtract, and fistl does not work for inf's and nan's.
700 :     */
701 :     ML_CODE_HDR(logb_a)
702 :     movl 4(stdarg),temp /* msb for little endian arch */
703 : monnier 29 sarl IMMED(20), temp /* throw out 20 bits */
704 : monnier 243 andl IMMED(0x7ff),temp /* clear all but 11 low bits */
705 :     subl IMMED(1023), temp /* unbias */
706 : monnier 29 sall IMMED(1), temp /* room for tag bit */
707 :     addl IMMED(1), temp /* tag bit */
708 : monnier 2 movl temp, stdarg
709 :     CONTINUE
710 :    
711 :    
712 :     /* scalb : (real * int) -> real
713 :     * Scale the first argument by 2 raised to the second argument. Raise
714 :     * Float("underflow") or Float("overflow") as appropriate.
715 :     * NB: We assume the first floating point "register" is
716 :     * caller-save, so we can use it here (see x86/x86.sml). */
717 :    
718 :     ML_CODE_HDR(scalb_a)
719 : monnier 243 CHECKLIMIT
720 : monnier 2 pushl 4(stdarg) /* Get copy of scalar. */
721 : monnier 243 sarl IMMED(1), (%esp) /* Untag it. */
722 : monnier 2 fildl (%esp) /* Load it ... */
723 : monnier 243 /* fstp %st(1) */ /* ... into 1st FP reg. */
724 : monnier 2 movl (stdarg), temp /* Get pointer to real. */
725 :     fldl (temp) /* Load it into temp. */
726 :    
727 :     fscale /* Multiply exponent by scalar. */
728 : monnier 29 movl IMMED(DESC_reald), (allocptr)
729 : monnier 2 fstpl 4(allocptr) /* Store resulting float. */
730 : monnier 243 addl IMMED(4), allocptr /* Allocate word for tag. */
731 : monnier 2 movl allocptr, stdarg /* Return a pointer to the float. */
732 : monnier 243 addl IMMED(8), allocptr /* Allocate room for float. */
733 :     fstpl (%esp)
734 :     addl IMMED(4), %esp /* Discard copy of scalar. */
735 :    
736 : monnier 2 CONTINUE
737 :    
738 :     /* end of X86.prim.asm */

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