;;; -*- Mode:Lisp; Package:(NC LISP); Readtable:CL; Base:10 -*- ;;; Copyright (c) 1985 Yale University ;;; Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees. ;;; This material was developed by the T Project at the Yale University Computer ;;; Science Department. Permission to copy this software, to redistribute it, ;;; and to use it for any purpose is granted, subject to the following restric- ;;; tions and understandings. ;;; 1. Any copy made of this software must include this copyright notice in full. ;;; 2. Users of this software agree to make their best efforts (a) to return ;;; to the T Project at Yale any improvements or extensions that they make, ;;; so that these may be included in future releases; and (b) to inform ;;; the T Project of noteworthy uses of this software. ;;; 3. All materials developed as a consequence of the use of this software ;;; shall duly acknowledge such use, in accordance with the usual standards ;;; of acknowledging credit in academic research. ;;; 4. Yale has made no warrantee or representation that the operation of ;;; this software will be error-free, and Yale is under no obligation to ;;; provide any services, by way of maintenance, update, or otherwise. ;;; 5. In conjunction with products arising from the use of this material, ;;; there shall be no use of the name of the Yale University nor of any ;;; adaptation thereof in any advertising, promotional, or sales literature ;;; without prior written consent from Yale in each case. ;;; ;;;; Primitive Operations ;---------------------------------------------------------------- ;;;; Compiler Internal Primitives ;;; from primops;base (define-primop Y (???) (:generate (node) (generate-labels node)) (:simplify (node) (simplify-y node)) (:special? t)) (define-primop conditional (test-primop &rest args) (:generate (node) (primop.generate (primop-value (call-arg-n 3 node)) node)) (:conditional? t) (:simplify (node) (primop.simplify (primop-value (call-arg-n 3 node)) node))) (define-primop test (???) (:generate (node) (primop.generate (primop-value (call-arg-n 4 node)) node)) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-test node)) (:conditional? t)) (define-primop true? (value) (:generate (node) (generate-nil-test node)) (:presimplify (node) (presimplify-predicate node)) (:type-predicate? (primop) t) ; (:type (node) '(proc (cont boolean?) top?)) ) ;(define-primop contents-location ; (:generate (node) ; (generate-contents-location node))) (define-primop setq-lexical (var value) (:side-effects? t) (:generate (node) (generate-lexical-setq node (call-arg-n 2 node) (call-arg-n 3 node)))) (define-primop setq-special (symbol value) (:side-effects? t) (:generate (node) (generate-special-setq node (call-arg-n 2 node) (call-arg-n 3 node)))) (define-primop special-ref (symbol) (:generate (node) (generate-special-ref node (call-arg-n 2 node)))) (define-primop function-ref (symbol) (:generate (node) (generate-function-ref node (call-arg-n 2 node)))) ;;; Primop which generates setup code ;;; for optional argument (define-primop optional-setup (first-label nargs supplied-p-vars &rest init-labels) (:generate (node) (generate-optional-setup node)) (:side-effects? t) (:special? t)) ;;; this does nothing ;;; optional inits use it (define-primop noop () (:generate (node) node nil) (:side-effects? t)) ;;; Primop which generates an OPEN instruction ;;; this primop is put in by make-user-call ;;; during node conversion (define-primop open-frame (call) (:side-effects? t) (:generate (node) (generate-open node))) ;--------------------------------------------------------------- ;;;; Lisp Primitives (define-primop eq (x y) (:generate (node) (comparator node 'K:BR-NOT-EQUAL 'K:BW-32)) (:presimplify (node) (presimplify-to-conditional node)) (:conditional? t) ; (:type (node) ; node ; '(proc (cont boolean?) fixnum? fixnum?)) ) ;;;; Arithmatic Comparisons (define-primop zerop (number) (:generate (node) (generate-arith-predicate node 'K:BR-NOT-ZERO 'K:BW-24)) (:presimplify (node) (presimplify-predicate node)) (:conditional? t)) (define-primop minusp (number) (:generate (node) (generate-arith-predicate node 'K:BR-NOT-NEGATIVE 'K:BW-24)) (:presimplify (node) (presimplify-predicate node)) (:conditional? t)) (define-primop plusp (number) (:generate (node) (generate-arith-predicate node 'K:BR-NOT-POSITIVE 'K:BW-24)) (:presimplify (node) (presimplify-predicate node)) (:conditional? t)) (define-primop = (number1 number2) (:generate (node) (comparator node 'K:BR-NOT-EQUAL 'K:BW-24)) (:presimplify (node) (presimplify-to-conditional node)) (:conditional? t) ; (:type (node) ; node ; '(proc (cont boolean?) fixnum? fixnum?)) ) (define-primop < (n1 n2) (:generate (node) (comparator node 'K:BR-NOT-LESS-THAN 'K:BW-24)) (:presimplify (node) (presimplify-to-conditional node)) (:conditional? t) ; (:type (node) ; node ; '(proc (cont boolean?) fixnum? fixnum?)) ) (define-primop > (n1 n2) (:generate (node) (comparator node 'K:BR-NOT-GREATER-THAN 'K:BW-24)) (:presimplify (node) (presimplify-to-conditional node)) (:conditional? t) ; (:type (node) ; node ; '(proc (cont boolean?) fixnum? fixnum?)) ) (define-primop >= (n1 n2) (:generate (node) (comparator node 'K:BR-NOT-GREATER-OR-EQUAL 'K:BW-24)) (:presimplify (node) (presimplify-to-conditional node)) (:conditional? t) ; (:type (node) ; node ; '(proc (cont boolean?) fixnum? fixnum?)) ) (define-primop <= (n1 n2) (:generate (node) (comparator node 'K:BR-NOT-LESS-THAN-OR-EQUAL 'K:BW-24)) (:presimplify (node) (presimplify-to-conditional node)) (:conditional? t) ; (:type (node) ; node ; '(proc (cont boolean?) fixnum? fixnum?)) ) ;;;; Logical Primops (define-primop 2-arg-logand (n1 n2) (:simplify (node) (simplify-if-constant-expression node 'logand)) (:generate (node) (generate-binop node 'K:AND 'K:AND 'K:BW-24))) (define-primop 2-arg-logxor (n1 n2) (:simplify (node) (simplify-if-constant-expression node 'logxor)) (:generate (node) (generate-binop node 'K:XOR 'K:XOR 'K:BW-24))) (define-primop 2-arg-logior (n1 n2) (:simplify (node) (simplify-if-constant-expression node 'logior)) (:generate (node) (generate-binop node 'K:OR 'K:OR 'K:BW-24))) (define-primop ash (n nbits) (:simplify (node) (simplify-if-constant-expression node 'ash)) (:generate (node) (destructure (((cont n nbits) (call-args node))) (if (literal-node? nbits) (let ((amount (leaf-value nbits))) (if (< amount 0) (if (> amount -6) (let ((dest (continuation-expecting cont))) (dotimes (i (abs amount)) (emit-alu 'K:SHIFT-DN-AR-R dest IGNORED (get-right-operand n) 'K:BW-24))) (cerror "foo" "> 5 bit shifts not yet implemented")) (if (< amount 6) (let ((dest (continuation-expecting cont))) (dotimes (i amount) (emit-alu 'K:SHIFT-UP-0F-R dest IGNORED (get-right-operand n) 'K:BW-24))) (cerror "foo" "> 5 bit shifts not yet implemented")))) (progn (cerror "foo" "call ash")))))) (define-primop byte (size position) (:simplify (node) (simplify-if-constant-expression node 'byte)) (:generate (node) (destructure (((cont size position) (call-args node))) ;; `(hw:dpb ,size vinc:%%byte-size ,position) (generate-dpb cont size `',vinc:%%byte-size position)))) ;;;; Arithmetic Primops (defun value-if-literal (node) (when (literal-node? node) (literal-value node))) (define-primop 2-arg-+ (n1 n2) (:simplify (node) (simplify-if-constant-expression node '+)) (:generate (node) (generate-binop node 'K:L+R 'K:L+R 'K:BW-24))) (define-primop 2-arg-- (n1 n2) (:simplify (node) (simplify-if-constant-expression node '-)) (:generate (node) (generate-binop node 'K:L-R 'K:R-L 'K:BW-24))) (define-primop 1+ (n) (:simplify (node) (simplify-if-constant-expression node '1+)) (:generate (node) (generate-unop node 'K:R+1 'K:BW-24)) ; (:type (node) '(proc (cont fixnum?) fixnum?)) ) (define-primop 1- (n) (:simplify (node) (simplify-if-constant-expression node '1-)) (:generate (node) (generate-unop node 'K:R-1 'K:BW-24)) ; (:type (node) '(proc (cont fixnum?) fixnum?)) ) ;---------------------------------------------------------------- ;;;; Hardware Primops (define-primop hw:nop () (:side-effects? t) (:generate (node) (emit 'K:NOP) (generate-move ''nil (continuation-expecting (call-arg-n 1 node))))) ;;; compiler internal ;;; (hw: ...) expands into this (define-primop read-functional-source (fsource) (:side-effects? t) (:generate (node) (generate-move (leaf-value (call-arg-n 2 node)) (continuation-expecting (call-arg-n 1 node))))) ;;; compiler internal ;;; (hw: ...) expands into this (define-primop write-functional-dest (fdest value) (:side-effects? t) (:generate (node) (let ((value (call-arg-n 3 node))) (generate-move value (leaf-value (call-arg-n 2 node))) (generate-move ''nil (continuation-expecting (call-arg-n 1 node)))))) ;;; This does not use write-functional-dest because ;;; it has to be done twice and a temp holding the value ;;; could get allocated to MEMORY-MAP then the second ;;; move would not get generated. (define-primop hw:write-map (value) (:side-effects? t) (:generate (node) (let ((ref (get-right-operand (call-arg-n 2 node)))) (emit 'K:MOVE 'K:MEMORY-MAP ref 'K:UNBOXED) (emit 'K:MOVE 'K:MEMORY-MAP ref 'K:UNBOXED) (generate-move ref (continuation-expecting (call-arg-n 1 node)))))) ;;; This does not use write-functional-dest because ;;; it has to be done twice and a temp holding the value ;;; could get allocated to GC-RAM then the second ;;; move would not get generated. (define-primop hw:write-gc-ram (value) (:side-effects? t) (:generate (node) (let ((ref (get-right-operand (call-arg-n 2 node)))) (emit 'K:MOVE 'K:GC-RAM ref 'K:UNBOXED) (emit 'K:MOVE 'K:GC-RAM ref 'K:UNBOXED) (generate-move ref (continuation-expecting (call-arg-n 1 node)))))) ;;; This does not use write-functional-dest because ;;; it has to be done twice and a temp holding the value ;;; could get allocated to TRANSPORTER-RAM then the second ;;; move would not get generated. (define-primop hw:write-transporter-ram (value) (:side-effects? t) (:generate (node) (let ((ref (get-right-operand (call-arg-n 2 node)))) (emit 'K:MOVE 'K:TRANSPORTER-RAM ref 'K:UNBOXED) (emit 'K:MOVE 'K:TRANSPORTER-RAM ref 'K:UNBOXED) (generate-move ref (continuation-expecting (call-arg-n 1 node)))))) (define-primop hw:dpb (value byte-spec word) (:simplify (node) (simplify-if-constant-expression node 'dpb)) (:generate (node) (destructure (((cont value byte-spec word) (call-args node))) (generate-dpb cont value byte-spec word)))) (define-primop hw:dpb-xor (value byte-spec word) (:simplify (node) (simplify-if-constant-expression node 'dpb)) (:generate (node) (destructure (((cont value byte-spec word) (call-args node))) (generate-dpb cont value byte-spec word 'K:FIELD-XOR)))) (define-primop hw:dpb-unboxed (value byte-spec word) (:simplify (node) (simplify-if-constant-expression node 'dpb)) (:generate (node) (destructure (((cont value byte-spec word) (call-args node))) (generate-dpb cont value byte-spec word 'K:FIELD-PASS 'K:UNBOXED)))) (defun hw-ldb (from byte-spec into) (dpb (ldb byte-spec from) (byte (byte-size byte-spec) 0) into)) (define-primop hw:ldb (from byte-spec into) (:simplify (node) (simplify-if-constant-expression node 'hw-ldb)) (:generate (node) (destructure (((cont from byte-spec into) (call-args node))) (if (literal-node? byte-spec) (emit-alu-field 'K:FIELD-PASS (continuation-expecting cont) (get-left-operand from) (get-right-operand into) (let ((byte-spec (leaf-value byte-spec))) `(BYTE ,(byte-size byte-spec) ;(ldb vinc:%%byte-size byte-spec) ;target byte-size ,(- (byte-position byte-spec)))) ;(ldb vinc:%%byte-position byte-spec)))) ;target byte-position 'K:PW-II) (progn (emit 'K:MOVE R1 (get-right-operand byte-spec) 'K:BW-16) (emit-alu 'K:NEG-R R1 IGNORED R1 'K:BW-8) (emit-alu 'K:LOAD-STATUS-R 'K:NOP-NO-OVERFLOW-TRAP IGNORED R1 'K:BW-16) (emit-alu-field 'K:FIELD-PASS (continuation-expecting cont) (get-left-operand from) (get-right-operand into) ''0 'K:PW-RR)))))) (define-primop hw:32logbitp (index n) (:conditional? t) (:presimplify (node) (presimplify-to-conditional node)) (:generate (node) (let ((index (call-arg-n 4 node)) (n (call-arg-n 5 node))) (if (literal-node? index) (emit-alu-field 'K:EXTRACT-BIT-RIGHT 'K:NOP-NO-OVERFLOW-TRAP IGNORED (get-right-operand n) `(BYTE 0 ,(leaf-value index)) 'K:PW-II) (progn (emit-alu 'K:LOAD-STATUS-R 'K:NOP-NO-OVERFLOW-TRAP IGNORED (get-right-operand index) 'K:BW-8) (emit-alu-field 'K:EXTRACT-BIT-RIGHT 'K:NOP-NO-OVERFLOW-TRAP IGNORED (get-right-operand n) ''0 'K:PW-RR))) (generate-conditional node 'K:BR-ZERO)))) ;;; Don't ask about the next few. ;;; Do a tail open (define-primop hw:ch-topen () (:side-effects? t) (:generate (node) (emit 'K:TAIL-OPEN))) ;;; Have the call hardware do a tail call operation ;;; without really calling (define-primop hw:ch-tcall () (:generate (node) (emit 'K:TAIL-CALL '(0 0) 'K:NEXT-PC-PC+1)) (:side-effects? t)) ;;; Have the call hardware do an open-call operation ;;; without transferring control. (define-primop hw:ch-open-call () (:generate (node) (emit 'K:OPEN-CALL '(0 0) 'K:NEXT-PC-PC+1)) (:side-effects? t)) (define-primop hw:ch-topen-call () (:generate (node) (emit 'K:TAIL-OPEN-CALL '(0 0) 'K:NEXT-PC-PC+1)) (:side-effects? t)) (define-primop hw:ch-return () (:generate (node) (emit 'K:NOP 'K:CH-RETURN 'k:next-pc-pc+1)) (side-effects? t)) ;;; dispatch to a computed value (define-primop hw:dispatch (pc) (:generate (node) (generate-move (call-arg-n 2 node) 'K:NOP-NO-OVERFLOW-TRAP) (emit 'K:NOP) (emit 'K:NOP 'K:NEXT-PC-DISPATCH) (generate-move ''NIL (continuation-expecting (call-arg-n 1 node)))) (:side-effects? t)) (define-primop hw:jump (fcn) (:side-effects? t) (:special? t) ;we do our own contination (ignore it) (:generate (node) (emit 'K:JUMP (leaf-value (call-arg-n 2 node))))) ;(define-primop hw:unboxed-constant (number) ; (:generate (node) ; (let ((n (call-arg-n 2 node))) ; (if (and (literal-node? n) ; (integerp (leaf-value n))) ; (emit 'K:MOVEI (continuation-expecting (call-arg-n 1 node)) (cons '/# (leaf-value n)) 'K:UNBOXED) ; (error "Argument to HW:UNBOXED-CONSTANT: ~s should be an integer." (leaf-value n)))))) ;;; Actually this is the same as eq? (define-primop hw:32= (n1 n2) (:generate (node) (comparator node 'K:BR-NOT-EQUAL 'K:BW-32)) (:presimplify (node) (presimplify-to-conditional node)) (:conditional? t) ; (:type (node) ; node ; '(proc (cont boolean?) fixnum? fixnum?)) ) (define-primop hw:32>= (n1 n2) (:generate (node) (comparator node 'K:BR-NOT-GREATER-OR-EQUAL 'K:BW-32)) (:presimplify (node) (presimplify-to-conditional node)) (:conditional? t) ; (:type (node) ; node ; '(proc (cont boolean?) fixnum? fixnum?)) ) (define-primop hw:32logand (n1 n2) (:simplify (node) (simplify-if-constant-expression node 'logand)) (:generate (node) (generate-binop node 'K:AND 'K:AND 'K:BW-32))) (define-primop hw:32logxor (n1 n2) (:simplify (node) (simplify-if-constant-expression node 'logxor)) (:generate (node) (generate-binop node 'K:XOR 'K:XOR 'K:BW-32))) (define-primop hw:32logior (n1 n2) (:simplify (node) (simplify-if-constant-expression node 'logior)) (:generate (node) (generate-binop node 'K:OR 'K:OR 'K:BW-32))) (define-primop hw:32-1+ (n) ; (:simplify (node) ; (simplify-if-constant-expression node '1+)) (:generate (node) (generate-unop node 'K:R+1 'K:BW-32))) (define-primop hw:32-2+ (n) ; (:simplify (node) ; (simplify-if-constant-expression node '1+)) (:generate (node) (generate-unop node 'K:R+2 'K:BW-32))) (define-primop hw:32-4+ (n) ; (:simplify (node) ; (simplify-if-constant-expression node '1+)) (:generate (node) (generate-unop node 'K:R+4 'K:BW-32))) (define-primop hw:32+ (n1 n2) (:generate (node) (generate-binop node 'K:L+R 'K:L+R))) (define-primop hw:32- (n1 n2) (:generate (node) (generate-binop node 'K:L-R 'K:R-L))) ;;; This is just like equal but doesn't TRAP-UNLES-BOTH-FIX (define-primop hw:24= (n1 n2) (:generate (node) (comparator node 'K:BR-NOT-EQUAL 'K:BW-24)) (:presimplify (node) (presimplify-to-conditional node)) (:conditional? t) ; (:type (node) ; node ; '(proc (cont boolean?) fixnum? fixnum?)) ) ;;; like + but no dtp trap (define-primop hw:24+ (n1 n2) (:generate (node) (generate-binop node 'K:L+R 'K:L+R 'K:BW-24))) ;;;; Lisp Subprimitives (define-primop funcall-internal (f) (:side-effects? t) (:simplify (node) (simplify-funcall node)) (:generate (node))) ;;; ksi ;;; (KSI:OPEN-FRAME ) ;;; (alu l+r+2 *arg-1* *arg-1* ) ;;; (alu l+r+2 *arg-1* *arg-1* ) ;(define-primop ksi:open-frame ; (:side-effects? t) ; (:generate (node) ; (emit 'K:KOPEN) ; ;; bump stack-pointer if nargs>16 ; )) ;;; (move *arg-1* ) ;;; (move *arg-2* ) ;;; (jump ksi:set-arg-aux (*return-pc-1* opc)) ;;; ;;; ksi:set-arg-aux ;;; (alu l-r ignore *arg-1* '15) ;;; (alu l+r+4 noop *arg-1* opc br-gt) ;;; (branch set-stack-arg (r+1 noop ignore *return-pc-1*)) ;;; (dispatch) ;;; (noop) ;this doesn't get executed ;;; (dispatch (move O0 *arg-2*)) ;;; (dispatch (move O1 *arg-2*)) ;;; (dispatch (move O2 *arg-2*)) ;;; (dispatch (move O3 *arg-2*)) ;;; (dispatch (move O4 *arg-2*)) ;;; (dispatch (move O5 *arg-2*)) ;;; (dispatch (move O6 *arg-2*)) ;;; (dispatch (move O7 *arg-2*)) ;;; (dispatch (move O8 *arg-2*)) ;;; (dispatch (move O9 *arg-2*)) ;;; (dispatch (move O10 *arg-2*)) ;;; (dispatch (move O11 *arg-2*)) ;;; (dispatch (move O12 *arg-2*)) ;;; (dispatch (move O13 *arg-2*)) ;;; (dispatch (move O14 *arg-2*)) ;;; (dispatch (move O15 *arg-2*)) ;;; get-stack-arg ;;; ;;; (KSI:SET-ARG ) ;(define-primop ksi:set-arg)