|
|
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.