Instruction Set Architecture (ISA)

EEEFFEE·2023년 9월 6일
0

Computer Architecture

목록 보기
2/6
post-thumbnail

23.09.04 최초 작성

1. Instruction Set

프로세서에서 지원하는 명령어들의 집합. 프로세서가 다를 경우 다른 Instruction Set을 지원한다.

ABI = User portion of the Instruction Set + Operating System Interface // 작성된 프로그램(이진코드)의 이식성 표준을 결정한다.

1.1 ISA 구조

ADD X9, X20, X21
Op Code : 수행할 명령어 (ADD)
Operand : 피연산자 (X20, X21)
Place to Store Result : 연산 결과를 저장할 공간(X9)

1.2 레지스터(Register)

레지스터는 프로세서 내부에 위치한 저장공간으로 프로세서가 명령어 실행에 사용할 데이터를 저장한다. ARMv8의 경우 레지스터의 크기는 64비트이며 총 32개의 레지스터를 갖고 있다. 레지스터의 크기인 64비트를 묶어 더블 워드(Double Word)라고 한다.

2. 피연산자

  1. 산술 피연산자

    산술 명령어의 피연산자는 레지스터에 위치한 값만을 사용할 수 있다.

  2. 메모리 피연산자

    모든 값을 레지스터에 저장할 수 없으므로 메모리로부터 인출해 사용해야 한다. 이를 위한 명령어를 데이터 전송 명령어(Data Transfer Instruction)이라고 한다.

    • load : 메모리에서 레지스터로 데이터 복사
    • store : 레지스터로부터 메모리로 데이터 복사
  3. 수치(Immediate) 피연산자
    메모리로부터 인출하지 않아 해당 피연산자를 활용하면 연산 속도가 빠르다.

표기할 것표기 방법(예시)의미
레지스터X22번 레지스터(0~31), 혹은 그 레지스터에 저장된 값
메모리[X11, #8]X11레지스터에 저장된 배열의 시작주소에 8을 더한 주소의 값
수치#6정수 6

3. 명령어의 내부 표현

3.1 기본 명령어 필드

3.1.1 R-Type Instruction

opcode : 명령어가 실행할 연산의 종류
Rm : 두 번째 피연산자 레지스터
shamt : 자리이동(shift) 양
Rn : 첫번째 피연산자 레지스터
Rd : 결과를 저장할 레지스터

3.1.2 D-Type Instruction

  • R-Type의 경우 피연산자 레지스터 정보의 크기가 5-bit로 제한되어 252^5를 넘는 값을 지정할 수 없다.

  • D-Type은 이 문제를 해결하기 위해 필드의 크기를 조절하여 292^9까지의 값을 지정할 수 있도록 한 형식이다.

  • LDUR ...

ex) `LDUR X9, [X22, #64]`

address : #64 (262^6)
Rn : X22
Rt : X9

3.1.3 I-Type Instruction

  • D-Type의 경우에도 값이 제한되어 R-Type에서와 같은 문제가 발생할 수 있다.

  • 이를 위해 I-Type 명령어 형식을 만들어 더 큰 상수를 활용한 연산을 가능하게 했다.

  • ADDI, SUBI ...

3.2 Logical Operation

  • 워드 내 비트에 대한 연산, 비트들을 워드로, 워드를 비트로 전환하는 연산(packing & unpacking)을 위한 명령어

3.2.1 자리이동(shift)

  • 더블 워드 내의 모든 비트를 오른쪽 or 왼쪽으로 옮기며 이동 후 빈자리는 0으로 채워넣는다.

  • LSL, LSR ...

LSL X11, X19, #4

shamt : #4
Rd : X11
Rn : X19

3.2.2 논리연산

  • 각 비트별 연산을 담당한다.

  • AND, ORR, NOT, EOR ...

AND X9, X11, X12
ORR X9, X11, X12
NOT X9, X11, X12
...

3.3 Conditional Operation

  • 입력 데이터나 연산 결과를 판단해 실행하기 위한 연산자 (반복문또한 포함)

  • CBZ, CBNZ ...

