# Jeux d'instructions de manipulation de bits

Les jeux d’instructions de manipulation de bits (Bit Manipulation Instruction sets, BMI) sont des extensions de l’architecture de jeu d'instructions x86 pour les microprocesseurs d’Intel et d’AMD. Le but de ces jeux d’instructions est d’améliorer la vitesse de manipulation de bits. Toutes les instructions de ces ensembles sont non-SIMD et ne fonctionnent que sur des registres à usage général.
Il existe deux ensembles publiés par Intel : BMI (maintenant appelé BMI1) et BMI2 ; ils ont tous deux été introduits avec la microarchitecture Haswell avec les fonctionnalités d’appariement BMI1 offertes par le jeu d’instructions ABM d’AMD et BMI2 les étendant. Deux autres ensembles ont été publiés par AMD : ABM (Advanced Bit Manipulation, qui est également un sous-ensemble de SSE4a implémenté par Intel dans le cadre de SSE4.2 et de BMI1), et TBM (Trailing Bit Manipulation, une extension introduite avec les processeurs basés sur Piledriver en tant qu’extension de BMI1, mais abandonnée ensuite dans les processeurs basés sur Zen).

## ABM (Advanced Bit Manipulation)

AMD a été le premier à introduire les instructions qui forment maintenant le BMI1 d’Intel dans le cadre de son jeu d’instructions ABM (Advanced Bit Manipulation), puis a ajouté plus tard la prise en charge des nouvelles instructions BMI2 d’Intel. AMD annonce aujourd’hui la disponibilité de ces fonctionnalités via les flags CPU BMI1 et BMI2 d’Intel et demande aux programmeurs de les choisir en conséquence.
Tandis qu'Intel considère POPCNT comme appartenant à SSE4.2 et LZCNT appartenant à BMI1, Intel et AMD indiquent tous deux de la présence de ces deux instructions individuellement. POPCNT a un drapeau CPUID de même nom et Intel et AMD utilisent le drapeau AMD ABM pour indiquer le support de LZCNT (puisque LZCNT combiné avec BMI1 et BMI2 complète le jeu d'instructions ABM étendu)$^,$.
| Code | Instruction | Description |
| F3 0F B8 /r | POPCNT | Comptage de population |
| F3 0F BD /r | LZCNT | Compte le nombre de bits à zéro à gauche (en tête) |
LZCNT est liée à l'instruction Bit Scan Reverse (BSR), mais arme les drapeaux ZF (si le résultat vaut zéro) et CF (si la source vaut zéro) plutôt que d'armer le drapeau ZF (si la source vaut zéro). Il produit également un résultat défini (la taille de l'opérande source en bits) si l'opérande source vaut zéro. Pour un argument différent de zéro, la somme des résultats de LZCNT et de BSR est la taille en bits de l'argument moins 1 (par exemple, si l'argument 32 bits est 0x000f0000, LZCNT donne 12 et BSR donne 19, la somme vaut 31).
Le codage de LZCNT est tel que si ABM n'est pas supporté, alors l'instruction BSR est exécutée à la place$^{:227}$.

## BMI1 (Bit Manipulation Instruction Set 1)

Les instructions ci-dessous sont celles activées par le bit BMI dans le CPUID. Intel considère officiellement LZCNT comme partie de BMI, mais indique le support de LZCNT à l'aide du flag CPUID ABM. BMI1 est disponible sur les processeurs AMD Jaguar, Piledriver et plus récents, et sur les processeurs Intel Haswell et plus récents.
| Code | Instruction | Description | Expression C équivalente$^,$$^,$ |
| VEX.LZ.0F38 F2 /r | ANDN | (NON A) ET B logique | ~x & y |
| VEX.LZ.0F38 F7 /r | BEXTR | Extraction d'un champ de bits (avec registre) | (src >> start) & ((1 << len) - 1) |
| VEX.LZ.0F38 F3 /3 | BLSI | Extrait le bit isolé à 1 de poids le plus faible | x & -x |
| VEX.LZ.0F38 F3 /2 | BLSMSK | Obtient le masque jusqu'au bit à 1 de poids le plus faible | x ^ (x - 1) |
| VEX.LZ.0F38 F3 /1 | BLSR | Met à zéro le bit à 1 de poids le plus faible | x & (x - 1) |
| F3 0F BC /r | TZCNT | Compte le nombre de bits à zéro en queue (à droite) | |
L'instruction TZCNT est presque identique à l'instruction Bit Scan Forward (BSF), mais arme les drapeaux ZF (si le résultat vaut zéro) et CF (si la source vaut zéro) plutôt que d'armer le drapeau ZF (si la source vaut zéro). Pour un argument différent de zéro, les résultats de TZCNT et de BSF sont identiques.
Comme avec LZCNT, le codage de TZCNT est tel que si BMI1 n'est pas supporté, alors l'instruction BSF est exécutée à la place$^{:352}$.

