I am looking into using the PDEP/PEXT machine instructions as part of Nim proc:s and it seems to me that the asm keyword requires that you somehow know which registers contains which variable.
So I am thinking using the intrinsic C functions like: unsigned __int64 _pext_u64(unsigned __int64 src, unsigned __int64 mask); through the foreign function interface makes more sense.
Is this right or am I missing something?
you somehow know which registers contains which variable.
You can use the backticks to get existing variables, see the docs at https://nim-lang.org/docs/manual.html#statements-and-expressions-assembler-statement
I am looking into using the PDEP/PEXT machine instructions as part of Nim proc:s and it seems to me that the asm keyword requires that you somehow know which registers contains which variable.
No you can use GCC/Clang extended ASM.
func add256_asm(a: var BigInt[256], b: BigInt[256]) {.noinline.}=
var tmp: uint64
when defined(gcc):
asm """
movq 0+%[b], %[tmp]
addq %[tmp], 0+%[a]
movq 8+%[b], %[tmp]
adcq %[tmp], 8+%[a]
movq 16+%[b], %[tmp]
adcq %[tmp], 16+%[a]
movq 24+%[b], %[tmp]
adcq %[tmp], 24+%[a]
: [tmp] "+r" (`tmp`), [a] "=&m" (`a->limbs[0]`)
: [b] "m"(`b->limbs[0]`)
: "cc"
"""
elif defined(clang):
# https://lists.llvm.org/pipermail/llvm-dev/2017-August/116202.html
# Remove the 0 from 8+0 when the proc is inline ....
asm """
movq 0+0%[b], %[tmp]
addq %[tmp], 0+0%[a]
movq 8+0%[b], %[tmp]
adcq %[tmp], 8+0%[a]
movq 16+0%[b], %[tmp]
adcq %[tmp], 16+0%[a]
movq 24+0%[b], %[tmp]
adcq %[tmp], 24+0%[a]
: [tmp] "+r" (`tmp`), [a] "=&m" (`a->limbs[0]`)
: [b] "m"(`b->limbs[0]`)
: "cc"
"""
else:
{.error: "Unsupported compiler".}