MIPS의 여러 Instructions에 대해 살펴보자.
Logical Operations
AND Operation (R-format)
word에서 특정 부분의 bit들을 mask할 때 유용하다.
- 특정 bit들을 선택하고, 나머지는 0으로 둔다.
OR Operation (R-format)
word에서 특정 부분을 포함시키고 싶을 때 유용하다.
- 특정 bit 부분을 무조건 1로 바꾸고, 나머지는 그대로 계승한다.
NOT Operation
word의 bit들을 모두 반전시키고 싶을 때 유용하다. (0 -> 1, 1 -> 0)
- MIPS는 not inst.를 따로 만들진 않았고, nor를 활용하여 NOT을 구현하였다.
- a NOR b => NOT (a OR b)이므로, b=0일 경우 NOT (a OR 0) = NOT a가 된다.
Shift Operations (R-format Instruction)
모든 bit들을 왼쪽/오른쪽으로 몇 칸이나 shift 시킬 것인가
sll
- 왼쪽으로 shift
- 전체 bit들이 왼쪽으로 이동하며, 이동하면서 생기는 오른쪽의 빈 공간들은 0으로 채워진다.
- sll $t2, $s0, 8 # s0에 담긴 값을 8bits만큼 왼쪽으로 shift 시켜 t2에 담는다.
- i비트만큼 왼쪽으로 shift한 것은, 2^i만큼 곱한 것과 같다.
slr
- 오른쪽으로 shift
- 전체 bit들이 오른쪽으로 이동하며, 이동하면서 생기는 왼쪽의 빈 공간들은 0으로 채워진다.
- i비트만큼 오른쪽으로 shift한 것은, 2^i만큼 나눈 것과 같다. 이 때, 부호가 있는 표현에서는 MSB가 0이 되므로 음의 여부도 달라질 수 있으니 유의해야 한다.
Conditional Operations
조건(condition)에 대한 operations.
조건이 true라면 label된 Inst.로 향하게 하는 branch. false라면 그대로 진행
MIPS Control Flow Instructions (I-format)
bne $s0, $s1, Lbl # $s0 != $s1이라면 Lbl로 가라
beq $s0, $s2, Lbl # $s0 == $s1이라면 Lbl로 가라
예제
C code:
if (i == j) f = g + h;
else f = g - h;
(f=$s0, g=$s1, h=$s2, i=$s3, j=$s4)
MIPS code:
beq $s3, $s4, Else
sub $s0, $s1, $s2
j Exit
Else: add $s0, $s1, $s2
Exit: ...
C code:
while (save[i] == k) i+=1;
(i=$s3, k=$s5, save의 시작 주소=$s6)
MIPS code:
Loop: sll $t0, $s3, 2 #현재 save의 base address인 $s6에 i번째 index만큼 이동하여 가기 위해서는 $s6 + (4*i)가 되어야 한다.
add $t0, $t0, $s6
lw $t1, 0($t1)
bne $t1, $s5, Exit
addi $s3, $s3, 1
j Loop
Exit: ...
More Branch Instructions
좀 더 조건적인 Inst. (조건이 true라면 결과를 1로 만들고, 아니라면 0으로 만든다)
slt rd, rs, rt
- if (rs < rt) rd = 1; else rd = 0;
slti rt, rs, constant
- if (rs < constant) rt = 1; else rt = 0;
bne, beq와 혼합하여 사용한다.
slt $t0, $t1, $t2 # $t1 < $t2라면 $t0를 1로, 아니라면 0으로
beq $t0, $zero, L # $t0가 0이라면 L로
=> 이렇게 혼합하여 사용해서 less than등을 표현할 수 있다.
Branch Instruction Design
왜 blt(branch less than), bge(branch greater or equal) 등은 없는가?
- 하드웨어 입장에서 <, ≤ 등의 연산은 =, ≠보다 느리다.
- 모든 branch Inst.를 지원하면 한 inst.마다 기존보다 더 많은 일을 수행하게 되고, 클럭 속도가 느려진다. => 모든 Inst.가 불이익을 받는다. (클럭 속도가 느려지므로)
- 그리고 beq, bne는 자주 쓰이는 Inst. 이다. (MIPS의 좋은 설계를 위한 적당한 타협 설계 규칙)
Signed vs. Unsigned
부호가 있는 비교: slt, slti
부호가 없는 비교, sltu, sltui
예제
$s0 = 1111 1111 1111 1111 1111 1111 1111 1111
$s1 = 0000 0000 0000 0000 0000 0000 0000 0001
slt $t0, $s0, $s1 => $t0 = 1 ($s0 < $s1 이기 때문)
sltu $t0, $s0, $s1 => $t0 = 0 ($s0 > $s1이기 때문)
Branching Far Away
만약 branch 명령어의 destination이 16bits 범위보다 훨씬 멀리 있는 경우 어떻게 해야 할까?
jump instruction (J-format)
op (6bits): opcode
address (26bits): target 주소
- target 주소는 26bits지만, PC에서 4bits를 가져오고, 끝에 2bits를 00을 붙여서 32bits를 만든다.
이제 16bits보다 먼 범위를 jump해보자.
beq $s0, $s1, L1에서 L1이 먼 주소라고 한다면
bne $s0, $s1, L2
j L1
L2: ...
로 표현할 수 있다.