Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/branches/idlbasis-devel/src/runtime/mach-dep/SPARC.prim.asm
ViewVC logotype

Annotation of /sml/branches/idlbasis-devel/src/runtime/mach-dep/SPARC.prim.asm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 859 - (view) (download)

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

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