Adding Custom Instructions to RISC-V GCC Toolchain
First, clone these repos:
git clone git@github.com:riscv-collab/riscv-gnu-toolchain.git
cd ./riscv-gnu-toolchain/
git submodule update --init --recursivegit clone git@github.com:riscv/riscv-opcodes.gitFirst, we are going to use riscv-opcodes to generate the encoding of our custom instruction.
Under extensions/unratified/, create a new file for the new instruction. We will use rv_testinst as an example
Inside the file, we have our custom instruction:
testinst rd rs1 rs2 31..25=1 14..12=0 6..2=0x1A 1..0=3Then, run the following command to generate C header for this instriction:
uv run riscv_opcodes -c "unratified/rv_testinst"In the resulting encoding.out.h file, we can see the custom instruction:
/* Automatically generated by parse_opcodes. */
#ifndef RISCV_ENCODING_H
#define RISCV_ENCODING_H
#define MATCH_TESTINST 0x200006b
#define MASK_TESTINST 0xfe00707f
Then, we go to riscv-gnu-toolchain repo.
We need to edit the following files:
./binutils/bfd/elfxx-riscv.c
./binutils/include/opcode/riscv-opc.h
./binutils/include/opcode/riscv.h
./gcc/gcc/common/config/riscv/riscv-common.cc
and also the files in ./gdb that is similar to binutils.
static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
{
{"xcvalu", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
...
+ {"xtestinst", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
...
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
Call riscv_subset_supports to make sure if the instuction is valid. */
bool
riscv_multi_subset_supports (riscv_parse_subset_t *rps,
enum riscv_insn_class insn_class)
{
switch (insn_class)
{
case INSN_CLASS_I:
return riscv_subset_supports (rps, "i");
...
+ case INSN_CLASS_XTESTINST:
+ return riscv_subset_supports (rps, "xtestinst");
...
/* Each instuction is belonged to an instruction class INSN_CLASS_*.
Call riscv_subset_supports_ext to determine the missing extension. */
const char *
riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
enum riscv_insn_class insn_class)
{
switch (insn_class)
{
case INSN_CLASS_I:
return "i";
...
+ case INSN_CLASS_XPENGUIN:
+ return "xpenguin";...
#define MASK_CV_SUB_DIV4 0xfe00707f
#define MASK_CV_SUB_DIV8 0xfe00707f
/* Vendor-specific (UC Berkeley) Xpenguin custom instructions. */
+ #define MATCH_TESTINST 0x200006b
+ #define MASK_TESTINST 0xfe00707f
...
/* Smrnmi instruction */
DECLARE_INSN(mnret, MATCH_MNRET, MASK_MNRET)
+ /* Vendor-specific (UC Berkeley) Xpenguin custom instructions. */
+ DECLARE_INSN(testinst, MATCH_TESTINST, MASK_TESTINST)
/* All RISC-V instructions belong to at least one of these classes. */
enum riscv_insn_class
{
INSN_CLASS_NONE,
...
INSN_CLASS_XCVSIMD,
+ INSN_CLASS_XPENGUIN,
INSN_CLASS_XTHEADBA,...
{"cv.sub.div8", 0, INSN_CLASS_XCVSIMD, "d,s,t", MATCH_CV_SUB_DIV8, MASK_CV_SUB_DIV8, match_opcode, 0},
+ /* Vendor-specific (UC Berkeley) Xpenguin custom instructions. */
+ {"testinst", 0, INSN_CLASS_XPENGUIN, "d,s,t", MATCH_TESTINST, MASK_TESTINST, match_opcode, 0 },
/* Vendor-specific (T-Head) XTheadBa instructions. */
{"th.addsl", 0, INSN_CLASS_XTHEADBA, "d,s,t,Xtu2@25", MATCH_TH_ADDSL, MASK_TH_ADDSL, match_opcode, 0},
...
{"xcvbi", ISA_SPEC_CLASS_NONE, 1, 0},
+ {"xpenguin", ISA_SPEC_CLASS_NONE, 1, 0},
{"xtheadba", ISA_SPEC_CLASS_NONE, 1, 0},Build
./configure --prefix=/scratch/tk/Desktop/riscv-matrix/riscv-unknown-elf/
makeOptionally, enable multilib
./configure --prefix=/scratch/tk/Desktop/riscv-matrix/riscv-unknown-elf/ --with-cmodel=medany --enable-multilibExample program
#include <stdint.h>
#include <stdio.h>
int main(void) {
asm volatile("testinst x1, x0, x4\n");
printf("hello\n");
return 0;
}
riscv64-unknown-elf-gcc main.c -o main.elfriscv64-unknown-elf-objdump -d main.elf > disassemble.SLast updated
Was this helpful?
