aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--riscv/decode.h6
-rw-r--r--riscv/insn_template.cc27
-rw-r--r--riscv/processor.cc20
-rw-r--r--riscv/processor.h21
5 files changed, 55 insertions, 20 deletions
diff --git a/README.md b/README.md
index c1501c3..0b097ce 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ completion of the US transcontinental railway.
Spike supports the following RISC-V ISA features:
- RV32I and RV64I base ISAs, v2.1
+ - RV32E and RV64E base ISAs, v1.9
- Zifencei extension, v2.0
- Zicsr extension, v2.0
- M extension, v2.0
diff --git a/riscv/decode.h b/riscv/decode.h
index 3b3cf54..0365047 100644
--- a/riscv/decode.h
+++ b/riscv/decode.h
@@ -175,7 +175,8 @@ private:
#define MMU (*p->get_mmu())
#define STATE (*p->get_state())
#define FLEN (p->get_flen())
-#define READ_REG(reg) STATE.XPR[reg]
+#define CHECK_REG(reg) ((void) 0)
+#define READ_REG(reg) ({ CHECK_REG(reg); STATE.XPR[reg]; })
#define READ_FREG(reg) STATE.FPR[reg]
#define RD READ_REG(insn.rd())
#define RS1 READ_REG(insn.rs1())
@@ -184,7 +185,7 @@ private:
#define WRITE_RD(value) WRITE_REG(insn.rd(), value)
#ifndef RISCV_ENABLE_COMMITLOG
-# define WRITE_REG(reg, value) STATE.XPR.write(reg, value)
+# define WRITE_REG(reg, value) ({ CHECK_REG(reg); STATE.XPR.write(reg, value); })
# define WRITE_FREG(reg, value) DO_WRITE_FREG(reg, freg(value))
# define WRITE_VSTATUS
#else
@@ -197,6 +198,7 @@ private:
# define WRITE_REG(reg, value) ({ \
reg_t wdata = (value); /* value may have side effects */ \
STATE.log_reg_write[(reg) << 4] = {wdata, 0}; \
+ CHECK_REG(reg); \
STATE.XPR.write(reg, wdata); \
})
# define WRITE_FREG(reg, value) ({ \
diff --git a/riscv/insn_template.cc b/riscv/insn_template.cc
index b3dd330..e6a2f52 100644
--- a/riscv/insn_template.cc
+++ b/riscv/insn_template.cc
@@ -3,7 +3,7 @@
#include "insn_template.h"
#include "insn_macros.h"
-reg_t rv32_NAME(processor_t* p, insn_t insn, reg_t pc)
+reg_t rv32i_NAME(processor_t* p, insn_t insn, reg_t pc)
{
#define xlen 32
reg_t npc = sext_xlen(pc + insn_length(OPCODE));
@@ -13,7 +13,30 @@ reg_t rv32_NAME(processor_t* p, insn_t insn, reg_t pc)
return npc;
}
-reg_t rv64_NAME(processor_t* p, insn_t insn, reg_t pc)
+reg_t rv64i_NAME(processor_t* p, insn_t insn, reg_t pc)
+{
+ #define xlen 64
+ reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+ #include "insns/NAME.h"
+ trace_opcode(p, OPCODE, insn);
+ #undef xlen
+ return npc;
+}
+
+#undef CHECK_REG
+#define CHECK_REG(reg) require((reg) < 16)
+
+reg_t rv32e_NAME(processor_t* p, insn_t insn, reg_t pc)
+{
+ #define xlen 32
+ reg_t npc = sext_xlen(pc + insn_length(OPCODE));
+ #include "insns/NAME.h"
+ trace_opcode(p, OPCODE, insn);
+ #undef xlen
+ return npc;
+}
+
+reg_t rv64e_NAME(processor_t* p, insn_t insn, reg_t pc)
{
#define xlen 64
reg_t npc = sext_xlen(pc + insn_length(OPCODE));
diff --git a/riscv/processor.cc b/riscv/processor.cc
index ede80fe..b956f39 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -1042,11 +1042,13 @@ insn_func_t processor_t::decode_insn(insn_t insn)
size_t idx = insn.bits() % OPCODE_CACHE_SIZE;
insn_desc_t desc = opcode_cache[idx];
- if (unlikely(insn.bits() != desc.match || !desc.func(xlen))) {
+ bool rve = extension_enabled('E');
+
+ if (unlikely(insn.bits() != desc.match || !desc.func(xlen, rve))) {
// fall back to linear search
int cnt = 0;
insn_desc_t* p = &instructions[0];
- while ((insn.bits() & p->mask) != p->match || !desc.func(xlen))
+ while ((insn.bits() & p->mask) != p->match || !desc.func(xlen, rve))
p++, cnt++;
desc = *p;
@@ -1063,7 +1065,7 @@ insn_func_t processor_t::decode_insn(insn_t insn)
opcode_cache[idx].match = insn.bits();
}
- return desc.func(xlen);
+ return desc.func(xlen, rve);
}
void processor_t::register_insn(insn_desc_t desc)
@@ -1112,13 +1114,17 @@ void processor_t::register_base_instructions()
#undef DECLARE_INSN
#define DEFINE_INSN(name) \
- extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
- extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
+ extern reg_t rv32i_##name(processor_t*, insn_t, reg_t); \
+ extern reg_t rv64i_##name(processor_t*, insn_t, reg_t); \
+ extern reg_t rv32e_##name(processor_t*, insn_t, reg_t); \
+ extern reg_t rv64e_##name(processor_t*, insn_t, reg_t); \
register_insn((insn_desc_t){ \
name##_match, \
name##_mask, \
- rv32_##name, \
- rv64_##name});
+ rv32i_##name, \
+ rv64i_##name, \
+ rv32e_##name, \
+ rv64e_##name});
#include "insn_list.h"
#undef DEFINE_INSN
diff --git a/riscv/processor.h b/riscv/processor.h
index de896bf..35f8afc 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -29,14 +29,22 @@ struct insn_desc_t
{
insn_bits_t match;
insn_bits_t mask;
- insn_func_t rv32;
- insn_func_t rv64;
+ insn_func_t rv32i;
+ insn_func_t rv64i;
+ insn_func_t rv32e;
+ insn_func_t rv64e;
- insn_func_t func(int xlen) { return xlen == 64 ? rv64 : rv32; }
+ insn_func_t func(int xlen, bool rve)
+ {
+ if (rve)
+ return xlen == 64 ? rv64e : rv32e;
+ else
+ return xlen == 64 ? rv64i : rv32i;
+ }
static insn_desc_t illegal()
{
- return {0, 0, &illegal_instruction, &illegal_instruction};
+ return {0, 0, &illegal_instruction, &illegal_instruction, &illegal_instruction, &illegal_instruction};
}
};
@@ -603,9 +611,4 @@ public:
vectorUnit_t VU;
};
-#define REGISTER_INSN(proc, name, match, mask, archen) \
- extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
- extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
- proc->register_insn((insn_desc_t){match, mask, rv32_##name, rv64_##name,archen});
-
#endif