diff options
Diffstat (limited to 'src/common/asm.c')
-rw-r--r-- | src/common/asm.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/common/asm.c b/src/common/asm.c index 692256f..645bd6a 100644 --- a/src/common/asm.c +++ b/src/common/asm.c @@ -36,6 +36,34 @@ static const unsigned int _bval[16] = { }; +/** + * Nombre de bits à 1 dans un octet. + * + * python3 -c "print(', '.join([ str(bin(n).count('1')) for n in range(256) ]))" | sed -re 's/(.{48})/\1\n/g' | sed 's/ $//' + */ + +static const unsigned int _bcount[256] = { + + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 + +}; + + /****************************************************************************** * * @@ -111,3 +139,73 @@ bool msb_64(uint64_t v, unsigned int *p) return true; } + + +/****************************************************************************** +* * +* Paramètres : v = valeur quelconque sur 32 bits. * +* * +* Description : Détermine le nombre de bits à 1 dans une valeur de 32 bits. * +* * +* Retour : Nombre de bits à 1. * +* * +* Remarques : - * +* * +******************************************************************************/ + +unsigned int popcount_32(uint32_t v) +{ + unsigned int result; /* Valeur à retourner */ + + /** + * Il existe de nombreuses méthodes pour obtenir le résultat attendu + * sans recourir à des extensions GCC ou à des instructions d'assembleur : + * + * - http://gurmeet.net/puzzles/fast-bit-counting-routines/ + * + * On chosit un bon compromis entre efficacité et lecture. + * + */ + + result = _bcount[v & 0xff] + + _bcount[(v >> 8) & 0xff] + + _bcount[(v >> 16) & 0xff] + + _bcount[(v >> 24) & 0xff]; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : v = valeur quelconque sur 64 bits. * +* * +* Description : Détermine le nombre de bits à 1 dans une valeur de 64 bits. * +* * +* Retour : Nombre de bits à 1. * +* * +* Remarques : - * +* * +******************************************************************************/ + +unsigned int popcount_64(uint64_t v) +{ + unsigned int result; /* Valeur à retourner */ + + /** + * Cf. popcount_32(). + */ + + result = _bcount[v & 0xff] + + _bcount[(v >> 8) & 0xff] + + _bcount[(v >> 16) & 0xff] + + _bcount[(v >> 24) & 0xff] + + _bcount[(v >> 32) & 0xff] + + _bcount[(v >> 40) & 0xff] + + _bcount[(v >> 48) & 0xff] + + _bcount[(v >> 56) & 0xff]; + + return result; + +} |