sgi1981, спасибо, в этом действительно была ошибка. Ещё я заметил, что unpcklpd пакует аргументы таки в обратном порядке, и что в конце должно стоять ret 8.
Вот код со всеми изменениями :
Код | .686 .model flat .XMM option casemap: none .data half real8 0.5 amsk dq 7fffffffffffffffh .code _XMM_F@24 proc ; (const __m128d q_LeftRight, const double V) push ebp mov ebp, esp movsd xmm1, QWORD PTR [ebp+8] ; pick V on xmm1 mulsd xmm1, QWORD PTR half ; V := 0.5 * V movsd xmm2, QWORD PTR amsk ; double abs value bit mask andpd xmm2, xmm1 ; abs(0.5 * V) on xmm2 movsd xmm3, xmm2 ; abs(0.5 * V) on xmm3 addsd xmm2, xmm1 ; 0.5 * V + abs(0.5 * V) subsd xmm1, xmm3 ; 0.5 * V - abs(0.5 * V) unpcklpd xmm1, xmm2 ; (0.5 * V + abs(0.5 * V), 0.5 * V - abs(0.5 * V)) mulpd xmm0, xmm1 ; * q_LeftRight mov esp, ebp pop ebp ret 8 _XMM_F@24 endp end
|
А вот для него "стенд", проверяющий совпадение результатов с функцией высокого уровня :
Код | // XMMTest.cpp : Defines the entry point for the console application. //
#include "stdafx.h" #include <intrin.h> #include <math.h> #include <stdlib.h> #include <time.h> #include <iostream>
__m128d F( const __m128d q_LeftRight, const double V) {
const double vHalf = 0.5 * V, absVHalf = abs(vHalf); return _mm_mul_pd(q_LeftRight, _mm_set_pd(vHalf + absVHalf, vHalf - absVHalf));
}
extern "C" __m128d __stdcall XMM_F( const __m128d q_LeftRight, const double V);
int _tmain(int argc, _TCHAR* argv[]) { const int ntests = 1000; for (int itest = 0; itest < ntests; itest++) { srand((unsigned)time(NULL));
double V = ((double)rand() - rand()) * (double)rand() / rand() * (double)itest / ntests; __m128d q_LeftRight = _mm_set_pd((double)rand() / rand(), (double)rand() / rand());
const __m128d resultAsm = XMM_F(q_LeftRight, V), resultControl = F(q_LeftRight, V);
_CRT_ALIGN(16) double resultAsmValues[2]; _mm_store_pd(resultAsmValues, resultAsm); _CRT_ALIGN(16) double resultControlValues[2]; _mm_store_pd(resultControlValues, resultControl);
std::cout << "Asm : " << resultAsmValues[0] << " " << resultAsmValues[1]; std::cout << ", Control : " << resultControlValues[0] << " " << resultControlValues[1] << std::endl; if ((resultAsmValues[0] != resultControlValues[0]) || (resultAsmValues[1] != resultControlValues[1])) { std::cout << "Different results!" << std::endl; break; } }
std::cout << "Done." << std::endl; std::cin.get();
return 0; }
|
Весь проект тоже присоединён - может кому-то пригодится, как туториал.
Если ещё где-то ошибки или я плохо сделал - скажите, пожалуйста. |