Skip to the content.

参考文档里介绍了32位和64位的规格,只关注64位。 操作系统部分涉及到的指令集其实不太多,比如浮点单元之类的就不需要。

数据类型

RV64 中 C 类型定义如下:

参数:

RV64中约定,尽可能使用寄存器来传递参数,最多8个(a0-a7,浮点fa0-fa7),一般按顺序传递。

小于64位的参数,将在寄存器低位上存储,RV64是小端(little edtion)系统。

2*64bit大小的参数,使用两个寄存器进行存储,并且对齐。

大于两倍的参数,使用引用传参

没有使用寄存器传参的使用stack,sp指向第一个;

返回值:

返回值保存在a0,如果不够a1,(同样的浮点寄存器就是fa0,fa1)。 只有很小的返回值才直接放入寄存器,大个的返回值都将保存在内存中。

caller(调用者)分配内存,callee(被调用者)将值写入到指定位置。

标准RV调用中,栈向下增长,并16bit对齐。

其他寄存器

t0-t6,是在函数中临时使用的,由caller保存; s0-s11,如果使用,由callee保存;

总结图如下:

xv6-riscv中的swtch函数

参考https://github.com/mit-pdos/xv6-riscv/blob/riscv/kernel/swtch.S

函数swtch,为了与C关键字switch区别,改为swtch,它的作用是xv6中切换内核线程, 不过使用汇编代码编写,如果用C定义如下:

void swtch(struct context *old, struct context *new);

内核线程之间切换,它们同属一个内核运行进程中,其实就是寄存器的切换。 根据上面说到的规则(gcc或其他编译器,会保证规则被正确使用),需要保存和恢复的寄存器是:

参考