128乘法和除法的内在函数

时间:2015-09-12 15:50:58

标签: c++ c gcc assembly intrinsics

在x86_64中,我知道mul和div的代码支持128个整数,方法是将rax中的低64位和rdx寄存器的高位放在一起。我在intel intrinsics指南中寻找某种内在的功能,我找不到一个。我正在写一个大字库,字大小为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,那就太好了。

2 个答案:

答案 0 :(得分:2)

gcc有__int128__uint128种类型。

算术应该使用正确的汇编指令;我过去曾使用它们来获得产品的高64位,尽管我从来没有将它用于分割。如果它没有使用正确的,请提交错误报告/功能请求。

答案 1 :(得分:1)

Last I looked into it the intrinsic were in a state of flux。在这种情况下,内在函数的主要原因似乎是由于64位模式下的MSVC不允许内联汇编。

使用MSVC(我认为是ICC),您可以_umul128使用mul_mulx_u64使用mulx。这些在GCC中不起作用,至少不是GCC 4.9(_umul128比GCC 4.9更老)。我不知道GCC是否计划支持这些,因为您可以通过mul(取决于您的编译选项)或直接通过内联汇编间接获得mulx__int128

__int128正常工作,直到您需要更大的类型和128位进位。然后,您需要adcadcxadox,这些内在函数更是一个问题。英特尔的文档与MSVC不同意,编译器似乎还没有使用这些内在函数生成adox。请参阅此问题:_addcarry_u64 and _addcarryx_u64 with MSVC and ICC

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