前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >riscv gcc中添加自定义的csr支持

riscv gcc中添加自定义的csr支持

作者头像
bigmagic
发布2021-08-20 15:14:22
1.6K0
发布2021-08-20 15:14:22
举报
文章被收录于专栏:嵌入式iot嵌入式iot

riscv gcc中添加自定义的csr支持

  • 1.概述
  • 2.不改变编译工具链实现CSR添加
  • 3.在编译器中集成CSR名称
  • 4.编译开发riscv gcc相关
  • 5.小结

1.概述

由于RISCV的模块化的指令集的定义,各家都有着自己的实现方式。从当前看来,除了标准的CSR外,很多都实现了自己的CSR指令扩展。如何自定义CSR并且让编译器能够识别,本文将进行一定的分析,同时从riscv gcc开发的角度出发,来分析编译器开发的流程。

2.不改变编译工具链实现CSR添加

如果想读写CSR,可以使用汇编指令进行操作。

代码语言:javascript
复制
void test_csr()
{
  int a = 0x00200;
  asm volatile("csrw 0x307,%0"::"r"(a));
}

通过反汇编

代码语言:javascript
复制
riscv32-unknown-elf-objdump -D virt_test.elf > 1.txt

得到该函数的汇编代码

由于编号为0x307的CSR没有标准定义,所以会直接会体现在汇编函数中。但是这样并不会影响功能的使用。

对于这些非标准的CSR的读写操作,RISCV GCC并不会根据特定的编码序号生成相应的名称。

比如芯来科技为其eclic定义的一条CSR。

如果用标准的GCC进行编译,那么需要给定CSR地址(0x7ed)。

这样的实现,在写汇编函数的时候,给定CSR的地址即可,不能写名字。比如:

代码语言:javascript
复制
csrw 0x7ed,zero

通过上述的方式,可以完成不改变编译器的情况下,实现非标准的CSR的操作。

3.在编译器中集成CSR名称

往往通过汇编去查看时,若没有CSR名称,直接去查看CSR的地址,有时候还需要通过CSR的地址,查阅相关的寄存器手册,才能明白读写哪个寄存器。为了简化这种操作,可以将CSR的名称添加到gcc中。这里借用玄铁C906上的扩展指令进行实验。

如果不想改变gcc,那么实现上直接可以通过内联汇编。

代码语言:javascript
复制
void test_csr()
{
  int a = 0x00200;
  asm volatile("csrw 0x7c0,%0"::"r"(a));
}

那么最后反汇编得到结果如下:

这显然还是不够直观。

为了让其更加的直观,可以修改RISCV工具链。

这里使用的是riscv-gnu-toolchain,目前做编译器开发需要对该仓库的使用非常熟悉。

代码语言:javascript
复制
https://github.com/riscv/riscv-gnu-toolchain.git

将代码进行clone后,更新子模块。

代码语言:javascript
复制
git submodule init
git submodule update

其中需要修改的是riscv-gnu-toolchain/riscv-binutils/include/opcode/riscv-opc.h

同时将MXSTATUS的地址添加进去。

这样就能够,编译工具链,用生成的编译工具链去编译代码,就能够正常的看到反汇编的执行效果了。

这样,无论是传递地址csrw 0x7c0,zero,还是传递名称csrw mxstatus,zero,汇编器都能够正常的输出CSR名称。

通过对编译器的修改,也是非常的简单的实现了这个功能。

4.编译开发riscv gcc相关

如果要研究riscv gcc的开发工作,搭建环境,加快编译效率很关键。由于编译工具链很大,涉及到的模块很多,而且编译的过程很复杂,为了节省编译的时间,可以通过编译选项来进行约束。

通常情况下,编译全功能的gcc,可以采用

代码语言:javascript
复制
./configure --prefix=$PREFIX --enable-multilib --with-cmodel=medany

当使能了--enable-multilib,就能够编译很多版本的lib库。

代码语言:javascript
复制
./riscv64-unknown-elf-gcc --print-multi-lib
.;
rv32i/ilp32;@march=rv32i@mabi=ilp32
rv32ic/ilp32;@march=rv32ic@mabi=ilp32
rv32im/ilp32;@march=rv32im@mabi=ilp32
rv32imc/ilp32;@march=rv32imc@mabi=ilp32
rv32iac/ilp32;@march=rv32iac@mabi=ilp32
rv32imac/ilp32;@march=rv32imac@mabi=ilp32
rv32imafc/ilp32f;@march=rv32imafc@mabi=ilp32f
rv32imafdc/ilp32d;@march=rv32imafdc@mabi=ilp32d
rv32e/ilp32e;@march=rv32e@mabi=ilp32e
rv32ec/ilp32e;@march=rv32ec@mabi=ilp32e
rv32emc/ilp32e;@march=rv32emc@mabi=ilp32e
rv32ema/ilp32e;@march=rv32ema@mabi=ilp32e
rv32emac/ilp32e;@march=rv32emac@mabi=ilp32e
rv32eac/ilp32e;@march=rv32eac@mabi=ilp32e
rv64i/lp64;@march=rv64i@mabi=lp64
rv64im/lp64;@march=rv64im@mabi=lp64
rv64imc/lp64;@march=rv64imc@mabi=lp64
rv64imac/lp64;@march=rv64imac@mabi=lp64
rv64imafc/lp64f;@march=rv64imafc@mabi=lp64f

这样实际上也是消耗了很多时间,为了解决这个问题,可以指定特定的march和mabi进行编译和测试,待开发完成后,发布时在进行整体编译。这样开发效率会高出很多。

代码语言:javascript
复制
make clean
./configure --prefix=$RISCV/0727/rv32 --with-arch=rv32gc  --with-abi=ilp32d --disable-gdb
make -j8

例如上面的命令,只编译march为rv32gc,abi为ilp32d的gcc模型。省略掉很多库的编译,让编译的时间缩短了不少。

5.小结

为自己的处理器添加特定的CSR支持,一种情况下可以使用CSR的地址进行,另外一种就是修改汇编器,前一种方法比较直观,适合使用riscv通用编译器的开发方式进行开发,但是不够直观。后一种则需要修改汇编器,并且需要自己编译工具链,比较复杂,但是使用起来直观,简单。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嵌入式IoT 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • riscv gcc中添加自定义的csr支持
    • 1.概述
      • 2.不改变编译工具链实现CSR添加
        • 3.在编译器中集成CSR名称
          • 4.编译开发riscv gcc相关
            • 5.小结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档