Annotation of researchv10no/cmd/sml/src/runtime/SPARC.prim.s, revision 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.