aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChih-Min Chao <chihmin.chao@sifive.com>2020-05-07 21:09:47 -0700
committerChih-Min Chao <chihmin.chao@sifive.com>2020-05-13 22:08:50 -0700
commit7e75ab9f7417a1c31b1f97bd69a9683251b5224a (patch)
treeac38830cb4aa8a400a00375ea05c8f53086d5e19
parent6fe796c4443749169a224358c62a2068d679126d (diff)
downloadspike-7e75ab9f7417a1c31b1f97bd69a9683251b5224a.zip
spike-7e75ab9f7417a1c31b1f97bd69a9683251b5224a.tar.gz
spike-7e75ab9f7417a1c31b1f97bd69a9683251b5224a.tar.bz2
rvv: amo pre-0.9
Signed-off-by: Chih-Min Chao <chihmin.chao@sifive.com>
-rw-r--r--riscv/decode.h52
-rw-r--r--riscv/insns/vamoadde_v.h2
-rw-r--r--riscv/insns/vamoande_v.h2
-rw-r--r--riscv/insns/vamomaxe_v.h2
-rw-r--r--riscv/insns/vamomaxue_v.h2
-rw-r--r--riscv/insns/vamomine_v.h2
-rw-r--r--riscv/insns/vamominue_v.h2
-rw-r--r--riscv/insns/vamoore_v.h2
-rw-r--r--riscv/insns/vamoswape_v.h2
-rw-r--r--riscv/insns/vamoxore_v.h2
-rw-r--r--riscv/mmu.h2
-rw-r--r--riscv/processor.cc5
-rw-r--r--riscv/riscv.mk.in12
-rw-r--r--spike_main/disasm.cc27
14 files changed, 116 insertions, 0 deletions
diff --git a/riscv/decode.h b/riscv/decode.h
index bf7d2ae..d4db8e7 100644
--- a/riscv/decode.h
+++ b/riscv/decode.h
@@ -112,6 +112,7 @@ public:
uint64_t rvc_rs2s() { return 8 + x(2, 3); }
uint64_t v_vm() { return x(25, 1); }
+ uint64_t v_wd() { return x(26, 1); }
uint64_t v_nf() { return x(29, 3); }
uint64_t v_simm5() { return xs(15, 5); }
uint64_t v_zimm5() { return x(15, 5); }
@@ -1705,6 +1706,57 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
p->VU.vstart = 0;
//
+// vector: amo
+//
+#define VI_AMO(op, type) \
+ require_vector; \
+ require_extension(EXT_ZVAMO); \
+ VI_CHECK_SSS(false); \
+ VI_DUPLICATE_VREG(insn.rs2(), P.VU.vlmax); \
+ const reg_t vl = P.VU.vl; \
+ const reg_t baseAddr = RS1; \
+ const reg_t vd = insn.rd(); \
+ const reg_t rs2_num = insn.rs2(); \
+ for (reg_t i = P.VU.vstart; i < vl; ++i) { \
+ VI_ELEMENT_SKIP(i); \
+ VI_STRIP(i); \
+ switch (P.VU.vsew) { \
+ case e8: {\
+ auto vs3 = P.VU.elt< type ## 8_t>(vd, vreg_inx); \
+ auto val = MMU.amo_uint8(baseAddr + index[i], [&]( type ## 8_t lhs) { op }); \
+ if (insn.v_wd()) \
+ P.VU.elt< type ## 8_t>(vd, vreg_inx, true) = val; \
+ } \
+ break; \
+ case e16: {\
+ auto vs3 = P.VU.elt< type ## 16_t>(vd, vreg_inx); \
+ auto val = MMU.amo_uint16(baseAddr + index[i], [&]( type ## 16_t lhs) { op }); \
+ if (insn.v_wd()) \
+ P.VU.elt< type ## 16_t>(vd, vreg_inx, true) = val; \
+ } \
+ break; \
+ case e32: {\
+ auto vs3 = P.VU.elt< type ## 32_t>(vd, vreg_inx); \
+ auto val = MMU.amo_uint32(baseAddr + index[i], [&]( type ## 32_t lhs) { op }); \
+ if (insn.v_wd()) \
+ P.VU.elt< type ## 32_t>(vd, vreg_inx, true) = val; \
+ } \
+ break; \
+ case e64: {\
+ auto vs3 = P.VU.elt< type ## 64_t>(vd, vreg_inx); \
+ auto val = MMU.amo_uint64(baseAddr + index[i], [&]( type ## 64_t lhs) { op }); \
+ if (insn.v_wd()) \
+ P.VU.elt< type ## 64_t>(vd, vreg_inx, true) = val; \
+ } \
+ break; \
+ default: \
+ require(0); \
+ break; \
+ } \
+ } \
+ P.VU.vstart = 0;
+
+//
// vector: vfp helper
//
#define VI_VFP_COMMON \
diff --git a/riscv/insns/vamoadde_v.h b/riscv/insns/vamoadde_v.h
new file mode 100644
index 0000000..9e59bdd
--- /dev/null
+++ b/riscv/insns/vamoadde_v.h
@@ -0,0 +1,2 @@
+//vamoadde.v vd, (rs1), vs2, vd
+VI_AMO({ return lhs + vs3; }, uint);
diff --git a/riscv/insns/vamoande_v.h b/riscv/insns/vamoande_v.h
new file mode 100644
index 0000000..90eb60d
--- /dev/null
+++ b/riscv/insns/vamoande_v.h
@@ -0,0 +1,2 @@
+//vamoande.v vd, (rs1), vs2, vd
+VI_AMO({ return lhs & vs3; }, uint);
diff --git a/riscv/insns/vamomaxe_v.h b/riscv/insns/vamomaxe_v.h
new file mode 100644
index 0000000..ab6539d
--- /dev/null
+++ b/riscv/insns/vamomaxe_v.h
@@ -0,0 +1,2 @@
+//vamomaxe.v vd, (rs1), vs2, vd
+VI_AMO({ return lhs >= vs3 ? lhs : vs3; }, int);
diff --git a/riscv/insns/vamomaxue_v.h b/riscv/insns/vamomaxue_v.h
new file mode 100644
index 0000000..1bdc50c
--- /dev/null
+++ b/riscv/insns/vamomaxue_v.h
@@ -0,0 +1,2 @@
+//vamomaxue.v vd, (rs1), vs2, vd
+VI_AMO({ return lhs >= vs3 ? lhs : vs3;; }, uint);
diff --git a/riscv/insns/vamomine_v.h b/riscv/insns/vamomine_v.h
new file mode 100644
index 0000000..fd931b2
--- /dev/null
+++ b/riscv/insns/vamomine_v.h
@@ -0,0 +1,2 @@
+//vamomine.v vd, (rs1), vs2, vd
+VI_AMO({ return lhs < vs3 ? lhs : vs3; }, int);
diff --git a/riscv/insns/vamominue_v.h b/riscv/insns/vamominue_v.h
new file mode 100644
index 0000000..d8616da
--- /dev/null
+++ b/riscv/insns/vamominue_v.h
@@ -0,0 +1,2 @@
+//vamominue.v vd, (rs1), vs2, vd
+VI_AMO({ return lhs < vs3 ? lhs : vs3;; }, uint);
diff --git a/riscv/insns/vamoore_v.h b/riscv/insns/vamoore_v.h
new file mode 100644
index 0000000..c35789c
--- /dev/null
+++ b/riscv/insns/vamoore_v.h
@@ -0,0 +1,2 @@
+//vamoore.v vd, (rs1), vs2, vd
+VI_AMO({ return lhs | vs3; }, uint);
diff --git a/riscv/insns/vamoswape_v.h b/riscv/insns/vamoswape_v.h
new file mode 100644
index 0000000..4cc15cb
--- /dev/null
+++ b/riscv/insns/vamoswape_v.h
@@ -0,0 +1,2 @@
+//vamoswape.v vd, (rs1), vs2, vd
+VI_AMO({ return vs3; }, uint);
diff --git a/riscv/insns/vamoxore_v.h b/riscv/insns/vamoxore_v.h
new file mode 100644
index 0000000..7eb1199
--- /dev/null
+++ b/riscv/insns/vamoxore_v.h
@@ -0,0 +1,2 @@
+//vamoore.v vd, (rs1), vs2, vd
+VI_AMO({ return lhs ^ vs3; }, uint);
diff --git a/riscv/mmu.h b/riscv/mmu.h
index b84fd4a..271faac 100644
--- a/riscv/mmu.h
+++ b/riscv/mmu.h
@@ -205,6 +205,8 @@ public:
store_func(uint64)
// perform an atomic memory operation at an aligned address
+ amo_func(uint8)
+ amo_func(uint16)
amo_func(uint32)
amo_func(uint64)
diff --git a/riscv/processor.cc b/riscv/processor.cc
index d5cbc98..b0da161 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -272,6 +272,8 @@ void processor_t::parse_isa_string(const char* str)
auto ext_str = std::string(ext, end - ext);
if (ext_str == "zfh") {
extension_table[EXT_ZFH] = true;
+ } else if (ext_str == "zvamo") {
+ extension_table[EXT_ZVAMO] = true;
} else {
sprintf(error_msg, "unsupported extension '%s'", ext_str.c_str());
bad_isa_string(str, error_msg);
@@ -297,6 +299,9 @@ void processor_t::parse_isa_string(const char* str)
if (supports_extension('Q') && !supports_extension('D'))
bad_isa_string(str, "'Q' extension requires 'D'");
+
+ if (supports_extension(EXT_ZVAMO) && !supports_extension('V'))
+ bad_isa_string(str, "'Zvamo' extension requires 'V'");
}
void state_t::reset(reg_t max_isa)
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index e597427..eeff3d0 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -645,6 +645,17 @@ riscv_insn_ext_v_alu_fp = \
vmfne_vf \
vmfne_vv \
+riscv_insn_ext_v_amo = \
+ vamoswape_v \
+ vamoadde_v \
+ vamoande_v \
+ vamomaxe_v \
+ vamomaxue_v \
+ vamomine_v \
+ vamominue_v \
+ vamoore_v \
+ vamoxore_v \
+
riscv_insn_ext_v_ldst = \
vle8_v \
vle16_v \
@@ -688,6 +699,7 @@ riscv_insn_ext_v_ctrl = \
riscv_insn_ext_v = \
$(riscv_insn_ext_v_alu_fp) \
$(riscv_insn_ext_v_alu_int) \
+ $(riscv_insn_ext_v_amo) \
$(riscv_insn_ext_v_ctrl) \
$(riscv_insn_ext_v_ldst) \
diff --git a/spike_main/disasm.cc b/spike_main/disasm.cc
index e62c985..571ec23 100644
--- a/spike_main/disasm.cc
+++ b/spike_main/disasm.cc
@@ -349,6 +349,12 @@ struct : public arg_t {
}
} v_vtype;
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return "x0";
+ }
+} x0;
+
typedef struct {
reg_t match;
reg_t mask;
@@ -374,6 +380,7 @@ disassembler_t::disassembler_t(int xlen)
const uint32_t mask_rvc_rs2 = 0x1fUL << 2;
const uint32_t mask_rvc_imm = mask_rvc_rs2 | 0x1000UL;
const uint32_t mask_nf = 0x7Ul << 29;
+ const uint32_t mask_wd = 0x1Ul << 26;
const uint32_t mask_vldst = 0x7Ul << 12 | 0x1UL << 28;
#define DECLARE_INSN(code, match, mask) \
@@ -1142,6 +1149,26 @@ disassembler_t::disassembler_t(int xlen)
#undef DISASM_OPIV_W__INSN
#undef DISASM_VFUNARY0_INSN
+ #define DISASM_VAMO_INSN(name) \
+ add_insn(new disasm_insn_t(#name "e.v", match_##name##e_v | mask_wd, \
+ mask_##name##e_v | mask_wd, \
+ {&vd, &v_address, &vs2, &vd, &opt, &vm})); \
+ add_insn(new disasm_insn_t(#name "e.v", match_##name##e_v, \
+ mask_##name##e_v | mask_wd, \
+ {&x0, &v_address, &vs2, &vd, &opt, &vm}));
+
+ DISASM_VAMO_INSN(vamoswap);
+ DISASM_VAMO_INSN(vamoadd);
+ DISASM_VAMO_INSN(vamoxor);
+ DISASM_VAMO_INSN(vamoand);
+ DISASM_VAMO_INSN(vamoor);
+ DISASM_VAMO_INSN(vamomin);
+ DISASM_VAMO_INSN(vamomax);
+ DISASM_VAMO_INSN(vamominu);
+ DISASM_VAMO_INSN(vamomaxu);
+
+ #undef DISASM_VAMO_INSN
+
if (xlen == 32) {
DISASM_INSN("c.flw", c_flw, 0, {&rvc_fp_rs2s, &rvc_lw_address});
DISASM_INSN("c.flwsp", c_flwsp, 0, {&frd, &rvc_lwsp_address});