向RISCV-32ima添加新指令:“错误的RISCV-操作码”

时间:2018-08-13 15:35:33

标签: riscv binutils

我正在寻求有关我要添加到riscv的扩展名的帮助。

全局设置

我的工作基准是riscv-tools repo的克隆,其中包含常用工具,其中包括:

  • riscv-fesvr
  • riscv-gnu-toolchain
  • riscv-isa-sim
  • riscv操作码
  • riscv-pk

nb:我从中克隆的最后一个提交是c6d58cecb3862deb742e1a5cc9d1c682f2c50ba9(2018-04-24)。

我的工作基于riscv32-ima内核。我想向该处理器的ISA添加一条指令,以激活处理器中的特定组件。

从proc本身的行为来看,我没有问题:我修改了峰值,并且我的指令(以及我添加到处理器中的组件)运行得很好。

在汇编器中,指令如下:

addi a0, a0, 0
...            // other code
setupcomp      // activate my component ... 
...            // other code

请注意,此指令没有任何操作数。

我做什么

我躲开了一段时间,发现this tutorial有点老了。

所以,我:

  1. 转到riscv-tools/riscv-opcodes/
  2. opcode及其掩码添加到riscv-tools/riscv-opcodes/opcodes。我的看起来像这样:

    setupcomp 31..28=ignore 27..20=ignore 19..15=ignore 14..12=0 11..7=ignore 6..2=0x1a 1..0=3
    
  3. 从那里,我重建必要的.h文件:

    make install
    
  4. 现在,我将必要的stucts添加到riscv-tools/riscv-gnu-toolchain/riscv-binutils-gdb/include/opcode/riscv-opc.h,并正式声明了该指令:

    #define MATCH_SETUPCOMP 0x6b
    #define MASK_SETUPCOMP  0x707f
    DECLARE_INSN(setupcomp, MATCH_SETUPCOMP, MASK_SETUPCOMP)
    

    这些值,我是从操作码项目中生成的。

  5. 我还将必要的定义添加到: riscv-tools/riscv-gnu-toolchain/riscv-binutils-gdb/opcodes/riscv-opc.c

    {"setupcomp", "I", "", MATCH_SETUPCOMP, MASK_SETUPCOMP, match_opcode, 0 },
    

现在,到现在为止,我相信我已经完成了所有必要的工作。我仍然对我想要的操作码有疑问,但是我不认为这会对我观察到的行为和现在描述的行为产生影响。

我遇到的问题

当我用riscv-tools/build-rv32ima.sh script构建所有内容时,在过程即将结束时(我相信测试套件之类的东西),我收到一条消息,抱怨:

Assembler messages:
Error: internal: bad RISC-V opcode (bits 0xffffffffffff8f80 undefined): setupcomp 
Fatal error: Broken assembler.  No assembly attempted.
make[6]: *** [lib_a-dummy.o] Error 1

我认为我在指令的声明中缺少某些内容,可能是该声明未正确“转发”到实际需要它的工具链的每个部分。 但是我找不到哪里/什么/如何/何时,对此我将不胜感激。

当然,我很可能会缺少一些明显的东西,所以请保持谦逊:)

3 个答案:

答案 0 :(得分:0)

向工具链添加自定义指令的最佳选择是使用我们的const readline = require('readline'); x = []; const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); rl.question('What do you think of Node.js? ', (answer) => { // TODO: Log the answer in a database rl.close(); x.push(answer); console.log(x[0]); }); 汇编程序指令。虽然这不能给您带来漂亮的语法(应该使用预处理器宏或C包装函数),但确实可以避免碰到很多问题的工具链。

关于此问题的最佳文档是the GAS testsuite for .insn。基本上,用户可以发出RISC-V ISA手册定义的任何格式的指令,并带有直接填写每个位模式的选项。它与GCC的内联汇编寄存器分配框架完全集成在一起,与其他指令一样工作。

答案 1 :(得分:0)

只需运行以下命令来解析MASK / MATCH:

cat opcodes-pseudo opcodes opcodes-rvc opcodes-rvc-pseudo opcodes-custom | ./parse-opcodes -c > ~/temp.h

它为riscv-gnu-toolchain/riscv-binutils-gdb/include/opcode/riscv-opc.h提供了正确的MASK和MATCH 现在重新编译就可以了!

答案 2 :(得分:0)

正如Domso所说,riscv-opc.c似乎要求显式屏蔽不是参数的每一位。但是,如果您在ignore文件中将位设置为opcodes,则parse-opcodes生成的掩码将不会设置这些位。确实这就是您想要的,因为掩码应该表明设置的位是操作码的一部分。

由于fence.i使用被忽略的位,因此您可以通过查看定义的方式来推导如何处理被忽略的位:

riscv-opc.h中,MASK_FENCE_I只是由parse-opcodes生成的掩码:

#define MATCH_FENCE_I 0x100f
#define MASK_FENCE_I  0x707f

DECLARE_INSN的掩码始终不变:

DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I)

但是在riscv-opc.c中,被忽略的位使用按位或屏蔽。

{"fence.i", "I", "", MATCH_FENCE_I, MASK_FENCE | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, 0 }

由于fence.i不带参数,因此等效于

{"fence.i", "I", "", 0xFFFFFFFF, match_opcode, 0 }

因此,您应该将MASK_SETUPCOMP保持原样,以便可以将其分配给DECLARE_INSN,但请将riscv-opc.c中的掩码设置为0xFFFFFFFF。同样,由于MASK_SETUPCOMPmake install复制到一堆头文件中,因此最好保持一致。