'Rebuild QEMU (For RISCV-GNU-TOOLCHAIN)

This is a follow-up from the following question Custom Instruction crashing with SIGNAL 4 (Illegal Instruction): RISC-V (32) GNU-Toolchain with QEMU (apologies if I have missed any etiquette points in advance or formatted this in an unsavoury way, as I am still new to posting here). I am using the latest version of the riscv-gnu-toolchain, so I am just wondering what caveats and differences this process will be for this platform.

I was following namely two guides to add custom RISC-V instructions to QEMU - namely https://www.ashling.com/wp-content/uploads/QEMU_CUSTOM_INST_WP.pdf and https://chowdera.com/2021/04/20210430120004272q.html.

After editing qemu/target/riscv/insn32.decode with a free opcode (following Ashling tutorial), and implementing translator function in insn_trans/trans_rvi.c.inc - QEMU hangs when calling the function as an .insn directive (I know this to work - ). Changing opcodes of existing instructions to test if disassembly changes indicated to me that QEMU was not registering the changes I made and that I didn't rebuild/recompile QEMU correctly. I simply ran make clean, reconfigured and make again in the QEMU directory to rebuild it - Is this the correct way to rebuild QEMU in this toolchain or is there something I missed.

The code to call

#include <stdio.h>


static int test_ins(int a, int b) {
        int result;
        asm volatile(".insn r 0x33, 7, 0x20, %0, %1, %2" : "=r"(result) : "r"(a), "r"(b));
        return result;
}


int main() {
        int a, b, result;
        a = 2;
        b = 4;
        result = test_ins(a,b);
        printf("%d\n", result);
}

Instruction in insn32.decode is as follows:

OPCODE = "0110011", FUNCT3 = "111" and FUNCT7 = "0100000".

Implementation of aforementioned instruction is as follows:

static bool trans_bitcnt(DisasContext *ctx, arg_bitcnt *a)
{
TCGLabel *loop_source1 = gen_new_label();
TCGLabel *loop_source2 = gen_new_label();
TCGv source1, source2, dstval, cntval;
source1 = tcg_temp_local_new();
source2 = tcg_temp_local_new();
dstval = tcg_temp_local_new();
cntval = tcg_temp_local_new();
// Count all the bits set in rs1 and rs2 and put that number in rd
gen_get_gpr(source1, a->rs1);
gen_get_gpr(source2, a->rs2);
tcg_gen_movi_tl(cntval, 0x0);
/* Count the bits that are set in the first register */
gen_set_label(loop_source1);
tcg_gen_andi_tl(dstval, source1, 0x1);
tcg_gen_shri_tl(source1, source1, 0x1);
tcg_gen_add_tl(cntval, cntval, dstval);
tcg_gen_brcondi_tl(TCG_COND_NE, source1, 0x0, loop_source1);
/* Count the bits that are set in the second register */
gen_set_label(loop_source2);
tcg_gen_andi_tl(dstval, source2, 0x1);
tcg_gen_shri_tl(source2, source2, 0x1);
tcg_gen_add_tl(cntval, cntval, dstval);
tcg_gen_brcondi_tl(TCG_COND_NE, source2, 0x0, loop_source2);
 /* Update the destination register with the bits total */
gen_set_gpr(a->rd, cntval);
tcg_temp_free(source1);
tcg_temp_free(source2);
tcg_temp_free(dstval);
tcg_temp_free(cntval);
return true;
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source