diff --git a/README.adoc b/README.adoc index 1890029..c968556 100644 --- a/README.adoc +++ b/README.adoc @@ -12427,6 +12427,9 @@ Do a BT and then swap the value of the tested bit. * link:userland/arch/x86_64/setcc.S[SETcc] + Set a a byte of a register to 0 or 1 depending on the cc condition. +* link:userland/arch/x86_64/popcnt.S[POPCNT] ++ +Count the number of 1 bits. * link:userland/arch/x86_64/test.S[TEST] + Like <> but does AND instead of SUB: diff --git a/userland/arch/x86_64/popcnt.S b/userland/arch/x86_64/popcnt.S new file mode 100644 index 0000000..dc0da8a --- /dev/null +++ b/userland/arch/x86_64/popcnt.S @@ -0,0 +1,37 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#x86-bit-and-byte-instructions */ + +#include + +LKMC_PROLOGUE + mov $0, %rbx + popcnt %rbx, %rax + LKMC_ASSERT_EQ(%rax, $0) + + mov $1, %rbx + popcnt %rbx, %rax + LKMC_ASSERT_EQ(%rax, $1) + + mov $2, %rbx + popcnt %rbx, %rax + LKMC_ASSERT_EQ(%rax, $1) + + mov $3, %rbx + popcnt %rbx, %rax + LKMC_ASSERT_EQ(%rax, $2) + + mov $4, %rbx + popcnt %rbx, %rax + LKMC_ASSERT_EQ(%rax, $1) + + mov $5, %rbx + popcnt %rbx, %rax + LKMC_ASSERT_EQ(%rax, $2) + + mov $6, %rbx + popcnt %rbx, %rax + LKMC_ASSERT_EQ(%rax, $2) + + mov $7, %rbx + popcnt %rbx, %rax + LKMC_ASSERT_EQ(%rax, $3) +LKMC_EPILOGUE