📄 arith.lisp
字号:
(:arg-types signed-num) (:results (res :scs (any-reg))) (:result-types positive-fixnum) (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift) (:generator 30 (let ((loop (gen-label)) (test (gen-label))) (move shift arg) (inst bgez shift test) (move res zero-tn t) (inst b test) (inst nor shift shift) (emit-label loop) (inst add res (fixnumize 1)) (emit-label test) (inst bne shift loop) (inst srl shift 1))))(define-vop (unsigned-byte-32-count) (:translate logcount) (:note "inline (unsigned-byte 32) logcount") (:policy :fast-safe) (:args (arg :scs (unsigned-reg) :target num)) (:arg-types unsigned-num) (:results (res :scs (unsigned-reg))) (:result-types positive-fixnum) (:temporary (:scs (non-descriptor-reg) :from (:argument 0) :to (:result 0) :target res) num) (:temporary (:scs (non-descriptor-reg)) mask temp) (:generator 30 (inst li mask #x55555555) (inst srl temp arg 1) (inst and num arg mask) (inst and temp mask) (inst addu num temp) (inst li mask #x33333333) (inst srl temp num 2) (inst and num mask) (inst and temp mask) (inst addu num temp) (inst li mask #x0f0f0f0f) (inst srl temp num 4) (inst and num mask) (inst and temp mask) (inst addu num temp) (inst li mask #x00ff00ff) (inst srl temp num 8) (inst and num mask) (inst and temp mask) (inst addu num temp) (inst li mask #x0000ffff) (inst srl temp num 16) (inst and num mask) (inst and temp mask) (inst addu res num temp)));;; Multiply and Divide.(define-vop (fast-*/fixnum=>fixnum fast-fixnum-binop) (:temporary (:scs (non-descriptor-reg)) temp) (:translate *) (:generator 4 (inst sra temp y n-fixnum-tag-bits) (inst mult x temp) (inst mflo r)))(define-vop (fast-*/signed=>signed fast-signed-binop) (:translate *) (:generator 3 (inst mult x y) (inst mflo r)))(define-vop (fast-*/unsigned=>unsigned fast-unsigned-binop) (:translate *) (:generator 3 (inst multu x y) (inst mflo r)))(define-vop (fast-truncate/fixnum fast-fixnum-binop) (:translate truncate) (:results (q :scs (any-reg)) (r :scs (any-reg))) (:result-types tagged-num tagged-num) (:temporary (:scs (non-descriptor-reg) :to :eval) temp) (:vop-var vop) (:save-p :compute-only) (:generator 11 (let ((zero (generate-error-code vop division-by-zero-error x y))) (inst beq y zero)) (inst nop) (inst div x y) (inst mflo temp) (inst sll q temp n-fixnum-tag-bits) (inst mfhi r)))(define-vop (fast-truncate/unsigned fast-unsigned-binop) (:translate truncate) (:results (q :scs (unsigned-reg)) (r :scs (unsigned-reg))) (:result-types unsigned-num unsigned-num) (:vop-var vop) (:save-p :compute-only) (:generator 12 (let ((zero (generate-error-code vop division-by-zero-error x y))) (inst beq y zero)) (inst nop) (inst divu x y) (inst mflo q) (inst mfhi r)))(define-vop (fast-truncate/signed fast-signed-binop) (:translate truncate) (:results (q :scs (signed-reg)) (r :scs (signed-reg))) (:result-types signed-num signed-num) (:vop-var vop) (:save-p :compute-only) (:generator 12 (let ((zero (generate-error-code vop division-by-zero-error x y))) (inst beq y zero)) (inst nop) (inst div x y) (inst mflo q) (inst mfhi r)));;;; Binary conditional VOPs:(define-vop (fast-conditional) (:conditional) (:info target not-p) (:effects) (:affected) (:temporary (:scs (non-descriptor-reg)) temp) (:policy :fast-safe))(define-vop (fast-conditional/fixnum fast-conditional) (:args (x :scs (any-reg)) (y :scs (any-reg))) (:arg-types tagged-num tagged-num) (:note "inline fixnum comparison"))(define-vop (fast-conditional-c/fixnum fast-conditional/fixnum) (:args (x :scs (any-reg))) (:arg-types tagged-num (:constant (signed-byte-with-a-bite-out 14 4))) (:info target not-p y))(define-vop (fast-conditional/signed fast-conditional) (:args (x :scs (signed-reg)) (y :scs (signed-reg))) (:arg-types signed-num signed-num) (:note "inline (signed-byte 32) comparison"))(define-vop (fast-conditional-c/signed fast-conditional/signed) (:args (x :scs (signed-reg))) (:arg-types signed-num (:constant (signed-byte-with-a-bite-out 16 1))) (:info target not-p y))(define-vop (fast-conditional/unsigned fast-conditional) (:args (x :scs (unsigned-reg)) (y :scs (unsigned-reg))) (:arg-types unsigned-num unsigned-num) (:note "inline (unsigned-byte 32) comparison"))(define-vop (fast-conditional-c/unsigned fast-conditional/unsigned) (:args (x :scs (unsigned-reg))) (:arg-types unsigned-num (:constant (and (signed-byte-with-a-bite-out 16 1) unsigned-byte))) (:info target not-p y))(defmacro define-conditional-vop (translate &rest generator) `(progn ,@(mapcar #'(lambda (suffix cost signed) (unless (and (member suffix '(/fixnum -c/fixnum)) (eq translate 'eql)) `(define-vop (,(intern (format nil "~:@(FAST-IF-~A~A~)" translate suffix)) ,(intern (format nil "~:@(FAST-CONDITIONAL~A~)" suffix))) (:translate ,translate) (:generator ,cost (let* ((signed ,signed) (-c/fixnum ,(eq suffix '-c/fixnum)) (y (if -c/fixnum (fixnumize y) y))) (declare (ignorable signed -c/fixnum y)) ,@generator))))) '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned) '(3 2 5 4 5 4) '(t t t t nil nil))))(define-conditional-vop < (cond ((and signed (eql y 0)) (if not-p (inst bgez x target) (inst bltz x target))) (t (if signed (inst slt temp x y) (inst sltu temp x y)) (if not-p (inst beq temp target) (inst bne temp target)))) (inst nop))(define-conditional-vop > (cond ((and signed (eql y 0)) (if not-p (inst blez x target) (inst bgtz x target))) ((integerp y) (let ((y (+ y (if -c/fixnum (fixnumize 1) 1)))) (if signed (inst slt temp x y) (inst sltu temp x y)) (if not-p (inst bne temp target) (inst beq temp target)))) (t (if signed (inst slt temp y x) (inst sltu temp y x)) (if not-p (inst beq temp target) (inst bne temp target)))) (inst nop));;; EQL/FIXNUM is funny because the first arg can be of any type, not just a;;; known fixnum.(define-conditional-vop eql (declare (ignore signed)) (when (integerp y) (inst li temp y) (setf y temp)) (if not-p (inst bne x y target) (inst beq x y target)) (inst nop));;; These versions specify a fixnum restriction on their first arg. We have;;; also generic-eql/fixnum VOPs which are the same, but have no restriction on;;; the first arg and a higher cost. The reason for doing this is to prevent;;; fixnum specific operations from being used on word integers, spuriously;;; consing the argument.;;;(define-vop (fast-eql/fixnum fast-conditional) (:args (x :scs (any-reg)) (y :scs (any-reg))) (:arg-types tagged-num tagged-num) (:note "inline fixnum comparison") (:translate eql) (:ignore temp) (:generator 3 (if not-p (inst bne x y target) (inst beq x y target)) (inst nop)));;;(define-vop (generic-eql/fixnum fast-eql/fixnum) (:args (x :scs (any-reg descriptor-reg)) (y :scs (any-reg))) (:arg-types * tagged-num) (:variant-cost 7))(define-vop (fast-eql-c/fixnum fast-conditional/fixnum) (:args (x :scs (any-reg))) (:arg-types tagged-num (:constant (signed-byte 14))) (:info target not-p y) (:translate eql) (:generator 2 (let ((y (cond ((eql y 0) zero-tn) (t (inst li temp (fixnumize y)) temp)))) (if not-p (inst bne x y target) (inst beq x y target)) (inst nop))));;;(define-vop (generic-eql-c/fixnum fast-eql-c/fixnum) (:args (x :scs (any-reg descriptor-reg))) (:arg-types * (:constant (signed-byte 14))) (:variant-cost 6));;;; 32-bit logical operations(define-vop (merge-bits) (:translate merge-bits) (:args (shift :scs (signed-reg unsigned-reg)) (prev :scs (unsigned-reg)) (next :scs (unsigned-reg))) (:arg-types tagged-num unsigned-num unsigned-num) (:temporary (:scs (unsigned-reg) :to (:result 0)) temp) (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res) (:results (result :scs (unsigned-reg))) (:result-types unsigned-num) (:policy :fast-safe) (:generator 4 (let ((done (gen-label))) (inst beq shift done) (inst srl res next shift) (inst subu temp zero-tn shift) (inst sll temp prev temp) (inst or res res temp) (emit-label done) (move result res))))(define-vop (shift-towards-someplace) (:policy :fast-safe) (:args (num :scs (unsigned-reg)) (amount :scs (signed-reg))) (:arg-types unsigned-num tagged-num) (:results (r :scs (unsigned-reg))) (:result-types unsigned-num))(define-vop (shift-towards-start shift-towards-someplace)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -