2013-03-31 25 views
3

UNI端口分配,我需要編寫用於計數在一個字符串中組件(由指針和索引定義)的空格數的函數。有使用pcmpeqb這個要求(即與SSE寄存器的工作),以及提示使用popcntpmovmskb。我的基本方法是,在處理16字節的塊串,每塊裝入%xmm8並與%xmm9被初始化爲包含16個空格比較。但是,我需要特意處理最後一個塊。如何在SSE寄存器末尾「刪除」字節?

我首先想到的是使用一個循環指令來刪除垃圾過去的字符串的結尾。 (該字符串保證有結束後分配一些額外的空間,以防止段錯誤,但該數據可能不應該被用於比較。)我偶然發現PSRLDQ但它似乎不接受非直接參。 (或者至少拒絕我拋棄它。)所以我的問題是:我怎樣才能刪除SSE寄存器的最後X個字節,而不是將它的一半調零,或者逐字執行? (據我所知大部分可用的操作對他們做。)

我的代碼(模樣板)目前看起來是這樣的 - 有問題的位是接近年底,標籤_last:後:

# === Arguments === 
    # %rdi - char *input 
    # %rsi - size_t count 
    # === Temporaries === 
    # %rdx - how many chars to process in final run 
    # %rcx - how many characters were "read" already 
    # %r8 - pop count of last iteration 
    # %r9 
    # %r11 
    # === SSE Temporaries === 
    # %xmm8 - the chunk of the string being processed 
    # %xmm9 - 16 spaces 

    xor %rcx, %rcx 
    xor %rax, %rax 
    movdqu _spaces(%rip), %xmm9 

_loop: 
    # set %rdx to number of characters left to process 
    mov %rsi, %rdx 
    sub %rcx, %rdx 

    # we've reached the end of the string 
    cmp %rdx, %rsi 
    jge _end 

    movdqu (%rdi, %rcx), %xmm8 # load chunk of string to process 
    add $16, %rcx 

    # less than 16 characters to process 
    cmp $16, %rdx 
    jg _last 

_compare: #compare %xmm8 with spaces and add count of spaces to %eax 
    pcmpeqb %xmm9, %xmm8 
    pmovmskb %xmm8, %r8d 
    popcntl %r8d, %r8d 
    add %r8d, %eax 
    jmp _loop 

_last: # last part of string, less than 16 chars 
    sub $16, %rdx 
    neg %rdx 
    # I need to delete possible garbage after the last chars 
    psrldq %edx, %xmm8 
    jmp _compare 

_end: 
    ret 

(那裏的控制流可能仍然有問題,但我會在稍後處理。)

回答

2

我認爲最簡單的解決方案是使用SSE寄存器中的全部16個字符,但屏蔽掉pmovmskb之後的位。請注意,使用像您一樣的16字節負載是不安全的,因爲您可能會跨越到不可訪問的頁面。

+0

感謝您的警告,但分配狀態表明,我可以依賴至少16字節可以在字符串參數中的最後一個字符後訪問。我在睡覺之後嘗試一下你的建議,似乎需要重新安排一下控制流程。 – millimoose

2

不要打擾試圖「刪除」在上交所寄存器中的額外的字節。相反,在比較和執行PMOVMSKB之後,只需屏蔽結果掩碼中對應於額外字節的位。這是一個非常標準的矢量化方法;而不是跳過箍環來獲取你想要的數據,處理所有事情,然後清理你以後不想要的數據。