c - 用于扩展除法/乘法的 gcc intrinsic

标签 c gcc

现代 CPU 可以在两个 native 大小的字之间执行扩展乘法,并将低位和高位结果存储在单独的寄存器中。同样,在执行除法时,他们将商和余数存储在两个不同的寄存器中,而不是丢弃不需要的部分。

是否有某种可移植的 gcc 内在函数会采用以下签名:

void extmul(size_t a, size_t b, size_t *lo, size_t *hi);

或者类似的,除法:

void extdiv(size_t a, size_t b, size_t *q, size_t *r);

我知道我可以通过在代码中加入#ifdef 来通过内联汇编和鞋拔式可移植性自己完成它,或者我可以使用部分和来模拟乘法部分(这会慢得多),但我想避免这种情况为了可读性。肯定存在一些内置函数来执行此操作吗?

最佳答案

对于 4.6 版的 gcc,您可以使用 __int128。这适用于大多数 64 位硬件。例如

要获得 64x64 位乘法的 128 位结果,只需使用

void extmul(size_t a, size_t b, size_t *lo, size_t *hi) {
    __int128 result = (__int128)a * (__int128)b;
    *lo = (size_t)result;
    *hi = result >> 64;
}

在 x86_64 上,gcc 足够聪明,可以将其编译为

   0:   48 89 f8                mov    %rdi,%rax
   3:   49 89 d0                mov    %rdx,%r8
   6:   48 f7 e6                mul    %rsi
   9:   49 89 00                mov    %rax,(%r8)
   c:   48 89 11                mov    %rdx,(%rcx)
   f:   c3                      retq   

不需要 native 128 位支持或类似支持,内联后仅保留 mul 指令。

编辑:在 32 位 arch 上,这以类似的方式工作,您需要将 __int128_t 替换为 uint64_t 并将移位宽度替换为 32。优化将在甚至更老的 gcc。

关于c - 用于扩展除法/乘法的 gcc intrinsic,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13187629/

相关文章:

c++ - 模板化类的静态常量

android - 有没有办法在链接时覆盖-fvisibility=hidden?

无法理解简单程序集 x86 中 %rax 的值

c - 从结构中获取信息并在另一个函数中使用

c - 在 C 中顺序打开超过 4092 个文件

c - 用类给 C 加香料

c - 如何跟踪 C 中的特定函数/文件?

c - 读取或写入预取之间的区别

c++ - 将函数返回值传递给引用参数导致 GCC 中的编译错误

对指针指针和动态内存分配感到困惑