Annotation of 43BSD/ucb/lisp/liszt/funa.l, revision 1.1.1.1

1.1       root        1: (include-if (null (get 'chead 'version)) "../chead.l")
                      2: (Liszt-file funa
                      3:    "$Header: funa.l,v 1.11 83/08/28 17:14:35 layer Exp $")
                      4: 
                      5: ;;; ----       f u n a                         function compilation
                      6: ;;;
                      7: ;;;                            -[Mon Aug 22 22:01:01 1983 by layer]-
                      8: 
                      9: 
                     10: ;--- cc-and :: compile an and expression
                     11: ; We evaluate forms from left to right as long as they evaluate to
                     12: ; a non nil value.  We only have to worry about storing the value of
                     13: ; the last expression in g-loc.
                     14: ;
                     15: (defun cc-and nil
                     16:   (let ((finlab (d-genlab))
                     17:        (finlab2)
                     18:        (exps (if (cdr v-form) thenret else '(t))))     ; (and) ==> t
                     19:        (if (null (cdr g-cc))
                     20:           then (d-exp (do ((g-cc (cons nil finlab))
                     21:                            (g-loc)
                     22:                            (g-ret)
                     23:                            (ll exps (cdr ll)))
                     24:                           ((null (cdr ll)) (car ll))
                     25:                           (d-exp (car ll))))
                     26:                (if g-loc
                     27:                    then (setq finlab2 (d-genlab))
                     28:                         (e-goto finlab2)
                     29:                         (e-label finlab)
                     30:                         (d-move 'Nil g-loc)
                     31:                         (e-label finlab2)
                     32:                    else (e-label finlab))
                     33:           else ;--- cdr g-cc is non nil, thus there is
                     34:                ; a quick escape possible if one of the
                     35:                ; expressions evals to nil
                     36: 
                     37:                (if (null g-loc) then (setq finlab (cdr g-cc)))
                     38:                (d-exp (do ((g-cc (cons nil finlab))
                     39:                            (g-loc)
                     40:                            (g-ret)
                     41:                            (ll exps (cdr ll)))
                     42:                           ((null (cdr ll)) (car ll))
                     43:                           (d-exp (car ll))))
                     44:                ; if g-loc is non nil, then we have evaled the and
                     45:                ; expression to yield nil, which we must store in
                     46:                ; g-loc and then jump to where the cdr of g-cc takes us
                     47:                (if g-loc
                     48:                    then (setq finlab2 (d-genlab))
                     49:                         (e-goto finlab2)
                     50:                         (e-label finlab)
                     51:                         (d-move 'Nil g-loc)
                     52:                         (e-goto (cdr g-cc))
                     53:                         (e-label finlab2))))
                     54:   (d-clearreg))         ; we cannot predict the state of the registers
                     55: 
                     56: ;--- cc-arg  :: get the nth arg from the current lexpr
                     57: ;
                     58: ; the syntax for Franz lisp is (arg i)
                     59: ; for interlisp the syntax is (arg x i) where x is not evaluated and is
                     60: ; the name of the variable bound to the number of args.  We can only handle
                     61: ; the case of x being the variable for the current lexpr we are compiling
                     62: ;
                     63: (defun cc-arg nil
                     64:    (prog (nillab finlab)
                     65:        (setq nillab (d-genlab)
                     66:             finlab (d-genlab))
                     67:        (if (not (eq 'lexpr g-ftype)) 
                     68:           then (comp-err " arg only allowed in lexprs"))
                     69:        (if (and (eq (length (cdr v-form)) 2) fl-inter)
                     70:           then (if (not (eq (car g-args) (cadr v-form)))
                     71:                    then (comp-err " arg expression is for non local lexpr "
                     72:                                   v-form)
                     73:                    else (setq v-form (cdr v-form))))
                     74:        (if (and (null g-loc) (null g-cc))
                     75:           then ;bye bye, wouldn't do anything
                     76:                (return nil))
                     77:        (if (and (fixp (cadr v-form)) (>& (cadr v-form) 0))
                     78:           then ; simple case (arg n) for positive n
                     79:                (d-move `(fixnum ,(cadr v-form)) 'reg)
                     80:                #+for-68k
                     81:                (progn
                     82:                    (e-sub `(-4 #.olbot-reg) 'd0)
                     83:                    (if g-loc
                     84:                        then (e-move '(% -8 #.olbot-reg d0) (e-cvt g-loc)))
                     85:                    (if g-cc then (e-cmpnil '(% -8 #.olbot-reg d0))))
                     86:                #+for-vax
                     87:                (progn
                     88:                    (e-sub3 '(* -4 #.olbot-reg) '(0 r0) 'r0)
                     89:                    (if g-loc
                     90:                        then (e-move '(-8 #.olbot-reg r0) (e-cvt g-loc))
                     91:                     elseif g-cc
                     92:                        then (e-tst '(-8 #.olbot-reg r0))))
                     93:                (d-handlecc)
                     94:        elseif (or (null (cadr v-form))
                     95:                   (and (fixp (cadr v-form)) (=& 0 (cadr v-form))))
                     96:           then ;---the form is: (arg nil) or (arg) or (arg 0).
                     97:                ;   We have a private copy of the number of args right
                     98:                ; above the arguments on the name stack, so that
                     99:                ; the user can't clobber it... (0 olbot) points
                    100:                ; to the user setable copy, and (-4 olbot) to our
                    101:                ; copy.
                    102:                (if g-loc then (e-move '(-4 #.olbot-reg) (e-cvt g-loc)))
                    103:                ;   Will always return a non nil value, so
                    104:                ; don't even test it.
                    105:                (if (car g-cc) then (e-goto (car g-cc)))
                    106:           else ; general (arg <form>)
                    107:                (let ((g-loc 'reg)
                    108:                      (g-cc (cons nil nillab))
                    109:                      (g-ret))
                    110:                    (d-exp (cadr v-form)))  ;boxed fixnum or nil
                    111:                ; (arg 0) returns nargs (compiler only!)
                    112:                (d-cmp 'reg '(fixnum 0))
                    113:                (e-gotonil nillab)
                    114:                
                    115:                ; ... here we are doing (arg <number>), <number> != 0
                    116:                #+for-68k
                    117:                (progn
                    118:                    (e-sub '(-4 #.olbot-reg) 'd0)
                    119:                    (if g-loc
                    120:                        then (e-move '(% -8 #.olbot-reg d0) (e-cvt g-loc)))
                    121:                    (if g-cc then (e-cmpnil '(% -8 #.olbot-reg d0))))
                    122:                #+for-vax
                    123:                (progn
                    124:                    (e-sub3 `(* -4 #.olbot-reg) '(0 r0) 'r0)
                    125:                    (if g-loc
                    126:                        then (e-move '(-8 #.olbot-reg r0) (e-cvt g-loc))
                    127:                     elseif g-cc
                    128:                        then (e-tst '(-8 #.olbot-reg r0))))
                    129:                (d-handlecc)
                    130:                (e-goto finlab)
                    131:                (e-label nillab)
                    132:                ; here we are doing (arg nil) which
                    133:                ; returns the number of args
                    134:                ; which is always true if anyone is testing
                    135:                (if g-loc
                    136:                    then (e-move '(-4 #.olbot-reg) (e-cvt g-loc))
                    137:                         #+for-68k (if g-cc then (e-cmpnil '(-4 #.olbot-reg)))
                    138:                         (d-handlecc)
                    139:                 elseif (car g-cc)
                    140:                    then (e-goto (car g-cc))) ;always true
                    141:                (e-label finlab))))
                    142: 
                    143: ;--- c-assembler-code
                    144: ; the args to assembler-code are a list of assembler language 
                    145: ; statements.  This statements are put directly in the code
                    146: ; stream produced by the compiler.  Beware: The interpreter cannot
                    147: ; interpret the assembler-code function.
                    148: ;
                    149: (defun c-assembler-code nil
                    150:   (setq g-skipcode nil)                ; turn off code skipping
                    151:   (makecomment '(assembler code start))
                    152:   (do ((xx (cdr v-form) (cdr xx)))
                    153:       ((null xx))
                    154:       (e-write1 (car xx)))
                    155:   (makecomment '(assembler code end)))
                    156: 
                    157: ;--- cm-assq :: assoc with eq for testing
                    158: ;
                    159: ; form: (assq val list)
                    160: ;
                    161: (defun cm-assq nil
                    162:   `(do ((xx-val ,(cadr v-form))
                    163:        (xx-lis ,(caddr v-form) (cdr xx-lis)))
                    164:        ((null xx-lis))
                    165:        (cond ((eq xx-val (caar xx-lis)) (return (car xx-lis))))))
                    166: 
                    167: ;--- cc-atom :: test for atomness
                    168: ;
                    169: (defun cc-atom nil
                    170:   (d-typecmplx (cadr v-form)
                    171:               #.(immed-const (plus 1_0 1_1 1_2 1_4 1_5 1_6 1_7 1_9 1_10))))
                    172: 
                    173: ;--- c-bcdcall :: do a bcd call
                    174: ;
                    175: ; a bcdcall is the franz equivalent of the maclisp subrcall.
                    176: ; it is called with
                    177: ; (bcdcall 'b_obj 'arg1 ...)
                    178: ;  where b_obj must be a binary object. no type checking is done.
                    179: ;
                    180: (defun c-bcdcall nil
                    181:   (d-callbig 1 (cdr v-form) t))
                    182: 
                    183: ;--- cc-bcdp :: check for bcdpness
                    184: ;
                    185: (defun cc-bcdp nil
                    186:   (d-typesimp (cadr v-form) #.(immed-const 5)))
                    187: 
                    188: ;--- cc-bigp :: check for bignumness
                    189: ;
                    190: (defun cc-bigp nil
                    191:   (d-typesimp (cadr v-form) #.(immed-const 9)))
                    192: 
                    193: ;--- c-boole :: compile
                    194: ;
                    195: #+for-vax
                    196: (progn 'compile
                    197: (defun c-boole nil
                    198:    (cond ((fixp (cadr v-form))
                    199:          (setq v-form (d-boolexlate (d-booleexpand v-form)))))
                    200:    (cond ((eq 'boole (car v-form))     ;; avoid recursive calls to d-exp
                    201:          (d-callbig 'boole (cdr v-form) nil))
                    202:         (t (let ((g-loc 'reg) (g-cc nil) (g-ret nil))  ; eval answer
                    203:               (d-exp v-form)))))
                    204: 
                    205: ;--- d-booleexpand :: make sure boole only has three args
                    206: ;  we use the identity (boole k x y z) == (boole k (boole k x y) z)
                    207: ; to make sure that there are exactly three args to a call to boole
                    208: ;
                    209: (defun d-booleexpand (form)
                    210:    (if (and (dtpr form) (eq 'boole (car form)))
                    211:        then (if (< (length form) 4)
                    212:                then (comp-err "Too few args to boole : " form)
                    213:             elseif (= (length form) 4)
                    214:                then form
                    215:                else (d-booleexpand
                    216:                         `(boole ,(cadr form)
                    217:                                  (boole ,(cadr form)
                    218:                                          ,(caddr form)
                    219:                                          ,(cadddr form))
                    220:                                  ,@(cddddr form))))
                    221:        else form))
                    222: 
                    223: (declare (special x y))
                    224: (defun d-boolexlate (form)
                    225:    (if (atom form)
                    226:        then form
                    227:     elseif (and (eq 'boole (car form))
                    228:                (fixp (cadr form)))
                    229:        then (let ((key (cadr form))
                    230:                  (x (d-boolexlate (caddr form)))
                    231:                  (y (d-boolexlate (cadddr form)))
                    232:                  (res))
                    233:                (makecomment `(boole key = ,key))
                    234:                (if (eq key 0)          ;; 0
                    235:                    then `(progn ,x ,y 0)
                    236:                 elseif (eq key 1)      ;; x * y
                    237:                    then `(fixnum-BitAndNot ,x (fixnum-BitXor ,y -1))
                    238:                 elseif (eq key 2)      ;; !x * y
                    239:                    then `(fixnum-BitAndNot (fixnum-BitXor ,x -1)
                    240:                                            (fixnum-BitXor ,y -1))
                    241:                 elseif (eq key 3)      ;; y
                    242:                    then `(progn ,x ,y)
                    243:                 elseif (eq key 4)      ;; x * !y
                    244:                    then `(fixnum-BitAndNot ,x ,y)
                    245:                 elseif (eq key 5)      ;; x
                    246:                    then `(prog1 ,x ,y)
                    247:                 elseif (eq key 6)        ;; x xor y
                    248:                    then `(fixnum-BitXor ,x ,y)
                    249:                 elseif (eq key 7)      ;; x + y
                    250:                    then `(fixnum-BitOr ,x ,y)
                    251:                 elseif (eq key 8)      ;; !(x xor y)
                    252:                    then `(fixnum-BitXor (fixnum-BitOr ,x ,y) -1)
                    253:                 elseif (eq key 9)      ;; !(x xor y)
                    254:                    then `(fixnum-BitXor (fixnum-BitXor ,x ,y) -1)
                    255:                 elseif (eq key 10)     ;; !x
                    256:                    then `(prog1 (fixnum-BitXor ,x -1) ,y)
                    257:                 elseif (eq key 11)     ;; !x + y
                    258:                    then `(fixnum-BitOr (fixnum-BitXor ,x -1) ,y)
                    259:                 elseif (eq key 12)     ;; !y
                    260:                    then `(progn ,x (fixnum-BitXor ,y -1))
                    261:                 elseif (eq key 13)     ;; x + !y
                    262:                    then `(fixnum-BitOr ,x (fixnum-BitXor ,y -1))
                    263:                 elseif (eq key 14)     ;; !x + !y
                    264:                    then `(fixnum-BitOr (fixnum-BitXor ,x -1)
                    265:                                        (fixnum-BitXor ,y -1))
                    266:                 elseif (eq key 15)     ;; -1
                    267:                    then `(progn ,x ,y -1)
                    268:                    else form))
                    269:        else form))
                    270: 
                    271: (declare (unspecial x y))
                    272: ) ;; end for-vax
                    273: 
                    274: 
                    275: ;--- c-*catch :: compile a *catch expression
                    276: ;
                    277: ; the form of *catch is (*catch 'tag 'val)
                    278: ; we evaluate 'tag and set up a catch frame, and then eval 'val
                    279: ;
                    280: (defun c-*catch nil
                    281:    (let ((g-loc 'reg)
                    282:         (g-cc nil)
                    283:         (g-ret nil)
                    284:         (finlab (d-genlab))
                    285:         (beglab (d-genlab)))
                    286:        (d-exp (cadr v-form))           ; calculate tag into 'reg
                    287:        (d-pushframe #.F_CATCH 'reg 'Nil) ; the Nil is a don't care
                    288:        (push nil g-labs)               ; disallow labels
                    289:        ; retval will be non 0 if we were thrown to, in which case the value
                    290:        ; thrown is in _lispretval.
                    291:        ; If we weren't thrown-to the value should be calculated in r0.
                    292:        (e-tst '_retval)
                    293:        (e-write2 #+for-vax 'jeql #+for-68k 'jeq beglab)
                    294:        (e-move '_lispretval (e-cvt 'reg))
                    295:        (e-write2 #+for-vax 'jbr #+for-68k 'jra finlab)
                    296:        (e-label beglab)
                    297:        (d-exp (caddr v-form))
                    298:        (e-label finlab)
                    299:        (d-popframe)    ; remove catch frame from stack
                    300:        (unpush g-locs) ; remove (catcherrset . 0)
                    301:        (unpush g-labs)  ; allow labels again
                    302:        (d-clearreg)))
                    303: 
                    304: ;--- d-pushframe :: put an evaluation frame on the stack
                    305: ;
                    306: ; This is equivalant in the C system to 'errp = Pushframe(class,arg1,arg2);'
                    307: ; We stack a frame which describes the class (will always be F_CATCH)
                    308: ; and the other option args.
                    309: ; 2/10/82 - it is a bad idea to stack a variable number of arguments, since
                    310: ; this makes it more complicated to unstack frames.  Thus we will always
                    311: ; stack the maximum --jkf
                    312: (defun d-pushframe (class arg1 arg2)
                    313:   (C-push (e-cvt arg2))
                    314:   (C-push (e-cvt arg1))
                    315:   (C-push `($ ,class))
                    316:   (if (null $global-reg$)
                    317:       then (e-move '#.np-reg '#.np-sym)
                    318:           (e-move '#.np-reg '#.lbot-sym))
                    319:   (e-quick-call '_qpushframe)
                    320:   (e-move (e-cvt 'reg) '_errp)
                    321:   (push '(catcherrset . 0) g-locs))
                    322: 
                    323: ;--- d-popframe :: remove an evaluation frame from the stack
                    324: ;
                    325: ; This is equivalent in the C system to 'errp = Popframe();'
                    326: ;  n is the number of arguments given to the pushframe which
                    327: ; created this frame.  We have to totally remove this frame from
                    328: ; the stack only if we are in a local function, but for now, we just
                    329: ; do it all the time.
                    330: ;
                    331: (defun d-popframe ()
                    332:    (let ((treg #+for-vax 'r1 #+for-68k 'a5))
                    333:        (e-move '_errp treg)
                    334:        (e-move `(#.OF_olderrp ,treg) '_errp)
                    335:        ; there are always 3 arguments pushed, and the frame contains 5
                    336:        ; longwords.  We should make these parameters into manifest
                    337:        ; constants --jkf
                    338:        (e-add3 `($ ,(+ (* 3 4) (* 5 4))) treg 'sp)))
                    339: 
                    340: ;--- c-cond :: compile a "cond" expression
                    341: ;
                    342: ; not that this version of cond is a 'c' rather than a 'cc' . 
                    343: ; this was done to make coding this routine easier and because
                    344: ; it is believed that it wont harm things much if at all
                    345: ;
                    346: (defun c-cond nil
                    347:   (makecomment '(beginning cond))
                    348:   (do ((clau (cdr v-form) (cdr clau))
                    349:        (finlab (d-genlab))
                    350:        (nxtlab)
                    351:        (save-reguse)
                    352:        (seent))
                    353:       ((or (null clau) seent)
                    354:        ; end of cond
                    355:        ; if haven't seen a t must store a nil in `reg'
                    356:        (if (null seent)  then (d-move 'Nil 'reg))
                    357:        (e-label finlab))
                    358: 
                    359:       ; case 1 - expr
                    360:       (if (atom (car clau))
                    361:          then (comp-err "bad cond clause " (car clau))
                    362:       ; case 2 - (expr)
                    363:        elseif (null (cdar clau))
                    364:          then (let ((g-loc (if (or g-cc g-loc) then 'reg))
                    365:                     (g-cc (cons finlab nil))
                    366:                     (g-ret (and g-ret (null (cdr clau)))))
                    367:                    (d-exp (caar clau)))
                    368:       ; case 3 - (t expr1 expr2 ...)
                    369:        elseif (or (eq t (caar clau))
                    370:                  (equal ''t (caar clau)))
                    371:          then (let ((g-loc (if (or g-cc g-loc) then 'reg))
                    372:                     g-cc)
                    373:                    (d-exps (cdar clau)))
                    374:               (setq seent t)
                    375:       ; case 4 - (expr1 expr2 ...)
                    376:        else (let ((g-loc nil)
                    377:                  (g-cc (cons nil (setq nxtlab (d-genlab))))
                    378:                  (g-ret nil))
                    379:                 (d-exp (caar clau)))
                    380:            (setq save-reguse (copy g-reguse))
                    381:            (let ((g-loc (if (or g-cc g-loc) then 'reg))
                    382:                  g-cc)
                    383:                 (d-exps (cdar clau)))
                    384:            (if (or (cdr clau) (null seent)) then (e-goto finlab))
                    385:            (e-label nxtlab)
                    386:            (setq g-reguse save-reguse)))
                    387:   
                    388:   (d-clearreg))
                    389:              
                    390: ;--- c-cons :: do a cons instruction quickly
                    391: ;
                    392: (defun c-cons nil
                    393:   (d-pushargs (cdr v-form))            ; there better be 2 args
                    394:   (e-quick-call '_qcons)
                    395:   (setq g-locs (cddr g-locs))
                    396:   (setq g-loccnt (- g-loccnt 2))
                    397:   (d-clearreg))
                    398: 
                    399: ;--- c-cxr :: compile a cxr instruction
                    400: ; 
                    401: ;
                    402: (defun cc-cxr nil
                    403:   (d-supercxr t nil))
                    404: 
                    405: ;--- d-supercxr :: do a general struture reference
                    406: ;      type - one of fixnum-block,flonum-block,<other-symbol>
                    407: ; the type is that of an array, so <other-symbol> could be t, nil
                    408: ; or anything else, since anything except *-block is treated the same
                    409: ;
                    410: ; the form of a cxr is (cxr index hunk) but supercxr will handle
                    411: ; arrays too, so hunk could be (getdata (getd 'arrayname))
                    412: ;
                    413: ; offsetonly is t if we only care about the offset of this element from
                    414: ; the beginning of the data structure.  If offsetonly is t then type
                    415: ; will be nil.
                    416: ;
                    417: ; Note: this takes care of g-loc and g-cc 
                    418: 
                    419: #+for-vax
                    420: (defun d-supercxr (type offsetonly)
                    421:   (let ((arg1 (cadr v-form))
                    422:        (arg2 (caddr v-form))
                    423:        lop rop semisimple)
                    424: 
                    425:        (if (fixp arg1) then (setq lop `(immed ,arg1))
                    426:           else (d-fixnumexp arg1)      ; calculate index into r5
                    427:                (setq lop 'r5))         ; and remember that it is there
                    428: 
                    429:        ; before we calculate the second expression, we may have to save
                    430:        ; the value just calculated into r5.  To be safe we stack away
                    431:        ; r5 if the expression is not simple or semisimple.
                    432:        (if (not (setq rop (d-simple arg2)))    
                    433:           then (if (and (eq lop 'r5) 
                    434:                         (not (setq semisimple (d-semisimple arg2))))
                    435:                    then (C-push (e-cvt lop)))
                    436:                (let ((g-loc 'reg) g-cc)
                    437:                     (d-exp arg2))
                    438:                (setq rop 'r0)
                    439: 
                    440:                (if (and (eq lop 'r5) (not semisimple))
                    441:                    then (C-pop (e-cvt lop))))
                    442: 
                    443:        (if (eq type 'flonum-block)
                    444:          then (setq lop (d-structgen lop rop 8))
                    445:               (e-write3 'movq lop 'r4)
                    446:               (e-quick-call '_qnewdoub)        ; box number
                    447:               (d-clearreg)                     ; clobbers all regs
                    448:               (if (and g-loc (not (eq g-loc 'reg)))
                    449:                  then (d-move 'reg g-loc))
                    450:               (if (car g-cc) then (e-goto (car g-cc)))
                    451:          else (setq lop (d-structgen lop rop 4)
                    452:                     rop (if g-loc then
                    453:                             (if (eq type 'fixnum-block) then 'r5 
                    454:                                else (e-cvt g-loc))))
                    455:               (if rop 
                    456:                  then (if offsetonly
                    457:                          then (e-write3 'moval lop rop)
                    458:                          else (e-move lop rop))
                    459:                       (if (eq type 'fixnum-block) 
                    460:                           then (e-call-qnewint)
                    461:                                (d-clearreg)
                    462:                                (if (not (eq g-loc 'reg))
                    463:                                    then (d-move 'reg g-loc))
                    464:                                ; result is always non nil.
                    465:                                (if (car g-cc) then (e-goto (car g-cc)))
                    466:                           else (d-handlecc))
                    467:                elseif g-cc 
                    468:                  then (if (eq type 'fixnum-block)
                    469:                          then (if (car g-cc) 
                    470:                                  then (e-goto (car g-cc)))
                    471:                          else (e-tst lop)
                    472:                                (d-handlecc))))))
                    473: 
                    474: #+for-68k
                    475: (defun d-supercxr (type offsetonly)
                    476:    (let ((arg1 (cadr v-form))
                    477:         (arg2 (caddr v-form))
                    478:         lop rop semisimple)
                    479:        (makecomment `(Starting d-supercxr: vform: ,v-form))
                    480:        (if (fixp arg1) then (setq lop `(immed ,arg1))
                    481:           else (d-fixnumexp arg1)        ; calculate index into fixnum-reg
                    482:                (d-regused '#.fixnum-reg)
                    483:                (setq lop '#.fixnum-reg)) ; and remember that it is there
                    484:        ;
                    485:        ; before we calculate the second expression, we may have to save
                    486:        ; the value just calculated into fixnum-reg. To be safe we stack away
                    487:        ; fixnum-reg if the expression is not simple or semisimple.
                    488:        (if (not (setq rop (d-simple arg2)))    
                    489:           then (if (and (eq lop '#.fixnum-reg)
                    490:                         (not (setq semisimple (d-semisimple arg2))))
                    491:                    then (C-push (e-cvt lop)))
                    492:                (let ((g-loc 'areg) g-cc)
                    493:                    (d-exp arg2))
                    494:                (setq rop 'a0)
                    495:                ;
                    496:                (if (and (eq lop '#.fixnum-reg) (not semisimple))
                    497:                    then (C-pop (e-cvt lop))))
                    498:        ;
                    499:        (if (eq type 'flonum-block)
                    500:           then (setq lop (d-structgen lop rop 8))
                    501:                (break " d-supercxr : flonum stuff not done.")
                    502:                (e-write3 'movq lop 'r4)
                    503:                (e-quick-call '_qnewdoub)       ; box number
                    504:                (d-clearreg)                    ; clobbers all regs
                    505:                (if (and g-loc (not (eq g-loc 'areg)))
                    506:                    then (d-move 'areg g-loc))
                    507:                (if (car g-cc) then (e-goto (car g-cc)))
                    508:           else (if (and (dtpr rop) (eq 'stack (car rop)))
                    509:                    then (e-move (e-cvt rop) 'a1)
                    510:                         (setq rop 'a1))
                    511:                (setq lop (d-structgen lop rop 4)
                    512:                      rop (if g-loc then
                    513:                              (if (eq type 'fixnum-block)
                    514:                                  then '#.fixnum-reg 
                    515:                                  else (e-cvt g-loc))))
                    516:                (if rop 
                    517:                    then (if offsetonly
                    518:                             then (e-write3 'lea lop 'a5)
                    519:                                  (e-move 'a5 rop)
                    520:                             else (e-move lop rop))
                    521:                         (if (eq type 'fixnum-block) 
                    522:                             then (e-call-qnewint)
                    523:                                  (d-clearreg)
                    524:                                  (if (not (eq g-loc 'areg))
                    525:                                      then (d-move 'areg g-loc))
                    526:                                  ; result is always non nil.
                    527:                                  (if (car g-cc) then (e-goto (car g-cc)))
                    528:                             else (e-cmpnil lop)
                    529:                                  (d-handlecc))
                    530:                 elseif g-cc 
                    531:                    then (if (eq type 'fixnum-block)
                    532:                             then (if (car g-cc) 
                    533:                                      then (e-goto (car g-cc)))
                    534:                             else (if g-cc
                    535:                                      then (e-cmpnil lop)
                    536:                                           (d-handlecc)))))
                    537:        (makecomment "Done with d-supercxr")))
                    538: 
                    539: ;--- d-semisimple :: check if result is simple enough not to clobber r5
                    540: ; currently we look for the case of (getdata (getd 'foo))
                    541: ; since we know that this will only be references to r0.
                    542: ; More knowledge can be added to this routine.
                    543: ;
                    544: (defun d-semisimple (form)
                    545:   (or (d-simple form)
                    546:       (and (dtpr form) 
                    547:           (eq 'getdata (car form))
                    548:           (dtpr (cadr form))
                    549:           (eq 'getd (caadr form))
                    550:           (dtpr (cadadr form))
                    551:           (eq 'quote (caadadr form)))))
                    552: 
                    553: ;--- d-structgen :: generate appropriate address for indexed access
                    554: ;      index - index address, must be (immed n) or r5 (which contains int)
                    555: ;      base  - address of base
                    556: ;      width - width of data element
                    557: ; want to calculate appropriate address for base[index]
                    558: ; may require emitting instructions to set up registers
                    559: ; returns the address of the base[index] suitable for setting or reading
                    560: ;
                    561: ; the code sees the base as a stack value as a special case since it
                    562: ; can generate (perhaps) better code for that case.
                    563: 
                    564: #+for-vax
                    565: (defun d-structgen (index base width)
                    566:   (if (and (dtpr base) (eq (car base) 'stack))
                    567:       then (if (dtpr index)    ; i.e if index = (immed n)
                    568:               then (d-move index 'r5)) ; get immed in register
                    569:           ;  the result is always *n(r6)[r5]
                    570:           (append (e-cvt `(vstack ,(cadr base))) '(r5))
                    571:       else (if (not (atom base))       ; i.e if base is not register
                    572:               then (d-move base 'r0)   ; (if nil gets here we will fail)
                    573:                    (d-clearreg 'r0)
                    574:                    (setq base 'r0))
                    575:           (if (dtpr index) then `(,(* width (cadr index)) ;immed index
                    576:                                    ,base)
                    577:                            else `(0 ,base r5))))
                    578: 
                    579: #+for-68k
                    580: (defun d-structgen (index base width)
                    581:    (if (and (dtpr base) (eq (car base) 'stack))
                    582:        then (break "d-structgen: bad args(1)")
                    583:        else (if (not (atom base))      ; i.e if base is not register
                    584:                then (d-move base 'a0)  ; (if nil gets here we will fail)
                    585:                     (d-clearreg 'a0)
                    586:                     (setq base 'a0))
                    587:            (if (dtpr index)
                    588:                then `(,(* width (cadr index)) ,base)
                    589:                else (d-regused 'd6)
                    590:                     (e-move index 'd6)
                    591:                     (e-write3 'asll '($ 2) 'd6)
                    592:                     `(% 0 ,base d6))))
                    593: 
                    594: ;--- c-rplacx :: complile a rplacx expression
                    595: ;
                    596: ;  This simple calls the general structure hacking function, d-superrplacx
                    597: ;  The argument, hunk, means that the elements stored in the hunk are not
                    598: ;  fixum-block or flonum-block arrays.
                    599: (defun c-rplacx nil
                    600:   (d-superrplacx 'hunk))
                    601: 
                    602: ;--- d-superrplacx :: handle general setting of things in structures
                    603: ;      type - one of fixnum-block, flonum-block, hunk
                    604: ; see d-supercxr for comments
                    605: ; form of rplacx is (rplacx index hunk valuetostore)
                    606: #+for-vax
                    607: (defun d-superrplacx (type)
                    608:         (let ((arg1 (cadr v-form))
                    609:               (arg2 (caddr v-form))
                    610:               (arg3 (cadddr v-form))
                    611:               lop rop semisimple)
                    612:              
                    613:              ; calulate index and put it in r5 if it is not an immediate
                    614:              ; set lop to the location of the index
                    615:              (if (fixp arg1) then (setq lop `(immed ,arg1))
                    616:                  else (d-fixnumexp arg1)
                    617:                       (setq lop 'r5))  
                    618:              
                    619:              ; set rop to the location of the hunk.  If we have to 
                    620:              ; calculate the hunk, we may have to save r5.
                    621:              ; If we are doing a rplacx (type equals hunk) then we must
                    622:              ; return the hunk in r0.
                    623:              (if (or (eq type 'hunk) (not (setq rop (d-simple arg2))))
                    624:                  then (if (and (eq lop 'r5) 
                    625:                                (not (setq semisimple (d-semisimple arg2))))
                    626:                           then (d-move lop '#.Cstack))
                    627:                       (let ((g-loc 'r0) g-cc)
                    628:                            (d-exp arg2))
                    629:                       (setq rop 'r0)
                    630:                  
                    631:                       (if (and (eq lop 'r5) (not semisimple))
                    632:                           then (d-move '#.unCstack lop)))
                    633: 
                    634:              ; now that the index and data block locations are known, we 
                    635:              ; caclulate the location of the index'th element of hunk
                    636:              (setq rop
                    637:                    (d-structgen lop rop
                    638:                                 (if (eq type 'flonum-block) then 8 else 4)))
                    639: 
                    640:              ; the code to calculate the value to store and the actual
                    641:              ; storing depends on the type of data block we are storing in.
                    642:              (if (eq type 'flonum-block) 
                    643:                  then (if (setq lop (d-simple `(cdr ,arg3)))
                    644:                           then (e-write3 'movq (e-cvt lop) rop)
                    645:                           else ; preserve rop since it may be destroyed
                    646:                                ; when arg3 is calculated
                    647:                                (e-write3 'movaq rop '#.Cstack)
                    648:                                (let ((g-loc 'r0) g-cc)
                    649:                                     (d-exp arg3))
                    650:                                (d-clearreg 'r0)
                    651:                                (e-write3 'movq '(0 r0) "*(sp)+"))
                    652:               elseif (and (eq type 'fixnum-block)
                    653:                           (setq arg3 `(cdr ,arg3))
                    654:                           nil)
                    655:                      ; fixnum-block is like hunk except we must grab the
                    656:                      ; fixnum value out of its box, hence the (cdr arg3)
                    657:                   thenret
                    658:               else (if (setq lop (d-simple arg3))
                    659:                        then (e-move (e-cvt lop) rop)
                    660:                        else ; if we are dealing with hunks, we must save
                    661:                             ; r0 since that contains the value we want to
                    662:                             ; return.
                    663:                             (if (eq type 'hunk) then (d-move 'reg 'stack)
                    664:                                                      (Push g-locs nil)
                    665:                                                      (incr g-loccnt))
                    666:                             (e-write3 'moval rop '#.Cstack)
                    667:                             (let ((g-loc "*(sp)+") g-cc)
                    668:                                  (d-exp arg3))
                    669:                             (if (eq type 'hunk) then (d-move 'unstack 'reg)
                    670:                                                      (unpush g-locs)
                    671:                                                      (decr g-loccnt))
                    672:                             (d-clearreg 'r0)))))
                    673: 
                    674: #+for-68k
                    675: (defun d-superrplacx (type)
                    676:    (let ((arg1 (cadr v-form))
                    677:         (arg2 (caddr v-form))
                    678:         (arg3 (cadddr v-form))
                    679:         lop rop semisimple)
                    680:        (makecomment `(starting d-superrplacx ,type :: v-form = ,v-form))
                    681:        ;
                    682:        ; calulate index and put it in '#.fixnum-reg if it is not an immediate
                    683:        ; set lop to the location of the index
                    684:        (if (fixp arg1) then (setq lop `(immed ,arg1))
                    685:           else (d-fixnumexp arg1)
                    686:                (d-regused '#.fixnum-reg)
                    687:                (setq lop '#.fixnum-reg))
                    688:        ;
                    689:        ; set rop to the location of the hunk.  If we have to
                    690:        ; calculate the hunk, we may have to save '#.fixnum-reg.
                    691:        ; If we are doing a rplacx (type equals hunk) then we must
                    692:        ; return the hunk in d0.
                    693:        (if (or (eq type 'hunk) (not (setq rop (d-simple arg2))))
                    694:           then (if (and (eq lop '#.fixnum-reg)
                    695:                         (not (setq semisimple (d-semisimple arg2))))
                    696:                    then (d-move lop '#.Cstack))
                    697:                (let ((g-loc 'a0) g-cc)
                    698:                    (d-exp arg2))
                    699:                (setq rop 'a0)
                    700:                (if (and (eq lop '#.fixnum-reg) (not semisimple))
                    701:                    then (d-move '#.unCstack lop)))
                    702:        ;
                    703:        ; now that the index and data block locations are known, we
                    704:        ; caclulate the location of the index'th element of hunk
                    705:        (setq rop
                    706:             (d-structgen lop rop
                    707:                          (if (eq type 'flonum-block) then 8 else 4)))
                    708:        ;
                    709:        ; the code to calculate the value to store and the actual
                    710:        ; storing depends on the type of data block we are storing in.
                    711:        (if (eq type 'flonum-block) 
                    712:           then (break "flonum stuff not in yet")
                    713:                (if (setq lop (d-simple `(cdr ,arg3)))
                    714:                    then (e-write3 'movq (e-cvt lop) rop)
                    715:                    else ; preserve rop since it may be destroyed
                    716:                         ; when arg3 is calculated
                    717:                         (e-write3 'movaq rop '#.Cstack)
                    718:                         (let ((g-loc 'd0) g-cc)
                    719:                             (d-exp arg3))
                    720:                         (d-clearreg 'd0)
                    721:                         (e-write3 'movq '(0 d0) "*(sp)+"))
                    722:        elseif (and (eq type 'fixnum-block)
                    723:                    (setq arg3 `(cdr ,arg3))
                    724:                    nil)
                    725:             ; fixnum-block is like hunk except we must grab the
                    726:             ; fixnum value out of its box, hence the (cdr arg3)
                    727:           thenret
                    728:           else (if (setq lop (d-simple arg3))
                    729:                    then (e-move (e-cvt lop) rop)
                    730:                    else ; if we are dealing with hunks, we must save
                    731:                         ; d0 since that contains the value we want to
                    732:                         ; return.
                    733:                         (if (eq type 'hunk)
                    734:                             then (L-push 'a0)
                    735:                                  (push nil g-locs)
                    736:                                  (incr g-loccnt))
                    737:                         (e-write3 'lea rop 'a5)
                    738:                         (C-push 'a5)
                    739:                         (let ((g-loc '(racc * 0 sp)) g-cc)
                    740:                             (d-exp arg3))
                    741:                         (if (eq type 'hunk)
                    742:                             then (L-pop 'd0)
                    743:                                  (unpush g-locs)
                    744:                                  (decr g-loccnt))))
                    745:        (makecomment '(d-superrplacx done))))
                    746:                            
                    747: ;--- cc-cxxr :: compile a "c*r" instr where *
                    748: ;              is any sequence of a's and d's
                    749: ;      - arg : argument of the cxxr function
                    750: ;      - pat : a list of a's and d's in the reverse order of that
                    751: ;                      which appeared between the c and r
                    752: ;
                    753: #+for-vax
                    754: (defun cc-cxxr (arg pat)
                    755:   (prog (resloc loc qloc sofar togo keeptrack)
                    756:        ; check for the special case of nil, since car's and cdr's
                    757:        ; are nil anyway
                    758:        (if (null arg)
                    759:            then (if g-loc then (d-move 'Nil g-loc)
                    760:                     (d-handlecc)
                    761:                  elseif (cdr g-cc) then (e-goto (cdr g-cc)))
                    762:                 (return))
                    763:                                      
                    764:        (if (and (symbolp arg) (setq qloc (d-bestreg arg pat)))
                    765:            then (setq resloc (car qloc)
                    766:                       loc   resloc
                    767:                       sofar  (cadr qloc)
                    768:                       togo   (caddr qloc))
                    769:            else (setq resloc
                    770:                       (if (d-simple arg)
                    771:                           thenret
                    772:                           else (let ((g-loc 'reg)
                    773:                                      (g-cc nil)
                    774:                                      (g-ret nil))
                    775:                                    (d-exp arg))
                    776:                                'r0))
                    777:               (setq sofar nil togo pat))
                    778: 
                    779:        (if (and arg (symbolp arg)) then (setq keeptrack t))
                    780: 
                    781:        ; if resloc is a global variable, we must move it into a register
                    782:        ; right away to be able to do car's and cdr's
                    783:        (if (and (dtpr resloc) (or (eq (car resloc) 'bind)
                    784:                                  (eq (car resloc) 'vstack)))
                    785:           then (d-move resloc 'reg)
                    786:                (setq resloc 'r0))
                    787: 
                    788:        ; now do car's and cdr's .  Values are placed in r0. We stop when
                    789:        ; we can get the result in one machine instruction.  At that point
                    790:        ; we see whether we want the value or just want to set the cc's.
                    791:        ; If the intermediate value is in a register, 
                    792:        ; we can do : car cdr cddr cdar
                    793:        ; If the intermediate value is on the local vrbl stack or lbind
                    794:        ; we can do : cdr
                    795:        (do ((curp togo newp)
                    796:            (newp))
                    797:           ((null curp) (if g-loc then (d-movespec loc g-loc)
                    798:                            elseif g-cc then (e-tst loc))
                    799:                        (d-handlecc))
                    800:           (if (symbolp resloc)
                    801:               then (if (eq 'd (car curp))
                    802:                        then (if (or (null (cdr curp))
                    803:                                     (eq 'a (cadr curp)))
                    804:                                 then (setq newp (cdr curp)   ; cdr
                    805:                                            loc `(0 ,resloc)
                    806:                                            sofar (append sofar (list 'd)))
                    807:                                 else (setq newp (cddr curp)  ; cddr
                    808:                                            loc `(* 0 ,resloc)
                    809:                                            sofar (append sofar
                    810:                                                          (list 'd 'd))))
                    811:                        else (if (or (null (cdr curp))
                    812:                                     (eq 'a (cadr curp)))
                    813:                                 then (setq newp (cdr curp)   ; car
                    814:                                            loc `(4 ,resloc)
                    815:                                            sofar (append sofar (list 'a)))
                    816:                                 else (setq newp (cddr curp)  ; cdar
                    817:                                            loc `(* 4 ,resloc)
                    818:                                            sofar (append sofar
                    819:                                                          (list 'a 'd)))))
                    820:               elseif (and (eq 'd (car curp))
                    821:                           (not (eq '* (car (setq loc (e-cvt resloc))))))
                    822:                 then (setq newp (cdr curp)     ; (cdr <local>)
                    823:                            loc (cons '* loc)
                    824:                            sofar (append sofar (list 'd)))
                    825:               else  (setq loc (e-cvt resloc)
                    826:                           newp curp))
                    827:           (if newp                     ; if this is not the last move
                    828:               then (setq resloc
                    829:                          (d-allocreg (if keeptrack then nil else 'r0)))
                    830:                    (d-movespec loc resloc)
                    831:                    (if keeptrack then (d-inreg resloc (cons arg sofar)))))))
                    832: 
                    833: #+for-68k
                    834: (defun cc-cxxr (arg pat)
                    835:    (prog (resloc loc qloc sofar togo keeptrack)
                    836:        (makecomment '(starting cc-cxxr))
                    837:        ; check for the special case of nil, since car's and cdr's
                    838:        ; are nil anyway
                    839:        (if (null arg)
                    840:           then (if g-loc then (d-move 'Nil g-loc))
                    841:                (if (cdr g-cc) then (e-goto (cdr g-cc)))
                    842:                (return))
                    843:        (if (and (symbolp arg) (setq qloc (d-bestreg arg pat)))
                    844:           then (setq resloc (car qloc)
                    845:                      loc   resloc
                    846:                      sofar  (cadr qloc)
                    847:                      togo   (caddr qloc))
                    848:           else (setq resloc
                    849:                      (if (d-simple arg) thenret
                    850:                          else (d-clearreg 'a0)
                    851:                               (let ((g-loc 'areg)
                    852:                                     (g-cc nil)
                    853:                                     (g-ret nil))
                    854:                                   (d-exp arg))
                    855:                               'a0))
                    856:                (setq sofar nil togo  pat))
                    857:        (if (and arg (symbolp arg)) then (setq keeptrack t))
                    858:        ;
                    859:        ; if resloc is a global variable, we must move it into a register
                    860:        ; right away to be able to do car's and cdr's
                    861:        (if (and (dtpr resloc) (or (eq (car resloc) 'bind)
                    862:                                  (eq (car resloc) 'vstack)))
                    863:           then (d-move resloc 'areg)
                    864:                (setq resloc 'a0))
                    865:        ; now do car's and cdr's .  Values are placed in a0. We stop when
                    866:        ; we can get the result in one machine instruction.  At that point
                    867:        ; we see whether we want the value or just want to set the cc's.
                    868:        ; If the intermediate value is in a register,
                    869:        ; we can do : car cdr cddr cdar
                    870:        ; If the intermediate value is on the local vrbl stack or lbind
                    871:        ; we can do : cdr
                    872:        (do ((curp togo newp)
                    873:            (newp))
                    874:           ((null curp)
                    875:            (if g-loc then (d-movespec loc g-loc))
                    876:            ;
                    877:            ;;;important: the below kludge is needed!!
                    878:            ;;;consider the compilation of the following:
                    879:            ;
                    880:            ;;; (cond ((setq c (cdr c)) ...))
                    881:            ;;; the following instructions are generated:
                    882:            ;;; movl  a4@(N),a5    ; the setq
                    883:            ;;; movl  a5@,a4@(N)
                    884:            ;;; movl  a4@,a5       ; the last two are generated if g-cc
                    885:            ;;; cmpl  a5@,d7       ; is non-nil
                    886:            ;
                    887:            ;;; observe that the original value the is supposed to set
                    888:            ;;; the cc's is clobered in the operation!!
                    889:            ;(msg "g-loc: " (e-cvt g-loc) N "loc: " loc N)
                    890:            (if g-cc
                    891:                then (if (and (eq '* (car loc))
                    892:                              (equal (caddr loc) (cadr (e-cvt g-loc))))
                    893:                         then (e-cmpnil '(0 a5))
                    894:                         else (e-cmpnil loc)))
                    895:            (d-handlecc))
                    896:           (if (symbolp resloc)
                    897:               then (if (eq 'd (car curp))
                    898:                        then (if (or (null (cdr curp))
                    899:                                     (eq 'a (cadr curp)))
                    900:                                 then (setq newp (cdr curp)   ; cdr
                    901:                                            loc `(0 ,resloc)
                    902:                                            sofar (append sofar (list 'd)))
                    903:                                 else (setq newp (cddr curp)  ; cddr
                    904:                                            loc `(* 0 ,resloc)
                    905:                                            sofar (append sofar
                    906:                                                          (list 'd 'd))))
                    907:                        else (if (or (null (cdr curp))
                    908:                                     (eq 'a (cadr curp)))
                    909:                                 then (setq newp (cdr curp)   ; car
                    910:                                            loc `(4 ,resloc)
                    911:                                            sofar (append sofar (list 'a)))
                    912:                                 else (setq newp (cddr curp)  ; cdar
                    913:                                            loc `(* 4 ,resloc)
                    914:                                            sofar (append sofar
                    915:                                                          (list 'a 'd)))))
                    916:            elseif (and (eq 'd (car curp))
                    917:                        (not (eq '* (car (setq loc (e-cvt resloc))))))
                    918:               then (setq newp (cdr curp)       ; (cdr <local>)
                    919:                          loc (cons '* loc)
                    920:                          sofar (append sofar (list 'd)))
                    921:               else  (setq loc (e-cvt resloc)
                    922:                           newp curp))
                    923:           (if newp                     ; if this is not the last move
                    924:               then (setq resloc
                    925:                          (d-alloc-register 'a
                    926:                                            (if keeptrack then nil else 'a1)))
                    927:                    (d-movespec loc resloc)
                    928:                    ;(if keeptrack then (d-inreg resloc (cons arg sofar)))
                    929:                    ))
                    930:        (makecomment '(done with cc-cxxr))))

unix.superglobalmegacorp.com

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