From ebf2239bc0f2e306ed98acaef232fce9c8f1d5d2 Mon Sep 17 00:00:00 2001 From: Christophe Rhodes Date: Thu, 4 Sep 2003 15:05:34 +0000 Subject: [PATCH] 0.8.3.35: Since we're playing with backends... ... add the x86 CMOV instruction ... and a (disabled by default) VOP that uses it for ASH No, it's not noticeably faster; why do you ask? *sigh* --- src/compiler/x86/arith.lisp | 34 ++++++++++++++++++++++++++++++++++ src/compiler/x86/insts.lisp | 22 ++++++++++++++++++++++ version.lisp-expr | 2 +- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/compiler/x86/arith.lisp b/src/compiler/x86/arith.lisp index 0675614..88c8122 100644 --- a/src/compiler/x86/arith.lisp +++ b/src/compiler/x86/arith.lisp @@ -788,6 +788,40 @@ (inst shl result :cl) DONE)) + +;;; FIXME: before making knowledge of this too public, it needs to be +;;; fixed so that it's actually _faster_ than the non-CMOV version; at +;;; least on my Celeron-XXX laptop, this version is marginally slower +;;; than the above version with branches. -- CSR, 2003-09-04 +(define-vop (fast-cmov-ash/unsigned=>unsigned) + (:translate ash) + (:policy :fast-safe) + (:args (number :scs (unsigned-reg) :target result) + (amount :scs (signed-reg) :target ecx)) + (:arg-types unsigned-num signed-num) + (:results (result :scs (unsigned-reg) :from (:argument 0))) + (:result-types unsigned-num) + (:temporary (:sc signed-reg :offset ecx-offset :from (:argument 1)) ecx) + (:temporary (:sc any-reg :from (:eval 0) :to (:eval 1)) zero) + (:note "inline ASH") + (:guard (member :cmov *backend-subfeatures*)) + (:generator 4 + (move result number) + (move ecx amount) + (inst or ecx ecx) + (inst jmp :ns positive) + (inst neg ecx) + (inst xor zero zero) + (inst shr result :cl) + (inst cmp ecx 31) + (inst cmov :nbe result zero) + (inst jmp done) + + POSITIVE + ;; The result-type ensures us that this shift will not overflow. + (inst shl result :cl) + + DONE)) ;;; Note: documentation for this function is wrong - rtfm (define-vop (signed-byte-32-len) diff --git a/src/compiler/x86/insts.lisp b/src/compiler/x86/insts.lisp index c64e761..59e7a7d 100644 --- a/src/compiler/x86/insts.lisp +++ b/src/compiler/x86/insts.lisp @@ -588,6 +588,16 @@ :type 'byte-reg/mem) (reg :field (byte 3 19) :value #b000)) +(sb!disassem:define-instruction-format (cond-move 24 + :default-printer + '('cmov cc :tab reg ", " reg/mem)) + (prefix :field (byte 8 0) :value #b00001111) + (op :field (byte 4 12) :value #b0100) + (cc :field (byte 4 8) :type 'condition-code) + (reg/mem :fields (list (byte 2 22) (byte 3 16)) + :type 'reg/mem) + (reg :field (byte 3 19) :type 'reg)) + (sb!disassem:define-instruction-format (enter-format 32 :default-printer '(:name :tab disp @@ -1784,6 +1794,18 @@ (emit-byte segment #b11100000) (emit-byte-displacement-backpatch segment target))) +;;;; conditional move +(define-instruction cmov (segment cond dst src) + (:printer cond-move ()) + (:emitter + (aver (register-p dst)) + (let ((size (matching-operand-size dst src))) + (aver (or (eq size :word) (eq size :dword))) + (maybe-emit-operand-size-prefix segment size)) + (emit-byte segment #b00001111) + (emit-byte segment (dpb (conditional-opcode cond) (byte 4 0) #b01000000)) + (emit-ea segment src (reg-tn-encoding dst)))) + ;;;; conditional byte set (define-instruction set (segment dst cond) diff --git a/version.lisp-expr b/version.lisp-expr index ef9aeea..b7b69a0 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"0.8.3.34" +"0.8.3.35" -- 1.7.10.4