SIMD에는 정수형과 실수형 두 가지 병렬 연산 방식이 있다. 내포하고 있는 Pack의 형태에 따라 연산하는 방식이 달라지기 때문이다. 초기 MMX에는 64bit 병렬 연산만 가능하였으나 SSE2fh sjadjdhaustj 128bit 병렬 연산이 가능해졌다.

 

명명법

P<SIMD_op><suffix>

 

접두사 P는 'packed'를 의미하며 정수형 SIMD 명령어이다. 실수형 SIMD 명령어는 P 접사가 뒤에 붙어 실수형과 정수형을 구분하게 된다(4장 참조).

 

<SIMD_op> : 실제 연산을 수행할 내용(명령어)이 오게 된다. 예를 들면 덧셈일 경우 ADD, 뺄셈일 경우 SUB와 같이 연산을 의마하게 되는 단어가 오게 된다.

 

<suffix> : 연산을 수행할 pack의 사이즈를 의미하는 접미사가 오게 된다.

 

 

MOVDQU : Move Unaligned Double Quad word

- 128bit 레지스터 혹은 128bit 메모리에 정렬되어 있지 않은 값을 읽어올 때 사용한다.

-------------------------------------------

MOVDQU xmm1. xmm2/m128

MOVDQU xmm2/m128, xmm1

-------------------------------------------

