# Compiler HW3 Guide
簡單說明一下寫作業三需要的小技巧。
- 完整的規格書
- 指令的行為
- 64 bits environment
- toolchain 常用指令
## 完整規格書
附在作業公告的是基本指令(Base)的規格書。裡面其實有太多作業用不到的資訊了。
參考連結
[The RISC-V Instruction Set Manual](https://content.riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf)
## 指令行為
最常用的指令
- Memory load store
- ld
- load double word to memory
- `ld rd, offset(rs1)`
- sd
- store double word to memory
- `sd rd, offset(rs1)`
- lw
- load word to memory
- `lw rd, offset(rs1)`
- sw
- store word to memory
- `sw rd, offset(rs1)`
> 這裡指的 word 為 32 bits
- Arithmetic
- add
- `add rd, rs1, rs2`
- sub
- `sub rd, rs1, rs2`
- mul
- `mul rd, rs1, rs2`
- div
- `div rd, rs1, rs2`
> 就是字面上的意思
- Jump
- bne
- if rs1 != rs2 then jump to label
- `bne rs1, rs2, label`
- blt
- if rs1 < rs2 then jump to label
- `blt rs1, rs2, label`
- beq
- if rs1 == rs2 then jump to label
- `beq rs1, rs2, label`
- bgt
- if rs1 > rs2 then jump to label
- `bge rs1, rs2, label`
## 64 bits environment
有部份的指令會因為 32 bits 與 64 bits 環境的部份而有不一樣的行為。
典型的範例就是 Arithmetic 系列指令。
因為一個 Register 從 32bits -> 64bits。所以原本指令從
32bits <- 32bits + 32bits
變成
64bits <- 64bits + 64bits
再者因為register變大。alloc 給某些變數的空間也要變大。
> 除非你有特別的需要你的變數一定要小於register的大小。像是 int 若規定只有 32 bits,那就只需要alloc 4 byte 就好。
## 常用 toolchain 指令
- `riscv64-unknown-elf-gcc`
- 實際上就是 gcc,只是 target 被換成riscv64
- `spike`
- 一個模擬器,可以執行riscv的執行檔
- `riscv64-unknown-elf-objdump`
- 拆開可執行檔(elf)
```
# From assembly to elf
riscv64-unknown-elf-gcc yourfile.s -o outfile
# From .c to assembly file
riscv64-unknown-elf-gcc -S yourfile.c
# Run the elf
spike pk your_elf_file
# Check each instruction address
riscv64-unknown-elf-objdump -dC your_elf_file > log
# find with label or function name
grep -rni "main" log
less log
```
## Spike Debug mode

- enable debug mode
```
spike -d pk your_elf_file
```
- debug mode usage
```
# Here 0 is mean the label of cpu,
# but we run single core only
# Check reg value
reg 0
# Check Mem value
mem 0 address
# Jump to some pc
until pc 0 pc_address
```