|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.