if (i = j) f = g + h; else f = g - h;

SUB X9, X22, X23	//i-j 값을 X9에 저장
CBNZ X9, Else	//X9 값이 0이 아니면 Else로 분기
ADD X19, X20, X21
B Exit
Else : SUB X19, X20, X21
Exit :

Loop Operation

while (save[i] == k)	i += 1;

Loop : LSL X10, X22, #3	// Temp reg X10 = i * 8
ADD X10, X10, X25	// X10 = address of save[i], 주소에 8을 더해줘야 다음 위치 가르킴
LDUR X9, [X10, #0]	// Temp reg X9 = save[i]
SUB X11, X9, X24	// X11 = save[i] - k
CBNZ X11, eXIT		// go to Exit if save[i] is not k
ADDI X22, X22, #1	// i = i + 1
B Loop				// go to Loop
Exit :
  • 연산 결과의 상태를 저장해 나타내는 비트를 flag라고 한다.

    • N(음수) : 연산 결과 MSB 비트가 1이면 1
    • Z(제로) : 연산 결과 0이면 1
    • V(오버플로) : 연산 결과 오버플로가 발생하면 1
    • C(캐리) : 연산 결과 MSB에서 발생한 캐리가 1 / MSB로 버로우 발생시 1

Signed Number

B.[X]기능flag 조건
EQ==Z = 1
NE\neqZ = 0
LT<<N! = V
LE\leq~(Z = 0 & N = V)
GT>>Z = 0 & N = V
GE\geqN = V

Unsigned Number

B.[X]기능flag 조건
EQ==Z = 1
NE\neqZ = 0
LT<<C = 0
LE\leq~(Z = 0 & C = 1)
GT>>Z = 0 & C = 1
GE\geqC = 1

3.4 Procedure Call Operations

Procedure(프로시저) : 이해하기 쉽고 재사용이 가능하도록 프로그램을 구조화 하는 방법(=함수)
Parameter : 프로시저에 값을 보내고 결과를 받아오는 역할

  • Procedure 실행 단계

    1. 프로시저가 접근할 수 있는 곳에 인수를 넣는다.
    2. 프로시저가 제어를 넘긴다.
    3. 프로시저가 필요로 하는 메모리 자원을 획득한다.
    4. 필요한 작업을 수행한다.
    5. 호출한 프로그램이 접근할 수있는 장소에 결과값을 넣는다.
    6. 프로시저는 프로그램 내의 여러 곳에 호출될 수 있으므로 원래 위치로 제어를 돌려준다.
  • LEG 아키텍처 Procedure 레지스터 할당 관례

    • X0 ~ X7 : 전달할 인수와 결과값을 가짐
    • X9 ~ X17 : 프로시저 호출 시 피호출 프로그램이 값을 보존해 주지 않음
    • X19 ~ X28 : 프로시저 호출 전과 후의 값이 유지되어야 함
    • LR (X30) : 호출한 곳으로 돌아가기 위한 Return Address(복귀 주소)를 가짐.
  • AAPCS (Procedure Call Standard for ARM Architecture) : ARM 아키텍처 프로시저 레지스터 할당 관례

    • X0 ~ X7 : 전달할 인수와 결과값을 가짐
    • X9 ~ X15 : 프로시저 호출 시 피호출 프로그램이 값을 보존해 주지 않음 (지역변수)
    • FP (X29) : 프레임 포인터로 레지스터로 이전 스택 포인터 주소 저장
    • LR (X30) : 호출한 곳으로 돌아가기 위한 Return Address(복귀 주소)를 가짐.

Caller (호출 프로그램) : 프로시저 실행을 시작시키고 필요한 인수를 제공하는 프로그램
Callee (피호출 프로그램) : Caller가 제공하는 인수를 이용해 연산을 실행하고 Caller로 제어를 넘기는 프로그램.

Leaf Procedure : 다른 프로시저를 호출하지 않는 프로시저

BL ProcdureAddress // 지정된 주소로 점프하며(ProcdureAddress) 다음 명령어의 주소를 LR에 저장
BR LR // LR에 저장된 주소로 복귀

long long int leaf_example (long long int g, long long 
int h, long long int i, long long int j)
{
 long long int f;
 f = (g + h) − (i + j);
 return f;
}

---

leaf_example:	SUBI SP, SP, #24 // adjust stack to make room for 3 items
STUR X10, [SP,#16] // save register X10 for use afterwards
STUR X9, [SP,#8] // save register X9 for use afterwards
STUR X19, [SP,#0] // save register X19 for use afterwards

ADD X9,X0,X1 // register X9 contains g + h
ADD X10,X2,X3 // register X10 contains i + j
SUB X19,X9,X10 // f = X9 − X10, which is (g + h) − (i + j)

ADD X0,X19,XZR // returns f (X0 = X19 + 0)

LDUR X19, [SP,#0] // restore register X19 for caller
LDUR X9, [SP,#8] // restore register X9 for caller
LDUR X10, [SP,#16] // restore register X10 for caller
ADDI SP,SP,#24 // adjust stack to delete 3 items

BR LR // branch back to calling routine

  • 재귀 프로시저의 경우

long long int fact (long long int n)
{
 if (n < 1) return (1);
 else return (n * fact(n − 1));
}
---
fact:
SUBI SP, SP, #16 // adjust stack for 2 items
STUR LR, [SP,#8] // save the return address
STUR X0, [SP,#0] // save the argument n

SUBIS ZXR,X0, #1 // test for n < 1
B.GE L1 // if n >= 1, go to L1

ADDI X1,XZR, #1 // return 1
ADDI SP,SP,#16 // pop 2 items off stack
BR LR // return to caller

L1: SUBI X0,X0,#1 // n >= 1: argument gets (n − 1)
 BL fact // call fact with (n − 1)

LDUR X0, [SP,#0] // return from BL: restore argument n
LDUR LR, [SP,#8] // restore the return address
ADDI SP, SP, #16 // adjust stack pointer to pop 2 items

MUL X1,X0,X1 // return n * fact (n − 1)

BR LR // return to the caller

3.4.1 메모리 공간 할당


Text : 프로그램 코드 영역
Static Data : 전역 변수 및 상수 저장 공간
Dynamic Data : 힙 공간 (동적으로 할당되는 데이터를 저장)
Stack : 스택 공간

  • 스택의 경우

    - Procedure Frame : 프로시저의 레지스터 데이터와 지역 변수를 가지고 있는 스택 영역.
    - Frame Pointer (FP) : 프로시저의 저장된 레지스터와 지역 변수의 시작 위치를 표시하는 값. 일반적으로 X29를 사용한다.
    -SP : 프로시저의 저장된 레지스터와 지역 변수의 마지막 위치를 표시하는 값. X28를 사용한다.

3.5 긴 수치와 주소를 위한 주소지정 방식

  • 수치의 경우

    명령어 형식에 따라 값을 저장하면 큰 상수를 저장할 수 없는 경우가 발생한다. 큰 상수를 저장하기 위한 명령어로 MOVZ, MOVK가 있다.

    	- `MOVZ` : 지정한 비트를 제외하고 0으로 만들며 지정한 위치에 값을 입력한다.
    	- `MOVK` : 지정한 비트 외의 비트를 조작하지 않으며 지정한 위치에 값을 입력한다.

  • 주소의 경우

    명령어 형식에 따라 분기하는 주소를 나타내는 비트의 크기가 제한된다. 이를 해결하기 위해 특정 레지스터의 값(프로그램 카운터 (PC) 등...)에 주소를 나타내는 비트의 값을 더해 나타낸다.

    • Addressing mode(주소지정 방식)
      1. 수치 주소지정 : 피연산자는 명령어에 있는 상수
      2. 레지스터 주소 지정 : 피연산자는 레지스터
      3. 베이스(변위) 주소지정 : 레지스터의 상수 + 명령어에 있는 상수
      4. PC-상대 주소지정 : PC값 + 명령어 내의 상수

       

0개의 댓글