大家好,我们团队的名字是Hey Siri,参赛编号是CICC1584,这次来分享在c/c++程序中嵌入汇编的写法,协处理器的自定义指令就是靠这种方法实现的,nice demo的下载链接在:https://www.rvmcu.com/community-topic-id-340.html。
以nice demo中这段程序为例
在胡镇波老师的《RISC-V架构与嵌入式开发快速入门》一书的181页出,有对此做过介绍,asm是GCC的关键字,表示进行内联汇编操作。volatile也是关键字,表示告诉编译器不对汇编程序进行任何优化。
这段汇编程序可分成两部分来看,“”内是汇编指令的具体内容
开始的insn r 0x7b,6 ,6可以看作是一个整体指令, r是RISC-V的r型指令,协处理只能定义成r型,其他指令格式如下所示:
而0x7b表示的是哪一种custom,一种可以定义出4种类型,每种定义格式为:
Custom-0 ——— 7‘b0001011 ——— 7’h0b
Custom-1 ——— 7‘b0101011 ——— 7’h2b
Custom-2 ——— 7‘b1011011 ——— 7’h5b
Custom-3 ——— 7‘b1111011 ——— 7’h7b
随后的6表示指令的14到12位,即funct3,
协处理器的rtl代码中可见这个定义,这里的110的顺序对应顺序为rd,rs1,rs2,使用寄存器的话就把对应位置1,在上述链接的指令格式中也可见其对应关系:
后面一个6就是对应指令编号了,在31位到25位的地方,不同的指令编号即表示不同的指令,所以每种custom类型都可以定义出128条自定义指令,4种指令一共能定义出512条自定义指令。
现在指令已经介绍完了,相信学过汇编的同学都知道汇编指令中有这源操作数跟目的操作数这两个概念,源操作数表是需要处理的数,目的操作数是处理结果,汇编指令写完之后需要为指令指出需要操作的数,此处后面的%0, %1, x0即表示操作数,顺序遵照rd,rs1,rs2,使用了的寄存器使用%+数字或者%+[变量名]来注明,使用数字的话,后续处理要注意顺序,未使用的寄存器可以写x0。
这样就介绍完了分号内的内容,我们设置好了一条汇编指令,但是需要将汇编程序处理的数据跟c/c++程序处理的数据对应起来。
分号外的程序就起到一个约束的作用,“=r”中的等号表示为输出变量做输出,后续()里的变量就是需要输出的变量,汇编程序执行后把()里的变量值更新,r表示使用编译器自动分配的寄存器来存储该操作数变量,m表示使用内存地址来存储该操作数变量,rm则编译器自动选择最优方案。
而此前在设置寄存器时,有提到用%+数字的方式,这种是隐含指定,比如有两个输出操作数,两个输入数,那么%0表示第一个输出操作数,%1表示第二个输入操作数,%3表示第一个输入操作数,%4表示第二个输入操作数。用%+[变量名]的明确指明方式就不需要按顺序。
我们团队先在蜂鸟的核里根据nice指令的接口,挂了一个协处理器,定义软件指令开关协处理器,并可以读取协处理器发回的数据,软件代码如下所示:
使用串口监视可以发现读数据跟开关功能都可以正常实现
这篇贴子分享了编写协处理器自定义指令的方法,能力有限,难免出现疏漏,我们也只是刚刚入门,勉强会用的程度,有些理解不到位或者错误的地方希望大家能够指正,共同学习共同进步,祝各参赛队比赛顺利!