RISC-V开发 linux下GCC编译自定义指令流程笔记

第一步:利用GCC提供了内嵌汇编的功能可以在C代码中直接内嵌汇编语言

第二步:利用RSIC-V的中的.insn模板进行自定义指令的插入

第三步:RISC-V开发环境的搭建

C语言插入汇编

        GCC提供了内嵌汇编的功能可以在C代码中直接内嵌汇编语言语句方便了程序设计。使用内嵌汇编,要先编写汇编指令模板,然后将C语言表达式与指令的操作数相关联,并告诉GCC对这些操作有哪些限制条件。

void test(void)
  {
      input= 1;
      __asm__ __volatile__ 
      (
        "movl %1,%0" :
        "=r" (result) : 
        "r" (input)
      );
     return 1;
  }

对应的汇编代码如下;
行号   代码 解释
1
7
8  movl    $1, input                     对应C语言语句input = 1;
9  movl    input, %eax	隐式处理
10 #APP                                  GCC插入的注释,表示内嵌汇编开始
11 movl    %eax,%eax                     我们的内嵌汇编语句
12 #NO_APP                               GCC  插入的注释,表示内嵌汇编结束
13 movl    %eax, result                  将结果存入result变量,隐式处理

        “movl %1,%0”是指令模板;“%0”和“%1”代表指令的操作数,称为占位符,内嵌汇编靠它们将C语言表达式与指令操作数相对应。“result”和“input”为C语言中的两个变量名。其中result对应着%0,input对应着%1。即movl input result。

        在每个操作数前面有一个用引号括起来的字符串,字符串的内容是对该操作数的限制或者说要求。“result”前面的限制字符串是“=r”,其中“=”表示“result”是输出操作数,“r”表示需要将“result”与某个通用寄存器相关联,先将操作数的值读入寄存器,然后在指令中使用相应寄存器,而不是“result”本身,当然指令执行完后需要将寄存器中的值存入变量“result”,从表面上看好像是指令直接对“result”进行操作,实际上GCC做了隐式处理,这样我们可以少写一些指令。“input”前面的“r”表示该表达式需要先放入某个寄存器,然后在指令中使用该寄存器参加运算。

RSIC-V支持自定义指令

核心思想:利用Kito Cheng提供的.insn模板进行开发

第一步:确定opcode RV32指令架构中定义了4种custom指令类型,opcode需使用表格custom-0/custom-1/custom-2/custom-3中的一种:

第二步: 确定指令类型 需要结合指令的功能来进行选择,有6种指令指令格式,分别为R/I/S/B/U/J类型

R型用于寄存器-寄存器间的操作

I型用于短立即数和访存(Load)

操作 S型用于访存Store操作

B型用于条件跳转

U型用于长立即数

J型用于无条件跳转

第三步: 确定指令编码 根据opcode以及指令类型,还需要确定其它字段的编码,比如R-type中,需要确定func3/func7字段的编码。并且编译器不会限制这两个字段的类型,支持我们自定义不同的类型来区分指令

第四步:在C语言中插入该指令

例:自定义一条指令,功能是算术运算,有两个源操作数,所以指令类型为可以选择R-type

对应的.insn模板为: .insn r opcode, func3, func7, rd, rs1, rs2

其中.insn为模板前缀 r代表该指令为R型指令 opcode使用custom-0/custom-1/custom-2/custom-3中的一种,代表这是自定义的指令 func3/func7字段可以自定义

C测试函数:

C代码
#include <stdio.h>
int main() {
	int a = 0;
	int b = 0;
	asm volatile (
       	".insn r 0x7b, 6, 6, %0, %1, x0"
       	:"=r"(a)
       	:"r"(b)
     	);	
	return 0;
}
汇编文件
main:
	addi	sp,sp,-32
	sw	s0,28(sp)
	addi	s0,sp,32
	sw	zero,-20(s0)
	sw	zero,-24(s0)
	lw	a5,-24(s0)
 #APP
# 9 "test.c" 1
	.insn r 0x7b, 6, 6, a5, a5, x0 生成的新指令
# 0 "" 2
 #NO_APP
	sw	a5,-20(s0)
	li	a5,0
	mv	a0,a5
	lw	s0,28(sp)
	addi	sp,sp,32
	jr	ra

反汇编文件

00000000 <main>:
   0:	1101                	addi	sp,sp,-32
   2:	ce22                	sw	s0,28(sp)
   4:	1000                	addi	s0,sp,32
   6:	fe042623          	sw	zero,-20(s0)
   a:	fe042423          	sw	zero,-24(s0)
   e:	fe842783          	lw	a5,-24(s0)
  12:	0c07e7fb          	.insn	4, 0x0c07e7fb 生成的新指令机器码
  16:	fef42623          	sw	a5,-20(s0)
  1a:	4781                	li	a5,0
  1c:	853e                	mv	a0,a5
  1e:	4472                	lw	s0,28(sp)
  20:	6105                	addi	sp,sp,32
  22:	8082                	ret

