aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorChih-Min Chao <chihmin.chao@sifive.com>2019-04-03 00:46:57 -0700
committerChih-Min Chao <chihmin.chao@sifive.com>2019-04-03 00:46:57 -0700
commiteb9770e3aedf2a88d745c0d68d8ec92bb145cdce (patch)
tree420d213f447a405b73ca90e9cd6351e04cab10f4 /riscv
parenta1133dcf763446fe23e018339504d6cb4eb2eb1d (diff)
downloadspike-eb9770e3aedf2a88d745c0d68d8ec92bb145cdce.zip
spike-eb9770e3aedf2a88d745c0d68d8ec92bb145cdce.tar.gz
spike-eb9770e3aedf2a88d745c0d68d8ec92bb145cdce.tar.bz2
rvv:add widing saturation instruction
Signed-off-by: Chih-Min Chao <chihmin.chao@sifive.com>
Diffstat (limited to 'riscv')
-rw-r--r--riscv/insns/vwsmacc_vv.h41
-rw-r--r--riscv/insns/vwsmacc_vx.h39
-rw-r--r--riscv/insns/vwsmaccu_vv.h41
-rw-r--r--riscv/insns/vwsmaccu_vx.h41
-rw-r--r--riscv/insns/vwsmsac_vv.h41
-rw-r--r--riscv/insns/vwsmsac_vx.h34
-rw-r--r--riscv/insns/vwsmsacu_vv.h41
-rw-r--r--riscv/insns/vwsmsacu_vx.h36
8 files changed, 284 insertions, 30 deletions
diff --git a/riscv/insns/vwsmacc_vv.h b/riscv/insns/vwsmacc_vv.h
index 5a6316f..53e51ff 100644
--- a/riscv/insns/vwsmacc_vv.h
+++ b/riscv/insns/vwsmacc_vv.h
@@ -1,5 +1,36 @@
-// vwsmacc
-VI_VV_LOOP
-({
- // NOT IMPLEMENTED YET
-})
+// vwsmacc.vv vd, vs2, vs1
+V_WIDE_CHECK;
+VRM vrm = STATE.VU.get_vround_mode();
+const int gb = STATE.VU.vsew / 2;
+
+#define WIDE_FUNC(sew1, sew2) \
+ { \
+ type_sew_t<sew2>::type &vd = STATE.VU.elt<type_sew_t<sew2>::type>(rd_num, i); \
+ type_sew_t<sew1>::type vs1 = STATE.VU.elt<type_sew_t<sew1>::type>(rs1_num, i); \
+ type_sew_t<sew1>::type vs2 = STATE.VU.elt<type_sew_t<sew1>::type>(rs2_num, i); \
+ int##sew2##_t round = (vrm == VRM::RUN) ? 1 << (gb - 1) : 0; \
+ int##sew2##_t res; \
+ bool sat = false; \
+ res = ((((int##sew2##_t)(int##sew1##_t)vs2 * (int##sew2##_t)(int##sew1##_t)vs1) + round) >> gb); \
+ vd = sat_add<int##sew2##_t, uint##sew2##_t>(vd, res, sat); \
+ STATE.VU.vxsat = sat; \
+ }
+
+VI_LOOP_BASE
+ V_LOOP_ELEMENT_SKIP;
+
+ switch(STATE.VU.vsew) {
+ case e8:
+ WIDE_FUNC(8, 16);
+ break;
+ case e16:
+ WIDE_FUNC(16, 32);
+ break;
+ default:
+ WIDE_FUNC(32, 64);
+ break;
+ }
+
+VI_LOOP_END
+
+#undef WIDE_FUNC
diff --git a/riscv/insns/vwsmacc_vx.h b/riscv/insns/vwsmacc_vx.h
index 71412c8..57e6443 100644
--- a/riscv/insns/vwsmacc_vx.h
+++ b/riscv/insns/vwsmacc_vx.h
@@ -1,5 +1,34 @@
-// vwsmacc
-VI_VX_LOOP
-({
- // NOT IMPLEMENTED YET
-})
+// vwsmacc.vx vd, vs2, rs1
+V_WIDE_CHECK;
+VRM vrm = STATE.VU.get_vround_mode();
+const int gb = STATE.VU.vsew / 2;
+
+#define WIDE_FUNC(sew1, sew2) \
+ { \
+ type_sew_t<sew2>::type &vd = STATE.VU.elt<type_sew_t<sew2>::type>(rd_num, i); \
+ type_sew_t<sew1>::type rs1 = RS1; \
+ type_sew_t<sew1>::type vs2 = STATE.VU.elt<type_sew_t<sew1>::type>(rs2_num, i); \
+ int##sew2##_t round = (vrm == VRM::RUN) ? 1 << (gb - 1) : 0; \
+ int##sew2##_t res; \
+ bool sat = false; \
+ res = ((((int##sew2##_t)(int##sew1##_t)vs2 * (int##sew2##_t)(int##sew1##_t)rs1) + round) >> gb); \
+ vd = sat_add<int##sew2##_t, uint##sew2##_t>(vd, res, sat); \
+ STATE.VU.vxsat = sat; \
+ }
+
+VI_LOOP_BASE
+ V_LOOP_ELEMENT_SKIP;
+
+ switch(STATE.VU.vsew) {
+ case e8:
+ WIDE_FUNC(8, 16);
+ break;
+ case e16:
+ WIDE_FUNC(16, 32);
+ break;
+ default:
+ WIDE_FUNC(32, 64);
+ break;
+ }
+
+VI_LOOP_END
diff --git a/riscv/insns/vwsmaccu_vv.h b/riscv/insns/vwsmaccu_vv.h
index dbea439..dc5726b 100644
--- a/riscv/insns/vwsmaccu_vv.h
+++ b/riscv/insns/vwsmaccu_vv.h
@@ -1,5 +1,36 @@
-// vwsmaccu
-VI_VV_LOOP
-({
- // NOT IMPLEMENTED YET
-})
+// vwsmaccu.vv vd, vs2, vs1
+V_WIDE_CHECK;
+VRM vrm = STATE.VU.get_vround_mode();
+const int gb = STATE.VU.vsew / 2;
+
+#define WIDE_FUNC(sew1, sew2) \
+ { \
+ type_sew_t<sew2>::type &vd = STATE.VU.elt<type_sew_t<sew2>::type>(rd_num, i); \
+ type_sew_t<sew1>::type vs1 = STATE.VU.elt<type_sew_t<sew1>::type>(rs1_num, i); \
+ type_sew_t<sew1>::type vs2 = STATE.VU.elt<type_sew_t<sew1>::type>(rs2_num, i); \
+ uint##sew2##_t round = (vrm == VRM::RUN) ? 1 << (gb - 1) : 0; \
+ uint##sew2##_t res; \
+ bool sat = false; \
+ res = ((((uint##sew2##_t)(uint##sew1##_t)vs2 * (uint##sew2##_t)(uint##sew1##_t)vs1) + round) >> gb); \
+ vd = sat_addu<uint##sew2##_t>(vd, res, sat); \
+ STATE.VU.vxsat = sat; \
+ }
+
+VI_LOOP_BASE
+ V_LOOP_ELEMENT_SKIP;
+
+ switch(STATE.VU.vsew) {
+ case e8:
+ WIDE_FUNC(8, 16);
+ break;
+ case e16:
+ WIDE_FUNC(16, 32);
+ break;
+ default:
+ WIDE_FUNC(32, 64);
+ break;
+ }
+
+VI_LOOP_END
+
+#undef WIDE_FUNC
diff --git a/riscv/insns/vwsmaccu_vx.h b/riscv/insns/vwsmaccu_vx.h
index e049bcd..f0a1028 100644
--- a/riscv/insns/vwsmaccu_vx.h
+++ b/riscv/insns/vwsmaccu_vx.h
@@ -1,5 +1,36 @@
-// vwsmaccu
-VI_VX_LOOP
-({
- // NOT IMPLEMENTED YET
-})
+// vwsmaccu vd, vs2, rs1
+V_WIDE_CHECK;
+VRM vrm = STATE.VU.get_vround_mode();
+const int gb = STATE.VU.vsew / 2;
+
+#define WIDE_FUNC(sew1, sew2) \
+ { \
+ type_sew_t<sew2>::type &vd = STATE.VU.elt<type_sew_t<sew2>::type>(rd_num, i); \
+ type_sew_t<sew1>::type rs1 = RS1; \
+ type_sew_t<sew1>::type vs2 = STATE.VU.elt<type_sew_t<sew1>::type>(rs2_num, i); \
+ uint##sew2##_t round = (vrm == VRM::RUN) ? 1 << (gb - 1) : 0; \
+ uint##sew2##_t res; \
+ bool sat = false; \
+ res = ((((uint##sew2##_t)(uint##sew1##_t)vs2 * (uint##sew2##_t)(uint##sew1##_t)rs1) + round) >> gb); \
+ vd = sat_addu<uint##sew2##_t>(vd, res, sat); \
+ STATE.VU.vxsat = sat; \
+ }
+
+VI_LOOP_BASE
+ V_LOOP_ELEMENT_SKIP;
+
+ switch(STATE.VU.vsew) {
+ case e8:
+ WIDE_FUNC(8, 16);
+ break;
+ case e16:
+ WIDE_FUNC(16, 32);
+ break;
+ default:
+ WIDE_FUNC(32, 64);
+ break;
+ }
+
+VI_LOOP_END
+
+#undef WIDE_FUNC
diff --git a/riscv/insns/vwsmsac_vv.h b/riscv/insns/vwsmsac_vv.h
index fb8a7c7..e0a3e89 100644
--- a/riscv/insns/vwsmsac_vv.h
+++ b/riscv/insns/vwsmsac_vv.h
@@ -1,5 +1,36 @@
-// vwsmsac
-VI_VV_LOOP
-({
- // NOT IMPLEMENTED YET
-})
+// vwsmsac.vv vd, vs2, vs1
+V_WIDE_CHECK;
+VRM vrm = STATE.VU.get_vround_mode();
+const int gb = STATE.VU.vsew / 2;
+
+#define WIDE_FUNC(sew1, sew2) \
+ { \
+ type_sew_t<sew2>::type &vd = STATE.VU.elt<type_sew_t<sew2>::type>(rd_num, i); \
+ type_sew_t<sew1>::type vs1 = STATE.VU.elt<type_sew_t<sew1>::type>(rs1_num, i); \
+ type_sew_t<sew1>::type vs2 = STATE.VU.elt<type_sew_t<sew1>::type>(rs2_num, i); \
+ int##sew2##_t round = (vrm == VRM::RUN) ? 1 << (gb - 1) : 0; \
+ int##sew2##_t res; \
+ bool sat = false; \
+ res = ((((int##sew2##_t)(int##sew1##_t)vs2 * (int##sew2##_t)(int##sew1##_t)vs1) + round) >> gb); \
+ vd = sat_add<int##sew2##_t, uint##sew2##_t>(vd, -res, sat); \
+ STATE.VU.vxsat = sat; \
+ }
+
+VI_LOOP_BASE
+ V_LOOP_ELEMENT_SKIP;
+
+ switch(STATE.VU.vsew) {
+ case e8:
+ WIDE_FUNC(8, 16);
+ break;
+ case e16:
+ WIDE_FUNC(16, 32);
+ break;
+ default:
+ WIDE_FUNC(32, 64);
+ break;
+ }
+
+VI_LOOP_END
+
+#undef WIDE_FUNC
diff --git a/riscv/insns/vwsmsac_vx.h b/riscv/insns/vwsmsac_vx.h
new file mode 100644
index 0000000..dd13dab
--- /dev/null
+++ b/riscv/insns/vwsmsac_vx.h
@@ -0,0 +1,34 @@
+// vwsmsac.vx vd, vs2, rs1
+V_WIDE_CHECK;
+VRM vrm = STATE.VU.get_vround_mode();
+const int gb = STATE.VU.vsew / 2;
+
+#define WIDE_FUNC(sew1, sew2) \
+ { \
+ type_sew_t<sew2>::type &vd = STATE.VU.elt<type_sew_t<sew2>::type>(rd_num, i); \
+ type_sew_t<sew1>::type rs1 = RS1; \
+ type_sew_t<sew1>::type vs2 = STATE.VU.elt<type_sew_t<sew1>::type>(rs2_num, i); \
+ int##sew2##_t round = (vrm == VRM::RUN) ? 1 << (gb - 1) : 0; \
+ int##sew2##_t res; \
+ bool sat = false; \
+ res = ((((int##sew2##_t)(int##sew1##_t)vs2 * (int##sew2##_t)(int##sew1##_t)rs1) + round) >> gb); \
+ vd = sat_add<int##sew2##_t, uint##sew2##_t>(vd, -res, sat); \
+ STATE.VU.vxsat = sat; \
+ }
+
+VI_LOOP_BASE
+ V_LOOP_ELEMENT_SKIP;
+
+ switch(STATE.VU.vsew) {
+ case e8:
+ WIDE_FUNC(8, 16);
+ break;
+ case e16:
+ WIDE_FUNC(16, 32);
+ break;
+ default:
+ WIDE_FUNC(32, 64);
+ break;
+ }
+
+VI_LOOP_END
diff --git a/riscv/insns/vwsmsacu_vv.h b/riscv/insns/vwsmsacu_vv.h
index d8a0bab..92726f7 100644
--- a/riscv/insns/vwsmsacu_vv.h
+++ b/riscv/insns/vwsmsacu_vv.h
@@ -1,5 +1,36 @@
-// vwsmsacu
-VI_VV_LOOP
-({
- // NOT IMPLEMENTED YET
-})
+// vwsmsacu vd, vs2, vs1
+V_WIDE_CHECK;
+VRM vrm = STATE.VU.get_vround_mode();
+const int gb = STATE.VU.vsew / 2;
+
+#define WIDE_FUNC(sew1, sew2) \
+ { \
+ type_sew_t<sew2>::type &vd = STATE.VU.elt<type_sew_t<sew2>::type>(rd_num, i); \
+ type_sew_t<sew1>::type vs1 = STATE.VU.elt<type_sew_t<sew1>::type>(rs1_num, i); \
+ type_sew_t<sew1>::type vs2 = STATE.VU.elt<type_sew_t<sew1>::type>(rs2_num, i); \
+ uint##sew2##_t round = (vrm == VRM::RUN) ? 1 << (gb - 1) : 0; \
+ uint##sew2##_t res; \
+ bool sat = false; \
+ res = ((((uint##sew2##_t)(uint##sew1##_t)vs2 * (uint##sew2##_t)(uint##sew1##_t)vs1) + round) >> gb); \
+ vd = sat_addu<uint##sew2##_t>(vd, -res, sat); \
+ STATE.VU.vxsat = sat; \
+ }
+
+VI_LOOP_BASE
+ V_LOOP_ELEMENT_SKIP;
+
+ switch(STATE.VU.vsew) {
+ case e8:
+ WIDE_FUNC(8, 16);
+ break;
+ case e16:
+ WIDE_FUNC(16, 32);
+ break;
+ default:
+ WIDE_FUNC(32, 64);
+ break;
+ }
+
+VI_LOOP_END
+
+#undef WIDE_FUNC
diff --git a/riscv/insns/vwsmsacu_vx.h b/riscv/insns/vwsmsacu_vx.h
new file mode 100644
index 0000000..71e7797
--- /dev/null
+++ b/riscv/insns/vwsmsacu_vx.h
@@ -0,0 +1,36 @@
+// vwsmsacu vd, vs2, rs1
+V_WIDE_CHECK;
+VRM vrm = STATE.VU.get_vround_mode();
+const int gb = STATE.VU.vsew / 2;
+
+#define WIDE_FUNC(sew1, sew2) \
+ { \
+ type_sew_t<sew2>::type &vd = STATE.VU.elt<type_sew_t<sew2>::type>(rd_num, i); \
+ type_sew_t<sew1>::type rs1 = RS1; \
+ type_sew_t<sew1>::type vs2 = STATE.VU.elt<type_sew_t<sew1>::type>(rs2_num, i); \
+ uint##sew2##_t round = (vrm == VRM::RUN) ? 1 << (gb - 1) : 0; \
+ uint##sew2##_t res; \
+ bool sat = false; \
+ res = ((((uint##sew2##_t)(uint##sew1##_t)vs2 * (uint##sew2##_t)(uint##sew1##_t)rs1) + round) >> gb); \
+ vd = sat_addu<uint##sew2##_t>(vd, -res, sat); \
+ STATE.VU.vxsat = sat; \
+ }
+
+VI_LOOP_BASE
+ V_LOOP_ELEMENT_SKIP;
+
+ switch(STATE.VU.vsew) {
+ case e8:
+ WIDE_FUNC(8, 16);
+ break;
+ case e16:
+ WIDE_FUNC(16, 32);
+ break;
+ default:
+ WIDE_FUNC(32, 64);
+ break;
+ }
+
+VI_LOOP_END
+
+#undef WIDE_FUNC