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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 249 - (view) (download)
Original Path: sml/branches/SMLNJ/src/runtime/mach-dep/SPARC.prim.asm

1 : monnier 249 /* SPARC.prim.asm
2 :     *
3 :     * COPYRIGHT (c) 1992 by AT&T Bell Laboratories.
4 :     *
5 :     * AUTHOR: John Reppy
6 :     * Cornell University
7 :     * Ithaca, NY 14853
8 :     * jhr@cs.cornell.edu
9 :     */
10 :    
11 :     #include "asm-base.h"
12 :     #include "ml-base.h"
13 :     #include "ml-values.h"
14 :     #include "tags.h"
15 :     #include "ml-request.h"
16 :     #include "ml-limits.h"
17 :     #include "mlstate-offsets.h" /** this file is generated **/
18 :    
19 :     /* SPARC runtime code for ML. Registers are used as follows:
20 :     *
21 :     * %g0 zero
22 :     * %g1 standard link
23 :     * %g2-3 misc regs
24 :     * %g4 heap limit pointer
25 :     * %g5 store pointer
26 :     * %g6 limit pointer
27 :     * %g7 exception handler
28 :     *
29 :     * %o0-1 misc regs
30 :     * %o2 asm tmp
31 :     * %o3-5 misc regs
32 :     * %o6 sp
33 :     * %o7 gcLink
34 :     *
35 :     * %l0-7 misc regs
36 :     *
37 :     * %i0 standard arg
38 :     * %i1 standard cont
39 :     * %i2 standard clos
40 :     * %i3 base ptr
41 :     * %i4 misc reg
42 :     * %i5 var ptr
43 :     * %i6 fp (don't touch)
44 :     * %i7 misc reg
45 :     *
46 :     */
47 :    
48 :    
49 :     #define ZERO %g0
50 :     #define EXNCONT %g7 /* exception handler (ml_exncont) */
51 :     #define ALLOCPTR %g6 /* freespace pointer (ml_allocptr) */
52 :     #define STOREPTR %g5 /* store pointer (ml_storeptr) */
53 :     #define LIMITPTR %g4 /* heap limit pointer (ml_limitptr)*/
54 :     #define STDARG %i0 /* standard argument (ml_arg) */
55 :     #define STDCONT %i1 /* standard continuation (ml_cont) */
56 :     #define STDCLOS %i2 /* standard closure (ml_clos) */
57 :     #define VARPTR %i5 /* var pointer (ml_varptr) */
58 :     #define STDLINK %g1 /* standard link (ml_linkptr) */
59 :     #define MISCREG0 %g2
60 :     #define MISCREG1 %g3
61 :     #define MISCREG2 %o0
62 :     #define PC %o7 /* ml_pc */
63 :    
64 :     #define ASMTMP %o2 /* assembly temporary used in ML */
65 :     #define TMPREG1 ASMTMP
66 :     #define TMPREG2 %o3
67 :     #define TMPREG3 %o4
68 :     #define TMPREG4 %o5
69 :    
70 :     /* %o2 and %o3 are also used as for multiply and divide */
71 :    
72 :     /*
73 :     * %o6 = %sp (not used by ML)
74 :     * %i6 = %fp (not used by ML)
75 :     * %i7 = return address to C code (not used by ML)
76 :     *
77 :     * The ML stack frame has the following layout (set up by restoreregs):
78 :     *
79 :     * | |
80 :     * %fp = %sp+112: | spill area |
81 :     * +-------------------+
82 :     * %sp+108: | unused |
83 :     * +-------------------+
84 :     * %sp+104: | saved %o7 |
85 :     * +-------------------+
86 :     * %sp+100: | addr of _saveregs |
87 :     * +-------------------+
88 :     * %sp+96: | ptr to MLState |
89 :     * +-------------------+
90 :     * %sp+92: | temp for floor |
91 :     * +-------------------+
92 :     * %sp+88: | temp for cvti2d |
93 :     * +-------------------+
94 :     * %sp+84: | addr of _ml_udiv |
95 :     * +-------------------+
96 :     * %sp+80: | addr of _ml_umul |
97 :     * +-------------------+
98 :     * %sp+76: | addr of _ml_div |
99 :     * +-------------------+
100 :     * %sp+72: | addr of _ml_mul |
101 :     * +-------------------+
102 :     * %sp+68: | saved %g6 |
103 :     * +-------------------+
104 :     * %sp+64: | saved %g7 |
105 :     * +-------------------+
106 :     * | space to save |
107 :     * | in and local |
108 :     * %sp: | registers |
109 :     * +-------------------+
110 :     *
111 :     * Note that this must be a multiple of 8 bytes. The size of the
112 :     * stack frame is:
113 :     */
114 :     #define ML_FRAMESIZE 4096
115 :    
116 :     #define MUL_OFFSET 72
117 :     #define DIV_OFFSET 76
118 :     #define UMUL_OFFSET 80
119 :     #define UDIV_OFFSET 84
120 :     #define FLOOR_OFFSET 92
121 :     #define MLSTATE_OFFSET 96
122 :     #define STARTGC_OFFSET 100
123 :     #define i7_OFFSET 104
124 :    
125 :     #define CONTINUE \
126 :     jmp STDCONT; \
127 :     subcc ALLOCPTR,LIMITPTR,%g0
128 :    
129 :     #define CHECKLIMIT(label) \
130 :     blu label; \
131 :     nop; \
132 :     mov STDLINK,PC; \
133 :     ba CSYM(saveregs); \
134 :     nop; \
135 :     label:
136 :    
137 :    
138 :     TEXT
139 :    
140 :     /* sigh_return_a:
141 :     * The return continuation for the ML signal handler.
142 :     */
143 :     ML_CODE_HDR(sigh_return_a)
144 :     set ML_unit,STDLINK
145 :     set ML_unit,STDCLOS
146 :     set ML_unit,PC
147 :     ba set_request
148 :     set REQ_SIG_RETURN,TMPREG3 /* (delay slot) */
149 :    
150 :     /* sigh_resume:
151 :     * Resume execution at the point at which a handler trap occurred. This is a
152 :     * standard two-argument function, thus the closure is in ml_cont (stdcont).
153 :     */
154 :     ENTRY(sigh_resume)
155 :     mov STDLINK,PC
156 :     ba set_request
157 :     set REQ_SIG_RESUME,TMPREG3 /* (delay slot) */
158 :    
159 :     /* pollh_return_a:
160 :     * The return continuation for the ML poll handler.
161 :     */
162 :     ML_CODE_HDR(pollh_return_a)
163 :     set ML_unit,STDLINK
164 :     set ML_unit,STDCLOS
165 :     set ML_unit,PC
166 :     ba set_request
167 :     set REQ_POLL_RETURN,TMPREG3 /* (delay slot) */
168 :    
169 :     /* pollh_resume:
170 :     * Resume execution at the point at which a poll event occurred.
171 :     */
172 :     ENTRY(pollh_resume)
173 :     mov STDLINK,PC
174 :     ba set_request
175 :     set REQ_POLL_RESUME,TMPREG3 /* (delay slot) */
176 :    
177 :     ML_CODE_HDR(handle_a)
178 :     mov STDLINK,PC
179 :     ba set_request
180 :     set REQ_EXN,TMPREG3 /* (delay slot) */
181 :    
182 :     ML_CODE_HDR(return_a)
183 :     set ML_unit,STDLINK
184 :     set ML_unit,STDCLOS
185 :     set ML_unit,PC
186 :     ba set_request
187 :     set REQ_RETURN,TMPREG3 /* (delay slot) */
188 :    
189 :     ENTRY(request_fault)
190 :     mov STDLINK,PC
191 :     ba set_request
192 :     set REQ_FAULT,TMPREG3 /* (delay slot) */
193 :    
194 :     /* bind_cfun : (string * string) -> c_function
195 :     */
196 :     ML_CODE_HDR(bind_cfun_a)
197 :     CHECKLIMIT(bind_cfun_v_limit)
198 :     ba set_request
199 :     set REQ_BIND_CFUN,TMPREG3 /* (delay slot) */
200 :    
201 :     ML_CODE_HDR(build_literals_a)
202 :     CHECKLIMIT(build_literals_a_limit)
203 :     ba set_request
204 :     set REQ_BUILD_LITERALS,TMPREG3 /* (delay slot) */
205 :    
206 :     ML_CODE_HDR(callc_a)
207 :     CHECKLIMIT(callc_a_limit)
208 :     ba set_request
209 :     set REQ_CALLC,TMPREG3 /* (delay slot) */
210 :    
211 :     /*
212 :     * This is the entry point for starting gc called from ML's code.
213 :     * I've added an adjustment to the return address. The generated ML code
214 :     * uses the JMPL instruction, which does not add an offset of 8 to the
215 :     * correct return address.
216 :     *
217 :     * Allen 6/5/1998
218 :     */
219 :     ENTRY(saveregs0)
220 :     add PC, 8, PC
221 :     ENTRY(saveregs)
222 :     set REQ_GC,TMPREG3
223 :     /* fall through */
224 :    
225 :     set_request:
226 :     ld [%sp+MLSTATE_OFFSET],TMPREG2 /* get MLState ptr from stack */
227 :     ld [TMPREG2+VProcOffMSP],TMPREG1 /* TMPREG1 := VProcPtr */
228 :     st %g0,[TMPREG1+InMLOffVSP] /* note that we have left ML code */
229 :     st ALLOCPTR,[TMPREG2+AllocPtrOffMSP]
230 :     st LIMITPTR,[TMPREG2+LimitPtrOffMSP]
231 :     st STOREPTR,[TMPREG2+StorePtrOffMSP]/* save storeptr */
232 :     st STDLINK,[TMPREG2+LinkRegOffMSP]
233 :     st PC,[TMPREG2+PCOffMSP] /* PC of called function */
234 :     st STDARG,[TMPREG2+StdArgOffMSP] /* save stdarg */
235 :     st STDCLOS,[TMPREG2+StdClosOffMSP] /* save closure */
236 :     st STDCONT,[TMPREG2+StdContOffMSP] /* save stdcont */
237 :     st VARPTR,[TMPREG2+VarPtrOffMSP] /* save varptr */
238 :     st EXNCONT,[TMPREG2+ExnPtrOffMSP] /* save exncont */
239 :     st MISCREG0,[TMPREG2+Misc0OffMSP]
240 :     st MISCREG1,[TMPREG2+Misc1OffMSP]
241 :     st MISCREG2,[TMPREG2+Misc2OffMSP]
242 :    
243 :     ldd [%sp+64],%g6 /* restore C registers %g6 & %g7.*/
244 :     ld [%sp+i7_OFFSET],%i7 /* restore C return address */
245 :     mov TMPREG3,%i0 /* return request code */
246 :     ret
247 :     restore /* delay slot */
248 :    
249 :    
250 :     #define MLState ASMTMP
251 :     #define VProcPtr TMPREG4
252 :     ENTRY(restoreregs)
253 :     save %sp,-SA(ML_FRAMESIZE),%sp
254 :     st %i0,[%sp+MLSTATE_OFFSET] /* save MLState ptr on stack */
255 :     set CSYM(saveregs0),ASMTMP
256 :     st ASMTMP,[%sp+STARTGC_OFFSET]
257 :     mov %i0,MLState /* transfer MLState ptr to tmpreg4 */
258 :     std %g6,[%sp+64] /* save C registers %g6 & %g7 */
259 :     st %i7, [%sp+i7_OFFSET] /* save C return address */
260 :     set _ml_mul,TMPREG4 /* set pointer to ml_mul */
261 :     st TMPREG4,[%sp+MUL_OFFSET]
262 :     set _ml_div,TMPREG4 /* set pointer to ml_div */
263 :     st TMPREG4,[%sp+DIV_OFFSET]
264 :     set _ml_umul,TMPREG4 /* set pointer to ml_umul */
265 :     st TMPREG4,[%sp+UMUL_OFFSET]
266 :     set _ml_udiv,TMPREG4 /* set pointer to ml_udiv */
267 :     st TMPREG4,[%sp+UDIV_OFFSET]
268 :     ld [MLState+AllocPtrOffMSP],ALLOCPTR
269 :     ld [MLState+LimitPtrOffMSP],LIMITPTR
270 :     ld [MLState+StorePtrOffMSP],STOREPTR
271 :     ld [MLState+PCOffMSP],PC
272 :     ld [MLState+StdArgOffMSP],STDARG
273 :     ld [MLState+StdContOffMSP],STDCONT
274 :     ld [MLState+StdClosOffMSP],STDCLOS
275 :     ld [MLState+VarPtrOffMSP],VARPTR
276 :     ld [MLState+LinkRegOffMSP],STDLINK
277 :     ld [MLState+ExnPtrOffMSP],EXNCONT /* restore exnptr */
278 :     ld [MLState+Misc0OffMSP],MISCREG0
279 :     ld [MLState+Misc1OffMSP],MISCREG1
280 :     ld [MLState+Misc2OffMSP],MISCREG2
281 :     ld [MLState+VProcOffMSP],VProcPtr /* TMPREG4 := VProcPtr */
282 :     set 1,TMPREG2 /* note that we have entered ML code */
283 :     st TMPREG2,[VProcPtr+InMLOffVSP]
284 :     ld [VProcPtr+NPendingSysOffVSP],TMPREG2 /* check for pending signals */
285 :     ld [VProcPtr+NPendingOffVSP],TMPREG3
286 :     addcc TMPREG2,TMPREG3,%g0
287 :     bne pending_sigs
288 :     nop
289 :     CSYM(ml_go): /* invoke the ML code */
290 :     jmp PC
291 :     subcc ALLOCPTR,LIMITPTR,%g0 /* Heap limit test (delay slot) */
292 :    
293 :     pending_sigs: /* there are pending signals */
294 :     /* check if we are currently handling a signal */
295 :     ld [VProcPtr+InSigHandlerOffVSP],TMPREG2
296 :     tst TMPREG2
297 :     bne ml_go
298 :     set 1,TMPREG2 /* (delay slot) */
299 :     /* note that a handler trap is pending */
300 :     st TMPREG2,[VProcPtr+HandlerPendingOffVSP]
301 :     ba ml_go
302 :     mov ALLOCPTR,LIMITPTR /* (delay slot) */
303 :    
304 :    
305 :     #if defined(OPSYS_SUNOS) || defined(OPSYS_NEXTSTEP)
306 :     /* ZeroLimitPtr:
307 :     *
308 :     * Zero the heap limit pointer so that a trap will be generated on the next limit
309 :     * check and then continue executing ML code.
310 :     * NOTE: this code cannot trash any registers (other than limitptr) or the condition
311 :     * code. To achieve this we work inside a new register window.
312 :     * Also note that this code is not needed under SOLARIS 2.x, since we can
313 :     * directly change the register from C.
314 :     */
315 :     TEXT
316 :     ENTRY(ZeroLimitPtr)
317 :     save %sp,-SA(WINDOWSIZE),%sp
318 :     sethi %hi(CSYM(SavedPC)),%l1
319 :     ld [%l1+%lo(CSYM(SavedPC))],%o0
320 :     set 0,LIMITPTR
321 :     jmp %o0
322 :     restore /* (delay slot) */
323 :     #endif /* OPSYS_SUNOS */
324 :    
325 :    
326 :     /* array : (int * 'a) -> 'a array
327 :     * Allocate and initialize a new array. This can cause GC.
328 :     */
329 :     ML_CODE_HDR(array_a)
330 :     CHECKLIMIT(array_a_limit)
331 :     ld [STDARG],TMPREG1 /* tmp1 = length in words */
332 :     sra TMPREG1,1,TMPREG2 /* tmp2 = length (untagged) */
333 :     cmp TMPREG2,SMALL_OBJ_SZW /* is this a small object? */
334 :     bgt 3f
335 :     nop
336 :     /** allocate and initialize array data **/
337 :     ld [STDARG+4],STDARG /* stdarg = initial value */
338 :     sll TMPREG2,TAG_SHIFTW,TMPREG3 /* build descriptor in tmp3 */
339 :     or TMPREG3,MAKE_TAG(DTAG_arr_data),TMPREG3
340 :     st TMPREG3,[ALLOCPTR] /* store the descriptor */
341 :     inc 4,ALLOCPTR /* allocptr++ */
342 :     mov ALLOCPTR,TMPREG3 /* array data ptr in tmp3 */
343 :     1: /* loop */
344 :     st STDARG,[ALLOCPTR]
345 :     deccc 1,TMPREG2 /* if (--length > 0) */
346 :     bgt 1b /* then continue */
347 :     inc 4,ALLOCPTR /* allocptr++ (delay slot) */
348 :     /* end loop */
349 :     /** allocate array header **/
350 :     set DESC_polyarr,TMPREG2 /* descriptor in tmp2 */
351 :     st TMPREG2,[ALLOCPTR] /* store the descriptor */
352 :     inc 4,ALLOCPTR /* allocptr++ */
353 :     mov ALLOCPTR,STDARG /* result = header addr */
354 :     st TMPREG3,[ALLOCPTR] /* store pointer to data */
355 :     st TMPREG1,[ALLOCPTR+4]
356 :     inc 8,ALLOCPTR /* allocptr += 2 */
357 :     CONTINUE
358 :    
359 :     3: /* here we do off-line allocation for big arrays */
360 :     mov STDLINK,PC
361 :     ba set_request
362 :     set REQ_ALLOC_ARRAY,TMPREG3 /* (delayslot) */
363 :    
364 :     /* create_r : int -> realarray
365 :     * Create a new realarray.
366 :     */
367 :     ML_CODE_HDR(create_r_a)
368 :     CHECKLIMIT(create_r_a_limit)
369 :     sra STDARG,1,TMPREG2 /* tmp2 = length (untagged int) */
370 :     sll TMPREG2,1,TMPREG2 /* tmp2 = length in words */
371 :     cmp TMPREG2,SMALL_OBJ_SZW /* is this a small object? */
372 :     bgt 1f
373 :     nop
374 :     /* Allocate the data object */
375 :     sll TMPREG2,TAG_SHIFTW,TMPREG1 /* build data desc in tmp1 */
376 :     or TMPREG1,MAKE_TAG(DTAG_raw64),TMPREG1
377 :     #ifdef ALIGN_REALDS
378 :     or ALLOCPTR,0x4,ALLOCPTR /* desc is unaliged */
379 :     #endif
380 :     st TMPREG1,[ALLOCPTR] /* store the data descriptor */
381 :     inc 4,ALLOCPTR /* allocptr++ */
382 :     mov ALLOCPTR,TMPREG3 /* tmp3 = data object */
383 :     sll TMPREG2,2,TMPREG2 /* tmp2 = length in bytes */
384 :     add ALLOCPTR,TMPREG2,ALLOCPTR /* allocptr += length */
385 :     /* Allocate the header object */
386 :     set DESC_real64arr,TMPREG1
387 :     st TMPREG1,[ALLOCPTR] /* header descriptor */
388 :     inc 4,ALLOCPTR /* allocptr++ */
389 :     st TMPREG3,[ALLOCPTR] /* header data field */
390 :     st STDARG,[ALLOCPTR+4] /* header length field */
391 :     mov ALLOCPTR,STDARG /* stdarg = header object */
392 :     inc 8,ALLOCPTR /* allocptr += 2 */
393 :     CONTINUE
394 :    
395 :     1: /* off-line allocation of big realarrays */
396 :     mov STDLINK,PC
397 :     ba set_request
398 :     set REQ_ALLOC_REALDARRAY,TMPREG3 /* (delayslot) */
399 :    
400 :     /* create_b : int -> bytearray
401 :     * Create a bytearray of the given length.
402 :     */
403 :     ML_CODE_HDR(create_b_a)
404 :     CHECKLIMIT(create_b_a_limit)
405 :     sra STDARG,1,TMPREG2 /* tmp2 = length (sparc int) */
406 :     add TMPREG2,3,TMPREG2 /* tmp2 = length in words */
407 :     sra TMPREG2,2,TMPREG2
408 :     cmp TMPREG2,SMALL_OBJ_SZW /* is this a small object? */
409 :     bgt 1f
410 :     nop
411 :     /* Allocate the data object */
412 :     sll TMPREG2,TAG_SHIFTW,TMPREG1 /* build data desc in tmp1 */
413 :     or TMPREG1,MAKE_TAG(DTAG_raw32),TMPREG1
414 :     st TMPREG1,[ALLOCPTR] /* store the data descriptor */
415 :     inc 4,ALLOCPTR /* allocptr++ */
416 :     mov ALLOCPTR,TMPREG3 /* tmp3 = data object */
417 :     sll TMPREG2,2,TMPREG2 /* tmp2 = length in bytes */
418 :     add ALLOCPTR,TMPREG2,ALLOCPTR /* allocptr += length */
419 :     /* Allocate the header object */
420 :     set DESC_word8arr,TMPREG1 /* header descriptor */
421 :     st TMPREG1,[ALLOCPTR]
422 :     inc 4,ALLOCPTR /* allocptr++ */
423 :     st TMPREG3,[ALLOCPTR] /* header data field */
424 :     st STDARG,[ALLOCPTR+4] /* header length field */
425 :     mov ALLOCPTR,STDARG /* stdarg = header object */
426 :     inc 8,ALLOCPTR /* allocptr += 2 */
427 :     CONTINUE
428 :    
429 :     1: /* here we do off-line allocation for big bytearrays */
430 :     mov STDLINK,PC
431 :     ba set_request
432 :     set REQ_ALLOC_BYTEARRAY,TMPREG3 /* (delayslot) */
433 :    
434 :     /* create_s : int -> string
435 :     * Create a string of the given length (> 0).
436 :     */
437 :     ML_CODE_HDR(create_s_a)
438 :     CHECKLIMIT(create_s_a_limit)
439 :     sra STDARG,1,TMPREG2 /* tmp2 = length (sparc int) */
440 :     add TMPREG2,4,TMPREG2 /* tmp2 = length in words */
441 :     /* (including zero at end). */
442 :     sra TMPREG2,2,TMPREG2
443 :     cmp TMPREG2,SMALL_OBJ_SZW /* is this a small object? */
444 :     bgt 1f
445 :     nop
446 :     /* Allocate the data object */
447 :     sll TMPREG2,TAG_SHIFTW,TMPREG1 /* build data desc in tmp1 */
448 :     or TMPREG1,MAKE_TAG(DTAG_raw32),TMPREG1
449 :     st TMPREG1,[ALLOCPTR] /* store the data descriptor */
450 :     inc 4,ALLOCPTR /* allocptr++ */
451 :     mov ALLOCPTR,TMPREG3 /* tmp3 = data object */
452 :     sll TMPREG2,2,TMPREG2 /* tmp2 = length in bytes */
453 :     add ALLOCPTR,TMPREG2,ALLOCPTR /* allocptr += length */
454 :     st %g0,[ALLOCPTR-4] /* store 0 in last word of data */
455 :     /* Allocate the header object */
456 :     set DESC_string,TMPREG1 /* header descriptor */
457 :     st TMPREG1,[ALLOCPTR]
458 :     inc 4,ALLOCPTR /* allocptr++ */
459 :     st TMPREG3,[ALLOCPTR] /* header data field */
460 :     st STDARG,[ALLOCPTR+4] /* header length field */
461 :     mov ALLOCPTR,STDARG /* stdarg = header object */
462 :     inc 8,ALLOCPTR /* allocptr += 2 */
463 :     CONTINUE
464 :    
465 :     1: /* here we do off-line allocation for big strings */
466 :     mov STDLINK,PC
467 :     ba set_request
468 :     set REQ_ALLOC_STRING,TMPREG3 /* (delayslot) */
469 :    
470 :     /* create_v_a : (int * 'a list) -> 'a vector
471 :     * Create a vector with elements taken from a list.
472 :     * NOTE: the front-end ensures that list cannot be nil.
473 :     */
474 :     ML_CODE_HDR(create_v_a)
475 :     CHECKLIMIT(create_v_a_limit)
476 :     ld [STDARG],TMPREG1 /* tmp1 = length (tagged int) */
477 :     sra TMPREG1,1,TMPREG2 /* tmp2 = length (untagged int) */
478 :     cmp TMPREG2,SMALL_OBJ_SZW /* is this a small object? */
479 :     bgt 1f
480 :     nop
481 :     /* allocate and initialize data object */
482 :     sll TMPREG2,TAG_SHIFTW,TMPREG2 /* build descriptor in TMPREG2 */
483 :     or TMPREG2,MAKE_TAG(DTAG_vec_data),TMPREG2
484 :     st TMPREG2,[ALLOCPTR] /* store the descriptor */
485 :     inc 4,ALLOCPTR /* allocptr++ */
486 :     ld [STDARG+4],TMPREG2 /* tmp2 = list */
487 :     mov ALLOCPTR,STDARG /* stdarg = data obj */
488 :     2: /* loop */
489 :     ld [TMPREG2],TMPREG3 /* tmp3 = hd(tmp2) */
490 :     ld [TMPREG2+4],TMPREG2 /* tmp2 = tl(tmp2) */
491 :     st TMPREG3,[ALLOCPTR] /* store element */
492 :     cmp TMPREG2,ML_nil /* if (tmp2 <> nil) goto loop */
493 :     bne 2b
494 :     inc 4,ALLOCPTR /* allocptr++ (delay slot) */
495 :     /* end loop */
496 :     /* allocate header object */
497 :     set DESC_polyvec,TMPREG3 /* descriptor in TMPREG3 */
498 :     st TMPREG3,[ALLOCPTR] /* header descriptor */
499 :     inc 4,ALLOCPTR /* allocptr++ */
500 :     st STDARG,[ALLOCPTR] /* header data field */
501 :     st TMPREG1,[ALLOCPTR+4] /* header length field */
502 :     mov ALLOCPTR,STDARG /* result = header object */
503 :     inc 8,ALLOCPTR /* allocptr += 2 */
504 :     CONTINUE
505 :    
506 :     1: /* off-line allocation of big vectors */
507 :     mov STDLINK,PC
508 :     ba set_request
509 :     set REQ_ALLOC_VECTOR,TMPREG3 /* (delayslot) */
510 :    
511 :    
512 :     /* floor : real -> int
513 :     * Return the floor of the argument ; do not check for out-of-range (it's
514 :     * the ML code's responsibility to check before calling. */
515 :     ML_CODE_HDR(floor_a)
516 :     ld [STDARG],%f0 /* fetch arg into %f0, %f1. */
517 :     ld [STDARG+4],%f1
518 :     ld [STDARG],TMPREG2 /* tmpreg2 gets high word. */
519 :     tst TMPREG2 /* negative ? */
520 :     blt 1f
521 :     nop
522 :     /* handle positive case */
523 :     fdtoi %f0,%f2 /* cvt to int (round towards 0) */
524 :     st %f2,[%sp+FLOOR_OFFSET]
525 :     ld [%sp+FLOOR_OFFSET],TMPREG2 /* tmpreg2 gets int result (via stack temp). */
526 :     add TMPREG2,TMPREG2,TMPREG2
527 :     add TMPREG2,1,STDARG
528 :     CONTINUE
529 :    
530 :     1: /* handle negative case. */
531 :     fdtoi %f0,%f2 /* cvt to int (round towards 0) */
532 :     st %f2,[%sp+FLOOR_OFFSET]
533 :     fitod %f2,%f4 /* cvt back to real to check for fraction */
534 :     fcmpd %f0,%f4 /* same value? */
535 :     ld [%sp+FLOOR_OFFSET],TMPREG2 /* tmpreg2 gets int result (via stack temp). */
536 :     fbe 2f /* check result of fcmpd */
537 :     nop
538 :     dec TMPREG2 /* push one lower */
539 :     2: /* cvt result to ML int, and continue */
540 :     add TMPREG2,TMPREG2,TMPREG2
541 :     add TMPREG2,1,STDARG
542 :     CONTINUE
543 :    
544 :     /* logb : real -> int
545 :     * Extract and unbias the exponent.
546 :     * The IEEE bias is 1023.
547 :     */
548 :     ML_CODE_HDR(logb_a)
549 :     ld [STDARG],TMPREG2 /* extract exponent. */
550 :     srl TMPREG2,19,TMPREG2
551 :     and TMPREG2,2047*2,TMPREG2 /* unbias and cvt to ML int. */
552 :     sub TMPREG2,2045,STDARG /* 2(n-1023)+1 == 2n-2045. */
553 :     CONTINUE
554 :    
555 :    
556 :     /* scalb : (real * int) -> real
557 :     * Scale the first argument by 2 raised to the second argument. Raise
558 :     * Float("underflow") or Float("overflow") as appropriate.
559 :     */
560 :     ML_CODE_HDR(scalb_a)
561 :     CHECKLIMIT(scalb_a_limit)
562 :     ld [STDARG+4],TMPREG1 /* tmpreg1 gets scale (second arg) */
563 :     sra TMPREG1,1,TMPREG1 /* cvt scale to sparc int */
564 :     ld [STDARG],STDARG /* stdarg gets real (first arg) */
565 :     ld [STDARG],TMPREG4 /* tmpreg4 gets high word of real value. */
566 :     set 0x7ff00000,TMPREG2 /* tmpreg2 gets exponent mask. */
567 :     andcc TMPREG4,TMPREG2,TMPREG3 /* extract exponent into tmpreg3. */
568 :     be 1f /* if 0 then return same */
569 :     nop
570 :     srl TMPREG3,20,TMPREG3 /* cvt exp to int (delay slot). */
571 :     addcc TMPREG3,TMPREG1,TMPREG1 /* tmpreg1 = exp + scale */
572 :     ble under /* if new exp <= 0 then underflow */
573 :     nop
574 :     cmp TMPREG1,2047 /* if new exp >= 2047 then overflow */
575 :     bge over
576 :     nop
577 :     andn TMPREG4,TMPREG2,TMPREG4 /* mask out old exponent. */
578 :     sll TMPREG1,20,TMPREG1 /* shift new exp to exponent position. */
579 :     or TMPREG4,TMPREG1,TMPREG4 /* set new exponent. */
580 :     ld [STDARG+4],TMPREG1 /* tmpreg1 gets low word of real value. */
581 :     7:
582 :     #ifdef ALIGN_REALDS
583 :     or ALLOCPTR,0x4,ALLOCPTR /* desc is unaliged */
584 :     #endif
585 :     st TMPREG4,[ALLOCPTR+4] /* allocate the new real value */
586 :     st TMPREG1,[ALLOCPTR+8]
587 :     set DESC_reald,TMPREG1
588 :     st TMPREG1,[ALLOCPTR]
589 :     add ALLOCPTR,4,STDARG /* set result. */
590 :     inc 12,ALLOCPTR /* allocptr += 3 */
591 :     1: CONTINUE
592 :    
593 :     over: /* handle overflow */
594 :     t ST_INT_OVERFLOW /* generate an Overflow exn. We do this */
595 :     /* never get here */ /* via a trap to produce a SIGOVFL */
596 :    
597 :     under: /* handle underflow */
598 :     set 0,TMPREG4
599 :     set 0,TMPREG1
600 :     ba 7b
601 :     nop
602 :    
603 :     /** Integer multiplication and division routines **/
604 :     .global .mul, .div, .umul, .udiv
605 :    
606 :     /* ml_mul:
607 :     * multiply %o2 by %o3, returning the result in %o2
608 :     * Note: this code assumes that .mul doesn't trash any global or input
609 :     * registers.
610 :     */
611 :     _ml_mul:
612 :     save %sp,-SA(WINDOWSIZE),%sp
613 :     /** NOTE: if %g1, %g2, %g3 are not callee save, then this can be avoided **/
614 :     /** NOTE: .mul doesn't use %g2, %g3, but the dynamic linking initialization
615 :     ** does.
616 :     **/
617 :     mov %g1,%l1 /* save %g1 which may get trashed */
618 :     mov %g2,%l2
619 :     mov %g3,%l3
620 :     mov %i2,%o0
621 :     call .mul
622 :     mov %i3,%o1 /* (delay slot) */
623 :     mov %l1,%g1 /* restore %g1 */
624 :     mov %l2,%g2
625 :     mov %l3,%g3
626 :     bnz 1f /* if z is clear, then overflow */
627 :     restore %o0,0,%o2 /* result in %o2 (delay slot) */
628 :     retl
629 :     nop
630 :     1: /* handle overflow. */
631 :     t ST_INT_OVERFLOW /* generate an Overflow exn. We do this */
632 :     /* via a trap to produce a SIGOVFL */
633 :    
634 :     /* ml_div:
635 :     * divide %o2 by %o3, returning the result in %o2.
636 :     * Note: .div uses %g1, %g2 and %g3, so we must save them. We do this using the
637 :     * locals of the new window, since .div is a leaf routine.
638 :     */
639 :     _ml_div:
640 :     save %sp,-SA(WINDOWSIZE),%sp
641 :     addcc %i3,%g0,%o1 /* %o1 is divisor (and check for zero) */
642 :     bz 1f
643 :     /* save %g1, %g2 and %g3 (using new window) */
644 :     /** NOTE: if %g1, %g2, %g3 are not callee save, then this can be avoided **/
645 :     mov %g1,%l1 /* (delay slot) */
646 :     mov %g2,%l2
647 :     mov %g3,%l3
648 :     call .div
649 :     mov %i2,%o0 /* (delay slot) */
650 :     /* restore %g1, %g2 and %g3 */
651 :     mov %l3,%g3
652 :     mov %l2,%g2
653 :     mov %l1,%g1
654 :     ret
655 :     restore %o0,0,%o2 /* result in %o2 (delay slot) */
656 :     1: /* handle zero divide */
657 :     restore /* restore ML window */
658 :     t ST_DIV0 /* generate a Div exn. We do this via a */
659 :     /* trap to produce a SIGDIV */
660 :    
661 :     /* ml_umul:
662 :     * multiply %o2 by %o3 (unsigned), returning the result in %o2. This does
663 :     * raise Overflow.
664 :     * Note: this code assumes that .mul doesn't trash any global or input
665 :     * registers.
666 :     */
667 :     _ml_umul:
668 :     save %sp,-SA(WINDOWSIZE),%sp
669 :     /** NOTE: if %g1, %g2, %g3 are not callee save, then this can be avoided **/
670 :     /** NOTE: .mul doesn't use %g2, %g3, but the dynamic linking initialization
671 :     ** does.
672 :     **/
673 :     mov %g1,%l1 /* save %g1 which may get trashed */
674 :     mov %g2,%l2
675 :     mov %g3,%l3
676 :     mov %i2,%o0
677 :     call .umul
678 :     mov %i3,%o1 /* (delay slot) */
679 :     mov %l1,%g1 /* restore %g1 */
680 :     mov %l2,%g2
681 :     mov %l3,%g3
682 :     ret
683 :     restore %o0,0,%o2 /* result in %o2 (delay slot) */
684 :    
685 :    
686 :     /* ml_udiv:
687 :     * divide %o2 by %o3 (unsigned), returning the result in %o2.
688 :     * Note: .udiv uses %g1, %g2 and %g3, so we must save them. We do this using the
689 :     * locals of the new window, since .div is a leaf routine.
690 :     */
691 :     _ml_udiv:
692 :     save %sp,-SA(WINDOWSIZE),%sp
693 :     addcc %i3,%g0,%o1 /* %o1 is divisor (and check for zero) */
694 :     bz 1f
695 :     /* save %g1, %g2 and %g3 (using new window) */
696 :     /** NOTE: if %g1, %g2, %g3 are not callee save, then this can be avoided **/
697 :     mov %g1,%l1 /* (delay slot) */
698 :     mov %g2,%l2
699 :     mov %g3,%l3
700 :     call .udiv
701 :     mov %i2,%o0 /* (delay slot) */
702 :     /* restore %g1, %g2 and %g3 */
703 :     mov %l3,%g3
704 :     mov %l2,%g2
705 :     mov %l1,%g1
706 :     ret
707 :     restore %o0,0,%o2 /* result in %o2 (delay slot) */
708 :     1: /* handle zero divide */
709 :     restore /* restore ML window */
710 :     t ST_DIV0 /* generate a Div exn. We do this via a */
711 :     /* trap to produce a SIGDIV */
712 :    
713 :    
714 :     /* try_lock : spin_lock -> bool
715 :     * low-level test-and-set style primitive for mutual-exclusion among
716 :     * processors.
717 :     */
718 :     ML_CODE_HDR(try_lock_a)
719 :     #if (MAX_PROCS > 1)
720 :     ???
721 :     #else (MAX_PROCS == 1)
722 :     ld [STDARG],TMPREG1 /* load previous value into tmpreg1 */
723 :     set ML_false,TMPREG4 /* ML_false */
724 :     st TMPREG4,[STDARG] /* store ML_false into the lock */
725 :     mov TMPREG1,STDARG /* return previous value of lock */
726 :     CONTINUE
727 :     #endif
728 :    
729 :     /* unlock : releases a spin lock
730 :     */
731 :     ML_CODE_HDR(unlock_a)
732 :     #if (MAX_PROCS > 1)
733 :     ???
734 :     #else (MAX_PROCS == 1)
735 :     set ML_true,TMPREG1 /* store ML_true ... */
736 :     st TMPREG1,[STDARG] /* into the lock */
737 :     set ML_unit,STDARG /* return unit */
738 :     CONTINUE
739 :     #endif
740 :    
741 :    
742 :     /* SetFSR:
743 :     * Load the floating-point status register with the given word.
744 :     */
745 :     ENTRY(SetFSR)
746 :     set fsrtmp,%o1
747 :     st %o0,[%o1]
748 :     retl
749 :     ld [%o1],%fsr /* (delay slot) */
750 :     DATA
751 :     fsrtmp: .word 0
752 :     TEXT
753 :    
754 :    
755 :     /* void FlushICache (char *addr, int nbytes)
756 :     */
757 :     ENTRY(FlushICache)
758 :     and %o1,0x1F,%o2 /* m <- (nbytes % (32-1)) >> 2 (use %o2 for m) */
759 :     srl %o2,2,%o2
760 :     srl %o1,5,%o1 /* i <- (nbytes >> 5) */
761 :     /* FLUSH4 implements: if (m > 0) { FLUSH addr; addr += 4; m--;} else goto L_test */
762 :     #define FLUSH4 \
763 :     tst %o2; \
764 :     ble L_test; \
765 :     nop; \
766 :     iflush %o0; \
767 :     inc 4,%o0; \
768 :     dec 1,%o2
769 :     FLUSH4
770 :     FLUSH4
771 :     FLUSH4
772 :     FLUSH4
773 :     FLUSH4
774 :     FLUSH4
775 :     FLUSH4
776 :     /* addr is 32-byte aligned here */
777 :     L_test:
778 :     tst %o1
779 :     be L_exit
780 :     nop
781 :     L_loop: /* flush 32 bytes per iteration */
782 :     iflush %o0
783 :     iflush %o0+8
784 :     iflush %o0+16
785 :     iflush %o0+24
786 :     deccc 1,%o1 /* if (--i > 0) goto L_loop */
787 :     bg L_loop
788 :     inc 32,%o0 /* addr += 32 (delay slot) */
789 :     L_exit:
790 :     retl
791 :     nop

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