128乘法和除法的内在函数

在x86_64中,我知道mul和div的代码通过将低64位放在rax中而高位放在rdx寄存器中来支持128个整数。 我在intel intrinsics指南中寻找某种内在的function,我找不到一个。 我正在写一个大字库,字大小为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 <data[i]; //r = top % b; //a->data[i] = top / b; } if(rem) *rem = r; return ubi_strip_leading_zeros(a); } 

如果我可以在x86intrinsics.h标头而不是内联asm中使用某些东西,那将是很好的。

gcc有__int128__uint128类型。

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

最后我调查了内在物质处于不稳定状态 。 在这种情况下,内在函数的主要原因似乎是由于64位模式下的MSVC不允许内联汇编。

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

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

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