[patch] Two Intel ADX instructions

Robert Smith <[email protected]> Sun, 1 Mar 2026 14:09:04 -0500
Newsgroups gmane.lisp.steel-bank.devel
Message-ID <CAPbE8xAS_atXbYq4CY8d0eyU2UE+72udwjpwGZ3s=p0A-mNoGQ@mail.gmail.com>
Hello SBCL friends:

Attached is a patch to add ADCX and ADOX to SBCL's assembler. It
doesn't change any VOPs. It's a very small patch, but I'm not sure if
I got a few things right. Some points:

- The ADX extension isn't supported by all processors. Support began
on AMD Ryzen and Intel Broadwell (both ~10 years ago, plus or minus).
Since this is "recent", I decided to put these instruction definitions
next to their closest cousin, MULX, in the AVX2 file. (Technically
MULX is from the BMI2, too.)

- There is a CPUID way to determine support, but I felt getting into
the weeds of config and build for this granular addition was too much,
so I instead rely on AVX2 "implying" ADX.

- The tests are just a couple smoke tests, nothing too serious.

- I'm not an expert at x86 instruction encodings, so I did a little
bit of mimicry + referencing section 10.5 of [1].

- I've tested these instructions in an "actual" application that uses
these paths billions of times in a tedious arithmetic calculation with
verified intermediate and final results.

This patch allows me to write faster code for extremely high-precision
arithmetic beyond SBCL BIGNUM and GMP, specifically for add-mul-carry
chains that occur in large integer multiplication and a few other
places. While it's a welcome improvement in many regards, it's not
critical, so I will not be offended in the slightest if this patch is
turned away. :)

Robert

[1]
https://web.archive.org/web/20130929035331/http://download-software.intel.com/sites/default/files/319433-015.pdf

_______________________________________________
Sbcl-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sbcl-devel
0001-Add-ADCX-and-ADOX-instruction-definitions.patch (application/x-patch, 2.4 KB)
From 2555e1e4b6fa7a891b8359e49ea8a2389fe710e7 Mon Sep 17 00:00:00 2001
From: Robert Smith <[email protected]>
Date: Sun, 1 Mar 2026 17:39:43 +0000
Subject: [PATCH] Add ADCX and ADOX instruction definitions

---
 src/compiler/x86-64/avx2-insts.lisp | 18 ++++++++++++++++++
 tests/assembler.pure.lisp           | 12 ++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/src/compiler/x86-64/avx2-insts.lisp b/src/compiler/x86-64/avx2-insts.lisp
index c2b41363b..99256691c 100644
--- a/src/compiler/x86-64/avx2-insts.lisp
+++ b/src/compiler/x86-64/avx2-insts.lisp
@@ -1271,3 +1271,21 @@
   . #.(avx2-inst-printer-list 'vex-gpr #xF2 #xF6
                               :nds t
                               :opcode-prefix #x0f38))
+
+(define-instruction adcx (segment &prefix prefix dst src)
+  (:printer ext-2byte-prefix-reg-reg/mem
+            ((prefix #x66) (op1 #x38) (op2 #xf6)))
+  (:emitter
+   (let ((size (pick-operand-size prefix dst src)))
+     (aver (memq size '(:dword :qword)))
+     (emit-sse-inst-2byte segment dst src #x66 #x38 #xf6
+                          :operand-size size))))
+
+(define-instruction adox (segment &prefix prefix dst src)
+  (:printer ext-2byte-prefix-reg-reg/mem
+            ((prefix #xf3) (op1 #x38) (op2 #xf6)))
+  (:emitter
+   (let ((size (pick-operand-size prefix dst src)))
+     (aver (memq size '(:dword :qword)))
+     (emit-sse-inst-2byte segment dst src #xf3 #x38 #xf6
+                          :operand-size size))))
diff --git a/tests/assembler.pure.lisp b/tests/assembler.pure.lisp
index d73e496af..2177952ea 100644
--- a/tests/assembler.pure.lisp
+++ b/tests/assembler.pure.lisp
@@ -107,6 +107,18 @@
   (test-assemble `(crc32 :qword ,r9-tn ,(ea r14-tn r15-tn))
                  "F24F0F38F10C3E   CRC32 R9, QWORD PTR [R14+R15]"))
 
+(test-util:with-test (:name :assemble-adcx-adox :skipped-on (not :x86-64))
+  ;; ADCX: 66 [REX.W] 0F 38 F6 ModRM
+  (test-assemble `(adcx ,eax ,ebx)
+                 "660F38F6C3       ADCX EAX, EBX")
+  (test-assemble `(adcx ,rax-tn ,rbx-tn)
+                 "66480F38F6C3     ADCX RAX, RBX")
+  ;; ADOX: F3 [REX.W] 0F 38 F6 ModRM
+  (test-assemble `(adox ,eax ,ebx)
+                 "F30F38F6C3       ADOX EAX, EBX")
+  (test-assemble `(adox ,rax-tn ,rbx-tn)
+                 "F3480F38F6C3     ADOX RAX, RBX"))
+
 (test-util:with-test (:name :assemble-unsigned-qword-imm-to-mem :skipped-on (not :x86-64))
   ;; unsigned bits cast as signed bits
   (let ((const #xffffffff801234BB))
-- 
2.43.0