diff --git a/.cproject b/.cproject
index 64a9192..48c5c3a 100644
--- a/.cproject
+++ b/.cproject
@@ -10,6 +10,7 @@
+
@@ -17,7 +18,7 @@
-
+
@@ -45,7 +46,17 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -177,4 +188,5 @@
+
diff --git a/.project b/.project
index 3e68573..84a8200 100644
--- a/.project
+++ b/.project
@@ -1,6 +1,6 @@
- dbt-riscv
+ DBT-RISE-RISCV
@@ -23,5 +23,6 @@
org.eclipse.cdt.core.ccnature
org.eclipse.cdt.managedbuilder.core.managedBuildNature
org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+ org.eclipse.linuxtools.tmf.project.nature
diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs
new file mode 100644
index 0000000..3834c16
--- /dev/null
+++ b/.settings/org.eclipse.cdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+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/CMakeLists.txt b/CMakeLists.txt
index 3f61bce..82594ec 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,8 @@ include(clang-format)
add_subdirectory(external)
add_subdirectory(dbt-core)
add_subdirectory(sc-components)
+add_subdirectory(softfloat)
+GET_DIRECTORY_PROPERTY(SOFTFLOAT_INCLUDE_DIRS DIRECTORY softfloat DEFINITION SOFTFLOAT_INCLUDE_DIRS)
add_subdirectory(riscv)
add_subdirectory(riscv.sc)
diff --git a/cycles.txt b/cycles.txt
new file mode 100644
index 0000000..2f86175
--- /dev/null
+++ b/cycles.txt
@@ -0,0 +1,1728 @@
+{
+ "RV32GC" : [
+ {
+ "name" : "LUI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AUIPC",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "JAL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "JALR",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "BEQ",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BNE",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BLT",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BGE",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BLTU",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BGEU",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "LB",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LH",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LBU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LHU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SB",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SH",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ADDI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLTI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLTIU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "XORI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ORI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ANDI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLLI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRLI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRAI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ADD",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SUB",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLT",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLTU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "XOR",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRA",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "OR",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AND",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FENCE",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FENCE_I",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ECALL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "EBREAK",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "URET",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRET",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "MRET",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "WFI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SFENCE.VMA",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRS",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRC",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRWI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRSI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRCI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "MUL",
+ "size" : 32,
+ "delay" : 5
+ },
+ {
+ "name" : "MULH",
+ "size" : 32,
+ "delay" : 5
+ },
+ {
+ "name" : "MULHSU",
+ "size" : 320,
+ "delay" : 5
+ },
+ {
+ "name" : "MULHU",
+ "size" : 32,
+ "delay" : 5
+ },
+ {
+ "name" : "DIV",
+ "size" : 32,
+ "delay" : 10
+ },
+ {
+ "name" : "DIVU",
+ "size" : 32,
+ "delay" : 10
+ },
+ {
+ "name" : "REM",
+ "size" : 32,
+ "delay" : 10
+ },
+ {
+ "name" : "REMU",
+ "size" : 32,
+ "delay" : 10
+ },
+ {
+ "name" : "LR.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SC.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOSWAP.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOADD.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOXOR.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOAND.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOOR.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMIN.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMAX.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMINU.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMAXU.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "C.ADDI4SPN",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.LW",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.SW",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.ADDI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.NOP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.JAL",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.LI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.LUI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.ADDI16SP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.SRLI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.SRAI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.ANDI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.SUB",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.XOR",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.OR",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.AND",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.J",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.BEQZ",
+ "size" : 16,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "C.BNEZ",
+ "size" : 16,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "C.SLLI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.LWSP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.MV",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.JR",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.ADD",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.JALR",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.EBREAK",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.SWSP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "DII",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "FLW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMADD.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMSUB.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FNMADD.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FNMSUB.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FADD.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSUB.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMUL.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FDIV.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSQRT.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSGNJ.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSGNJN.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSGNJX.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMIN.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMAX.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCVT.W.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCVT.WU.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FEQ.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FLT.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FLE.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCLASS.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCVT.S.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCVT.S.WU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMV.X.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMV.W.X",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "C.FLW",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.FSW",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.FLWSP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.FSWSP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "FLD",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSD",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMADD.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMSUB.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FNMADD.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FNMSUB.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FADD.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSUB.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMUL.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FDIV.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSQRT.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSGNJ.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSGNJN.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FSGNJX.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMIN.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FMAX.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCVT.S.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCVT.D.S",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FEQ.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FLT.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FLE.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCLASS.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCVT.W.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCVT.WU.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCVT.D.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FCVT.D.WU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "C.FLD",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.FSD",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.FLDSP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.FSDSP",
+ "size" : 16,
+ "delay" : 1
+ }
+ ],
+ "RV32IMAC" : [
+ {
+ "name" : "LUI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AUIPC",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "JAL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "JALR",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "BEQ",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BNE",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BLT",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BGE",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BLTU",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BGEU",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "LB",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LH",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LBU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LHU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SB",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SH",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ADDI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLTI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLTIU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "XORI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ORI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ANDI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLLI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRLI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRAI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ADD",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SUB",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLT",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLTU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "XOR",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRA",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "OR",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AND",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FENCE",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FENCE_I",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ECALL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "EBREAK",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "URET",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRET",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "MRET",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "WFI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SFENCE.VMA",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRS",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRC",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRWI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRSI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRCI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "MUL",
+ "size" : 32,
+ "delay" : 5
+ },
+ {
+ "name" : "MULH",
+ "size" : 32,
+ "delay" : 5
+ },
+ {
+ "name" : "MULHSU",
+ "size" : 32,
+ "delay" : 5
+ },
+ {
+ "name" : "MULHU",
+ "size" : 32,
+ "delay" : 5
+ },
+ {
+ "name" : "DIV",
+ "size" : 32,
+ "delay" : 10
+ },
+ {
+ "name" : "DIVU",
+ "size" : 32,
+ "delay" : 10
+ },
+ {
+ "name" : "REM",
+ "size" : 32,
+ "delay" : 10
+ },
+ {
+ "name" : "REMU",
+ "size" : 32,
+ "delay" : 10
+ },
+ {
+ "name" : "LR.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SC.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOSWAP.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOADD.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOXOR.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOAND.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOOR.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMIN.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMAX.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMINU.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMAXU.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "C.ADDI4SPN",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.LW",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.SW",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.ADDI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.NOP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.JAL",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.LI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.LUI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.ADDI16SP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.SRLI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.SRAI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.ANDI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.SUB",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.XOR",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.OR",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.AND",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.J",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.BEQZ",
+ "size" : 16,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "C.BNEZ",
+ "size" : 16,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "C.SLLI",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.LWSP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.MV",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.JR",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.ADD",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.JALR",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.EBREAK",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "C.SWSP",
+ "size" : 16,
+ "delay" : 1
+ },
+ {
+ "name" : "DII",
+ "size" : 16,
+ "delay" : 1
+ }
+ ],
+ "RV64IA" : [
+ {
+ "name" : "LWU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LD",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SD",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLLI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRLI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRAI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ADDIW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLLIW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRLIW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRAIW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ADDW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SUBW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLLW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRLW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRAW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LUI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AUIPC",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "JAL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "JALR",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "BEQ",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BNE",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BLT",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BGE",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BLTU",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "BGEU",
+ "size" : 32,
+ "delay" : [1, 3]
+ },
+ {
+ "name" : "LB",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LH",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LBU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LHU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SB",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SH",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ADDI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLTI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLTIU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "XORI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ORI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ANDI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ADD",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SUB",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLT",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SLTU",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "XOR",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRA",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "OR",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AND",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FENCE",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "FENCE_I",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "ECALL",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "EBREAK",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "URET",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SRET",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "MRET",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "WFI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SFENCE.VMA",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRW",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRS",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRC",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRWI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRSI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "CSRRCI",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LR.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SC.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOSWAP.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOADD.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOXOR.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOAND.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOOR.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMIN.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMAX.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMINU.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMAXU.D",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "LR.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "SC.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOSWAP.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOADD.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOXOR.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOAND.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOOR.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMIN.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMAX.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMINU.W",
+ "size" : 32,
+ "delay" : 1
+ },
+ {
+ "name" : "AMOMAXU.W",
+ "size" : 32,
+ "delay" : 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/dbt-core b/dbt-core
index 23dbab0..393c374 160000
--- a/dbt-core
+++ b/dbt-core
@@ -1 +1 @@
-Subproject commit 23dbab0b768d122c492110d1db34408e9ae787f3
+Subproject commit 393c374cac4950e629036dda1615abedf866961f
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/etc/dbt-riscv Debug hello gdb.launch b/etc/dbt-riscv Debug hello gdb.launch
index 6079ecd..2f53e11 100644
--- a/etc/dbt-riscv Debug hello gdb.launch
+++ b/etc/dbt-riscv Debug hello gdb.launch
@@ -19,7 +19,7 @@
-
+
diff --git a/etc/dbt-riscv Debug hello w plugin.launch b/etc/dbt-riscv Debug hello w plugin.launch
new file mode 100644
index 0000000..f46628e
--- /dev/null
+++ b/etc/dbt-riscv Debug hello w plugin.launch
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/etc/dbt-riscv SC Debug hello.launch b/etc/dbt-riscv SC Debug hello.launch
index ab45f89..c1650db 100644
--- a/etc/dbt-riscv SC Debug hello.launch
+++ b/etc/dbt-riscv SC Debug hello.launch
@@ -19,7 +19,7 @@
-
+
diff --git a/etc/dbt-riscv dhrystone.launch b/etc/dbt-riscv dhrystone.launch
new file mode 100644
index 0000000..a666818
--- /dev/null
+++ b/etc/dbt-riscv dhrystone.launch
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/riscv.sc/CMakeLists.txt b/riscv.sc/CMakeLists.txt
index e022264..1351b5a 100644
--- a/riscv.sc/CMakeLists.txt
+++ b/riscv.sc/CMakeLists.txt
@@ -68,7 +68,7 @@ include_directories(
add_dependent_subproject(dbt-core)
add_dependent_subproject(sc-components)
-add_dependent_header(util)
+add_dependent_subproject(riscv)
include_directories(
${PROJECT_SOURCE_DIR}/incl
diff --git a/riscv.sc/src/CMakeLists.txt b/riscv.sc/src/CMakeLists.txt
index 348b663..4e11fc5 100644
--- a/riscv.sc/src/CMakeLists.txt
+++ b/riscv.sc/src/CMakeLists.txt
@@ -41,6 +41,7 @@ add_executable(${APPLICATION_NAME} ${APP_SOURCES})
target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME})
target_link_libraries(${APPLICATION_NAME} risc-v)
target_link_libraries(${APPLICATION_NAME} dbt-core)
+target_link_libraries(${APPLICATION_NAME} softfloat)
target_link_libraries(${APPLICATION_NAME} sc-components)
target_link_libraries(${APPLICATION_NAME} ${CONAN_LIBS_SEASOCKS})
target_link_libraries(${APPLICATION_NAME} external)
diff --git a/riscv.sc/src/sysc/core_complex.cpp b/riscv.sc/src/sysc/core_complex.cpp
index 44e1b63..5d673b4 100644
--- a/riscv.sc/src/sysc/core_complex.cpp
+++ b/riscv.sc/src/sysc/core_complex.cpp
@@ -103,7 +103,9 @@ public:
base_type::hart_state& get_state() { return this->state; }
- void notify_phase(exec_phase) override;
+ void notify_phase(exec_phase p) override {
+ if(p == ISTART) owner->sync(this->reg.icount+cycle_offset);
+ }
sync_type needed_sync() const override { return PRE_SYNC; }
@@ -131,9 +133,12 @@ public:
return owner->write_mem_dbg(addr.val, length, data) ? Ok : Err;
else{
auto res = owner->write_mem(addr.val, length, data) ? Ok : Err;
- // TODO: this is an ugly hack (clear MTIP on mtimecmp write), needs to be fixed
- if(addr.val==0x2004000)
- this->csr[arch::mip] &= ~(1ULL<<7);
+ // clear MTIP on mtimecmp write
+ if(addr.val==0x2004000){
+ reg_t val;
+ this->read_csr(arch::mip, val);
+ this->write_csr(arch::mip, val & ~(1ULL<<7));
+ }
return res;
}
}
@@ -198,11 +203,6 @@ int cmd_sysc(int argc, char* argv[], debugger::out_func of, debugger::data_func
}
-void core_wrapper::notify_phase(exec_phase p) {
- if(p == ISTART)
- owner->sync(this->reg.icount+cycle_offset);
-}
-
core_complex::core_complex(sc_core::sc_module_name name)
: sc_core::sc_module(name)
, NAMED(initiator)
diff --git a/riscv/CMakeLists.txt b/riscv/CMakeLists.txt
index 8db683b..b07998d 100644
--- a/riscv/CMakeLists.txt
+++ b/riscv/CMakeLists.txt
@@ -41,30 +41,14 @@ message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
llvm_map_components_to_libnames(llvm_libs support core mcjit x86codegen x86asmparser)
-find_package(SystemC)
-if(SystemC_FOUND)
- add_definitions(-DWITH_SYSTEMC)
- include_directories(${SystemC_INCLUDE_DIRS})
- link_directories(${SystemC_LIBRARY_DIRS})
-else(SystemC_FOUND)
- message( FATAL_ERROR "SystemC library not found." )
-endif(SystemC_FOUND)
-
-if(SCV_FOUND)
- add_definitions(-DWITH_SCV)
- link_directories(${SCV_LIBRARY_DIRS})
-endif(SCV_FOUND)
-
# This sets the include directory for the reference project. This is the -I flag in gcc.
include_directories(
${PROJECT_SOURCE_DIR}/incl
+ ${SOFTFLOAT_INCLUDE_DIRS}
${LLVM_INCLUDE_DIRS}
)
-
add_dependent_subproject(dbt-core)
add_dependent_subproject(sc-components)
-add_dependent_header(util)
-
include_directories(
${PROJECT_SOURCE_DIR}/incl
${PROJECT_SOURCE_DIR}/../external/elfio
diff --git a/riscv/gen_input/RV32C.core_desc b/riscv/gen_input/RV32C.core_desc
index 59bc051..fba428c 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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ }
+ 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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ }
+ 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]{32};
+ }
+ }
+}
+
+InsructionSet RV32DC extends RV32IC{
constants {
XLEN, FLEN
}
@@ -211,32 +268,50 @@ InsructionSet RV32CF extends RV32CI {
instructions{
C.FLD { //(RV32/64)
encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7: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[64] <= MEM[offs]{64};
+ if(FLEN==64)
+ F[rd_idx] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd_idx] <= (upper<<64) | res;
+ }
}
- 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;
+ 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]{64}<=F[rs2_idx]{64};
}
- 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;
+ args_disass:"f%rd$d, %uimm%(x2)";
+ val x2_idx[5] <= 2;
+ val offs[XLEN] <= X[x2_idx]+uimm;
+ val res[64] <= MEM[offs]{64};
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | zext(res, FLEN);
+ }
}
C.FSDSP {//(RV32/64)
encoding:b101 | uimm[5:3] | uimm[8: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]{64}<=F[rs2]{64};
}
- 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 +359,7 @@ InsructionSet RV64CI extends RV32CI {
}
}
-InsructionSet RV128CI extends RV64CI {
+InsructionSet RV128IC extends RV64IC {
constants {
XLEN
}
diff --git a/riscv/gen_input/RV32D.core_desc b/riscv/gen_input/RV32D.core_desc
new file mode 100644
index 0000000..56c1262
--- /dev/null
+++ b/riscv/gen_input/RV32D.core_desc
@@ -0,0 +1,298 @@
+import "RV32IBase.core_desc"
+
+InsructionSet RV32D extends RV32IBase{
+ constants {
+ FLEN, FFLAG_MASK := 0x1f
+ }
+ registers {
+ [31:0] F[FLEN], FCSR[32]
+ }
+ instructions{
+ FLD {
+ encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000111;
+ args_disass:"f%rd$d, %imm%(x%rs1$d)";
+ val offs[XLEN] <= X[rs1]+imm;
+ val res[64] <= MEM[offs]{64};
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ }
+ FSD {
+ encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100111;
+ args_disass:"f%rs2$d, %imm%(x%rs1$d)";
+ val offs[XLEN] <= X[rs1]+imm;
+ MEM[offs]{64}<=F[rs2]{64};
+ }
+ FMADD.D {
+ encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011;
+ 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[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(0, 64), choose(rm<7, rm{8}, FCSR{8}));
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FMSUB.D {
+ encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111;
+ 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[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8}));
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FNMADD.D {
+ encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111;
+ 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[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8}));
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FNMSUB.D {
+ encoding: rs3[4:0] | b01 | 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[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8}));
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FADD.D {
+ encoding: b0000001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
+ // F[rd]f <= F[rs1]f + F[rs2]f;
+ val res[64] <= fdispatch_fadd_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FSUB.D {
+ encoding: b0000101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
+ // F[rd]f <= F[rs1]f - F[rs2]f;
+ val res[64] <= fdispatch_fsub_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FMUL.D {
+ encoding: b0001001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
+ // F[rd]f <= F[rs1]f * F[rs2]f;
+ val res[64] <= fdispatch_fmul_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FDIV.D {
+ encoding: b0001101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"x%rd$d, f%rs1$d, f%rs2$d";
+ // F[rd]f <= F[rs1]f / F[rs2]f;
+ val res[64] <= fdispatch_fdiv_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FSQRT.D {
+ encoding: b0101101 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"x%rd$d, f%rs1$d";
+ //F[rd]f<=sqrt(F[rs1]f);
+ val res[64] <= fdispatch_fsqrt_d(F[rs1]{64}, choose(rm<7, rm{8}, FCSR{8}));
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FSGNJ.D {
+ encoding: b0010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
+ args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
+ val res[64] <= (F[rs1]{64} & 0x7fffffff) | (F[rs2]{64} & 0x80000000);
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ }
+ FSGNJN.D {
+ encoding: b0010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
+ args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
+ val res[64] <= (F[rs1]{64} & 0x7fffffff) | (~F[rs2]{64} & 0x80000000);
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ }
+ FSGNJX.D {
+ encoding: b0010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
+ args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
+ val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & 0x80000000);
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ }
+ FMIN.D {
+ encoding: b0010101 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
+ args_disass:"f%rd$d, f%rs1$d, f%rs2$d";
+ //F[rd]f<= choose(F[rs1]fF[rs2]f, F[rs1]f, F[rs2]f);
+ val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32));
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FCVT.S.D {
+ encoding: b0100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"f%rd$d, f%rs1$d";
+ val res[32] <= fdispatch_fconv_d2f(F[rs1], rm{8});
+ // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= upper<<32 | zext(res, FLEN);
+ }
+ FCVT.D.S {
+ encoding: b0100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"f%rd$d, f%rs1$d";
+ val res[64] <= fdispatch_fconv_f2d(F[rs1]{32}, rm{8});
+ if(FLEN==64){
+ F[rd] <= res;
+ } else {
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ }
+ FEQ.D {
+ encoding: b1010001 | 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_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32));
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FLT.D {
+ encoding: b1010001 | 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_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32));
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FLE.D {
+ encoding: b1010001 | 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_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32));
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FCLASS.D {
+ encoding: b1110001 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011;
+ args_disass:"x%rd$d, f%rs1$d";
+ X[rd]<=fdispatch_fclass_d(F[rs1]{64});
+ }
+ FCVT.W.D {
+ encoding: b1100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"x%rd$d, f%rs1$d";
+ X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN);
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FCVT.WU.D {
+ encoding: b1100001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"x%rd$d, f%rs1$d";
+ X[rd]<= zext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN);
+ val flags[32] <= fdispatch_fget_flags();
+ FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
+ }
+ FCVT.D.W {
+ encoding: b1101001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"f%rd$d, x%rs1$d";
+ val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8});
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ }
+ FCVT.D.WU {
+ encoding: b1101001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
+ args_disass:"f%rd$d, x%rs1$d";
+ val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8});
+ if(FLEN==64)
+ F[rd] <= res;
+ else { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<64) | res;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/riscv/gen_input/RV32F.core_desc b/riscv/gen_input/RV32F.core_desc
index 6efb8fb..a5324fd 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 := 0x1f
}
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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
}
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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ 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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ 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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ 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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ 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:"f%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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ 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:"f%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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ 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:"f%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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ 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:"f%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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ 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:"f%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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ 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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
}
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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
}
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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
}
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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ 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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
}
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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(res, FLEN);
+ }
+ }
+ 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 { // NaN boxing
+ val upper[FLEN] <= -1;
+ F[rd] <= (upper<<32) | zext(X[rs1], FLEN);
+ }
}
}
}
\ No newline at end of file
diff --git a/riscv/gen_input/RV32IBase.core_desc b/riscv/gen_input/RV32IBase.core_desc
index bbf4a79..22f02f7 100644
--- a/riscv/gen_input/RV32IBase.core_desc
+++ b/riscv/gen_input/RV32IBase.core_desc
@@ -1,12 +1,12 @@
InsructionSet RV32IBase {
constants {
XLEN,
- XLEN_BIT_MASK,
PCLEN,
- fence,
- fencei,
- fencevmal,
- fencevmau
+ XLEN_BIT_MASK:=0x1f,
+ fence:=0,
+ fencei:=1,
+ fencevmal:=2,
+ fencevmau:=3
}
address_spaces {
diff --git a/riscv/gen_input/RV32M.core_desc b/riscv/gen_input/RV32M.core_desc
index d8a15dd..2296923 100644
--- a/riscv/gen_input/RV32M.core_desc
+++ b/riscv/gen_input/RV32M.core_desc
@@ -2,14 +2,14 @@ import "RV32IBase.core_desc"
InsructionSet RV32M extends RV32IBase {
constants {
- XLEN2
+ MAXLEN:=128
}
instructions{
MUL{
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
- val res[XLEN2] <= zext(X[rs1], XLEN2) * zext(X[rs2], XLEN2);
+ val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res , XLEN);
}
}
@@ -17,7 +17,7 @@ InsructionSet RV32M extends RV32IBase {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
- val res[XLEN2] <= sext(X[rs1], XLEN2) * sext(X[rs2], XLEN2);
+ val res[MAXLEN] <= sext(X[rs1], MAXLEN) * sext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN);
}
}
@@ -25,7 +25,7 @@ InsructionSet RV32M extends RV32IBase {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
- val res[XLEN2] <= sext(X[rs1], XLEN2) * zext(X[rs2], XLEN2);
+ val res[MAXLEN] <= sext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN);
}
}
@@ -33,7 +33,7 @@ InsructionSet RV32M extends RV32IBase {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d";
if(rd != 0){
- val res[XLEN2] <= zext(X[rs1], XLEN2) * zext(X[rs2], XLEN2);
+ val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN);
}
}
@@ -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..b5d82fe 100644
--- a/riscv/gen_input/minres_rv.core_desc
+++ b/riscv/gen_input/minres_rv.core_desc
@@ -2,24 +2,34 @@ import "RV32IBase.core_desc"
import "RV32M.core_desc"
import "RV32A.core_desc"
import "RV32C.core_desc"
+import "RV32F.core_desc"
+import "RV32D.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;
- XLEN2:=64;
- XLEN_BIT_MASK:=0x1f;
PCLEN:=32;
- fence:=0;
- fencei:=1;
- fencevmal:=2;
- fencevmau:=3;
+ // definitions for the architecture wrapper
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
- MISA_VAL:=0b01000000000101000001000100000001;
+ MISA_VAL:=0b01000000000101000001000100000101;
+ PGSIZE := 4096; //1 << 12;
+ PGMASK := 4095; //PGSIZE-1
+ }
+}
+
+Core RV32GC provides RV32IBase, RV32M, RV32A, RV32IC, RV32F, RV32FC, RV32D, RV32DC {
+ constants {
+ XLEN:=32;
+ FLEN:=64;
+ PCLEN:=32;
+ // definitions for the architecture wrapper
+ // XL ZYXWVUTSRQPONMLKJIHGFEDCBA
+ MISA_VAL:=0b01000000000101000001000100101101;
PGSIZE := 4096; //1 << 12;
PGMASK := 4095; //PGSIZE-1
}
@@ -30,13 +40,8 @@ Core RV64IA provides RV64IBase, RV64A, RV32A {
template:"vm_riscv.in.cpp";
constants {
XLEN:=64;
- XLEN2:=128;
- XLEN_BIT_MASK:=0x3f;
PCLEN:=64;
- fence:=0;
- fencei:=1;
- fencevmal:=2;
- fencevmau:=3;
+ // definitions for the architecture wrapper
// XL ZYXWVUTSRQPONMLKJIHGFEDCBA
MISA_VAL:=0b10000000000001000000000100000001;
PGSIZE := 4096; //1 << 12;
diff --git a/riscv/gen_input/templates/incl-CORENAME.h.gtl b/riscv/gen_input/templates/incl-CORENAME.h.gtl
index 2b5686a..5e53476 100644
--- a/riscv/gen_input/templates/incl-CORENAME.h.gtl
+++ b/riscv/gen_input/templates/incl-CORENAME.h.gtl
@@ -56,6 +56,8 @@ struct traits<${coreDef.name.toLowerCase()}> {
enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}};
+ constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0};
+
enum reg_e {<%
allRegs.each { reg ->
if( reg instanceof RegisterFile) {
@@ -78,8 +80,6 @@ struct traits<${coreDef.name.toLowerCase()}> {
using addr_t = uint${addrDataWidth}_t;
- using code_word_t = uint${addrDataWidth}_t; //TODO: check removal
-
using virt_addr_t = iss::typed_addr_t;
using phys_addr_t = iss::typed_addr_t;
@@ -99,7 +99,6 @@ struct traits<${coreDef.name.toLowerCase()}> {
enum sreg_flag_e {FLAGS};
enum mem_type_e {${allSpaces.collect{s -> s.name}.join(', ')}};
-
};
struct ${coreDef.name.toLowerCase()}: public arch_if {
@@ -112,8 +111,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 +155,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..d4552cc 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 *, unsigned);
+}
+}
+
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, traits::FP_REGS_SIZE);
+ }
+
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));
@@ -101,7 +112,6 @@ protected:
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);
}
@@ -310,8 +320,6 @@ template inline void vm_impl::gen_trap_check(llvm::BasicBl
bb, this->trap_blk, 1);
}
-} // namespace ${coreDef.name.toLowerCase()}
-
template <>
std::unique_ptr create(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
std::unique_ptr<${coreDef.name.toLowerCase()}::vm_impl> ret =
diff --git a/riscv/src/internal/vm_riscv.in.cpp b/riscv/gen_input/templates/vm_riscv.in.cpp
similarity index 100%
rename from riscv/src/internal/vm_riscv.in.cpp
rename to riscv/gen_input/templates/vm_riscv.in.cpp
diff --git a/riscv/incl/iss/arch/riscv_hart_msu_vp.h b/riscv/incl/iss/arch/riscv_hart_msu_vp.h
index 64f9381..9e820ce 100644
--- a/riscv/incl/iss/arch/riscv_hart_msu_vp.h
+++ b/riscv/incl/iss/arch/riscv_hart_msu_vp.h
@@ -48,13 +48,14 @@
#include
#include
#include
+#include
namespace iss {
namespace arch {
enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 };
-enum csr_name {
+enum riscv_csr {
/* user-level CSR */
// User Trap Setup
ustatus = 0x000,
@@ -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..0f9d93e
--- /dev/null
+++ b/riscv/incl/iss/arch/rv32gc.h
@@ -0,0 +1,277 @@
+////////////////////////////////////////////////////////////////////////////////
+// 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=64, PCLEN=32, MISA_VAL=1075056941, PGSIZE=4096, PGMASK=4095};
+
+ constexpr static unsigned FP_REGS_SIZE = 64;
+
+ 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,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,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,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,416,424}};
+ 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};
+};
+
+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;
+ uint64_t F0 = 0;
+ uint64_t F1 = 0;
+ uint64_t F2 = 0;
+ uint64_t F3 = 0;
+ uint64_t F4 = 0;
+ uint64_t F5 = 0;
+ uint64_t F6 = 0;
+ uint64_t F7 = 0;
+ uint64_t F8 = 0;
+ uint64_t F9 = 0;
+ uint64_t F10 = 0;
+ uint64_t F11 = 0;
+ uint64_t F12 = 0;
+ uint64_t F13 = 0;
+ uint64_t F14 = 0;
+ uint64_t F15 = 0;
+ uint64_t F16 = 0;
+ uint64_t F17 = 0;
+ uint64_t F18 = 0;
+ uint64_t F19 = 0;
+ uint64_t F20 = 0;
+ uint64_t F21 = 0;
+ uint64_t F22 = 0;
+ uint64_t F23 = 0;
+ uint64_t F24 = 0;
+ uint64_t F25 = 0;
+ uint64_t F26 = 0;
+ uint64_t F27 = 0;
+ uint64_t F28 = 0;
+ uint64_t F29 = 0;
+ uint64_t F30 = 0;
+ uint64_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..571b758 100644
--- a/riscv/incl/iss/arch/rv32imac.h
+++ b/riscv/incl/iss/arch/rv32imac.h
@@ -48,7 +48,9 @@ struct traits {
constexpr static char const* const core_type = "RV32IMAC";
- enum constants {XLEN=32, XLEN2=64, XLEN_BIT_MASK=31, PCLEN=32, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=1075056897, PGSIZE=4096, PGMASK=4095};
+ enum constants {XLEN=32, PCLEN=32, MISA_VAL=1075056901, PGSIZE=4096, PGMASK=4095};
+
+ constexpr static unsigned FP_REGS_SIZE = 0;
enum reg_e {
X0,
@@ -117,7 +119,6 @@ struct traits {
enum sreg_flag_e {FLAGS};
enum mem_type_e {MEM, CSR, FENCE, RES};
-
};
struct rv32imac: public arch_if {
@@ -198,6 +199,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..10a8989 100644
--- a/riscv/incl/iss/arch/rv64ia.h
+++ b/riscv/incl/iss/arch/rv64ia.h
@@ -48,7 +48,9 @@ struct traits {
constexpr static char const* const core_type = "RV64IA";
- enum constants {XLEN=64, XLEN2=128, XLEN_BIT_MASK=63, PCLEN=64, fence=0, fencei=1, fencevmal=2, fencevmau=3, MISA_VAL=2147746049, PGSIZE=4096, PGMASK=4095};
+ enum constants {XLEN=64, PCLEN=64, MISA_VAL=2147746049, PGSIZE=4096, PGMASK=4095};
+
+ constexpr static unsigned FP_REGS_SIZE = 0;
enum reg_e {
X0,
@@ -117,7 +119,6 @@ struct traits {
enum sreg_flag_e {FLAGS};
enum mem_type_e {MEM, CSR, FENCE, RES};
-
};
struct rv64ia: public arch_if {
@@ -198,6 +199,10 @@ protected:
} reg;
std::array addr_mode;
+
+
+ uint32_t get_fcsr(){return 0;}
+ void set_fcsr(uint32_t val){}
};
diff --git a/riscv/src/CMakeLists.txt b/riscv/src/CMakeLists.txt
index 8b73954..229b067 100644
--- a/riscv/src/CMakeLists.txt
+++ b/riscv/src/CMakeLists.txt
@@ -1,11 +1,11 @@
# library files
FILE(GLOB RiscVHeaders *.h)
+FILE(GLOB IssSources iss/*.cpp internal/*.cpp)
+
+
set(LIB_HEADERS ${RiscVHeaders} )
set(LIB_SOURCES
- iss/rv32imac.cpp
- iss/rv64ia.cpp
- internal/vm_rv32imac.cpp
- internal/vm_rv64ia.cpp
+ ${IssSources}
plugin/instruction_count.cpp
plugin/cycle_estimate.cpp
)
@@ -35,6 +35,7 @@ add_executable(${APPLICATION_NAME} ${APP_SOURCES})
# Links the target exe against the libraries
target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME})
target_link_libraries(${APPLICATION_NAME} dbt-core)
+target_link_libraries(${APPLICATION_NAME} softfloat)
target_link_libraries(${APPLICATION_NAME} sc-components)
target_link_libraries(${APPLICATION_NAME} external)
target_link_libraries(${APPLICATION_NAME} ${llvm_libs})
diff --git a/riscv/src/internal/fp_functions.cpp b/riscv/src/internal/fp_functions.cpp
new file mode 100644
index 0000000..34c1bac
--- /dev/null
+++ b/riscv/src/internal/fp_functions.cpp
@@ -0,0 +1,458 @@
+////////////////////////////////////////////////////////////////////////////////
+// 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"
+}
+
+#include
+
+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, uint32_t flen) {
+ if(flen){
+ 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(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));
+ if(flen>32){
+ FDECL(fconv_d2f, INT_TYPE(32), INT_TYPE(64), INT_TYPE(8));
+ FDECL(fconv_f2d, INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
+ FDECL(fadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
+ FDECL(fsub_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
+ FDECL(fmul_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
+ FDECL(fdiv_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
+ FDECL(fsqrt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(8));
+ FDECL(fcmp_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32));
+ FDECL(fcvt_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
+ FDECL(fmadd_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32), INT_TYPE(8));
+ FDECL(fsel_d, INT_TYPE(64), INT_TYPE(64), INT_TYPE(64), INT_TYPE(32));
+ FDECL(fclass_d, INT_TYPE(64), INT_TYPE(64));
+ }
+ }
+}
+
+}
+}
+}
+
+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 ^= 1ULL<<31;
+ return res.v;
+}
+
+uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op) {
+ softfloat_exceptionFlags = 0;
+ bool v1_nan = (v1 & defaultNaNF32UI) == defaultNaNF32UI;
+ bool v2_nan = (v2 & defaultNaNF32UI) == defaultNaNF32UI;
+ 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;
+}
+
+uint32_t fconv_d2f(uint64_t v1, uint8_t mode){
+ softfloat_roundingMode=rmm_map[mode&0x7];
+ bool nan = (v1 & defaultNaNF64UI)==defaultNaNF64UI;
+ if(nan){
+ return defaultNaNF32UI;
+ } else {
+ float32_t res = f64_to_f32(float64_t{v1});
+ return res.v;
+ }
+}
+
+uint64_t fconv_f2d(uint32_t v1, uint8_t mode){
+ bool nan = (v1 & defaultNaNF32UI)==defaultNaNF32UI;
+ if(nan){
+ return defaultNaNF64UI;
+ } else {
+ softfloat_roundingMode=rmm_map[mode&0x7];
+ float64_t res = f32_to_f64(float32_t{v1});
+ return res.v;
+ }
+}
+
+uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) {
+ bool nan = (v1&defaultNaNF32UI)==quiet_nan32;
+ bool snan = softfloat_isSigNaNF32UI(v1);
+ float64_t v1f{v1},v2f{v2};
+ softfloat_roundingMode=rmm_map[mode&0x7];
+ softfloat_exceptionFlags=0;
+ float64_t r =f64_add(v1f, v2f);
+ return r.v;
+}
+
+uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) {
+ float64_t v1f{v1},v2f{v2};
+ softfloat_roundingMode=rmm_map[mode&0x7];
+ softfloat_exceptionFlags=0;
+ float64_t r=f64_sub(v1f, v2f);
+ return r.v;
+}
+
+uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) {
+ float64_t v1f{v1},v2f{v2};
+ softfloat_roundingMode=rmm_map[mode&0x7];
+ softfloat_exceptionFlags=0;
+ float64_t r=f64_mul(v1f, v2f);
+ return r.v;
+}
+
+uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) {
+ float64_t v1f{v1},v2f{v2};
+ softfloat_roundingMode=rmm_map[mode&0x7];
+ softfloat_exceptionFlags=0;
+ float64_t r=f64_div(v1f, v2f);
+ return r.v;
+}
+
+uint64_t fsqrt_d(uint64_t v1, uint8_t mode) {
+ float64_t v1f{v1};
+ softfloat_roundingMode=rmm_map[mode&0x7];
+ softfloat_exceptionFlags=0;
+ float64_t r=f64_sqrt(v1f);
+ return r.v;
+}
+
+uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op) {
+ float64_t v1f{v1},v2f{v2};
+ softfloat_exceptionFlags=0;
+ bool nan = (v1&defaultNaNF64UI)==quiet_nan32 || (v2&defaultNaNF64UI)==quiet_nan32;
+ bool snan = softfloat_isSigNaNF64UI(v1) || softfloat_isSigNaNF64UI(v2);
+ switch(op){
+ case 0:
+ if(nan | snan){
+ if(snan) softfloat_raiseFlags(softfloat_flag_invalid);
+ return 0;
+ } else
+ return f64_eq(v1f,v2f )?1:0;
+ case 1:
+ if(nan | snan){
+ softfloat_raiseFlags(softfloat_flag_invalid);
+ return 0;
+ } else
+ return f64_le(v1f,v2f )?1:0;
+ case 2:
+ if(nan | snan){
+ softfloat_raiseFlags(softfloat_flag_invalid);
+ return 0;
+ } else
+ return f64_lt(v1f,v2f )?1:0;
+ default:
+ break;
+ }
+ return -1;
+}
+
+uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) {
+ float64_t v1f{v1};
+ softfloat_exceptionFlags=0;
+ float64_t r;
+ int32_t res;
+ switch(op){
+ case 0: //w->s, fp to int32
+ res = f64_to_i64(v1f,rmm_map[mode&0x7],true);
+ return (uint64_t)res;
+ case 1: //wu->s
+ return f64_to_ui64(v1f,rmm_map[mode&0x7],true);
+ case 2: //s->w
+ r=i64_to_f64(v1);
+ return r.v;
+ case 3: //s->wu
+ r=ui64_to_f64(v1);
+ return r.v;
+ }
+ return 0;
+}
+
+uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_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;
+ float64_t res = softfloat_mulAddF64(v1, v2, v3, op&0x1);
+ if(op>1) res.v ^= 1ULL<<63;
+ return res.v;
+}
+
+uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op) {
+ softfloat_exceptionFlags = 0;
+ bool v1_nan = (v1 & defaultNaNF64UI) == defaultNaNF64UI;
+ bool v2_nan = (v2 & defaultNaNF64UI) == defaultNaNF64UI;
+ bool v1_snan = softfloat_isSigNaNF64UI(v1);
+ bool v2_snan = softfloat_isSigNaNF64UI(v2);
+ if (v1_snan || v2_snan) softfloat_raiseFlags(softfloat_flag_invalid);
+ if (v1_nan || v1_snan)
+ return (v2_nan || v2_snan) ? defaultNaNF64UI : v2;
+ else
+ if (v2_nan || v2_snan)
+ return v1;
+ else {
+ if ((v1 & std::numeric_limits::max()) == 0 && (v2 & std::numeric_limits::max()) == 0) {
+ return op == 0 ?
+ ((v1 & std::numeric_limits::min()) ? v1 : v2) :
+ ((v1 & std::numeric_limits::min()) ? v2 : v1);
+ } else {
+ float64_t v1f{ v1 }, v2f{ v2 };
+ return op == 0 ?
+ (f64_lt(v1f, v2f) ? v1 : v2) :
+ (f64_lt(v1f, v2f) ? v2 : v1);
+ }
+ }
+}
+
+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..5514005
--- /dev/null
+++ b/riscv/src/internal/vm_rv32gc.cpp
@@ -0,0 +1,8415 @@
+////////////////////////////////////////////////////////////////////////////////
+// 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 *, unsigned);
+}
+}
+
+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, traits::FP_REGS_SIZE);
+ }
+
+ 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 FLD */
+ {32, 0b00000000000000000011000000000111, 0b00000000000000000111000001111111, &this_class::__fld},
+ /* instruction FSD */
+ {32, 0b00000000000000000011000000100111, 0b00000000000000000111000001111111, &this_class::__fsd},
+ /* instruction FMADD.D */
+ {32, 0b00000010000000000000000001000011, 0b00000110000000000000000001111111, &this_class::__fmadd_d},
+ /* instruction FMSUB.D */
+ {32, 0b00000010000000000000000001000111, 0b00000110000000000000000001111111, &this_class::__fmsub_d},
+ /* instruction FNMADD.D */
+ {32, 0b00000010000000000000000001001111, 0b00000110000000000000000001111111, &this_class::__fnmadd_d},
+ /* instruction FNMSUB.D */
+ {32, 0b00000010000000000000000001001011, 0b00000110000000000000000001111111, &this_class::__fnmsub_d},
+ /* instruction FADD.D */
+ {32, 0b00000010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fadd_d},
+ /* instruction FSUB.D */
+ {32, 0b00001010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fsub_d},
+ /* instruction FMUL.D */
+ {32, 0b00010010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fmul_d},
+ /* instruction FDIV.D */
+ {32, 0b00011010000000000000000001010011, 0b11111110000000000000000001111111, &this_class::__fdiv_d},
+ /* instruction FSQRT.D */
+ {32, 0b01011010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fsqrt_d},
+ /* instruction FSGNJ.D */
+ {32, 0b00100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnj_d},
+ /* instruction FSGNJN.D */
+ {32, 0b00100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjn_d},
+ /* instruction FSGNJX.D */
+ {32, 0b00100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__fsgnjx_d},
+ /* instruction FMIN.D */
+ {32, 0b00101010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fmin_d},
+ /* instruction FMAX.D */
+ {32, 0b00101010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__fmax_d},
+ /* instruction FCVT.S.D */
+ {32, 0b01000000000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_s_d},
+ /* instruction FCVT.D.S */
+ {32, 0b01000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_s},
+ /* instruction FEQ.D */
+ {32, 0b10100010000000000010000001010011, 0b11111110000000000111000001111111, &this_class::__feq_d},
+ /* instruction FLT.D */
+ {32, 0b10100010000000000001000001010011, 0b11111110000000000111000001111111, &this_class::__flt_d},
+ /* instruction FLE.D */
+ {32, 0b10100010000000000000000001010011, 0b11111110000000000111000001111111, &this_class::__fle_d},
+ /* instruction FCLASS.D */
+ {32, 0b11100010000000000001000001010011, 0b11111111111100000111000001111111, &this_class::__fclass_d},
+ /* instruction FCVT.W.D */
+ {32, 0b11000010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_w_d},
+ /* instruction FCVT.WU.D */
+ {32, 0b11000010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_wu_d},
+ /* instruction FCVT.D.W */
+ {32, 0b11010010000000000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_w},
+ /* instruction FCVT.D.WU */
+ {32, 0b11010010000100000000000001010011, 0b11111111111100000000000001111111, &this_class::__fcvt_d_wu},
+ /* instruction C.FLD */
+ {16, 0b0010000000000000, 0b1110000000000011, &this_class::__c_fld},
+ /* instruction C.FSD */
+ {16, 0b1010000000000000, 0b1110000000000011, &this_class::__c_fsd},
+ /* instruction C.FLDSP */
+ {16, 0b0010000000000010, 0b1110000000000011, &this_class::__c_fldsp},
+ /* instruction C.FSDSP */
+ {16, 0b1010000000000010, 0b1110000000000011, &this_class::__c_fsdsp},
+ }};
+
+ /* 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