## BMI2 (Bit Manipulation Instruction Set 2)

Intel a introduit BMI2 en même temps que BMI1 dans sa gamme de processeurs Haswell. Seul AMD a produit des processeurs supportant BMI1 mais pas BMI 2 ; BMI2 est supporté par l'architecture AMD Excavator et plus récente.
| Codage | Instruction | Description |
| VEX.LZ.0F38 F5 /r | BZHI | Mise à zéro des bits les plus élevés à partir d'une position de bit spécifiée [src & (1 << inx)-1] |
| VEX.LZ.F2.0F38 F6 /r | MULX | Multiplication non signée sans affecter les drapeaux, avec des registres de destination quelconques |
| VEX.LZ.F2.0F38 F5 /r | PDEP | Dépôt de bits en parallèle |
| VEX.LZ.F3.0F38 F5 /r | PEXT | Extraction de bits en parallèle |
| VEX.LZ.F2.0F3A F0 /r ib | RORX | Rotation logique vers la droite sans affecter les drapeaux |
| VEX.LZ.F3.0F38 F7 /r | SARX | Décalage arithmétique vers la droite sans affecter les drapeaux |
| VEX.LZ.F2.0F38 F7 /r | SHRX | Décalage logique vers la droite sans affecter les drapeaux |
| VEX.LZ.66.0F38 F7 /r | SHLX | Décalage logique vers la gauche sans affecter les drapeaux |

### Dépôt et extraction de bits

Les instructions PDEP et PEXT sont de nouvelles instructions généralisées de compression et d’expansion au niveau du bit. Elles prennent deux entrées : l’un est une source, et l’autre est un sélecteur. Le sélecteur est une image bitmap qui sélectionne les bits qui doivent être compressés ou décompressés. PEXT copie les bits sélectionnés de la source vers les bits de poids faible contigus de la destination ; les bits de destination d’ordre supérieur sont effacés. PDEP fait l’inverse pour les bits sélectionnés : les bits de poids faible contigus sont copiés sur les bits sélectionnés de la destination ; les autres bits de destination sont effacés. Cela peut être utilisé pour extraire n’importe quel champ de bits de l’entrée, et même effectuer beaucoup de brassage au niveau des bits, ce qui aurait été coûteux auparavant. Bien que ces instructions soient similaires aux instructions SIMD de gather-scatter (en) (collecte-diffusion) au niveau des bits, les instructions PDEP et PEXT (comme le reste des jeux d’instructions BMI) fonctionnent sur des registres à usage général.
Les instructions sont disponibles en versions 32 bits et 64 bits. Voici un exemple d’utilisation d’une source et d’un sélecteur arbitraires en mode 32 bits :
| Instruction | Masque du sélecteur | Source | Destination |
| PEXT | 0xff00fff0 | 0x12345678 | 0x00012567 |
| PDEP | 0xff00fff0 | 0x00012567 | 0x12005670 |
Les processeurs AMD avant Zen 3 qui implémentent PDEP et PEXT le font en microcode, avec une latence de 18 cycles contre 3 cycles sur Zen 3. Par conséquent, il est souvent plus rapide d'utiliser d'autres instructions sur ces processeurs.

## TBM (Trailing Bit Manipulation)

