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

1.1       root        1: /* Copyright 1989 by AT&T Bell Laboratories */
                      2: #include "tags.h"
                      3: #include "prof.h"
                      4: #include "prim.h"
                      5: #define stdarg 2
                      6: #define stdcont 3
                      7: #define stdclos 4
                      8: #define storeptr 22
                      9: #define dataptr 23
                     10: #define exnptr 30
                     11: #define artemp1 24
                     12: #define artemp2 25
                     13: #define artemp3 20
                     14: #define ptrtemp 21
                     15: #define String(handle,len,str) .align 2;\
                     16:                               .set noreorder;\
                     17:                               .word len*power_tags+tag_string;\
                     18:                               handle: .ascii str;\
                     19:                               .set reorder
                     20: #define Closure(name) .align   2;\
                     21:                      .set noreorder;\
                     22:                      .word     mak_desc(1,tag_record);\
                     23:                      name:     .word 9f; /* address of routine */ \
                     24:                      .word     1; /* here for historical reasons */\
                     25:                      .word     tag_backptr;\
                     26:                      .set reorder;\
                     27:                      9:
                     28:        .data
                     29: bottom: .word 0                        /* C's saved stack pointer */
                     30: saved_pc_diff: .word 0
                     31: 
                     32: 
                     33:        .text
                     34: 
                     35:        .globl  runvec
                     36:        .align  2
                     37:         .word  mak_desc(8,tag_record)
                     38: runvec:
                     39:        .word   array_v
                     40:         .word  callc_v
                     41:        .word   create_b_v
                     42:        .word   create_s_v
                     43:        .word   floor_v
                     44:        .word   logb_v
                     45:        .word   scalb_v
                     46:        .word   syscall_v
                     47: 
                     48: Closure(array_v)
                     49:        lw $artemp1,0($stdarg)          /* tagged length in $artemp1 */
                     50:        lw $10,4($stdarg)               /* get initial value in $10 */
                     51:        sra $artemp1,1                  /* drop the tag bit */
                     52:        sll $artemp2,$artemp1,width_tags /* length for descr into $artemp2 */
                     53:        ori $artemp2,tag_array          /* complete descriptor into $artemp2 */
                     54:        sll $artemp1,2                  /* get length in bytes into $artemp1 */
                     55: .set noreorder /* can't reorder because collection might occur */
                     56:        add $artemp3,$artemp1,$dataptr  /* $artemp3 points to last word 
                     57:                                                        of new array*/
                     58: badgc1:        sw $0,($artemp3)                        /* clear; causes allocation */
                     59: .set reorder  /* can rearrange instructions again */
                     60:        sw $artemp2,0($dataptr)         /* store the descriptor */
                     61:        add $dataptr,4                  /* points to new object */
                     62:        add $artemp3,$artemp1,$dataptr  /* beyond last word of new array*/
                     63:        add $stdarg,$dataptr,$0         /* put ptr in return register
                     64:                                        (return val = arg of continuation) */
                     65:                b 2f
                     66:         1:     sw $10,0($dataptr)              /* store the value */
                     67:                addi $dataptr,4                 /* on to the next word */
                     68:         2:     bne $dataptr,$artemp3,1b        /* if not off the end, repeat */
                     69:         
                     70: 
                     71:        lw $10,0($stdcont)              /* grab continuation */
                     72:        j $10                           /* return */
                     73: 
                     74: Closure(create_b_v)
                     75:        addi $artemp3,$0,tag_bytearray  /* tag into $artemp3 */
                     76:        b       2f
                     77: Closure(create_s_v)
                     78:        addi $artemp3,$0,tag_string     /* tag into $artemp3 */
                     79: 2:     
                     80:        addi    $artemp1,$stdarg,13     /* $2n+14$ */
                     81:        sra     $artemp1,3              /* number of words in string+tag */
                     82:        sll     $artemp1,2              /* # of bytes allocated for str+tag */
                     83: .set noreorder /* don't cross gc boundary */
                     84:        add     $artemp2,$artemp1,$dataptr /* beyond last word of string */
                     85: badgc2:        sw $0,-4($artemp2)              /* clear last; causes allocation */
                     86: .set reorder
                     87:        sra     $artemp2,$stdarg,1      /* untagged length in bytes */
                     88:        sll     $artemp2,width_tags     /* room for descriptor */
                     89:        or      $artemp2,$artemp3       /* descriptor */
                     90:        sw      $artemp2,0($dataptr)    /* store descriptor */
                     91:        addi    $stdarg,$dataptr,4      /* pointer to new string */
                     92:        add     $dataptr,$artemp1       /* advance; save 1 instruction */
                     93:        lw $10,0($stdcont)              /* grab continuation */
                     94:        j $10                           /* return */
                     95: 
                     96:        .globl saveregs
                     97:        .globl handle_c
                     98:        .globl return_c
                     99:        .globl restoreregs
                    100: .ent restoreregs
                    101: restoreregs:
                    102: #define regspace 44
                    103: #define localspace 4
                    104: #define argbuild 16
                    105: #define framesize (regspace+localspace+argbuild) /* must be multiple of 8 */
                    106: #define frameoffset (0-localspace)
                    107:        subu $sp,framesize
                    108: .mask 0xd0ff0000,0-localspace
                    109:        sw      $31,argbuild+40($sp)
                    110:        sw      $30,argbuild+36($sp)
                    111:        sw      $gp,argbuild+32($sp)
                    112:         sw      $23,argbuild+28($sp)
                    113:         sw      $22,argbuild+24($sp)
                    114:         sw      $21,argbuild+20($sp)
                    115:         sw      $20,argbuild+16($sp)
                    116:         sw      $19,argbuild+12($sp)
                    117:         sw      $18,argbuild+8($sp)
                    118:         sw      $17,argbuild+4($sp)
                    119:         sw      $16,argbuild($sp)
                    120: 
                    121: .set noat
                    122:        cfc1 $at,$31            /* grab fpa control register */
                    123:        ori  $at,$at,0x600      /* set O and Z bits */
                    124:        ctc1 $at,$31            /* return fpa control register */
                    125: .set at
                    126: 
                    127:        sw      $sp,bottom      /* save C's stack pointer */
                    128:     lw $artemp1,saved_pc
                    129:        la $artemp2,badgc1
                    130:        beq $artemp1,$artemp2,badpc
                    131:        la $artemp2,badgc2
                    132:        beq $artemp1,$artemp2,badpc
                    133: 
                    134:     b 1f
                    135: badpc:
                    136:     subu $artemp1,4            /* adjust */
                    137:     sw $artemp1,saved_pc       /* save */
                    138: 1:
                    139: 
                    140: 
                    141:        /* the big three: argument, continuation, closure */
                    142:        lw      $stdarg,saved_ptrs
                    143:        lw      $stdcont,saved_ptrs+4
                    144:        lw      $stdclos,saved_ptrs+8
                    145:        
                    146:        /* All the miscellaneous guys */
                    147:         lw      $5,saved_ptrs+12
                    148:         lw      $6,saved_ptrs+16
                    149:         lw      $7,saved_ptrs+20
                    150:         lw      $8,saved_ptrs+24
                    151:         lw      $9,saved_ptrs+28
                    152:         lw      $10,saved_ptrs+32
                    153:         lw      $11,saved_ptrs+36
                    154:         lw      $12,saved_ptrs+40
                    155:         lw      $13,saved_ptrs+44
                    156:         lw      $14,saved_ptrs+48
                    157:         lw      $15,saved_ptrs+52
                    158:         lw      $16,saved_ptrs+56
                    159:         lw      $17,saved_ptrs+60
                    160:         lw      $18,saved_ptrs+64
                    161:         lw      $19,saved_ptrs+68
                    162: 
                    163:        lw      $21, saved_ptrs+72
                    164: 
                    165:        lw $artemp1,saved_pc
                    166:        lw $31,saved_pc_diff
                    167:        addu $31,$artemp1               /* mustn't overflow */
                    168:        lw      $artemp1,saved_nonptrs
                    169:        lw      $artemp2,saved_nonptrs+4
                    170:        lw      $artemp3,saved_nonptrs+8
                    171: 
                    172:        /* don't touch registers $26 and $27 */
                    173: 
                    174:        lw      $storeptr,saved_storeptr
                    175:        lw      $dataptr,saved_dataptr
                    176:        lw      $exnptr,saved_exnptr
                    177: 
                    178: .set noat /* This trick will cause a warning, but the code is OK */
                    179:        lw      $at,saved_pc    /* grab the saved program counter */
                    180:        j       $at             /* and continue executing at that spot */
                    181: .set at
                    182: 
                    183: Closure(handle_c) /* exception handler for ML functions called from C */
                    184:        li      $artemp1,CAUSE_EXN
                    185:        sw      $artemp1,cause
                    186:        b       saveregs
                    187: Closure(return_c) /* continuation for ML functions called from C */
                    188:        li      $artemp1,CAUSE_RET
                    189:        sw      $artemp1,cause
                    190: saveregs: 
                    191:                                        /* needn't save $1 */
                    192:        /* the big three: argument, continuation, closure */
                    193:        sw      $stdarg,saved_ptrs
                    194:        sw      $stdcont,saved_ptrs+4
                    195:        sw      $stdclos,saved_ptrs+8
                    196:        
                    197:        /* All the miscellaneous guys */
                    198:         sw      $5,saved_ptrs+12
                    199:         sw      $6,saved_ptrs+16
                    200:         sw      $7,saved_ptrs+20
                    201:         sw      $8,saved_ptrs+24
                    202:         sw      $9,saved_ptrs+28
                    203:         sw      $10,saved_ptrs+32
                    204:         sw      $11,saved_ptrs+36
                    205:         sw      $12,saved_ptrs+40
                    206:         sw      $13,saved_ptrs+44
                    207:         sw      $14,saved_ptrs+48
                    208:         sw      $15,saved_ptrs+52
                    209:         sw      $16,saved_ptrs+56
                    210:         sw      $17,saved_ptrs+60
                    211:         sw      $18,saved_ptrs+64
                    212:         sw      $19,saved_ptrs+68
                    213: 
                    214:        sw      $21, saved_ptrs+72
                    215: 
                    216:        sw      $artemp1,saved_nonptrs
                    217:        sw      $artemp2,saved_nonptrs+4
                    218:        sw      $artemp3,saved_nonptrs+8
                    219: 
                    220:        /* don't touch registers $26 and $27 */
                    221: 
                    222:        sw      $storeptr,saved_storeptr
                    223:        sw      $dataptr,saved_dataptr
                    224:        sw      $exnptr,saved_exnptr
                    225: 
                    226:        lw $artemp1,saved_pc
                    227:        subu $artemp1,$31,$artemp1      /* mustn't overflow */
                    228:        sw $artemp1,saved_pc_diff
                    229: 
                    230: 
                    231:        lw      $sp,bottom      /* recover C's stack pointer */
                    232:        lw      $31,argbuild+40($sp)
                    233:        lw      $30,argbuild+36($sp)
                    234:        lw      $gp,argbuild+32($sp)
                    235:         lw      $23,argbuild+28($sp)
                    236:         lw      $22,argbuild+24($sp)
                    237:         lw      $21,argbuild+20($sp)
                    238:         lw      $20,argbuild+16($sp)
                    239:         lw      $19,argbuild+12($sp)
                    240:         lw      $18,argbuild+8($sp)
                    241:         lw      $17,argbuild+4($sp)
                    242:         lw      $16,argbuild($sp)
                    243: 
                    244: 
                    245:        addu $sp,framesize
                    246:        j       $31     /* return to C program */
                    247: .end restoreregs
                    248: 
                    249: Closure(callc_v)
                    250:        sw $stdcont,argbuild+regspace($sp) /* save continuation on stack */
                    251:        lw $4,4($stdarg)        /* get value a into arg register */
                    252:        lw $10,0($stdarg)       /* get address of f into misc reg */
                    253:        jal $10                 /* call f ($31 can be trashed) */
                    254:        move $stdarg,$2         /* return val is argument to continuation */
                    255:        lw $stdcont,argbuild+regspace($sp) /* recover continuation */
                    256:        move $stdclos,$0
                    257:        move $5,$0
                    258:        move $6,$0
                    259:        move $7,$0
                    260:        move $8,$0
                    261:        move $9,$0
                    262:        move $10,$0
                    263:        move $11,$0
                    264:        move $12,$0
                    265:        move $13,$0
                    266:        move $14,$0
                    267:        move $15,$0
                    268:        /* $16--$23 and $30 are saved by the callee */
                    269: 
                    270:        lw $artemp3,cause       /* get cause */
                    271:         bne $artemp3,$0,saveregs /* if cause != 0, save ML & return to C */
                    272:        lw $10,0($stdcont)      /* grab continuation */
                    273:        j $10                   /* return */
                    274: Closure(syscall_v)
                    275:        sw $stdcont,argbuild+regspace($sp) /* save continuation on stack */
                    276:        lw $artemp1,8($stdarg)  /* 2*argc+1 in $artemp1 */
                    277:        sra $artemp1,1          /* argc in $artemp1 */
                    278:        move $16,$sp            /* save our $sp */
                    279:        ble $artemp1,4,1f               /* big enough */
                    280:        sub $artemp2,$artemp1,3         /* (temp2 = argc - 4 + 1) > 1 */
                    281:        sra $artemp2,1                  
                    282:        sll $artemp2,3                  /* temp2 = 4 * roundup (argc-4,2) */
                    283:        subu $sp,$artemp2               /* increase stack */
                    284: 1:
                    285: 
                    286:        lw $ptrtemp,4($stdarg)  /* argv in $ptrtemp */
                    287:        move $artemp2,$sp               /* destination in $artemp2 */
                    288:        b 1f                            /* branch forward to test */
                    289: 2:     /* argc > 0 */
                    290:        lw $artemp3,0($ptrtemp)         /* get list element */
                    291:        andi $10,$artemp3,1             /* tagged? */
                    292:        beqz $10,3f
                    293:        sra $artemp3,1                  /* drop tag bit */
                    294: 3:     sw $artemp3,0($artemp2)         /* save the argument */
                    295:        lw $ptrtemp,4($ptrtemp)         /* next element */
                    296:        add $artemp2,4                  /* next arg build area */
                    297:        sub $artemp1,1                  /* --argc */
                    298: 1:     bgtz $artemp1,2b                /* if argc>0, store another */
                    299: 
                    300:        lw $4,0($sp)
                    301:        lw $5,4($sp)
                    302:        lw $6,8($sp)
                    303:        lw $7,12($sp)
                    304: 
                    305: 9:     lw $2,0($stdarg)        /* get syscall # in $2; trash $stdarg */
                    306:        sra $2,1                /* throw out the tag bit */
                    307:        syscall
                    308:        move $sp,$16            /* recover the good stack pointer */
                    309:        lw $stdcont,argbuild+regspace($sp) /* recover continuation */
                    310:        bnez $7,1f              /* if error, return ~1 */
                    311:        move $stdarg,$2         /* return val is argument to continuation */
                    312:        add $stdarg,$stdarg     /* double return value */
                    313:        addi $stdarg,1          /* and add tag bit */
                    314:        b 2f
                    315: 1:     sw  $stdarg,errno
                    316:        li $stdarg,-1
                    317: 2:
                    318:        move $stdclos,$0
                    319:        move $5,$0
                    320:        move $6,$0
                    321:        move $7,$0
                    322:        move $8,$0
                    323:        move $9,$0
                    324:        move $10,$0
                    325:        move $11,$0
                    326:        move $12,$0
                    327:        move $13,$0
                    328:        move $14,$0
                    329:        move $15,$0
                    330:        /* $16--$23 and $30 are saved by the callee */
                    331: 
                    332:        lw $10,0($stdcont)      /* grab continuation */
                    333:        j $10                   /* return */
                    334: 
                    335: /* Floating exceptions raised (assuming ROP's are never passed to functions):
                    336:  *     DIVIDE BY ZERO - (div)
                    337:  *     OVERFLOW/UNDERFLOW - (add,div,sub,mul) as appropriate
                    338:  *
                    339:  * floor raises integer overflow if the float is out of 32-bit range,
                    340:  * so the float is tested before conversion, to make sure it is in (31-bit)
                    341:  * range */
                    342: 
                    343: Closure(floor_v)
                    344:        lwc1 $f4,0($stdarg)             /* get least significant word */
                    345:        lwc1 $f5,4($stdarg)             /* get most significant word */
                    346: .set noat
                    347:        cfc1 $at,$31            /* grab fpa control register */
                    348:        ori  $at,0x03           /* set rounding bits to 11 */
                    349:        ctc1 $at,$31            /* return fpa control register */
                    350: .set at
                    351:        cvt.w.d $f6,$f4                 /* convert to integer */
                    352: .set noat
                    353:        cfc1 $at,$31            /* grab fpa control register */
                    354:        ori  $at,0x03           /* set rounding bits to 11 */
                    355:        xori $at,0x03           /* set rounding bits to 00
                    356:        ctc1 $at,$31            /* return fpa control register */
                    357: .set at
                    358:        mfc1 $stdarg,$f6                /* get in std argument register */
                    359:        sll $stdarg,1           /* make room for tag bit */
                    360:        add $stdarg,1           /* add the tag bit */
                    361:        lw $10,0($stdcont)      /* grab continuation */
                    362:        j $10                   /* return */
                    363: 
                    364: 
                    365: Closure(logb_v)
                    366:        lw      $stdarg,4($stdarg)      /* most significant part */
                    367:        srl     $stdarg,20              /* throw out 20 low bits */
                    368:        andi    $stdarg,0x07ff          /* clear all but 11 low bits */
                    369:        sub     $stdarg,1023            /* subtract 1023 */
                    370:        sll     $stdarg,1               /* make room for tag bit */
                    371:        add     $stdarg,1               /* add the tag bit */
                    372:        lw      $10,0($stdcont)         /* grab continuation */
                    373:        j       $10                     /* return */
                    374: 
                    375: Closure(scalb_v)
                    376:        lw      $artemp1,4($stdarg)     /* get tagged n */
                    377:        sra     $artemp1,1              /* get real n */
                    378:        beqz    $artemp1,9f             /* if zero, return the old float */
                    379:        lw      $ptrtemp,0($stdarg)     /* get pointer to float */
                    380:        lw      $artemp2,4($ptrtemp)    /* most significant part */
                    381:        srl     $artemp2,20             /* throw out 20 low bits */
                    382:        andi    $artemp2,0x07ff         /* clear all but 11 low bits */
                    383:        add     $artemp3,$artemp2,$artemp1      /* new := old + n */
                    384:        blt     $artemp3,1,under        /* punt if underflow */
                    385:        bgt     $artemp3,2046,over      /* or overflow */
                    386:        xor     $artemp3,$artemp2       /* at3 = new xor old */
                    387:        sll     $artemp3,20             /* put exponent in right position */
                    388:        lw      $artemp2,4($ptrtemp)    /* most significant word */
                    389:        xor     $artemp2,$artemp3       /* change to new exponent */
                    390: .set noreorder
                    391:        sw      $artemp2,8($dataptr)    /* allocate; may cause gc */
                    392: .set reorder
                    393:        lw      $artemp2,0($ptrtemp)    /* get least significant word */
                    394:        li      $10,mak_desc(8,tag_string) /* make descriptor */
                    395:        sw      $artemp2,4($dataptr)    /* save lsw */
                    396:        sw      $10,0($dataptr)         /* save descriptor */
                    397:        add     $stdarg,$dataptr,4      /* get pointer to new float */
                    398:        add     $dataptr,12             /* point to new free word */
                    399:        lw      $10,0($stdcont)         /* grab continuation */
                    400:        j       $10                     /* return */
                    401: 
                    402: 9:     lw      $stdarg,0($stdarg)      /* get old float */
                    403:        lw      $10,0($stdcont)         /* grab continuation */
                    404:        j       $10                     /* return */
                    405: 
                    406: over:  la      $stdarg,1f              /* exception name in $stdarg */
                    407:        b       raise_real
                    408: String(1,8,"overflow")
                    409: under: la      $stdarg,1f              /* exception name in $stdarg */
                    410:        b       raise_real
                    411: String(1,9,"underflow\0\0\0")
                    412: 
                    413: raise_real:
                    414:  /* build new record to pass to exception handler */
                    415:  /*    [descriptor]
                    416:  /*    [exception (string)]
                    417:  /*    [real_e (more exception info)]
                    418:   */
                    419:        la      $10,real_e              /* get address of real_e */
                    420: .set noreorder
                    421:        sw      $10,8($dataptr)         /* allocate; may cause gc */
                    422: .set reorder
                    423:        sw      $stdarg,4($dataptr)
                    424:        li      $10,mak_desc(2,tag_record)
                    425:        sw      $10,0($dataptr)
                    426:        add     $stdarg,$dataptr,4      /* new record is argument */
                    427:        addi    $dataptr,12             /* $dataptr restored */
                    428:        move    $stdclos,$exnptr        /* make sure closure is right */
                    429:        lw      $10,0($exnptr)          /* grab handler */
                    430:        j       $10                     /* raise the exception */
                    431: 
                    432: /* this bogosity is for export.c */
                    433:        .globl  startptr
                    434: startptr: .word    __start     /* just a guess... */
                    435: 
                    436: 

unix.superglobalmegacorp.com

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