簡體   English   中英

XNOR 兩個 8 位塊中的 64 位寄存器

[英]XNOR two 64 bits registers in 8 bit blocks

我有兩個 64 位 vales,我想按如下方式對它們進行 XNOR:

RAX: 01000001 | 01000010 | 01000011 | 01000001 | 01000101 | 01000110 | 01000111 | 01000001     XNOR
RBX: 01000001 | 01000001 | 01000001 | 01000001 | 01000001 | 01000001 | 01000001 | 01000001
-------------------------------------------------------------------------------------------
RCX:    1          0          0          1          0          0          0          1



XNOR does the following:
    1 XNOR 1 | 1
    1 XNOR 0 | 0
    0 XNOR 1 | 0 
    0 XNOR 0 | 1

這樣每次 XNOR 的結果正好為0xff ,它在 RCX 寄存器中的相應塊 position 中輸出1

是否有 I64 指令或算術/邏輯表達式來解決上述問題?

其中的“8 位塊”部分使其與按位 XNOR 非常不同。 並且您希望使用 AND 以 8 位塊的形式水平減少 XNOR 結果。 這就是SIMD的全部意義所在

您想要的具體操作是比較是否相等。 幸運的是,x86 SSE2(或 MMX)pcmpeqb xmm0, xmm1正是這樣做的,在比較相等的元素中產生 0xFF (-1),在其他元素中產生 0x00。 您可以movq xmm0, src對其進行設置,將 8 字節零擴展加載到 16 字節 XMM 寄存器中。

您可以使用movq rcx, xmm0將結果(從 XMM0 的低 8 個字節)輸入 RCX,其中bsf rcx, rcx將找到最低非零位的 position。 或者test rcx, rcx會讓你分支。

如果您希望 RCX = 0x0100000100000001 (即每個字節底部的 1 位),您可以在 MOVQ 之前使用SSSE3 pabsb xmm0, xmm0來做字節的打包絕對值,映射 0xFF -> 1 並保持 0 不變。 與 SSE2 不同,這不是x86-64 的基准,但缺少它的 CPU 已經完全過時(例如 AMD Phenom II 是最新的)。


將 SIMD 比較結果放入 integer reg 的正常方法是pmovmskb 它與movq r, x一樣高效,但可以讓您獲得所有 16 字節元素,甚至無需使用 64 位寄存器。

    movq     xmm0, [rdi]       ; 8-byte load.  Use movdqu for all 16 bytes
    movq     xmm1, [rsi]
    pcmpeqb  xmm0, xmm1
    pmovmskb ecx, xmm0

    cmp      ecx, 0xffff
    je       all_were_equal

    test     cl, cl        ; low 8 bytes of compare result -> low 8 bits of RCX
    jnz      some_were_equal

這需要每個字節的高位。 即給你一個比較bitmap。 您可以bsf ecx, ecx找出 16 個字節中的哪個(如果有)是第一個匹配項。 (如果您的輸入是零擴展的 8 字節值,則第 9 個字節將始終匹配。CH 將從 pmovmskb 輸入的上半部分全為 1。)

當然,您可以簡單地對其進行分支,而不是對比較結果進行位掃描。 常見的方法有:

  • 如果任何元素比較為真,則test ecx, ecx / jnz跳轉
  • cmp ecx, 0xffff / je如果全部匹配則跳轉。

相關:將 16 字節字符串與 SSE進行比較,以使用內在函數執行此操作。


可以使用 MMX movq mm0, [rdi] / pcmpeqb mm0, [rsi]來執行此操作,但在某些最新的 CPU 上,MMX 的吞吐量比 SSE2 更差(例如 Skylake 上的執行端口更少),而且您需要一個緩慢的完成將 x87 state 恢復到 x87 模式后 -ish emms

盡管如此,如果您的數據自然是 8 字節塊,那么您將保存一個movq ,因此您不能自然地一次只處理 16 個字節。 並且指令更緊湊(機器代碼大小),正如您在英特爾手冊中看到的它們的編碼。 因此,如果 8 字節塊非常適合,並且您可以將 EMMS 置於足夠大的循環之外,那么 MMX 值得考慮。 (或者如果你絕對從不使用 x87 指令,甚至不調用任何庫函數,並且可以跳過 EMMS)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM