修改RISCV工具链

第一步是安装RISCV工具链:

$ git clone https://github.com/riscv/riscv-tools.git
$ git submodule update --init --recursive
$ export RISCV=/path/to/install/riscv/toolchain
$ ./build.sh

第二步明确要添加的指令,以mod指令为例:

mod r1, r2, r3

Semantics:
R[r1] = R[r2] % R[r3]

第三步打开 riscv-opcodes/opcodes文件,在这里,将能够看到分配给各种指令的各种操作码和指令位。 为mod指令分配了一条未使用的指令:

sra     rd rs1 rs2 31..25=32 14..12=5 6..2=0x0C 1..0=3
or      rd rs1 rs2 31..25=0  14..12=6 6..2=0x0C 1..0=3
and     rd rs1 rs2 31..25=0  14..12=7 6..2=0x0C 1..0=3

mod     rd rs1 rs2 31..25=1  14..12=0 6..2=0x1A 1..0=3

addiw   rd rs1 imm12            14..12=0 6..2=0x06 1..0=3
slliw   rd rs1 31..25=0  shamtw 14..12=1 6..2=0x06 1..0=3
srliw   rd rs1 31..25=0  shamtw 14..12=5 6..2=0x06 1..0=3
sraiw   rd rs1 31..25=32 shamtw 14..12=5 6..2=0x06 1..0=3

第四步,运行下面的代码得到MOD的掩码和代码:

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

打开 temp.h将看到:

#define MATCH_MOD 0x200006b                                                    
#define MASK_MOD 0xfe00707f

第五步,将上面的内容添加到:riscv-gnu-toolchain/riscv-binutils-gdb/include/opcode/riscv-opc.h文件中

第六步,修改riscv-gnu-toolchain/riscv-binutils-gdb/opcodes/riscv-opc.c文件:

const struct riscv_opcode riscv_opcodes[] =                                     
{                                                                               
/* name,      isa,   operands, match, mask, match_func, pinfo.  */              
{"unimp",     "C",   "",  0, 0xffffU,  match_opcode, 0 },                       
{"unimp",     "I",   "",  MATCH_CSRRW | (CSR_CYCLE << OP_SH_CSR), 0xffffffffU,  match_opcode, 0 }, /* csrw cycle, x0 */
{"ebreak",    "C",   "",  MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS },
{"ebreak",    "I",   "",    MATCH_EBREAK, MASK_EBREAK, match_opcode, 0 },          
{"sbreak",    "C",   "",  MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS },
{"sbreak",    "I",   "",    MATCH_EBREAK, MASK_EBREAK, match_opcode, INSN_ALIAS },
....
....
....
{"mod",       "I",   "d,s,t",  MATCH_MOD, MASK_MOD, match_opcode, 0 }
....
....

第七步,重新编译工具链

第八步,测试,使用下面的代码:

#include <stdio.h>

int main(){
  int a,b,c;
  a = 5;
  b = 2;
  asm volatile
  (
    "mod   %[z], %[x], %[y]\n\t"
    : [z] "=r" (c)
    : [x] "r" (a), [y] "r" (b)
  )  
 
  if ( c != 1 ){
     printf("\n[[FAILED]]\n");
     return -1;
  }
  
  printf("\n[[PASSED]]\n");

  return 0;
}

使用修改过的工具链编译:

$ riscv64-unknown-elf-gcc mod.c -o mod

打开obj dump文件查看指令是否被使用:

$ riscv64-unknown-elf-objdump -dC mod > mod.dump

在gem5中添加指令:

第一步,修改arch/riscv/decoder.isa 文件:0x33是0x10在fun7中预留的指令。

0x33: decode FUNCT3 {
        format ROp {
            0x0: decode FUNCT7 {
                0x0: add({{
                    Rd = Rs1_sd + Rs2_sd;
                }});
                0x1: mul({{
                    Rd = Rs1_sd*Rs2_sd;
                }}, IntMultOp);
                0x10: mod({{
                    Rd = Rs1_sd % Rs2_sd;
                }});
                0x20: sub({{
                    Rd = Rs1_sd - Rs2_sd;
                }});
            }

注意汇编器中的指令匹配是这样做的:

请参阅riscv-gnu-toolchain / riscv-binutils -gdb / opcodes / riscv-opc.c中的match_opcode()函数

op-> match和op-> mask是我们定义的MATCH和MASK宏。

((insn ^ op->match) & op->mask) == 0;

 这意味着如果你只是在指令中看到MATCH中的1位并翻转它们,然后看到屏蔽位,那么一切都应该是0.MASK告诉哪些位是有意义的,MATCH告诉所需的配置是什么。

在spike ISA simulator中添加指令:

第一步,riscv-isa-sim/riscv/encoding.h中添加:

#define MATCH_MOD 0x200006b                                                    
#define MASK_MOD 0xfe00707f
...
DECLARE_INSN(add, MATCH_MOD, MASK_MOD)

第二步,创建如下文件并添加:

riscv-isa-sim/riscv/insns/mod.h

WRITE_RD(sext_xlen(RS1 % RS2));

第三步,在riscv-isa-sim/riscv/riscv.mk.in中添加:

riscv_insn_list = \
      ...
      mod \
      ...

第四步,riscv-isa-sim/spike_main/disasm.cc中添加:

DEFINE_RTYPE(mod);

 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