;;; -*- Mode:Lisp; Package:(NC LISP); Readtable:CL; Base:10 -*- ;;;; Primitive Operations ;;; This file defines the primitive operations known to the compiler. ;;; Various fields and flags may be specified as follows: ;;; ;;; :CONDITIONAL? T if this is a predicate, ie, the value ;;; is a boolean and this predicate may be ;;; an argument to IF ;;; ;;; :SPECIAL? T if a continuation should not be generated ;;; for this primop, usually used only for ;;; more obscure flow of control primops ;;; ;;; :PRESIMPLIFY code to do some simplification before the simplification ;;; pass. The major use of this is for predicates, which ;;; should call presimplify-to-conditional ;;; ;;; :SIMPLIFY code which attempts to simplify this primop ;;; ;;; :GENERATE code which generates the code of this primop ;;; unless :special? is specified, this code ;;; must return and accessor for the return value, ;;; generate-continuation will move the return value ;;; to the appropriate place. ;---------------------------------------------------------------- ;;;; Compiler Internal Primitives ;;; from primops;base (define-primop Y (???) (:generate (node) (generate-labels node)) (:simplify (node) (simplify-y node)) (:special? t)) (define-primop %go (tag tagbody-cont) (:generate (node) (destructure (((tagbody-cont tag) (call-args node))) (generate-go tagbody-cont tag))) (: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-to-conditional node)) (:simplify (node) (simplify-test node)) (:type-predicate? (primop) t) (:type (node) '((t) boolean)) ) (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)))) (define-primop initialize-global (global value) (:side-effects? t) (:generate (node) (destructure (((nil global value) (call-args node))) (if (and (literal-node? global) (literal-node? value)) (emit-movei value (literal-value global)) (bug "INITIALIZE-GLOBAL called with bad args")) ''NIL))) (define-primop %cons-rest (var) (:side-effects? t) (:generate (node) (generate-cons-rest 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))) ;;; Primitives used by CATCH and THROW (define-primop %catch-open (cont tag) (:generate (node) (generate-catch-open node))) (define-primop %catch-body-values (&rest values) (:special? t) (:generate (node) (generate-catch-body-values node))) (define-primop %catch-continue () (:side-effects? t) (:special? t) (:generate (node) (generate-catch-continue node))) (define-primop %throw-internal (tag result) (:side-effects? t) (:special? t) (:generate (node) (generate-throw-internal node))) ;;; dispatch to labels (define-primop %dispatch ( ) ;; just to be careful (:side-effects? t) ;; no continuation for this luser ;; LUSER? this wins. (:special? t) (:generate (node) (let ((cont (car (call-args node))) (otherwise (second (call-exit-args node))) (procs (cddr (call-exit-args node)))) (destructure (((byte-spec word . values) (call-non-exit-args node))) (if (literal-node? byte-spec) (setq byte-spec (literal-value byte-spec)) (warn "The byte spec: ~s, is unknown at compile time.")) (let ((field-size (expt 2 (prims::byte-size byte-spec))) (clause-list '())) (do ((procs procs (cdr procs))) ((null procs)) (lambda-queue (car procs)) (let ((keys '())) (dotimes (i (literal-value (pop values))) (let ((value (literal-value (pop values)))) (when (> value field-size) (warn "The DISPATCH clause test value ~A is not a possible value of the field (BYTE ~a ~a)." value (prims::byte-size byte-spec) (prims::byte-position byte-spec))) (push value keys))) (push (cons keys (car procs)) clause-list))) (lambda-queue otherwise) (emit-alu-field 'K:FIELD-EXTRACT-R R0 IGNORED (get-right-operand word) `(PRIMS::BYTE ,(prims::byte-size byte-spec) ,(- (prims::byte-position byte-spec))) 'K:PW-II 'K:UNBOXED) (emit-alu 'K:L+R 'K:R1 'GR::*TRAP-DTP-CODE-5* 'K:TRAP-PC+ '(K:BW-32 K:BOXED)) (emit-alu 'K:L+R 'k:NOP 'K:R0 'K:R1 '(K:BW-32 K:BOXED)) (emit 'K:NOP) (emit 'K:NOP 'K:NEXT-PC-DISPATCH) (dotimes (i field-size) (let ((clause (assoc i clause-list :test #'member))) (emit-unconditional-branch (if clause (cdr clause) otherwise) )))))))) ;--------------------------------------------------------------- ;;;; Lisp Primitives ;(deftype boolean () t) (deftype boolean () '(or t nil)) (define-primop eq (x y) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'eq)) (:generate (node) (comparator node 'K:BR-NOT-EQUAL 'K:BW-32)) (:conditional? t) (:type (node) '((t t) boolean))) ;;; EQL is just like EQ except it traps if both sides are ;;; an extended numbers of the same type. (define-primop eql (x y) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'eql)) (:generate (node) (comparator node 'K:BR-NOT-EQUAL 'K:BW-32 'K:DT-HAIRY-NUMBER)) (:conditional? t) (:type (node) '((t t) boolean))) ;;;; Arithmatic Comparisons (define-primop zerop (number) (:presimplify (node) (presimplify-to-conditional node)) ;predicate (:simplify (node) (simplify-if-constant-predicate node 'zerop)) (:generate (node) (generate-fixnum-arith-predicate node 'K:BR-NOT-ZERO)) (:conditional? t) (:type (node) '((number) boolean))) (define-primop minusp (number) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'minusp)) (:generate (node) (generate-fixnum-arith-predicate node 'K:BR-NOT-NEGATIVE)) (:conditional? t) (:type (node) '((number) boolean))) (define-primop plusp (number) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'plusp)) (:generate (node) (generate-fixnum-arith-predicate node 'K:BR-NOT-POSITIVE)) (:conditional? t) (:type (node) '((number) boolean))) (define-primop 2-arg-= (number1 number2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node '=)) (:generate (node) ;; This does not use subtract: ;; (comparator node 'K:BR-NOT-EQUAL ;; 'K:BW-24 'K:DT-BOTH-FIXNUM) ;; so that we can tell the difference between = and < etc ;; for complex numbers (let ((left (call-arg-n 4 node)) (right (call-arg-n 5 node))) (multiple-value-bind (l r) (get-operands left right) (emit-alu 'K:XOR 'K:NOP l r '(K:BW-24 K:DT-BOTH-FIXNUM))) (generate-conditional node 'K:BR-NOT-EQUAL))) (:conditional? t) (:type (node) '((number number) boolean))) (define-primop 2-arg-< (n1 n2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node '<)) (:generate (node) (comparator node 'K:BR-NOT-LESS-THAN 'K:BW-24 'K:DT-BOTH-FIXNUM)) (:conditional? t) (:type (node) '((number number) boolean))) (define-primop 2-arg-> (n1 n2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node '>)) (:generate (node) (comparator node 'K:BR-NOT-GREATER-THAN 'K:BW-24 'K:DT-BOTH-FIXNUM)) (:conditional? t) (:type (node) '((number number) boolean))) (define-primop 2-arg->= (n1 n2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node '>=)) (:generate (node) (comparator node 'K:BR-NOT-GREATER-OR-EQUAL 'K:BW-24 'K:DT-BOTH-FIXNUM)) (:conditional? t) (:type (node) '((number number) boolean))) (define-primop 2-arg-<= (n1 n2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node '<=)) (:generate (node) (comparator node 'K:BR-NOT-LESS-OR-EQUAL 'K:BW-24 'K:DT-BOTH-FIXNUM)) (:conditional? t) (:type (node) '((number number) boolean))) ;;;; 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 'K:BOXED 'K:DT-BOTH-FIXNUM-WITH-OVERFLOW)) (:type (node) '((integer integer) integer))) (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 'K:BOXED 'K:DT-BOTH-FIXNUM-WITH-OVERFLOW)) (:type (node) '((integer integer) integer))) (define-primop 2-arg-logxnor (n1 n2) (:simplify (node) (simplify-if-constant-expression node 'logxor)) (:generate (node) (generate-binop node 'K:XNOR 'K:XNOR 'K:BW-24 'K:BOXED 'K:DT-BOTH-FIXNUM-WITH-OVERFLOW)) (:type (node) '((integer integer) integer))) (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 'K:BOXED 'K:DT-BOTH-FIXNUM-WITH-OVERFLOW)) (:type (node) '((integer integer) integer))) (define-primop ash (n nbits) (:simplify (node) (simplify-if-constant-expression node 'ash)) (:generate (node) (destructure (((cont n nbits) (call-args node))) (let ((dest (get-destination cont)) (num (get-right-operand n))) (let ((left (get-left-side-for-fixnum-unop num))) (if (literal-node? nbits) (let ((amount (leaf-value nbits))) (cond ((not (integerp amount)) (warn "Shift amount to ASH ~a is not an integer." amount)) ((= amount 1) (emit-alu 'K:SHIFT-UP-0F-R dest left num '(K:BW-24 K:BOXED K:DT-BOTH-FIXNUM-WITH-OVERFLOW))) ((= amount 2) (emit-alu 'K:SHIFT-UP-0F-R R0 left num '(K:BW-24 K:BOXED K:DT-BOTH-FIXNUM-WITH-OVERFLOW)) (emit-alu 'K:SHIFT-UP-0F-R dest R0 R0 '(K:BW-24 K:BOXED K:DT-BOTH-FIXNUM-WITH-OVERFLOW))) ((= amount -1) (emit-alu 'K:SHIFT-DN-AR-R dest left num '(K:BW-24 K:BOXED K:DT-BOTH-FIXNUM-WITH-OVERFLOW))) ((= amount -2) (emit-alu 'K:SHIFT-DN-AR-R R0 left num '(K:BW-24 K:BOXED K:DT-BOTH-FIXNUM-WITH-OVERFLOW)) (emit-alu 'K:SHIFT-DN-AR-R dest R0 R0 '(K:BW-24 K:BOXED K:DT-BOTH-FIXNUM-WITH-OVERFLOW))) ; ((minusp amount) shift-down) ; ((plusp amount) shift-up) ((zerop amount) (generate-move num dest)) (t (generate-internal-call 'NEW-MATH:ASH-GENERIC dest num nbits)))) ;;@@@ Do at compile time instead (generate-internal-call 'NEW-MATH:ASH-GENERIC dest num nbits))) dest))) (:type (node) '((integer integer) integer))) (define-primop dpb (value byte-spec word) (:simplify (node) (simplify-if-constant-expression node 'nlisp:dpb)) (:generate (node) (destructure (((cont value byte-spec word) (call-args node))) (if (and (literal-node? byte-spec) (let ((bs (literal-value byte-spec))) (< (+ (prims::byte-position bs) (prims::byte-size bs)) 23.))) (generate-dpb cont value byte-spec word 'K:DT-BOTH-FIXNUM) (let ((dest (get-destination cont))) (generate-internal-call 'NEW-MATH:FIELD-PASS-GENERIC dest value byte-spec word) dest))))) (define-primop prims::byte (size position) (:simplify (node) (simplify-if-constant-expression node 'prims:byte)) (:generate (node) (destructure (((cont size position) (call-args node))) ;; `(hw:dpb ,size vinc:%%byte-size ,position) ;; this isn't correct. It is more like ;; `(hw:dpb ,size vinc:%%byte-size (hw:ldb ,position vinc:%%byte-position 0.)) (emit-alu-field 'K:FIELD-PASS R1 (get-left-operand position) 'GR::*ZERO* `(PRIMS::BYTE ,(prims::byte-size vinc:%%byte-position) ,(- (prims::byte-position vinc:%%byte-position))) 'K::DT-BOTH-FIXNUM 'K:BOXED-RIGHT 'K:PW-II) (generate-dpb cont size `',vinc:%%byte-size R1 'K:DT-BOTH-FIXNUM)))) (define-primop prims::byte-size (byte) (:simplify (node) (simplify-if-constant-expression node 'prims:byte-size)) (:generate (node) (destructure (((cont byte) (call-args node))) (generate-ldb cont byte `',vinc:%%byte-size 0 'k:dt-both-fixnum)))) (define-primop prims::byte-position (byte) (:simplify (node) (simplify-if-constant-expression node 'prims:byte-position)) (:generate (node) (destructure (((cont byte) (call-args node))) (generate-ldb cont byte `',vinc:%%byte-position 0 'k:dt-both-fixnum)))) ;;;; Arithmetic Primops (define-primop 2-arg-+ (n1 n2) (:simplify (node) (simplify-if-constant-expression node '+)) (:generate (node) (let ((arg1 (call-arg-n 2 node)) (arg2 (call-arg-n 3 node))) (multiple-value-bind (literal non-literal) (if (literal-node? arg1) (values arg1 arg2) (if (literal-node? arg2) (values arg2 arg1))) (if literal (case (literal-value literal) (0 non-literal) (1 (generate-degenerate-fixnum-binop node non-literal 'K:R+1)) (2 (generate-degenerate-fixnum-binop node non-literal 'K:R+2)) (4 (generate-degenerate-fixnum-binop node non-literal 'K:R+4)) (t (generate-binop node 'K:L+R 'K:L+R 'K:BW-24 'K:BOXED 'K:DT-BOTH-FIXNUM-WITH-OVERFLOW))) (generate-binop node 'K:L+R 'K:L+R 'K:BW-24 'K:BOXED 'K:DT-BOTH-FIXNUM-WITH-OVERFLOW))))) (:type (node) '((number number) number))) (define-primop 2-arg-- (n1 n2) (:simplify (node) (simplify-if-constant-expression node '-)) (:generate (node) (let ((arg2 (call-arg-n 3 node))) (if (literal-node? arg2) (let ((arg1 (call-arg-n 2 node))) (case (literal-value arg2) (0 arg1) (1 (generate-degenerate-fixnum-binop node arg1 'K:R-1)) (2 (generate-degenerate-fixnum-binop node arg1 'K:R-2)) (4 (generate-degenerate-fixnum-binop node arg1 'K:R-4)) (t (generate-binop node 'K:L-R 'K:R-L 'K:BW-24 'K:BOXED 'K:DT-BOTH-FIXNUM-WITH-OVERFLOW)))) (generate-binop node 'K:L-R 'K:R-L 'K:BW-24 'K:BOXED 'K:DT-BOTH-FIXNUM-WITH-OVERFLOW)))) (:type (node) '((number number) number))) (define-primop 1+ (n) (:simplify (node) (simplify-if-constant-expression node '1+)) (:generate (node) (generate-fixnum-unop node 'K:R+1)) (:type (node) '((number) number))) (define-primop 1- (n) (:simplify (node) (simplify-if-constant-expression node '1-)) (:generate (node) (generate-fixnum-unop node 'K:R-1)) (:type (node) '((number) number))) ;---------------------------------------------------------------- ;;;; Lisp Subprimitives (define-primop funcall-internal (f &rest args) (:side-effects? t) (:simplify (node) (simplify-funcall node)) (:generate (node) (destructure (((cont fcn . args) (call-args node))) (generate-move fcn 'GR:*ARG-2*) (generate-move `',(length args) 'GR:*ARG-1*) (let ((dest (get-destination cont))) (apply #'generate-internal-call 'LI:FUNCALL-INTERNAL dest args) dest)))) (define-primop apply-internal (f &rest args) (:side-effects? t) (:generate (node) (destructure (((cont fcn . args) (call-args node))) (generate-move fcn 'GR:*ARG-2*) (let ((spread-args (butlast args)) (consed-args (car (last args)))) (generate-move `',(length spread-args) 'GR:*ARG-1*) (generate-move consed-args 'GR:*VALUE-1*) (let ((dest (get-destination cont))) (apply #'generate-internal-call 'LI:APPLY-INTERNAL dest spread-args) dest))))) (define-primop cons::%car (list) (:generate (node) (generate-move (call-arg-n 2 node) '(K:VMA-START-READ K:BOXED-VMA K:BOXED-MD) 'K:DT-RIGHT-LIST) (emit 'K:MEMORY-WAIT) 'K:MD)) (define-primop cons::%cdr (list) (:generate (node) (generate-move (call-arg-n 2 node) '(K:VMA-START-READ-CDR K:BOXED-VMA K:BOXED-MD) 'K:DT-RIGHT-LIST) (emit 'K:MEMORY-WAIT) 'K:MD)) (NOTE "%set-car and %set-cdr use DT-RIGHT-LIST, but shouldn't allow NIL") (define-primop cons::%set-car (ptr new-value return-value) (:side-effects? t) (:generate (node) (generate-gc-safe-memory-write (call-arg-n 2 node) (call-arg-n 3 node) (call-arg-n 4 node) '(K:VMA-START-READ-WILL-WRITE K:BOXED-VMA K:BOXED-MD) 'K:DT-RIGHT-LIST))) (define-primop cons::%set-cdr (ptr new-value return-value) (:side-effects? t) (:generate (node) (generate-gc-safe-memory-write (call-arg-n 2 node) (call-arg-n 3 node) (call-arg-n 4 node) '(K:VMA-START-READ-CDR-WILL-WRITE K:BOXED-VMA K:BOXED-MD) 'K:DT-RIGHT-LIST))) (define-primop cons::%store-contents (ptr new-value) (:side-effects? t) (:generate (node) (generate-gc-safe-memory-write (call-arg-n 2 node) (call-arg-n 3 node) (call-arg-n 3 node) '(K:VMA-START-READ-WILL-WRITE K:BOXED-VMA K:BOXED-MD) 'K:DT-NONE))) (define-primop cons::%store-contents-offset (ptr offset new-value) (:side-effects? t) (:generate (node) (generate-gc-safe-memory-write (call-arg-n 2 node) (call-arg-n 4 node) (call-arg-n 4 node) '(K:VMA-START-READ-WILL-WRITE K:UNBOXED-VMA K:BOXED-MD) 'K:DT-NONE (call-arg-n 3 node)))) (define-primop array::start-array-header-reference (array) (:side-effects? t) (:generate (node) (destructure (((cont array) (call-args node))) ;; data type traps don't work on immediates because ;; they look like unboxed (the box bits are for the result, not the source) (if (literal-p array) (if (arrayp (literal-value array)) (generate-move array '(K:VMA-START-READ K:BOXED-VMA K:BOXED-MD)) (progn (warn "AREF or ASET of the constant ~S which is not an array." (literal-value array)) ;; arrange to trap at run time (generate-move array R0) (emit-alu 'K:SETR '(K:VMA-START-READ K:BOXED-VMA K:BOXED-MD) 'GR:*RANDOM-STRUCTURE* R0 '(K:DT-RIGHT-ARRAY-AND-LEFT-STRUCTURE)))) (multiple-value-bind (left right) (get-operands 'gr:*random-structure* array) (emit-alu 'K:SETR '(K:VMA-START-READ K:BOXED-VMA K:BOXED-MD) left right '(K:DT-RIGHT-ARRAY-AND-LEFT-STRUCTURE)))) ''NIL))) (define-primop li:%char= (number1 number2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char=)) (:generate (node) (comparator node 'K:BR-NOT-EQUAL 'K:BW-24 'K:DT-BOTH-CHARACTER)) (:conditional? t) (:type (node) '((character character) boolean))) (define-primop li:%char/= (number1 number2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char/=)) (:generate (node) (comparator node 'K:BR-EQUAL 'K:BW-24 'K:DT-BOTH-CHARACTER)) (:conditional? t) (:type (node) '((character character) boolean))) (define-primop li:%char< (n1 n2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char<)) (:generate (node) (comparator node 'K:BR-NOT-LESS-THAN 'K:BW-24 'K:DT-BOTH-CHARACTER)) (:conditional? t) (:type (node) '((character character) boolean))) (define-primop li:%char> (n1 n2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char>)) (:generate (node) (comparator node 'K:BR-NOT-GREATER-THAN 'K:BW-24 'K:DT-BOTH-CHARACTER)) (:conditional? t) (:type (node) '((character character) boolean))) (define-primop li:%char>= (n1 n2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char>=)) (:generate (node) (comparator node 'K:BR-NOT-GREATER-OR-EQUAL 'K:BW-24 'K:DT-BOTH-CHARACTER)) (:conditional? t) (:type (node) '((character character) boolean))) (define-primop li:%char<= (n1 n2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char<=)) (:generate (node) (comparator node 'K:BR-NOT-LESS-OR-EQUAL 'K:BW-24 'K:DT-BOTH-CHARACTER)) (:conditional? t) (:type (node) '((character character) boolean))) (define-primop li:%char-equal (char1 char2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char-equal)) (:generate (node) (comparator node 'K:BR-NOT-EQUAL 'K:BW-8 'K:DT-BOTH-CHARACTER))) ;DT-NOT-BOTH-CHAR (define-primop li:%char-not-equal (char1 char2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char-not-equal)) (:generate (node) (comparator node 'K:BR-EQUAL 'K:BW-8 'K:DT-BOTH-CHARACTER))) ;DT-NOT-BOTH-CHAR (define-primop li:%char-lessp (char1 char2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char-lessp)) (:generate (node) (comparator node 'K:BR-NOT-LESS-THAN 'K:BW-8 'K:DT-BOTH-CHARACTER))) ;DT-NOT-BOTH-CHAR (define-primop li:%char-not-lessp (char1 char2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char-not-lessp)) (:generate (node) (comparator node 'K:BR-LESS-THAN 'K:BW-8 'K:DT-BOTH-CHARACTER))) ;DT-NOT-BOTH-CHAR (define-primop li:%char-greaterp (char1 char2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char-greaterp)) (:generate (node) (comparator node 'K:BR-NOT-GREATER-THAN 'K:BW-8 'K:DT-BOTH-CHARACTER))) ;DT-NOT-BOTH-CHAR (define-primop li:%char-not-greaterp (char1 char2) (:presimplify (node) (presimplify-to-conditional node)) (:simplify (node) (simplify-if-constant-predicate node 'char-not-greaterp)) (:generate (node) (comparator node 'K:BR-GREATER-THAN 'K:BW-8 'K:DT-BOTH-CHARACTER))) ;DT-NOT-BOTH-CHAR (define-primop li:%trap-if-not-character (char) (:side-effects? t) (:simplify (node) (let ((arg (call-arg-n 2 node))) (if (and (literal-node? arg) (characterp (literal-value arg))) (simplify-if-constant-expression node 'characterp)))) (:generate (node) (let ((left (get-left-operand (call-arg-n 2 node)))) (emit 'K:ALU 'K:PASS-STATUS 'K:NOP left left 'K:DT-BOTH-CHARACTER 'K:UNBOXED) ''NIL))) (define-primop li:%trap-if-not-both-fixnum (fixnum1 fixnum2) (:side-effects? t) (:simplify (node) (let ((arg1 (call-arg-n 2 node)) (arg2 (call-arg-n 3 node))) (if (or (and (literal-node? arg1) (si:fixnump (literal-value arg1))) (and (literal-node? arg2) (si:fixnump (literal-value arg2)))) (simplify-if-constant-expression node 'si:fixnump)))) (:generate (node) (let ((left (get-left-operand (call-arg-n 2 node))) (right (get-right-operand (call-arg-n 3 node)))) (emit 'K:ALU 'K:SEX-R 'K:NOP left right 'K:DT-BOTH-FIXNUM 'K:UNBOXED) ''NIL)))