Introduction
These extensions add bit operations on the general registers that would otherwise take several instructions: counting bits, isolating the lowest set bit, extracting a field, gathering or scattering bits by a mask, and shifts and multiplies that leave the flags alone. All of them work on 32-bit or 64-bit operands; POPCNT, LZCNT and TZCNT also on 16-bit ones. Each set has its own CPUID bit:
| Set | Instructions | First processors | CPUID |
|---|---|---|---|
| POPCNT | popcnt | AMD Barcelona, 2007; Intel Nehalem, 2008 | leaf 1, ECX bit 23 |
| LZCNT (AMD’s ABM) | lzcnt | AMD Barcelona, 2007; Intel Haswell, 2013 | leaf 8000_0001h, ECX bit 5 |
| BMI1 | andn, bextr, blsi, blsmsk, blsr, tzcnt | AMD Piledriver, 2012; Intel Haswell, 2013 | leaf 7, EBX bit 3 |
| BMI2 | bzhi, mulx, pdep, pext, rorx, sarx, shlx, shrx | Intel Haswell, 2013 | leaf 7, EBX bit 8 |
| TBM (AMD) | bextr with an immediate, blcfill, blci, blcic, blcmsk, blcs, blsfill, blsic, t1mskc, tzmsk | AMD Piledriver, 2012; dropped from Zen | leaf 8000_0001h, ECX bit 21 |
| ADX | adcx, adox | Intel Broadwell, 2014 | leaf 7, EBX bit 19 |
AMD’s ABM (advanced bit manipulation) was LZCNT and POPCNT together. BMI1 and BMI2
are encoded with a VEX prefix, though they work on general registers, and TBM with AMD’s
XOP prefix. Intel’s APX gives most of them EVEX forms in 64-bit mode, which can use
R16 to R31, and in which those that set flags may leave them alone
({nf}). The older bit instructions (BT, BSF, BSR, the shifts) are on the
Logic, shifts and bits page.
The instructions
In the forms, r32a is the register in ModRM.reg, r32b the
register in VEX.vvvv, and r/m32 ModRM.r/m; the 64-bit forms take
W1, in 64-bit mode only. In the encodings, VEX.LZ means
VEX.L = 0. The TBM encodings are written as AMD’s manual writes them: the XOP prefix
8F, then R, X, B and the map, then W, vvvv (dest where it
names the destination), L and pp.
Counting bits
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
popcnt | r16/32/64, r/m16/32/64 | F3 0F B8 /rEVEX.MAP4 88 /r (APX, with NF) | Counts the 1 bits of the source. ZF is set if the source is 0; OF, SF, AF, CF and PF are cleared. | POPCNT (AMD Barcelona, 2007; Intel Nehalem, 2008) |
lzcnt | r16/32/64, r/m16/32/64 | F3 0F BD /rEVEX.MAP4 F5 /r (APX, with NF) | Counts the leading 0 bits, from the top. A source of 0 gives the operand size and sets CF; a result of 0 sets ZF. A processor without LZCNT ignores the F3 and runs bsr, which gives a different answer. | LZCNT (AMD Barcelona, 2007; Intel Haswell, 2013) |
tzcnt | r16/32/64, r/m16/32/64 | F3 0F BC /rEVEX.MAP4 F4 /r (APX, with NF) | Counts the trailing 0 bits, from bit 0. A source of 0 gives the operand size and sets CF; a result of 0 sets ZF. On older processors it runs as bsf, which gives the same index for any source other than 0. | BMI1 (AMD Piledriver, 2012; Intel Haswell, 2013) |
BMI1
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
andn | r32a, r32b, r/m32r64a, r64b, r/m64 | VEX.LZ.0F38.W0 F2 /rVEX.LZ.0F38.W1 F2 /r | r32a = NOT r32b AND r/m32. Sets SF and ZF; clears OF and CF. | BMI1 (AMD Piledriver, 2012; Intel Haswell, 2013) |
bextr | r32a, r/m32, r32br64a, r/m64, r64b(TBM) r32/64, r/m32/64, imm32 | VEX.LZ.0F38.W0 F7 /rVEX.LZ.0F38.W1 F7 /r8F RXB.0A W.1111.0.00 10 /r id | Extracts a bit field: the start bit is bits 7–0 of the control, and the length bits 15–8. The BMI1 form takes the control from r32b, the TBM form from the immediate. The field goes to the low bits of the destination, zero-filled. ZF is set if the result is 0; CF and OF are cleared. | BMI1 (AMD Piledriver, 2012; Intel Haswell, 2013); the immediate form TBM (AMD Piledriver, 2012) |
blsi | r32b, r/m32r64b, r/m64 | VEX.LZ.0F38.W0 F3 /3VEX.LZ.0F38.W1 F3 /3 | Isolates the lowest set bit: x AND −x. The destination is VEX.vvvv. CF is set if the source is not 0. | BMI1 (AMD Piledriver, 2012; Intel Haswell, 2013) |
blsmsk | r32b, r/m32r64b, r/m64 | VEX.LZ.0F38.W0 F3 /2VEX.LZ.0F38.W1 F3 /2 | A mask up to and including the lowest set bit: x XOR (x − 1). CF is set if the source is 0. | BMI1 (AMD Piledriver, 2012; Intel Haswell, 2013) |
blsr | r32b, r/m32r64b, r/m64 | VEX.LZ.0F38.W0 F3 /1VEX.LZ.0F38.W1 F3 /1 | Clears the lowest set bit: x AND (x − 1). CF is set if the source is 0; ZF if the result is. | BMI1 (AMD Piledriver, 2012; Intel Haswell, 2013) |
BMI2
Apart from BZHI, these change no flags, which lets them sit between an instruction that sets the flags and one that reads them.
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
bzhi | r32a, r/m32, r32br64a, r/m64, r64b | VEX.LZ.0F38.W0 F5 /rVEX.LZ.0F38.W1 F5 /r | Zeroes the high bits: copies r/m32 with every bit from position n up cleared, n being bits 7–0 of r32b. CF is set if n is beyond the operand; SF and ZF from the result. | BMI2 (Intel Haswell, 2013) |
mulx | r32a, r32b, r/m32r64a, r64b, r/m64 | VEX.LZ.F2.0F38.W0 F6 /rVEX.LZ.F2.0F38.W1 F6 /r | Unsigned multiply of EDX or RDX by r/m: the high half of the product goes to r32a, the low half to r32b. No flags, which suits long multiplications mixed with ADCX and ADOX. | BMI2 (Intel Haswell, 2013) |
pdep | r32a, r32b, r/m32r64a, r64b, r/m64 | VEX.LZ.F2.0F38.W0 F5 /rVEX.LZ.F2.0F38.W1 F5 /r | Parallel deposit: takes the low bits of r32b in turn and puts them at the positions of the 1 bits of the mask in r/m32; the other bits are 0. | BMI2 (Intel Haswell, 2013) |
pext | r32a, r32b, r/m32r64a, r64b, r/m64 | VEX.LZ.F3.0F38.W0 F5 /rVEX.LZ.F3.0F38.W1 F5 /r | Parallel extract: takes the bits of r32b at the positions of the 1 bits of the mask in r/m32 and packs them into the low bits. | BMI2 (Intel Haswell, 2013) |
rorx | r32, r/m32, imm8r64, r/m64, imm8 | VEX.LZ.F2.0F3A.W0 F0 /r ibVEX.LZ.F2.0F3A.W1 F0 /r ib | Rotates right by the immediate into another register, without the flags. | BMI2 (Intel Haswell, 2013) |
sarx | r32a, r/m32, r32br64a, r/m64, r64b | VEX.LZ.F3.0F38.W0 F7 /rVEX.LZ.F3.0F38.W1 F7 /r | Arithmetic shift right of r/m by the count in r32b (masked to 5 or 6 bits), into r32a, without the flags. | BMI2 (Intel Haswell, 2013) |
shlx | r32a, r/m32, r32br64a, r/m64, r64b | VEX.LZ.66.0F38.W0 F7 /rVEX.LZ.66.0F38.W1 F7 /r | Shift left, likewise. | BMI2 (Intel Haswell, 2013) |
shrx | r32a, r/m32, r32br64a, r/m64, r64b | VEX.LZ.F2.0F38.W0 F7 /rVEX.LZ.F2.0F38.W1 F7 /r | Logical shift right, likewise. | BMI2 (Intel Haswell, 2013) |
TBM (AMD)
AMD’s trailing bit manipulation instructions each make a mask or a fill from the lowest set or clear bit of the source, in one step. The destination is in XOP.vvvv, the source in ModRM.r/m, and W picks 32 or 64 bits. In each, x is the source. They set ZF and SF from the result, and CF as AMD’s manual gives for each; OF is cleared.
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
blcfill | r32/64, r/m32/64 | 8F RXB.09 W.dest.0.00 01 /1 | Fills from the lowest clear bit: x AND (x + 1). | TBM (AMD Piledriver, 2012) |
blsfill | r32/64, r/m32/64 | 8F RXB.09 W.dest.0.00 01 /2 | Fills from the lowest set bit: x OR (x − 1). | TBM (AMD Piledriver, 2012) |
blcs | r32/64, r/m32/64 | 8F RXB.09 W.dest.0.00 01 /3 | Sets the lowest clear bit: x OR (x + 1). | TBM (AMD Piledriver, 2012) |
tzmsk | r32/64, r/m32/64 | 8F RXB.09 W.dest.0.00 01 /4 | A mask of the trailing zeros: NOT x AND (x − 1). | TBM (AMD Piledriver, 2012) |
blcic | r32/64, r/m32/64 | 8F RXB.09 W.dest.0.00 01 /5 | Isolates the lowest clear bit: NOT x AND (x + 1). | TBM (AMD Piledriver, 2012) |
blsic | r32/64, r/m32/64 | 8F RXB.09 W.dest.0.00 01 /6 | Isolates the lowest set bit and inverts: NOT x OR (x − 1). | TBM (AMD Piledriver, 2012) |
t1mskc | r32/64, r/m32/64 | 8F RXB.09 W.dest.0.00 01 /7 | The inverse mask of the trailing ones: NOT x OR (x + 1). | TBM (AMD Piledriver, 2012) |
blcmsk | r32/64, r/m32/64 | 8F RXB.09 W.dest.0.00 02 /1 | A mask up to the lowest clear bit: x XOR (x + 1). | TBM (AMD Piledriver, 2012) |
blci | r32/64, r/m32/64 | 8F RXB.09 W.dest.0.00 02 /6 | Isolates the lowest clear bit, all other bits set: x OR NOT (x + 1). | TBM (AMD Piledriver, 2012) |
ADX
ADCX and ADOX are add-with-carry instructions that use different flags as their carry, so that two chains of additions can run interleaved, as in big-number multiplication with MULX.
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
adcx | r32/64, r/m32/64 | 66 0F 38 F6 /rEVEX.MAP4.66 66 /r (APX, with ND) | Unsigned add with carry, using CF as the carry in and out. No other flag changes. | ADX (Intel Broadwell, 2014) |
adox | r32/64, r/m32/64 | F3 0F 38 F6 /rEVEX.MAP4.F3 66 /r (APX, with ND) | Unsigned add with carry, using OF as the carry in and out. No other flag changes. | ADX (Intel Broadwell, 2014) |
Notes
- APX forms. ANDN, BEXTR, BLSI, BLSMSK, BLSR, BZHI, MULX, PDEP, PEXT,
SARX, SHLX and SHRX have EVEX forms in map 2 and RORX in map 3, at the same opcodes as
their VEX forms. ANDN, BEXTR, BLSI, BLSMSK, BLSR and BZHI take NF there. LLVM shows
them without
{evex}. See APX’s EVEX fields. - VEX.L must be 0. With L = 1 the disassembler shows the bytes as invalid, as LLVM does.
- Outside 64-bit mode VEX.W is ignored here and the operand size is 32 bits.
Links
Reference
- Intel 64 and IA-32 Architectures Software Developer’s Manuals – Intel’s manuals; volume 2 describes each instruction
- AMD64 Architecture Programmer’s Manual, Volume 3 – AMD’s reference to the general-purpose instructions, including TBM and ABM
- Intel Advanced Performance Extensions (Intel APX) – Intel’s introduction to APX, with a link to its architecture specification
- x86 and amd64 instruction reference – Félix Cloutier’s web copy of the instruction pages of Intel’s manual