|
|
1.1 ! root 1: /* ! 2: * qfuncl.c ! 3: * lisp to C interface ! 4: * ! 5: * (c) copyright 1982, Regents of the University of California ! 6: * ! 7: * This is written in assembler but must be passed through the C preprocessor ! 8: * before being assembled. ! 9: */ ! 10: ! 11: #include "ltypes.h" ! 12: #include "config.h" ! 13: ! 14: /* important offsets within data types for atoms */ ! 15: #define Atomfnbnd 8 ! 16: ! 17: /* for arrays */ ! 18: #define Arrayaccfun 0 ! 19: ! 20: #ifdef PROF ! 21: .set indx,0 ! 22: #define Profile \ ! 23: movab prbuf+indx,r0 \ ! 24: .set indx,indx+4 \ ! 25: jsb mcount ! 26: #define Profile2 \ ! 27: movl r0,r5 \ ! 28: Profile \ ! 29: movl r5,r0 ! 30: #else ! 31: #define Profile ! 32: #define Profile2 ! 33: #endif ! 34: ! 35: #ifdef PORTABLE ! 36: #define NIL _nilatom ! 37: #define NP _np ! 38: #define LBOT _lbot ! 39: #else ! 40: #define NIL 0 ! 41: #define NP r6 ! 42: #define LBOT r7 ! 43: #endif ! 44: ! 45: ! 46: /* transfer table linkage routine */ ! 47: ! 48: .globl _qlinker ! 49: _qlinker: ! 50: .word 0x1fc0 # save all possible registers ! 51: Profile ! 52: tstl _exception # any pending exceptions ! 53: jeql noexc ! 54: tstl _sigintcnt # is it because of SIGINT ! 55: jeql noexc # if not, just leave ! 56: pushl $2 # else push SIGINT ! 57: callf $8,_sigcall ! 58: noexc: ! 59: movl r2, r0 # stick linktable entry in r0 ! 60: movl 4(r2),r1 # get atom pointer ! 61: retry: # come here after undef func error ! 62: movl Atomfnbnd(r1),r2 # get function binding ! 63: jleq nonex # if none, leave ! 64: tstl _stattab+2*4 # see if linking possible (Strans) ! 65: jeql nolink # no, it isn't ! 66: shar $9,r2,r3 # check type of function ! 67: cmpb $BCD,_typetable+1[r3] ! 68: jeql linkin # bcd, link it in! ! 69: cmpb $ARRAY,_typetable+1[r3] # how about array? ! 70: jeql doarray # yep ! 71: ! 72: ! 73: nolink: ! 74: pushl r1 # non, bcd, call interpreter ! 75: callf $8,_Ifuncal ! 76: ret ! 77: ! 78: /* ! 79: * handle arrays by pushing the array descriptor on the table and checking ! 80: * for a bcd array handler ! 81: */ ! 82: doarray: ! 83: shar $9,Arrayaccfun(r2),r3 # get access function addr shifted ! 84: cmpb $/**/BCD,_typetable+1[r3] # bcd?? ! 85: jneq nolink # no, let funcal handle it ! 86: #ifdef PORTABLE ! 87: movl NP,r4 ! 88: movl r2,(r4)+ # store array header on stack ! 89: movl r4,NP ! 90: #else ! 91: movl r2,(r6) # store array header on stack ! 92: addl2 $4, r6 ! 93: #endif ! 94: movl *(r2),r2 # get in func addr ! 95: jmp 2(r2) # jump in beyond calls header ! 96: ! 97: ! 98: linkin: ! 99: shar $9,4(r2),r3 # check type of function discipline ! 100: cmpb $0,_typetable+1[r3] # is it string? ! 101: jeql nolink # yes, it is a c call, so dont link in ! 102: movl (r2),r2 # get function addr ! 103: movl r2,(r0) # put fcn addr in table ! 104: jmp 2(r2) # enter fcn after mask ! 105: ! 106: nonex: pushl r0 # preserve table address ! 107: pushl r1 # non existant fcn ! 108: callf $8,_Undeff # call processor ! 109: movl r0,r1 # back in r1 ! 110: movl (sp)+,r0 # restore table address ! 111: jbr retry # for the retry. ! 112: ! 113: ! 114: .globl __erthrow # errmessage for uncaught throws ! 115: __erthrow: ! 116: .asciz "Uncaught throw from compiled code" ! 117: ! 118: .align 2 ! 119: .globl _tynames ! 120: _tynames: ! 121: .long NIL # nothing here ! 122: .long _lispsys+20*4 # str_name ! 123: .long _lispsys+21*4 # atom_name ! 124: .long _lispsys+19*4 # int_name ! 125: .long _lispsys+23*4 # dtpr_name ! 126: .long _lispsys+22*4 # doub_name ! 127: .long _lispsys+58*4 # funct_name ! 128: .long _lispsys+103*4 # port_name ! 129: .long _lispsys+47*4 # array_name ! 130: .long NIL # nothing here ! 131: .long _lispsys+50*4 # sdot_name ! 132: .long _lispsys+53*4 # val_nam ! 133: .long NIL # hunk2_nam ! 134: .long NIL # hunk4_nam ! 135: .long NIL # hunk8_nam ! 136: .long NIL # hunk16_nam ! 137: .long NIL # hunk32_nam ! 138: .long NIL # hunk64_nam ! 139: .long NIL # hunk128_nam ! 140: .long _lispsys+124*4 # vector_nam ! 141: .long _lispsys+125*4 # vectori_nam ! 142: ! 143: /* Quickly allocate small fixnums */ ! 144: ! 145: .globl _qnewint ! 146: _qnewint: ! 147: .word 0 ! 148: Profile ! 149: cmpl r5,$1024 ! 150: jgeq alloc ! 151: cmpl r5,$-1024 ! 152: jlss alloc ! 153: moval _Fixzero[r5],r0 ! 154: ret ! 155: alloc: ! 156: movl _int_str,r0 # move next cell addr to r0 ! 157: jlss callnewi # if no space, allocate ! 158: incl *_lispsys+24*4 # inc count of ints ! 159: movl (r0),_int_str # advance free list ! 160: movl r5,(r0) # put baby to bed. ! 161: ret ! 162: callnewi: ! 163: pushl r5 ! 164: callf $4,_newint ! 165: movl (sp)+,(r0) ! 166: ret ! 167: ! 168: ! 169: /* _qoneplus adds one to the boxed fixnum in r0 ! 170: * and returns a boxed fixnum. ! 171: */ ! 172: ! 173: .globl _qoneplus ! 174: _qoneplus: ! 175: .word 0 ! 176: Profile2 ! 177: addl3 (r0),$1,r5 ! 178: #ifdef PORTABLE ! 179: movl r6,NP ! 180: movl r6,LBOT ! 181: #endif ! 182: jmp _qnewint+2 ! 183: ! 184: /* _qoneminus subtracts one from the boxes fixnum in r0 and returns a ! 185: * boxed fixnum ! 186: */ ! 187: .globl _qoneminus ! 188: _qoneminus: ! 189: .word 0 ! 190: Profile2 ! 191: subl3 $1,(r0),r5 ! 192: #ifdef PORTABLE ! 193: movl r6,NP ! 194: movl r6,LBOT ! 195: #endif ! 196: jmp _qnewint+2 ! 197: ! 198: /* ! 199: * _qnewdoub quick allocation of a initialized double (float) cell. ! 200: * This entry point is required by the compiler for symmetry reasons. ! 201: * Passed to _qnewdoub in r4,r5 is a double precision floating point ! 202: * number. This routine allocates a new cell, initializes it with ! 203: * the given value and then returns the cell. ! 204: */ ! 205: ! 206: .globl _qnewdoub ! 207: _qnewdoub: ! 208: .word 0 ! 209: Profile ! 210: movl _doub_str,r0 # move next cell addr to r0 ! 211: jlss callnewd # if no space, allocate ! 212: incl *_lispsys+30*4 # inc count of doubs ! 213: movl (r0),_doub_str # advance free list ! 214: movl r4,(r0) # put baby to bed. ! 215: movl r5,4(r0) #was movq r4,(r0) ! 216: ret ! 217: ! 218: callnewd: ! 219: pushl r5 # stack initial value ! 220: pushl r4 ! 221: callf $4,_newdoub ! 222: movl (sp)+, (r0) # restore initial value ! 223: movl (sp)+, 4(r0) ! 224: ret ! 225: ! 226: .globl _qcons ! 227: ! 228: /* ! 229: * quick cons call, the car and cdr are stacked on the namestack ! 230: * and this function is jsb'ed to. ! 231: */ ! 232: ! 233: _qcons: ! 234: .word 0 ! 235: Profile ! 236: movl _dtpr_str,r0 # move next cell addr to r0 ! 237: jlss getnew # if ran out of space jump ! 238: incl *_lispsys+28*4 # inc count of dtprs ! 239: movl (r0),_dtpr_str # advance free list ! 240: storit: ! 241: subl2 $8,r6 ! 242: movl 4(r6),(r0) # store in cdr ! 243: movl (r6),4(r0) # store in car ! 244: ret ! 245: ! 246: getnew: ! 247: #ifdef PORTABLE ! 248: movl r6,NP ! 249: movab -8(r6),LBOT ! 250: #endif ! 251: callf $4,_newdot # must gc to get one ! 252: jbr storit # now initialize it. ! 253: ! 254: /* ! 255: * Fast equivalent of newdot, no longer entered by jsb ! 256: */ ! 257: ! 258: .globl _qnewdot ! 259: _qnewdot: ! 260: .word 0 ! 261: Profile ! 262: movl _dtpr_str,r0 # mov next cell addr t0 r0 ! 263: jlss mustallo # if ran out of space ! 264: incl *_lispsys+28*4 # inc count of dtprs ! 265: movl (r0),_dtpr_str # advance free list ! 266: clrl (r0) # replaces clrq ! 267: clrl 4(r0) ! 268: ret ! 269: mustallo: ! 270: callf $4,_newdot ! 271: ret ! 272: ! 273: /* prunel - return a list of dtpr cells to the free list ! 274: * this is called by the pruneb after it has discarded the top bignum ! 275: * the dtpr cells are linked through their cars not their cdrs. ! 276: * this returns with an ret ! 277: * ! 278: * method of operation: the dtpr list we get is linked by car's so we ! 279: * go through the list and link it by cdr's, then have the last dtpr ! 280: * point to the free list and then make the free list begin at the ! 281: * first dtpr. ! 282: */ ! 283: qprunel: ! 284: movl r0,r2 # remember first dtpr location ! 285: rep: decl *_lispsys+28*4 # decrement used dtpr count ! 286: movl 4(r0),r1 # put link value into r1 ! 287: jeql endoflist # if nil, then end of list ! 288: movl r1,(r0) # repl cdr w/ save val as car ! 289: movl r1,r0 # advance to next dtpr ! 290: jbr rep # and loop around ! 291: endoflist: ! 292: movl _dtpr_str,(r0) # make last 1 pnt to free list ! 293: movl r2,_dtpr_str # & free list begin at 1st 1 ! 294: ret ! 295: ! 296: /* ! 297: * qpruneb - called by the arithmetic routines to free an sdot and the dtprs ! 298: * which hang on it. ! 299: * called by ! 300: * pushl sdotaddr ! 301: * jsb _qpruneb ! 302: */ ! 303: .globl _qpruneb ! 304: _qpruneb: ! 305: .word 0 ! 306: Profile ! 307: movl 4(sp),r0 # get address ! 308: decl *_lispsys+48*4 # decr count of used sdots ! 309: movl _sdot_str,(r0) # have new sdot point to free list ! 310: movl r0,_sdot_str # start free list at new sdot ! 311: movl 4(r0),r0 # get address of first dtpr ! 312: jneq qprunel # if exists, prune it ! 313: ret # else return. ! 314: ! 315: ! 316: /* ! 317: * _qprunei ! 318: * called by the arithmetic routines to free a fixnum cell ! 319: * calling sequence ! 320: * pushl fixnumaddr ! 321: * jsb _qprunei ! 322: */ ! 323: ! 324: .globl _qprunei ! 325: _qprunei: ! 326: .word 0 ! 327: Profile ! 328: movl 4(sp),r0 # get address of fixnum ! 329: cmpl r0,$_Lastfix # is it a small fixnum ! 330: jleq skipit # if so, leave ! 331: decl *_lispsys+24*4 # decr count of used ints ! 332: movl _int_str,(r0) # link the fixnum into the free list ! 333: movl r0,_int_str ! 334: skipit: ! 335: ret ! 336: ! 337: ! 338: .globl _qpopnames ! 339: _qpopnames: # equivalent of C-code popnames, entered by jsb. ! 340: .word 0 ! 341: movl (sp)+,r0 # return address ! 342: movl (sp)+,r1 # Lower limit ! 343: movl _bnp,r2 # pointer to bind stack entry ! 344: qploop: ! 345: subl2 $8,r2 # for(; (--r2) > r1;) { ! 346: cmpl r2,r1 # test for done ! 347: jlss qpdone ! 348: movl (r2),*4(r2) # r2->atm->a.clb = r2 -> val; ! 349: brb qploop # } ! 350: qpdone: ! 351: movl r1,_bnp # restore bnp ! 352: jmp (r0) # return ! 353: ! 354: /* ! 355: * _qget : fast get subroutine ! 356: * (get 'atom 'ind) ! 357: * called with -8(r6) equal to the atom ! 358: * -4(r6) equal to the indicator ! 359: * no assumption is made about LBOT ! 360: * unfortunately, the atom may not in fact be an atom, it may ! 361: * be a list or nil, which are special cases. ! 362: * For nil, we grab the nil property list (stored in a special place) ! 363: * and for lists we punt and call the C routine since it is most likely ! 364: * and error and we havent put in error checks yet. ! 365: */ ! 366: ! 367: .globl _qget ! 368: _qget: ! 369: .word 0 ! 370: Profile ! 371: movl -4(r6),r1 # put indicator in r1 ! 372: movl -8(r6),r0 # and atom into r0 ! 373: jeql nilpli # jump if atom is nil ! 374: shar $9,r0,r2 # check type ! 375: cmpb _typetable+1[r2],$1 # is it a symbol?? ! 376: jneq notsymb # nope ! 377: movl 4(r0),r0 # yes, put prop list in r1 to begin scan ! 378: jeql fail # if no prop list, we lose right away ! 379: lp: cmpl r1,4(r0) # is car of list eq to indicator? ! 380: jeql good # jump if so ! 381: movl *(r0),r0 # else cddr down list ! 382: jneq lp # and jump if more list to go. ! 383: ! 384: fail: subl2 $8,NP # unstack args ! 385: ret # return with r0 eq to nil ! 386: ! 387: good: movl (r0),r0 # return cadr of list ! 388: movl 4(r0),r0 ! 389: subl2 $8,NP #unstack args ! 390: ret ! 391: ! 392: nilpli: movl _lispsys+64*4,r0 # want nil prop list, get it specially ! 393: jneq lp # and process if anything there ! 394: subl2 $8,NP #unstack args ! 395: ret # else fail ! 396: ! 397: notsymb: ! 398: #ifdef PORTABLE ! 399: movl r6,NP ! 400: movab -8(r6),LBOT # must set up LBOT before calling ! 401: #else ! 402: movab -8(r6),LBOT # must set up LBOT before calling ! 403: #endif ! 404: callf $4,_Lget # not a symbol, call C routine to error check ! 405: subl2 $8,NP #unstack args ! 406: ret # and return what it returned. ! 407: ! 408: #ifdef NOTNOW ! 409: /* ! 410: * _qexarith exact arithmetic ! 411: * calculates x=a*b+c where a,b and c are 32 bit 2's complement integers ! 412: * whose top two bits must be the same (i.e. the are members of the set ! 413: * of valid fixnum values for Franz Lisp). The result, x, will be 64 bits ! 414: * long but since each of a, b and c had only 31 bits of precision, the ! 415: * result x only has 62 bits of precision. The lower 30 bits are returned ! 416: * in *plo and the high 32 bits are returned in *phi. If *phi is 0 or -1 then ! 417: * x doesn't need any more than 31 bits plus sign to describe, so we ! 418: * place the sign in the high two bits of *plo and return 0 from this ! 419: * routine. A non zero return indicates that x requires more than 31 bits ! 420: * to describe. ! 421: */ ! 422: ! 423: .globl _qexarith ! 424: /* qexarith(a,b,c,phi,plo) ! 425: * int *phi, *plo; ! 426: */ ! 427: _qexarith: ! 428: emul 4(sp),8(sp),12(sp),r2 #r2 = a*b + c to 64 bits ! 429: extzv $0,$30,r2,*20(sp) #get new lo ! 430: extv $30,$32,r2,r0 #get new carry ! 431: beql out # hi = 0, no work necessary ! 432: movl r0,*16(sp) # save hi ! 433: mcoml r0,r0 # Is hi = -1 (it'll fit in one word) ! 434: bneq out # it doesn't ! 435: bitl $0xc0000000,*20(sp) # alter low so that it is ok. ! 436: out: ret ! 437: ! 438: #endif ! 439: ! 440: #ifdef NOTNOW ! 441: /* ! 442: * pushframe : stack a frame ! 443: * When this is called, the optional arguments and class have already been ! 444: * pushed on the stack as well as the return address (by virtue of the jsb) ! 445: * , we push on the rest of the stuff (see h/frame.h) ! 446: * for a picture of the save frame ! 447: */ ! 448: .globl _qpushframe ! 449: ! 450: _qpushframe: ! 451: Profile ! 452: movl _errp,-(sp) ! 453: movl _bnp,-(sp) ! 454: movl NP,-(sp) ! 455: movl LBOT,-(sp) ! 456: storer $0x3f00, -(sp) # save r13(fp), r12(ap),r11,r10,r9,r8 ! 457: movab 6*4(sp),r0 # return addr of lbot on stack ! 458: clrl _retval # set retval to C_INITIAL ! 459: #ifndef SPISFP ! 460: jmp *40(sp) # return through return address ! 461: #else ! 462: movab -4(sp),sp ! 463: movl sp,(sp) ! 464: movl _xsp,-(sp) ! 465: jmp *48(sp) ! 466: #endif ! 467: ! 468: /* ! 469: * qretfromfr ! 470: * called with frame to ret to in r11. The popnames has already been done. ! 471: * we must restore all registers, and jump to the ret addr. the popping ! 472: * must be done without reducing the stack pointer since an interrupt ! 473: * could come in at any time and this frame must remain on the stack. ! 474: * thus we can't use popr. ! 475: */ ! 476: ! 477: .globl _qretfromfr ! 478: ! 479: _qretfromfr: ! 480: Profile ! 481: movl r11,r0 # return error frame location ! 482: subl3 $24,r11,sp # set up sp at bottom of frame ! 483: movl sp,r1 # prepare to pop off ! 484: movl (r0),r8 # was movd (r0)+, r8 and such ! 485: movl 4(r0),r9 ! 486: movl 8(r0),r10 ! 487: movl 12(r0),r11 ! 488: movl 16(r0),r12 ! 489: movl 20(r0),r13 ! 490: movl 24(r0),LBOT ! 491: movl 28(r0),NP ! 492: addl2 $32, r0 #just in case ! 493: jmp *40(sp) # jump out of frame ! 494: #endif NOTNOW ! 495: ! 496: #ifdef SPISFP ! 497: ! 498: /* ! 499: * this is equivalent to qretfro for a native VMS system ! 500: * ! 501: */ ! 502: .globl _Iretfrm ! 503: _Iretfrm: ! 504: .word 0 ! 505: movl 4(fp),r0 # return error frame location ! 506: movl r0,r1 ! 507: movd -(r1),r12 ! 508: movd -(r1),r10 ! 509: movd -(r1),r8 ! 510: movl -(r1),sp ! 511: movl -(r1),_xsp ! 512: movd -(r1),r6 ! 513: movd -(r1),r4 ! 514: movd -(r1),r2 ! 515: movl r0,r1 ! 516: movl (r1)+,LBOT ! 517: movl (r1)+,NP ! 518: jmp *16(r0) ! 519: #endif SPISPF ! 520: ! 521: /* ! 522: * this routine finishes setting things up for dothunk ! 523: * it is code shared to keep the size of c-callable thunks ! 524: * for lisp functions, small. ! 525: */ ! 526: .globl _thcpy ! 527: _thcpy: ! 528: movl (sp),r0 ! 529: pushl r12 ! 530: pushl (r0) ! 531: pushl 4(r0) ! 532: addl2 $8,r0 # was postincrement ! 533: callf $4,_dothunk ! 534: ret ! 535: /* ! 536: * This routine gets the name of the inital entry point ! 537: * It is here so it can be under ifdef control. ! 538: */ ! 539: .globl _gstart ! 540: _gstart: ! 541: .word 0 ! 542: #if os_vms ! 543: moval _$$$start,r0 ! 544: #else ! 545: moval start,r0 ! 546: #endif ! 547: ret ! 548: ! 549: .globl _proflush ! 550: _proflush: ! 551: .word 0 ! 552: ret ! 553: ! 554: /* ! 555: * The definition of mcount must be present even when the C code ! 556: * isn't being profiled, since lisp code may reference it. ! 557: */ ! 558: ! 559: #ifndef os_vms ! 560: .globl mcount ! 561: mcount: ! 562: #endif ! 563: ! 564: .globl _mcount ! 565: _mcount: ! 566: ! 567: #ifdef PROF ! 568: movl (r0),r1 ! 569: bneq incr ! 570: movl _countbase,r1 ! 571: beql return ! 572: addl2 $8,_countbase ! 573: movl (sp),(r1)+ ! 574: movl r1,(r0) ! 575: incr: ! 576: incl (r1) ! 577: return: ! 578: #endif ! 579: ret ! 580: ! 581: ! 582: /* This must be at the end of the file. If we are profiling, allocate ! 583: * space for the profile buffer ! 584: */ ! 585: #ifdef PROF ! 586: .data ! 587: .comm _countbase,4 ! 588: .lcomm prbuf,indx+4 ! 589: .text ! 590: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.