koodev

ARM A32 명령어셋 VZIP

Programming

A32 명령어셋의 VZIP에 대해서 알아보자. 12.130 VZIP 을 참고했다.

이 명령어는 A64 버전의 ZIP1/ZIP2와 마찬가지로 두 벡터의 상위/하위 절반을 각각 떼어다가 뒤섞는다.

A32 버전의 VZIP은 특이하게도 Destination 피연산자가 따로 없다. 두 개의 피연산자를 갖는데 둘 다 상태가 변한다.

VZIP{cond}.size Qd, Qm
VZIP{cond}.size Dd, Dm
  • cond: 옵션. 조건처리.
  • size: 8 또는 16 또는 32.
  • Qd, Qm: 벡터 SIMD/FP 레지스터. Quadword.
  • Dd, Dm: 벡터 SIMD/FP 레지스터. Doubleword.

뒤섞는 방법은 아래 그림과 같다. 말하자면 A64 버전의 ZIP1ZIP2를 합쳐 놓은 것.

ARM A64 명령어셋 ZIP1, ZIP2

Programming

우선 ZIP1부터 정리한다. 이 명령어는 두 벡터에서, 즉 두 개의 SIMD/FP 레지스터에서 상위 절반(upper half)부분을 각각 떼어다가 뒤섞어(interleave) 붙인다. 설명보다는 그림으로 이해하는 것이 편할 듯.

ZIP1 <Vd>.<T>, <Vn>.<T>, <Vm>.<T>

위 그림에도 나와있듯이 ZIP2는 하위 절반 비트를 뒤섞는다.

뒤섞는 단위는 T파라미터에서 명시해 주는데, 8B, 16B, 4H, 8H, 2S, 4S, 2D 가 가능하다.

ARM A64 명령어세트 기본적인 내용 정리

Programming

ARM 명령어를 난생 처음 작성하다가 잘 안되어 기본적인 내용을 정리해본다. 이 내용은 Structure of the ARM A64 instruction set 에서 가져왔다.

레지스터

A64 아키텍쳐는 30개의 정수 레지스터가 있으며 각각은 x0부터 x31까지의 이름을 갖는다.

여기에 스택포인터 레지스터와 제로 레지스터가 있다. 제로 레지스터는 모든 비트가 0으로 고정된 레지스터이다. 그런데 이들 두개 모두 31번 레지스터 번호로 인코딩된다. 그리고 인스트럭션에 따라 스택포인터로 쓸지 제로레지스터로 사용할지가 결정된다.

30번 레지스터인 x30은 리턴주소를 저장하는데 사용된다.

여기서 이야기하는 레지스터들은 모두 길이가 64비트이다. 이들의 하위 32비트에 접근하는 용도로 w0에서 w31을 사용할 수 있다. 하위 비트에 쓰기 명령을 수행하면 상위 비트는 남아있게 될까? 그렇지는 않다. 하위 32비트에 쓰기 명령을 내리면 상위 32비트가 클리어된다.

부동소수점/벡터 레지스터

A64에는 위의 정수 레지스터와는 별개로 부동소수점이나 128비트 벡터 연산을 위한 32개의 레지스터가 존재한다. 이들은 벡터 연산을 지원하기 때문에 한꺼번에 64비트나 128비트씩 동작하도록 할 수 있다. 즉, 한번에 8비트 혹은 16비트, 32비트, 64비트씩 나누어 쓸 수 있다. 이렇게 하면 한번에 여러개의 동일한 연산을 수행시킬 수 있어서 코드 실행속도를 높일 수 있다. 원래는 루프를 돌면서 해야 할 일을 한꺼번에 수행하는 것이다.

명령어

명령어들은 ARM ARM for ARMv8-A 문서에서 설명되어 있다. 명령어 갯수는 앨리어스를 제외하고 442개 정도 된다고 한다.

A64 명령어들은 모두 32비트 길이이다.

(명령어들의 레벨 분류 - main encoding, instruction group, decode group, instruction - 에 대해서는 이해하지 못해 정리할 수 없었다)

같은 이름을 쓰고 피연산자를 달리 갖는 명령어가 있다. 예를 들어 아래 FMUL명령어는 두 개의 부동소수점을 곱한다. C 언어에서 a = b * c 와 같은 것이다. A64에서는 피연산자에 따라 아래에서 보여지는 것들 중 하나가 될 것이다.

fmul s0, s1, s2            ;single precision floats
fmul d0, d1, d2            ;double precision floats
fmul v0.2s, v1.2s, v2.2s   ;vectors with two singles
fmul v0.4s, v1.4s, v2.4s   ;vectors with four singles
fmul v0.2d, v1.2d, v2.2d   ;vectors with two doubles
fmul s0, s1, v2.s[0]       ;multiplies by a vector element
fmul d0, d1, v2.d[0]
fmul v0.2s, v1.2s, v2.s[0] ;combinations of the above
fmul v0.4s, v1.4s, v2.s[0]
fmul v0.2d, v1.2d, v2.d[0]

이렇게 하나의 FMUL에서 많은 변형이 생기게 된다. 모든 대표 명령어에서 이렇게 변형이 많이 생기는 것은 아니다. 그래서 이런 변형까지 다 계산하면 모든 명령어의 수는 1000에서 2000개 정도가 된다고 한다. 명령어세트 설계자는 이들 변형과 피연산자까지 모두 포함하여 32비트 길이의 공간에 인코딩해야 하며 혹시라도 나중에 추가될 수도 있는 부분을 위한 여분까지 남겨두어야 할 것이다.


나머지 부분은 이해를 못해서 제외한다.

'Programming' 카테고리의 다른 글

ARM A32 명령어셋 VZIP  (0) 2019.03.11
ARM A64 명령어셋 ZIP1, ZIP2  (0) 2019.03.11
Bash에서 문자열 검색 조건식 만들기  (0) 2018.07.22
Truncate PWD in prompt (MacOS)  (0) 2018.04.29
Regular expression in sed  (0) 2018.04.25