owned this note
owned this note
Published
Linked with GitHub
[TOC]
# 2.1 Instruction 設計哲學
## 簡單明瞭有助於一致性 (Simplicity favors regularity)
:::info
**Arithmetic Operations**:
``` =mips
add a,b,c #a = b + c,
```
所有的算術算子都是這個規格。
:::
## 小就是快 (Smaller is faster)
:::success
- **Register Operands**:
- arithmetic operations拿register operands來操作,因為register小所以快,MIPS擁有32 × 32-bit register file,也就是8*8 byte register,32bit又稱做一個word,t0 t9是暫存用,s0 s9是儲存用。
- **Memory Operands**:
- 但有時也需要使用較大的空間,因此有memory operands,需要load和store因此較慢,compiler會盡量使用register operands。
:::
## 讓常出現的部分加快 (Make the common case fast)
Immediate Operands:因為小的常數操作常出現,因此有immediate operands避免掉一個load,例如addi s3,s3, 4。
The Zero Constants:MIPS register 0 (zero)裡面只裝常數「0」,不能被覆寫,常用來移動值,例如addt2, s1,zero。
## 好的設計需要好的折衷辦法 (Good design demands good compromises)
R-format、I-format、J-format:根據需求有不同的format,但都是32bit且各個format盡量相似,以下是各種format。
## 以下是一些memory operands的特性:
:::info
### byte addressed:
每1個位址代表1個byte (8 bits)
:::
:::success
### Alignment:
為了加快執行速度,在讀 memory的時候會以一個 word 為單位,因此 data 在儲存時,memory offset 便會是 word size 倍數,藉此增加效能。
:::
:::info
### Big Endian and Small Endian:
MIPS在一個word內的存放順序是Big Endian,most-significant byte在位址數目最小的位子
- ex:0x12345678 (word內的順序)

:::
:::success
- 讓常出現的部分加快 (Make the common case fast)
- **Immediate Operands**:因為小的常數操作常出現,因此有immediate operands避免掉一個load,例如`addi s3,s3, 4`。
- **The Zero Constants**:MIPS register 0 (*zero*)裡面只裝常數「0」,不能被覆寫,常用來移動值,例如`add $t2, $s1,$zero`。(標示數值)
:::
:::danger
- 好的設計需要好的折衷辦法 (Good design demands good compromises)
**R-format**、**I-format**、**J-format**:根據需求有不同的format,但都是32bit且各個format盡量相似,以下是各種format。

:::
### three big type review
:::success
所有的BITS 加起來都要是32bits
:::
R type

I type

J type

## 2.2 MIPS Quick Look
重要暫存器一覽

指令格式一覽

### **重要的指令碼一覽**
:::info
- add :*op =0* ,**funct=32**
``` =mips
add a,b,c #a = b + c,
```
- sub : *op =0* ,**funct=34**
``` =mips
add a,b,c #a = b - c,
```
- addi: *op= 8* #<font color="#f00">加法**(立即值用)**</font>
:::
:::danger
- lw : *op =35* #<font color="#f00">讀檔</font>
- <font color="blue">lw $t0, 20($a0) # $t0 = Memory[$a0 + 20]</font>
- sw : *op =43* #<font color="#f00">存檔</font>
- <font color="blue">sw $t0, 20($a0) # Memory[$a0 + 20] = $t0</font>
:::
:::info
- move: **
- beq : *op =4* #比較是否相等
- bne : *op =*5 #比較是否不相等
- sll : *op =0* ,**funct=0** #左移
- slt : *op =0* ,**funct=42** #比較大小
- j : *op= 2*
:::
- 重要範例程式:procedure call以階乘為例,對照著activation record練習
- 進入procedure:下一行指令的位址放入$ra並跳到目標位址
- 離開procedure:把$ra裡的位址取出回到母函式


### **Addressing and Memory Accesses**
### leaf &noleaf
:::warning
- **Leaf** procedures: procedures that do not call others末端程序:本身是程序,而且不呼叫別的程序
- 
:::spoiler

1. 我們這邊會去算一次之後會去 POP 數值到 RIG 內部
2. 還原回原來的數值
:::
:::warning
- **No leaf** Procedures: procedures that call other procedures非末端程序:本身是程序,而且也呼叫別的程序() **遞迴**
- 
:::spoiler

:::
### loop(交大考題!!!)
:::info
### loop1
``` =c
clear1(int array[], int size)
{
int i;
for (i = 0; i < size; i += 1)
array[i] = 0;
}
```
:::spoiler
``` mips
move $t0,$zero # i = 0
loop1: sll $t1,$t0,2 # $t1 = i * 4
add $t2,$a0,$t1 # $t2 = address of array[i]
sw $zero, 0($t2) # array[i] = 0
addi $t0,$t0,1 # i = i + 1
slt $t3,$t0,$a1 # $t3 = (i < size)
bne $t3,$zero,loop1 # if (i < size) go to loop1
```
:::
:::info
### loop 2
``` c
clear2(int *array, int size)
{
int *p;
for (p = &array[0]; p < &array[size]; p = p + 1)
*p = 0;
}
```
:::spoiler
``` mips
move $t0,$a0 # p = address of array[0]
loop2: sw $zero,0($t0) # Memory[p] = 0
addi $t0,$t0,4 # p = p + 4
sll $t1,$a1,2 # $t1 = size * 4
add $t2,$a0,$t1 # $t2 = address of array[size]
slt $t3,$t0,$t2 # $t3 = (p<&array[size])
bne $t3,$zero,loop2 # if (p<&array[size]) go to loop2
```
:::
:::warning
- Jump指令 (Pseudo-direct addressing)
- 有限的32位指令長度對於大型程序的分支跳轉支持確實是個難題。MIPS指令中最小的操作碼域占6位,剩下的26位用於跳轉目標的編址。由於所有指令在記憶體中都是4 word對齊的,因此最低的2個地址位是無需存儲的,這样可供尋址範圍为**2^(26+2)=256** MB。分支跳轉地址被當做一個256 MB的段內絕對地址,而非PC相對尋址。這對於地址範圍超過256 MB的跳轉程序而言是無能为力的,所幸目前很少遇到這麼大的遠程跳轉需求。
- Branches out of segment
- 段外分支跳轉可以使用暫存器跳轉指令實現,它可以跳轉到任一32位地址。
``` mips
beq $at, $0, L
add $v1, $v0, $0
add $v1, $v1, $v1
j Somewhere
L: add $v1, $v0, $v0
```
- Conditional branches
- 條件分支跳轉指令opcode的後16位branch offset是相對PC的有號偏移量,由於指令是4 word對齊的,因此可支持的跳轉範圍實際上是`2^(16+2)=256KB`**(相對PC的-128 KB~+128 KB)**。如果確定跳轉目標地址在分支指令前後的128KB範圍內,編譯器就可以編碼只生成一條簡單的條件分支指令。
:::