master: Encode the remaining bmi1/2 instructions, movbe
stassats via Sbcl-commits <[email protected]> Wed, 29 Jul 2026 02:11:35 +0000
| Newsgroups | gmane.lisp.steel-bank.cvs |
|---|---|
| Message-ID | <[email protected]> |
The branch "master" has been updated in SBCL:
via 773469344bcb9da70284f722f0d1a414796dfa7e (commit)
from 76d957fcc77c2782f831a9d70dce383b7820b958 (commit)
- Log -----------------------------------------------------------------
commit 773469344bcb9da70284f722f0d1a414796dfa7e
Author: Stas Boukarev <[email protected]>
Date: Wed Jul 29 04:51:07 2026 +0300
Encode the remaining bmi1/2 instructions, movbe
---
src/compiler/x86-64/avx2-insts.lisp | 58 ++++++++++++++++++++++++++-----------
src/compiler/x86-64/insts.lisp | 35 ++++++++++++++++++++++
2 files changed, 76 insertions(+), 17 deletions(-)
diff --git a/src/compiler/x86-64/avx2-insts.lisp b/src/compiler/x86-64/avx2-insts.lisp
index a8d2334d4..74700ff60 100644
--- a/src/compiler/x86-64/avx2-insts.lisp
+++ b/src/compiler/x86-64/avx2-insts.lisp
@@ -381,7 +381,8 @@
(xmm-size thing))
(t
0)))
- (r (if (null reg)
+ (r (if (or (null reg)
+ (integerp reg))
0
(reg-7-p (reg-id reg))))
(x (cond ((and (ea-p thing)
@@ -1690,46 +1691,52 @@ REG is the source (encoded in ModR/M.r/m).
(emit-sse-inst-2byte segment dst src #xf3 #x38 #xf6
:operand-size size))))
-;;;; BMI2 instructions (VEX-encoded GPR operations)
+;;;; BMI1/2 instructions (VEX-encoded GPR operations)
;;;; All use VEX.LZ (L=0). W=1 for 64-bit, W=0 for 32-bit.
;;; Shifts with shift count in GPR (no flag side effects, not serialized on CL)
;;; SHRX/SHLX/SARX r64a, r/m64, r64b
;;; dst = reg field, src = r/m, count = vvvv
-(macrolet ((def (name prefix)
- `(define-instruction ,name (segment &prefix prefix dst src count)
- ,@(avx2-inst-printer-list 'vex-gpr prefix #xF7
+(macrolet ((def (name prefix opcode third-op-name)
+ `(define-instruction ,name (segment &prefix prefix dst src ,third-op-name)
+ ,@(avx2-inst-printer-list 'vex-gpr prefix opcode
+ :printer '(:name :tab reg ", " reg/mem ", " vvvv)
:nds t
:opcode-prefix #x0f38)
(:emitter
- (emit-avx2-inst segment src dst ,prefix #xF7
+ (emit-avx2-inst segment src dst ,prefix ,opcode
:opcode-prefix #x0f38
- :vvvv count
+ :vvvv ,third-op-name
:l 0
:w (ecase (pick-operand-size prefix dst src)
(:qword 1)
(:dword 0)))))))
- (def shrx #xF2)
- (def shlx #x66)
- (def sarx #xF3))
+ (def shrx #xF2 #xF7 count)
+ (def shlx #x66 #xF7 count)
+ (def sarx #xF3 #xF7 count)
+ (def bzhi nil #xF5 position)
+ (def bextr nil #xF7 control))
;;; PEXT/PDEP r64a, r64b, r/m64
;;; dst = reg field, src = vvvv, mask = r/m
-(macrolet ((def (name prefix)
- `(define-instruction ,name (segment &prefix prefix dst src mask)
- ,@(avx2-inst-printer-list 'vex-gpr prefix #xF5
+(macrolet ((def (name prefix opcode &optional (third-op-name 'src2)
+ printer)
+ `(define-instruction ,name (segment &prefix prefix dst src ,third-op-name)
+ ,@(avx2-inst-printer-list 'vex-gpr prefix opcode
:nds t
+ :printer printer
:opcode-prefix #x0f38)
(:emitter
- (emit-avx2-inst segment mask dst ,prefix #xF5
+ (emit-avx2-inst segment ,third-op-name dst ,prefix ,opcode
:opcode-prefix #x0f38
:vvvv src
:l 0
- :w (ecase (pick-operand-size prefix dst mask)
+ :w (ecase (pick-operand-size prefix dst src)
(:qword 1)
(:dword 0)))))))
- (def pext #xF3)
- (def pdep #xF2))
+ (def pext #xF3 #xF5 mask)
+ (def pdep #xF2 #xF5 mask)
+ (def andn nil #xF2))
;;; RORX r64a, r/m64, imm8
;;; dst = reg field, src = r/m, count = imm8, no vvvv
@@ -1746,4 +1753,21 @@ REG is the source (encoded in ModR/M.r/m).
. #.(avx2-inst-printer-list 'vex-gpr #xF2 #xF0
:opcode-prefix #x0f3a
:printer '(:name :tab reg ", " reg/mem)))
+(macrolet ((def (name reg)
+ `(define-instruction ,name (segment &prefix prefix dst src)
+ ,@(avx2-inst-printer-list 'vex-gpr nil #xF3
+ :opcode-prefix #x0f38
+ :more-fields `((reg ,reg))
+ :printer '(:name :tab vvvv ", " reg/mem))
+ (:emitter
+ (emit-avx2-inst segment src ,reg nil #xF3
+ :opcode-prefix #x0f38
+ :vvvv dst
+ :l 0
+ :w (ecase (pick-operand-size prefix dst src)
+ (:qword 1)
+ (:dword 0)))))))
+ (def blsr 1)
+ (def blsmsk 2)
+ (def blsi 3))
diff --git a/src/compiler/x86-64/insts.lisp b/src/compiler/x86-64/insts.lisp
index 465adb277..2ea66f9d9 100644
--- a/src/compiler/x86-64/insts.lisp
+++ b/src/compiler/x86-64/insts.lisp
@@ -1527,6 +1527,41 @@
(t
(error "bogus arguments to MOV: ~S ~S" dst src))))
+(define-instruction-format (movbe 32
+ :default-printer
+ `(:name :tab reg ", " reg/mem))
+ (prefix :field (byte 16 0) :value #x380F)
+ (op :field (byte 8 16))
+ (reg/mem :fields (list (byte 2 30) (byte 3 24))
+ :type 'reg/mem)
+ (reg :field (byte 3 27) :type 'reg))
+
+(define-instruction movbe (segment &prefix prefix dst src)
+ (:printer movbe ((op #xF0))
+ '(:name :tab reg ", " reg/mem))
+ (:printer movbe ((op #xF1))
+ '(:name :tab reg/mem ", " reg))
+ (:emitter
+ (let* ((size (pick-operand-size prefix dst src))
+ (src (sized-thing src size))
+ (dst (sized-thing dst size)))
+ (when (eq size :byte)
+ (error "MOVBE does not support 8-bit operands: ~S ~S" dst src))
+ (cond ((and (gpr-p dst) (not (gpr-p src)))
+ (emit-prefixes segment src dst size)
+ (emit-byte segment #x0F)
+ (emit-byte segment #x38)
+ (emit-byte segment #xF0)
+ (emit-ea segment src dst))
+ ((and (gpr-p src) (not (gpr-p dst)))
+ (emit-prefixes segment dst src size)
+ (emit-byte segment #x0F)
+ (emit-byte segment #x38)
+ (emit-byte segment #xF1)
+ (emit-ea segment dst src))
+ (t
+ (error "Invalid arguments to MOVBE: ~S ~S (requires one GPR and one memory operand)" dst src))))))
+
;;; MOVABS is not a mnemonic according to the CPU vendors, but every (dis)assembler
;;; in popular use chooses this mnemonic instead of MOV with an 8-byte operand.
;;; (Even with Intel-compatible syntax, LLVM produces MOVABS).
-----------------------------------------------------------------------
hooks/post-receive
--
SBCL