# 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 ![](https://i.imgur.com/La4uHsg.png) - 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 ```