From 48ad30dcaee98efe0969e84db1619b8dcda5f016 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Tue, 24 Apr 2018 11:05:11 +0200 Subject: [PATCH] Added RV32F extension, fixed RV32M bugs --- .cproject | 10 +- .settings/org.eclipse.cdt.core.prefs | 11 + dbt-core | 2 +- etc/CoreDSL generator.launch | 6 +- riscv/gen_input/RV32C.core_desc | 77 +- riscv/gen_input/RV32F.core_desc | 231 +- riscv/gen_input/RV32M.core_desc | 28 +- riscv/gen_input/minres_rv.core_desc | 22 +- riscv/gen_input/templates/incl-CORENAME.h.gtl | 17 +- .../gen_input/templates/src-CORENAME.cpp.gtl | 5 +- .../templates/vm-vm_CORENAME.cpp.gtl | 26 +- riscv/incl/iss/arch/riscv_hart_msu_vp.h | 44 + riscv/incl/iss/arch/rv32gc.h | 278 + riscv/incl/iss/arch/rv32imac.h | 6 + riscv/incl/iss/arch/rv64ia.h | 6 + riscv/src/internal/fp_functions.cpp | 290 + riscv/src/internal/vm_rv32gc.cpp | 6524 +++++++++++++++++ riscv/src/internal/vm_rv32imac.cpp | 608 +- riscv/src/internal/vm_rv64ia.cpp | 444 +- riscv/src/iss/rv32gc.cpp | 74 + riscv/src/main.cpp | 11 +- 21 files changed, 8208 insertions(+), 512 deletions(-) create mode 100644 .settings/org.eclipse.cdt.core.prefs create mode 100644 riscv/incl/iss/arch/rv32gc.h create mode 100644 riscv/src/internal/fp_functions.cpp create mode 100644 riscv/src/internal/vm_rv32gc.cpp create mode 100644 riscv/src/iss/rv32gc.cpp diff --git a/.cproject b/.cproject index 64a9192..1cc7571 100644 --- a/.cproject +++ b/.cproject @@ -13,7 +13,7 @@ - + @@ -46,6 +46,13 @@ + + + + + + + @@ -177,4 +184,5 @@ + diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 0000000..01d5b4d --- /dev/null +++ b/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/LLVM_HOME/delimiter=\: +environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/LLVM_HOME/operation=replace +environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/LLVM_HOME/value=/usr/lib/llvm-4.0 +environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true +environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/delimiter=\: +environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/operation=append +environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/value=/usr/lib/llvm-6.0 +environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true +environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true diff --git a/dbt-core b/dbt-core index bc05d40..d951285 160000 --- a/dbt-core +++ b/dbt-core @@ -1 +1 @@ -Subproject commit bc05d40184ccb8871afa61620fe2c67ce2951fa4 +Subproject commit d9512853b22e869938013c8dc0c6678a92d52c0e diff --git a/etc/CoreDSL generator.launch b/etc/CoreDSL generator.launch index d1f85cb..e6e6eda 100644 --- a/etc/CoreDSL generator.launch +++ b/etc/CoreDSL generator.launch @@ -2,7 +2,7 @@ - - - + + + diff --git a/riscv/gen_input/RV32C.core_desc b/riscv/gen_input/RV32C.core_desc index 59bc051..c19b9e3 100644 --- a/riscv/gen_input/RV32C.core_desc +++ b/riscv/gen_input/RV32C.core_desc @@ -1,6 +1,6 @@ import "RV32IBase.core_desc" -InsructionSet RV32CI { +InsructionSet RV32IC { constants { XLEN } @@ -197,7 +197,64 @@ InsructionSet RV32CI { } } -InsructionSet RV32CF extends RV32CI { +InsructionSet RV32FC extends RV32IC{ + constants { + XLEN, FLEN + } + address_spaces { + MEM[8] + } + registers { + [31:0] X[XLEN], + [31:0] F[FLEN] + } + instructions{ + C.FLW { + encoding: b011 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00; + args_disass:"f(8+%rd$d), %uimm%(x(8+%rs1$d))"; + val rs1_idx[5] <= rs1+8; + val rd_idx[5] <= rd+8; + val offs[XLEN] <= X[rs1_idx]+uimm; + val res[32] <= MEM[offs]{32}; + if(FLEN==32) + F[rd_idx] <= res; + else { + val upper[FLEN] <= (-1<<31); + F[rd_idx] <= upper*2 | res; + } + } + C.FSW { + encoding: b111 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00; + args_disass:"f(8+%rs2$d), %uimm%(x(8+%rs1$d))"; + val rs1_idx[5] <= rs1+8; + val rs2_idx[5] <= rs2+8; + val offs[XLEN] <= X[rs1_idx]+uimm; + MEM[offs]{32}<=F[rs2_idx]{32}; + } + C.FLWSP { + encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10; + args_disass:"f%rd$d, %uimm%(x2)"; + val x2_idx[5] <= 2; + val offs[XLEN] <= X[x2_idx]+uimm; + val res[32] <= MEM[offs]{32}; + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= (-1<<31); + F[rd] <= upper*2 | res; + } + } + C.FSWSP { + encoding:b111 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10; + args_disass:"f%rs2$d, %uimm%(x2), "; + val x2_idx[5] <= 2; + val offs[XLEN] <= X[x2_idx]+uimm; + MEM[offs]{32}<=F[rs2]; + } + } +} + +InsructionSet RV32DC extends RV32IC{ constants { XLEN, FLEN } @@ -212,31 +269,19 @@ InsructionSet RV32CF extends RV32CI { C.FLD { //(RV32/64) encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00; } - C.FLW {//(RV32) - encoding: b011 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00; - } C.FSD { //(RV32/64) encoding: b101 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00; } - C.FSW {//(RV32) - encoding: b111 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00; - } C.FLDSP {//(RV32/64) encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10; } - C.FLWSP {//RV32 - encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10; - } C.FSDSP {//(RV32/64) encoding:b101 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10; } - C.FSWSP {//(RV32) - encoding:b111 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10; - } } } -InsructionSet RV64CI extends RV32CI { +InsructionSet RV64IC extends RV32IC { constants { XLEN } @@ -284,7 +329,7 @@ InsructionSet RV64CI extends RV32CI { } } -InsructionSet RV128CI extends RV64CI { +InsructionSet RV128IC extends RV64IC { constants { XLEN } diff --git a/riscv/gen_input/RV32F.core_desc b/riscv/gen_input/RV32F.core_desc index 6efb8fb..ea5711e 100644 --- a/riscv/gen_input/RV32F.core_desc +++ b/riscv/gen_input/RV32F.core_desc @@ -2,104 +2,293 @@ import "RV32IBase.core_desc" InsructionSet RV32F extends RV32IBase{ constants { - FLEN, fcsr + FLEN, FFLAG_MASK } registers { - [31:0] F[FLEN] + [31:0] F[FLEN], FCSR[32] } instructions{ FLW { encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000111; + args_disass:"f%rd$d, %imm%(x%rs1$d)"; val offs[XLEN] <= X[rs1]+imm; - F[rd]<=MEM[offs]; + val res[32] <= MEM[offs]{32}; + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= (-1<<31); + F[rd] <= upper*2 | res; + } } FSW { encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100111; + args_disass:"f%rs2$d, %imm%(x%rs1$d)"; val offs[XLEN] <= X[rs1]+imm; - MEM[offs]<=F[rs2]; + MEM[offs]{32}<=F[rs2]{32}; } FMADD.S { encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011; - F[rd]f<= F[rs1]f * F[rs2]f * F[rs3]f; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; + //F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f; + val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(0, 32), choose(rm<7, rm{8}, FCSR{8})); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= (-1<<31); + F[rd] <= upper*2 | res; + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FMSUB.S { encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111; - F[rd]f<=F[rs1]f * F[rs2]f -F[rs3]f; - } - FNMSUB.S { - encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011; - F[rd]f<=-F[rs1]f * F[rs2]f- F[rs3]f; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; + //F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f; + val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8})); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= (-1<<31); + F[rd] <= upper*2 | res; + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FNMADD.S { encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111; - F[rd]f<=-F[rs1]f*F[rs2]f+F[rs3]f; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; + //F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f; + val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8})); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= (-1<<31); + F[rd] <= upper*2 | res; + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; + } + FNMSUB.S { + encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; + //F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f; + val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8})); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= (-1<<31); + F[rd] <= upper*2 | res; + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FADD.S { encoding: b0000000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - F[rd]f <= F[rs1]f + F[rs2]f; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + // F[rd]f <= F[rs1]f + F[rs2]f; + val res[32] <= fdispatch_fadd_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= (-1<<31); + F[rd] <= upper*2 | res; + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FSUB.S { encoding: b0000100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - F[rd]f <= F[rs1]f - F[rs2]f; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + // F[rd]f <= F[rs1]f - F[rs2]f; + val res[32] <= fdispatch_fsub_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | res; + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FMUL.S { encoding: b0001000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - F[rd]f <= F[rs1]f * F[rs2]; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + // F[rd]f <= F[rs1]f * F[rs2]f; + val res[32] <= fdispatch_fmul_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | res; + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FDIV.S { encoding: b0001100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - F[rd]f <= F[rs1]f / F[rs2]f; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + // F[rd]f <= F[rs1]f / F[rs2]f; + val res[32] <= fdispatch_fdiv_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | res; + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FSQRT.S { encoding: b0101100 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - F[rd]f<=sqrt(F[rs1]f); + args_disass:"x%rd$d, f%rs1$d"; + //F[rd]f<=sqrt(F[rs1]f); + val res[32] <= fdispatch_fsqrt_s(F[rs1]{32}, choose(rm<7, rm{8}, FCSR{8})); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | res; + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FSGNJ.S { encoding: b0010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; + val res[32] <= (F[rs1]{32} & 0x7fffffff) | (F[rs2]{32} & 0x80000000); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | res; + } } FSGNJN.S { encoding: b0010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; + args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; + val res[32] <= (F[rs1]{32} & 0x7fffffff) | (~F[rs2]{32} & 0x80000000); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | res; + } } FSGNJX.S { encoding: b0010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; + args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; + val res[32] <= F[rs1]{32} ^ (F[rs2]{32} & 0x80000000); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | res; + } } FMIN.S { encoding: b0010100 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; - F[rd]f<= choose(F[rs1]fF[rs2]f, F[rs1]f, F[rs2]f); + args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; + //F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f); + val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32)); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | res; + } + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FCVT.W.S { encoding: b1100000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"x%rd$d, f%rs1$d"; + X[rd]<= sext(fdispatch_fcvt_s(F[rs1]{32}, zext(0, 32), rm{8}), XLEN); + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FCVT.WU.S { encoding: b1100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; - } - FMV.X.W { - encoding: b1110000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"x%rd$d, f%rs1$d"; + X[rd]<= zext(fdispatch_fcvt_s(F[rs1]{32}, zext(1, 32), rm{8}), XLEN); + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FEQ.S { encoding: b1010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(0, 32)); + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FLT.S { encoding: b1010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(2, 32)); + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FLE.S { encoding: b1010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; + X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32)); + val flags[32] <= fdispatch_fget_flags(); + FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; } FCLASS.S { encoding: b1110000 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011; + args_disass:"x%rd$d, f%rs1$d"; + X[rd]<=fdispatch_fclass_s(F[rs1]{32}); } FCVT.S.W { encoding: b1101000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f%rd$d, x%rs1$d"; + val res[32] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8}); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | res; + } } FCVT.S.WU { encoding: b1101000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; + args_disass:"f%rd$d, x%rs1$d"; + val res[32] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8}); + if(FLEN==32) + F[rd] <= res; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | res; + } + } + FMV.X.W { + encoding: b1110000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"x%rd$d, f%rs1$d"; + X[rd]<=sext(F[rs1]{32}); } FMV.W.X { encoding: b1111000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; + args_disass:"f%rd$d, x%rs1$d"; + if(FLEN==32) + F[rd] <= X[rs1]; + else { + val upper[FLEN] <= -1<<31; + F[rd] <= upper*2 | X[rs1]; + } } } } \ No newline at end of file diff --git a/riscv/gen_input/RV32M.core_desc b/riscv/gen_input/RV32M.core_desc index d8a15dd..b2d88fa 100644 --- a/riscv/gen_input/RV32M.core_desc +++ b/riscv/gen_input/RV32M.core_desc @@ -41,9 +41,17 @@ InsructionSet RV32M extends RV32IBase { encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011; args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; if(rd != 0){ - if(X[rs2]!=0) - X[rd] <= sext(X[rs1], 32) / sext(X[rs2], 32); - else + if(X[rs2]!=0){ + val M1[XLEN] <= -1; + val MMIN[XLEN] <= -1<<(XLEN-1); + if(X[rs1]s==MMIN's) + if(X[rs2]s==M1's) + X[rd]<=MMIN; + else + X[rd] <= X[rs1]s / X[rs2]s; + else + X[rd] <= X[rs1]s / X[rs2]s; + }else X[rd] <= -1; } } @@ -61,9 +69,17 @@ InsructionSet RV32M extends RV32IBase { encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011; args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; if(rd != 0){ - if(X[rs2]!=0) - X[rd] <= sext(X[rs1], 32) % sext(X[rs2], 32); - else + if(X[rs2]!=0) { + val M1[XLEN] <= -1; + val MMIN[XLEN] <= -1<<(XLEN-1); + if(X[rs1]s==MMIN's) + if(X[rs2]s==M1's) + X[rd] <= 0; + else + X[rd] <= sext(X[rs1], 32) % sext(X[rs2], 32); + else + X[rd] <= sext(X[rs1], 32) % sext(X[rs2], 32); + } else X[rd] <= X[rs1]; } } diff --git a/riscv/gen_input/minres_rv.core_desc b/riscv/gen_input/minres_rv.core_desc index e735f99..3b8ee93 100644 --- a/riscv/gen_input/minres_rv.core_desc +++ b/riscv/gen_input/minres_rv.core_desc @@ -2,12 +2,13 @@ import "RV32IBase.core_desc" import "RV32M.core_desc" import "RV32A.core_desc" import "RV32C.core_desc" +import "RV32F.core_desc" import "RV64IBase.core_desc" //import "RV64M.core_desc" import "RV64A.core_desc" -Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32CI { +Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32IC { template:"vm_riscv.in.cpp"; constants { XLEN:=32; @@ -25,6 +26,25 @@ Core RV32IMAC provides RV32IBase, RV32M, RV32A, RV32CI { } } +Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC { + constants { + XLEN:=32; + FLEN:=32; + XLEN2:=64; + XLEN_BIT_MASK:=0x1f; + PCLEN:=32; + fence:=0; + fencei:=1; + fencevmal:=2; + fencevmau:=3; + // XL ZYXWVUTSRQPONMLKJIHGFEDCBA + MISA_VAL:=0b01000000000101000001000100000001; + PGSIZE := 4096; //1 << 12; + PGMASK := 4095; //PGSIZE-1 + FFLAG_MASK:=0x1f; + } +} + Core RV64IA provides RV64IBase, RV64A, RV32A { template:"vm_riscv.in.cpp"; diff --git a/riscv/gen_input/templates/incl-CORENAME.h.gtl b/riscv/gen_input/templates/incl-CORENAME.h.gtl index 2b5686a..4b0c2d3 100644 --- a/riscv/gen_input/templates/incl-CORENAME.h.gtl +++ b/riscv/gen_input/templates/incl-CORENAME.h.gtl @@ -100,6 +100,8 @@ struct traits<${coreDef.name.toLowerCase()}> { enum mem_type_e {${allSpaces.collect{s -> s.name}.join(', ')}}; + constexpr static bool has_fp_regs = ${allRegs.find {it.name=='FCSR'}!= null ?'true':'false'}; + }; struct ${coreDef.name.toLowerCase()}: public arch_if { @@ -112,8 +114,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { ${coreDef.name.toLowerCase()}(); ~${coreDef.name.toLowerCase()}(); - const std::string core_type_name() const override {return traits<${coreDef.name.toLowerCase()}>::core_type;} - void reset(uint64_t address=0) override; uint8_t* get_regs_base_ptr() override; @@ -158,9 +158,16 @@ protected: } reg; std::array addr_mode; - - uint64_t cycles = 0; - + +<% +def fcsr = allRegs.find {it.name=='FCSR'} +if(fcsr != null) {%> + uint${generator.getSize(fcsr)}_t get_fcsr(){return reg.FCSR;} + void set_fcsr(uint${generator.getSize(fcsr)}_t val){reg.FCSR = val;} +<%} else { %> + uint32_t get_fcsr(){return 0;} + void set_fcsr(uint32_t val){} +<%}%> }; } diff --git a/riscv/gen_input/templates/src-CORENAME.cpp.gtl b/riscv/gen_input/templates/src-CORENAME.cpp.gtl index 836bab0..5c2f1bd 100644 --- a/riscv/gen_input/templates/src-CORENAME.cpp.gtl +++ b/riscv/gen_input/templates/src-CORENAME.cpp.gtl @@ -68,6 +68,7 @@ uint8_t* ${coreDef.name.toLowerCase()}::get_regs_base_ptr(){ return reinterpret_cast(®); } -${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::v2p(const iss::addr_t& pc) { - return phys_addr_t(pc); //change logical address to physical address +${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &pc) { + return phys_addr_t(pc); // change logical address to physical address } + diff --git a/riscv/gen_input/templates/vm-vm_CORENAME.cpp.gtl b/riscv/gen_input/templates/vm-vm_CORENAME.cpp.gtl index b4f91f7..0b78375 100644 --- a/riscv/gen_input/templates/vm-vm_CORENAME.cpp.gtl +++ b/riscv/gen_input/templates/vm-vm_CORENAME.cpp.gtl @@ -48,6 +48,12 @@ #include namespace iss { +namespace vm { +namespace fp_impl{ +void add_fp_functions_2_module(llvm::Module *mod); +} +} + namespace ${coreDef.name.toLowerCase()} { using namespace iss::arch; using namespace llvm; @@ -81,6 +87,11 @@ protected: return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); } + void setup_module(llvm::Module* m) override { + super::setup_module(m); + vm::fp_impl::add_fp_functions_2_module(m); + } + inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) const { return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); @@ -106,6 +117,10 @@ protected: return this->builder.CreateLoad(get_reg_ptr(i), false); } + llvm::Value* gen_fdispatch(std::string fname, const std::vector& args); + + llvm::Value* gen_dispatch(std::string name, llvm::Value*, llvm::Value*, llvm::Value*); + inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), this->get_type(traits::XLEN)); @@ -310,7 +325,16 @@ template inline void vm_impl::gen_trap_check(llvm::BasicBl bb, this->trap_blk, 1); } -} // namespace ${coreDef.name.toLowerCase()} +template +inline llvm::Value* vm_impl::gen_fdispatch(std::string fname, const std::vector& args) { + return this->builder.CreateCall(this->mod->getFunction(fname), args); +} + +template +inline llvm::Value* vm_impl::gen_dispatch(std::string name, llvm::Value* val1, llvm::Value* val2, llvm::Value* val3) { +} + +} // namespace rv32imacf template <> std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) { diff --git a/riscv/incl/iss/arch/riscv_hart_msu_vp.h b/riscv/incl/iss/arch/riscv_hart_msu_vp.h index 64f9381..dede9de 100644 --- a/riscv/incl/iss/arch/riscv_hart_msu_vp.h +++ b/riscv/incl/iss/arch/riscv_hart_msu_vp.h @@ -48,6 +48,7 @@ #include #include #include +#include namespace iss { namespace arch { @@ -537,6 +538,8 @@ private: iss::status write_ip(unsigned addr, reg_t val); iss::status read_satp(unsigned addr, reg_t &val); iss::status write_satp(unsigned addr, reg_t val); + iss::status read_fcsr(unsigned addr, reg_t& val); + iss::status write_fcsr(unsigned addr, reg_t val); protected: void check_interrupt(); }; @@ -579,6 +582,13 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() csr_wr_cb[uie] = &riscv_hart_msu_vp::write_ie; csr_rd_cb[satp] = &riscv_hart_msu_vp::read_satp; csr_wr_cb[satp] = &riscv_hart_msu_vp::write_satp; + csr_rd_cb[fcsr] = &riscv_hart_msu_vp::read_fcsr; + csr_wr_cb[fcsr] = &riscv_hart_msu_vp::write_fcsr; + csr_rd_cb[fflags] = &riscv_hart_msu_vp::read_fcsr; + csr_wr_cb[fflags] = &riscv_hart_msu_vp::write_fcsr; + csr_rd_cb[frm] = &riscv_hart_msu_vp::read_fcsr; + csr_wr_cb[frm] = &riscv_hart_msu_vp::write_fcsr; + } template std::pair riscv_hart_msu_vp::load_file(std::string name, int type) { @@ -940,6 +950,39 @@ template iss::status riscv_hart_msu_vp::write_satp(unsigne update_vm_info(); return iss::Ok; } +template iss::status riscv_hart_msu_vp::read_fcsr(unsigned addr, reg_t& val) { + switch(addr){ + case 1: //fflags, 4:0 + val = bit_sub<0, 5>(this->get_fcsr()); + break; + case 2: // frm, 7:5 + val = bit_sub<5, 3>(this->get_fcsr()); + break; + case 3: // fcsr + val=this->get_fcsr(); + break; + default: + return iss::Err; + } + return iss::Ok; +} + +template iss::status riscv_hart_msu_vp::write_fcsr(unsigned addr, reg_t val) { + switch(addr){ + case 1: //fflags, 4:0 + this->set_fcsr( (this->get_fcsr() & 0xffffffe0) | (val&0x1f)); + break; + case 2: // frm, 7:5 + this->set_fcsr( (this->get_fcsr() & 0xffffff1f) | ((val&0x7)<<5)); + break; + case 3: // fcsr + this->set_fcsr(val&0xff); + break; + default: + return iss::Err; + } + return iss::Ok; +} template iss::status riscv_hart_msu_vp::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { @@ -1299,4 +1342,5 @@ template void riscv_hart_msu_vp::wait_until(uint64_t flags } } + #endif /* _RISCV_CORE_H_ */ diff --git a/riscv/incl/iss/arch/rv32gc.h b/riscv/incl/iss/arch/rv32gc.h new file mode 100644 index 0000000..106c70c --- /dev/null +++ b/riscv/incl/iss/arch/rv32gc.h @@ -0,0 +1,278 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, MINRES Technologies GmbH +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef _RV32GC_H_ +#define _RV32GC_H_ + +#include +#include +#include +#include + +namespace iss { +namespace arch { + +struct rv32gc; + +template<> +struct traits { + + constexpr static char const* const core_type = "RV32GC"; + + enum constants {XLEN=32, FLEN=32, XLEN2=64, XLEN_BIT_MASK=31, PCLEN=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=1075056897, PGSIZE=4096, PGMASK=4095, FFLAG_MASK=31}; + + enum reg_e { + X0, + X1, + X2, + X3, + X4, + X5, + X6, + X7, + X8, + X9, + X10, + X11, + X12, + X13, + X14, + X15, + X16, + X17, + X18, + X19, + X20, + X21, + X22, + X23, + X24, + X25, + X26, + X27, + X28, + X29, + X30, + X31, + PC, + F0, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + F25, + F26, + F27, + F28, + F29, + F30, + F31, + FCSR, + NUM_REGS, + NEXT_PC=NUM_REGS, + TRAP_STATE, + PENDING_TRAP, + MACHINE_STATE, + ICOUNT + }; + + using reg_t = uint32_t; + + using addr_t = uint32_t; + + using code_word_t = uint32_t; //TODO: check removal + + using virt_addr_t = iss::typed_addr_t; + + using phys_addr_t = iss::typed_addr_t; + + constexpr static unsigned reg_bit_width(unsigned r) { + constexpr std::array RV32GC_reg_size{{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}}; + return RV32GC_reg_size[r]; + } + + constexpr static unsigned reg_byte_offset(unsigned r) { + constexpr std::array RV32GC_reg_byte_offset{{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256,260,264,268,272,276,280,288}}; + return RV32GC_reg_byte_offset[r]; + } + + static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); + + enum sreg_flag_e {FLAGS}; + + enum mem_type_e {MEM, CSR, FENCE, RES}; + + constexpr static bool has_fp_regs = true; + +}; + +struct rv32gc: public arch_if { + + using virt_addr_t = typename traits::virt_addr_t; + using phys_addr_t = typename traits::phys_addr_t; + using reg_t = typename traits::reg_t; + using addr_t = typename traits::addr_t; + + rv32gc(); + ~rv32gc(); + + void reset(uint64_t address=0) override; + + uint8_t* get_regs_base_ptr() override; + /// deprecated + void get_reg(short idx, std::vector& value) override {} + void set_reg(short idx, const std::vector& value) override {} + /// deprecated + bool get_flag(int flag) override {return false;} + void set_flag(int, bool value) override {}; + /// deprecated + void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; + + uint64_t get_icount() { return reg.icount;} + + inline phys_addr_t v2p(const iss::addr_t& addr){ + if(addr.space != traits::MEM || + addr.type == iss::address_type::PHYSICAL || + addr_mode[static_cast(addr.access)&0x3]==address_type::PHYSICAL){ + return phys_addr_t(addr.access, addr.space, addr.val&traits::addr_mask); + } else + return virt2phys(addr); + } + + virtual phys_addr_t virt2phys(const iss::addr_t& addr); + + virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } + +protected: + struct RV32GC_regs { + uint32_t X0 = 0; + uint32_t X1 = 0; + uint32_t X2 = 0; + uint32_t X3 = 0; + uint32_t X4 = 0; + uint32_t X5 = 0; + uint32_t X6 = 0; + uint32_t X7 = 0; + uint32_t X8 = 0; + uint32_t X9 = 0; + uint32_t X10 = 0; + uint32_t X11 = 0; + uint32_t X12 = 0; + uint32_t X13 = 0; + uint32_t X14 = 0; + uint32_t X15 = 0; + uint32_t X16 = 0; + uint32_t X17 = 0; + uint32_t X18 = 0; + uint32_t X19 = 0; + uint32_t X20 = 0; + uint32_t X21 = 0; + uint32_t X22 = 0; + uint32_t X23 = 0; + uint32_t X24 = 0; + uint32_t X25 = 0; + uint32_t X26 = 0; + uint32_t X27 = 0; + uint32_t X28 = 0; + uint32_t X29 = 0; + uint32_t X30 = 0; + uint32_t X31 = 0; + uint32_t PC = 0; + uint32_t F0 = 0; + uint32_t F1 = 0; + uint32_t F2 = 0; + uint32_t F3 = 0; + uint32_t F4 = 0; + uint32_t F5 = 0; + uint32_t F6 = 0; + uint32_t F7 = 0; + uint32_t F8 = 0; + uint32_t F9 = 0; + uint32_t F10 = 0; + uint32_t F11 = 0; + uint32_t F12 = 0; + uint32_t F13 = 0; + uint32_t F14 = 0; + uint32_t F15 = 0; + uint32_t F16 = 0; + uint32_t F17 = 0; + uint32_t F18 = 0; + uint32_t F19 = 0; + uint32_t F20 = 0; + uint32_t F21 = 0; + uint32_t F22 = 0; + uint32_t F23 = 0; + uint32_t F24 = 0; + uint32_t F25 = 0; + uint32_t F26 = 0; + uint32_t F27 = 0; + uint32_t F28 = 0; + uint32_t F29 = 0; + uint32_t F30 = 0; + uint32_t F31 = 0; + uint32_t FCSR = 0; + uint32_t NEXT_PC = 0; + uint32_t trap_state = 0, pending_trap = 0, machine_state = 0; + uint64_t icount = 0; + } reg; + + std::array addr_mode; + + + uint32_t get_fcsr(){return reg.FCSR;} + void set_fcsr(uint32_t val){reg.FCSR = val;} + +}; + +} +} +#endif /* _RV32GC_H_ */ diff --git a/riscv/incl/iss/arch/rv32imac.h b/riscv/incl/iss/arch/rv32imac.h index 11e632c..2f8ce5c 100644 --- a/riscv/incl/iss/arch/rv32imac.h +++ b/riscv/incl/iss/arch/rv32imac.h @@ -118,6 +118,8 @@ struct traits { enum mem_type_e {MEM, CSR, FENCE, RES}; + constexpr static bool has_fp_regs = false; + }; struct rv32imac: public arch_if { @@ -198,6 +200,10 @@ protected: } reg; std::array addr_mode; + + + uint32_t get_fcsr(){return 0;} + void set_fcsr(uint32_t val){} }; diff --git a/riscv/incl/iss/arch/rv64ia.h b/riscv/incl/iss/arch/rv64ia.h index cc4ae1e..d97023f 100644 --- a/riscv/incl/iss/arch/rv64ia.h +++ b/riscv/incl/iss/arch/rv64ia.h @@ -118,6 +118,8 @@ struct traits { enum mem_type_e {MEM, CSR, FENCE, RES}; + constexpr static bool has_fp_regs = false; + }; struct rv64ia: public arch_if { @@ -198,6 +200,10 @@ protected: } reg; std::array addr_mode; + + + uint32_t get_fcsr(){return 0;} + void set_fcsr(uint32_t val){} }; diff --git a/riscv/src/internal/fp_functions.cpp b/riscv/src/internal/fp_functions.cpp new file mode 100644 index 0000000..c01492b --- /dev/null +++ b/riscv/src/internal/fp_functions.cpp @@ -0,0 +1,290 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, MINRES Technologies GmbH +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Contributors: +// eyck@minres.com - initial API and implementation +//////////////////////////////////////////////////////////////////////////////// + +#include +#include + +extern "C" { +#include +#include "internals.h" +#include "specialize.h" +} + +namespace iss { +namespace vm { +namespace fp_impl { + +using namespace std; + +#define INT_TYPE(L) Type::getIntNTy(mod->getContext(), L) +#define FLOAT_TYPE Type::getFloatTy(mod->getContext()) +#define DOUBLE_TYPE Type::getDoubleTy(mod->getContext()) +#define VOID_TYPE Type::getVoidTy(mod->getContext()) +#define THIS_PTR_TYPE Type::getIntNPtrTy(mod->getContext(), 8) +#define FDECLL(NAME, RET, ...) \ + Function *NAME##_func = CurrentModule->getFunction(#NAME); \ + if (!NAME##_func) { \ + std::vector NAME##_args{__VA_ARGS__}; \ + FunctionType *NAME##_type = FunctionType::get(RET, NAME##_args, false); \ + NAME##_func = Function::Create(NAME##_type, GlobalValue::ExternalLinkage, #NAME, CurrentModule); \ + NAME##_func->setCallingConv(CallingConv::C); \ + } + +#define FDECL(NAME, RET, ...) \ + std::vector NAME##_args{__VA_ARGS__}; \ + FunctionType *NAME##_type = llvm::FunctionType::get(RET, NAME##_args, false); \ + mod->getOrInsertFunction(#NAME, NAME##_type); + +using namespace llvm; + +void add_fp_functions_2_module(Module *mod) { + FDECL(fget_flags, INT_TYPE(32)); + FDECL(fadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fsub_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fmul_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fdiv_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fsqrt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fcmp_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); + FDECL(fcvt_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fmadd_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(8)); + FDECL(fsel_s, INT_TYPE(32), INT_TYPE(32), INT_TYPE(32), INT_TYPE(32)); + FDECL(fclass_s, INT_TYPE(32), INT_TYPE(32)); +} + +} +} +} + +using this_t = uint8_t *; +const uint8_t rmm_map[] = { + softfloat_round_near_even /*RNE*/, + softfloat_round_minMag/*RTZ*/, + softfloat_round_min/*RDN*/, + softfloat_round_max/*RUP?*/, + softfloat_round_near_maxMag /*RMM*/, + softfloat_round_max/*RTZ*/, + softfloat_round_max/*RTZ*/, + softfloat_round_max/*RTZ*/, +}; + +const uint32_t quiet_nan32=0x7fC00000; + +extern "C" { + +uint32_t fget_flags(){ + return softfloat_exceptionFlags&0x1f; +} + +uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) { + float32_t v1f{v1},v2f{v2}; + softfloat_roundingMode=rmm_map[mode&0x7]; + softfloat_exceptionFlags=0; + float32_t r =f32_add(v1f, v2f); + return r.v; +} + +uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode) { + float32_t v1f{v1},v2f{v2}; + softfloat_roundingMode=rmm_map[mode&0x7]; + softfloat_exceptionFlags=0; + float32_t r=f32_sub(v1f, v2f); + return r.v; +} + +uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode) { + float32_t v1f{v1},v2f{v2}; + softfloat_roundingMode=rmm_map[mode&0x7]; + softfloat_exceptionFlags=0; + float32_t r=f32_mul(v1f, v2f); + return r.v; +} + +uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode) { + float32_t v1f{v1},v2f{v2}; + softfloat_roundingMode=rmm_map[mode&0x7]; + softfloat_exceptionFlags=0; + float32_t r=f32_div(v1f, v2f); + return r.v; +} + +uint32_t fsqrt_s(uint32_t v1, uint8_t mode) { + float32_t v1f{v1}; + softfloat_roundingMode=rmm_map[mode&0x7]; + softfloat_exceptionFlags=0; + float32_t r=f32_sqrt(v1f); + return r.v; +} + +uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) { + float32_t v1f{v1},v2f{v2}; + softfloat_exceptionFlags=0; + bool nan = (v1&defaultNaNF32UI)==quiet_nan32 || (v2&defaultNaNF32UI)==quiet_nan32; + bool snan = softfloat_isSigNaNF32UI(v1) || softfloat_isSigNaNF32UI(v2); + switch(op){ + case 0: + if(nan | snan){ + if(snan) softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f32_eq(v1f,v2f )?1:0; + case 1: + if(nan | snan){ + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f32_le(v1f,v2f )?1:0; + case 2: + if(nan | snan){ + softfloat_raiseFlags(softfloat_flag_invalid); + return 0; + } else + return f32_lt(v1f,v2f )?1:0; + default: + break; + } + return -1; +} + +uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) { + float32_t v1f{v1}; + softfloat_exceptionFlags=0; + float32_t r; + int32_t res; + switch(op){ + case 0: //w->s, fp to int32 + res = f32_to_i32(v1f,rmm_map[mode&0x7],true); + return (uint32_t)res; + case 1: //wu->s + return f32_to_ui32(v1f,rmm_map[mode&0x7],true); + case 2: //s->w + r=i32_to_f32(v1); + return r.v; + case 3: //s->wu + r=ui32_to_f32(v1); + return r.v; + } + return 0; +} + +uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode) { + // op should be {softfloat_mulAdd_subProd(2), softfloat_mulAdd_subC(1)} + softfloat_roundingMode=rmm_map[mode&0x7]; + softfloat_exceptionFlags=0; + float32_t res = softfloat_mulAddF32(v1, v2, v3, op&0x1); + if(op>1) res.v ^= 0x80000000UL; + return res.v; +} + +uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) { + softfloat_exceptionFlags = 0; + bool v1_nan = (v1 & defaultNaNF32UI) == quiet_nan32; + bool v2_nan = (v2 & defaultNaNF32UI) == quiet_nan32; + bool v1_snan = softfloat_isSigNaNF32UI(v1); + bool v2_snan = softfloat_isSigNaNF32UI(v2); + if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid); + if (v1_nan || v1_snan) + return (v2_nan || v2_snan) ? defaultNaNF32UI : v2; + else + if (v2_nan || v2_snan) + return v1; + else { + if ((v1 & 0x7fffffff) == 0 && (v2 & 0x7fffffff) == 0) { + return op == 0 ? ((v1 & 0x80000000) ? v1 : v2) : ((v1 & 0x80000000) ? v2 : v1); + } else { + float32_t v1f{ v1 }, v2f{ v2 }; + return op == 0 ? (f32_lt(v1f, v2f) ? v1 : v2) : (f32_lt(v1f, v2f) ? v2 : v1); + } + } +} + +uint32_t fclass_s( uint32_t v1 ){ + + float32_t a{v1}; + union ui32_f32 uA; + uint_fast32_t uiA; + + uA.f = a; + uiA = uA.ui; + + uint_fast16_t infOrNaN = expF32UI( uiA ) == 0xFF; + uint_fast16_t subnormalOrZero = expF32UI( uiA ) == 0; + bool sign = signF32UI( uiA ); + bool fracZero = fracF32UI( uiA ) == 0; + bool isNaN = isNaNF32UI( uiA ); + bool isSNaN = softfloat_isSigNaNF32UI( uiA ); + + return + ( sign && infOrNaN && fracZero ) << 0 | + ( sign && !infOrNaN && !subnormalOrZero ) << 1 | + ( sign && subnormalOrZero && !fracZero ) << 2 | + ( sign && subnormalOrZero && fracZero ) << 3 | + ( !sign && infOrNaN && fracZero ) << 7 | + ( !sign && !infOrNaN && !subnormalOrZero ) << 6 | + ( !sign && subnormalOrZero && !fracZero ) << 5 | + ( !sign && subnormalOrZero && fracZero ) << 4 | + ( isNaN && isSNaN ) << 8 | + ( isNaN && !isSNaN ) << 9; +} + +uint64_t fclass_d(uint64_t v1 ){ + + float64_t a{v1}; + union ui64_f64 uA; + uint_fast64_t uiA; + + uA.f = a; + uiA = uA.ui; + + uint_fast16_t infOrNaN = expF64UI( uiA ) == 0x7FF; + uint_fast16_t subnormalOrZero = expF64UI( uiA ) == 0; + bool sign = signF64UI( uiA ); + bool fracZero = fracF64UI( uiA ) == 0; + bool isNaN = isNaNF64UI( uiA ); + bool isSNaN = softfloat_isSigNaNF64UI( uiA ); + + return + ( sign && infOrNaN && fracZero ) << 0 | + ( sign && !infOrNaN && !subnormalOrZero ) << 1 | + ( sign && subnormalOrZero && !fracZero ) << 2 | + ( sign && subnormalOrZero && fracZero ) << 3 | + ( !sign && infOrNaN && fracZero ) << 7 | + ( !sign && !infOrNaN && !subnormalOrZero ) << 6 | + ( !sign && subnormalOrZero && !fracZero ) << 5 | + ( !sign && subnormalOrZero && fracZero ) << 4 | + ( isNaN && isSNaN ) << 8 | + ( isNaN && !isSNaN ) << 9; +} + +} + diff --git a/riscv/src/internal/vm_rv32gc.cpp b/riscv/src/internal/vm_rv32gc.cpp new file mode 100644 index 0000000..2f8c0bf --- /dev/null +++ b/riscv/src/internal/vm_rv32gc.cpp @@ -0,0 +1,6524 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, MINRES Technologies GmbH +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Contributors: +// eyck@minres.com - initial API and implementation +// +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace iss { +namespace vm { +namespace fp_impl{ +void add_fp_functions_2_module(llvm::Module *mod); +} +} + +namespace rv32gc { +using namespace iss::arch; +using namespace llvm; +using namespace iss::debugger; + +template class vm_impl : public vm::vm_base { +public: + using super = typename vm::vm_base; + using virt_addr_t = typename super::virt_addr_t; + using phys_addr_t = typename super::phys_addr_t; + using code_word_t = typename super::code_word_t; + using addr_t = typename super::addr_t; + + vm_impl(); + + vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); + + void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; } + + target_adapter_if *accquire_target_adapter(server_if *srv) { + debugger_if::dbg_enabled = true; + if (vm::vm_base::tgt_adapter == nullptr) + vm::vm_base::tgt_adapter = new riscv_target_adapter(srv, this->get_arch()); + return vm::vm_base::tgt_adapter; + } + +protected: + using vm::vm_base::get_reg_ptr; + + template inline llvm::ConstantInt *size(T type) { + return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); + } + + void setup_module(llvm::Module* m) override { + super::setup_module(m); + vm::fp_impl::add_fp_functions_2_module(m); + } + + inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, + unsigned size) const { + return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); + } + + std::tuple gen_single_inst_behavior(virt_addr_t &, unsigned int &, + llvm::BasicBlock *) override; + + void gen_leave_behavior(llvm::BasicBlock *leave_blk) override; + + void gen_raise_trap(uint16_t trap_id, uint16_t cause); + + void gen_leave_trap(unsigned lvl); + + void gen_wait(unsigned type); + + void gen_trap_behavior(llvm::BasicBlock *) override; + + void gen_trap_check(llvm::BasicBlock *bb); + + + inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) { + return this->builder.CreateLoad(get_reg_ptr(i), false); + } + + llvm::Value* gen_fdispatch(std::string fname, const std::vector& args); + + llvm::Value* gen_dispatch(std::string name, llvm::Value*, llvm::Value*, llvm::Value*); + + inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { + llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), + this->get_type(traits::XLEN)); + this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); + } + + // some compile time constants + // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; + enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; + enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; + enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + + using this_class = vm_impl; + using compile_func = std::tuple (this_class::*)(virt_addr_t &pc, + code_word_t instr, + llvm::BasicBlock *bb); + std::array lut; + + std::array lut_00, lut_01, lut_10; + std::array lut_11; + + std::array qlut; + + std::array lutmasks = { { EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32 } }; + + void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[], + compile_func f) { + if (pos < 0) { + lut[idx] = f; + } else { + auto bitmask = 1UL << pos; + if ((mask & bitmask) == 0) { + expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f); + } else { + if ((valid & bitmask) == 0) { + expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f); + expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f); + } else { + auto new_val = idx << 1; + if ((value & bitmask) != 0) new_val++; + expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f); + } + } + } + } + + inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); } + + uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) { + if (pos >= 0) { + auto bitmask = 1UL << pos; + if ((mask & bitmask) == 0) { + lut_val = extract_fields(pos - 1, val, mask, lut_val); + } else { + auto new_val = lut_val << 1; + if ((val & bitmask) != 0) new_val++; + lut_val = extract_fields(pos - 1, val, mask, new_val); + } + } + return lut_val; + } + +private: + /**************************************************************************** + * start opcode definitions + ****************************************************************************/ + struct InstructionDesriptor { + size_t length; + uint32_t value; + uint32_t mask; + compile_func op; + }; + + const std::array instr_descr = {{ + /* entries are: size, valid value, valid mask, function ptr */ + /* instruction LUI */ + {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, + /* instruction AUIPC */ + {32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, &this_class::__auipc}, + /* instruction JAL */ + {32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, &this_class::__jal}, + /* instruction JALR */ + {32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, &this_class::__jalr}, + /* instruction BEQ */ + {32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, &this_class::__beq}, + /* instruction BNE */ + {32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, &this_class::__bne}, + /* instruction BLT */ + {32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, &this_class::__blt}, + /* instruction BGE */ + {32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, &this_class::__bge}, + /* instruction BLTU */ + {32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, &this_class::__bltu}, + /* instruction BGEU */ + {32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, &this_class::__bgeu}, + /* instruction LB */ + {32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, &this_class::__lb}, + /* instruction LH */ + {32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, &this_class::__lh}, + /* instruction LW */ + {32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, &this_class::__lw}, + /* instruction LBU */ + {32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, &this_class::__lbu}, + /* instruction LHU */ + {32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, &this_class::__lhu}, + /* instruction SB */ + {32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, &this_class::__sb}, + /* instruction SH */ + {32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, &this_class::__sh}, + /* instruction SW */ + {32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, &this_class::__sw}, + /* instruction ADDI */ + {32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, &this_class::__addi}, + /* instruction SLTI */ + {32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, &this_class::__slti}, + /* instruction SLTIU */ + {32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, &this_class::__sltiu}, + /* instruction XORI */ + {32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, &this_class::__xori}, + /* instruction ORI */ + {32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, &this_class::__ori}, + /* instruction ANDI */ + {32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, &this_class::__andi}, + /* instruction SLLI */ + {32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, &this_class::__slli}, + /* instruction SRLI */ + {32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srli}, + /* instruction SRAI */ + {32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, &this_class::__srai}, + /* instruction ADD */ + {32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__add}, + /* instruction SUB */ + {32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__sub}, + /* instruction SLL */ + {32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__sll}, + /* instruction SLT */ + {32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__slt}, + /* instruction SLTU */ + {32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__sltu}, + /* instruction XOR */ + {32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__xor}, + /* instruction SRL */ + {32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__srl}, + /* instruction SRA */ + {32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__sra}, + /* instruction OR */ + {32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__or}, + /* instruction AND */ + {32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__and}, + /* instruction FENCE */ + {32, 0b00000000000000000000000000001111, 0b11110000000000000111000001111111, &this_class::__fence}, + /* instruction FENCE_I */ + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, + /* instruction ECALL */ + {32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, &this_class::__ecall}, + /* instruction EBREAK */ + {32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, &this_class::__ebreak}, + /* instruction URET */ + {32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__uret}, + /* instruction SRET */ + {32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__sret}, + /* instruction MRET */ + {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, + /* instruction WFI */ + {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, + /* instruction SFENCE.VMA */ + {32, 0b00010010000000000000000001110011, 0b11111110000000000111111111111111, &this_class::__sfence_vma}, + /* instruction CSRRW */ + {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, + /* instruction CSRRS */ + {32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, &this_class::__csrrs}, + /* instruction CSRRC */ + {32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, &this_class::__csrrc}, + /* instruction CSRRWI */ + {32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, &this_class::__csrrwi}, + /* instruction CSRRSI */ + {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, + /* instruction CSRRCI */ + {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, + /* instruction MUL */ + {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, + /* instruction MULH */ + {32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, &this_class::__mulh}, + /* instruction MULHSU */ + {32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, &this_class::__mulhsu}, + /* instruction MULHU */ + {32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, &this_class::__mulhu}, + /* instruction DIV */ + {32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, &this_class::__div}, + /* instruction DIVU */ + {32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, &this_class::__divu}, + /* instruction REM */ + {32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, &this_class::__rem}, + /* instruction REMU */ + {32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, &this_class::__remu}, + /* instruction LR.W */ + {32, 0b00010000000000000010000000101111, 0b11111001111100000111000001111111, &this_class::__lr_w}, + /* instruction SC.W */ + {32, 0b00011000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__sc_w}, + /* instruction AMOSWAP.W */ + {32, 0b00001000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoswap_w}, + /* instruction AMOADD.W */ + {32, 0b00000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoadd_w}, + /* instruction AMOXOR.W */ + {32, 0b00100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoxor_w}, + /* instruction AMOAND.W */ + {32, 0b01100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoand_w}, + /* instruction AMOOR.W */ + {32, 0b01000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amoor_w}, + /* instruction AMOMIN.W */ + {32, 0b10000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomin_w}, + /* instruction AMOMAX.W */ + {32, 0b10100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomax_w}, + /* instruction AMOMINU.W */ + {32, 0b11000000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amominu_w}, + /* instruction AMOMAXU.W */ + {32, 0b11100000000000000010000000101111, 0b11111000000000000111000001111111, &this_class::__amomaxu_w}, + /* instruction C.ADDI4SPN */ + {16, 0b0000000000000000, 0b1110000000000011, &this_class::__c_addi4spn}, + /* instruction C.LW */ + {16, 0b0100000000000000, 0b1110000000000011, &this_class::__c_lw}, + /* instruction C.SW */ + {16, 0b1100000000000000, 0b1110000000000011, &this_class::__c_sw}, + /* instruction C.ADDI */ + {16, 0b0000000000000001, 0b1110000000000011, &this_class::__c_addi}, + /* instruction C.NOP */ + {16, 0b0000000000000001, 0b1111111111111111, &this_class::__c_nop}, + /* instruction C.JAL */ + {16, 0b0010000000000001, 0b1110000000000011, &this_class::__c_jal}, + /* instruction C.LI */ + {16, 0b0100000000000001, 0b1110000000000011, &this_class::__c_li}, + /* instruction C.LUI */ + {16, 0b0110000000000001, 0b1110000000000011, &this_class::__c_lui}, + /* instruction C.ADDI16SP */ + {16, 0b0110000100000001, 0b1110111110000011, &this_class::__c_addi16sp}, + /* instruction C.SRLI */ + {16, 0b1000000000000001, 0b1111110000000011, &this_class::__c_srli}, + /* instruction C.SRAI */ + {16, 0b1000010000000001, 0b1111110000000011, &this_class::__c_srai}, + /* instruction C.ANDI */ + {16, 0b1000100000000001, 0b1110110000000011, &this_class::__c_andi}, + /* instruction C.SUB */ + {16, 0b1000110000000001, 0b1111110001100011, &this_class::__c_sub}, + /* instruction C.XOR */ + {16, 0b1000110000100001, 0b1111110001100011, &this_class::__c_xor}, + /* instruction C.OR */ + {16, 0b1000110001000001, 0b1111110001100011, &this_class::__c_or}, + /* instruction C.AND */ + {16, 0b1000110001100001, 0b1111110001100011, &this_class::__c_and}, + /* instruction C.J */ + {16, 0b1010000000000001, 0b1110000000000011, &this_class::__c_j}, + /* instruction C.BEQZ */ + {16, 0b1100000000000001, 0b1110000000000011, &this_class::__c_beqz}, + /* instruction C.BNEZ */ + {16, 0b1110000000000001, 0b1110000000000011, &this_class::__c_bnez}, + /* instruction C.SLLI */ + {16, 0b0000000000000010, 0b1111000000000011, &this_class::__c_slli}, + /* instruction C.LWSP */ + {16, 0b0100000000000010, 0b1110000000000011, &this_class::__c_lwsp}, + /* instruction C.MV */ + {16, 0b1000000000000010, 0b1111000000000011, &this_class::__c_mv}, + /* instruction C.JR */ + {16, 0b1000000000000010, 0b1111000001111111, &this_class::__c_jr}, + /* instruction C.ADD */ + {16, 0b1001000000000010, 0b1111000000000011, &this_class::__c_add}, + /* instruction C.JALR */ + {16, 0b1001000000000010, 0b1111000001111111, &this_class::__c_jalr}, + /* instruction C.EBREAK */ + {16, 0b1001000000000010, 0b1111111111111111, &this_class::__c_ebreak}, + /* instruction C.SWSP */ + {16, 0b1100000000000010, 0b1110000000000011, &this_class::__c_swsp}, + /* instruction DII */ + {16, 0b0000000000000000, 0b1111111111111111, &this_class::__dii}, + /* instruction FLW */ + {32, 0b00000000000000000010000000000111, 0b00000000000000000111000001111111, &this_class::__flw}, + /* instruction FSW */ + {32, 0b00000000000000000010000000100111, 0b00000000000000000111000001111111, &this_class::__fsw}, + /* instruction FMADD.S */ + {32, 0b00000000000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_s}, + /* instruction FMSUB.S */ + {32, 0b00000000000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_s}, + /* instruction FNMADD.S */ + {32, 0b00000000000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_s}, + /* instruction FNMSUB.S */ + {32, 0b00000000000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_s}, + /* instruction FADD.S */ + {32, 0b00000000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_s}, + /* instruction FSUB.S */ + {32, 0b00001000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_s}, + /* instruction FMUL.S */ + {32, 0b00010000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_s}, + /* instruction FDIV.S */ + {32, 0b00011000000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_s}, + /* instruction FSQRT.S */ + {32, 0b01011000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_s}, + /* instruction FSGNJ.S */ + {32, 0b00100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_s}, + /* instruction FSGNJN.S */ + {32, 0b00100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_s}, + /* instruction FSGNJX.S */ + {32, 0b00100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_s}, + /* instruction FMIN.S */ + {32, 0b00101000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_s}, + /* instruction FMAX.S */ + {32, 0b00101000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_s}, + /* instruction FCVT.W.S */ + {32, 0b11000000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_s}, + /* instruction FCVT.WU.S */ + {32, 0b11000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_s}, + /* instruction FEQ.S */ + {32, 0b10100000000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_s}, + /* instruction FLT.S */ + {32, 0b10100000000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_s}, + /* instruction FLE.S */ + {32, 0b10100000000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_s}, + /* instruction FCLASS.S */ + {32, 0b11100000000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_s}, + /* instruction FCVT.S.W */ + {32, 0b11010000000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_w}, + /* instruction FCVT.S.WU */ + {32, 0b11010000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_wu}, + /* instruction FMV.X.W */ + {32, 0b11100000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_x_w}, + /* instruction FMV.W.X */ + {32, 0b11110000000000000000000001010011, 0b11111111111100000111000001111111, &this_class::__fmv_w_x}, + /* instruction C.FLW */ + {16, 0b0110000000000000, 0b1110000000000011, &this_class::__c_flw}, + /* instruction C.FSW */ + {16, 0b1110000000000000, 0b1110000000000011, &this_class::__c_fsw}, + /* instruction C.FLWSP */ + {16, 0b0110000000000010, 0b1110000000000011, &this_class::__c_flwsp}, + /* instruction C.FSWSP */ + {16, 0b1110000000000010, 0b1110000000000011, &this_class::__c_fswsp}, + }}; + + /* instruction definitions */ + /* instruction 0: LUI */ + std::tuple __lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("LUI"); + + this->gen_sync(iss::PRE_SYNC, 0); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + int32_t fld_imm_val = 0 | (signed_bit_sub<12,20>(instr) << 12); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("LUI x%1$d, 0x%2$05x"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_const(32U, fld_imm_val); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 0); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 1: AUIPC */ + std::tuple __auipc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AUIPC"); + + this->gen_sync(iss::PRE_SYNC, 1); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + int32_t fld_imm_val = 0 | (signed_bit_sub<12,20>(instr) << 12); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AUIPC x%1%, 0x%2$08x"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 1); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 2: JAL */ + std::tuple __jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("JAL"); + + this->gen_sync(iss::PRE_SYNC, 2); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + int32_t fld_imm_val = 0 | (bit_sub<12,8>(instr) << 12) | (bit_sub<20,1>(instr) << 11) | (bit_sub<21,10>(instr) << 1) | (signed_bit_sub<31,1>(instr) << 20); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("JAL x%1$d, 0x%2$x"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 4)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* PC_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 2); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 3: JALR */ + std::tuple __jalr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("JALR"); + + this->gen_sync(iss::PRE_SYNC, 3); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("JALR x%1$d, x%2$d, 0x%3$x"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 4)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* ret_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + Value* PC_val = this->builder.CreateAnd( + ret_val, + this->builder.CreateNot(this->gen_const(32U, 1))); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 3); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 4: BEQ */ + std::tuple __beq(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("BEQ"); + + this->gen_sync(iss::PRE_SYNC, 4); + + int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("BEQ x%1$d, x%2$d, 0x%3$x"); + ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 4)), + 32); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 4); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 5: BNE */ + std::tuple __bne(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("BNE"); + + this->gen_sync(iss::PRE_SYNC, 5); + + int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("BNE x%1$d, x%2$d, 0x%3$x"); + ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 4)), + 32); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 5); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 6: BLT */ + std::tuple __blt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("BLT"); + + this->gen_sync(iss::PRE_SYNC, 6); + + int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("BLT x%1$d, x%2$d, 0x%3$x"); + ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 32, true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + 32, true)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 4)), + 32); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 6); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 7: BGE */ + std::tuple __bge(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("BGE"); + + this->gen_sync(iss::PRE_SYNC, 7); + + int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("BGE x%1$d, x%2$d, 0x%3$x"); + ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SGE, + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 32, true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + 32, true)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 4)), + 32); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 7); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 8: BLTU */ + std::tuple __bltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("BLTU"); + + this->gen_sync(iss::PRE_SYNC, 8); + + int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("BLTU x%1$d, x%2$d, 0x%3$x"); + ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 4)), + 32); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 8); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 9: BGEU */ + std::tuple __bgeu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("BGEU"); + + this->gen_sync(iss::PRE_SYNC, 9); + + int16_t fld_imm_val = 0 | (bit_sub<7,1>(instr) << 11) | (bit_sub<8,4>(instr) << 1) | (bit_sub<25,6>(instr) << 5) | (signed_bit_sub<31,1>(instr) << 12); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("BGEU x%1$d, x%2$d, 0x%3$x"); + ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_UGE, + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 4)), + 32); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 9); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 10: LB */ + std::tuple __lb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("LB"); + + this->gen_sync(iss::PRE_SYNC, 10); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("LB x%1$d, %2%(x%3$d)"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 8/8), + 32, + true); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 10); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 11: LH */ + std::tuple __lh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("LH"); + + this->gen_sync(iss::PRE_SYNC, 11); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("LH x%1$d, %2%(x%3$d)"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 16/8), + 32, + true); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 11); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 12: LW */ + std::tuple __lw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("LW"); + + this->gen_sync(iss::PRE_SYNC, 12); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("LW x%1$d, %2%(x%3$d)"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + true); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 12); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 13: LBU */ + std::tuple __lbu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("LBU"); + + this->gen_sync(iss::PRE_SYNC, 13); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("LBU x%1$d, %2%(x%3$d)"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 8/8), + 32, + false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 13); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 14: LHU */ + std::tuple __lhu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("LHU"); + + this->gen_sync(iss::PRE_SYNC, 14); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("LHU x%1$d, %2%(x%3$d)"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 16/8), + 32, + false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 14); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 15: SB */ + std::tuple __sb(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SB"); + + this->gen_sync(iss::PRE_SYNC, 15); + + int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SB x%1$d, %2%(x%3$d)"); + ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(8))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 15); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 16: SH */ + std::tuple __sh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SH"); + + this->gen_sync(iss::PRE_SYNC, 16); + + int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SH x%1$d, %2%(x%3$d)"); + ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(16))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 16); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 17: SW */ + std::tuple __sw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SW"); + + this->gen_sync(iss::PRE_SYNC, 17); + + int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SW x%1$d, %2%(x%3$d)"); + ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 17); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 18: ADDI */ + std::tuple __addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("ADDI"); + + this->gen_sync(iss::PRE_SYNC, 18); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("ADDI x%1$d, x%2$d, %3%"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 18); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 19: SLTI */ + std::tuple __slti(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SLTI"); + + this->gen_sync(iss::PRE_SYNC, 19); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SLTI x%1$d, x%2$d, %3%"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 32, true), + this->gen_const(32U, fld_imm_val)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 19); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 20: SLTIU */ + std::tuple __sltiu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SLTIU"); + + this->gen_sync(iss::PRE_SYNC, 20); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SLTIU x%1$d, x%2$d, %3%"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + int32_t full_imm_val = fld_imm_val; + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, full_imm_val)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 20); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 21: XORI */ + std::tuple __xori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("XORI"); + + this->gen_sync(iss::PRE_SYNC, 21); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("XORI x%1$d, x%2$d, %3%"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateXor( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 21); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 22: ORI */ + std::tuple __ori(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("ORI"); + + this->gen_sync(iss::PRE_SYNC, 22); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("ORI x%1$d, x%2$d, %3%"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateOr( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 22); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 23: ANDI */ + std::tuple __andi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("ANDI"); + + this->gen_sync(iss::PRE_SYNC, 23); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("ANDI x%1$d, x%2$d, %3%"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateAnd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 23); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 24: SLLI */ + std::tuple __slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SLLI"); + + this->gen_sync(iss::PRE_SYNC, 24); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SLLI x%1$d, x%2$d, %3%"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_shamt_val > 31){ + this->gen_raise_trap(0, 0); + } else { + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateShl( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_shamt_val)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 24); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 25: SRLI */ + std::tuple __srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SRLI"); + + this->gen_sync(iss::PRE_SYNC, 25); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SRLI x%1$d, x%2$d, %3%"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_shamt_val > 31){ + this->gen_raise_trap(0, 0); + } else { + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateLShr( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_shamt_val)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 25); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 26: SRAI */ + std::tuple __srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SRAI"); + + this->gen_sync(iss::PRE_SYNC, 26); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_shamt_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SRAI x%1$d, x%2$d, %3%"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_shamt_val > 31){ + this->gen_raise_trap(0, 0); + } else { + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateAShr( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_shamt_val)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 26); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 27: ADD */ + std::tuple __add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("ADD"); + + this->gen_sync(iss::PRE_SYNC, 27); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("ADD x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 27); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 28: SUB */ + std::tuple __sub(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SUB"); + + this->gen_sync(iss::PRE_SYNC, 28); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SUB x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateSub( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 28); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 29: SLL */ + std::tuple __sll(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SLL"); + + this->gen_sync(iss::PRE_SYNC, 29); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SLL x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateShl( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(32U, 31))); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 29); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 30: SLT */ + std::tuple __slt(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SLT"); + + this->gen_sync(iss::PRE_SYNC, 30); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SLT x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 32, true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + 32, true)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 30); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 31: SLTU */ + std::tuple __sltu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SLTU"); + + this->gen_sync(iss::PRE_SYNC, 31); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SLTU x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 32, + false), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + 32, + false)), + this->gen_const(32U, 1), + this->gen_const(32U, 0), + 32); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 31); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 32: XOR */ + std::tuple __xor(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("XOR"); + + this->gen_sync(iss::PRE_SYNC, 32); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("XOR x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateXor( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 32); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 33: SRL */ + std::tuple __srl(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SRL"); + + this->gen_sync(iss::PRE_SYNC, 33); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SRL x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateLShr( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(32U, 31))); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 33); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 34: SRA */ + std::tuple __sra(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SRA"); + + this->gen_sync(iss::PRE_SYNC, 34); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SRA x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateAShr( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->builder.CreateAnd( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(32U, 31))); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 34); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 35: OR */ + std::tuple __or(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("OR"); + + this->gen_sync(iss::PRE_SYNC, 35); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("OR x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateOr( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 35); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 36: AND */ + std::tuple __and(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AND"); + + this->gen_sync(iss::PRE_SYNC, 36); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AND x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->builder.CreateAnd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 36); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 37: FENCE */ + std::tuple __fence(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FENCE"); + + this->gen_sync(iss::PRE_SYNC, 37); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_succ_val = 0 | (bit_sub<20,4>(instr)); + uint8_t fld_pred_val = 0 | (bit_sub<24,4>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("FENCE"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* FENCE_fence_val = this->builder.CreateOr( + this->builder.CreateShl( + this->gen_const(32U, fld_pred_val), + this->gen_const(32U, 4)), + this->gen_const(32U, fld_succ_val)); + this->gen_write_mem( + traits::FENCE, + (uint64_t)0, + this->builder.CreateZExtOrTrunc(FENCE_fence_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 37); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 38: FENCE_I */ + std::tuple __fence_i(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FENCE_I"); + + this->gen_sync(iss::PRE_SYNC, 38); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint16_t fld_imm_val = 0 | (bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("FENCE_I"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* FENCE_fencei_val = this->gen_const(32U, fld_imm_val); + this->gen_write_mem( + traits::FENCE, + (uint64_t)1, + this->builder.CreateZExtOrTrunc(FENCE_fencei_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 38); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::FLUSH, nullptr); + } + + /* instruction 39: ECALL */ + std::tuple __ecall(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("ECALL"); + + this->gen_sync(iss::PRE_SYNC, 39); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("ECALL"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + this->gen_raise_trap(0, 11); + this->gen_sync(iss::POST_SYNC, 39); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 40: EBREAK */ + std::tuple __ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("EBREAK"); + + this->gen_sync(iss::PRE_SYNC, 40); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("EBREAK"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + this->gen_raise_trap(0, 3); + this->gen_sync(iss::POST_SYNC, 40); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 41: URET */ + std::tuple __uret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("URET"); + + this->gen_sync(iss::PRE_SYNC, 41); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("URET"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + this->gen_leave_trap(0); + this->gen_sync(iss::POST_SYNC, 41); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 42: SRET */ + std::tuple __sret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SRET"); + + this->gen_sync(iss::PRE_SYNC, 42); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("SRET"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + this->gen_leave_trap(1); + this->gen_sync(iss::POST_SYNC, 42); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 43: MRET */ + std::tuple __mret(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("MRET"); + + this->gen_sync(iss::PRE_SYNC, 43); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("MRET"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + this->gen_leave_trap(3); + this->gen_sync(iss::POST_SYNC, 43); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 44: WFI */ + std::tuple __wfi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("WFI"); + + this->gen_sync(iss::PRE_SYNC, 44); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("WFI"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + this->gen_wait(1); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 44); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 45: SFENCE.VMA */ + std::tuple __sfence_vma(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SFENCE.VMA"); + + this->gen_sync(iss::PRE_SYNC, 45); + + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("SFENCE.VMA"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* FENCE_fencevmal_val = this->gen_const(32U, fld_rs1_val); + this->gen_write_mem( + traits::FENCE, + (uint64_t)2, + this->builder.CreateZExtOrTrunc(FENCE_fencevmal_val,this->get_type(32))); + Value* FENCE_fencevmau_val = this->gen_const(32U, fld_rs2_val); + this->gen_write_mem( + traits::FENCE, + (uint64_t)3, + this->builder.CreateZExtOrTrunc(FENCE_fencevmau_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 45); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 46: CSRRW */ + std::tuple __csrrw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("CSRRW"); + + this->gen_sync(iss::PRE_SYNC, 46); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("CSRRW x%1$d, %2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* rs_val_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + if(fld_rd_val != 0){ + Value* csr_val_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); + Value* CSR_csr_val = rs_val_val; + this->gen_write_mem( + traits::CSR, + fld_csr_val, + this->builder.CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + Value* X_rd_val = csr_val_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } else { + Value* CSR_csr_val = rs_val_val; + this->gen_write_mem( + traits::CSR, + fld_csr_val, + this->builder.CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 46); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 47: CSRRS */ + std::tuple __csrrs(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("CSRRS"); + + this->gen_sync(iss::PRE_SYNC, 47); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("CSRRS x%1$d, %2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); + Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + if(fld_rd_val != 0){ + Value* X_rd_val = xrd_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + if(fld_rs1_val != 0){ + Value* CSR_csr_val = this->builder.CreateOr( + xrd_val, + xrs1_val); + this->gen_write_mem( + traits::CSR, + fld_csr_val, + this->builder.CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 47); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 48: CSRRC */ + std::tuple __csrrc(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("CSRRC"); + + this->gen_sync(iss::PRE_SYNC, 48); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("CSRRC x%1$d, %2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); + Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + if(fld_rd_val != 0){ + Value* X_rd_val = xrd_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + if(fld_rs1_val != 0){ + Value* CSR_csr_val = this->builder.CreateAnd( + xrd_val, + this->builder.CreateNot(xrs1_val)); + this->gen_write_mem( + traits::CSR, + fld_csr_val, + this->builder.CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 48); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 49: CSRRWI */ + std::tuple __csrrwi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("CSRRWI"); + + this->gen_sync(iss::PRE_SYNC, 49); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_zimm_val = 0 | (bit_sub<15,5>(instr)); + uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("CSRRWI x%1$d, %2$d, 0x%3$x"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* CSR_csr_val = this->gen_ext( + this->gen_const(32U, fld_zimm_val), + 32, + false); + this->gen_write_mem( + traits::CSR, + fld_csr_val, + this->builder.CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 49); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 50: CSRRSI */ + std::tuple __csrrsi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("CSRRSI"); + + this->gen_sync(iss::PRE_SYNC, 50); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_zimm_val = 0 | (bit_sub<15,5>(instr)); + uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("CSRRSI x%1$d, %2$d, 0x%3$x"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); + if(fld_zimm_val != 0){ + Value* CSR_csr_val = this->builder.CreateOr( + res_val, + this->gen_ext( + this->gen_const(32U, fld_zimm_val), + 32, + false)); + this->gen_write_mem( + traits::CSR, + fld_csr_val, + this->builder.CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + } + if(fld_rd_val != 0){ + Value* X_rd_val = res_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 50); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 51: CSRRCI */ + std::tuple __csrrci(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("CSRRCI"); + + this->gen_sync(iss::PRE_SYNC, 51); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_zimm_val = 0 | (bit_sub<15,5>(instr)); + uint16_t fld_csr_val = 0 | (bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("CSRRCI x%1$d, %2$d, 0x%3$x"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_csr_val % (uint64_t)fld_zimm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); + if(fld_rd_val != 0){ + Value* X_rd_val = res_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + if(fld_zimm_val != 0){ + Value* CSR_csr_val = this->builder.CreateAnd( + res_val, + this->builder.CreateNot(this->gen_ext( + this->gen_const(32U, fld_zimm_val), + 32, + false))); + this->gen_write_mem( + traits::CSR, + fld_csr_val, + this->builder.CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 51); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 52: MUL */ + std::tuple __mul(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("MUL"); + + this->gen_sync(iss::PRE_SYNC, 52); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("MUL x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* res_val = this->builder.CreateMul( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 64, + false), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + 64, + false)); + Value* X_rd_val = this->gen_ext( + res_val, + 32, + false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 52); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 53: MULH */ + std::tuple __mulh(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("MULH"); + + this->gen_sync(iss::PRE_SYNC, 53); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("MULH x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* res_val = this->builder.CreateMul( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 64, + true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + 64, + true)); + Value* X_rd_val = this->gen_ext( + this->builder.CreateLShr( + res_val, + this->gen_const(32U, 32)), + 32, + false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 53); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 54: MULHSU */ + std::tuple __mulhsu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("MULHSU"); + + this->gen_sync(iss::PRE_SYNC, 54); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("MULHSU x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* res_val = this->builder.CreateMul( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 64, + true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + 64, + false)); + Value* X_rd_val = this->gen_ext( + this->builder.CreateLShr( + res_val, + this->gen_const(32U, 32)), + 32, + false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 54); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 55: MULHU */ + std::tuple __mulhu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("MULHU"); + + this->gen_sync(iss::PRE_SYNC, 55); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("MULHU x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* res_val = this->builder.CreateMul( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + 64, + false), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + 64, + false)); + Value* X_rd_val = this->gen_ext( + this->builder.CreateLShr( + res_val, + this->gen_const(32U, 32)), + 32, + false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 55); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 56: DIV */ + std::tuple __div(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("DIV"); + + this->gen_sync(iss::PRE_SYNC, 56); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("DIV x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(32U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + uint32_t M1_val = (-1); + uint32_t MMIN_val = (-1) << (32 - 1); + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 1), + 32, true), + this->gen_ext( + this->gen_const(32U, MMIN_val), + 32, true)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 2), + 32, true), + this->gen_ext( + this->gen_const(32U, M1_val), + 32, true)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* X_rd_val = this->gen_const(32U, MMIN_val); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->builder.CreateSDiv( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 3), + 32, true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 3), + 32, true)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->builder.CreateSDiv( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 2), + 32, true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 2), + 32, true)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->builder.CreateNeg(this->gen_const(32U, 1)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 56); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 57: DIVU */ + std::tuple __divu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("DIVU"); + + this->gen_sync(iss::PRE_SYNC, 57); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("DIVU x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(32U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* X_rd_val = this->builder.CreateUDiv( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 1), + 32, + false), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 1), + 32, + false)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->builder.CreateNeg(this->gen_const(32U, 1)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 57); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 58: REM */ + std::tuple __rem(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("REM"); + + this->gen_sync(iss::PRE_SYNC, 58); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("REM x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(32U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + uint32_t M1_val = (-1); + uint32_t MMIN_val = (-1) << (32 - 1); + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 1), + 32, true), + this->gen_ext( + this->gen_const(32U, MMIN_val), + 32, true)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 2), + 32, true), + this->gen_ext( + this->gen_const(32U, M1_val), + 32, true)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* X_rd_val = this->gen_const(32U, 0); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->builder.CreateSRem( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 3), + 32, + true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 3), + 32, + true)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->builder.CreateSRem( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 2), + 32, + true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 2), + 32, + true)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->gen_reg_load(fld_rs1_val + traits::X0, 1); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 58); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 59: REMU */ + std::tuple __remu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("REMU"); + + this->gen_sync(iss::PRE_SYNC, 59); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("REMU x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(32U, 0)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* X_rd_val = this->builder.CreateURem( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 1), + 32, + false), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 1), + 32, + false)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->gen_reg_load(fld_rs1_val + traits::X0, 1); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 59); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 60: LR.W */ + std::tuple __lr_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("LR.W"); + + this->gen_sync(iss::PRE_SYNC, 60); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("LR.W x%1$d, x%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(fld_rd_val != 0){ + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + Value* X_rd_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + true); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + Value* RES_offs_val = this->gen_ext( + this->builder.CreateNeg(this->gen_const(8U, 1)), + 32, + true); + this->gen_write_mem( + traits::RES, + offs_val, + this->builder.CreateZExtOrTrunc(RES_offs_val,this->get_type(32))); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 60); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 61: SC.W */ + std::tuple __sc_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("SC.W"); + + this->gen_sync(iss::PRE_SYNC, 61); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("SC.W x%1$d, x%2$d, x%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + Value* res1_val = this->gen_read_mem(traits::RES, offs_val, 32/8); + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_NE, + res1_val, + this->gen_const(32U, 0)), + bb_then, + bbnext); + this->builder.SetInsertPoint(bb_then); + { + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 1); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_NE, + res1_val, + this->gen_const(32U, 0)), + this->gen_const(32U, 0), + this->gen_const(32U, 1), + 32); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 61); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 62: AMOSWAP.W */ + std::tuple __amoswap_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AMOSWAP.W"); + + this->gen_sync(iss::PRE_SYNC, 62); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AMOSWAP.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + if(fld_rd_val != 0){ + Value* X_rd_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + true); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 62); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 63: AMOADD.W */ + std::tuple __amoadd_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AMOADD.W"); + + this->gen_sync(iss::PRE_SYNC, 63); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AMOADD.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + Value* res1_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + true); + if(fld_rd_val != 0){ + Value* X_rd_val = res1_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* res2_val = this->builder.CreateAdd( + res1_val, + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + Value* MEM_offs_val = res2_val; + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 63); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 64: AMOXOR.W */ + std::tuple __amoxor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AMOXOR.W"); + + this->gen_sync(iss::PRE_SYNC, 64); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AMOXOR.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + Value* res1_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + true); + if(fld_rd_val != 0){ + Value* X_rd_val = res1_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* res2_val = this->builder.CreateXor( + res1_val, + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + Value* MEM_offs_val = res2_val; + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 64); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 65: AMOAND.W */ + std::tuple __amoand_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AMOAND.W"); + + this->gen_sync(iss::PRE_SYNC, 65); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AMOAND.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + Value* res1_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + true); + if(fld_rd_val != 0){ + Value* X_rd_val = res1_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* res2_val = this->builder.CreateAnd( + res1_val, + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + Value* MEM_offs_val = res2_val; + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 65); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 66: AMOOR.W */ + std::tuple __amoor_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AMOOR.W"); + + this->gen_sync(iss::PRE_SYNC, 66); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AMOOR.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + Value* res1_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + true); + if(fld_rd_val != 0){ + Value* X_rd_val = res1_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* res2_val = this->builder.CreateOr( + res1_val, + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + Value* MEM_offs_val = res2_val; + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 66); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 67: AMOMIN.W */ + std::tuple __amomin_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AMOMIN.W"); + + this->gen_sync(iss::PRE_SYNC, 67); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AMOMIN.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + Value* res1_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + true); + if(fld_rd_val != 0){ + Value* X_rd_val = res1_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* res2_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SGT, + this->gen_ext( + res1_val, + 32, true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + 32, true)), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + res1_val, + 32); + Value* MEM_offs_val = res2_val; + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 67); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 68: AMOMAX.W */ + std::tuple __amomax_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AMOMAX.W"); + + this->gen_sync(iss::PRE_SYNC, 68); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AMOMAX.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + Value* res1_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + true); + if(fld_rd_val != 0){ + Value* X_rd_val = res1_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* res2_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_SLT, + this->gen_ext( + res1_val, + 32, true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + 32, true)), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + res1_val, + 32); + Value* MEM_offs_val = res2_val; + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 68); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 69: AMOMINU.W */ + std::tuple __amominu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AMOMINU.W"); + + this->gen_sync(iss::PRE_SYNC, 69); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AMOMINU.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + Value* res1_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + false); + if(fld_rd_val != 0){ + Value* X_rd_val = res1_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* res2_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_UGT, + res1_val, + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + res1_val, + 32); + Value* MEM_offs_val = res2_val; + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 69); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 70: AMOMAXU.W */ + std::tuple __amomaxu_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("AMOMAXU.W"); + + this->gen_sync(iss::PRE_SYNC, 70); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rl_val = 0 | (bit_sub<25,1>(instr)); + uint8_t fld_aq_val = 0 | (bit_sub<26,1>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("AMOMAXU.W x%1$d, x%2$d, x%3$d (aqu=%4$d,rel=%5$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_aq_val % (uint64_t)fld_rl_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + Value* res1_val = this->gen_ext( + this->gen_read_mem(traits::MEM, offs_val, 32/8), + 32, + false); + if(fld_rd_val != 0){ + Value* X_rd_val = res1_val; + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + Value* res2_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + res1_val, + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + res1_val, + 32); + Value* MEM_offs_val = res2_val; + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 70); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 71: C.ADDI4SPN */ + std::tuple __c_addi4spn(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.ADDI4SPN"); + + this->gen_sync(iss::PRE_SYNC, 71); + + uint8_t fld_rd_val = 0 | (bit_sub<2,3>(instr)); + uint16_t fld_imm_val = 0 | (bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.ADDI4SPN x%1$d, 0x%2$05x"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + if(fld_imm_val == 0){ + this->gen_raise_trap(0, 2); + } + uint8_t rd_idx_val = (fld_rd_val + 8); + uint8_t x2_idx_val = 2; + Value* X_rd_idx_val = this->builder.CreateAdd( + this->gen_reg_load(x2_idx_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 71); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 72: C.LW */ + std::tuple __c_lw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.LW"); + + this->gen_sync(iss::PRE_SYNC, 72); + + uint8_t fld_rd_val = 0 | (bit_sub<2,3>(instr)); + uint8_t fld_uimm_val = 0 | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.LW x(8+%1$d), x(8+%2$d), 0x%3$05x"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_uimm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + uint8_t rd_idx_val = (fld_rd_val + 8); + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* X_rd_idx_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 72); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 73: C.SW */ + std::tuple __c_sw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.SW"); + + this->gen_sync(iss::PRE_SYNC, 73); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); + uint8_t fld_uimm_val = 0 | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.SW x(8+%1$d), x(8+%2$d), 0x%3$05x"); + ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + uint8_t rs2_idx_val = (fld_rs2_val + 8); + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* MEM_offs_val = this->gen_reg_load(rs2_idx_val + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 73); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 74: C.ADDI */ + std::tuple __c_addi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.ADDI"); + + this->gen_sync(iss::PRE_SYNC, 74); + + int8_t fld_imm_val = 0 | (bit_sub<2,5>(instr)) | (signed_bit_sub<12,1>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.ADDI x%1$d, 0x%2$05x"); + ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + Value* X_rs1_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 74); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 75: C.NOP */ + std::tuple __c_nop(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.NOP"); + + this->gen_sync(iss::PRE_SYNC, 75); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("C.NOP"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + /* TODO: describe operations for C.NOP ! */ + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 75); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 76: C.JAL */ + std::tuple __c_jal(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.JAL"); + + this->gen_sync(iss::PRE_SYNC, 76); + + int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (signed_bit_sub<12,1>(instr) << 11); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.JAL 0x%1$05x"); + ins_fmter % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rd_val = 1; + Value* X_rd_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 2)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(rd_val + traits::X0), false); + Value* PC_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 76); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 77: C.LI */ + std::tuple __c_li(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.LI"); + + this->gen_sync(iss::PRE_SYNC, 77); + + int8_t fld_imm_val = 0 | (bit_sub<2,5>(instr)) | (signed_bit_sub<12,1>(instr) << 5); + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.LI x%1$d, 0x%2$05x"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + if(fld_rd_val == 0){ + this->gen_raise_trap(0, 2); + } + Value* X_rd_val = this->gen_const(32U, fld_imm_val); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 77); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 78: C.LUI */ + std::tuple __c_lui(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.LUI"); + + this->gen_sync(iss::PRE_SYNC, 78); + + int32_t fld_imm_val = 0 | (bit_sub<2,5>(instr) << 12) | (signed_bit_sub<12,1>(instr) << 17); + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.LUI x%1$d, 0x%2$05x"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + if(fld_rd_val == 0){ + this->gen_raise_trap(0, 2); + } + if(fld_imm_val == 0){ + this->gen_raise_trap(0, 2); + } + Value* X_rd_val = this->gen_const(32U, fld_imm_val); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 78); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 79: C.ADDI16SP */ + std::tuple __c_addi16sp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.ADDI16SP"); + + this->gen_sync(iss::PRE_SYNC, 79); + + int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (signed_bit_sub<12,1>(instr) << 9); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.ADDI16SP 0x%1$05x"); + ins_fmter % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t x2_idx_val = 2; + Value* X_x2_idx_val = this->builder.CreateAdd( + this->gen_ext( + this->gen_reg_load(x2_idx_val + traits::X0, 0), + 32, true), + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(X_x2_idx_val, get_reg_ptr(x2_idx_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 79); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 80: C.SRLI */ + std::tuple __c_srli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.SRLI"); + + this->gen_sync(iss::PRE_SYNC, 80); + + uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.SRLI x(8+%1$d), %2$d"); + ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + Value* X_rs1_idx_val = this->builder.CreateLShr( + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, fld_shamt_val)); + this->builder.CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 80); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 81: C.SRAI */ + std::tuple __c_srai(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.SRAI"); + + this->gen_sync(iss::PRE_SYNC, 81); + + uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.SRAI x(8+%1$d), %2$d"); + ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + Value* X_rs1_idx_val = this->builder.CreateAShr( + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, fld_shamt_val)); + this->builder.CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 81); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 82: C.ANDI */ + std::tuple __c_andi(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.ANDI"); + + this->gen_sync(iss::PRE_SYNC, 82); + + int8_t fld_imm_val = 0 | (bit_sub<2,5>(instr)) | (signed_bit_sub<12,1>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.ANDI x(8+%1$d), 0x%2$05x"); + ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + Value* X_rs1_idx_val = this->builder.CreateAnd( + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 82); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 83: C.SUB */ + std::tuple __c_sub(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.SUB"); + + this->gen_sync(iss::PRE_SYNC, 83); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); + uint8_t fld_rd_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.SUB x(8+%1$d), x(8+%2$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rd_idx_val = (fld_rd_val + 8); + uint8_t rs2_idx_val = (fld_rs2_val + 8); + Value* X_rd_idx_val = this->builder.CreateSub( + this->gen_reg_load(rd_idx_val + traits::X0, 0), + this->gen_reg_load(rs2_idx_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 83); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 84: C.XOR */ + std::tuple __c_xor(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.XOR"); + + this->gen_sync(iss::PRE_SYNC, 84); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); + uint8_t fld_rd_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.XOR x(8+%1$d), x(8+%2$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rd_idx_val = (fld_rd_val + 8); + uint8_t rs2_idx_val = (fld_rs2_val + 8); + Value* X_rd_idx_val = this->builder.CreateXor( + this->gen_reg_load(rd_idx_val + traits::X0, 0), + this->gen_reg_load(rs2_idx_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 84); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 85: C.OR */ + std::tuple __c_or(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.OR"); + + this->gen_sync(iss::PRE_SYNC, 85); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); + uint8_t fld_rd_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.OR x(8+%1$d), x(8+%2$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rd_idx_val = (fld_rd_val + 8); + uint8_t rs2_idx_val = (fld_rs2_val + 8); + Value* X_rd_idx_val = this->builder.CreateOr( + this->gen_reg_load(rd_idx_val + traits::X0, 0), + this->gen_reg_load(rs2_idx_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 85); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 86: C.AND */ + std::tuple __c_and(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.AND"); + + this->gen_sync(iss::PRE_SYNC, 86); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); + uint8_t fld_rd_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.AND x(8+%1$d), x(8+%2$d)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rd_idx_val = (fld_rd_val + 8); + uint8_t rs2_idx_val = (fld_rs2_val + 8); + Value* X_rd_idx_val = this->builder.CreateAnd( + this->gen_reg_load(rd_idx_val + traits::X0, 0), + this->gen_reg_load(rs2_idx_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 86); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 87: C.J */ + std::tuple __c_j(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.J"); + + this->gen_sync(iss::PRE_SYNC, 87); + + int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (signed_bit_sub<12,1>(instr) << 11); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.J 0x%1$05x"); + ins_fmter % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + Value* PC_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 87); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 88: C.BEQZ */ + std::tuple __c_beqz(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.BEQZ"); + + this->gen_sync(iss::PRE_SYNC, 88); + + int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (signed_bit_sub<12,1>(instr) << 8); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.BEQZ x(8+%1$d), 0x%2$05x"); + ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, 0)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 2)), + 32); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 88); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 89: C.BNEZ */ + std::tuple __c_bnez(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.BNEZ"); + + this->gen_sync(iss::PRE_SYNC, 89); + + int16_t fld_imm_val = 0 | (bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (signed_bit_sub<12,1>(instr) << 8); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.BNEZ x(8+%1$d), 0x%2$05x"); + ins_fmter % (uint64_t)fld_rs1_val % (int64_t)fld_imm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + Value* PC_val = this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_NE, + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, 0)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, fld_imm_val)), + this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 2)), + 32); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 89); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 90: C.SLLI */ + std::tuple __c_slli(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.SLLI"); + + this->gen_sync(iss::PRE_SYNC, 90); + + uint8_t fld_shamt_val = 0 | (bit_sub<2,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.SLLI x%1$d, %2$d"); + ins_fmter % (uint64_t)fld_rs1_val % (uint64_t)fld_shamt_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + if(fld_rs1_val == 0){ + this->gen_raise_trap(0, 2); + } + Value* X_rs1_val = this->builder.CreateShl( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_shamt_val)); + this->builder.CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 90); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 91: C.LWSP */ + std::tuple __c_lwsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.LWSP"); + + this->gen_sync(iss::PRE_SYNC, 91); + + uint8_t fld_uimm_val = 0 | (bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5); + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.LWSP x%1$d, sp, 0x%2$05x"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t x2_idx_val = 2; + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(x2_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* X_rd_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 91); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 92: C.MV */ + std::tuple __c_mv(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.MV"); + + this->gen_sync(iss::PRE_SYNC, 92); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,5>(instr)); + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.MV x%1$d, x%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + Value* X_rd_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 92); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 93: C.JR */ + std::tuple __c_jr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.JR"); + + this->gen_sync(iss::PRE_SYNC, 93); + + uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.JR x%1$d"); + ins_fmter % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + Value* PC_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 93); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 94: C.ADD */ + std::tuple __c_add(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.ADD"); + + this->gen_sync(iss::PRE_SYNC, 94); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,5>(instr)); + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.ADD x%1$d, x%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + Value* X_rd_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rd_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 94); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 95: C.JALR */ + std::tuple __c_jalr(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.JALR"); + + this->gen_sync(iss::PRE_SYNC, 95); + + uint8_t fld_rs1_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.JALR x%1$d"); + ins_fmter % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t r_idx_val = 1; + Value* X_r_idx_val = this->builder.CreateAdd( + cur_pc_val, + this->gen_const(32U, 2)); + this->builder.CreateStore(X_r_idx_val, get_reg_ptr(r_idx_val + traits::X0), false); + Value* PC_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); + this->gen_sync(iss::POST_SYNC, 95); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 96: C.EBREAK */ + std::tuple __c_ebreak(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.EBREAK"); + + this->gen_sync(iss::PRE_SYNC, 96); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("C.EBREAK"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + this->gen_raise_trap(0, 3); + this->gen_sync(iss::POST_SYNC, 96); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } + + /* instruction 97: C.SWSP */ + std::tuple __c_swsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.SWSP"); + + this->gen_sync(iss::PRE_SYNC, 97); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,5>(instr)); + uint8_t fld_uimm_val = 0 | (bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.SWSP x2+0x%1$05x, x%2$d"); + ins_fmter % (uint64_t)fld_uimm_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t x2_idx_val = 2; + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(x2_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 97); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 98: DII */ + std::tuple __dii(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("DII"); + + this->gen_sync(iss::PRE_SYNC, 98); + + ; + if(this->disass_enabled){ + /* generate console output when executing the command */ + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr("DII"), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + this->gen_raise_trap(0, 2); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 98); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 99: FLW */ + std::tuple __flw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FLW"); + + this->gen_sync(iss::PRE_SYNC, 99); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + int16_t fld_imm_val = 0 | (signed_bit_sub<20,12>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FLW f%1$d, %2%(x%3$d)"); + ins_fmter % (uint64_t)fld_rd_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 99); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 100: FSW */ + std::tuple __fsw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FSW"); + + this->gen_sync(iss::PRE_SYNC, 100); + + int16_t fld_imm_val = 0 | (bit_sub<7,5>(instr)) | (signed_bit_sub<25,7>(instr) << 5); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FSW f%1$d, %2%(x%3$d)"); + ins_fmter % (uint64_t)fld_rs2_val % (int64_t)fld_imm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, fld_imm_val)); + Value* MEM_offs_val = this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 100); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 101: FMADD.S */ + std::tuple __fmadd_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FMADD.S"); + + this->gen_sync(iss::PRE_SYNC, 101); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rs3_val = 0 | (bit_sub<27,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FMADD.S x%1$d, f%2$d, f%3$d, f%4$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs3_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(3U, fld_rm_val), + this->gen_const(3U, 7)), + this->gen_const(8U, fld_rm_val), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 101); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 102: FMSUB.S */ + std::tuple __fmsub_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FMSUB.S"); + + this->gen_sync(iss::PRE_SYNC, 102); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rs3_val = 0 | (bit_sub<27,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FMSUB.S x%1$d, f%2$d, f%3$d, f%4$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs3_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(3U, fld_rm_val), + this->gen_const(3U, 7)), + this->gen_const(8U, fld_rm_val), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 102); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 103: FNMADD.S */ + std::tuple __fnmadd_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FNMADD.S"); + + this->gen_sync(iss::PRE_SYNC, 103); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rs3_val = 0 | (bit_sub<27,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FNMADD.S x%1$d, f%2$d, f%3$d, f%4$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs3_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 2LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(3U, fld_rm_val), + this->gen_const(3U, 7)), + this->gen_const(8U, fld_rm_val), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 103); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 104: FNMSUB.S */ + std::tuple __fnmsub_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FNMSUB.S"); + + this->gen_sync(iss::PRE_SYNC, 104); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + uint8_t fld_rs3_val = 0 | (bit_sub<27,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FNMSUB.S x%1$d, f%2$d, f%3$d, f%4$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val % (uint64_t)fld_rs3_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmadd_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs3_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 3LL), + 32, + false), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(3U, fld_rm_val), + this->gen_const(3U, 7)), + this->gen_const(8U, fld_rm_val), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 104); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 105: FADD.S */ + std::tuple __fadd_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FADD.S"); + + this->gen_sync(iss::PRE_SYNC, 105); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FADD.S x%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fadd_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(3U, fld_rm_val), + this->gen_const(3U, 7)), + this->gen_const(8U, fld_rm_val), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 105); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 106: FSUB.S */ + std::tuple __fsub_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FSUB.S"); + + this->gen_sync(iss::PRE_SYNC, 106); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FSUB.S x%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsub_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(3U, fld_rm_val), + this->gen_const(3U, 7)), + this->gen_const(8U, fld_rm_val), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 106); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 107: FMUL.S */ + std::tuple __fmul_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FMUL.S"); + + this->gen_sync(iss::PRE_SYNC, 107); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FMUL.S x%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fmul_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(3U, fld_rm_val), + this->gen_const(3U, 7)), + this->gen_const(8U, fld_rm_val), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 107); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 108: FDIV.S */ + std::tuple __fdiv_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FDIV.S"); + + this->gen_sync(iss::PRE_SYNC, 108); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FDIV.S x%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fdiv_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(3U, fld_rm_val), + this->gen_const(3U, 7)), + this->gen_const(8U, fld_rm_val), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 108); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 109: FSQRT.S */ + std::tuple __fsqrt_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FSQRT.S"); + + this->gen_sync(iss::PRE_SYNC, 109); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FSQRT.S x%1$d, f%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsqrt_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_choose( + this->builder.CreateICmp( + ICmpInst::ICMP_ULT, + this->gen_const(3U, fld_rm_val), + this->gen_const(3U, 7)), + this->gen_const(8U, fld_rm_val), + this->builder.CreateTrunc( + this->gen_reg_load(traits::FCSR, 0), + this-> get_type(8) + ), + 8) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 109); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 110: FSGNJ.S */ + std::tuple __fsgnj_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FSGNJ.S"); + + this->gen_sync(iss::PRE_SYNC, 110); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FSGNJ.S f%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateOr( + this->builder.CreateAnd( + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_const(32U, 2147483647)), + this->builder.CreateAnd( + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_const(32U, 2147483648))); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 110); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 111: FSGNJN.S */ + std::tuple __fsgnjn_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FSGNJN.S"); + + this->gen_sync(iss::PRE_SYNC, 111); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FSGNJN.S f%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateOr( + this->builder.CreateAnd( + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_const(32U, 2147483647)), + this->builder.CreateAnd( + this->builder.CreateNot(this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + )), + this->gen_const(32U, 2147483648))); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 111); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 112: FSGNJX.S */ + std::tuple __fsgnjx_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FSGNJX.S"); + + this->gen_sync(iss::PRE_SYNC, 112); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FSGNJX.S f%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateXor( + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateAnd( + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_const(32U, 2147483648))); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 112); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 113: FMIN.S */ + std::tuple __fmin_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FMIN.S"); + + this->gen_sync(iss::PRE_SYNC, 113); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FMIN.S f%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 113); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 114: FMAX.S */ + std::tuple __fmax_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FMAX.S"); + + this->gen_sync(iss::PRE_SYNC, 114); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FMAX.S f%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fsel_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 114); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 115: FCVT.W.S */ + std::tuple __fcvt_w_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FCVT.W.S"); + + this->gen_sync(iss::PRE_SYNC, 115); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FCVT.W.S x%1$d, f%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* X_rd_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false), + this->gen_const(8U, fld_rm_val) + }), + 32, + true); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 115); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 116: FCVT.WU.S */ + std::tuple __fcvt_wu_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FCVT.WU.S"); + + this->gen_sync(iss::PRE_SYNC, 116); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FCVT.WU.S x%1$d, f%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* X_rd_val = this->gen_ext( + this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false), + this->gen_const(8U, fld_rm_val) + }), + 32, + false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 116); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 117: FEQ.S */ + std::tuple __feq_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FEQ.S"); + + this->gen_sync(iss::PRE_SYNC, 117); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FEQ.S x%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* X_rd_val = this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 0LL), + 32, + false) + }); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 117); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 118: FLT.S */ + std::tuple __flt_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FLT.S"); + + this->gen_sync(iss::PRE_SYNC, 118); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FLT.S x%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* X_rd_val = this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 2LL), + 32, + false) + }); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 118); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 119: FLE.S */ + std::tuple __fle_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FLE.S"); + + this->gen_sync(iss::PRE_SYNC, 119); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + uint8_t fld_rs2_val = 0 | (bit_sub<20,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FLE.S x%1$d, f%2$d, f%3$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val % (uint64_t)fld_rs2_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* X_rd_val = this->builder.CreateCall(this->mod->getFunction("fcmp_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs2_val + traits::F0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 1LL), + 32, + false) + }); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + Value* flags_val = this->builder.CreateCall(this->mod->getFunction("fget_flags"), std::vector{ + }); + Value* FCSR_val = this->builder.CreateAdd( + this->builder.CreateAnd( + this->gen_reg_load(traits::FCSR, 0), + this->builder.CreateNot(this->gen_const(32U, 31))), + flags_val); + this->builder.CreateStore(FCSR_val, get_reg_ptr(traits::FCSR), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 119); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 120: FCLASS.S */ + std::tuple __fclass_s(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FCLASS.S"); + + this->gen_sync(iss::PRE_SYNC, 120); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FCLASS.S x%1$d, f%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* X_rd_val = this->builder.CreateCall(this->mod->getFunction("fclass_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ) + }); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 120); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 121: FCVT.S.W */ + std::tuple __fcvt_s_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FCVT.S.W"); + + this->gen_sync(iss::PRE_SYNC, 121); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FCVT.S.W f%1$d, x%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 2LL), + 32, + false), + this->gen_const(8U, fld_rm_val) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 121); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 122: FCVT.S.WU */ + std::tuple __fcvt_s_wu(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FCVT.S.WU"); + + this->gen_sync(iss::PRE_SYNC, 122); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rm_val = 0 | (bit_sub<12,3>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FCVT.S.WU f%1$d, x%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* res_val = this->builder.CreateCall(this->mod->getFunction("fcvt_s"), std::vector{ + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this-> get_type(32) + ), + this->gen_ext( + this->gen_const(64U, 3LL), + 32, + false), + this->gen_const(8U, fld_rm_val) + }); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 122); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 123: FMV.X.W */ + std::tuple __fmv_x_w(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FMV.X.W"); + + this->gen_sync(iss::PRE_SYNC, 123); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FMV.X.W x%1$d, f%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + Value* X_rd_val = this->gen_ext( + this->builder.CreateTrunc( + this->gen_reg_load(fld_rs1_val + traits::F0, 0), + this-> get_type(32) + ), + 32, + true); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 123); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 124: FMV.W.X */ + std::tuple __fmv_w_x(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("FMV.W.X"); + + this->gen_sync(iss::PRE_SYNC, 124); + + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + uint8_t fld_rs1_val = 0 | (bit_sub<15,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("FMV.W.X f%1$d, x%2$d"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+4; + + if(32 == 32){ + Value* F_rd_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0)); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 124); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 125: C.FLW */ + std::tuple __c_flw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.FLW"); + + this->gen_sync(iss::PRE_SYNC, 125); + + uint8_t fld_rd_val = 0 | (bit_sub<2,3>(instr)); + uint8_t fld_uimm_val = 0 | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.FLW f(8+%1$d), %2%(x(8+%3$d))"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + uint8_t rd_idx_val = (fld_rd_val + 8); + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); + if(32 == 32){ + Value* F_rd_idx_val = res_val; + this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_idx_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_idx_val, get_reg_ptr(rd_idx_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 125); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 126: C.FSW */ + std::tuple __c_fsw(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.FSW"); + + this->gen_sync(iss::PRE_SYNC, 126); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,3>(instr)); + uint8_t fld_uimm_val = 0 | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3); + uint8_t fld_rs1_val = 0 | (bit_sub<7,3>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.FSW f(8+%1$d), %2%(x(8+%3$d))"); + ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val % (uint64_t)fld_rs1_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t rs1_idx_val = (fld_rs1_val + 8); + uint8_t rs2_idx_val = (fld_rs2_val + 8); + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(rs1_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* MEM_offs_val = this->builder.CreateTrunc( + this->gen_reg_load(rs2_idx_val + traits::F0, 0), + this-> get_type(32) + ); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 126); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 127: C.FLWSP */ + std::tuple __c_flwsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.FLWSP"); + + this->gen_sync(iss::PRE_SYNC, 127); + + uint8_t fld_uimm_val = 0 | (bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5); + uint8_t fld_rd_val = 0 | (bit_sub<7,5>(instr)); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.FLWSP f%1$d, %2%(x2)"); + ins_fmter % (uint64_t)fld_rd_val % (uint64_t)fld_uimm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t x2_idx_val = 2; + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(x2_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* res_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); + if(32 == 32){ + Value* F_rd_val = res_val; + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } else { + uint32_t upper_val = (-1) << 31; + Value* F_rd_val = this->builder.CreateOr( + this->builder.CreateMul( + this->gen_const(32U, upper_val), + this->gen_const(32U, 2)), + res_val); + this->builder.CreateStore(F_rd_val, get_reg_ptr(fld_rd_val + traits::F0), false); + } + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 127); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /* instruction 128: C.FSWSP */ + std::tuple __c_fswsp(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){ + bb->setName("C.FSWSP"); + + this->gen_sync(iss::PRE_SYNC, 128); + + uint8_t fld_rs2_val = 0 | (bit_sub<2,5>(instr)); + uint8_t fld_uimm_val = 0 | (bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2); + if(this->disass_enabled){ + /* generate console output when executing the command */ + boost::format ins_fmter("C.FSWSP f%1$d, %2%(x2), "); + ins_fmter % (uint64_t)fld_rs2_val % (uint64_t)fld_uimm_val; + std::vector args { + this->core_ptr, + this->gen_const(64, pc.val), + this->builder.CreateGlobalStringPtr(ins_fmter.str()), + }; + this->builder.CreateCall(this->mod->getFunction("print_disass"), args); + } + + Value* cur_pc_val = this->gen_const(32, pc.val); + pc=pc+2; + + uint8_t x2_idx_val = 2; + Value* offs_val = this->builder.CreateAdd( + this->gen_reg_load(x2_idx_val + traits::X0, 0), + this->gen_const(32U, fld_uimm_val)); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::F0, 0); + this->gen_write_mem( + traits::MEM, + offs_val, + this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(32))); + this->gen_set_pc(pc, traits::NEXT_PC); + this->gen_sync(iss::POST_SYNC, 128); + bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ + this->gen_trap_check(bb); + return std::make_tuple(vm::CONT, bb); + } + + /**************************************************************************** + * end opcode definitions + ****************************************************************************/ + std::tuple illegal_intruction(virt_addr_t &pc, code_word_t instr, + llvm::BasicBlock *bb) { + this->gen_sync(iss::PRE_SYNC, instr_descr.size()); + this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), true), + get_reg_ptr(traits::PC), true); + this->builder.CreateStore( + this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits::ICOUNT), true), + this->gen_const(64U, 1)), + get_reg_ptr(traits::ICOUNT), true); + pc = pc + ((instr & 3) == 3 ? 4 : 2); + this->gen_raise_trap(0, 2); // illegal instruction trap + this->gen_sync(iss::POST_SYNC, instr_descr.size()); + this->gen_trap_check(this->leave_blk); + return std::make_tuple(iss::vm::BRANCH, nullptr); + } +}; + +template void debug_fn(CODE_WORD insn) { + volatile CODE_WORD x = insn; + insn = 2 * x; +} + +template vm_impl::vm_impl() { this(new ARCH()); } + +template +vm_impl::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) +: vm::vm_base(core, core_id, cluster_id) { + qlut[0] = lut_00.data(); + qlut[1] = lut_01.data(); + qlut[2] = lut_10.data(); + qlut[3] = lut_11.data(); + for (auto instr : instr_descr) { + auto quantrant = instr.value & 0x3; + expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op); + } +} + +template +std::tuple +vm_impl::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, llvm::BasicBlock *this_block) { + // we fetch at max 4 byte, alignment is 2 + code_word_t insn = 0; + const typename traits::addr_t upper_bits = ~traits::PGMASK; + phys_addr_t paddr(pc); + try { + uint8_t *const data = (uint8_t *)&insn; + paddr = this->core.v2p(pc); + if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary + auto res = this->core.read(paddr, 2, data); + if (res != iss::Ok) throw trap_access(1, pc.val); + if ((insn & 0x3) == 0x3) { // this is a 32bit instruction + res = this->core.read(this->core.v2p(pc + 2), 2, data + 2); + } + } else { + auto res = this->core.read(paddr, 4, data); + if (res != iss::Ok) throw trap_access(1, pc.val); + } + } catch (trap_access &ta) { + throw trap_access(ta.id, pc.val); + } + if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0' + // curr pc on stack + typename vm_impl::processing_pc_entry addr(*this, pc, paddr); + ++inst_cnt; + auto lut_val = extract_fields(insn); + auto f = qlut[insn & 0x3][lut_val]; + if (f == nullptr) { + f = &this_class::illegal_intruction; + } + return (this->*f)(pc, insn, this_block); +} + +template void vm_impl::gen_leave_behavior(llvm::BasicBlock *leave_blk) { + this->builder.SetInsertPoint(leave_blk); + this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits::NEXT_PC), false)); +} + +template void vm_impl::gen_raise_trap(uint16_t trap_id, uint16_t cause) { + auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); + this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true); +} + +template void vm_impl::gen_leave_trap(unsigned lvl) { + std::vector args{ + this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)), + }; + this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); + auto *PC_val = this->gen_read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN / 8); + this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); +} + +template void vm_impl::gen_wait(unsigned type) { + std::vector args{ + this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)), + }; + this->builder.CreateCall(this->mod->getFunction("wait"), args); +} + +template void vm_impl::gen_trap_behavior(llvm::BasicBlock *trap_blk) { + this->builder.SetInsertPoint(trap_blk); + auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits::TRAP_STATE), true); + std::vector args{this->core_ptr, this->adj_to64(trap_state_val), + this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits::PC), false))}; + this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); + auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits::NEXT_PC), false); + this->builder.CreateRet(trap_addr_val); +} + +template inline void vm_impl::gen_trap_check(llvm::BasicBlock *bb) { + auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits::TRAP_STATE), true); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, v, + llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), + bb, this->trap_blk, 1); +} + +template +inline llvm::Value* vm_impl::gen_fdispatch(std::string fname, const std::vector& args) { + return this->builder.CreateCall(this->mod->getFunction(fname), args); +} + +template +inline llvm::Value* vm_impl::gen_dispatch(std::string name, llvm::Value* val1, llvm::Value* val2, llvm::Value* val3) { +} + +} // namespace rv32imacf + +template <> +std::unique_ptr create(arch::rv32gc *core, unsigned short port, bool dump) { + std::unique_ptr> ret = + std::make_unique>(*core, dump); + if (port != 0) debugger::server::run_server(ret.get(), port); + return ret; +} + +} // namespace iss diff --git a/riscv/src/internal/vm_rv32imac.cpp b/riscv/src/internal/vm_rv32imac.cpp index 850e394..6ba14bd 100644 --- a/riscv/src/internal/vm_rv32imac.cpp +++ b/riscv/src/internal/vm_rv32imac.cpp @@ -48,6 +48,12 @@ #include namespace iss { +namespace vm { +namespace fp_impl{ +void add_fp_functions_2_module(llvm::Module *mod); +} +} + namespace rv32imac { using namespace iss::arch; using namespace llvm; @@ -81,6 +87,11 @@ protected: return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); } + void setup_module(llvm::Module* m) override { + super::setup_module(m); + vm::fp_impl::add_fp_functions_2_module(m); + } + inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) const { return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); @@ -106,6 +117,10 @@ protected: return this->builder.CreateLoad(get_reg_ptr(i), false); } + llvm::Value* gen_fdispatch(std::string fname, const std::vector& args); + + llvm::Value* gen_dispatch(std::string name, llvm::Value*, llvm::Value*, llvm::Value*); + inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), this->get_type(traits::XLEN)); @@ -407,7 +422,7 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->gen_const(32U, fld_imm_val); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 0); @@ -443,7 +458,7 @@ private: Value* X_rd_val = this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 1); @@ -479,7 +494,7 @@ private: Value* X_rd_val = this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, 4)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* PC_val = this->builder.CreateAdd( cur_pc_val, @@ -518,10 +533,10 @@ private: Value* X_rd_val = this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, 4)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* ret_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); Value* PC_val = this->builder.CreateAnd( ret_val, @@ -559,8 +574,8 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_EQ, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, fld_imm_val)), @@ -601,8 +616,8 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, fld_imm_val)), @@ -644,10 +659,10 @@ private: this->builder.CreateICmp( ICmpInst::ICMP_SLT, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 32, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 32, true)), this->builder.CreateAdd( cur_pc_val, @@ -690,10 +705,10 @@ private: this->builder.CreateICmp( ICmpInst::ICMP_SGE, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 32, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 32, true)), this->builder.CreateAdd( cur_pc_val, @@ -735,8 +750,8 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, fld_imm_val)), @@ -777,8 +792,8 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_UGE, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, fld_imm_val)), @@ -817,14 +832,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 8/8), 32, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 10); @@ -858,14 +873,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 16/8), 32, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 11); @@ -899,14 +914,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 12); @@ -940,14 +955,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 8/8), 32, false); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 13); @@ -981,14 +996,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 16/8), 32, false); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 14); @@ -1022,9 +1037,9 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -1061,9 +1076,9 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -1100,9 +1115,9 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -1140,9 +1155,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 18); @@ -1180,15 +1195,13 @@ private: this->builder.CreateICmp( ICmpInst::ICMP_SLT, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 32, true), - this->gen_ext( - this->gen_const(32U, fld_imm_val), - 32, true)), + this->gen_const(32U, fld_imm_val)), this->gen_const(32U, 1), this->gen_const(32U, 0), 32); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 19); @@ -1226,16 +1239,12 @@ private: Value* X_rd_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 32, false), - this->gen_ext( - full_imm_val, - 32, false)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(32U, full_imm_val)), this->gen_const(32U, 1), this->gen_const(32U, 0), 32); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 20); @@ -1270,9 +1279,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateXor( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 21); @@ -1307,9 +1316,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateOr( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 22); @@ -1344,9 +1353,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAnd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 23); @@ -1384,9 +1393,9 @@ private: } else { if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1425,9 +1434,9 @@ private: } else { if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1466,9 +1475,9 @@ private: } else { if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } } this->gen_set_pc(pc, traits::NEXT_PC); @@ -1504,9 +1513,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 27); @@ -1541,9 +1550,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateSub( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 28); @@ -1578,11 +1587,11 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 31)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(32U, 31))); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 29); @@ -1620,15 +1629,15 @@ private: this->builder.CreateICmp( ICmpInst::ICMP_SLT, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 32, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 32, true)), this->gen_const(32U, 1), this->gen_const(32U, 0), 32); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 30); @@ -1666,17 +1675,17 @@ private: this->builder.CreateICmp( ICmpInst::ICMP_ULT, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 32, false), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 32, false)), this->gen_const(32U, 1), this->gen_const(32U, 0), 32); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 31); @@ -1711,9 +1720,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateXor( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 32); @@ -1748,11 +1757,11 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 31)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(32U, 31))); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 33); @@ -1787,11 +1796,11 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 31)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(32U, 31))); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 34); @@ -1826,9 +1835,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateOr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 35); @@ -1863,9 +1872,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAnd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 36); @@ -2166,7 +2175,7 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* rs_val_val = this->gen_reg_load(fld_rs1_val, 0); + Value* rs_val_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); if(fld_rd_val != 0){ Value* csr_val_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); Value* CSR_csr_val = rs_val_val; @@ -2175,7 +2184,7 @@ private: fld_csr_val, this->builder.CreateZExtOrTrunc(CSR_csr_val,this->get_type(32))); Value* X_rd_val = csr_val_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } else { Value* CSR_csr_val = rs_val_val; this->gen_write_mem( @@ -2215,10 +2224,10 @@ private: pc=pc+4; Value* xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val, 0); + Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); if(fld_rd_val != 0){ Value* X_rd_val = xrd_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } if(fld_rs1_val != 0){ Value* CSR_csr_val = this->builder.CreateOr( @@ -2261,10 +2270,10 @@ private: pc=pc+4; Value* xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val, 0); + Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); if(fld_rd_val != 0){ Value* X_rd_val = xrd_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } if(fld_rs1_val != 0){ Value* CSR_csr_val = this->builder.CreateAnd( @@ -2308,7 +2317,7 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* CSR_csr_val = this->gen_ext( this->gen_const(32U, fld_zimm_val), @@ -2364,7 +2373,7 @@ private: } if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 50); @@ -2400,7 +2409,7 @@ private: Value* res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 32/8); if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } if(fld_zimm_val != 0){ Value* CSR_csr_val = this->builder.CreateAnd( @@ -2448,18 +2457,18 @@ private: if(fld_rd_val != 0){ Value* res_val = this->builder.CreateMul( this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 64, false), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, false)); Value* X_rd_val = this->gen_ext( res_val, 32, false); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 52); @@ -2495,20 +2504,20 @@ private: if(fld_rd_val != 0){ Value* res_val = this->builder.CreateMul( this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 64, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, true)); Value* X_rd_val = this->gen_ext( this->builder.CreateLShr( res_val, - 32), + this->gen_const(32U, 32)), 32, false); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 53); @@ -2544,20 +2553,20 @@ private: if(fld_rd_val != 0){ Value* res_val = this->builder.CreateMul( this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 64, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, false)); Value* X_rd_val = this->gen_ext( this->builder.CreateLShr( res_val, - 32), + this->gen_const(32U, 32)), 32, false); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 54); @@ -2593,20 +2602,20 @@ private: if(fld_rd_val != 0){ Value* res_val = this->builder.CreateMul( this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 64, false), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, false)); Value* X_rd_val = this->gen_ext( this->builder.CreateLShr( res_val, - 32), + this->gen_const(32U, 32)), 32, false); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 55); @@ -2646,28 +2655,86 @@ private: // this->builder.SetInsertPoint(bb); this->gen_cond_branch(this->builder.CreateICmp( ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), this->gen_const(32U, 0)), bb_then, bb_else); this->builder.SetInsertPoint(bb_then); { - Value* X_rd_val = this->builder.CreateSDiv( + uint32_t M1_val = (-1); + uint32_t MMIN_val = (-1) << (32 - 1); + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 1), - 32, - true), + this->gen_reg_load(fld_rs1_val + traits::X0, 1), + 32, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 1), - 32, - true)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_const(32U, MMIN_val), + 32, true)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 2), + 32, true), + this->gen_ext( + this->gen_const(32U, M1_val), + 32, true)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* X_rd_val = this->gen_const(32U, MMIN_val); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->builder.CreateSDiv( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 3), + 32, true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 3), + 32, true)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->builder.CreateSDiv( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 2), + 32, true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 2), + 32, true)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); } this->builder.CreateBr(bbnext); this->builder.SetInsertPoint(bb_else); { Value* X_rd_val = this->builder.CreateNeg(this->gen_const(32U, 1)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->builder.CreateBr(bbnext); bb=bbnext; @@ -2711,7 +2778,7 @@ private: // this->builder.SetInsertPoint(bb); this->gen_cond_branch(this->builder.CreateICmp( ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), this->gen_const(32U, 0)), bb_then, bb_else); @@ -2719,20 +2786,20 @@ private: { Value* X_rd_val = this->builder.CreateUDiv( this->gen_ext( - this->gen_reg_load(fld_rs1_val, 1), + this->gen_reg_load(fld_rs1_val + traits::X0, 1), 32, false), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 1), + this->gen_reg_load(fld_rs2_val + traits::X0, 1), 32, false)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->builder.CreateBr(bbnext); this->builder.SetInsertPoint(bb_else); { Value* X_rd_val = this->builder.CreateNeg(this->gen_const(32U, 1)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->builder.CreateBr(bbnext); bb=bbnext; @@ -2776,28 +2843,90 @@ private: // this->builder.SetInsertPoint(bb); this->gen_cond_branch(this->builder.CreateICmp( ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), this->gen_const(32U, 0)), bb_then, bb_else); this->builder.SetInsertPoint(bb_then); { - Value* X_rd_val = this->builder.CreateSRem( + uint32_t M1_val = (-1); + uint32_t MMIN_val = (-1) << (32 - 1); + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 1), - 32, - true), + this->gen_reg_load(fld_rs1_val + traits::X0, 1), + 32, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 1), - 32, - true)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_const(32U, MMIN_val), + 32, true)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); + llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); + llvm::BasicBlock* bb_else = llvm::BasicBlock::Create(this->mod->getContext(), "elsebr", this->func, bbnext); + // this->builder.SetInsertPoint(bb); + this->gen_cond_branch(this->builder.CreateICmp( + ICmpInst::ICMP_EQ, + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 2), + 32, true), + this->gen_ext( + this->gen_const(32U, M1_val), + 32, true)), + bb_then, + bb_else); + this->builder.SetInsertPoint(bb_then); + { + Value* X_rd_val = this->gen_const(32U, 0); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->builder.CreateSRem( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 3), + 32, + true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 3), + 32, + true)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); + } + this->builder.CreateBr(bbnext); + this->builder.SetInsertPoint(bb_else); + { + Value* X_rd_val = this->builder.CreateSRem( + this->gen_ext( + this->gen_reg_load(fld_rs1_val + traits::X0, 2), + 32, + true), + this->gen_ext( + this->gen_reg_load(fld_rs2_val + traits::X0, 2), + 32, + true)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); + } + this->builder.CreateBr(bbnext); + bb=bbnext; + this->builder.SetInsertPoint(bb); } this->builder.CreateBr(bbnext); this->builder.SetInsertPoint(bb_else); { - Value* X_rd_val = this->gen_reg_load(fld_rs1_val, 1); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + Value* X_rd_val = this->gen_reg_load(fld_rs1_val + traits::X0, 1); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->builder.CreateBr(bbnext); bb=bbnext; @@ -2841,7 +2970,7 @@ private: // this->builder.SetInsertPoint(bb); this->gen_cond_branch(this->builder.CreateICmp( ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), this->gen_const(32U, 0)), bb_then, bb_else); @@ -2849,20 +2978,20 @@ private: { Value* X_rd_val = this->builder.CreateURem( this->gen_ext( - this->gen_reg_load(fld_rs1_val, 1), + this->gen_reg_load(fld_rs1_val + traits::X0, 1), 32, false), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 1), + this->gen_reg_load(fld_rs2_val + traits::X0, 1), 32, false)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->builder.CreateBr(bbnext); this->builder.SetInsertPoint(bb_else); { - Value* X_rd_val = this->gen_reg_load(fld_rs1_val, 1); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + Value* X_rd_val = this->gen_reg_load(fld_rs1_val + traits::X0, 1); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->builder.CreateBr(bbnext); bb=bbnext; @@ -2901,12 +3030,12 @@ private: pc=pc+4; if(fld_rd_val != 0){ - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); Value* RES_offs_val = this->gen_ext( this->builder.CreateNeg(this->gen_const(8U, 1)), 32, @@ -2949,7 +3078,7 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_read_mem(traits::RES, offs_val, 32/8); llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); @@ -2962,7 +3091,7 @@ private: bbnext); this->builder.SetInsertPoint(bb_then); { - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 1); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 1); this->gen_write_mem( traits::MEM, offs_val, @@ -2980,7 +3109,7 @@ private: this->gen_const(32U, 0), this->gen_const(32U, 1), 32); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 61); @@ -3015,15 +3144,15 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -3061,18 +3190,18 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateAdd( res1_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3111,18 +3240,18 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateXor( res1_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3161,18 +3290,18 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateAnd( res1_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3211,18 +3340,18 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateOr( res1_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3261,14 +3390,14 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( @@ -3277,9 +3406,9 @@ private: res1_val, 32, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 32, true)), - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res1_val, 32); Value* MEM_offs_val = res2_val; @@ -3320,14 +3449,14 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( @@ -3336,9 +3465,9 @@ private: res1_val, 32, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 32, true)), - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res1_val, 32); Value* MEM_offs_val = res2_val; @@ -3379,21 +3508,21 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, false); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_UGT, res1_val, - this->gen_reg_load(fld_rs2_val, 0)), - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res1_val, 32); Value* MEM_offs_val = res2_val; @@ -3434,25 +3563,21 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 32, false); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, - this->gen_ext( - res1_val, - 32, false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 32, false)), - this->gen_reg_load(fld_rs2_val, 0), + res1_val, + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res1_val, 32); Value* MEM_offs_val = res2_val; @@ -3496,9 +3621,9 @@ private: uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t x2_idx_val = 2; Value* X_rd_idx_val = this->builder.CreateAdd( - this->gen_reg_load(x2_idx_val, 0), + this->gen_reg_load(x2_idx_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 71); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3533,10 +3658,10 @@ private: uint8_t rs1_idx_val = (fld_rs1_val + 8); uint8_t rd_idx_val = (fld_rd_val + 8); Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1_idx_val, 0), + this->gen_reg_load(rs1_idx_val + traits::X0, 0), this->gen_const(32U, fld_uimm_val)); Value* X_rd_idx_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 72); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3571,9 +3696,9 @@ private: uint8_t rs1_idx_val = (fld_rs1_val + 8); uint8_t rs2_idx_val = (fld_rs2_val + 8); Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(rs1_idx_val, 0), + this->gen_reg_load(rs1_idx_val + traits::X0, 0), this->gen_const(32U, fld_uimm_val)); - Value* MEM_offs_val = this->gen_reg_load(rs2_idx_val, 0); + Value* MEM_offs_val = this->gen_reg_load(rs2_idx_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -3609,9 +3734,9 @@ private: pc=pc+2; Value* X_rs1_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val), false); + this->builder.CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 74); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3673,7 +3798,7 @@ private: Value* X_rd_val = this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, 2)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(rd_val + traits::X0), false); Value* PC_val = this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, fld_imm_val)); @@ -3710,7 +3835,7 @@ private: this->gen_raise_trap(0, 2); } Value* X_rd_val = this->gen_const(32U, fld_imm_val); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 77); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3748,7 +3873,7 @@ private: this->gen_raise_trap(0, 2); } Value* X_rd_val = this->gen_const(32U, fld_imm_val); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 78); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3781,10 +3906,10 @@ private: uint8_t x2_idx_val = 2; Value* X_x2_idx_val = this->builder.CreateAdd( this->gen_ext( - this->gen_reg_load(x2_idx_val, 0), + this->gen_reg_load(x2_idx_val + traits::X0, 0), 32, true), this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(X_x2_idx_val, get_reg_ptr(x2_idx_val), false); + this->builder.CreateStore(X_x2_idx_val, get_reg_ptr(x2_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 79); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3817,9 +3942,9 @@ private: uint8_t rs1_idx_val = (fld_rs1_val + 8); Value* X_rs1_idx_val = this->builder.CreateLShr( - this->gen_reg_load(rs1_idx_val, 0), + this->gen_reg_load(rs1_idx_val + traits::X0, 0), this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val), false); + this->builder.CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 80); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3852,9 +3977,9 @@ private: uint8_t rs1_idx_val = (fld_rs1_val + 8); Value* X_rs1_idx_val = this->builder.CreateAShr( - this->gen_reg_load(rs1_idx_val, 0), + this->gen_reg_load(rs1_idx_val + traits::X0, 0), this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val), false); + this->builder.CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 81); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3887,9 +4012,9 @@ private: uint8_t rs1_idx_val = (fld_rs1_val + 8); Value* X_rs1_idx_val = this->builder.CreateAnd( - this->gen_reg_load(rs1_idx_val, 0), + this->gen_reg_load(rs1_idx_val + traits::X0, 0), this->gen_const(32U, fld_imm_val)); - this->builder.CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val), false); + this->builder.CreateStore(X_rs1_idx_val, get_reg_ptr(rs1_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 82); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3923,9 +4048,9 @@ private: uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t rs2_idx_val = (fld_rs2_val + 8); Value* X_rd_idx_val = this->builder.CreateSub( - this->gen_reg_load(rd_idx_val, 0), - this->gen_reg_load(rs2_idx_val, 0)); - this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); + this->gen_reg_load(rd_idx_val + traits::X0, 0), + this->gen_reg_load(rs2_idx_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 83); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3959,9 +4084,9 @@ private: uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t rs2_idx_val = (fld_rs2_val + 8); Value* X_rd_idx_val = this->builder.CreateXor( - this->gen_reg_load(rd_idx_val, 0), - this->gen_reg_load(rs2_idx_val, 0)); - this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); + this->gen_reg_load(rd_idx_val + traits::X0, 0), + this->gen_reg_load(rs2_idx_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 84); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -3995,9 +4120,9 @@ private: uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t rs2_idx_val = (fld_rs2_val + 8); Value* X_rd_idx_val = this->builder.CreateOr( - this->gen_reg_load(rd_idx_val, 0), - this->gen_reg_load(rs2_idx_val, 0)); - this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); + this->gen_reg_load(rd_idx_val + traits::X0, 0), + this->gen_reg_load(rs2_idx_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 85); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4031,9 +4156,9 @@ private: uint8_t rd_idx_val = (fld_rd_val + 8); uint8_t rs2_idx_val = (fld_rs2_val + 8); Value* X_rd_idx_val = this->builder.CreateAnd( - this->gen_reg_load(rd_idx_val, 0), - this->gen_reg_load(rs2_idx_val, 0)); - this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val), false); + this->gen_reg_load(rd_idx_val + traits::X0, 0), + this->gen_reg_load(rs2_idx_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_idx_val, get_reg_ptr(rd_idx_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 86); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4099,7 +4224,7 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_EQ, - this->gen_reg_load(rs1_idx_val, 0), + this->gen_reg_load(rs1_idx_val + traits::X0, 0), this->gen_const(32U, 0)), this->builder.CreateAdd( cur_pc_val, @@ -4141,7 +4266,7 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_NE, - this->gen_reg_load(rs1_idx_val, 0), + this->gen_reg_load(rs1_idx_val + traits::X0, 0), this->gen_const(32U, 0)), this->builder.CreateAdd( cur_pc_val, @@ -4183,9 +4308,9 @@ private: this->gen_raise_trap(0, 2); } Value* X_rs1_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(32U, fld_shamt_val)); - this->builder.CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val), false); + this->builder.CreateStore(X_rs1_val, get_reg_ptr(fld_rs1_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 90); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4218,10 +4343,10 @@ private: uint8_t x2_idx_val = 2; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(x2_idx_val, 0), + this->gen_reg_load(x2_idx_val + traits::X0, 0), this->gen_const(32U, fld_uimm_val)); Value* X_rd_val = this->gen_read_mem(traits::MEM, offs_val, 32/8); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 91); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4252,8 +4377,8 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - Value* X_rd_val = this->gen_reg_load(fld_rs2_val, 0); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + Value* X_rd_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 92); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4283,7 +4408,7 @@ private: Value* cur_pc_val = this->gen_const(32, pc.val); pc=pc+2; - Value* PC_val = this->gen_reg_load(fld_rs1_val, 0); + Value* PC_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC, 93); this->gen_trap_check(this->leave_blk); @@ -4314,9 +4439,9 @@ private: pc=pc+2; Value* X_rd_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rd_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rd_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 94); bb = llvm::BasicBlock::Create(this->mod->getContext(), "entry", this->func, this->leave_blk); /* create next BasicBlock in chain */ @@ -4350,8 +4475,8 @@ private: Value* X_r_idx_val = this->builder.CreateAdd( cur_pc_val, this->gen_const(32U, 2)); - this->builder.CreateStore(X_r_idx_val, get_reg_ptr(r_idx_val), false); - Value* PC_val = this->gen_reg_load(fld_rs1_val, 0); + this->builder.CreateStore(X_r_idx_val, get_reg_ptr(r_idx_val + traits::X0), false); + Value* PC_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); this->builder.CreateStore(PC_val, get_reg_ptr(traits::NEXT_PC), false); this->gen_sync(iss::POST_SYNC, 95); this->gen_trap_check(this->leave_blk); @@ -4409,9 +4534,9 @@ private: uint8_t x2_idx_val = 2; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(x2_idx_val, 0), + this->gen_reg_load(x2_idx_val + traits::X0, 0), this->gen_const(32U, fld_uimm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -4570,7 +4695,16 @@ template inline void vm_impl::gen_trap_check(llvm::BasicBl bb, this->trap_blk, 1); } -} // namespace rv32imac +template +inline llvm::Value* vm_impl::gen_fdispatch(std::string fname, const std::vector& args) { + return this->builder.CreateCall(this->mod->getFunction(fname), args); +} + +template +inline llvm::Value* vm_impl::gen_dispatch(std::string name, llvm::Value* val1, llvm::Value* val2, llvm::Value* val3) { +} + +} // namespace rv32imacf template <> std::unique_ptr create(arch::rv32imac *core, unsigned short port, bool dump) { diff --git a/riscv/src/internal/vm_rv64ia.cpp b/riscv/src/internal/vm_rv64ia.cpp index 6186d58..9aa7777 100644 --- a/riscv/src/internal/vm_rv64ia.cpp +++ b/riscv/src/internal/vm_rv64ia.cpp @@ -48,6 +48,12 @@ #include namespace iss { +namespace vm { +namespace fp_impl{ +void add_fp_functions_2_module(llvm::Module *mod); +} +} + namespace rv64ia { using namespace iss::arch; using namespace llvm; @@ -81,6 +87,11 @@ protected: return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits())); } + void setup_module(llvm::Module* m) override { + super::setup_module(m); + vm::fp_impl::add_fp_functions_2_module(m); + } + inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) const { return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); @@ -106,6 +117,10 @@ protected: return this->builder.CreateLoad(get_reg_ptr(i), false); } + llvm::Value* gen_fdispatch(std::string fname, const std::vector& args); + + llvm::Value* gen_dispatch(std::string name, llvm::Value*, llvm::Value*, llvm::Value*); + inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val), this->get_type(traits::XLEN)); @@ -381,14 +396,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, false); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 0); @@ -422,14 +437,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 1); @@ -463,9 +478,9 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -506,9 +521,9 @@ private: } else { if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_shamt_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } } this->gen_set_pc(pc, traits::NEXT_PC); @@ -547,9 +562,9 @@ private: } else { if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_shamt_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } } this->gen_set_pc(pc, traits::NEXT_PC); @@ -588,9 +603,9 @@ private: } else { if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_shamt_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } } this->gen_set_pc(pc, traits::NEXT_PC); @@ -627,7 +642,7 @@ private: if(fld_rd_val != 0){ Value* res_val = this->builder.CreateAdd( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this-> get_type(32) ), this->gen_const(32U, fld_imm_val)); @@ -635,7 +650,7 @@ private: res_val, 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 6); @@ -671,7 +686,7 @@ private: if(fld_rd_val != 0){ Value* sh_val_val = this->builder.CreateShl( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this-> get_type(32) ), this->gen_const(32U, fld_shamt_val)); @@ -679,7 +694,7 @@ private: sh_val_val, 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 7); @@ -715,7 +730,7 @@ private: if(fld_rd_val != 0){ Value* sh_val_val = this->builder.CreateLShr( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this-> get_type(32) ), this->gen_const(32U, fld_shamt_val)); @@ -723,7 +738,7 @@ private: sh_val_val, 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 8); @@ -759,7 +774,7 @@ private: if(fld_rd_val != 0){ Value* sh_val_val = this->builder.CreateAShr( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this-> get_type(32) ), this->gen_const(32U, fld_shamt_val)); @@ -767,7 +782,7 @@ private: sh_val_val, 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 9); @@ -801,18 +816,18 @@ private: if(fld_rd_val != 0){ Value* res_val = this->builder.CreateAdd( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this-> get_type(32) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), this-> get_type(32) )); Value* X_rd_val = this->gen_ext( res_val, 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 10); @@ -846,18 +861,18 @@ private: if(fld_rd_val != 0){ Value* res_val = this->builder.CreateSub( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this-> get_type(32) ), this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), this-> get_type(32) )); Value* X_rd_val = this->gen_ext( res_val, 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 11); @@ -891,16 +906,16 @@ private: pc=pc+4; if(fld_rd_val != 0){ - Value* mask_val = this->gen_const(32U, 31); + uint32_t mask_val = 31; Value* count_val = this->builder.CreateAnd( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), this-> get_type(32) ), - mask_val); + this->gen_const(32U, mask_val)); Value* sh_val_val = this->builder.CreateShl( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this-> get_type(32) ), count_val); @@ -908,7 +923,7 @@ private: sh_val_val, 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 12); @@ -942,16 +957,16 @@ private: pc=pc+4; if(fld_rd_val != 0){ - Value* mask_val = this->gen_const(32U, 31); + uint32_t mask_val = 31; Value* count_val = this->builder.CreateAnd( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), this-> get_type(32) ), - mask_val); + this->gen_const(32U, mask_val)); Value* sh_val_val = this->builder.CreateLShr( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this-> get_type(32) ), count_val); @@ -959,7 +974,7 @@ private: sh_val_val, 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 13); @@ -993,16 +1008,16 @@ private: pc=pc+4; if(fld_rd_val != 0){ - Value* mask_val = this->gen_const(32U, 31); + uint32_t mask_val = 31; Value* count_val = this->builder.CreateAnd( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), this-> get_type(32) ), - mask_val); + this->gen_const(32U, mask_val)); Value* sh_val_val = this->builder.CreateAShr( this->builder.CreateTrunc( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this-> get_type(32) ), count_val); @@ -1010,7 +1025,7 @@ private: sh_val_val, 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 14); @@ -1044,7 +1059,7 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->gen_const(64U, fld_imm_val); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 15); @@ -1080,7 +1095,7 @@ private: Value* X_rd_val = this->builder.CreateAdd( cur_pc_val, this->gen_const(64U, fld_imm_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 16); @@ -1116,7 +1131,7 @@ private: Value* X_rd_val = this->builder.CreateAdd( cur_pc_val, this->gen_const(64U, 4)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* PC_val = this->builder.CreateAdd( cur_pc_val, @@ -1152,7 +1167,7 @@ private: pc=pc+4; Value* new_pc_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); Value* align_val = this->builder.CreateAnd( new_pc_val, @@ -1178,7 +1193,7 @@ private: Value* X_rd_val = this->builder.CreateAdd( cur_pc_val, this->gen_const(64U, 4)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* PC_val = this->builder.CreateAnd( new_pc_val, @@ -1220,8 +1235,8 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_EQ, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), this->builder.CreateAdd( cur_pc_val, this->gen_const(64U, fld_imm_val)), @@ -1262,8 +1277,8 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_NE, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), this->builder.CreateAdd( cur_pc_val, this->gen_const(64U, fld_imm_val)), @@ -1305,10 +1320,10 @@ private: this->builder.CreateICmp( ICmpInst::ICMP_SLT, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 64, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, true)), this->builder.CreateAdd( cur_pc_val, @@ -1351,10 +1366,10 @@ private: this->builder.CreateICmp( ICmpInst::ICMP_SGE, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 64, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, true)), this->builder.CreateAdd( cur_pc_val, @@ -1396,8 +1411,8 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), this->builder.CreateAdd( cur_pc_val, this->gen_const(64U, fld_imm_val)), @@ -1438,8 +1453,8 @@ private: Value* PC_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_UGE, - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), this->builder.CreateAdd( cur_pc_val, this->gen_const(64U, fld_imm_val)), @@ -1478,14 +1493,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 8/8), 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 25); @@ -1519,14 +1534,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 16/8), 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 26); @@ -1560,14 +1575,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 27); @@ -1601,14 +1616,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 8/8), 64, false); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 28); @@ -1642,14 +1657,14 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 16/8), 64, false); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 29); @@ -1683,9 +1698,9 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -1722,9 +1737,9 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -1761,9 +1776,9 @@ private: pc=pc+4; Value* offs_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -1801,9 +1816,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 33); @@ -1841,15 +1856,13 @@ private: this->builder.CreateICmp( ICmpInst::ICMP_SLT, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 64, true), - this->gen_ext( - this->gen_const(64U, fld_imm_val), - 64, true)), + this->gen_const(64U, fld_imm_val)), this->gen_const(64U, 1), this->gen_const(64U, 0), 64); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 34); @@ -1887,16 +1900,12 @@ private: Value* X_rd_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, - this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), - 64, false), - this->gen_ext( - full_imm_val, - 64, false)), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_const(64U, full_imm_val)), this->gen_const(64U, 1), this->gen_const(64U, 0), 64); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 35); @@ -1931,9 +1940,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateXor( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 36); @@ -1968,9 +1977,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateOr( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 37); @@ -2005,9 +2014,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAnd( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->gen_const(64U, fld_imm_val)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 38); @@ -2042,9 +2051,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAdd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 39); @@ -2079,9 +2088,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateSub( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 40); @@ -2116,11 +2125,11 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateShl( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 63)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(64U, 63))); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 41); @@ -2158,15 +2167,15 @@ private: this->builder.CreateICmp( ICmpInst::ICMP_SLT, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 64, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, true)), this->gen_const(64U, 1), this->gen_const(64U, 0), 64); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 42); @@ -2204,17 +2213,17 @@ private: this->builder.CreateICmp( ICmpInst::ICMP_ULT, this->gen_ext( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), 64, false), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, false)), this->gen_const(64U, 1), this->gen_const(64U, 0), 64); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 43); @@ -2249,9 +2258,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateXor( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 44); @@ -2286,11 +2295,11 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateLShr( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 63)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(64U, 63))); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 45); @@ -2325,11 +2334,11 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAShr( - this->gen_reg_load(fld_rs1_val, 0), + this->gen_reg_load(fld_rs1_val + traits::X0, 0), this->builder.CreateAnd( - this->gen_reg_load(fld_rs2_val, 0), - 63)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs2_val + traits::X0, 0), + this->gen_const(64U, 63))); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 46); @@ -2364,9 +2373,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateOr( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 47); @@ -2401,9 +2410,9 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->builder.CreateAnd( - this->gen_reg_load(fld_rs1_val, 0), - this->gen_reg_load(fld_rs2_val, 0)); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->gen_reg_load(fld_rs1_val + traits::X0, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 48); @@ -2704,7 +2713,7 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* rs_val_val = this->gen_reg_load(fld_rs1_val, 0); + Value* rs_val_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); if(fld_rd_val != 0){ Value* csr_val_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); Value* CSR_csr_val = rs_val_val; @@ -2713,7 +2722,7 @@ private: fld_csr_val, this->builder.CreateZExtOrTrunc(CSR_csr_val,this->get_type(64))); Value* X_rd_val = csr_val_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } else { Value* CSR_csr_val = rs_val_val; this->gen_write_mem( @@ -2753,10 +2762,10 @@ private: pc=pc+4; Value* xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val, 0); + Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); if(fld_rd_val != 0){ Value* X_rd_val = xrd_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } if(fld_rs1_val != 0){ Value* CSR_csr_val = this->builder.CreateOr( @@ -2799,10 +2808,10 @@ private: pc=pc+4; Value* xrd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); - Value* xrs1_val = this->gen_reg_load(fld_rs1_val, 0); + Value* xrs1_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); if(fld_rd_val != 0){ Value* X_rd_val = xrd_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } if(fld_rs1_val != 0){ Value* CSR_csr_val = this->builder.CreateAnd( @@ -2846,7 +2855,7 @@ private: if(fld_rd_val != 0){ Value* X_rd_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* CSR_csr_val = this->gen_ext( this->gen_const(64U, fld_zimm_val), @@ -2902,7 +2911,7 @@ private: } if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 62); @@ -2938,7 +2947,7 @@ private: Value* res_val = this->gen_read_mem(traits::CSR, fld_csr_val, 64/8); if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } if(fld_zimm_val != 0){ Value* CSR_csr_val = this->builder.CreateAnd( @@ -2985,12 +2994,12 @@ private: pc=pc+4; if(fld_rd_val != 0){ - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); Value* RES_offs_val = this->gen_ext( this->builder.CreateNeg(this->gen_const(8U, 1)), 64, @@ -3033,7 +3042,7 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res_val = this->gen_read_mem(traits::RES, offs_val, 8/8); llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); @@ -3047,13 +3056,13 @@ private: bb_else); this->builder.SetInsertPoint(bb_then); { - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 1); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 1); this->gen_write_mem( traits::MEM, offs_val, this->builder.CreateZExtOrTrunc(MEM_offs_val,this->get_type(64)));if(fld_rd_val != 0){ Value* X_rd_val = this->gen_const(64U, 0); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } } this->builder.CreateBr(bbnext); @@ -3061,7 +3070,7 @@ private: { if(fld_rd_val != 0){ Value* X_rd_val = this->gen_const(64U, 1); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } } this->builder.CreateBr(bbnext); @@ -3100,15 +3109,15 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -3146,18 +3155,18 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateAdd( res_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3196,18 +3205,18 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateXor( res_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3246,18 +3255,18 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateAnd( res_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3296,18 +3305,18 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateOr( res_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3346,14 +3355,14 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( @@ -3362,9 +3371,9 @@ private: res_val, 64, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, true)), - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res_val, 64); Value* MEM_offs_val = res_val; @@ -3405,14 +3414,14 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( @@ -3421,9 +3430,9 @@ private: res_val, 64, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, true)), - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res_val, 64); Value* MEM_offs_val = res2_val; @@ -3464,21 +3473,21 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, false); if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_UGT, res_val, - this->gen_reg_load(fld_rs2_val, 0)), - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res_val, 64); Value* MEM_offs_val = res2_val; @@ -3519,21 +3528,21 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 64/8), 64, false); if(fld_rd_val != 0){ Value* X_rd_val = res_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, res_val, - this->gen_reg_load(fld_rs2_val, 0)), - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res_val, 64); Value* MEM_offs_val = res2_val; @@ -3574,12 +3583,12 @@ private: pc=pc+4; if(fld_rd_val != 0){ - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); Value* RES_offs_val = this->gen_ext( this->builder.CreateNeg(this->gen_const(8U, 1)), 32, @@ -3622,7 +3631,7 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_read_mem(traits::RES, offs_val, 32/8); llvm::BasicBlock* bbnext = llvm::BasicBlock::Create(this->mod->getContext(), "endif", this->func, this->leave_blk); llvm::BasicBlock* bb_then = llvm::BasicBlock::Create(this->mod->getContext(), "thenbr", this->func, bbnext); @@ -3635,7 +3644,7 @@ private: bbnext); this->builder.SetInsertPoint(bb_then); { - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 1); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 1); this->gen_write_mem( traits::MEM, offs_val, @@ -3653,7 +3662,7 @@ private: this->gen_const(64U, 0), this->gen_const(64U, 1), 64); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } this->gen_set_pc(pc, traits::NEXT_PC); this->gen_sync(iss::POST_SYNC, 76); @@ -3688,15 +3697,15 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); if(fld_rd_val != 0){ Value* X_rd_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, true); - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } - Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val, 0); + Value* MEM_offs_val = this->gen_reg_load(fld_rs2_val + traits::X0, 0); this->gen_write_mem( traits::MEM, offs_val, @@ -3734,18 +3743,18 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateAdd( res1_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3784,18 +3793,18 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateXor( res1_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3834,18 +3843,18 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateAnd( res1_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3884,18 +3893,18 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->builder.CreateOr( res1_val, - this->gen_reg_load(fld_rs2_val, 0)); + this->gen_reg_load(fld_rs2_val + traits::X0, 0)); Value* MEM_offs_val = res2_val; this->gen_write_mem( traits::MEM, @@ -3934,14 +3943,14 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( @@ -3950,9 +3959,9 @@ private: res1_val, 64, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, true)), - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res1_val, 64); Value* MEM_offs_val = res2_val; @@ -3993,14 +4002,14 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, true); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( @@ -4009,9 +4018,9 @@ private: res1_val, 64, true), this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), 64, true)), - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res1_val, 64); Value* MEM_offs_val = res2_val; @@ -4052,21 +4061,21 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, false); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_UGT, res1_val, - this->gen_reg_load(fld_rs2_val, 0)), - this->gen_reg_load(fld_rs2_val, 0), + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res1_val, 64); Value* MEM_offs_val = res2_val; @@ -4107,25 +4116,21 @@ private: Value* cur_pc_val = this->gen_const(64, pc.val); pc=pc+4; - Value* offs_val = this->gen_reg_load(fld_rs1_val, 0); + Value* offs_val = this->gen_reg_load(fld_rs1_val + traits::X0, 0); Value* res1_val = this->gen_ext( this->gen_read_mem(traits::MEM, offs_val, 32/8), 64, false); if(fld_rd_val != 0){ Value* X_rd_val = res1_val; - this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val), false); + this->builder.CreateStore(X_rd_val, get_reg_ptr(fld_rd_val + traits::X0), false); } Value* res2_val = this->gen_choose( this->builder.CreateICmp( ICmpInst::ICMP_ULT, - this->gen_ext( - res1_val, - 64, false), - this->gen_ext( - this->gen_reg_load(fld_rs2_val, 0), - 64, false)), - this->gen_reg_load(fld_rs2_val, 0), + res1_val, + this->gen_reg_load(fld_rs2_val + traits::X0, 0)), + this->gen_reg_load(fld_rs2_val + traits::X0, 0), res1_val, 64); Value* MEM_offs_val = res2_val; @@ -4259,7 +4264,16 @@ template inline void vm_impl::gen_trap_check(llvm::BasicBl bb, this->trap_blk, 1); } -} // namespace rv64ia +template +inline llvm::Value* vm_impl::gen_fdispatch(std::string fname, const std::vector& args) { + return this->builder.CreateCall(this->mod->getFunction(fname), args); +} + +template +inline llvm::Value* vm_impl::gen_dispatch(std::string name, llvm::Value* val1, llvm::Value* val2, llvm::Value* val3) { +} + +} // namespace rv32imacf template <> std::unique_ptr create(arch::rv64ia *core, unsigned short port, bool dump) { diff --git a/riscv/src/iss/rv32gc.cpp b/riscv/src/iss/rv32gc.cpp new file mode 100644 index 0000000..95472fe --- /dev/null +++ b/riscv/src/iss/rv32gc.cpp @@ -0,0 +1,74 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, MINRES Technologies GmbH +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +//////////////////////////////////////////////////////////////////////////////// + +#include "util/ities.h" +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#include +#ifdef __cplusplus +} +#endif +#include +#include +#include + +using namespace iss::arch; + +rv32gc::rv32gc() { + reg.icount=0; +} + +rv32gc::~rv32gc(){ +} + +void rv32gc::reset(uint64_t address) { + for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits::reg_t),0)); + reg.PC=address; + reg.NEXT_PC=reg.PC; + reg.trap_state=0; + reg.machine_state=0x0; +} + +uint8_t* rv32gc::get_regs_base_ptr(){ + return reinterpret_cast(®); +} + +rv32gc::phys_addr_t rv32gc::virt2phys(const iss::addr_t &pc) { + return phys_addr_t(pc); // change logical address to physical address +} + diff --git a/riscv/src/main.cpp b/riscv/src/main.cpp index 48a4905..a241da0 100644 --- a/riscv/src/main.cpp +++ b/riscv/src/main.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -103,15 +104,19 @@ int main(int argc, char *argv[]) { // instantiate the simulator std::unique_ptr vm{nullptr}; std::string isa_opt(clim["isa"].as()); - iss::plugin::instruction_count ic_plugin("riscv/gen_input/src-gen/rv32imac_cyles.txt"); - iss::plugin::cycle_estimate ce_plugin("riscv/gen_input/src-gen/rv32imac_cyles.txt"); +// iss::plugin::instruction_count ic_plugin("riscv/gen_input/src-gen/rv32imac_cyles.txt"); +// iss::plugin::cycle_estimate ce_plugin("riscv/gen_input/src-gen/rv32imac_cyles.txt"); if (isa_opt.substr(0, 4)=="rv64") { iss::arch::rv64ia* cpu = new iss::arch::riscv_hart_msu_vp(); vm = iss::create(cpu, clim["gdb-port"].as()); - } else if (isa_opt.substr(0, 4)=="rv32") { + } else if (isa_opt.substr(0, 5)=="rv32i") { iss::arch::rv32imac* cpu = new iss::arch::riscv_hart_msu_vp(); vm = iss::create(cpu, clim["gdb-port"].as()); //vm->register_plugin(ce_plugin); + } else if (isa_opt.substr(0, 5)=="rv32g") { + iss::arch::rv32gc* cpu = new iss::arch::riscv_hart_msu_vp(); + vm = iss::create(cpu, clim["gdb-port"].as()); + //vm->register_plugin(ce_plugin); } else { LOG(ERROR) << "Illegal argument value for '--isa': " << clim["isa"].as() << std::endl; return 127;