使用Spike执行RISC-V gnu toolchain编译出来的ELF档,就可以得到完整执行此EFL档需要用到哪些指令。利用script统计後可以得到如下结果:
指令 | 执行次数 | 指令 | 执行次数 | 指令 | 执行次数 | 指令 | 执行次数 |
---|---|---|---|---|---|---|---|
c.addi | 22 | c.bnez | 6 | c.sub | 3 | jalr | 1 |
c.swsp | 22 | c.add | 6 | srai | 3 | c.andi | 1 |
c.lwsp | 21 | c.sw | 6 | bgeu | 2 | bltu | 1 |
addi | 14 | c.lw | 6 | andi | 2 | blt | 1 |
c.li | 14 | c.lui | 6 | slli | 2 | bltz | 1 |
sb | 13 | c.j | 5 | sw | 2 | c.slli | 1 |
lw | 11 | auipc | 4 | sub | 2 | sll | 1 |
c.mv | 10 | beqz | 4 | c.addi4spn | 2 | c.and | 1 |
ret | 10 | c.jalr | 4 | c.addi16sp | 2 | lbu | 1 |
c.beqz | 9 | li | 4 | beq | 2 | ecall | 1 |
c.jal | 6 | bne | 4 |
以上表格是根据执行次数的多寡来排序,这次就先处理第一个指令c.addi。
首先在RVCore中新增inst_c_addi成员函式:
impl RVCore {
fn inst_c_addi(&mut self, inst: &inst_type::InstType) {
if inst.get_rd() != 0 {
self.regs[inst.get_rd()] = self.regs[inst.get_rd()] + inst.get_imm_ci();
}
}
}
其中的get_rd(), get_imm_ci()等函式可以参考c.addi的spec:
inst参数是指令经过decode之後得到的,InstType定义如下:
pub enum InstID {
C_ADDI,
}
pub struct InstType {
pub data: u32, // 从memory fetch到的指令
pub len: u32, // 指令长度
pub id: InstID, // 指令ID,由decoder填上
}
接下来实作c.addi的UT:
fn inst_c_addi_code(rd: u32, imm: u32) -> InstType {
InstType {
data: (((imm >> 5) & 1) << 12) | (rd << 7) | ((imm & 0x1f) << 2) | 0x1,
len: 2,
id: InstID::C_ADDI,
}
}
#[test]
fn test_inst_c_addi() {
let mut core: RVCore = Default::default();
core.regs[2] = 0x1234;
core.inst_c_addi(&inst_c_addi_code(2, 0x1));
assert_eq!(0x1235, core.regs[2]);
}
如此就完成了c.addi指令的实作,其他指令也可以比照办理,完整程序码可以参考此连结。
今天我们要来将 Chatbot 与 Language Understanding Service (...
昨天主要描述在心理层面应该要注意的事情,今天则是从实际层面上细数在自学并准备 APCS 时会碰到什麽...
开发过程中常常会需要使用console.log()来检视输出是否正确,所以能够妥善运用各种conso...
哈罗大家好~ 关於 SharePoint 的应用,到昨天告一段落,回顾一下你可能会觉得,文件库、清单...
这一篇要跟大家分享的是,直接在程序码的地方建立一个资料表,除了用之前的方法,还可以用下面这个方法 C...