insn支持的所有模板如下

R type: .insn r opcode, func3, func7, rd, rs1, rs2
     +-------+-----+-----+-------+----+-------------+
     | func7 | rs2 | rs1 | func3 | rd |      opcode |
     +-------+-----+-----+-------+----+-------------+
     31      25    20    15      12   7             0

R type with 4 register operands: .insn r opcode, func3, func2, rd, rs1, rs2, rs3
     +-----+-------+-----+-----+-------+----+-------------+
     | rs3 | func2 | rs2 | rs1 | func3 | rd |      opcode |
     +-----+-------+-----+-----+-------+----+-------------+
     31    27      25    20    15      12   7             0

I type: .insn i opcode, func3, rd, rs1, simm12
     +-------------+-----+-------+----+-------------+
     |      simm12 | rs1 | func3 | rd |      opcode |
     +-------------+-----+-------+----+-------------+
     31            20    15      12   7             0

S type: .insn s opcode, func3, rd, rs1, simm12
     +--------------+-----+-----+-------+-------------+-------------+
     | simm12[11:5] | rs2 | rs1 | func3 | simm12[4:0] |      opcode |
     +--------------+-----+-----+-------+-------------+-------------+
     31             25    20    15      12            7             0

SB type: .insn sb opcode, func3, rd, rs1, symbol
SB type: .insn sb opcode, func3, rd, simm12(rs1)
     +--------------+-----+-----+-------+-------------+-------------+
     | simm21[11:5] | rs2 | rs1 | func3 | simm12[4:0] |      opcode |
     +--------------+-----+-----+-------+-------------+-------------+
     31             25    20    15      12            7             0

U type: .insn u opcode, rd, simm20
     +---------------------------+----+-------------+
     |                    simm20 | rd |      opcode |
     +---------------------------+----+-------------+
     31                          12   7             0

UJ type: .insn uj opcode, rd, symbol
     +------------+--------------+------------+---------------+----+-------------+
     | simm20[20] | simm20[10:1] | simm20[11] | simm20[19:12] | rd |      opcode |
     +------------+--------------+------------+---------------+----+-------------+
     31           30             21           20              12   7             0

CR type: .insn cr opcode2, func4, rd, rs2
     +---------+--------+-----+---------+
     |   func4 | rd/rs1 | rs2 | opcode2 |
     +---------+--------+-----+---------+
     15        12       7     2        0

	 

理论知识如上所示

下面为RISC-V开发环境的搭建
拉取码云上的riscv-gnu-toolchain镜像
git clone  https://gitee.com/mirrors/riscv-gnu-toolchain
cd riscv-gnu-toolchain
git clone https://gitee.com/mirrors/riscv-dejagnu
git clone -b riscv-gcc-10.2.0 https://gitee.com/mirrors/riscv-gcc
git clone -b riscv-glibc-2.29 https://gitee.com/mirrors/riscv-glibc
git clone https://gitee.com/mirrors/riscv-newlib
git clone -b riscv-binutils-2.35 https://gitee.com/mirrors/riscv-binutils-gdb  riscv-binutils
git clone -b fsf-gdb-10.1-with-sim https://gitee.com/mirrors/riscv-binutils-gdb  riscv-gdb


编译工具链
sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev \
gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev
pwd #获取当前路径 src
vi ~/.bashrc

i
export RISCV="把上面的src放到这里"
export PATH=$PATH:$RISCV/bin
:wq

source ~/.bashrc

编译riscv-gnu-toolchain

mkdir build
cd build
../configure --prefix=$RISCV --with-arch=rv32gc --with-abi=ilp32d
sudo apt install libncurses5-dev
sudo make -j4
make install

至此,C语言文件可以正常编译,但无法执行。

安装QEMU
cd
 sudo apt-get install libglib2.0-dev ninja-build  build-essential zlib1g-dev pkg-config libglib2.0-dev  \
binutils-dev libboost-all-dev autoconf libtool libssl-dev  libpixman-1-dev libpython-dev  \
 virtualenv libmount-dev   libpixman-1-dev
wget https://download.qemu.org/qemu-6.2.0.tar.xz
tar xvJf qemu-6.2.0.tar.xz
cd qemu-6.2.0
mkdir build
cd build
../configure
make -j4   #wait...
之后是获取新指令机器码的一些操作
vi test.c
riscv32-unknown-elf-gcc -S -o test.s test.c #生成汇编文件
riscv32-unknown-elf-gcc -c -o test.o test.c #生成机器码
riscv32-unknown-elf-objdump -d test.o       #反汇编查看机器码
riscv32-unknown-elf-gcc test.c -o test      #生成可执行文件
../qemu-6.2.0/build/qemu-riscv32 test       #在qemu上执行文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红叶落水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值