#4. MIPS R, I, J-format Instructions, 명령어 포맷

컴퓨터구조론 2023. 12. 17. 17:11
반응형

MIPS의 모든 명령어 셋은 데이터시트로  다음 링크에서 확인이 가능하다.

https://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdf

 

MIPS 명령어 셋에는 3가지 옵션이 존재한다. R, I, J Format이 존재하며 이번 글에서는 R포맷의 명령어에 대해 알아본다.

MIPS 공식 데이터시트에 있는 Formats

1. R-format Instructions

MIPS의 R-format 명령어는 위 그림과 같다. 32bit로 구성되어 있으며 각 자리가 의미하는 것은 다음과 같다.

OPCODE(31~26) : operation을 나타내는 부분으로 총 6비트 구성, R,I,J의 형식을 구분하며, 함수의 형식을 구분하는 경우도 있다.

rs(25~21) : register의 주소를 나타내는 부분으로 source register을 의미한다. 총 5비트이기 때문에 32개의 register중에서 어느 register을 사용할 지 나타낸다.

rt(20~16) : register의 주소를 나타내는 부분  target register을 의미한다. 총 5비트이기 때문에 32개의 register중에서 어느 register을 사용할 지 나타낸다.

rd(15~11) : register의 주소를 나타내는 부분 destination register을 의미한다. 총 5비트이기 때문에 32개의 register중에서 어느 register을 사용할 지 나타낸다.

shamt(10~6) : Shifting 양을 결정하는 곳으로, 얼마나 shifiting 시킬지를 결정하는 비트이다. 총 5비트

funct(5~0) : 함수를 결정하는 비트로, add, addi, lw, 등 이 비트를 확인하여 어떤 동작을 할 지 결정할 수 있다. 총 6비트

총 6+5+5+5+5+6 비트로 32비트가 만들어지게 되는 것이다. 이렇게 한번에 32개의 비트를 읽을 수 있으므로, MIPS는 32비트 컴퓨터를 구동할 수 있게 된다.

 

2. 예시

그렇다면, 예시를 한 번 살펴보자

만약 add 함수를 호출한다고 생각해보자.

mips 공식 데이터시트에 보면, add는 R format 이며, opcode는 0, function 자리는 20(16진수) 로 나타내면 된다고 한다. 그러면

add $t0, $s1, $s2 

라는 명령어를 작성했다고 생각해보자. 그럼 컴퓨터 내부에서는

opcode : 0, rs : $s1(17), rt : $s2(18). rd : $t0(8), shamt : 0, funct : 32(16진수 20) 로 작성되며

이를 2진수로 표현하면 다음표와 같이 작성 가능하다.

  opcode rs rt rd shamt funct
10진수 0 17 18 8 0 32
2진수 000000  10001  10010  01000 00000  100000  

이를 컴퓨터에서는 16진수로 나타내기도 하며, 여기서는 0232 4020으로 나타낼 수 있다.

이렇게 0과 1을 통해 컴퓨터에게 명령을 내릴 수 있으며, 이런 명령어 집합을 ISA( Instruction set architecture) 라고 이야기한다.

2. I-format instruction 

마찬가지로 I-format도 살펴보자

이번에는 I-Format 형태의 명령어이다. 

OPCODE(31~26) : operation을 나타내는 부분으로 총 6비트 구성, R,I,J의 형식을 구분하며, 함수의 형식을 구분하는 경우도 있다.

rs(25~21) : register의 주소를 나타내는 부분으로 source register을 의미한다. 총 5비트이기 때문에 32개의 register중에서 어느 register을 사용할 지 나타낸다.

rt(20~16) : register의 주소를 나타내는 부분  target register을 의미한다. 총 5비트이기 때문에 32개의 register중에서 어느 register을 사용할 지 나타낸다.

immediate(15~0) : 주소값이나 상수를 나타내는 부분으로, 명령어에 따라서 상수값을 더하던지 혹은 주소값을 표현할 수 있다.

예시로는 addi, lw, sw 등이 있다.

2-1. 16비트 상수만으로 32비트를 제어해야 한다.

여기서 뒤쪽 16비트( immediate(15~0) )의 사용처에 대해서 조금 생각해보자면 과연 16개 비트만으로, 32개의 비트를 사용하는 레지스터에 충분한 값을 공급해야할텐데, 명령어 셋을 확인해보면 이것이 가능하다.

위 사진은 lui 명령어인데, 이를 통해서 레지스터의 상위비트에 16개의 비트를 넣을 수 있다.

그리고 이를 쉬프트 연산을 통해서 이동시키고, 다시 또 상위비트 16개를 넣으면 총 32비트의 연산이 가능해지는 것이다.

(이 외에도 lui, ori를 사용해서 하는 방법도 있다.)

이는 결국 명령어 체계를 만들때, 최대한 32비트 안에서 효율적으로 모든 연산이 가능하도록 명령어 셋을 만들어 낸 결과물이며, 우리 생각으로는 바로 32비트를 넣을 수 있도록 하면 되지 않나? 라는 생각이 들기도 하지만, 그것보다 명령어 셋을 줄이는 것이 더 효율적인 디자인이 될 수 있다는 것을 생각해봐야 한다.

이렇게 우리가 C언어로 작성할 때에는 단순히 코드 작성을 통해 변수를 제어하지만, 실제로 이것이 컴파일이 되어서 0과 1연산을 통해서 제어되는 방식은 우리의 생각과는 조금 다르게 작동한다. 

또 하나 예시로는 만약 어떤 값을 복사한다고 하였을 때, 바로 복사하는 경우도 있겠지마는 실제로는, add 연산을 할때 0을 더하는 식으로 값을 복사하기도 한다.

addi $s0 $s1 0

addi  연산은 상수를 덧셈하는 연산인데, 이렇게 작성하면 S1의 값을 S0에 복사하는 셈이 된다. 

3. J-format

마지막으로 J-format

J-format은 두가지 명령어밖에 없는데, j, jal이 있고, 이는 나중에 프로그램 카운터(PC)를 증가시키거나, 원하는 주소로 건너뛸때 사용된다.

J 명령어는, 뒤쪽에 원하는 주소를 적어 바로 PC를 건너뛰어서 원하는 명령어를 실행하도록 하고

Jal 명령어는 다음 명령어 주소(PC+4)를 저장하고 다음 주소로 이동하는 명령어 입니다. 이는 C언어 코드 작성시에 다른 함수를 호출해야 하는 경우, 혹은 반복문으로 인해 앞으로 돌아가야할 경우등에서 사용되게 됩니다.

이번 글에서는 단순히 명령어 타입에 대해서만 이야기 하고, 조금 더 자세한 함수들의 구조들에 대해서는 차차 하나씩 알아보도록 하겠습니다.

 

4. 디자인 원칙

명령어 포맷을 모두 확인해보았으니, 왜 이런 명령어 체계를 갖게 되었는지 생각해 보아야 합니다.

MIPS 명령어 체계를 디자인할때 4가지 원칙이 있는데, 이는 다음과 같고, 제 나름대로 해석을 넣어보았습니다.

1. Simplicity favors regularity (간단함은 규칙성을 선호한다.) : 규칙성이 일관적이어야 간단하다.

2. Smaller is faster (작은것이 빠르다) : 명령어 집합을 너무 많이 만들거나, 32비트를 넘지 마라

3. Make the common case fast (자주 쓰는 것들을 빠르게) : 산술연산은 간단히

4. Good design demands good compromises (좋은 디자인은 절충이 가능하다) : 간단하게 만드는게 best지만, 필요한 경우에는 쉽게 디자인을 추가하자.

 

반응형