|
|
1.1 root 1: (include "caspecs.l")
2: (eval-when (compile)
3: (fasl 'camacs))
4:
5: (setq sectioncddrid "@(#)cddr.l 5.4 11/11/80") ; id for SCCS
6:
7: ; cc-not :: compile a "not" or "null" expression = cc-not =
8: ;
9: (defun cc-not nil
10: (makecomment '(beginning not))
11: (If (null g-loc)
12: then (let ((g-cc (cons (cdr g-cc) (car g-cc)))
13: (g-ret nil))
14: (d-exp (cadr v-form)))
15: else (let ((finlab (d-genlab))
16: (finlab2 (d-genlab))
17: (g-ret nil))
18: ; eval arg and jump to finlab if nil
19: (let ((g-cc (cons finlab nil))
20: g-loc)
21: (d-exp (cadr v-form)))
22: ; didn't jump, answer must be t
23: (d-move 'T g-loc)
24: (If (car g-cc) then (e-goto (car g-cc))
25: else (e-goto finlab2))
26: (e-label finlab)
27: ; answer is nil
28: (d-move 'Nil g-loc)
29: (If (cdr g-cc) then (e-goto (cdr g-cc)))
30: (e-label finlab2))))
31:
32:
33: ;--- cc-numberp :: check for numberness = cc-numberp =
34: ;
35: (defun cc-numberp nil
36: (d-typecmplx (cadr v-form)
37: '#.(concat '$ (plus 1_2 1_4 1_9))))
38:
39:
40: ;--- cc-or :: compile an "or" expression = cc-or =
41: ;
42: (defun cc-or nil
43: (let ((finlab (d-genlab))
44: (finlab2)
45: (exps (If (cdr v-form) thenret else '(nil)))) ; (or) => nil
46: (If (null (car g-cc))
47: then (d-exp (do ((g-cc (cons finlab nil))
48: (g-loc (If g-loc then 'reg))
49: (g-ret nil)
50: (ll exps (cdr ll)))
51: ((null (cdr ll)) (car ll))
52: (d-exp (car ll))))
53: (If g-loc then (setq finlab2 (d-genlab))
54: (e-goto finlab2)
55: (e-label finlab)
56: (d-move 'reg g-loc)
57: (e-label finlab2)
58: else (e-label finlab))
59: else (If (null g-loc) then (setq finlab (car g-cc)))
60: (d-exp (do ((g-cc (cons finlab nil))
61: (g-loc (If g-loc then 'reg))
62: (g-ret nil)
63: (ll exps (cdr ll)))
64: ((null (cdr ll)) (car ll))
65: (d-exp (car ll))))
66: (If g-loc then (setq finlab2 (d-genlab))
67: (e-goto finlab2)
68: (e-label finlab)
69: (d-move 'reg g-loc)
70: (e-goto (car g-cc)) ; result is t
71: (e-label finlab2)))
72: (d-clearreg))) ; we are not sure of the state due to possible branches.
73:
74:
75: ;--- c-prog :: compile a "prog" expression = c-prog =
76: ;
77: ; for interlisp compatibility, we allow the formal variable list to
78: ; contain objects of this form (vrbl init) which gives the initial value
79: ; for that variable (instead of nil)
80: ;
81: (defun c-prog nil
82: (let (g-loc g-cc seeninit initf ((spcs locs initsv . initsn)
83: (d-classify (cadr v-form)))
84: (p-rettrue g-ret) (g-ret nil))
85:
86: (e-pushnil (length locs)) ; locals initially nil
87: (d-bindprg spcs locs) ; bind locs and specs
88:
89: (cond (initsv (d-pushargs initsv)
90: (mapc '(lambda (x)
91: (d-move 'unstack (d-loc x))
92: (decr g-loccnt)
93: (unpush g-locs))
94: (nreverse initsn))))
95:
96: ; determine all possible labels
97: (do ((ll (cddr v-form) (cdr ll))
98: (labs nil))
99: ((null ll) (setq g-labs `((,(d-genlab) ,@labs)
100: ,@g-labs)))
101: (If (and (car ll) (symbolp (car ll)))
102: then (If (assq (car ll) labs)
103: then (comp-err "label is mulitiply defined " (car ll))
104: else (setq labs (cons (cons (car ll) (d-genlab))
105: labs)))))
106:
107: ; compile each form which is not a label
108: (d-clearreg) ; unknown state after binding
109: (do ((ll (cddr v-form) (cdr ll)))
110: ((null ll))
111: (If (or (null (car ll)) (not (symbolp (car ll))))
112: then (d-exp (car ll))
113: else (e-label (cdr (assq (car ll) (cdar g-labs))))
114: (d-clearreg)))) ; dont know state after label
115:
116: ; result is nil if fall out and care about value
117: (If (or g-cc g-loc) then (d-move 'Nil 'reg))
118:
119: (e-label (caar g-labs)) ; return to label
120: (setq g-labs (cdr g-labs))
121: (d-unbind)) ; unbind our frame
122:
123:
124: ;--- d-bindprg :: do binding for a prog expression
125: ; - spcs : list of special variables
126: ; - locs : list of local variables
127: ; - specinit : init values for specs (or nil if all are nil)
128: ;
129: (defun d-bindprg (spcs locs)
130:
131:
132: ; place the local vrbls and prog frame entry on the stack
133: (setq g-loccnt (+ g-loccnt (length locs))
134: g-locs (nconc locs `((prog . ,(length spcs)) ,@g-locs)))
135:
136: ; now bind the specials, if any, to nil
137: (If spcs then (e-setupbind)
138: (mapc '(lambda (vrb)
139: (e-shallowbind vrb 'Nil))
140: spcs)
141: (e-unsetupbind)))
142:
143: ;--- d-unbind :: remove one frame from g-locs
144: ;
145: (defun d-unbind nil
146: (do ((count 0 (1+ count)))
147: ((dtpr (car g-locs))
148: (If (not (zerop (cdar g-locs)))
149: then (e-unshallowbind (cdar g-locs)))
150: (cond ((not (zerop count))
151: (e-dropnp count)
152:
153: (setq g-loccnt (- g-loccnt count))))
154: (setq g-locs (cdr g-locs)))
155: (setq g-locs (cdr g-locs))))
156:
157:
158: ;--- d-classify :: seperate variable list into special and non-special
159: ; - lst : list of variables
160: ; returns ( xxx yyy zzz . aaa)
161: ; where xxx is the list of special variables and
162: ; yyy is the list of local variables
163: ; zzz are the non nil initial values for prog variables
164: ; aaa are the names corresponding to the values in zzz
165: ;
166: (defun d-classify (lst)
167: (do ((ll lst (cdr ll))
168: (locs) (spcs) (init) (initsv) (initsn)
169: (name))
170: ((null ll) (cons spcs (cons locs (cons initsv initsn))))
171: (If (atom (car ll)) then (setq name (car ll))
172: else (setq name (caar ll))
173: (Push initsn name)
174: (Push initsv (cadar ll)))
175: (If (d-specialp name)
176: then (Push spcs name)
177: else (Push locs name))))
178:
179: ; cm-progn :: compile a "progn" expression = cm-progn =
180: ;
181: (defun cm-progn nil
182: `((lambda nil ,@(cdr v-form))))
183:
184:
185: ; cm-prog1 :: compile a "prog1" expression = cm-prog1 =
186: ;
187: (defun cm-prog1 nil
188: (let ((gl (d-genlab)))
189: `((lambda (,gl)
190: ,@(cddr v-form)
191: ,gl)
192: ,(cadr v-form))))
193:
194:
195: ; cm-prog2 :: compile a "prog2" expression = cm-prog2 =
196: ;
197: (defun cm-prog2 nil
198: (let ((gl (d-genlab)))
199: `((lambda (,gl) ,(cadr v-form)
200: (setq ,gl ,(caddr v-form))
201: ,@(cdddr v-form)
202: ,gl)
203: nil)))
204:
205:
206: ;--- cc-quote : compile a "quote" expression = cc-quote =
207: ;
208: ; if we are just looking to set the ; cc, we just make sure
209: ; we set the cc depending on whether the expression quoted is
210: ; nil or not.
211: (defun cc-quote nil
212: (let ((arg (cadr v-form))
213: argloc)
214:
215: (If (null g-loc)
216: then (If (and (null arg) (cdr g-cc)
217: then (e-goto (cdr g-cc))
218: elseif (and arg (car g-cc))
219: then (e-goto (car g-cc)))
220: elseif (null g-cc)
221: then (comp-warn "losing the value of this expression " (or v-form)))
222: else (d-move (d-loclit arg nil) g-loc)
223: (d-handlecc))))
224:
225:
226: ;--- d-loc :: return the location of the variable or value in IADR form
227: ; - form : form whose value we are to locate
228: ;
229: ; if we are given a xxx as form, we check yyy;
230: ; xxx yyy
231: ; -------- ---------
232: ; nil Nil is always returned
233: ; symbol return the location of the symbols value, first looking
234: ; in the registers, then on the stack, then the bind list.
235: ; If g-ingorereg is t then we don't check the registers.
236: ; We would want to do this if we were interested in storing
237: ; something in the symbol's value location.
238: ; number always return the location of the number on the bind
239: ; list (as a (lbind n))
240: ; other always return the location of the other on the bind
241: ; list (as a (lbind n))
242: ;
243: (defun d-loc (form)
244: (If (null form) then 'Nil
245: elseif (numberp form) then
246: (If (and (fixp form) (greaterp form -1025) (lessp form 1024))
247: then `(fixnum ,form) ; small fixnum
248: else (d-loclit form nil))
249: elseif (symbolp form)
250: then (If (and (null g-ignorereg) (car (d-bestreg form nil))) thenret
251: else (If (d-specialp form) then (d-loclit form t)
252: else
253: (do ((ll g-locs (cdr ll)) ; check stack
254: (n g-loccnt))
255: ((null ll)
256: (comp-warn (or form) " declared special by compiler")
257: (d-makespec form)
258: (d-loclit form t))
259: (If (atom (car ll))
260: then (If (eq form (car ll))
261: then (return `(stack ,n))
262: else (setq n (1- n)))))))
263: else (d-loclit form nil)))
264:
265:
266: ;--- d-loclit :: locate or add litteral to bind list
267: ; - form : form to check for and add if not present
268: ; - flag : if t then if we are given a symbol, return the location of
269: ; its value, else return the location of the symbol itself
270: ;
271: ; scheme: we share the locations of atom (symbols,numbers,string) but always
272: ; create a fresh copy of anything else.
273: (defun d-loclit (form flag)
274: (prog (loc onplist symboltype)
275: (If (null form)
276: then (return 'Nil)
277: elseif (symbolp form)
278: then (setq symboltype t)
279: (cond ((setq loc (get form g-bindloc))
280: (setq onplist t)))
281: elseif (atom form)
282: then (do ((ll g-lits (cdr ll)) ; search for atom on list
283: (n g-litcnt (1- n)))
284: ((null ll))
285: (If (eq form (car ll))
286: then (setq loc n) ; found it
287: (return)))) ; leave do
288: (If (null loc)
289: then (Push g-lits form)
290: (setq g-litcnt (1+ g-litcnt)
291: loc g-litcnt)
292: (cond ((and symboltype (null onplist))
293: (putprop form loc g-bindloc))))
294:
295: (return (If (and flag symboltype) then `(bind ,loc)
296: else `(lbind ,loc)))))
297:
298:
299:
300: ;--- d-locv :: find the location of a value cell, and dont return a register
301: ;
302: (defun d-locv (sm)
303: (let ((g-ignorereg t))
304: (d-loc sm)))
305:
306:
307: ;--- c-setarg :: set a lexpr's arg = cc-setarg =
308: ; form is (setarg index value)
309: ;
310: (defun c-setarg nil
311: (If (not (eq 'lexpr g-ftype))
312: then (comp-err "setarg only allowed in lexprs"))
313: (If (and fl-inter (eq (length (cdr v-form)) 3)) ; interlisp setarg
314: then (If (not (eq (cadr v-form) (car g-args)))
315: then (comp-err "setarg: can only compile local setargs " v-form)
316: else (setq v-form (cdr v-form))))
317: (d-pushargs (list (cadr v-form))) ; stack index
318: (let ((g-loc 'reg)
319: (g-cc nil)
320: (g-ret nil))
321: (d-exp (caddr v-form)))
322: (d-clearreg 'r1) ; indicate we are clobbering r1
323: (e-write3 'movl `(* -4 #.Np-reg) 'r1) ; actual number to r1
324: (e-write3 'movl 'r0 "*-4(fp)[r1]") ; store value in
325: (e-pop 1)
326: (unpush g-locs)
327: (decr g-loccnt))
328:
329: ;--- cc-stringp :: check for string ness = cc-stringp =
330: ;
331: (defun cc-stringp nil
332: (d-typesimp (cadr v-form) '$0))
333:
334:
335: ;--- cc-symbolp :: check for symbolness = cc-symbolp =
336: ;
337: (defun cc-symbolp nil
338: (d-typesimp (cadr v-form) '$1))
339:
340:
341:
342: ;--- c-return :: compile a "return" statement = c-return =
343: ;
344: (defun c-return nil
345: ; value is always put in r0
346: (let ((g-loc 'reg)
347: g-cc
348: g-ret)
349: (d-exp (cadr v-form)))
350:
351: ; if we are doing a non local return, compute number of specials to unbind
352: ; and locals to pop
353: (If (car g-labs) then (e-goto (caar g-labs))
354: else (do ((loccnt 0)
355: (speccnt 0)
356: (ll g-labs (cdr ll))
357: (locs g-locs))
358: ((null ll) (comp-err "return used not within a prog or do"))
359: (If (car ll) then (comp-warn " non local return used ")
360: ; unbind down to but not including
361: ; this frame.
362: (If (greaterp loccnt 0)
363: then (e-pop loccnt))
364: (If (greaterp speccnt 0)
365: then (e-unshallowbind speccnt))
366: (e-goto (caar ll))
367: (return)
368: else ; determine number of locals and special on
369: ; stack for this frame, add to running
370: ; totals
371: (do ()
372: ((dtpr (car locs))
373: (setq speccnt (+ speccnt (cdar locs))
374: locs (cdr locs)))
375: (incr loccnt)
376: (setq locs (cdr locs)))))))
377:
378:
379: ; c-rplaca :: compile a "rplaca" expression = c-rplaca =
380: ;
381: (defun c-rplaca nil
382: (let ((ssimp (d-simple (caddr v-form)))
383: (g-ret nil))
384: (let ((g-loc (If ssimp then 'reg else 'stack))
385: (g-cc nil))
386: (d-exp (cadr v-form)))
387: (If (null ssimp) then (Push g-locs nil)
388: (incr g-loccnt)
389: (let ((g-loc 'r1)
390: (g-cc nil))
391: (d-exp (caddr v-form)))
392: (d-move 'unstack 'reg)
393: (unpush g-locs)
394: (decr g-loccnt)
395: (e-move 'r1 '(4 r0))
396: else (e-move (e-cvt ssimp) '(4 r0)))
397: (d-clearreg))) ; cant tell what we are clobbering
398:
399:
400: ; c-rplacd :: compile a "rplacd" expression = c-rplacd =
401: ;
402: (defun c-rplacd nil
403: (let ((ssimp (d-simple (caddr v-form)))
404: (g-ret nil))
405: (let ((g-loc (If ssimp then 'reg else 'stack))
406: (g-cc nil))
407: (d-exp (cadr v-form)))
408: (If (null ssimp) then (Push g-locs nil)
409: (incr g-loccnt)
410: (let ((g-loc 'r1)
411: (g-cc nil))
412: (d-exp (caddr v-form)))
413: (d-move 'unstack 'reg)
414: (unpush g-locs)
415: (decr g-loccnt)
416: (e-move 'r1 '(0 r0))
417: else (e-move (e-cvt ssimp) '(0 r0)))
418: (d-clearreg)))
419:
420: ; c-set :: compile a "set" expression = c-set =
421:
422:
423: ;--- cc-setq :: compile a "setq" expression = c-setq =
424: ;
425: (defun cc-setq nil
426: (let (tmp)
427: (If (oddp (length (cdr v-form)))
428: then (comp-err "wrong number of args to setq "
429: (or v-form))
430: elseif (cdddr v-form) ; if multiple setq's
431: then (do ((ll (cdr v-form) (cddr ll))
432: (g-loc)
433: (g-cc nil))
434: ((null (cddr ll)) (setq tmp ll))
435: (setq g-loc (d-locv (car ll)))
436: (d-exp (cadr ll))
437: (d-clearuse (car ll)))
438: else (setq tmp (cdr v-form)))
439:
440: ; do final setq
441: (let ((g-loc (d-locv (car tmp)))
442: (g-cc (If g-loc then nil else g-cc))
443: (g-ret nil))
444: (d-exp (cadr tmp))
445: (d-clearuse (car tmp)))
446: (If g-loc then (d-move (d-locv (car tmp)) g-loc)
447: (If g-cc then (d-handlecc)))))
448:
449:
450:
451: ; cc-typep :: compile a "typep" expression = cc-typep =
452: ;
453: ; this returns the type of the expression, it is always non nil
454: ;
455: (defun cc-typep nil
456: (let ((argloc (d-simple (cadr v-form)))
457: (g-ret))
458: (If (null argloc) then (let ((g-loc 'reg) g-cc)
459: (d-exp (cadr v-form)))
460: (setq argloc 'reg))
461: (If g-loc then (e-write4 'ashl '$-9 (e-cvt argloc) 'r0)
462: (e-write3 'cvtbl "_typetable+1[r0]" 'r0)
463: (e-write3 'movl "_tynames+4[r0]" 'r0)
464: (e-write3 'movl "(r0)" (e-cvt g-loc)))
465: (If (car g-cc) then (e-goto (car g-cc)))))
466:
467:
468:
469: ; cm-symeval :: compile a symeval expression.
470: ; the symbol cell in franz lisp is just the cdr.
471: ;
472: (defun cm-symeval nil
473: `(cdr ,(cadr v-form)))
474:
475:
476: ; c-*throw :: compile a "*throw" expression =c-*throw =
477: ;
478: ; the form of *throw is (*throw 'tag 'val) .
479: ; we calculate and stack the value of tag, then calculate val
480: ; we call Idothrow to do the actual work, and only return if the
481: ; throw failed.
482: ;
483: (defun c-*throw nil
484: (let ((arg2loc (d-simple (caddr v-form)))
485: g-cc
486: g-ret
487: arg1loc)
488: (If arg2loc then (If (setq arg1loc (d-simple (cadr v-form)))
489: then (e-write2 'pushl (e-cvt arg2loc))
490: (e-write2 'pushl (e-cvt arg1loc))
491: else (let ((g-loc 'reg))
492: (d-exp (cadr v-form)) ; calc tag
493: (e-write2 'pushl (e-cvt arg2loc))
494: (e-write2 'pushl (e-cvt 'reg))))
495: else (let ((g-loc 'stack))
496: (d-exp (cadr v-form)) ; calc tag to stack
497: (Push g-locs nil)
498: (incr g-loccnt)
499: (setq g-loc 'reg)
500: (d-exp (caddr v-form)) ; calc value into r0
501: (e-write2 'pushl (e-cvt 'reg))
502: (e-write2 'pushl (e-cvt 'unstack))
503: (unpush g-locs)
504: (decr g-loccnt)))
505: (e-write3 'calls '$0 '_Idothrow)
506: (e-write2 'clrl '"-(sp)") ; non contuable error
507: (e-write2 'pushab '__erthrow) ; string to print
508: (e-write3 'calls '$2 '_error)))
509:
510:
511:
512: ;--- cm-zerop :: convert zerop to a quick test = cm-zerop =
513: ; zerop is only allowed on fixnum and flonum arguments. In both cases,
514: ; if the value of the first 32 bits is zero, then we have a zero.
515: ; thus we can define it as a macro:
516: (defun cm-zerop nil
517: (cond ((atom (cadr v-form))
518: `(and (null (cdr ,(cadr v-form))) (not (bigp ,(cadr v-form)))))
519: (t (let ((gnsy (gensym)))
520: `((lambda (,gnsy)
521: (and (null (cdr ,gnsy))
522: (not (bigp ,gnsy))))
523: ,(cadr v-form))))))
524:
525:
526:
527: ;------- FIXNUM arithmetic section ---------
528: ; beware all ye who read this section
529: ;
530:
531:
532:
533: (declare (localf d-upordown d-fixop))
534:
535: ;--- c-1+ :: fixnum add1 function
536: ;
537: (defun c-1+ nil
538: (d-upordown 'addl3))
539:
540: ;--- c-1- :: fixnum sub1 function
541: ;
542: (defun c-1- nil
543: (d-upordown 'subl3))
544:
545: (defun d-upordown (opcode)
546: (let ((arg (cadr v-form))
547: argloc)
548: (If (setq argloc (d-simple `(cdr ,arg)))
549: then (e-write4 opcode '$1 (e-cvt argloc) 'r5)
550: else (let ((g-loc 'reg)
551: g-ret
552: g-cc)
553: (d-exp arg))
554: (e-write4 opcode '$1 "(r0)" 'r5))
555: (e-write2 "jsb" "_qnewint")
556: (d-clearreg)))
557:
558:
559: ;--- c-+ :: fixnum add = c-+ =
560: ;
561: (defun c-+ nil
562: (d-fixop 'addl3 'plus))
563:
564: (defun c-- nil
565: (d-fixop 'subl3 'difference))
566:
567: (defun c-* nil
568: (d-fixop 'mull3 'times))
569:
570: (defun c-/ nil
571: (d-fixop 'divl3 'quotient))
572:
573: (defun c-\\ nil
574: (d-fixop 'ediv 'remainder))
575:
576: (defun d-fixop (opcode lispopcode)
577: (prog (op1 op2 rop1 rop2 simpleop1)
578: (If (not (eq 3 (length v-form))) ; only handle two ops for now
579: then (d-callbig lispopcode (cdr v-form))
580: else (setq op1 (cadr v-form)
581: op2 (caddr v-form))
582: (If (fixp op1)
583: then (setq rop1 (concat '$ op1) ; simple int
584: simpleop1 t)
585: else (If (setq rop1 (d-simple `(cdr ,op1)))
586: then (setq rop1 (e-cvt rop1))
587: else (let ((g-loc 'reg) g-cc g-ret)
588: (d-exp op1))
589: (setq rop1 '|(r0)|)))
590: (If (fixp op2)
591: then (setq rop2 (concat '$ op2))
592: else (If (setq rop2 (d-simple `(cdr ,op2)))
593: then (setq rop2 (e-cvt rop2))
594: else (e-write3 'movl rop1 "-(sp)")
595: (setq rop1 "(sp)+")
596: (let ((g-loc 'reg)
597: g-cc g-ret)
598: (d-exp op2))
599: (setq rop2 '|(r0)|)))
600: (If (eq opcode 'ediv)
601: then (If (not simpleop1) then (e-write3 'movl rop1 'r2) ; need quad
602: (e-write4 'ashq '$-32 'r1 'r1)
603: (setq rop1 'r1)) ; word div.
604: (e-write5 'ediv rop2 rop1 'r0 'r5)
605: else (e-write4 opcode rop2 rop1 'r5))
606:
607: (e-write2 'jsb "_qnewint")
608: (d-clearreg))))
609:
610:
611:
612:
613: ;---- d routines (general ones, others are near function using them)
614:
615:
616:
617: ;--- d-cmp :: compare two IADR values
618: ;
619: (defun d-cmp (arg1 arg2)
620: (e-write3 'cmpl (e-cvt arg1) (e-cvt arg2)))
621:
622:
623: ;--- d-handlecc :: handle g-cc
624: ; at this point the Z condition code has been set up and if g-cc is
625: ; non nil, we must jump on condition to the label given in g-cc
626: ;
627: (defun d-handlecc nil
628: (If (car g-cc) then (e-gotot (car g-cc))
629: elseif (cdr g-cc) then (e-gotonil (cdr g-cc))))
630:
631:
632: ;--- d-invert :: handle inverted condition codes
633: ; this routine is called if a result has just be computed which alters
634: ; the condition codes such that Z=1 if the result is t, and Z=0 if the
635: ; result is nil (this is the reverse of the usual sense). The purpose
636: ; of this routine is to handle g-cc and g-loc. That is if g-loc is
637: ; specified, we must convert the value of the Z bit of the condition
638: ; code to t or nil and store that in g-loc. After handling g-loc we
639: ; must handle g-cc, that is if the part of g-cc is non nil which matches
640: ; the inverse of the current condition code, we must jump to that.
641: ;
642: (defun d-invert nil
643: (If (null g-loc)
644: then (If (car g-cc) then (e-gotonil (car g-cc))
645: elseif (cdr g-cc) then (e-gotot (cdr g-cc)))
646: else (let ((lab1 (d-genlab))
647: (lab2 (If (cdr g-cc) thenret else (d-genlab))))
648: (e-gotonil lab1)
649: ; Z=1, but remember that this implies nil due to inversion
650: (d-move 'Nil g-loc)
651: (e-goto lab2)
652: (e-label lab1)
653: ; Z=0, which means t
654: (d-move 'T g-loc)
655: (If (car g-cc) then (e-goto (car g-cc)))
656: (If (null (cdr g-cc)) then (e-label lab2)))))
657:
658:
659: ;--- d-noninvert :: handle g-cc and g-loc assuming cc non inverted
660: ;
661: ; like d-invert except Z=0 implies nil, and Z=1 implies t
662: ;
663: (defun d-noninvert nil
664: (If (null g-loc)
665: then (If (car g-cc) then (e-gotot (car g-cc))
666: elseif (cdr g-cc) then (e-gotonil (cdr g-cc)))
667: else (let ((lab1 (d-genlab))
668: (lab2 (If (cdr g-cc) thenret else (d-genlab))))
669: (e-gotot lab1)
670: ; Z=0, this implies nil
671: (d-move 'Nil g-loc)
672: (e-goto lab2)
673: (e-label lab1)
674: ; Z=1, which means t
675: (d-move 'T g-loc)
676: (If (car g-cc) then (e-goto (car g-cc)))
677: (If (null (cdr g-cc)) then (e-label lab2)))))
678:
679: ;--- d-macroexpand :: macro expand a form as much as possible
680: ;
681: (defun d-macroexpand (form)
682: (prog nil
683: loop
684: (If (and (dtpr form)
685: (symbolp (car form))
686: (eq 'macro (d-functyp (car form))))
687: then (setq form (apply (car form) form))
688: (go loop))
689: (return form)))
690:
691: ;--- d-makespec :: declare a variable to be special
692: ;
693: (defun d-makespec (vrb)
694: (putprop vrb t g-spec))
695:
696:
697: ;--- d-move :: emit instructions to move value from one place to another
698: ;
699: (defun d-move (from to)
700: (makecomment `(from ,(e-uncvt from) to ,(e-uncvt to)))
701: (cond ((eq 'Nil from) (e-write2 'clrl (e-cvt to)))
702: (t (e-write3 'movl (e-cvt from) (e-cvt to)))))
703:
704:
705: ;--- d-simple :: see of arg can be addresses in one instruction
706: ; we define simple and really simple as follows
707: ; <rsimple> ::= number
708: ; quoted anything
709: ; local symbol
710: ; t
711: ; nil
712: ; <simple> ::= <rsimple>
713: ; (cdr <rsimple>)
714: ; global symbol
715: ;
716: (defun d-simple (arg)
717: (let (tmp)
718: (If (d-rsimple arg) thenret
719: elseif (symbolp arg) then (d-loc arg)
720: elseif (and (memq (car arg) '(cdr car cddr cdar))
721: (setq tmp (d-rsimple (cadr arg))))
722: then (If (eq 'Nil tmp) then tmp
723: elseif (atom tmp)
724: then (If (eq 'car (car arg)) then `(racc 4 ,tmp)
725: elseif (eq 'cdr (car arg)) then `(racc 0 ,tmp)
726: elseif (eq 'cddr (car arg)) then `(racc * 0 ,tmp)
727: elseif (eq 'cdar (car arg)) then `(racc * 4 ,tmp))
728: elseif (not (eq 'cdr (car arg))) then nil
729: elseif (eq 'lbind (car tmp)) then `(bind ,(cadr tmp))
730: elseif (eq 'stack (car tmp)) then `(vstack ,(cadr tmp))
731: elseif (eq 'fixnum (car tmp)) then `(immed ,(cadr tmp))
732: elseif (atom (car tmp)) then `(0 ,(cadr tmp))
733: else (comp-err "bad arg to d-simple: " (or arg))))))
734:
735: (defun d-rsimple (arg)
736: (If (atom arg) then
737: (If (null arg) then 'Nil
738: elseif (eq t arg) then 'T
739: elseif (or (numberp arg)
740: (memq arg g-locs))
741: then (d-loc arg)
742: else (car (d-bestreg arg nil)))
743: elseif (eq 'quote (car arg)) then (d-loclit (cadr arg) nil)))
744:
745: ;--- d-movespec :: move from loc to loc where the first addr given is
746: ; an EIADR
747: ; - from : EIADR
748: ; - to : IADR
749: ;
750: (defun d-movespec (from to)
751: (makecomment `(fromspec ,from to ,(e-uncvt to)))
752: (e-write3 'movl from (e-cvt to)))
753:
754:
755: ;--- d-specialp :: check if a variable is special
756: ; a varible is special if it has been declared as such, or if
757: ; the variable special is t
758: (defun d-specialp (vrb)
759: (or special (get vrb g-spec)))
760:
761:
762: ;--- d-tst :: test the given value (set the cc)
763: ;
764: (defun d-tst (arg)
765: (e-write2 'tstl (e-cvt arg)))
766:
767: ;--- d-typesimp :: determine the type of the argument
768: ;
769: (defun d-typesimp (arg val)
770: (let ((argloc (d-simple arg)))
771: (If (null argloc) then (let ((g-loc 'reg)
772: g-cc g-ret)
773: (d-exp arg))
774: (setq argloc 'reg))
775: (e-write4 'ashl '$-9 (e-cvt argloc) 'r0)
776: (e-write3 'cmpb '"_typetable+1[r0]" val)
777: (d-invert)))
778:
779: ;--- d-typecmplx :: determine if arg has one of many types
780: ; - arg : lcode argument to be evaluated and checked
781: ; - vals : fixnum with a bit in position n if we are to check type n
782: ;
783: (defun d-typecmplx (arg vals)
784: (let ((argloc (d-simple arg))
785: (reg))
786: (If (null argloc) then (let ((g-loc 'reg)
787: g-cc g-ret)
788: (d-exp arg))
789: (setq argloc 'reg))
790: (setq reg 'r0)
791: (e-write4 'ashl '$-9 (e-cvt argloc) reg)
792: (e-write3 'cvtbl (concat "_typetable+1[" reg "]") reg)
793: (e-write4 'ashl reg '$1 reg)
794: (e-write3 'bitw vals reg)
795: (d-noninvert)))
796:
797:
798: ;---- register handling routines.
799:
800: ;--- d-allocreg :: allocate a register
801: ; name - the name of the register to allocate or nil if we should
802: ; allocate the least recently used.
803: ;
804: (defun d-allocreg (name)
805: (If name
806: then (let ((av (assoc name g-reguse)))
807: (If av then (rplaca (cdr av) (1+ (cadr av)))) ; inc used count
808: name)
809: else ; find smallest used count
810: (do ((small (car g-reguse))
811: (smc (cadar g-reguse))
812: (lis (cdr g-reguse) (cdr lis)))
813: ((null lis)
814: (rplaca (cdr small) (1+ smc))
815: (car small))
816: (If (< (cadar lis) smc)
817: then (setq small (car lis)
818: smc (cadr small))))))
819:
820:
821: ;--- d-bestreg :: determine the register which is closest to what we have
822: ; name - name of variable whose subcontents we want
823: ; pat - list of d's and a's which tell which part we want
824: ;
825: (defun d-bestreg (name pat)
826: (do ((ll g-reguse (cdr ll))
827: (val)
828: (best)
829: (tmp)
830: (bestv -1))
831: ((null ll) (If best then (rplaca (cdr best) (1+ (cadr best)))
832: (list (car best)
833: (If (> bestv 0)
834: then (rplacd (nthcdr (1- bestv)
835: (setq tmp
836: (copy pat)))
837: nil)
838: tmp
839: else nil)
840: (nthcdr bestv pat))))
841: (If (and (setq val (cddar ll))
842: (eq name (car val)))
843: then (If (> (setq tmp (d-matchcnt pat (cdr val)))
844: bestv)
845: then (setq bestv tmp
846: best (car ll))))))
847:
848: ;--- d-matchcnt :: determine how many parts of a pattern match
849: ; want - pattern we want to achieve
850: ; have - pattern whose value exists in a register
851: ;
852: ; we return a count of the number of parts of the pattern match.
853: ; If this pattern will be any help at all, we return a value from
854: ; 0 to the length of the pattern.
855: ; If this pattern will not work at all, we return a number smaller
856: ; than -1.
857: ; For `have' to be useful for `want', `have' must be a substring of
858: ; `want'. If it is a substring, we return the length of `have'.
859: ;
860: (defun d-matchcnt (want have)
861: (let ((length 0))
862: (If (do ((hh have (cdr hh))
863: (ww want (cdr ww)))
864: ((null hh) t)
865: (If (or (null ww) (not (eq (car ww) (car hh))))
866: then (return nil)
867: else (incr length)))
868: then length
869: else -2)))
870:
871:
872:
873: ;--- d-clearreg :: clear all values in registers or just one
874: ; if no args are given, clear all registers.
875: ; if an arg is given, clear that register
876: ;
877: (defun d-clearreg n
878: (cond ((zerop n)
879: (mapc '(lambda (x) (rplaca (cdr x) 0)
880: (rplacd (cdr x) nil))
881: g-reguse))
882: (t (let ((av (assoc (arg 1) g-reguse)))
883: (If av then (rplaca (cdr av) 0)
884: (rplacd (cdr av) nil))))))
885:
886:
887: ;--- d-clearuse :: clear all register which reference a given variable
888: ;
889: (defun d-clearuse (varib)
890: (mapc '(lambda (x)
891: (If (eq (caddr x) varib) then (rplacd (cdr x) nil)))
892: g-reguse))
893:
894:
895: ;--- d-inreg :: declare that a value is in a register
896: ; name - register name
897: ; value - value in a register
898: ;
899: (defun d-inreg (name value)
900: (let ((av (assoc name g-reguse)))
901: (If av then (rplacd (cdr av) value))
902: name))
903:
904:
905: ;---- e routines
906:
907:
908:
909: (defun e-cvt (arg)
910: (If (eq 'reg arg) then 'r0
911: elseif (eq 'Nil arg) then '$0
912: elseif (eq 'T arg) then (If g-trueloc thenret
913: else (setq g-trueloc (e-cvt (d-loclit t nil))))
914: elseif (eq 'stack arg) then '(+ #.Np-reg)
915: elseif (eq 'unstack arg) then '(- #.Np-reg)
916: elseif (atom arg) then arg
917: elseif (dtpr arg) then (If (eq 'stack (car arg))
918: then `(,(* 4 (1- (cadr arg))) #.oLbot-reg)
919: elseif (eq 'vstack (car arg))
920: then `(* ,(* 4 (1- (cadr arg))) #.oLbot-reg)
921: elseif (eq 'bind (car arg))
922: then `(* ,(* 4 (1- (cadr arg))) #.bind-reg)
923: elseif (eq 'lbind (car arg))
924: then `( ,(* 4 (1- (cadr arg))) #.bind-reg)
925: elseif (eq 'fixnum (car arg))
926: then `(\# ,(cadr arg))
927: elseif (eq 'immed (car arg))
928: then `($ ,(cadr arg))
929: elseif (eq 'racc (car arg))
930: then (cdr arg)
931: else (comp-err " bad arg to e-cvt : "
932: (or arg)))
933: else (comp-warn "bad arg to e-cvt : " (or arg))))
934:
935:
936: ;--- e-uncvt :: inverse of e-cvt, used for making comments pretty
937: ;
938: (defun e-uncvt (arg)
939: (If (atom arg) then (If (eq 'Nil arg) then nil
940: else arg)
941: elseif (eq 'stack (car arg))
942: then (do ((i g-loccnt)
943: (ll g-locs))
944: ((and (equal i (cadr arg)) (atom (car ll))) (car ll))
945: (If (atom (car ll)) then (setq ll (cdr ll)
946: i (1- i))
947: else (setq ll (cdr ll))))
948: elseif (or (eq 'bind (car arg)) (eq 'lbind (car arg)))
949: then (do ((i g-litcnt (1- i))
950: (ll g-lits (cdr ll)))
951: ((equal i (cadr arg)) (cond ((eq 'lbind (car arg))
952: (list 'quote (car ll)))
953: (t (car ll)))))
954: else arg))
955:
956: ;--- e-cvtas :: convert an EIADR to vax unix assembler fmt and print it
957: ; - form : an EIADR form
958: ;
959: (defun e-cvtas (form)
960: (If (atom form)
961: then (sfilewrite form)
962: else (If (eq '* (car form)) then (If (eq '\# (cadr form))
963: then (setq form `($ ,(caddr form)))
964: else (sfilewrite "*")
965: (setq form (cdr form))))
966: (If (numberp (car form))
967: then (sfilewrite (car form))
968: (sfilewrite "(")
969: (sfilewrite (cadr form))
970: (sfilewrite ")")
971: (If (caddr form)
972: then (sfilewrite "[")
973: (sfilewrite (caddr form))
974: (sfilewrite "]"))
975: elseif (eq '+ (car form))
976: then (sfilewrite '"(")
977: (sfilewrite (cadr form))
978: (sfilewrite '")+")
979: elseif (eq '- (car form))
980: then (sfilewrite '"-(")
981: (sfilewrite (cadr form))
982: (sfilewrite '")")
983: elseif (eq '\# (car form)) ; 5120 is base of small fixnums
984: then (sfilewrite (concat "$" (+ (* (cadr form) 4) 5120)))
985: elseif (eq '$ (car form))
986: then (sfilewrite '"$")
987: (sfilewrite (cadr form)))))
988: ;--- e-cmp :: emit code to compare the two given args
989: ; - arg1, arg2 : EIADRs
990: ;
991: (defun e-cmp (arg1 arg2)
992: (e-write3 'cmpl arg1 arg2))
993:
994: ;--- e-docomment :: print any comment lines
995: ;
996: (defun e-docomment nil
997: (If g-comments
998: then (do ((ll (nreverse g-comments) (cdr ll)))
999: ((null ll))
1000: (sfilewrite '" #")
1001: (sfilewrite (car ll))
1002: (terpr vp-sfile))
1003: (setq g-comments nil)
1004: else (terpr vp-sfile)))
1005: ;--- e-goto :: emit code to jump to the location given
1006: ;
1007: (defun e-goto (lbl)
1008: (e-jump lbl))
1009:
1010: ;--- e-gotonil :: emit code to jump if nil was last computed
1011: ;
1012: (defun e-gotonil (lbl)
1013: (e-write2 'jeql lbl))
1014:
1015: ;--- e-gotot :: emit code to jump if t was last computed
1016: (defun e-gotot (lbl)
1017: (e-write2 'jneq lbl))
1018:
1019: ;--- e-label :: emit a label
1020: (defun e-label (lbl)
1021: (setq g-skipcode nil)
1022: (e-writel lbl))
1023:
1024: ;--- e-move :: move value from one place to anther
1025: ; this corresponds to d-move except the args are EIADRS
1026: ;
1027: (defun e-move (from to)
1028: (If (equal 0 from) then (e-write2 'clrl to)
1029: else (e-write3 'movl from to)))
1030:
1031: ;--- e-pop :: pop the given number of args from the stack
1032: ; g-locs is not! fixed
1033: ;
1034: (defun e-pop (nargs)
1035: (If (greaterp nargs 0)
1036: then (e-dropnp nargs)))
1037:
1038:
1039: ;--- e-pushnil :: push a given number of nils on the stack
1040: ;
1041: (defun e-pushnil (nargs)
1042: (do ((i nargs))
1043: ((zerop i))
1044: (If (greaterp i 1) then (e-write2 'clrq np-plus)
1045: (setq i (- i 2))
1046: elseif (equal i 1) then (e-write2 'clrl np-plus)
1047: (setq i (1- i)))))
1048:
1049: ;--- e-tst :: test a value, arg is an EIADR
1050: ;
1051: (defun e-tst (arg)
1052: (e-write2 'tstl arg))
1053: ;--- e-setupbind :: setup for shallow binding
1054: ;
1055: (defun e-setupbind nil
1056: (e-write3 'movl '#.Bnp-val '#.bNp-reg))
1057:
1058: ;--- e-unsetupbind :: restore temp value of bnp to real loc
1059: ;
1060: (defun e-unsetupbind nil
1061: (e-write3 'movl '#.bNp-reg '#.Bnp-val))
1062:
1063: ;--- e-shallowbind :: shallow bind value of variable and initialize it
1064: ; - name : variable name
1065: ; - val : IADR value for variable
1066: ;
1067: (defun e-shallowbind (name val)
1068: (let ((vloc (d-loclit name t)))
1069: (e-write3 'movl (e-cvt vloc) '(+ #.bNp-reg)) ; store old val
1070: (e-write3 'movl (e-cvt `(lbind ,@(cdr vloc)))
1071: '(+ #.bNp-reg)) ; now name
1072: (d-move val vloc)))
1073:
1074: ;--- e-unshallowbind :: un shallow bind n variable from top of stack
1075: ;
1076: (defun e-unshallowbind (n)
1077: (e-setupbind) ; set up binding register
1078: (do ((i 1 (1+ i)))
1079: ((greaterp i n))
1080: (e-write3 'movl `(,(* -8 i) ,bNp-reg) `(* ,(+ 4 (* -8 i)) ,bNp-reg)))
1081: (e-write4 'subl3 `($ ,(* 8 n)) bNp-reg Bnp-val))
1082:
1083: ;----------- very low level routines
1084: ; all output to the assembler file goes through these routines.
1085: ; They filter out obviously extraneous instructions as well as
1086: ; combine sequential drops of np.
1087:
1088: ;--- e-dropnp :: unstack n values from np.
1089: ; rather than output the instruction now, we just remember that it
1090: ; must be done before any other instructions are done. This will
1091: ; enable us to catch sequential e-dropnp's
1092: ;
1093: (defun e-dropnp (n)
1094: (If (not g-skipcode)
1095: then (setq g-dropnpcnt (+ n (If g-dropnpcnt thenret else 0)))))
1096:
1097: ;--- em-checknpdrop :: check if we have a pending npdrop
1098: ; and do it if so.
1099: ;
1100: (defmacro em-checknpdrop nil
1101: `(If g-dropnpcnt then (let ((dr g-dropnpcnt))
1102: (setq g-dropnpcnt nil)
1103: (e-write3 'subl2 `($ ,(* dr 4)) Np-reg))))
1104:
1105: ;--- em-checkskip :: check if we are skipping this code due to jump
1106: ;
1107: (defmacro em-checkskip nil
1108: '(If g-skipcode then (sfilewrite "# ")))
1109:
1110:
1111: ;--- e-jump :: jump to given label
1112: ; and set g-skipcode so that all code following until the next label
1113: ; will be skipped.
1114: ;
1115: (defun e-jump (l)
1116: (em-checknpdrop)
1117: (e-write2 'jbr l)
1118: (setq g-skipcode t))
1119:
1120: ;--- e-return :: do return, and dont check for np drop
1121: ;
1122: (defun e-return nil
1123: (setq g-dropnpcnt nil) ; we dont need to worry about nps
1124: (e-write1 'ret))
1125:
1126:
1127: ;--- e-writel :: write out a label
1128: ;
1129: (defun e-writel (label)
1130: (setq g-skipcode nil)
1131: (em-checknpdrop)
1132: (sfilewrite label)
1133: (sfilewrite '":")
1134: (e-docomment))
1135:
1136: ;--- e-write1 :: write out one litteral
1137: ;
1138: (defun e-write1 (lit)
1139: (em-checkskip)
1140: (em-checknpdrop)
1141: (sfilewrite lit)
1142: (e-docomment))
1143:
1144: ;--- e-write2 :: write one one litteral, and one operand
1145: ;
1146: (defun e-write2 (lit frm)
1147: (em-checkskip)
1148: (em-checknpdrop)
1149: (sfilewrite lit)
1150: (sfilewrite '" ")
1151: (e-cvtas frm)
1152: (e-docomment))
1153:
1154: ;--- e-write3 :: write one one litteral, and two operands
1155: ;
1156: (defun e-write3 (lit frm1 frm2)
1157: (em-checkskip)
1158: (em-checknpdrop)
1159: (sfilewrite lit)
1160: (sfilewrite '" ")
1161: (e-cvtas frm1)
1162: (sfilewrite '",")
1163: (e-cvtas frm2)
1164: (e-docomment))
1165:
1166: ;--- e-write4 :: write one one litteral, and three operands
1167: ;
1168: (defun e-write4 (lit frm1 frm2 frm3)
1169: (em-checkskip)
1170: (em-checknpdrop)
1171: (sfilewrite lit)
1172: (sfilewrite '" ")
1173: (e-cvtas frm1)
1174: (sfilewrite '",")
1175: (e-cvtas frm2)
1176: (sfilewrite '",")
1177: (e-cvtas frm3)
1178: (e-docomment))
1179:
1180:
1181: ;--- e-write5 :: write one one litteral, and four operands
1182: ;
1183: (defun e-write5 (lit frm1 frm2 frm3 frm4)
1184: (em-checkskip)
1185: (em-checknpdrop)
1186: (sfilewrite lit)
1187: (sfilewrite '" ")
1188: (e-cvtas frm1)
1189: (sfilewrite '",")
1190: (e-cvtas frm2)
1191: (sfilewrite '",")
1192: (e-cvtas frm3)
1193: (sfilewrite '",")
1194: (e-cvtas frm4)
1195: (e-docomment))
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.