From a965b24aa955d412041927c47a86483b7df74adc Mon Sep 17 00:00:00 2001 From: Vacantron Chen Date: Sun, 10 Nov 2024 21:43:18 +0800 Subject: [PATCH] Add "src/rv32_jit.c" This file is generated by "tools/gen-jit-template.py" To bring up the Linux Kernel to just-in-time (JIT) compilation, we need to update the memory-related operation with the memory management unit. However, the current "src/rv32_jit.c" was generated by the template. That template reduced the rework for the repeated statements, but also reduced the flexibility and the intuitiveness for bring up the new feature. In this commit, we deprecate that template and just use a regular file for the flexibility. --- .gitignore | 1 - Makefile | 5 +- src/rv32_jit.c | 713 ++++++++++++++++++++++++++++++++++++++ tools/gen-jit-template.py | 274 --------------- 4 files changed, 714 insertions(+), 279 deletions(-) create mode 100644 src/rv32_jit.c delete mode 100755 tools/gen-jit-template.py diff --git a/.gitignore b/.gitignore index 647c8dec..9a1596b2 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,3 @@ tests/arch-test-target/config.ini tests/arch-test-target/sail_cSim/riscv_sim_RV32 tests/scimark2/ __pycache__/ -src/rv32_jit.c diff --git a/Makefile b/Makefile index f0928fde..b16a1629 100644 --- a/Makefile +++ b/Makefile @@ -194,9 +194,6 @@ ifeq ($(call has, JIT), 1) $(error JIT mode only supports for x64 and arm64 target currently.) endif -src/rv32_jit.c: - $(Q)tools/gen-jit-template.py $(CFLAGS) > $@ - $(OUT)/jit.o: src/jit.c src/rv32_jit.c $(VECHO) " CC\t$@\n" $(Q)$(CC) -o $@ $(CFLAGS) -c -MMD -MF $@.d $< @@ -353,7 +350,7 @@ endif endif clean: - $(RM) $(BIN) $(OBJS) $(DEV_OBJS) $(BUILD_DTB) $(HIST_BIN) $(HIST_OBJS) $(deps) $(WEB_FILES) $(CACHE_OUT) src/rv32_jit.c + $(RM) $(BIN) $(OBJS) $(DEV_OBJS) $(BUILD_DTB) $(HIST_BIN) $(HIST_OBJS) $(deps) $(WEB_FILES) $(CACHE_OUT) distclean: clean -$(RM) $(DOOM_DATA) $(QUAKE_DATA) $(BUILDROOT_DATA) $(LINUX_DATA) $(RM) -r $(OUT)/linux-image diff --git a/src/rv32_jit.c b/src/rv32_jit.c new file mode 100644 index 00000000..4c1dad9f --- /dev/null +++ b/src/rv32_jit.c @@ -0,0 +1,713 @@ +GEN(nop, {}) +GEN(lui, { + vm_reg[0] = map_vm_reg(state, ir->rd); + emit_load_imm(state, vm_reg[0], ir->imm); +}) +GEN(auipc, { + vm_reg[0] = map_vm_reg(state, ir->rd); + emit_load_imm(state, vm_reg[0], ir->pc + ir->imm); +}) +GEN(jal, { + if (ir->rd) { + vm_reg[0] = map_vm_reg(state, ir->rd); + emit_load_imm(state, vm_reg[0], ir->pc + 4); + } + store_back(state); + emit_jmp(state, ir->pc + ir->imm); + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(jalr, { + vm_reg[0] = ra_load(state, ir->rs1); + emit_mov(state, vm_reg[0], temp_reg); + emit_alu32_imm32(state, 0x81, 0, temp_reg, ir->imm); + emit_alu32_imm32(state, 0x81, 4, temp_reg, ~1U); + if (ir->rd) { + vm_reg[1] = map_vm_reg(state, ir->rd); + emit_load_imm(state, vm_reg[1], ir->pc + 4); + } + store_back(state); + parse_branch_history_table(state, ir); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(beq, { + ra_load2(state, ir->rs1, ir->rs2); + emit_cmp32(state, vm_reg[1], vm_reg[0]); + store_back(state); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x84); + if (ir->branch_untaken) { + emit_jmp(state, ir->pc + 4); + } + emit_load_imm(state, temp_reg, ir->pc + 4); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); + emit_jump_target_offset(state, JUMP_LOC, state->offset); + if (ir->branch_taken) { + emit_jmp(state, ir->pc + ir->imm); + } + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(bne, { + ra_load2(state, ir->rs1, ir->rs2); + emit_cmp32(state, vm_reg[1], vm_reg[0]); + store_back(state); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x85); + if (ir->branch_untaken) { + emit_jmp(state, ir->pc + 4); + } + emit_load_imm(state, temp_reg, ir->pc + 4); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); + emit_jump_target_offset(state, JUMP_LOC, state->offset); + if (ir->branch_taken) { + emit_jmp(state, ir->pc + ir->imm); + } + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(blt, { + ra_load2(state, ir->rs1, ir->rs2); + emit_cmp32(state, vm_reg[1], vm_reg[0]); + store_back(state); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x8c); + if (ir->branch_untaken) { + emit_jmp(state, ir->pc + 4); + } + emit_load_imm(state, temp_reg, ir->pc + 4); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); + emit_jump_target_offset(state, JUMP_LOC, state->offset); + if (ir->branch_taken) { + emit_jmp(state, ir->pc + ir->imm); + } + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(bge, { + ra_load2(state, ir->rs1, ir->rs2); + emit_cmp32(state, vm_reg[1], vm_reg[0]); + store_back(state); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x8d); + if (ir->branch_untaken) { + emit_jmp(state, ir->pc + 4); + } + emit_load_imm(state, temp_reg, ir->pc + 4); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); + emit_jump_target_offset(state, JUMP_LOC, state->offset); + if (ir->branch_taken) { + emit_jmp(state, ir->pc + ir->imm); + } + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(bltu, { + ra_load2(state, ir->rs1, ir->rs2); + emit_cmp32(state, vm_reg[1], vm_reg[0]); + store_back(state); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x82); + if (ir->branch_untaken) { + emit_jmp(state, ir->pc + 4); + } + emit_load_imm(state, temp_reg, ir->pc + 4); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); + emit_jump_target_offset(state, JUMP_LOC, state->offset); + if (ir->branch_taken) { + emit_jmp(state, ir->pc + ir->imm); + } + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(bgeu, { + ra_load2(state, ir->rs1, ir->rs2); + emit_cmp32(state, vm_reg[1], vm_reg[0]); + store_back(state); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x83); + if (ir->branch_untaken) { + emit_jmp(state, ir->pc + 4); + } + emit_load_imm(state, temp_reg, ir->pc + 4); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); + emit_jump_target_offset(state, JUMP_LOC, state->offset); + if (ir->branch_taken) { + emit_jmp(state, ir->pc + ir->imm); + } + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(lb, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, ir->rs1); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = map_vm_reg(state, ir->rd); + emit_load_sext(state, S8, temp_reg, vm_reg[1], 0); +}) +GEN(lh, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, ir->rs1); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = map_vm_reg(state, ir->rd); + emit_load_sext(state, S16, temp_reg, vm_reg[1], 0); +}) +GEN(lw, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, ir->rs1); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = map_vm_reg(state, ir->rd); + emit_load(state, S32, temp_reg, vm_reg[1], 0); +}) +GEN(lbu, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, ir->rs1); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = map_vm_reg(state, ir->rd); + emit_load(state, S8, temp_reg, vm_reg[1], 0); +}) +GEN(lhu, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, ir->rs1); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = map_vm_reg(state, ir->rd); + emit_load(state, S16, temp_reg, vm_reg[1], 0); +}) +GEN(sb, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, ir->rs1); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = ra_load(state, ir->rs2); + emit_store(state, S8, vm_reg[1], temp_reg, 0); +}) +GEN(sh, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, ir->rs1); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = ra_load(state, ir->rs2); + emit_store(state, S16, vm_reg[1], temp_reg, 0); +}) +GEN(sw, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, ir->rs1); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = ra_load(state, ir->rs2); + emit_store(state, S32, vm_reg[1], temp_reg, 0); +}) +GEN(addi, { + vm_reg[0] = ra_load(state, ir->rs1); + vm_reg[1] = map_vm_reg(state, ir->rd); + if (vm_reg[0] != vm_reg[1]) { + emit_mov(state, vm_reg[0], vm_reg[1]); + } + emit_alu32_imm32(state, 0x81, 0, vm_reg[1], ir->imm); +}) +GEN(slti, { + vm_reg[0] = ra_load(state, ir->rs1); + emit_cmp_imm32(state, vm_reg[0], ir->imm); + vm_reg[1] = map_vm_reg(state, ir->rd); + emit_load_imm(state, vm_reg[1], 1); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x8c); + emit_load_imm(state, vm_reg[1], 0); + emit_jump_target_offset(state, JUMP_LOC, state->offset); +}) +GEN(sltiu, { + vm_reg[0] = ra_load(state, ir->rs1); + emit_cmp_imm32(state, vm_reg[0], ir->imm); + vm_reg[1] = map_vm_reg(state, ir->rd); + emit_load_imm(state, vm_reg[1], 1); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x82); + emit_load_imm(state, vm_reg[1], 0); + emit_jump_target_offset(state, JUMP_LOC, state->offset); +}) +GEN(xori, { + vm_reg[0] = ra_load(state, ir->rs1); + vm_reg[1] = map_vm_reg(state, ir->rd); + if (vm_reg[0] != vm_reg[1]) { + emit_mov(state, vm_reg[0], vm_reg[1]); + } + emit_alu32_imm32(state, 0x81, 6, vm_reg[1], ir->imm); +}) +GEN(ori, { + vm_reg[0] = ra_load(state, ir->rs1); + vm_reg[1] = map_vm_reg(state, ir->rd); + if (vm_reg[0] != vm_reg[1]) { + emit_mov(state, vm_reg[0], vm_reg[1]); + } + emit_alu32_imm32(state, 0x81, 1, vm_reg[1], ir->imm); +}) +GEN(andi, { + vm_reg[0] = ra_load(state, ir->rs1); + vm_reg[1] = map_vm_reg(state, ir->rd); + if (vm_reg[0] != vm_reg[1]) { + emit_mov(state, vm_reg[0], vm_reg[1]); + } + emit_alu32_imm32(state, 0x81, 4, vm_reg[1], ir->imm); +}) +GEN(slli, { + vm_reg[0] = ra_load(state, ir->rs1); + vm_reg[1] = map_vm_reg(state, ir->rd); + if (vm_reg[0] != vm_reg[1]) { + emit_mov(state, vm_reg[0], vm_reg[1]); + } + emit_alu32_imm8(state, 0xc1, 4, vm_reg[1], ir->imm & 0x1f); +}) +GEN(srli, { + vm_reg[0] = ra_load(state, ir->rs1); + vm_reg[1] = map_vm_reg(state, ir->rd); + if (vm_reg[0] != vm_reg[1]) { + emit_mov(state, vm_reg[0], vm_reg[1]); + } + emit_alu32_imm8(state, 0xc1, 5, vm_reg[1], ir->imm & 0x1f); +}) +GEN(srai, { + vm_reg[0] = ra_load(state, ir->rs1); + vm_reg[1] = map_vm_reg(state, ir->rd); + if (vm_reg[0] != vm_reg[1]) { + emit_mov(state, vm_reg[0], vm_reg[1]); + } + emit_alu32_imm8(state, 0xc1, 7, vm_reg[1], ir->imm & 0x1f); +}) +GEN(add, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32(state, 0x01, temp_reg, vm_reg[2]); +}) +GEN(sub, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32(state, 0x29, temp_reg, vm_reg[2]); +}) +GEN(sll, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32_imm32(state, 0x81, 4, temp_reg, 0x1f); + emit_alu32(state, 0xd3, 4, vm_reg[2]); +}) +GEN(slt, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_cmp32(state, vm_reg[1], vm_reg[0]); + emit_load_imm(state, vm_reg[2], 1); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x8c); + emit_load_imm(state, vm_reg[2], 0); + emit_jump_target_offset(state, JUMP_LOC, state->offset); +}) +GEN(sltu, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_cmp32(state, vm_reg[1], vm_reg[0]); + emit_load_imm(state, vm_reg[2], 1); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x82); + emit_load_imm(state, vm_reg[2], 0); + emit_jump_target_offset(state, JUMP_LOC, state->offset); +}) +GEN(xor, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32(state, 0x31, temp_reg, vm_reg[2]); +}) +GEN(srl, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32_imm32(state, 0x81, 4, temp_reg, 0x1f); + emit_alu32(state, 0xd3, 5, vm_reg[2]); +}) +GEN(sra, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32_imm32(state, 0x81, 4, temp_reg, 0x1f); + emit_alu32(state, 0xd3, 7, vm_reg[2]); +}) +GEN(or, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32(state, 0x09, temp_reg, vm_reg[2]); +}) +GEN(and, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32(state, 0x21, temp_reg, vm_reg[2]); +}) +GEN(fence, { assert(NULL); }) +GEN(ecall, { + store_back(state); + emit_load_imm(state, temp_reg, ir->pc); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_call(state, (intptr_t) rv->io.on_ecall); + emit_exit(state); +}) +GEN(ebreak, { + store_back(state); + emit_load_imm(state, temp_reg, ir->pc); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_call(state, (intptr_t) rv->io.on_ebreak); + emit_exit(state); +}) +GEN(wfi, { assert(NULL); }) +GEN(uret, { assert(NULL); }) +GEN(sret, { assert(NULL); }) +GEN(hret, { assert(NULL); }) +GEN(mret, { assert(NULL); }) +GEN(sfencevma, { assert(NULL); }) +#if RV32_HAS(Zifencei) /* RV32 Zifencei Standard Extension */ +GEN(fencei, { assert(NULL); }) +#endif +#if RV32_HAS(Zicsr) /* RV32 Zicsr Standard Extension */ +GEN(csrrw, { assert(NULL); }) +GEN(csrrs, { assert(NULL); }) +GEN(csrrc, { assert(NULL); }) +GEN(csrrwi, { assert(NULL); }) +GEN(csrrsi, { assert(NULL); }) +GEN(csrrci, { assert(NULL); }) +#endif +#if RV32_HAS(EXT_M) +GEN(mul, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + muldivmod(state, 0x28, temp_reg, vm_reg[2], 0); +}) +GEN(mulh, { + ra_load2_sext(state, ir->rs1, ir->rs2, true, true); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + muldivmod(state, 0x2f, temp_reg, vm_reg[2], 0); + emit_alu64_imm8(state, 0xc1, 5, vm_reg[2], 32); +}) +GEN(mulhsu, { + ra_load2_sext(state, ir->rs1, ir->rs2, true, false); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + muldivmod(state, 0x2f, temp_reg, vm_reg[2], 0); + emit_alu64_imm8(state, 0xc1, 5, vm_reg[2], 32); +}) +GEN(mulhu, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + muldivmod(state, 0x2f, temp_reg, vm_reg[2], 0); + emit_alu64_imm8(state, 0xc1, 5, vm_reg[2], 32); +}) +GEN(div, { + ra_load2_sext(state, ir->rs1, ir->rs2, true, true); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + muldivmod(state, 0x38, temp_reg, vm_reg[2], 1); +}) +GEN(divu, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + muldivmod(state, 0x38, temp_reg, vm_reg[2], 0); +}) +GEN(rem, { + ra_load2_sext(state, ir->rs1, ir->rs2, true, true); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + muldivmod(state, 0x98, temp_reg, vm_reg[2], 1); +}) +GEN(remu, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + muldivmod(state, 0x98, temp_reg, vm_reg[2], 0); +}) +#endif +#if RV32_HAS(EXT_A) +GEN(lrw, { assert(NULL); }) +GEN(scw, { assert(NULL); }) +GEN(amoswapw, { assert(NULL); }) +GEN(amoaddw, { assert(NULL); }) +GEN(amoxorw, { assert(NULL); }) +GEN(amoandw, { assert(NULL); }) +GEN(amoorw, { assert(NULL); }) +GEN(amominw, { assert(NULL); }) +GEN(amomaxw, { assert(NULL); }) +GEN(amominuw, { assert(NULL); }) +GEN(amomaxuw, { assert(NULL); }) +#endif +#if RV32_HAS(EXT_F) +GEN(flw, { assert(NULL); }) +GEN(fsw, { assert(NULL); }) +GEN(fmadds, { assert(NULL); }) +GEN(fmsubs, { assert(NULL); }) +GEN(fnmsubs, { assert(NULL); }) +GEN(fnmadds, { assert(NULL); }) +GEN(fadds, { assert(NULL); }) +GEN(fsubs, { assert(NULL); }) +GEN(fmuls, { assert(NULL); }) +GEN(fdivs, { assert(NULL); }) +GEN(fsqrts, { assert(NULL); }) +GEN(fsgnjs, { assert(NULL); }) +GEN(fsgnjns, { assert(NULL); }) +GEN(fsgnjxs, { assert(NULL); }) +GEN(fmins, { assert(NULL); }) +GEN(fmaxs, { assert(NULL); }) +GEN(fcvtws, { assert(NULL); }) +GEN(fcvtwus, { assert(NULL); }) +GEN(fmvxw, { assert(NULL); }) +GEN(feqs, { assert(NULL); }) +GEN(flts, { assert(NULL); }) +GEN(fles, { assert(NULL); }) +GEN(fclasss, { assert(NULL); }) +GEN(fcvtsw, { assert(NULL); }) +GEN(fcvtswu, { assert(NULL); }) +GEN(fmvwx, { assert(NULL); }) +#endif +#if RV32_HAS(EXT_C) +GEN(caddi4spn, { + vm_reg[0] = ra_load(state, rv_reg_sp); + vm_reg[1] = map_vm_reg(state, ir->rd); + if (vm_reg[0] != vm_reg[1]) { + emit_mov(state, vm_reg[0], vm_reg[1]); + } + emit_alu32_imm32(state, 0x81, 0, vm_reg[1], (uint16_t) ir->imm); +}) +GEN(clw, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, ir->rs1); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = map_vm_reg(state, ir->rd); + emit_load(state, S32, temp_reg, vm_reg[1], 0); +}) +GEN(csw, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, ir->rs1); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = ra_load(state, ir->rs2); + emit_store(state, S32, vm_reg[1], temp_reg, 0); +}) +GEN(cnop, {}) +GEN(caddi, { + vm_reg[0] = ra_load(state, ir->rd); + emit_alu32_imm32(state, 0x81, 0, vm_reg[0], (int16_t) ir->imm); +}) +GEN(cjal, { + vm_reg[0] = map_vm_reg(state, rv_reg_ra); + emit_load_imm(state, vm_reg[0], ir->pc + 2); + store_back(state); + emit_jmp(state, ir->pc + ir->imm); + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(cli, { + vm_reg[0] = map_vm_reg(state, ir->rd); + emit_load_imm(state, vm_reg[0], ir->imm); +}) +GEN(caddi16sp, { + vm_reg[0] = ra_load(state, ir->rd); + emit_alu32_imm32(state, 0x81, 0, vm_reg[0], ir->imm); +}) +GEN(clui, { + vm_reg[0] = map_vm_reg(state, ir->rd); + emit_load_imm(state, vm_reg[0], ir->imm); +}) +GEN(csrli, { + vm_reg[0] = ra_load(state, ir->rs1); + emit_alu32_imm8(state, 0xc1, 5, vm_reg[0], ir->shamt); +}) +GEN(csrai, { + vm_reg[0] = ra_load(state, ir->rs1); + emit_alu32_imm8(state, 0xc1, 7, vm_reg[0], ir->shamt); +}) +GEN(candi, { + vm_reg[0] = ra_load(state, ir->rs1); + emit_alu32_imm32(state, 0x81, 4, vm_reg[0], ir->imm); +}) +GEN(csub, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32(state, 0x29, temp_reg, vm_reg[2]); +}) +GEN(cxor, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32(state, 0x31, temp_reg, vm_reg[2]); +}) +GEN(cor, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32(state, 0x09, temp_reg, vm_reg[2]); +}) +GEN(cand, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32(state, 0x21, temp_reg, vm_reg[2]); +}) +GEN(cj, { + store_back(state); + emit_jmp(state, ir->pc + ir->imm); + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(cbeqz, { + vm_reg[0] = ra_load(state, ir->rs1); + emit_cmp_imm32(state, vm_reg[0], 0); + store_back(state); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x84); + if (ir->branch_untaken) { + emit_jmp(state, ir->pc + 2); + } + emit_load_imm(state, temp_reg, ir->pc + 2); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); + emit_jump_target_offset(state, JUMP_LOC, state->offset); + if (ir->branch_taken) { + emit_jmp(state, ir->pc + ir->imm); + } + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(cbnez, { + vm_reg[0] = ra_load(state, ir->rs1); + emit_cmp_imm32(state, vm_reg[0], 0); + store_back(state); + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x85); + if (ir->branch_untaken) { + emit_jmp(state, ir->pc + 2); + } + emit_load_imm(state, temp_reg, ir->pc + 2); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); + emit_jump_target_offset(state, JUMP_LOC, state->offset); + if (ir->branch_taken) { + emit_jmp(state, ir->pc + ir->imm); + } + emit_load_imm(state, temp_reg, ir->pc + ir->imm); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(cslli, { + vm_reg[0] = ra_load(state, ir->rd); + emit_alu32_imm8(state, 0xc1, 4, vm_reg[0], (uint8_t) ir->imm); +}) +GEN(clwsp, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, rv_reg_sp); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = map_vm_reg(state, ir->rd); + emit_load(state, S32, temp_reg, vm_reg[1], 0); +}) +GEN(cjr, { + vm_reg[0] = ra_load(state, ir->rs1); + emit_mov(state, vm_reg[0], temp_reg); + store_back(state); + parse_branch_history_table(state, ir); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(cmv, { + vm_reg[0] = ra_load(state, ir->rs2); + vm_reg[1] = map_vm_reg(state, ir->rd); + if (vm_reg[0] != vm_reg[1]) { + emit_mov(state, vm_reg[0], vm_reg[1]); + } else { + set_dirty(vm_reg[1], true); + } +}) +GEN(cebreak, { + store_back(state); + emit_load_imm(state, temp_reg, ir->pc); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_call(state, (intptr_t) rv->io.on_ebreak); + emit_exit(state); +}) +GEN(cjalr, { + vm_reg[0] = ra_load(state, ir->rs1); + emit_mov(state, vm_reg[0], temp_reg); + vm_reg[1] = map_vm_reg(state, rv_reg_ra); + emit_load_imm(state, vm_reg[1], ir->pc + 2); + store_back(state); + parse_branch_history_table(state, ir); + emit_store(state, S32, temp_reg, parameter_reg[0], offsetof(riscv_t, PC)); + emit_exit(state); +}) +GEN(cadd, { + ra_load2(state, ir->rs1, ir->rs2); + vm_reg[2] = map_vm_reg(state, ir->rd); + emit_mov(state, vm_reg[1], temp_reg); + emit_mov(state, vm_reg[0], vm_reg[2]); + emit_alu32(state, 0x01, temp_reg, vm_reg[2]); +}) +GEN(cswsp, { + memory_t *m = PRIV(rv)->mem; + vm_reg[0] = ra_load(state, rv_reg_sp); + emit_load_imm(state, temp_reg, (intptr_t) (m->mem_base + ir->imm)); + emit_alu64(state, 0x01, vm_reg[0], temp_reg); + vm_reg[1] = ra_load(state, ir->rs2); + emit_store(state, S32, vm_reg[1], temp_reg, 0); +}) +#endif +#if RV32_HAS(EXT_C) && RV32_HAS(EXT_F) +GEN(cflwsp, { assert(NULL); }) +GEN(cfswsp, { assert(NULL); }) +GEN(cflw, { assert(NULL); }) +GEN(cfsw, { assert(NULL); }) +#endif diff --git a/tools/gen-jit-template.py b/tools/gen-jit-template.py deleted file mode 100755 index ff605b07..00000000 --- a/tools/gen-jit-template.py +++ /dev/null @@ -1,274 +0,0 @@ -#!/usr/bin/env python3 - -''' -This script serves as a code generator for creating JIT code templates -based on existing code files in the 'src' directory, eliminating the need -for writing duplicated code. -''' - -import re -import sys - -INSN = { - "Zifencei": ["fencei"], - "Zicsr": [ - "csrrw", - "csrrs", - "csrrc", - "csrrw", - "csrrsi", - "csrrci"], - "EXT_M": [ - "mul", - "mulh", - "mulhsu", - "mulhu", - "div", - "divu", - "rem", - "remu"], - "EXT_A": [ - "lrw", - "scw", - "amoswapw", - "amoaddw", - "amoxorw", - "amoandw", - "amoorw", - "amominw", - "amomaxw", - "amominuw", - "amomaxuw"], - "EXT_F": [ - "flw", - "fsw", - "fmadds", - "fmsubs", - "fnmsubs", - "fnmadds", - "fadds", - "fsubs", - "fmuls", - "fdivs", - "fsqrts", - "fsgnjs", - "fsgnjns", - "fsgnjxs", - "fmins", - "fmaxs", - "fcvtws", - "fcvtwus", - "fmvxw", - "feqs", - "flts", - "fles", - "fclasss", - "fcvtsw", - "fcvtswu", - "fmvwx"], - "EXT_C": [ - "caddi4spn", - "clw", - "csw", - "cnop", - "caddi", - "cjal", - "cli", - "caddi16sp", - "clui", - "csrli", - "csrai", - "candi", - "csub", - "cxor", - "cor", - "cand", - "cj", - "cbeqz", - "cbnez", - "cslli", - "clwsp", - "cjr", - "cmv", - "cebreak", - "cjalr", - "cadd", - "cswsp", - ], - "EXT_FC": [ - "cflwsp", - "cfswsp", - "cflw", - "cfsw", - ], -} -EXT_LIST = ["Zifencei", "Zicsr", "EXT_M", "EXT_A", "EXT_F", "EXT_C"] -SKIP_LIST = [] -# check enabled extension in Makefile - - -def parse_argv(EXT_LIST, SKIP_LIST): - for argv in sys.argv: - if argv.find("RV32_FEATURE_") != -1: - ext = argv[argv.find("RV32_FEATURE_") + 13:-2] - if argv[-1:] == "1" and EXT_LIST.count(ext): - EXT_LIST.remove(ext) - for ext in EXT_LIST: - SKIP_LIST += INSN[ext] - if "EXT_F" in EXT_LIST or "EXT_C" in EXT_LIST: - SKIP_LIST += INSN["EXT_FC"] - -parse_argv(EXT_LIST, SKIP_LIST) -# prepare PROLOGUE -output = "" -f = open('src/rv32_template.c', 'r') -lines = f.read() -# remove_comment -lines = re.sub(r'/\*[\s|\S]+?\*/', "", lines) -# remove exception handler -lines = re.sub(r'RV_EXC[\S]+?\([\S|\s]+?\);\s', "", lines) -# collect functions -emulate_funcs = re.findall(r'RVOP\([\s|\S]+?}\)', lines) -codegen_funcs = re.findall(r'GEN\([\s|\S]+?}\)', lines) -op = [] -impl = [] -for i in range(len(emulate_funcs)): - op.append(emulate_funcs[i][5:emulate_funcs[i].find(',')].strip()) - impl.append(codegen_funcs[i]) - -f.close() - -fields = {"imm", "pc", "rs1", "rs2", "rd", "shamt", "branch_taken", "branch_untaken"} -virt_regs = {"VR0", "VR1", "VR2"} -# generate jit template -for i in range(len(op)): - if (not SKIP_LIST.count(op[i])): - output += impl[i][0:4] + op[i] + ", {" - IRs = re.findall(r'[\s|\S]+?;', impl[i][5:]) - # parse_and_translate_IRs - for i in range(len(IRs)): - IR = IRs[i].strip()[:-1] - items = [s.strip() for s in IR.split(',')] - asm = "" - for i in range(len(items)): - if items[i] in fields: - items[i] = "ir->" + items[i] - if items[i] in virt_regs: - items[i] = "vm_reg[" + items[i][-1] + "]" - if items[i] == "TMP": - items[i] = "temp_reg" - if items[0] == "alu32imm": - if len(items) == 8: - asm = "emit_alu32_imm{}(state, {}, {}, {}, ({}{}_t) {});".format( - items[1], items[2], items[3], items[4], items[5], items[6], items[7]) - elif len(items) == 7: - asm = "emit_alu32_imm{}(state, {}, {}, {}, {} & {});".format( - items[1], items[2], items[3], items[4], items[5], items[6]) - else: - asm = "emit_alu32_imm{}(state, {}, {}, {}, {});".format( - items[1], items[2], items[3], items[4], items[5]) - elif items[0] == "alu64imm": - asm = "emit_alu64_imm{}(state, {}, {}, {}, {});".format( - items[1], items[2], items[3], items[4], items[5]) - elif items[0] == "alu64": - asm = "emit_alu64(state, {}, {}, {});".format( - items[1], items[2], items[3]) - elif items[0] == "alu32": - asm = "emit_alu32(state, {}, {}, {});".format( - items[1], items[2], items[3]) - elif items[0] == "ldimm": - if items[2] == "mem": - asm = "emit_load_imm(state, {}, (intptr_t) (m->mem_base + ir->imm));".format( - items[1]) - elif len(items) == 4: - asm = "emit_load_imm(state, {}, {} + {});".format( - items[1], items[2], items[3]) - else: - asm = "emit_load_imm(state, {}, {});".format( - items[1], items[2]) - elif items[0] == "lds": - if (items[3] == "X"): - asm = "emit_load_sext(state, {}, parameter_reg[0], {}, offsetof(riscv_t, X) + 4 * {});".format( - items[1], items[2], items[4]) - else: - asm = "emit_load_sext(state, {}, {}, {}, {});".format( - items[1], items[2], items[3], items[4]) - elif items[0] == "rald": - asm = "{} = ra_load(state, {});".format(items[1], items[2]) - elif items[0] == "rald2": - asm = "ra_load2(state, {}, {});".format(items[1], items[2]) - elif items[0] == "rald2s": - asm = "ra_load2_sext(state, {}, {}, {}, {});".format(items[1], items[2], items[3], items[4]) - elif items[0] == "map": - asm = "{} = map_vm_reg(state, {});".format(items[1], items[2]) - elif items[0] == "ld": - if (items[3] == "X"): - asm = "emit_load(state, {}, parameter_reg[0], {}, offsetof(riscv_t, X) + 4 * {});".format( - items[1], items[2], items[4]) - else: - asm = "emit_load(state, {}, {}, {}, {});".format( - items[1], items[2], items[3], items[4]) - elif items[0] == "st": - if (items[3] == "X"): - asm = "emit_store(state, {}, {}, parameter_reg[0], offsetof(riscv_t, X) + 4 * {});".format( - items[1], items[2], items[4]) - elif items[3] == "PC" or items[3] == "compressed": - asm = "emit_store(state, {}, {}, parameter_reg[0], offsetof(riscv_t, {}));".format( - items[1], items[2], items[3]) - else: - asm = "emit_store(state, {}, {}, {}, {});".format( - items[1], items[2], items[3], items[4]) - elif items[0] == "mov": - asm = "emit_mov(state, {}, {});".format( - items[1], items[2]) - elif items[0] == "cmp": - asm = "emit_cmp32(state, {}, {});".format( - items[1], items[2]) - elif items[0] == "cmpimm": - asm = "emit_cmp_imm32(state, {}, {});".format( - items[1], items[2]) - elif items[0] == "jmp": - asm = "emit_jmp(state, {} + {});".format( - items[1], items[2]) - elif items[0] == "jcc": - asm = "emit_jcc_offset(state, {});".format(items[1]) - elif items[0] == "setjmpoff": - asm = "uint32_t jump_loc = state->offset;" - elif items[0] == "jmpoff": - asm = "emit_jump_target_offset(state, JUMP_LOC, state->offset);" - elif items[0] == "mem": - asm = "memory_t *m = PRIV(rv)->mem;" - elif items[0] == "call": - asm = "emit_call(state, (intptr_t) rv->io.on_{});".format( - items[1]) - elif items[0] == "exit": - asm = "emit_exit(state);" - elif items[0] == "mul": - asm = "muldivmod(state, {}, {}, {}, {});".format( - items[1], items[2], items[3], items[4]) - elif items[0] == "div": - asm = "muldivmod(state, {}, {}, {}, {});".format( - items[1], items[2], items[3], items[4]) - elif items[0] == "mod": - asm = "muldivmod(state, {}, {}, {}, {});".format( - items[1], items[2], items[3], items[4]) - elif items[0] == "cond": - if items[1] == "regneq": - items[1] = "vm_reg[0] != vm_reg[1]" - asm = "if({})".format(items[1]) + "{" - elif items[0] == "else": - asm = "} else {" - elif items[0] == "end": - asm = "}" - elif items[0] == "pollute": - asm = "set_dirty({}, true);".format(items[1]) - elif items[0] == "break": - asm = "store_back(state);" - elif items[0] == "assert": - asm = "assert(NULL);" - elif items[0] == "predict": - asm = "parse_branch_history_table(state, ir);" - output += asm + "\n" - output += "})\n" - -sys.stdout.write(output)