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.masm
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (view) (download)

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

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