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

Defined functions

clrq defined in line 1; never used
incl defined in line 1; used 4 times
jmp defined in line 1; used 8 times
movl defined in line 1; used 82 times
movq defined in line 1; used 14 times
pushl defined in line 1; used 6 times

Defined macros

Arrayaccfun defined in line 22; used 1 times
  • in line 88
Atomfnbnd defined in line 19; used 1 times
  • in line 67
LBOT defined in line 46; used 12 times
NIL defined in line 44; used 9 times
NP defined in line 45; used 15 times
Profile defined in line 35; used 11 times
Profile2 defined in line 36; used 2 times
Last modified: 1985-08-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 667
Valid CSS Valid XHTML 1.0 Strict