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