-
Notifications
You must be signed in to change notification settings - Fork 31
How to add a new instruction
For an evolving ISA like RISC-V, it is common that we will have support for new instructions or new ISA extensions to the backend. In this post, we explain the steps to add a new instruction to an existing backend. In this case, we use the riscv64 backend as an example, but the process is similar to other backends as well.
- Add constants (
src/codegen/riscv64/constants-riscv64.h)
constants-riscv64.h defines constants that are related to instruction classes and encodings that are shared by the Assembler, Disasm, and Simulator. You will need to add new opcode to enum Opcode_t and other constants if it uses a new instruction format. Sometimes, a new instruction uses a new class of registers. Then one needs to add new register classes to register-riscv64.h.
- Add to the assembler (
src/codegen/riscv64/assembler-riscv64.h/cc)
Add a new Assembler API to assembler-riscv64.cc and assembler-riscv64.h as the generator for the new instruction. These Assembler APIs are typically named after the instruction name unless there is a naming conflict, such as and is named as and_.
// assembler-riscv64.h
void add(Register rd, Register rs1, Register rs2);
// assembler-riscv64.cc
void Assembler::add(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0b0000000, 0b000, rd, rs1, rs2);
}
If the instruction uses a new instruction format, one needs to add a new generator function for this new instruction format (e.g., GenInstrALU_rr).
- Add to the simulator (
src/codegen/riscv64/simulator-riscv64.h/cc)
Implement the behavior of the instruction in the simulator as shown blow:
void Simulator::DecodeRVRType() {
switch (instr_.InstructionBits() & kRTypeMask) {
case RO_ADD: {
set_rd(sext_xlen(rs1() + rs2()));
break;
}
Note that constants like kRTypeMask is defined in constants-riscv64.h and is shared by both Assembler, Simulator, and Disasm.
- Test the instruction
Once an instruction is added to the Assembler and the Simulator, it can be tested under the simulator build run. The new instruction needs to be added test/cctest/test-assembler-riscv64.cc
UTEST_R2_FORM_WITH_OP(add, int64_t, LARGE_INT_EXCEED_32_BIT, MIN_VAL_IMM12, +)
which is a macro that specifies two input operands to add and compare it against the expected result computing by + the two operands.
- Add to the disassembler (
src/diagnostics/riscv64/disasm-riscv64.h/cc)
Add the disassembler for the new instruction, as shown below:
void Decoder::DecodeRType(Instruction* instr) {
switch (instr->InstructionBits() & kRTypeMask) {
case RO_ADD:
Format(instr, "add 'rd, 'rs1, 'rs2");
break;
- Test disassembler
Add a test for disassembly the new instruction in test/cctest/test-disam-riscv64.cc as shown below:
COMPARE(add(s6, t0, t4), "01d28b33 add s6, t0, t4");
- Use the new instruction
- Home
- Getting Started
- Project Management
- For Developers
- RISC-V Backend Design Doc
- Community operation