TBM est constitué d'instructions complémentaires au jeu d'instructions initié par BMI1 ; leur nature complémentaire signifie qu'elles n'ont pas nécessairement besoin d'être utilisées directement mais qu'elles peuvent être générées par un compilateur optimisé si elles sont supportées. AMD a introduit TBM en même temps que BMI1 dans sa gamme de processeurs Piledriver ; les processeurs AMD suivants Jaguar et Zen ne supportent pas TBM. Aucun processeur Intel (au moins jusqu'à Alder Lake) ne supporte TBM.
| Codage | Instruction | Description | Expression C équivalente$^,$ |
| XOP.LZ.0A 10 /r id | BEXTR | Extraire un champ de bits (avec immédiat) | (src >> start) & ((1 << len) - 1) |
| XOP.LZ.09 01 /1 | BLCFILL | Remplir à partir du bit à zéro de poids le plus faible | x & (x + 1) |
| XOP.LZ.09 02 /6 | BLCI | Isoler le bit à zéro de poids le plus faible | x | ~(x + 1) |
| XOP.LZ.09 01 /5 | BLCIC | Isoler le bit à zéro de poids le plus faible et calculer le complément | ~x & (x + 1) |
| XOP.LZ.09 02 /1 | BLCMSK | Masque à partir du bit à zéro de poids le plus faible | x ^ (x + 1) |
| XOP.LZ.09 01 /3 | BLCS | Mettre à 1 le bit de poids le plus faible | x | (x + 1) |
| XOP.LZ.09 01 /2 | BLSFILL | Remplir à partir du bit à 1 de poids le plus faible | x | (x - 1) |
| XOP.LZ.09 01 /6 | BLSIC | Isoler le bit à 1 de poids le plus faible et calculer le complément | ~x | (x - 1) |
| XOP.LZ.09 01 /7 | T1MSKC | Masque inverse pour les zéros en queue (à droite) | ~x | (x + 1) |
| XOP.LZ.09 01 /4 | TZMSK | Masque pour les zéros en queue (à droite) | ~x & (x - 1) |

## CPU supportant ces instructions

* Intel
** Processeurs Nehalem et plus récents (comme Sandy Bridge, Ivy Bridge) (support de POPCNT)
** Processeurs Silvermont (support de POPCNT)
** Processeurs Haswell et plus récents (Skylake, Broadwell, Skylake) (support d'ABM, de BMI1 et de BMI2)
* AMD
** Processeurs basés sur K10 (support d'ABM)
** Processeurs à faible consommation "Cat"
*** Processeurs basés sur Bobcat (support d'ABM)
*** Processeurs basés sur Jaguar et plus récents (support d'ABM et de BMI1)
*** Processeurs basés sur Puma et plus récents (support d'ABM et de BMI1)
** Processeurs "Équipement Lourd"
*** Processeurs basés sur Bulldozer (support d'ABM)
*** Processeurs basés sur Piledriver (support d'ABM, de BMI1 et de TBM)
*** Processeurs basés sur Steamroller (support d' ABM, de BMI1 et de TBM)
*** Processeurs basés sur Excavator et plus récents (support d'ABM, de BMI1, de BMI2 et de TBM ; PEXT et PDEP microcodés)
** Processeurs basés sur Zen, Zen+ et Zen 2 (support d'ABM, de BMI1 et de BMI2 ; PEXT et PDEP microcodés)
** Processeurs Zen 3 et plus récents (support d'ABM, de BMI1 et de BMI2 ; implémentation entièrement hardware)
On notera que le support des extensions d'instructions signifie que le processeur est capable d'exécuter les instructions supportées dans un objectif de compatibilité logicielle. Le processeur peut très bien ne pas très efficace en faisant cela. Par exemple, les processeurs Excavator jusqu'à Zen 2 implémentent les instructions PEXT et PDEP à l'aide de microcode, ce qui fait que les instructions s'exécutent de façon beaucoup plus lente que le même comportement reproduit avec d'autres instructions (Une méthode logicielle appelée "zp7" est, en fait, plus rapide sur ces machines). Pour une performance optimale, il est recommandé aux développeurs de compilateurs de choisir d'utiliser les instructions individuelles dans les extensions sur la base de profils de performance spécifiques à l'architecture plutôt que sur la disponibilité de l'extension.