int main(int argc, char* argv[])
{
	short ShortArrayA[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
	short ShortArrayB[8]{ 0 };

	__asm
	{
		pushad
		movdqu xmm0, ShortArrayA	//xmm0 = ShortArrayA
		//ShortArrayA 메모리 변수를 xmm0 레지스터에 대입
		movdqu ShortArrayB, xmm0	//ShortArrayB = xmm0
		//xmm0 레지스터의 값을 ShortArrayB 메모리에 대입
		popad
	}

	cout << "ShortArrayB : " << ShortArrayB[7]<<", " << ShortArrayB[6] << ", " << ShortArrayB[5] << ", " << ShortArrayB[4] << ", "
		<< ShortArrayB[3] << ", " << ShortArrayB[2] << ", " << ShortArrayB[1] << ", " << ShortArrayB[0] << endl;


	return 0;
}

 

MOVDQU : Move Aligned Double Quad word

- 128bit 레지스터 혹은 128bit 메모리에 정렬되어 있는 값을 읽어올 때 사용한다. 메모리가 정렬되어 있으므로 movdqu보다 빠른 속도로 값을 읽어올 수 있다.

-------------------------------------------

MOVDQA xmm1. xmm2/m128

MOVDQA xmm2/m128, xmm1

-------------------------------------------

int main(int argc, char* argv[])
{
	__declspec(align(16)) short ShortArrayA[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
	__declspec(align(16)) short ShortArrayB[8]{ 0 };

	__asm
	{
		pushad
		movdqu xmm0, ShortArrayA	//xmm0 = ShortArrayA
		//ShortArrayA 메모리 변수를 xmm0 레지스터에 대입
		movdqu ShortArrayB, xmm0	//ShortArrayB = xmm0
		//xmm0 레지스터의 값을 ShortArrayB 메모리에 대입
		popad
	}

	cout << "ShortArrayB : " << ShortArrayB[7]<<", " << ShortArrayB[6] << ", " << ShortArrayB[5] << ", " << ShortArrayB[4] << ", "
		<< ShortArrayB[3] << ", " << ShortArrayB[2] << ", " << ShortArrayB[1] << ", " << ShortArrayB[0] << endl;


	return 0;
}

 

 

논리 연산

 

128bit XMM 레지스터의 모든 값에 대해 bit 연산을 수행한다. 논리 연산으로 동작하는 규칙은 같으며 128bit 모두에 대해 이루어지는 것이 다르다.

 

-PAND (Bitwise Logical And)

2개의 128bit XMM 레지스터를 받아서 bit 단위 AND 연산을 수행한다. 비교 연산 후 충족하는 값만 뽑아낼 때 많이 사용한다.

-------------------------------------------

PAND xmm1, xmm2/m128

-------------------------------------------

 

-POR (Bitwise Logical OR)

2개의 128bit XMM 레지스터를 받아서 bit 단위 OR 연산을 수행한다. 

-------------------------------------------

POR xmm1, xmm2/m128

-------------------------------------------

 

-PXOR (Bitwise Logical Exclusive OR)

2개의 128bit XMM 레지스터를 받아서 bit 단위 XOR 연산을 수행한다. 만일 같은 레지스터에 대하여 XOR 연산을 수행하면 해당 레지스터는 0으로 초기화된다. 따라서 레지스터를 초기화할 때 많이 사용된다.

-------------------------------------------

PXOR xmm1, xmm2/m128

-------------------------------------------

 

-PANDN (Bitwise Logical And Not)

2개의 128bit XMM 레지스터를 받아서 bit 단위 ANDNOT연산을 수행한다. 

-------------------------------------------

PANDN xmm1, xmm2/m128

-------------------------------------------

 

 

int main(int argc, char* argv[])
{
	__declspec(align(16)) int IntArrayA[4] = { 1, 1, 0, 0 };
	__declspec(align(16)) int IntArrayB[4] = { 1, 0, 1, 0 };
	__declspec(align(16)) int ANDResult[4] = { 0 };		//0으로 초기화	
	__declspec(align(16)) int ORResult[4] = { 0 };		//0으로 초기화	
	__declspec(align(16)) int XORResult[4] = { 0 };		//0으로 초기화
	__declspec(align(16)) int ANDNOTResult[4] = { 0 };	//0으로 초기화

	__asm
	{
		pushad
		movdqa xmm0, IntArrayA	//xmm0 = IntArrayA;	
		movdqa xmm1, xmm0		//xmm1 = xmm0;
		movdqa xmm2, xmm0		//xmm2 = xmm0;
		movdqa xmm3, xmm0		//xmm3 = xmm0;
		movdqa xmm4, IntArrayB	//xmm4 = IntArrayB;
			
		pand xmm0, xmm4			//AND 연산
		por xmm1, xmm4			//OR 연산
		pxor xmm2, xmm4			//XOR 연산
		pandn xmm3, xmm4		//ANDNOT 연산

		movdqa ANDResult, xmm0		//ANDResult = xmm0;
		movdqa ORResult, xmm1		//ORResult = xmm1;
		movdqa XORResult, xmm2		//XORResult = xmm2;
		movdqa ANDNOTResult, xmm3	//ANDNOTResult = xmm3;

		popad
	}

	cout << "ANDResult : " << ANDResult[0] << ", " << ANDResult[1] << ", " << ANDResult[2] << ", " << ANDResult[3] << endl;
	cout << "ORResult : " << ORResult[0] << ", " << ORResult[1] << ", " << ORResult[2] << ", " << ORResult[3] << endl;
	cout << "XORResult : " << XORResult[0] << ", " << XORResult[1] << ", " << XORResult[2] << ", " << XORResult[3] << endl;
	cout << "ANDNOTResult : " << ANDNOTResult[0] << ", " << ANDNOTResult[1] << ", " << ANDNOTResult[2] << ", " << ANDNOTResult[3] << endl;


	return 0;
}

'자기개발 > SIMD' 카테고리의 다른 글

SIMD - Intrinsics 개요  (0) 2021.10.08
SIMD - memcpy구현  (0) 2021.10.08
SIMD - 최대값 구하기( C랑 비교)  (0) 2021.10.08
SIMD - (feat C++, Assembly 조건 제어문)  (0) 2021.10.07
SIMD 알아보기 (feat C++, Assembly 연산)  (0) 2021.10.07
Posted by pi92

블로그 이미지
pi92

공지사항

Yesterday
Today
Total

달력

 « |  » 2025.5
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

최근에 올라온 글

최근에 달린 댓글

글 보관함