ISA
명령어 집합 구조는 마이크로프로세서가 인식해서 기능을 이해하고 실행할 수 있는 기계어 명령어를 말한다.
ISA(Intsruction Set Architecture)는 하드웨어와 소프트웨어의 인터페이스로서 컴퓨터가 인식할수 있는 기계어의 집합을 의미한다.
ISA에는 다음과 같은 것들을 정의한다
- 명령의 종류
- 데이터를 사용하는 방법
- 데이터의 형식
- 명령어의 형식
MIPS ISA
Design Principle
-
Simplicity favors regularity
- 모든 MIPS 산술명령은 연산자 1개와 피연산자 3개를 가진다
- ex) add a, a, b : a = a +b
- 규칙성은 구현을 단순하게 하고 단순함은 적은 비용으로 성능을 향상할 수 있도록 한다
-
Smaller is faster
- 피연산자는 소수의 MIPS 레지스터 중에서 선택한다
- ex) add $t0, $s1, $s2
- 현실에서는 레지스터보다 많은양의 데이터가 유지되어야 하기 떄문에 메모리를 도입한다
- load : 메모리에서 레지스터로 연산을 수행할 값을 불러온다
- store : 연산의 결과를 메모리에 저장한다
- ex) lw $t0, 32($s3) : $t0레지스터에 $s3에 저장된 주소로부터 32비트 떨어진 메모리의 값을 로드
- 메모리의 값을 사용하려면 추가적인 연산(load/store)이 필요하기 때문에 컴파일러는 가능한 레지스터를 사용하는것이 성능향상에 도움이 된다.
-
Make the common case faster
- 작은 값의 상수연산은 메모리를 거치지 않고 직접 수행한다
- ex) addi $t0, $t0, 4
- $zero레지스터는 상수 0을 의미
- ex) add $t0, $t1, $zero : $t0 = $t1(대입)
-
Good design demands good compromise
- 모든 명령을 같은 길이로 통일하고, 유사한 형식을 가지도록 한다
- R-format : 레지스터 연산을 위한 명령어 형식
- op(6bits) rs(5bits) rt(5bits) rd(5bits) shamt(5bits) funct(5bits)
- op(opcode) : 명령의 종류
- rs : first source
- rt : second source
- rd : destination
- shamt : shift amount
- funct : function code
- ex) add $t0, $t1, $t2 : op=0 rs=$t1 rt=$t2 td=$t0 shamt=0 funct=32(add)
- I-format : 상수 및 메모리 연산을 위한 명령어 형식
- op(6bits) rs(5bits) rt(5bits) Constant_or_Address(16bits)
- ex) lw $t0, 32($s0) : op=35(lw) rs=$s0 rt=$t0 address=32
Data Representation - Numbers
- MIPS에서 숫자는 2진수 word(32bit)길이의 Big endian방식으로 저장된다.
- Big endian : Most Significiant Byte를 먼저 저장(왼쪽부터 앞 주소)
- Little endian : Least Significiant Byte를 먼저 저장(오른쪽부터 앞 주소)
- Unsigned numbers : 2진수 그대로 표현
- Signed numbers : 음수를 2의 보수로 표현
- 2의 보수 : 이진수에 1의보수를 취한 뒤 1을 더한 값
- ex) 1 = 001 -> -1 = (1의 보수)110 -> (2의 보수)111
- 음수를 2의 보수로 표현하면 일반적인 산술연산을 통해 모든 수의 계산이 가능함
- Signed extension : n-bit 숫자를 n-bit이상으로 확장할 때에는 sign bit만 왼쪽으로 복사한다(sign bit : 가장 왼쪽 비트)
- ex) -1 = 1111 1111 -> 1111 1111 1111 1111
MIPS-based CPU
- Control Unit : 프로세서의 동작을 결정함
- Arithmetic&Logic Unit : 연산을 수행함
- Register : 연산에 사용되는 값들을 저장함(general purpose register)
- Program Counter : 다음으로 수행될 명령의 메모리상의 주소를 저장함
- Instruction Register : 현재 명령을 저장함
- 명령이 수행되는 과정
- fetch : Control unit이 PC에 저장된 메모리 주소에 있는 명령을 IR로 로드함
- decode : Control unit이 IR에 저장된 명령을 해석함
- execute : ALU가 연산을 수행함
Operations
operation | MIPS | 비고 |
---|
Add | (R)add,(I)addi | |
Subtract | (R)sub | |
Bitwise OR | (R)or,(I)ori | |
Bitwise NOR | (R)nor | NOT = nor a, b, $zero |
Bitwise AND | (R)and,(I)andi | |
Shift left | (R)sll | |
Shift right | (R)srl | |
Branch equal(==) | (I)beq | |
Branch not equal(!=) | (I)bne | |
Jump | (J-format)j | J-format : op(6bits) LABEL(26bits) |
Set on less than(<, signed) | (R)slt, (I)slti | slt + beq = bge, slt + bne = blt |
Set on less than(unsigned) | (R)sltu, (I)sltui | |
Procedures
- 프로그램 속 함수
- caller와 callee로 구분
Calling - Returning Process
- caller가 callee에게 argument를 넘겨주고 주솟값을 전달함
- caller가 callee에게 컨트롤을 넘겨줌
- callee가 연산을 수행함
- callee가 caller에게 return value룰 전달함
- callee가 caller에게 받은 주솟값으로 컨트롤을 넘겨줌
- caller는 저장된 값을 복원함
caller와 callee는 레지스터를 사용하여 매개변수와 주솟값, return value를 교환한다
- $v0 ~ $v1 : return values from functions
- $a0 ~ $a3 : arguments to funxctions
- $ra : return address
여러 프로시저가 같은 레지스터를 사용한다면 레지스터의 값이 덮어쓰여질 수 있는데, 이를 방지하기 위해 스택을 사용한다
- 각각의 프로시저를 수행하는데 필요한 정보는 스택에 저장된다
- $sp : stack pointer. 스택의 top을 가리키는 주소
Register Saving
몇몇 레지스터들은 프로시저 콜 이후에 복구가 가능해야 한다
- preserved register : 값이 유지되어야 하는 레지스터
- $s0 ~ $s7 : saved variables
- $gp : global pointer
- $sp : stack pointer
- $fp : frame pointer
- $ra : return address
- non-preserved register : 임시로 사용되는 레지스터
- $v0 ~ $v1 : return values
- $a0 ~ $a3 : arguments to functions
- $t0 ~ $t9 : temporary variables
이를 위해 caller와 callee는 각각 아래의 작업을 수행하여야 한다
- Callee가 preserved register를 사용하는 경우
- Save after calling : 프로시저 호출 이후 레지스터의 값을 스택에 보관한다
- Restore before returning : 컨트롤을 반환하기 전에 스택의 값을 레지스터로 복구한다
- Caller가 non-preserved register의 값을 유지해야 하는 경우
- Save before calling : 프로시저 호출 전에 레지스터의 값을 스택에 보관한다
- Restore after returning : 컨트롤을 돌려받은 이후 스택의 값을 레지스터로 복구한다
Instructions
- jal PROCEDURE_LABEL : $ra에 return address를 저장하고 PROCEDURE_LABEL로 jump(call)
- jr $ra : $ra로 jump(return)
- addi $sp, $sp, -4 // sw $t0, 0($sp) : push to stack
- lw $t0, 0($sp) // addi $sp, $sp, 4 : pop from stack
MIPS Memory Allocation
Local data
Procedure call로 인해 스택에 데이터가 저장되면 첫번째 스택 프레임의 위치를 $fp에 저장해두고 함수가 실행되는 동안 $fp를 유지하여 참조변수를 저장한다.
Data and Code
MIPS에서 메모리의 낮은 주소에는 코드가, 높은 주소에는 데이터가 저장된다.
- Code : 명령어 정보를 저장하는 공간. Program Counter에 저장되는 주솟값의 범위
- Global variable : 전역변수가 저장되는 공간. Code 바로 다음에 위치. $gp에 주솟값 유지
- Activation records : 프로시저가 수행되는 동안 보관되는 정보가 저장되는 스택공간. 높은 주소부터 낮은 주소로 증가. $sp에 주솟값 유지
- Dynamically-allocated data : 동적으로 할당되는 데이터가 저장되는 힙 공간. 낮은 주소부터 높은 주소로 증가.
Addressing Mode
- Immediate addressing : 명령에 포함된 데이터에 직접 접근
- immediate operands
- ex) addi $t0, $t1, 4 <- constant에 직접 접근
- Register addressing : 명령에 사용된 레지스터에 저장된 데이터에 접근
- register operands
- ex) addi $t0, $t1, 4 <- register 주소를 통해 데이터에 접근
- Base addressing : 메모리의 시작주소와 offset을 통해 메모리에 접근
- data transfer instructions
- ex) lw $t0, 32($s0) <- 레지스터에 저장된 주솟값에 offset을 더해 target address를 계산하여 데이터에 접근
- PC-relative addressing : PC레지스터와 offset을 통해 메모리에 접근
- branch instructions
- ex) bne $t0, $t1, LABEL <- PC레지스터에 offset*4를 더해 target address를 계산하여 메모리에 접근
- Pseudo direct jump addressing : PC레지스터와 instruction에 포함된 address를 통해 메모리에 접근
- branch instructions
- ex) j LABEL <- PC레지스터의 값과 address를 이어붙여 나온 주솟값으로 메모리에 접근