Skip to content

Instantly share code, notes, and snippets.

@wanabe
Last active August 10, 2024 10:37
Show Gist options
  • Save wanabe/2fd182293aa623a32df39d08fd2a65f7 to your computer and use it in GitHub Desktop.
Save wanabe/2fd182293aa623a32df39d08fd2a65f7 to your computer and use it in GitHub Desktop.

なつやすみのにっき 2024/08/10

ふと RISC-V を試したくなりました

ので docker + qemu で試してみます。

ファイルを作った後 WSL で以下のようにして環境を作りました。

sudo apt install qemu-user-static
docker compose build

アーキテクチャのエミュレーションが挟まるのでただの apt update でも大変遅いです。待つしかありません。 環境が出来上がったら、C のコードをビルドしてみます。

make で出来上がったものがこちらです。

なるほど何もわからない。RISC-V の呼び出し規約も命令セットも知らないのでわかるわけがない。 "riscv (abi OR call-convention)" で Google 検索してみると、日本語もわかりやすい解説、riscv.org 公式など多数の文書が見つかります。

あたりが今もっとも欲しい情報に近そうです。なんとなく読み取れた情報を列挙します。

  • (float 系はややこしくなるのでとりあえず無視する)
  • x0-31 のレジスタがある
  • レジスタは役割によって別名がついている
    • x0
      • zero
    • x1
      • ra
    • x2
      • sp
    • x3
      • gp
    • x4
      • tp
    • x5 - x7
      • t0 - t2
    • x8 - x9
      • s0 - s1
    • x10 - x17
      • a0 - a7
    • x18 - x27
      • s2 - s11
    • x28 - x31
      • t3 - t6
    • (aarch64 に馴染みがあれば理解は早いかも?すみません適当言っています)
  • スタックポインタ sp (x2)を減算してヒープ=作業領域を確保する。
    • (だいたいそうだと思うので当たり前と言えば当たり前かもしれない)
    • addi sp, sp, -48 のように負数を add する
      • sub とは言わないようだ
  • sd s0, 32(sp) は「レジスタ s0(x8)の値を (sp+32) 番地に store (書き込み)する 」と読む
  • ld s0, 32(sp) は「レジスタ s0(x8)に (sp+32) 番地の値を load (読み込み)する 」と読む
  • retjr ra つまり「レジスタ ra(x1)の値の番地にジャンプする」と読む

ほんのり何かわかった気になってきました。ここで命令列も見てみます。やっとです。普通最初に見るべきでは?というのはその通りなのですが、いきなりドカンと命令列を見ても結局よくわからなさそうだと思ったので後回しにしました。

ざっと見た感想を列挙します。

  • 末尾の "i" は immediate つまり即値を表していそう
  • x0 が常にゼロなことを利用して x0 +- imm をするパターンが面白い
  • mv reg1, reg2 は reg1 reg2 の値 入れるということで、直感的な並び順でよかった
    • store 系も mv と同じ順、つまり dst, src の並びにした方が覚えやすいのでは?と個人的には思う
    • load 系と同じ並びにすることに何か意味があるんだろうからそこはそういうものだと思うしかない
  • "c." で始まる圧縮命令がかなり多そう

ところで

楽な方法ばかり取っていましたが、公式ドキュメントが正しい拠り所であろうとは思います。

ところで(2)

「りすくぶい」って勝手に読んでたんですが「りすくふぁいぶ」なんですね。 RISC-I, RISC-II, SOAR, SPUR があって 5 世代目とのこと。へー。

services:
riscv64:
platform: linux/riscv64
build:
context: .
volumes:
- "./:/work"
working_dir: /work
FROM ubuntu:24.10
RUN apt update -y && apt install -y build-essential
CFLAGS = -O0
files != ls *.c|sed -e 's/\(.*\)\.c/\1.s \1.dump/'
.PHONY: all clean
.SUFFIXES: .c .o .s .dump
all: $(files)
@:
clean:
rm -f *.o *.dump *.s
.c.o:
cc $(CFLAGS) -c $<
.c.s:
cc $(CFLAGS) -S $<
.o.dump:
objdump -S $< > $@
int main(void) {
return 0;
}
test1.o: file format elf64-littleriscv
Disassembly of section .text:
0000000000000000 <main>:
0: 1141 addi sp,sp,-16
2: e406 sd ra,8(sp)
4: e022 sd s0,0(sp)
6: 0800 addi s0,sp,16
8: 4781 li a5,0
a: 853e mv a0,a5
c: 60a2 ld ra,8(sp)
e: 6402 ld s0,0(sp)
10: 0141 addi sp,sp,16
12: 8082 ret
.file "test1.c"
.option pic
.attribute arch, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0"
.attribute unaligned_access, 0
.attribute stack_align, 16
.text
.align 1
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
addi sp,sp,-16
.cfi_def_cfa_offset 16
sd ra,8(sp)
sd s0,0(sp)
.cfi_offset 1, -8
.cfi_offset 8, -16
addi s0,sp,16
.cfi_def_cfa 8, 0
li a5,0
mv a0,a5
ld ra,8(sp)
.cfi_restore 1
ld s0,0(sp)
.cfi_restore 8
.cfi_def_cfa 2, 16
addi sp,sp,16
.cfi_def_cfa_offset 0
jr ra
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 14.2.0-1ubuntu1) 14.2.0"
.section .note.GNU-stack,"",@progbits
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment