Annotation of researchv10no/cmd/sml/src/runtime/SPARC.prim.s, revision 1.1.1.1

1.1       root        1: /* Copyright 1989 by AT&T Bell Laboratories */
                      2: /* SPARC.prim.s
                      3:  *
                      4:  * J.H. Reppy
                      5:  * Cornell University
                      6:  * Ithaca, NY  14853
                      7:  * [email protected]
                      8:  *
                      9:  * HISTORY:
                     10:  *   03/15/89  created
                     11:  *   11/20/89  revised for to use heap limit check.
                     12:  *
                     13:  * SPARC runtime code for ML.  Registers are used as follows:
                     14:  *
                     15:  * %g7 : exception handler continuation
                     16:  * %g6 : freespace pointer
                     17:  * %g5 : store pointer
                     18:  * %g4 : heap limit pointer
                     19:  *
                     20:  * %i2 = closure; can be ignored because contains no free vars
                     21:  * %i0 = arg
                     22:  * %i1 = continuation
                     23:  * %i3 = base code pointer
                     24:  *
                     25:  * %o0,%o1 = arith. temps
                     26:  * %g1-%g3,%l0-%l7,%i4-%i5 = misc. registers (contain only pointers or tagged ints)
                     27:  * %o5 = pointer temp.
                     28:  *
                     29:  * %o2,%o3 = used for args to ml_mul & ml_div, also used as temp registers
                     30:  * %o4,%o5 = temp registers
                     31:  *
                     32:  * %o6 = %sp (not used by ML)
                     33:  * %i6 = %fp (not used by ML)
                     34:  * %i7 = return address to C code (not used by ML)
                     35:  * %o7 = not used
                     36:  *
                     37:  * There are four places in this file where garbage collection can be triggered:
                     38:  * in array_v, create_s_v, scalb_v and in raise_real.  It it important that only
                     39:  * registers saved by _saveregs be live at these points. Also, only pointer
                     40:  * registers can contain heap pointers at these points.
                     41:  */
                     42: 
                     43: #include <machine/asm_linkage.h>
                     44: #include <machine/trap.h>
                     45: #include "tags.h"
                     46: #include "prof.h"
                     47: #include "prim.h"
                     48: 
                     49: /* Macros to fetch and store values in memory; use %o5 as an addressing register. */
                     50: #define FETCH(addr, reg)                       \
                     51:            sethi   %hi(addr),%o3;              \
                     52:            ld      [%o3+%lo(addr)],reg
                     53: #define STORE(reg, addr)                       \
                     54:            sethi   %hi(addr),%o3;              \
                     55:            st      reg,[%o3+%lo(addr)]
                     56: 
                     57: 
                     58: /* Macros to save and restore the global registers.  We save %g1-%g7 in the
                     59:  * corresponding locals of the new window.  The C-routine/system call is
                     60:  * guaranteed not to touch the local or in registers (which are the out registers
                     61:  * of the ML window).
                     62:  */
                     63: #define SAVE_ML_REGS                           \
                     64:            mov     %g1,%l1;                    \
                     65:            mov     %g2,%l2;                    \
                     66:            mov     %g3,%l3;                    \
                     67:            mov     %g4,%l4;                    \
                     68:            mov     %g5,%l5;                    \
                     69:            mov     %g6,%l6;                    \
                     70:            mov     %g7,%l7
                     71: 
                     72: #define RESTORE_ML_REGS                                \
                     73:            mov     %l1,%g1;                    \
                     74:            mov     %l2,%g2;                    \
                     75:            mov     %l3,%g3;                    \
                     76:            mov     %l4,%g4;                    \
                     77:            mov     %l5,%g5;                    \
                     78:            mov     %l6,%g6;                    \
                     79:            mov     %l7,%g7
                     80: 
                     81: /* The ML stack frame has the following layout (set up by restoreregs):
                     82:  *
                     83:  *                     +-----------------+
                     84:  *     %fp = %sp+80:   | temp for floor  |
                     85:  *                     +-----------------+
                     86:  *     %sp+76:         | addr of _ml_div |
                     87:  *                     +-----------------+
                     88:  *     %sp+72:         | addr of _ml_mul |
                     89:  *                     +-----------------+
                     90:  *     %sp+68:         |    saved %g6    |
                     91:  *                     +-----------------+
                     92:  *     %sp+64:         |    saved %g7    |
                     93:  *                     +-----------------+
                     94:  *                     |  space to save  |
                     95:  *                     |  in and local   |
                     96:  *     %sp:            |    registers    |
                     97:  *                     +-----------------+
                     98:  *
                     99:  * the size of the frame is
                    100:  */
                    101: #define ML_FRAMESIZE (WINDOWSIZE+20)
                    102: 
                    103: 
                    104: #define String(handle,len,str)                 \
                    105:            .align  4;                          \
                    106:            .word   len*power_tags+tag_string;  \
                    107:     handle: .ascii  str;                       \
                    108:            .align  4
                    109: 
                    110: #define Closure(name)                          \
                    111:            .align  4;                          \
                    112:            .word   mak_desc(1,tag_record);     \
                    113:     name:   .word   7f;                                \
                    114:            .word   1;                          \
                    115:            .word   tag_backptr;                \
                    116:     7:
                    117: 
                    118: #define RAISE                                  \
                    119:            ld      [%g7],%i2;                  \
                    120:            jmp     %i2;                        \
                    121:            mov     %g7,%i1     /* (delay slot) */
                    122: 
                    123: #define CONTINUE                               \
                    124:            ld      [%i1],%i2;                  \
                    125:            jmp     %i2;                        \
                    126:            nop
                    127: 
                    128: 
                    129:        .seg    "text"
                    130:        .global _runvec
                    131:        .align  4
                    132:        .word   mak_desc(8, tag_record)
                    133: _runvec:
                    134:        .word   _array_v
                    135:        .word   _callc_v
                    136:        .word   _create_b_v
                    137:        .word   _create_s_v
                    138:        .word   _floor_v
                    139:        .word   _logb_v
                    140:        .word   _scalb_v
                    141:        .word   _syscall_v
                    142: 
                    143: 
                    144:        .global _startprim
                    145: _startprim:
                    146: 
                    147: 
                    148: /* array : (int * 'a) -> 'a array
                    149:  * Allocate and initialize a new array.         This can cause GC.
                    150:  */
                    151: Closure(_array_v)
                    152: 1:
                    153:        ld      [%i0],%o0               /* get length into %o0 */
                    154:        ld      [%i0+4],%l0             /* get default into %l0 */
                    155:        sra     %o0,1,%o0               /* convert to sparc int */
                    156:        sll     %o0,width_tags,%o1      /* build the tag in %o1 */
                    157:        or      %o1,tag_array,%o1
                    158:        sll     %o0,2,%o0               /* scale length to bytes */
                    159:        add     %g4,%o0,%o4             /* check the heap limit */
                    160:        addcc   %g6,%o4,%g0
                    161:        bvs     3f                          /* we hit the limit, so trap safely */
                    162:        dec     4,%o0                   /* length-- */
                    163:        st      %o1,[%g6-4]             /* store the tag */
                    164:        mov     %g6,%i0                 /* result := object addr. */
                    165: 2:                                     /* initialization loop */
                    166:        st      %l0,[%g6]                   /* store default. */
                    167:        deccc   4,%o0                       /* length-- */
                    168:        bge     2b
                    169:        inc     4,%g6                       /* freeptr++ (delay slot) */
                    170:        /* end loop */
                    171:        inc     4,%g6                   /* freeptr++ */
                    172:        CONTINUE
                    173: 3:                                     /* we come here to do a safe GC trap. */
                    174:        add     %g0,0,%g0                   /* a nop to get PC adjust right */
                    175:        taddcctv %g6,%o4,%g0                /* cause the GC trap. */
                    176:        ba      1b                          /* retry the allocation. */
                    177:        nop
                    178: 
                    179: 
                    180: /* create_b : int -> string
                    181:  * create_s : int -> string
                    182:  * Create bytearray or string of given length. This can cause GC.
                    183:  */
                    184: Closure(_create_b_v)
                    185:        ba      2f
                    186:        mov     tag_bytearray,%l1   /* (delay slot) */
                    187: 
                    188: Closure(_create_s_v)
                    189:        mov     tag_string,%l1
                    190: 
                    191: 2:     sra     %i0,1,%o0           /* %o0 = length (sparc int) */
                    192:        sll     %o0,width_tags,%o2
                    193:        or      %o2,%l1,%o1         /* build the tag in %o1 */
                    194:        add     %o0,3,%o0           /* %o0 = length in words (no tag) */
                    195:        sra     %o0,2,%o0
                    196:        sll     %o0,2,%o0           /* %o0 = length in bytes (no tag) */
                    197:        add     %g4,%o0,%o4         /* Check the heap limit. */
                    198:        addcc   %g6,%o4,%g0
                    199:        bvs     3f                      /* we hit the limit, so trap safely. */
                    200:        st      %o1,[%g6-4]         /* store the tag */
                    201:        mov     %g6,%i0             /* result := object addr */
                    202:        add     %o0,4,%o0           /* %o0 = length in bytes (including tag) */
                    203:        add     %o0,%g6,%g6         /* freeptr += length */
                    204:        CONTINUE
                    205: 3:                                 /* we come here to do a safe GC trap. */
                    206:        add     %g0,0,%g0               /* a nop to get PC adjust right */
                    207:        taddcctv %g6,%o4,%g0            /* cause the GC trap. */
                    208:        ba      2b                      /* retry the allocation. */
                    209:        nop
                    210: 
                    211: 
                    212: /* floor : real -> int
                    213:  * Return the floor of the argument or else raise Float("floor") if out of range.
                    214:  * We implement the range check by using an integer comparison with the high 32
                    215:  * bits of the real value (which contains the biased exponent).
                    216:  * (double)(2^30)   == [0x41d00000, 0x0]
                    217:  * (double)(-2^30)  == [0xc1d00000, 0x0]
                    218:  */
                    219: Closure(_floor_v)
                    220:        ld      [%i0],%f0           /* fetch arg into %f0, %f1. */
                    221:        ld      [%i0+4],%f1
                    222:        ld      [%i0],%o0           /* %o0 gets high word. */
                    223:        tst     %o0                 /* negative ? */
                    224:        blt     1f
                    225:        nop
                    226:                                /* handle positive case */
                    227:        set     0x41d00000,%o1      /* %o1 = 2^30 */
                    228:        cmp     %o0,%o1             /* if %o0 >= 2^30 then range error */
                    229:        bge     out_of_range
                    230:        nop
                    231:        fdtoi   %f0,%f2             /* cvt to int (round towards 0) */
                    232:        st      %f2,[%sp+80]
                    233:        ld      [%sp+80],%o0        /* %o0 gets int result (via stack temp). */
                    234:        ba      2f
                    235:        nop
                    236: 1:                             /* handle negative case. */
                    237:        set     0xc1d00000,%o1      /* %o1 = -2^30 */
                    238:        cmp     %o0,%o1             /* if %o0 < -2^30 then range error */
                    239:        bge     out_of_range        /* not bl because of sign. */
                    240:        nop
                    241:        fdtoi   %f0,%f2             /* cvt to int (round towards 0) */
                    242:        st      %f2,[%sp+80]
                    243:        fitod   %f2,%f4             /* cvt back to real to check for fraction */
                    244:        fcmpd   %f0,%f4             /* same value? */
                    245:        ld      [%sp+80],%o0        /* %o0 gets int result (via stack temp). */
                    246:        fbe     2f                  /* check result of fcmpd */
                    247:        nop
                    248:        dec     %o0                 /* push one lower */
                    249: 2:                             /* cvt result to ML int, and continue */
                    250:        add     %o0,%o0,%o0
                    251:        add     %o0,1,%i0
                    252:        CONTINUE
                    253: 
                    254: out_of_range:                  /* out of range, so raise Float("floor"). */
                    255:        set     1f,%i0
                    256:        ba      _raise_real
                    257: String(1, 5, "floor\0\0\0")
                    258: 
                    259: 
                    260: /* logb : real -> int
                    261:  * Extract and unbias the exponent, return 0 for a zero exponent.
                    262:  * The IEEE bias is 1023.
                    263:  */
                    264: Closure(_logb_v)
                    265:        ld      [%i0],%o0               /* extract exponent. */
                    266:        srl     %o0,20,%o0
                    267:        andcc   %o0,0x7ff,%o0           /* if (exp == 0) */
                    268:        beq     1f
                    269:        nop
                    270:        sll     %o0,1,%o0               /* else unbias and cvt to ML int. */
                    271:        sub     %o0,2045,%i0            /* 2(n-1023)+1 == 2n-2045. */
                    272: 1:     CONTINUE
                    273: 2:     ba      1b
                    274:        set     1,%i0                   /* return ML zero (delay slot) */
                    275: 
                    276: 
                    277: /* scalb : (real * int) -> real
                    278:  * Scale the first argument by 2 raised to the second argument.         Raise
                    279:  * Float("underflow") or Float("overflow") as appropriate.
                    280:  */
                    281: Closure(_scalb_v)
                    282:        taddcctv %g6,%g4,%g0        /* check the heap limit. */
                    283:        ld      [%i0+4],%o0         /* %o0 gets scale (second arg) */
                    284:        sra     %o0,1,%o0           /* cvt scale to sparc int */
                    285:        ld      [%i0],%i0           /* %i0 gets real (first arg) */
                    286:        ld      [%i0],%o1           /* %o1 gets high word of real value. */
                    287:        set     0x7ff00000,%o3      /* %o3 gets exponent mask. */
                    288:        andcc   %o1,%o3,%o4         /* extract exponent into %o4. */
                    289:        beq     1f                  /* if 0 then return same */
                    290:        nop
                    291:        srl     %o4,20,%o4          /* cvt exp to int (delay slot). */
                    292:        addcc   %o4,%o0,%o0         /* %o0 = exp + scale */
                    293:        ble     under               /* if new exp <= 0 then underflow */
                    294:        nop
                    295:        cmp     %o0,2047            /* if new exp >= 2047 then overflow */
                    296:        bge     over
                    297:        nop
                    298:        andn    %o1,%o3,%o1         /* mask out old exponent. */
                    299:        sll     %o0,20,%o0          /* shift new exp to exponent position. */
                    300:        or      %o1,%o0,%o1         /* set new exponent. */
                    301:        ld      [%i0+4],%o0         /* %o0 gets low word of real value. */
                    302:        st      %o1,[%g6]           /* allocate the new real value */
                    303:        st      %o0,[%g6+4]
                    304:        set     mak_desc(8,tag_string),%o0
                    305:        st      %o0,[%g6-4]
                    306:        mov     %g6,%i0             /* set result. */
                    307:        inc     12,%g6              /* storeptr += 3 */
                    308: 1:     CONTINUE
                    309: 
                    310: over:                          /* handle overflow */
                    311:        set     1f,%i0
                    312:        ba      _raise_real
                    313:        nop
                    314: String(1, 8, "overflow")
                    315: under:                         /* handle underflow */
                    316:        set     1f,%i0
                    317:        ba      _raise_real
                    318:        nop
                    319: String(1, 9, "underflow\0\0\0")
                    320: 
                    321: 
                    322: /* raise_real:
                    323:  * Raise the exception Float with the string in %i0.
                    324:  */
                    325: _raise_real:
                    326:        taddcctv %g6,%g4,%g0            /* check the heap limit. */
                    327:        set     _real_e,%o0             /* allocate the exception. */
                    328:        st      %i0,[%g6]
                    329:        st      %o0,[%g6+4]
                    330:        set     mak_desc(2,tag_record),%o0
                    331:        st      %o0,[%g6-4]
                    332:        mov     %g6,%i0
                    333:        inc     12,%g6                  /* freeptr += 3 */
                    334:        RAISE
                    335: 
                    336: 
                    337:        .global _endprim
                    338: _endprim:
                    339: 
                    340: 
                    341: /* syscall : (int * string list * int) -> int
                    342:  * Note: it is assumed that there are no more than five arguments, plus the code.
                    343:  */
                    344: Closure(_syscall_v)
                    345: #define TMPSIZE 20             /* space to save upto five args */
                    346: #define TMPBASE WINDOWSIZE     /* offset of start of temp save area. */
                    347:        mov     %i0,%o0
                    348:        save    %sp,-SA(WINDOWSIZE+TMPSIZE),%sp
                    349:        SAVE_ML_REGS
                    350:        ld      [%i0+8],%o0     /* %o0 = argcount */
                    351:        sra     %o0,1,%o0       /* cvt to sparc int */
                    352:        add     %sp,TMPBASE,%o1 /* %o1 = base address of temp area */
                    353:        ld      [%i0+4],%o2     /* %o2 = arglist */
                    354: 1:                             /* loop: process arg list, saving in temp area */
                    355:        deccc   1,%o0               /* if --argcount < 0 then done */
                    356:        bl      3f
                    357:        nop
                    358:        ld      [%o2],%o3           /* fetch next arg */
                    359:        btst    1,%o3               /* is the arg an unboxed value? */
                    360:        be      2f
                    361:        ld      [%o2+4],%o2         /* advance arg list pointer (delay slot) */
                    362:        sra     %o3,1,%o3           /* cvt unboxed arg to sparc int */
                    363: 2:     st      %o3,[%o1]           /* store arg in temp area */
                    364:        ba      1b
                    365:        inc     4,%o1               /* tempptr++ (delay slot) */
                    366:        /* end of loop */
                    367: 3:                             /* load the args into the output registers, we */
                    368:                                /* use all six registers even though there may */
                    369:                                /* be fewer arguments. */
                    370:        ld      [%i0],%o0       /* %o0 = system call number */
                    371:        sra     %o0,1,%o0       /* cvt to sparc int */
                    372:        ld      [%sp+TMPBASE],%o1
                    373:        ld      [%sp+TMPBASE+4],%o2
                    374:        ld      [%sp+TMPBASE+8],%o3
                    375:        ld      [%sp+TMPBASE+12],%o4
                    376:        ld      [%sp+TMPBASE+16],%o5
                    377:        clr     %g1             /* 0 is code for syscall. */
                    378:        ta      %g0
                    379:        blu     5f
                    380:        nop
                    381:        sll     %o0,1,%o0       /* cvt result to ML int */
                    382:        inc     1,%o0
                    383: 4:     RESTORE_ML_REGS
                    384:        restore %o0,0,%i0       /* restore register window, returning result */
                    385:        CONTINUE
                    386: 5:                             /* an error, so return -1 */
                    387:        STORE   (%o0, _errno)
                    388:        ba      4b
                    389:        set     -1,%o0          /* (delay slot) */
                    390: 
                    391: /* callc :  ('b * 'a) -> int
                    392:  * Call a C function with one argument.
                    393:  */
                    394: Closure(_callc_v)
                    395:        mov     %i0,%o0
                    396:        save    %sp,-SA(WINDOWSIZE),%sp
                    397:        SAVE_ML_REGS
                    398:        ld      [%i0],%o1       /* %o1 = address of the C function */
                    399:        jmpl    %o1,%o7         /* call the C function */
                    400:        ld      [%i0+4],%o0     /* %o0 = arg (delay slot) */
                    401:        RESTORE_ML_REGS
                    402:        restore %o0,0,%i0       /* restore ML register window, returning result */
                    403:        FETCH   (_cause, %o4)
                    404:        tst     %o4             /* if (cause != 0) */
                    405:        bne     _saveregs       /* then return up to the C environment. */
                    406:        nop                     /* (delay slot) */
                    407:        CONTINUE
                    408: 
                    409: 
                    410: /* Space to save pointer and non-pointer registers; this is allocated here to
                    411:  * insure quad-word alignment.
                    412:  */
                    413:        .seg    "data"
                    414:        .global _saved_ptrs,_saved_nonptrs
                    415:        .align  8
                    416: _saved_ptrs:
                    417:        .skip   (32*4)
                    418:        .align  8
                    419: _saved_nonptrs:
                    420:        .skip   (32*4)
                    421:        .seg    "text"
                    422: 
                    423: 
                    424: /* handle_c, return_c, saveregs and restoreregs:
                    425:  *
                    426:  * handle_c is the root exception handler continuation.
                    427:  * return_c is the root return continuation.
                    428:  * saveregs saves the current ML registers and returns to C code.
                    429:  * restoreregs restores the ML registers and jumps to the ML code address
                    430:  * in save_pc.
                    431:  */
                    432:        .global _handle_c, _return_c, _saveregs, _restoreregs
                    433:        .global _inML, _fault_pending, _fault_code
                    434: 
                    435: Closure(_handle_c)
                    436:        ba      set_cause
                    437:        set     CAUSE_EXN,%o4
                    438: 
                    439: Closure(_return_c)
                    440:        set     CAUSE_RET,%o4
                    441: set_cause:
                    442:        STORE   (%o4, _cause)
                    443: _saveregs:
                    444:        add     %i3,-4096,%i3           /* adjust the base code ptr (sub 4096) */
                    445:        set     _saved_ptrs,%o3
                    446:        std     %i0,[%o3]               /* save %i0, %i1 */
                    447:        std     %i2,[%o3+8]             /* save %i2, %i3 */
                    448:        std     %i4,[%o3+16]            /* save %i4, %i5 */
                    449:        std     %l0,[%o3+24]            /* save %l0, %l1 */
                    450:        std     %l2,[%o3+32]            /* save %l2, %l3 */
                    451:        std     %l4,[%o3+40]            /* save %l4, %l5 */
                    452:        std     %l6,[%o3+48]            /* save %l6, %l7 */
                    453:        std     %g2,[%o3+56]            /* save %g2, %g3 */
                    454:        st      %g1,[%o3+64]            /* save %g1 */
                    455:        set     _saved_nonptrs,%o3
                    456:        std     %o0,[%o3]               /* save %o0, %o1 as non-pointers */
                    457:        STORE   (%g0, _inML)            /* note that we are leaving ML code */
                    458:        STORE   (%g7, _saved_exnptr)
                    459:        dec     4,%g6                   /* adjust store pointer */
                    460:        STORE   (%g6, _saved_dataptr)
                    461:        STORE   (%g5, _saved_storeptr)
                    462: #ifdef OLD
                    463:        set     0x7ffffffc,%o0          /* adjust limit ptr */
                    464:        sub     %o0,%g4,%g4
                    465:        STORE   (%g4, _saved_limit)
                    466: #endif
                    467:        ldd     [%sp+64],%g6            /* restore C registers %g6 & %g7. */
                    468:        ret
                    469:        restore                         /* restore C register window (delay slot) */
                    470: 
                    471: _restoreregs:
                    472:        save    %sp,-SA(ML_FRAMESIZE),%sp
                    473:        STORE   (%sp, _bottom)          /* record the base of the ML frame */
                    474:        std     %g6,[%sp+64]            /* save C registers %g6 & %g7 */
                    475:        set     _ml_mul,%o0             /* set pointer to ml_mul */
                    476:        st      %o0,[%sp+72]
                    477:        set     _ml_div,%o0             /* set pointer to ml_div */
                    478:        st      %o0,[%sp+76]
                    479:        FETCH   (_saved_exnptr, %g7)
                    480:        FETCH   (_saved_dataptr, %g6)
                    481:        inc     4,%g6                   /* adjust store pointer */
                    482:        FETCH   (_saved_storeptr, %g5)
                    483:        FETCH   (_saved_limit, %g4)
                    484:        set     0x7ffffffc,%o0          /* adjust limit ptr */
                    485:        sub     %o0,%g4,%g4
                    486:        set     1,%o0                   /* note that we are entering ML code */
                    487:        STORE   (%o0, _inML)
                    488:        set     _saved_ptrs,%o3
                    489:        ldd     [%o3],%i0               /* restore %i0, %i1 */
                    490:        ldd     [%o3+8],%i2             /* restore %i2, %i3 */
                    491:        ldd     [%o3+16],%i4            /* restore %i4, %i5 */
                    492:        ldd     [%o3+24],%l0            /* restore %l0, %l1 */
                    493:        ldd     [%o3+32],%l2            /* restore %l2, %l3 */
                    494:        ldd     [%o3+40],%l4            /* restore %l4, %l5 */
                    495:        ldd     [%o3+48],%l6            /* restore %l6, %l7 */
                    496:        ldd     [%o3+56],%g2            /* restore %g2, %g3 */
                    497:        ld      [%o3+64],%g1            /* restore %g1 */
                    498:        set     _saved_nonptrs,%o3
                    499:        ldd     [%o3],%o0               /* restore %o0, %o1 as non-pointers */
                    500:        FETCH   (_fault_pending, %o4)   /* check for a pending fault */
                    501:        tst     %o4
                    502:        bne     _fault
                    503:        nop
                    504:        sub     %i3,-4096,%i3           /* adjust the base code ptr (add 4096) */
                    505:        FETCH   (_saved_pc, %o4)        /* fetch the ML code address. */
                    506:        jmp     %o4                     /* invoke the ML code */
                    507:        nop
                    508: 
                    509: _fault:                                    /* there is a pending fault */
                    510:         clr     %o4                     /* clear the pending fault flag */
                    511:         STORE   (%o4, _fault_pending)
                    512:        FETCH   (_fault_code, %i0)      /* get the fault exception packet. */
                    513:        RAISE                           /* raise the exception */
                    514: 
                    515: /** Integer multiplication and division routines **
                    516:  *
                    517:  * The arguments are %o2, %o3 and the result is in %o2.
                    518:  * Note: this code assumes that .mul and .div don't trash any global or input
                    519:  * registers.
                    520:  */
                    521:        .global .mul, .div
                    522: 
                    523: /* ml_mul:
                    524:  * multiply %o2 by %o3, returning the result in %o2
                    525:  * Note: this code assumes that .mul doesn't trash any global or input
                    526:  * registers.
                    527:  */
                    528: _ml_mul:
                    529:        save    %sp,-SA(WINDOWSIZE),%sp
                    530:        mov     %i2,%o0
                    531:        call    .mul
                    532:        mov     %i3,%o1                 /* (delay slot) */
                    533:        bnz     1f                      /* if z is clear, then overflow */
                    534:        restore %o0,0,%o2               /* result in %o2 (delay slot) */
                    535:        retl
                    536:        nop
                    537: 1:                                     /* handle overflow. */
                    538:        set     _overflow_e,%i0
                    539:        RAISE
                    540:        
                    541: /* ml_div:
                    542:  * divide %o2 by %o3, returning the result in %o2.
                    543:  * Note: .div uses %g1, %g2 and %g3, so we must save them.  We do this using the
                    544:  * locals of the new window, since .div is a leaf routine.
                    545:  */
                    546: _ml_div:
                    547:        save    %sp,-SA(WINDOWSIZE),%sp
                    548:        addcc   %i3,%g0,%o1             /* %o1 is divisor (and check for zero) */
                    549:        bz      1f
                    550:                                    /* save %g1, %g2 and %g3 (using new window) */
                    551:        mov     %g1,%l1                 /* (delay slot) */
                    552:        mov     %g2,%l2
                    553:        mov     %g3,%l3
                    554:        call    .div
                    555:        mov     %i2,%o0                 /* (delay slot) */
                    556:                                    /* restore %g1, %g2 and %g3 */
                    557:        mov     %l3,%g3
                    558:        mov     %l2,%g2
                    559:        mov     %l1,%g1
                    560:        ret
                    561:        restore %o0,0,%o2               /* result in %o2 (delay slot) */
                    562: 1:                                 /* handle zero divide */
                    563:        restore                         /* restore ML window */
                    564:        set     _div_e,%i0
                    565:        RAISE
                    566: 
                    567: 
                    568: /* this bogosity is for export.c */
                    569:        .global _startptr
                    570: _startptr:
                    571:        .long    start
                    572: 
                    573: 
                    574: #include <sun4/trap.h>
                    575: 
                    576: /* ml_longjmp:
                    577:  * Restore the ML register window.
                    578:  */
                    579:        .global _ml_longjmp
                    580: _ml_longjmp:
                    581:        t       ST_FLUSH_WINDOWS        /* flush all reg windows to the stack */
                    582:        FETCH   (_bottom, %fp)          /* set %fp to the %sp of the ML frame */
                    583:        sub     %fp,SA(WINDOWSIZE),%sp
                    584:        restore                         /* restore the ML frame, also restoring */
                    585:                                        /* the local and in registers. */
                    586:        ba      _saveregs
                    587:        nop
                    588: 
                    589: 
                    590: /* _set_fpsr:
                    591:  *
                    592:  *    Load the floating-point status register with the given word.
                    593:  */
                    594:        .global _set_fsr
                    595: _set_fsr:
                    596:        set     fsrtmp,%o1
                    597:        st      %o0,[%o1]
                    598:        retl
                    599:        ld      [%o1],%fsr              /* (delay slot) */
                    600:        .seg    "data"
                    601: fsrtmp:        .word   0

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.