Instruction Set ( 명령어 집합 )
- 컴퓨터에서 사용되는 Instruction ( 명령, 작업 )의 레퍼토리(순서를 가진 목록)
- 다른 컴퓨터는 다른 instruction set을 가짐
- 하지만 대부분 공통된 특성을 가짐
- 초기 컴퓨터는 아주 단순한 instruction set을 가졌었음
- Simplefied implementation
- 복잡한 instruction set으로 고급화, 많은 함수를 제공
- Complex instructino sets (CISC)
- 많은 현대의 컴퓨터들도 단순한 instruction set을 가짐
- Reduced instruction sets(RISC)
The MIPS Instruction Set
- Stanford MIPS는 MIPS Technologies에 의해 상용화 되었다.
- 전형적인 현대의 ISA들과 비슷한 특성들을 공유
- embedded core 시장에서 높은 점유율
- 가전기기, 네트워크/저장장치, 카메라, 프린터 등에 사용됨
- 최근에는 ARM이라는 CPU에도 많이 씀
Arithmetic Operation
- 덧셈과 뺄셈 - 삼항연산
- 2개의 source와 하나의 destination
add a, b, c # a gets b + c
- 모든 산술 arithmetic operation은 위와 같은 형태를 지닌다.
설계 원칙 1: Simplicity favors regularity
- 규칙성은 구현을 수월, 간결하게 해준다.
- 간결함은 낮은 cost에서도 높은 성능을 가능토록 한다.
Arithmetic Example
- c code
f = (g + h) - (i + j);
- Compiled MIPS code
add t0, g, h # temp t0 = g + h add t1, i, j # temp t1 = i + j sub f, t0, t1 # f = t0 - t1
Register Operands
- arithmetic instruction은 register operand를 사용한다.
- 레지스터를 연산처리기로 사용
- MIPS는 32개의 32-bit register file을 갖는다
- 자주 접근하는 데이터를 위한 고속의 저장소
- 0~31까지 번호로 매겨짐
- 32-bit 는 하나의 “word”
- Assembler names
- 임시 값 ( temporary values )
- $t0, $t1, …, $t9
- 저장된 변수 ( saved variables )
- $s0, $s1, …, $s7
설계 원칙 2: 작을 수록 빠르다.
c.f. 메인 메모리는 수백만개의 구역을 가진다.
레지스터는 32-bit가 32개일 뿐이기 때문에 초고속의 메모리
Register Operand Example
- c code
f = (g + h) - (i + j)
- Compiled MIPS code
add $t0, $s1, $s2 add $t1, $s3, $s4 sub $s0, $t0, $t1
Memory Operands
- 메인 메모리는 복합 데이터를 다룬다.
- array, structures, dynamic data
- arithmetic operation을 위해서
- 메모리에서 레지스터로 값을 적재 (load)
- 연산 결과는 레지스터에서 다시 메모리로 가져옴 (store)
- 메모리는 byte단위로 접근함
- 주소 한 칸은 byte로 이루어짐
- word 단위로 메모리에 정렬됨
- 주소들은 4개의 배수. ( 1word = 4byte = 32bit )
- MIPS는 Big Endian이다.
- Most-significant Byte는 가장 작은 자리의 주소에 위치한다. ( byte단위로 거꾸로 들어간다 )
- Big Endian: 가장 왼쪽 byte가 word address이다.
- 뒤집어서 저장. 작은 곳에 큰 자릿수
- MIPS
- Little Endian: 가장 오른쪽 byte가 word address 이다.
- 그대로 저장. 작은 곳에 작은 자릿수
- RISC-V
- MSB (Most significant Bit): 가장 큰 자릿수의 비트. 가장 왼쪽의 비트
- LSB (Least Significant Bit): 가장 작은 자릿 수의 비트. 가장 오른쪽의 비트
Memory Operand Example 1
- c code
g = h + A[8]
→ G는 $s1, h는 $s2에, A의 base address는 $s3에
- Compiled MIPS code
- index 8은 32(4*8 ← 0, 4, 8, 12, …, 32)의 offset을 필요로 함.
- word는 4byte
lw $t0, 32($s3) # load word (메모리($s3)에 담긴 주소(+32)를 이용하여 한 word만큼의 데이터를 $t0에 로드) add $s1, $s2, $t0
Memory Operand Example 2
- c code
A[12] = h + A[8];
→ h는 $s2에, A의 base Address는 $s3에
- Compiled MIPS code
lw $t0, 32($s3) # load word add $t0, $s2, $t0 sw $t0, 48($s3) # store word
Registers vs Memory
- 메모리에 직접 접근하는 것보다 레지스터에 접근하는 것이 훨씬 빠름
- 메모리의 데이터를 레지스터에서 사용하기 위해 레지스터에 데이터를 불러오고 다시 메모리에 저장하는 방법을 사용한다.
- Load-Store Architecture
- 컴파일러는 가능한 변수들을 레지스터를 활용하여 처리해야 한다.
- 변수 처리를 위해 메모리에 접근하는 일을 최대한 줄이기
- 레지스터 최적화는 매우 중요하다.
즉각 연산
→ 변수가 아닌 상수를 사용하여 바로 연산
- instruction에 상수를 사용
addi $s3, $s3, 4
- immediate instruction에 뺄셈은 지원하지 않는다.
addi $s2, $s1, -1
설계 원칙 3: 일반적인 경우를 빠르게 하라.
- 작은 수의 상수는 프로그래밍에서 자주 사용된다.
- immediate operand는 load instruction을 줄여준다.
The Constant Zero
- MIPS 레지스터의 0번 레지스터($zero)는 항상 0이다.
- 값을 변경할 수 없는 고정된 상수. 읽기만 가능
- 많은 작업에 유용하다. ex) 레지스터간의 이동
add $t2, $s1, $zero
Representing Instructions
- instructions는 binary로 인코딩된다.
- binary는 기계어로 불림
- MIPS instructions
- 32-bit의 word로 인코딩된다
- 적은 종류의 포맷(규칙)으로 되어 있다.
Regularity
- 레지스터 번호
- $t0 ~ $t7 ⇒ 레지스터 번호 8 ~ 15
- $t8 ~ $t9 ⇒ 레지스터 번호 24 ~ 25
- $s0 ~ $s7 ⇒ 레지스터 번호 16 ~ 23
Unsigned Binary Integers
- n-bit 수들의 합으로 이루어짐
- 범위: 0 ~ 2^n - 1
- 32비트의 경우
- 0 부터 4,294,967,295
2s-Complement signed Integers
- n-bit 수들의 합으로 이루어짐 (MSB는 부호의 역할)
- 범위: -2^n-1 ~ 2^n-1
- 32비트의 경우
- -2,147,483,648 ~ 2,147,483,647
Signed Negation
비트의 확장
- 같은 수를 더 많은 비트를 이용하면서 표현
- MIPS에서의 instruction set
- addi: immediate value를 늘린다
- lb, lh: loaded byte/halfword를 늘린다
- beq, ben: displacement를 늘린다
- 부호 비트와 같은 값을 왼쪽으로 늘려주면 됨
- unsigned: 0
- Example: 8-bit에서 16-bit
- +2: 0000 0010 => 0000 0000 0000 0010
- –2: 1111 1110 => 1111 1111 1111 1110
MIPS-32 ISA
- Instruction 카테고리
- Computational
- Load/Store
- Jump and Branch
- Floating Point
- coprocessor
- Memory Management
- Special
R format
op(6 bit) | rs(5 bit) | rt(5 bit) | rd(5 bit) | shamt(5 bit) | funct( 6bit) |
명령 종류 구분 | 첫 번째 source 레지스터의 번호 | 두 번째 source 레지스터의 번호 | 결과를 저장할 레지스터의 번호 | shift할 값 (srl, sll) | 명령 종류를 구분하는 번호 |
J format
op(6 bit) | jump target(26 bit) |
명령 종류 구분 | 점프할 명령어의 주소 / 4 |
MIPS Arithmetic Instructions
add $t0, $s1, $s2
- 각각의 세 개의 피연산자는 데이터 경로의 레지스터 파일을 정확히 지정한다.
Instruction format (R format)
0 | $s1 | $s2 | $t0 | 0 | add |
0 | 17 | 18 | 8 | 0 | ㅤ |
000000 10001 10010 01000 00000 100000_2 = 02324020_16
MIPS Register File
- 32개의 32-bit 레지스터들을 갖는다. 이 레지스터 집합에는
- 2개의 read port (src1 addr, src2 addr)
- 1개의 write 포트 (dst addr)
- 32개의 레지스터 주소를 위한 것임으로, 각각 5비트만 담을 수 있어도 충분하다.
- 레지스터는 메인메모리보다 빠르다
- 하지만 구성되는 레지스터 수가 많을 수록 속도는 느리다.
- (e.g., 64개의 레지스터 집합이 32개의 레지스터 집합보다 50% 이상 느릴 수 있다)
- read/write 포트의 증가는 속도에 2차 함수적인 영향을 준다. (정비례가 아니라, ^2)
- 컴파일러가 쓰기에 더 용이하다
- e.g., (A*B) ~ (C*D) ~ (E*F) 어느 순서로든 연산할 수 있다. (스택에 비해)
- 변수를 저장할 수 있다
- 코드의 밀도를 향상시킨다. (레지스터는 메모리보다 적은 비트 수로 불리기 때문에(5bits<32bits))
Stored Program Computers
- instruction들은 binary로 표현된다. 마치 data처럼
- instruction들과 data들은 메모리에 적재(store)된다
- 프로그램들은 다른 프로그램 위에서 동작하기도 한다.
- e.g., 컴파일러, 링커, ...
- Binary compatibility(binary 일치성)은 컴파일된 프로그램들이 다른 컴퓨터에서도 작동하도록 해준다.
- Standardized ISAs (정규화된 ISA)
Logical Operations
- bit단위 조작을 위한 instruction
Operation | C | Java | MIPS |
Shift left | << | << | sll |
Shift right | >> | >> | srl |
Bitwise AND | & | & | and, andi |
Bitwise OR | | | | | or, ori |
Bitwise NOT | ~ | ~ | nor |
- word에서 비트그룹을 추출하거나 새로 집어넣는데 유용하다.
MIPS Shift Operations
op | ㅤ | rt | rd | shamt | funct |
- word에 있는 모든 비트를 왼쪽 / 오른쪽으로 shift
sll $t2, $s0, 8 # $t2 = $s0 << 8 bits srl $t2, $s0, 8 # $t2 = $s0 >> 8 bits
- 빈 공간들은 0으로 채워진다.
- sign bit도 달라질 수 있다.
AND Operations
- word에서 비트마스킹에 용이하다
- 특정 비트들을 선택하고 나머지는 0으로 볼 때
and $t0, $t1, $t2
OR Operations
- word에서 특정 부분의 비트를 포함시킬때 용이하다
- 나머지는 계승시키면서 특정 부분을 1로 만들 때
or $t0, $t1, $t2
NOT Operations
- word의 비트들을 모두 반전시키고 싶을 때 유용
- 0은 1로, 1은 0으로
- MIPS는 NOR 3항 연산으로 구현한다.
- a NOR b는 NOT (a OR b)를 의미한다.
nor $t0, $t1, $zero
MIPS I-format Instructions
op(6 bit) | rs(5 bit) | rt(5 bit) | immediate(16 bit) |
명령 종류 구분 | 첫 번째 source 레지스터의 번호 | 결과를 저장할 레지스터의 번호 | 상수 혹은 주소 값 |
설계 원칙 4: 좋은 설계는 좋은 타협을 필요로 한다.
- Immediate arithmetic과 load/store instruction은 다른 종류의 작업이지만, I-format으로 모두 표현할 수 있다.
- 다른 종류의 작업들을 한 포맷으로 표현하면 decode(복호화, 비트코드를 명령으로 인식)하는 것을 어렵게 만들지만, 32-bit instruction들을 균일하도록 해준다
- 가능한 포맷이 적도록 같은 크기로 표현 가능한 작업들을 묶어야 한다. 고성능을 위해.
MIPS (RISC) Design Principles
- Simplicity favors regularity. 규칙성을 이용하여 간결하게 만든다.
- instruction size 고정
- instruction format의 적은 수
- opcode는 항상 처음의 6 bit
- Smaller is faster. 작을 수록 빠르다.
- 한정된 instruction set
- 레지스터 파일에 한정된 레지스터 수
- Make the common case fast. 일반적인 경우(자주 사용되는 경로)를 빠르게 해라.
- register 파일로부터 계산되는 피연산자들을 가져옴
- 즉각 연산이 가능한 피연산자를 instruction에 포함 가능
- Good design demands good compromises. 좋은 설계는 좋은 타협을 필요로 한다.
- 3개의 instruction format
MIPS Memory Access Instructions
- MIPS는 메모리에 접근하기 위한 두가지의 데이터 전달 instruction이 있다.
- lw, sw
- 5bit address를 사용해서 load, store가 가능하다.
Machine Language - Load Instruction
- Load/Store Instruction Format (I format)
lw $t0, 24($s3)
lw | $s3 | $t0 | 24 |
35 | 19 | 8 | 24 |
Aside: Loading and Storing Bytes
- MIPS에서는 bytes를 옮기기 위해 특별한 instruction을 제공한다.
lb $t0, 1($s3) # load byte from memory sb $t0, 6($s3) # store byte from memory
lb: 메모리 주소 + offset에 존재하는 값의 하위 8/16 비트를 가져와 저장
sb: $t0의 값 중 하위 8/16비트를 메모리 주소 + offset에 저장
MIPS Immediate Instructions
- $zero가 아니어도 작은 상수값들은 보통 자주 쓰이기에 메모리에 넣어놓고 load해온다.
addi $sp, $sp, 4 # $sp = $sp + 4 slti $t0, $s2, 15 # $t0 = 1 if $s2 < 15 else $t0 = 0
큰 수는?
직접 32bit의 constant를 레지스터에 로드하고 싶을 때에는 아래의 두 instruction을 사용해야 한다.
- load upper immediate instruction ( 상위 16비트에 )
lui $t0, 1010101010101010
16 | 0 | 8 | 1010101010101010_2 |
- 아래의 비트를 ori 사용하여
ori $t0, $t0, 1010101010101010
1010 1010 1010 1010 0000 0000 0000 0000
⇒ 1010 1010 1010 1010 1010 1010 1010 1010