簡體   English   中英

SSE中的SSE4內聯匯編問題

[英]SSE4 inline assembly problems in C++

Hello Everyone我想執行以下形式的內聯匯編指令

BLENDPD xmm1,xmm2/m128, imm8

我是內聯裝配的新手,所以我遇到了一些困難。 我的代碼是:

#include<iostream>
using namespace std;
int main()
{
  long long y;
  __asm("blendpd %0,$0xabcd000000001111abcd000000001111,$0x1":
    "=r" (y):
    );
  cout<<y;
  return 0;
}

我的第一個錯誤是得到一個128位操作數,所以我使用了長十六進制數,但我仍然需要輸出為128位,因為我希望2能夠在屏幕上打印y。 最重要的是我知道我的__asm語法是錯誤的,但無法弄清楚,加上我不確定使用英特爾或AT&T語法進行編譯會在使用__asm時產生影響。

歡迎任何幫助。 干杯! =)

編輯:我現在有這個版本,並得到一個未定義的函數錯誤。

  #include<iostream>
  #include<emmintrin.h>
  using namespace std;

int main()
{
const int mask=5;
__m128d v2 = _mm_set_pd(1.0, 2.0);
__m128d v1;
v1=_mm_blend_pd(v1, v2, mask);
return 0;
}

首先,對於這類事情,您很少需要使用內聯匯編。 GCC通常提供“編譯器內在”函數,允許您使用C函數語法而不是匯編語法調用給定的特殊指令。

在這種情況下,您想要的內部函數是_mm_blend_pd(),它具有此函數簽名

#include <smmintrin.h>
__m128d _mm_blend_pd(__m128d v1, __m128d v2, const int mask);

編譯器將用單個blendpd指令替換它; 這實際上不是函數調用。

__m128d數據類型是一個包含兩個雙精度浮點值的向量; 你可以從像這樣的雙打數組中創建一個:

__m128d v = _mm_set_pd(1.0, 2.0);

要從矢量中檢索值以打印它們,可以將矢量存儲到雙精度浮點數組中:

double a[2];
_mm_store_pd(a, v);

所有這些都基於英特爾內在函數手冊, 網址http://www.info.univ-angers.fr/~richer/ens/l3info/ao/intel_intrinsics.pdf ; 雖然這是指英特爾C ++編譯器,但GCC支持相同的語法。

編輯:替換錯誤emmintrin.h與正確smmintrin.h 另請注意, mask值需要為2位(向量中每個值一位); 0,1,2或3以外的值會產生錯誤。 當然,您需要使用-msse4 GCC選項進行編譯。

作為我的另一個答案的替代答案,這里是如何使用內聯匯編而不是內在匯編。 (正如Thomas Pornin在我的另一個答案中指出的那樣,內在函數通常更好,因為它們更便攜,但有時你也想要這樣的東西。)

首先,我作弊 - 我使用內部函數的版本,並用-S編譯它,並查看生成的匯編代碼,它是:

    movsd   -64(%rbp), %xmm0
    movhpd  -56(%rbp), %xmm0
    movsd   -48(%rbp), %xmm1
    movhpd  -40(%rbp), %xmm1
    blendpd $3, %xmm1, %xmm0
    movlpd  %xmm0, -64(%rbp)
    movhpd  %xmm0, -56(%rbp)

您可以在這里看到與原始代碼不同的一些內容。 首先,請注意兩個128位參數不是即時的 - 它們是xmm0和xmm1寄存器。 此外,您的操作數錯誤 - 掩碼首先出現,包含輸出的寄存器最后。 修復這些,並編譯代碼。

這里的第二個問題是你將通用寄存器的結果存儲到y ,而blendpd指令不接觸通用寄存器,所以這只是存儲垃圾。 您需要xmm0寄存器,您可以使用=Yz (請參閱GCC的文檔 )。 並且你不能把它存儲long long ,即64位; 你需要一個128位向量變量。 解決所有這些問題,更正的代碼是:

#include<iostream>
#include<smmintrin.h>
using namespace std;
int main()
{
  __m128d y;
  __asm("blendpd $0x3,%%xmm1,%%xmm0":
    "=Yz" (y):
    );
  // cout<<y;
  return 0;
}

你會注意到我必須注釋掉cout線,因為它沒有處理SSE向量的規定; 你需要使用_mm_store_pd內在函數來首先從y獲取單個double值。 (或者你可以添加更多的內聯匯編來調用movhpdmovhld指令直接從寄存器中獲取double值,而不是使用約束將它們分配給y 。)

而且你有它 - 編譯並運行良好。 當然,輸入值是未定義的(無論這些寄存器中是否隨機出現),因此輸出仍然是垃圾 - 如果您想獲得有意義的結果,則需要先添加一些內容以將值加載到寄存器中。

暫無
暫無

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

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