128乘法和除法的内在联系

问题描述 投票:2回答:2

在x86_64中,我知道mul和div opp代码支持128个整数,把下位64位放在rax中,上位放在rdx寄存器中。 我在英特尔的内在指南中寻找某种内在代码来实现这个功能,但我找不到。 我正在编写一个大数库,其中字的大小是64位。 现在我正在做这样的单字除法。

int ubi_div_i64(ubigint_t* a, ubi_i64_t b, ubi_i64_t* rem)
{
    if(b == 0)
        return UBI_MATH_ERR;

    ubi_i64_t r = 0;

    for(size_t i = a->used; i-- > 0;)
    {

        ubi_i64_t out;
        __asm__("\t"
                "div %[d] \n\t"
                : "=a"(out), "=d"(r)
                : "a"(a->data[i]), "d"(r), [d]"r"(b)
                : "cc");
        a->data[i] = out;


        //ubi_i128_t top = (r << 64) + a->data[i];
        //r = top % b;
        //a->data[i] = top / b;
    }
    if(rem)
        *rem = r;

    return ubi_strip_leading_zeros(a);
}

如果能在x86intrinsics.h头中使用一些东西,而不是内联asm,那就更好了。

c gcc inline-assembly intrinsics 128-bit
2个回答
2
投票

gcc有 __int128__uint128 类型。

它们的运算 当存在正确的汇编指令时,它应该使用正确的汇编指令;我过去曾用它们来获取产品的上64位,尽管我从未用它来进行划分。如果它没有使用正确的,酌情提交一个bug报告功能请求。


1
投票

我最后一次调查时,内在的都在变化中. 在这种情况下,内在的主要原因似乎是由于64位模式下的MSVC不允许内联装配。

在MSVC(我想还有ICC)中,你可以使用 _umul128 对于 mul_mulx_u64 对于 mulx. 这些在GCC中不起作用 , 至少在GCC 4.9中不起作用(_umul128 比GCC 4.9老得多)。) 我不知道GCC是否计划支持这些,因为你可以得到 mulmulx 间接通过 __int128 (取决于你的编译选项)或直接通过内联汇编。

__int128 在你需要一个更大的类型和128位的携带之前,这个方法都很好用。然后你需要 adc, adcxadox 而这些在本质上更是一个问题。英特尔的文档与MSVC不一致,而编译器似乎并没有生成 adox 然而有了这些内在的东西。请看这个问题。_addcarry_u64和_addcarryx_u64与MSVC和ICC的关系。.

内联装配可能是GCC(甚至可能是ICC)的最佳解决方案。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.