assembly 如何检查一个寄存器是否包含一个零字节没有SIMD指令

cfh9epnr  于 2023-06-06  发布在  其他
关注(0)|答案(1)|浏览(129)

给定x64架构中的64位通用寄存器(不是xmm寄存器),填充有一个字节的无符号值。如何在不使用SSE指令的情况下同时检查它的零值?
有没有一种方法可以以并行的方式完成,而不需要以4位的步长迭代寄存器?
我试着将它与某些64位掩码进行比较,但它不起作用。

ars1skjm

ars1skjm1#

从技术上讲,你可以这样做:

// True if any of the 8 bytes in the integer is 0
bool anyZeroByte( uint64_t v )
{
    // Compute bitwise OR of 8 bits in each byte
    v |= ( v >> 4 ) & 0x0F0F0F0F0F0F0F0Full;
    v |= ( v >> 2 ) & 0x0303030303030303ull;
    constexpr uint64_t lowMask = 0x0101010101010101ull;
    v |= ( v >> 1 ) & lowMask;
    // Isolate the lowest bit
    v &= lowMask;
    // Now these bits are 0 for zero bytes, 1 for non-zero;
    // Invert that bit
    v ^= lowMask;
    // Now these bits are 1 for zero bytes, 0 for non-zero
    // Compute the result
    return 0 != v;
}

但是SIMD会更快。SSE是x64架构的绝对要求,世界上所有的AMD64处理器都需要支持SSE1和SSE2。下面是SSE2版本:

bool anyZeroByteSse2( uint64_t v )
{
    __m128i vec = _mm_cvtsi64_si128( (int64_t)v );
    __m128i zero = _mm_setzero_si128();
    __m128i eq = _mm_cmpeq_epi8( vec, zero );
    return 0 != ( _mm_movemask_epi8( eq ) & 0xFF );
}

这是6条指令而不是16条:link

相关问题