|
|
1.1 ! root 1: (include-if (null (get 'chead 'version)) "../chead.l") ! 2: (Liszt-file funa ! 3: "$Header: funa.l,v 1.12 87/12/15 17:02:01 sklower 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: #+(or for-vax for-tahoe) ! 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: #+(or for-vax for-tahoe) ! 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: #+(or for-vax for-tahoe) ! 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 #+for-vax `(fixnum-BitAndNot ,x (fixnum-BitXor ,y -1)) ! 238: #+for-tahoe `(fixnum-BitAnd ,x ,y) ! 239: elseif (eq key 2) ;; !x * y ! 240: then #+for-vax `(fixnum-BitAndNot (fixnum-BitXor ,x -1) ! 241: (fixnum-BitXor ,y -1)) ! 242: #+for-tahoe `(fixnum-BitAnd (fixnum-BitXor ,x -1) ,y) ! 243: elseif (eq key 3) ;; y ! 244: then `(progn ,x ,y) ! 245: elseif (eq key 4) ;; x * !y ! 246: then #+for-vax `(fixnum-BitAndNot ,x ,y) ! 247: #+for-tahoe `(fixnum-BitAnd ,x (fixnum-BitXor ,y -1)) ! 248: elseif (eq key 5) ;; x ! 249: then `(prog1 ,x ,y) ! 250: elseif (eq key 6) ;; x xor y ! 251: then `(fixnum-BitXor ,x ,y) ! 252: elseif (eq key 7) ;; x + y ! 253: then `(fixnum-BitOr ,x ,y) ! 254: elseif (eq key 8) ;; !(x xor y) ! 255: then `(fixnum-BitXor (fixnum-BitOr ,x ,y) -1) ! 256: elseif (eq key 9) ;; !(x xor y) ! 257: then `(fixnum-BitXor (fixnum-BitXor ,x ,y) -1) ! 258: elseif (eq key 10) ;; !x ! 259: then `(prog1 (fixnum-BitXor ,x -1) ,y) ! 260: elseif (eq key 11) ;; !x + y ! 261: then `(fixnum-BitOr (fixnum-BitXor ,x -1) ,y) ! 262: elseif (eq key 12) ;; !y ! 263: then `(progn ,x (fixnum-BitXor ,y -1)) ! 264: elseif (eq key 13) ;; x + !y ! 265: then `(fixnum-BitOr ,x (fixnum-BitXor ,y -1)) ! 266: elseif (eq key 14) ;; !x + !y ! 267: then `(fixnum-BitOr (fixnum-BitXor ,x -1) ! 268: (fixnum-BitXor ,y -1)) ! 269: elseif (eq key 15) ;; -1 ! 270: then `(progn ,x ,y -1) ! 271: else form)) ! 272: else form)) ! 273: ! 274: (declare (unspecial x y)) ! 275: ) ;; end for-vax ! 276: ! 277: ! 278: ;--- c-*catch :: compile a *catch expression ! 279: ; ! 280: ; the form of *catch is (*catch 'tag 'val) ! 281: ; we evaluate 'tag and set up a catch frame, and then eval 'val ! 282: ; ! 283: (defun c-*catch nil ! 284: (let ((g-loc 'reg) ! 285: (g-cc nil) ! 286: (g-ret nil) ! 287: (finlab (d-genlab)) ! 288: (beglab (d-genlab))) ! 289: (d-exp (cadr v-form)) ; calculate tag into 'reg ! 290: (d-pushframe #.F_CATCH 'reg 'Nil) ; the Nil is a don't care ! 291: (push nil g-labs) ; disallow labels ! 292: ; retval will be non 0 if we were thrown to, in which case the value ! 293: ; thrown is in _lispretval. ! 294: ; If we weren't thrown-to the value should be calculated in r0. ! 295: (e-tst '_retval) ! 296: (e-write2 #+(or for-vax for-tahoe) 'jeql #+for-68k 'jeq beglab) ! 297: (e-move '_lispretval (e-cvt 'reg)) ! 298: (e-write2 #+(or for-vax for-tahoe) 'jbr #+for-68k 'jra finlab) ! 299: (e-label beglab) ! 300: (d-exp (caddr v-form)) ! 301: (e-label finlab) ! 302: (d-popframe) ; remove catch frame from stack ! 303: (unpush g-locs) ; remove (catcherrset . 0) ! 304: (unpush g-labs) ; allow labels again ! 305: (d-clearreg))) ! 306: ! 307: ;--- d-pushframe :: put an evaluation frame on the stack ! 308: ; ! 309: ; This is equivalant in the C system to 'errp = Pushframe(class,arg1,arg2);' ! 310: ; We stack a frame which describes the class (will always be F_CATCH) ! 311: ; and the other option args. ! 312: ; 2/10/82 - it is a bad idea to stack a variable number of arguments, since ! 313: ; this makes it more complicated to unstack frames. Thus we will always ! 314: ; stack the maximum --jkf ! 315: (defun d-pushframe (class arg1 arg2) ! 316: (C-push (e-cvt arg2)) ! 317: (C-push (e-cvt arg1)) ! 318: (C-push `($ ,class)) ! 319: (if (null $global-reg$) ! 320: then (e-move '#.np-reg '#.np-sym) ! 321: (e-move '#.np-reg '#.lbot-sym)) ! 322: (e-quick-call '_qpushframe) ! 323: (e-move (e-cvt 'reg) '_errp) ! 324: (push '(catcherrset . 0) g-locs)) ! 325: ! 326: ;--- d-popframe :: remove an evaluation frame from the stack ! 327: ; ! 328: ; This is equivalent in the C system to 'errp = Popframe();' ! 329: ; n is the number of arguments given to the pushframe which ! 330: ; created this frame. We have to totally remove this frame from ! 331: ; the stack only if we are in a local function, but for now, we just ! 332: ; do it all the time. ! 333: ; ! 334: (defun d-popframe () ! 335: (let ((treg #+(or for-vax for-tahoe) 'r1 #+for-68k 'a5)) ! 336: (e-move '_errp treg) ! 337: (e-move `(#.OF_olderrp ,treg) '_errp) ! 338: ; there are always 3 arguments pushed, and the frame contains 5 ! 339: ; longwords. We should make these parameters into manifest ! 340: ; constants --jkf ! 341: (e-add3 `($ ,(+ (* 3 4) (* 5 4))) treg 'sp))) ! 342: ! 343: ;--- c-cond :: compile a "cond" expression ! 344: ; ! 345: ; not that this version of cond is a 'c' rather than a 'cc' . ! 346: ; this was done to make coding this routine easier and because ! 347: ; it is believed that it wont harm things much if at all ! 348: ; ! 349: (defun c-cond nil ! 350: (makecomment '(beginning cond)) ! 351: (do ((clau (cdr v-form) (cdr clau)) ! 352: (finlab (d-genlab)) ! 353: (nxtlab) ! 354: (save-reguse) ! 355: (seent)) ! 356: ((or (null clau) seent) ! 357: ; end of cond ! 358: ; if haven't seen a t must store a nil in `reg' ! 359: (if (null seent) then (d-move 'Nil 'reg)) ! 360: (e-label finlab)) ! 361: ! 362: ; case 1 - expr ! 363: (if (atom (car clau)) ! 364: then (comp-err "bad cond clause " (car clau)) ! 365: ; case 2 - (expr) ! 366: elseif (null (cdar clau)) ! 367: then (let ((g-loc (if (or g-cc g-loc) then 'reg)) ! 368: (g-cc (cons finlab nil)) ! 369: (g-ret (and g-ret (null (cdr clau))))) ! 370: (d-exp (caar clau))) ! 371: ; case 3 - (t expr1 expr2 ...) ! 372: elseif (or (eq t (caar clau)) ! 373: (equal ''t (caar clau))) ! 374: then (let ((g-loc (if (or g-cc g-loc) then 'reg)) ! 375: g-cc) ! 376: (d-exps (cdar clau))) ! 377: (setq seent t) ! 378: ; case 4 - (expr1 expr2 ...) ! 379: else (let ((g-loc nil) ! 380: (g-cc (cons nil (setq nxtlab (d-genlab)))) ! 381: (g-ret nil)) ! 382: (d-exp (caar clau))) ! 383: (setq save-reguse (copy g-reguse)) ! 384: (let ((g-loc (if (or g-cc g-loc) then 'reg)) ! 385: g-cc) ! 386: (d-exps (cdar clau))) ! 387: (if (or (cdr clau) (null seent)) then (e-goto finlab)) ! 388: (e-label nxtlab) ! 389: (setq g-reguse save-reguse))) ! 390: ! 391: (d-clearreg)) ! 392: ! 393: ;--- c-cons :: do a cons instruction quickly ! 394: ; ! 395: (defun c-cons nil ! 396: (d-pushargs (cdr v-form)) ; there better be 2 args ! 397: (e-quick-call '_qcons) ! 398: (setq g-locs (cddr g-locs)) ! 399: (setq g-loccnt (- g-loccnt 2)) ! 400: (d-clearreg)) ! 401: ! 402: ;--- c-cxr :: compile a cxr instruction ! 403: ; ! 404: ; ! 405: (defun cc-cxr nil ! 406: (d-supercxr t nil)) ! 407: ! 408: ;--- d-supercxr :: do a general struture reference ! 409: ; type - one of fixnum-block,flonum-block,<other-symbol> ! 410: ; the type is that of an array, so <other-symbol> could be t, nil ! 411: ; or anything else, since anything except *-block is treated the same ! 412: ; ! 413: ; the form of a cxr is (cxr index hunk) but supercxr will handle ! 414: ; arrays too, so hunk could be (getdata (getd 'arrayname)) ! 415: ; ! 416: ; offsetonly is t if we only care about the offset of this element from ! 417: ; the beginning of the data structure. If offsetonly is t then type ! 418: ; will be nil. ! 419: ; ! 420: ; Note: this takes care of g-loc and g-cc ! 421: ! 422: #+(or for-vax for-tahoe) ! 423: (defun d-supercxr (type offsetonly) ! 424: (let ((arg1 (cadr v-form)) ! 425: (arg2 (caddr v-form)) ! 426: lop rop semisimple) ! 427: ! 428: (if (fixp arg1) then (setq lop `(immed ,arg1)) ! 429: else (d-fixnumexp arg1) ; calculate index into r5 ! 430: (setq lop 'r5)) ; and remember that it is there ! 431: ! 432: ; before we calculate the second expression, we may have to save ! 433: ; the value just calculated into r5. To be safe we stack away ! 434: ; r5 if the expression is not simple or semisimple. ! 435: (if (not (setq rop (d-simple arg2))) ! 436: then (if (and (eq lop 'r5) ! 437: (not (setq semisimple (d-semisimple arg2)))) ! 438: then (C-push (e-cvt lop))) ! 439: (let ((g-loc 'reg) g-cc) ! 440: (d-exp arg2)) ! 441: (setq rop 'r0) ! 442: ! 443: (if (and (eq lop 'r5) (not semisimple)) ! 444: then (C-pop (e-cvt lop)))) ! 445: ! 446: (if (eq type 'flonum-block) ! 447: then (setq lop (d-structgen lop rop 8)) ! 448: (e-write3 'movq lop 'r4) ! 449: (e-quick-call '_qnewdoub) ; box number ! 450: (d-clearreg) ; clobbers all regs ! 451: (if (and g-loc (not (eq g-loc 'reg))) ! 452: then (d-move 'reg g-loc)) ! 453: (if (car g-cc) then (e-goto (car g-cc))) ! 454: else (setq lop (d-structgen lop rop 4) ! 455: rop (if g-loc then ! 456: (if (eq type 'fixnum-block) then 'r5 ! 457: else (e-cvt g-loc)))) ! 458: (if rop ! 459: then (if offsetonly ! 460: then (e-write3 'moval lop rop) ! 461: else (e-move lop rop)) ! 462: (if (eq type 'fixnum-block) ! 463: then (e-call-qnewint) ! 464: (d-clearreg) ! 465: (if (not (eq g-loc 'reg)) ! 466: then (d-move 'reg g-loc)) ! 467: ; result is always non nil. ! 468: (if (car g-cc) then (e-goto (car g-cc))) ! 469: else (d-handlecc)) ! 470: elseif g-cc ! 471: then (if (eq type 'fixnum-block) ! 472: then (if (car g-cc) ! 473: then (e-goto (car g-cc))) ! 474: else (e-tst lop) ! 475: (d-handlecc)))))) ! 476: ! 477: #+for-68k ! 478: (defun d-supercxr (type offsetonly) ! 479: (let ((arg1 (cadr v-form)) ! 480: (arg2 (caddr v-form)) ! 481: lop rop semisimple) ! 482: (makecomment `(Starting d-supercxr: vform: ,v-form)) ! 483: (if (fixp arg1) then (setq lop `(immed ,arg1)) ! 484: else (d-fixnumexp arg1) ; calculate index into fixnum-reg ! 485: (d-regused '#.fixnum-reg) ! 486: (setq lop '#.fixnum-reg)) ; and remember that it is there ! 487: ; ! 488: ; before we calculate the second expression, we may have to save ! 489: ; the value just calculated into fixnum-reg. To be safe we stack away ! 490: ; fixnum-reg if the expression is not simple or semisimple. ! 491: (if (not (setq rop (d-simple arg2))) ! 492: then (if (and (eq lop '#.fixnum-reg) ! 493: (not (setq semisimple (d-semisimple arg2)))) ! 494: then (C-push (e-cvt lop))) ! 495: (let ((g-loc 'areg) g-cc) ! 496: (d-exp arg2)) ! 497: (setq rop 'a0) ! 498: ; ! 499: (if (and (eq lop '#.fixnum-reg) (not semisimple)) ! 500: then (C-pop (e-cvt lop)))) ! 501: ; ! 502: (if (eq type 'flonum-block) ! 503: then (setq lop (d-structgen lop rop 8)) ! 504: (break " d-supercxr : flonum stuff not done.") ! 505: (e-write3 'movq lop 'r4) ! 506: (e-quick-call '_qnewdoub) ; box number ! 507: (d-clearreg) ; clobbers all regs ! 508: (if (and g-loc (not (eq g-loc 'areg))) ! 509: then (d-move 'areg g-loc)) ! 510: (if (car g-cc) then (e-goto (car g-cc))) ! 511: else (if (and (dtpr rop) (eq 'stack (car rop))) ! 512: then (e-move (e-cvt rop) 'a1) ! 513: (setq rop 'a1)) ! 514: (setq lop (d-structgen lop rop 4) ! 515: rop (if g-loc then ! 516: (if (eq type 'fixnum-block) ! 517: then '#.fixnum-reg ! 518: else (e-cvt g-loc)))) ! 519: (if rop ! 520: then (if offsetonly ! 521: then (e-write3 'lea lop 'a5) ! 522: (e-move 'a5 rop) ! 523: else (e-move lop rop)) ! 524: (if (eq type 'fixnum-block) ! 525: then (e-call-qnewint) ! 526: (d-clearreg) ! 527: (if (not (eq g-loc 'areg)) ! 528: then (d-move 'areg g-loc)) ! 529: ; result is always non nil. ! 530: (if (car g-cc) then (e-goto (car g-cc))) ! 531: else (e-cmpnil lop) ! 532: (d-handlecc)) ! 533: elseif g-cc ! 534: then (if (eq type 'fixnum-block) ! 535: then (if (car g-cc) ! 536: then (e-goto (car g-cc))) ! 537: else (if g-cc ! 538: then (e-cmpnil lop) ! 539: (d-handlecc))))) ! 540: (makecomment "Done with d-supercxr"))) ! 541: ! 542: ;--- d-semisimple :: check if result is simple enough not to clobber r5 ! 543: ; currently we look for the case of (getdata (getd 'foo)) ! 544: ; since we know that this will only be references to r0. ! 545: ; More knowledge can be added to this routine. ! 546: ; ! 547: (defun d-semisimple (form) ! 548: (or (d-simple form) ! 549: (and (dtpr form) ! 550: (eq 'getdata (car form)) ! 551: (dtpr (cadr form)) ! 552: (eq 'getd (caadr form)) ! 553: (dtpr (cadadr form)) ! 554: (eq 'quote (caadadr form))))) ! 555: ! 556: ;--- d-structgen :: generate appropriate address for indexed access ! 557: ; index - index address, must be (immed n) or r5 (which contains int) ! 558: ; base - address of base ! 559: ; width - width of data element ! 560: ; want to calculate appropriate address for base[index] ! 561: ; may require emitting instructions to set up registers ! 562: ; returns the address of the base[index] suitable for setting or reading ! 563: ; ! 564: ; the code sees the base as a stack value as a special case since it ! 565: ; can generate (perhaps) better code for that case. ! 566: ! 567: #+(or for-vax for-tahoe) ! 568: (defun d-structgen (index base width) ! 569: (if (and (dtpr base) (eq (car base) 'stack)) ! 570: then (if (dtpr index) ; i.e if index = (immed n) ! 571: then (d-move index 'r5)) ; get immed in register ! 572: ; the result is always *n(r6)[r5] ! 573: (append (e-cvt `(vstack ,(cadr base))) '(r5)) ! 574: else (if (not (atom base)) ; i.e if base is not register ! 575: then (d-move base 'r0) ; (if nil gets here we will fail) ! 576: (d-clearreg 'r0) ! 577: (setq base 'r0)) ! 578: (if (dtpr index) then `(,(* width (cadr index)) ;immed index ! 579: ,base) ! 580: else `(0 ,base r5)))) ! 581: ! 582: #+for-68k ! 583: (defun d-structgen (index base width) ! 584: (if (and (dtpr base) (eq (car base) 'stack)) ! 585: then (break "d-structgen: bad args(1)") ! 586: else (if (not (atom base)) ; i.e if base is not register ! 587: then (d-move base 'a0) ; (if nil gets here we will fail) ! 588: (d-clearreg 'a0) ! 589: (setq base 'a0)) ! 590: (if (dtpr index) ! 591: then `(,(* width (cadr index)) ,base) ! 592: else (d-regused 'd6) ! 593: (e-move index 'd6) ! 594: (e-write3 'asll '($ 2) 'd6) ! 595: `(% 0 ,base d6)))) ! 596: ! 597: ;--- c-rplacx :: complile a rplacx expression ! 598: ; ! 599: ; This simple calls the general structure hacking function, d-superrplacx ! 600: ; The argument, hunk, means that the elements stored in the hunk are not ! 601: ; fixum-block or flonum-block arrays. ! 602: (defun c-rplacx nil ! 603: (d-superrplacx 'hunk)) ! 604: ! 605: ;--- d-superrplacx :: handle general setting of things in structures ! 606: ; type - one of fixnum-block, flonum-block, hunk ! 607: ; see d-supercxr for comments ! 608: ; form of rplacx is (rplacx index hunk valuetostore) ! 609: #+(or for-vax for-tahoe) ! 610: (defun d-superrplacx (type) ! 611: (let ((arg1 (cadr v-form)) ! 612: (arg2 (caddr v-form)) ! 613: (arg3 (cadddr v-form)) ! 614: lop rop semisimple) ! 615: ! 616: ; calulate index and put it in r5 if it is not an immediate ! 617: ; set lop to the location of the index ! 618: (if (fixp arg1) then (setq lop `(immed ,arg1)) ! 619: else (d-fixnumexp arg1) ! 620: (setq lop 'r5)) ! 621: ! 622: ; set rop to the location of the hunk. If we have to ! 623: ; calculate the hunk, we may have to save r5. ! 624: ; If we are doing a rplacx (type equals hunk) then we must ! 625: ; return the hunk in r0. ! 626: (if (or (eq type 'hunk) (not (setq rop (d-simple arg2)))) ! 627: then (if (and (eq lop 'r5) ! 628: (not (setq semisimple (d-semisimple arg2)))) ! 629: then (d-move lop '#.Cstack)) ! 630: (let ((g-loc 'r0) g-cc) ! 631: (d-exp arg2)) ! 632: (setq rop 'r0) ! 633: ! 634: (if (and (eq lop 'r5) (not semisimple)) ! 635: then (d-move '#.unCstack lop))) ! 636: ! 637: ; now that the index and data block locations are known, we ! 638: ; caclulate the location of the index'th element of hunk ! 639: (setq rop ! 640: (d-structgen lop rop ! 641: (if (eq type 'flonum-block) then 8 else 4))) ! 642: ! 643: ; the code to calculate the value to store and the actual ! 644: ; storing depends on the type of data block we are storing in. ! 645: (if (eq type 'flonum-block) ! 646: then (if (setq lop (d-simple `(cdr ,arg3))) ! 647: then (e-write3 'movq (e-cvt lop) rop) ! 648: else ; preserve rop since it may be destroyed ! 649: ; when arg3 is calculated ! 650: (e-write3 'movaq rop '#.Cstack) ! 651: (let ((g-loc 'r0) g-cc) ! 652: (d-exp arg3)) ! 653: (d-clearreg 'r0) ! 654: (e-write3 'movq '(0 r0) "*(sp)+")) ! 655: elseif (and (eq type 'fixnum-block) ! 656: (setq arg3 `(cdr ,arg3)) ! 657: nil) ! 658: ; fixnum-block is like hunk except we must grab the ! 659: ; fixnum value out of its box, hence the (cdr arg3) ! 660: thenret ! 661: else (if (setq lop (d-simple arg3)) ! 662: then (e-move (e-cvt lop) rop) ! 663: else ; if we are dealing with hunks, we must save ! 664: ; r0 since that contains the value we want to ! 665: ; return. ! 666: (if (eq type 'hunk) then (d-move 'reg 'stack) ! 667: (Push g-locs nil) ! 668: (incr g-loccnt)) ! 669: (e-write3 'moval rop '#.Cstack) ! 670: (let ((g-loc "*(sp)+") g-cc) ! 671: (d-exp arg3)) ! 672: (if (eq type 'hunk) then (d-move 'unstack 'reg) ! 673: (unpush g-locs) ! 674: (decr g-loccnt)) ! 675: (d-clearreg 'r0))))) ! 676: ! 677: #+for-68k ! 678: (defun d-superrplacx (type) ! 679: (let ((arg1 (cadr v-form)) ! 680: (arg2 (caddr v-form)) ! 681: (arg3 (cadddr v-form)) ! 682: lop rop semisimple) ! 683: (makecomment `(starting d-superrplacx ,type :: v-form = ,v-form)) ! 684: ; ! 685: ; calulate index and put it in '#.fixnum-reg if it is not an immediate ! 686: ; set lop to the location of the index ! 687: (if (fixp arg1) then (setq lop `(immed ,arg1)) ! 688: else (d-fixnumexp arg1) ! 689: (d-regused '#.fixnum-reg) ! 690: (setq lop '#.fixnum-reg)) ! 691: ; ! 692: ; set rop to the location of the hunk. If we have to ! 693: ; calculate the hunk, we may have to save '#.fixnum-reg. ! 694: ; If we are doing a rplacx (type equals hunk) then we must ! 695: ; return the hunk in d0. ! 696: (if (or (eq type 'hunk) (not (setq rop (d-simple arg2)))) ! 697: then (if (and (eq lop '#.fixnum-reg) ! 698: (not (setq semisimple (d-semisimple arg2)))) ! 699: then (d-move lop '#.Cstack)) ! 700: (let ((g-loc 'a0) g-cc) ! 701: (d-exp arg2)) ! 702: (setq rop 'a0) ! 703: (if (and (eq lop '#.fixnum-reg) (not semisimple)) ! 704: then (d-move '#.unCstack lop))) ! 705: ; ! 706: ; now that the index and data block locations are known, we ! 707: ; caclulate the location of the index'th element of hunk ! 708: (setq rop ! 709: (d-structgen lop rop ! 710: (if (eq type 'flonum-block) then 8 else 4))) ! 711: ; ! 712: ; the code to calculate the value to store and the actual ! 713: ; storing depends on the type of data block we are storing in. ! 714: (if (eq type 'flonum-block) ! 715: then (break "flonum stuff not in yet") ! 716: (if (setq lop (d-simple `(cdr ,arg3))) ! 717: then (e-write3 'movq (e-cvt lop) rop) ! 718: else ; preserve rop since it may be destroyed ! 719: ; when arg3 is calculated ! 720: (e-write3 'movaq rop '#.Cstack) ! 721: (let ((g-loc 'd0) g-cc) ! 722: (d-exp arg3)) ! 723: (d-clearreg 'd0) ! 724: (e-write3 'movq '(0 d0) "*(sp)+")) ! 725: elseif (and (eq type 'fixnum-block) ! 726: (setq arg3 `(cdr ,arg3)) ! 727: nil) ! 728: ; fixnum-block is like hunk except we must grab the ! 729: ; fixnum value out of its box, hence the (cdr arg3) ! 730: thenret ! 731: else (if (setq lop (d-simple arg3)) ! 732: then (e-move (e-cvt lop) rop) ! 733: else ; if we are dealing with hunks, we must save ! 734: ; d0 since that contains the value we want to ! 735: ; return. ! 736: (if (eq type 'hunk) ! 737: then (L-push 'a0) ! 738: (push nil g-locs) ! 739: (incr g-loccnt)) ! 740: (e-write3 'lea rop 'a5) ! 741: (C-push 'a5) ! 742: (let ((g-loc '(racc * 0 sp)) g-cc) ! 743: (d-exp arg3)) ! 744: (if (eq type 'hunk) ! 745: then (L-pop 'd0) ! 746: (unpush g-locs) ! 747: (decr g-loccnt)))) ! 748: (makecomment '(d-superrplacx done)))) ! 749: ! 750: ;--- cc-cxxr :: compile a "c*r" instr where * ! 751: ; is any sequence of a's and d's ! 752: ; - arg : argument of the cxxr function ! 753: ; - pat : a list of a's and d's in the reverse order of that ! 754: ; which appeared between the c and r ! 755: ; ! 756: #+(or for-vax for-tahoe) ! 757: (defun cc-cxxr (arg pat) ! 758: (prog (resloc loc qloc sofar togo keeptrack) ! 759: ; check for the special case of nil, since car's and cdr's ! 760: ; are nil anyway ! 761: (if (null arg) ! 762: then (if g-loc then (d-move 'Nil g-loc) ! 763: (d-handlecc) ! 764: elseif (cdr g-cc) then (e-goto (cdr g-cc))) ! 765: (return)) ! 766: ! 767: (if (and (symbolp arg) (setq qloc (d-bestreg arg pat))) ! 768: then (setq resloc (car qloc) ! 769: loc resloc ! 770: sofar (cadr qloc) ! 771: togo (caddr qloc)) ! 772: else (setq resloc ! 773: (if (d-simple arg) ! 774: thenret ! 775: else (let ((g-loc 'reg) ! 776: (g-cc nil) ! 777: (g-ret nil)) ! 778: (d-exp arg)) ! 779: 'r0)) ! 780: (setq sofar nil togo pat)) ! 781: ! 782: (if (and arg (symbolp arg)) then (setq keeptrack t)) ! 783: ! 784: ; if resloc is a global variable, we must move it into a register ! 785: ; right away to be able to do car's and cdr's ! 786: (if (and (dtpr resloc) (or (eq (car resloc) 'bind) ! 787: (eq (car resloc) 'vstack))) ! 788: then (d-move resloc 'reg) ! 789: (setq resloc 'r0)) ! 790: ! 791: ; now do car's and cdr's . Values are placed in r0. We stop when ! 792: ; we can get the result in one machine instruction. At that point ! 793: ; we see whether we want the value or just want to set the cc's. ! 794: ; If the intermediate value is in a register, ! 795: ; we can do : car cdr cddr cdar ! 796: ; If the intermediate value is on the local vrbl stack or lbind ! 797: ; we can do : cdr ! 798: (do ((curp togo newp) ! 799: (newp)) ! 800: ((null curp) (if g-loc then (d-movespec loc g-loc) ! 801: elseif g-cc then (e-tst loc)) ! 802: (d-handlecc)) ! 803: (if (symbolp resloc) ! 804: then (if (eq 'd (car curp)) ! 805: then (if (or (null (cdr curp)) ! 806: (eq 'a (cadr curp))) ! 807: then (setq newp (cdr curp) ; cdr ! 808: loc `(0 ,resloc) ! 809: sofar (append sofar (list 'd))) ! 810: else (setq newp (cddr curp) ; cddr ! 811: loc `(* 0 ,resloc) ! 812: sofar (append sofar ! 813: (list 'd 'd)))) ! 814: else (if (or (null (cdr curp)) ! 815: (eq 'a (cadr curp))) ! 816: then (setq newp (cdr curp) ; car ! 817: loc `(4 ,resloc) ! 818: sofar (append sofar (list 'a))) ! 819: else (setq newp (cddr curp) ; cdar ! 820: loc `(* 4 ,resloc) ! 821: sofar (append sofar ! 822: (list 'a 'd))))) ! 823: elseif (and (eq 'd (car curp)) ! 824: (not (eq '* (car (setq loc (e-cvt resloc)))))) ! 825: then (setq newp (cdr curp) ; (cdr <local>) ! 826: loc (cons '* loc) ! 827: sofar (append sofar (list 'd))) ! 828: else (setq loc (e-cvt resloc) ! 829: newp curp)) ! 830: (if newp ; if this is not the last move ! 831: then (setq resloc ! 832: (d-allocreg (if keeptrack then nil else 'r0))) ! 833: (d-movespec loc resloc) ! 834: (if keeptrack then (d-inreg resloc (cons arg sofar))))))) ! 835: ! 836: #+for-68k ! 837: (defun cc-cxxr (arg pat) ! 838: (prog (resloc loc qloc sofar togo keeptrack) ! 839: (makecomment '(starting cc-cxxr)) ! 840: ; check for the special case of nil, since car's and cdr's ! 841: ; are nil anyway ! 842: (if (null arg) ! 843: then (if g-loc then (d-move 'Nil g-loc)) ! 844: (if (cdr g-cc) then (e-goto (cdr g-cc))) ! 845: (return)) ! 846: (if (and (symbolp arg) (setq qloc (d-bestreg arg pat))) ! 847: then (setq resloc (car qloc) ! 848: loc resloc ! 849: sofar (cadr qloc) ! 850: togo (caddr qloc)) ! 851: else (setq resloc ! 852: (if (d-simple arg) thenret ! 853: else (d-clearreg 'a0) ! 854: (let ((g-loc 'areg) ! 855: (g-cc nil) ! 856: (g-ret nil)) ! 857: (d-exp arg)) ! 858: 'a0)) ! 859: (setq sofar nil togo pat)) ! 860: (if (and arg (symbolp arg)) then (setq keeptrack t)) ! 861: ; ! 862: ; if resloc is a global variable, we must move it into a register ! 863: ; right away to be able to do car's and cdr's ! 864: (if (and (dtpr resloc) (or (eq (car resloc) 'bind) ! 865: (eq (car resloc) 'vstack))) ! 866: then (d-move resloc 'areg) ! 867: (setq resloc 'a0)) ! 868: ; now do car's and cdr's . Values are placed in a0. We stop when ! 869: ; we can get the result in one machine instruction. At that point ! 870: ; we see whether we want the value or just want to set the cc's. ! 871: ; If the intermediate value is in a register, ! 872: ; we can do : car cdr cddr cdar ! 873: ; If the intermediate value is on the local vrbl stack or lbind ! 874: ; we can do : cdr ! 875: (do ((curp togo newp) ! 876: (newp)) ! 877: ((null curp) ! 878: (if g-loc then (d-movespec loc g-loc)) ! 879: ; ! 880: ;;;important: the below kludge is needed!! ! 881: ;;;consider the compilation of the following: ! 882: ; ! 883: ;;; (cond ((setq c (cdr c)) ...)) ! 884: ;;; the following instructions are generated: ! 885: ;;; movl a4@(N),a5 ; the setq ! 886: ;;; movl a5@,a4@(N) ! 887: ;;; movl a4@,a5 ; the last two are generated if g-cc ! 888: ;;; cmpl a5@,d7 ; is non-nil ! 889: ; ! 890: ;;; observe that the original value the is supposed to set ! 891: ;;; the cc's is clobered in the operation!! ! 892: ;(msg "g-loc: " (e-cvt g-loc) N "loc: " loc N) ! 893: (if g-cc ! 894: then (if (and (eq '* (car loc)) ! 895: (equal (caddr loc) (cadr (e-cvt g-loc)))) ! 896: then (e-cmpnil '(0 a5)) ! 897: else (e-cmpnil loc))) ! 898: (d-handlecc)) ! 899: (if (symbolp resloc) ! 900: then (if (eq 'd (car curp)) ! 901: then (if (or (null (cdr curp)) ! 902: (eq 'a (cadr curp))) ! 903: then (setq newp (cdr curp) ; cdr ! 904: loc `(0 ,resloc) ! 905: sofar (append sofar (list 'd))) ! 906: else (setq newp (cddr curp) ; cddr ! 907: loc `(* 0 ,resloc) ! 908: sofar (append sofar ! 909: (list 'd 'd)))) ! 910: else (if (or (null (cdr curp)) ! 911: (eq 'a (cadr curp))) ! 912: then (setq newp (cdr curp) ; car ! 913: loc `(4 ,resloc) ! 914: sofar (append sofar (list 'a))) ! 915: else (setq newp (cddr curp) ; cdar ! 916: loc `(* 4 ,resloc) ! 917: sofar (append sofar ! 918: (list 'a 'd))))) ! 919: elseif (and (eq 'd (car curp)) ! 920: (not (eq '* (car (setq loc (e-cvt resloc)))))) ! 921: then (setq newp (cdr curp) ; (cdr <local>) ! 922: loc (cons '* loc) ! 923: sofar (append sofar (list 'd))) ! 924: else (setq loc (e-cvt resloc) ! 925: newp curp)) ! 926: (if newp ; if this is not the last move ! 927: then (setq resloc ! 928: (d-alloc-register 'a ! 929: (if keeptrack then nil else 'a1))) ! 930: (d-movespec loc resloc) ! 931: ;(if keeptrack then (d-inreg resloc (cons arg sofar))) ! 932: )) ! 933: (makecomment '(done with cc-cxxr))))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.