我正试图将一些Forth加载到运行在RISC-V SBC上的Forth编译器中(但我不认为这是一个与Forth相关的问题(:
>load /root/repos/riscyforth/test2.4th
: cuboid * * [ The cuboid has a volume of ] . ;
OK
cuboid
Program received signal SIGILL, Illegal instruction.
0x0000003ff7dbd038 in ?? ()
上面显示的是,我加载了带有Forth的文件,第一行,回显到终端,是单词长方体的定义。随后的OK显示Forth编译器已成功编译该单词。
然后第二行是这个词的调用,长方体,然后是程序(在本例中在GDB下运行(已经用SIGILL兑现的消息。
然而,这就是拆解所显示的:
(gdb) disassemble 0x3ff7dbd038, 0x3ff7dbd078
Dump of assembler code from 0x3ff7dbd038 to 0x3ff7dbd078:
=> 0x0000003ff7dbd038: addi s9,s9,-8
0x0000003ff7dbd03c: sd s7,0(s9)
0x0000003ff7dbd040: li s8,63
0x0000003ff7dbd044: slli s8,s8,0x20
0x0000003ff7dbd048: lui t0,0xf7dbd
0x0000003ff7dbd04c: ori t0,t0,0
0x0000003ff7dbd050: slli t0,t0,0x20
0x0000003ff7dbd054: srli t0,t0,0x20
0x0000003ff7dbd058: or s8,s8,t0
0x0000003ff7dbd05c: addi s8,s8,112
0x0000003ff7dbd060: mv s7,s8
0x0000003ff7dbd062: nop
0x0000003ff7dbd064: lui t0,0x10
0x0000003ff7dbd068: addi t0,t0,1976 # 0x107b8 <COLON_NEXT>
0x0000003ff7dbd06c: jr t0
0x0000003ff7dbd070: addi a2,sp,868
0x0000003ff7dbd072: nop
0x0000003ff7dbd074: unimp
0x0000003ff7dbd076: unimp
这正是我所期望的,可以看出,0x0000003ff7dbd038有一条非常好的指令。
这个内存被作为可执行文件写入系统,这种机制对我在命令行上定义的单词很有效(而不是从文件中读取(。此外,如果我只是在我加载的文件中定义这个词,然后从命令行运行它,也没关系(我知道这些可能表明加载有问题,但我看不到它,也看不到为什么它会生成这个信号(。
更令人困惑的是,如果我使用GDB逐步完成代码,那么我就不会遇到SIGILL问题,并且从0x0000003ff7dbd038开始的代码会像我预期的那样执行。
这是RVBoards Nezha上的RV64-在此之前,执行标准的Forth解释器命令:
NEXT:
ld s8, 0(s7) # Word address register takes content of next secondary
addi s7, s7, ADDRWIDTH # Next secondary along
RUN:
ld t0, 0(s8) # Extract first instruction address of primitive
与x86不同,RISC-V不允许在没有同步的情况下编写机器代码并执行它,即使在同一线程内也是如此。在执行新编写的机器代码之前,发出一条fence.i
指令,使指令缓存与内存的当前状态同步。