diff --git a/README.md b/README.md index 47676100..42ee21e5 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ Spike supports the following RISC-V ISA features: - Zvkt extension, v1.0 - Zvkn, Zvknc, Zvkng extension, v1.0 - Zvks, Zvksc, Zvksg extension, v1.0 + - Zvzip extension, v0.1 - Zicond extension, v1.0 - Zilsd extension, v1.0 - Zclsd extension, v1.0 diff --git a/disasm/disasm.cc b/disasm/disasm.cc index 37dfb2c5..df56ff50 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -2183,6 +2183,14 @@ void disassembler_t::add_instructions(const isa_parser_t* isa, bool strict) DEFINE_VECTOR_MULTIPLYADD_VV(vwabdau_vv); } + if (ext_enabled(EXT_ZVZIP)) { + DEFINE_VECTOR_VV(vzip_vv); + DEFINE_VECTOR_V(vunzipe_v); + DEFINE_VECTOR_V(vunzipo_v); + DEFINE_VECTOR_VV(vpaire_vv); + DEFINE_VECTOR_VV(vpairo_vv); + } + if (ext_enabled(EXT_ZVBB)) { #define DEFINE_VECTOR_VIU_ZIMM6(code) \ add_vector_viu_z6_insn(this, #code, match_##code, mask_##code) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index 32151744..9d4548a1 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -327,6 +327,8 @@ void isa_parser_t::add_extension(const std::string& ext_str, const char* str) } else if (ext_str == "zvfwldot16bf") { extension_table[EXT_ZVFWLDOT16BF] = true; } else if (ext_str == "zvkt") { + } else if (ext_str == "zvzip") { + extension_table[EXT_ZVZIP] = true; } else if (ext_str == "sstc") { extension_table[EXT_SSTC] = true; } else if (ext_str == "smcsrind") { diff --git a/riscv/insns/vpaire_vv.h b/riscv/insns/vpaire_vv.h new file mode 100644 index 00000000..960b134a --- /dev/null +++ b/riscv/insns/vpaire_vv.h @@ -0,0 +1,7 @@ +// vunzipe.vv vd, vs1, vs2, vm + +#include "zvzip_ext_macros.h" + +require_zvzip; + +VI_VPAIR_VV_LOOP(i - 1, i) diff --git a/riscv/insns/vpairo_vv.h b/riscv/insns/vpairo_vv.h new file mode 100644 index 00000000..449a493f --- /dev/null +++ b/riscv/insns/vpairo_vv.h @@ -0,0 +1,7 @@ +// vunzipo.vv vd, vs1, vs2, vm + +#include "zvzip_ext_macros.h" + +require_zvzip; + +VI_VPAIR_VV_LOOP(i, i + 1) diff --git a/riscv/insns/vunzipe_v.h b/riscv/insns/vunzipe_v.h new file mode 100644 index 00000000..7415c363 --- /dev/null +++ b/riscv/insns/vunzipe_v.h @@ -0,0 +1,7 @@ +// vunzipe.v vd, vs2, vm + +#include "zvzip_ext_macros.h" + +require_zvzip; + +VI_VUNZIP_V_LOOP(i << 1) diff --git a/riscv/insns/vunzipo_v.h b/riscv/insns/vunzipo_v.h new file mode 100644 index 00000000..e2950d92 --- /dev/null +++ b/riscv/insns/vunzipo_v.h @@ -0,0 +1,7 @@ +// vunzipo.v vd, vs2, vm + +#include "zvzip_ext_macros.h" + +require_zvzip; + +VI_VUNZIP_V_LOOP((i << 1) + 1) diff --git a/riscv/insns/vzip_vv.h b/riscv/insns/vzip_vv.h new file mode 100644 index 00000000..7d2b7855 --- /dev/null +++ b/riscv/insns/vzip_vv.h @@ -0,0 +1,7 @@ +// vzip.vv vd, vs1, vs2, vm + +#include "zvzip_ext_macros.h" + +require_zvzip; + +VI_VZIP_VV_LOOP(i >> 1, i >> 1) diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index ed669831..ada74c76 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -88,6 +88,7 @@ typedef enum { EXT_ZVQLDOT16I, EXT_ZVFQLDOT8F, EXT_ZVFWLDOT16BF, + EXT_ZVZIP, EXT_SSTC, EXT_ZAAMO, EXT_ZALRSC, diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 3a6bd3a1..a996b889 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -1143,6 +1143,13 @@ riscv_insn_ext_zvabd = \ vwabda_vv \ vwabdau_vv \ +riscv_insn_ext_zvzip = \ + vzip_vv \ + vunzipe_v \ + vunzipo_v \ + vpaire_vv \ + vpairo_vv \ + riscv_insn_list = \ $(riscv_insn_ext_i) \ $(riscv_insn_ext_c) \ @@ -1174,6 +1181,7 @@ riscv_insn_list = \ $(riscv_insn_ext_zvbdot) \ $(riscv_insn_ext_zvldot) \ $(riscv_insn_ext_zvabd) \ + $(riscv_insn_ext_zvzip) \ $(riscv_insn_priv) \ $(riscv_insn_smrnmi) \ $(riscv_insn_svinval) \ diff --git a/riscv/zvzip_ext_macros.h b/riscv/zvzip_ext_macros.h new file mode 100644 index 00000000..745b3b8e --- /dev/null +++ b/riscv/zvzip_ext_macros.h @@ -0,0 +1,110 @@ +#ifndef RISCV_ZVZIP_MACROS_H_ +#define RISCV_ZVZIP_MACROS_H_ + +#define require_zvzip \ + do { \ + require_vector(true); \ + require_extension(EXT_ZVZIP); \ + } while (0) + +#define ZVZIP_EXTRACT_V(x, VS2_IDX) \ + type_sew_t::type UNUSED &vd = P.VU.elt::type>(rd_num, i, true); \ + vd = P.VU.elt::type>(rs2_num, VS2_IDX); + +#define ZVZIP_EXTRACT_VV(x, VS1_IDX, VS2_IDX) \ + type_sew_t::type UNUSED &vd = P.VU.elt::type>(rd_num, i, true); \ + vd = (i & 1) \ + ? ((VS1_IDX) >= P.VU.vlmax ? 0 : P.VU.elt::type>(rs1_num, VS1_IDX)) \ + : ((VS2_IDX) >= P.VU.vlmax ? 0 : P.VU.elt::type>(rs2_num, VS2_IDX)); + +#define VI_VZIP_VV_CHECK \ + require_vector(true); \ + require(P.VU.vflmul <= 4); \ + require_align(insn.rd(), P.VU.vflmul * 2); \ + require_align(insn.rs2(), P.VU.vflmul); \ + require_align(insn.rs1(), P.VU.vflmul); \ + require_vm; \ + if (P.VU.vflmul < 1) { \ + require_noover(insn.rd(), P.VU.vflmul * 2, insn.rs2(), P.VU.vflmul); \ + require_noover(insn.rd(), P.VU.vflmul * 2, insn.rs1(), P.VU.vflmul); \ + } else { \ + require_noover_widen(insn.rd(), P.VU.vflmul * 2, insn.rs2(), P.VU.vflmul); \ + require_noover_widen(insn.rd(), P.VU.vflmul * 2, insn.rs1(), P.VU.vflmul); \ + } + +#define VI_VZIP_VV_LOOP_BASE \ + require(P.VU.vsew >= e8 && P.VU.vsew <= e64); \ + reg_t vl = P.VU.vl->read() * 2; \ + reg_t UNUSED sew = P.VU.vsew; \ + reg_t UNUSED rd_num = insn.rd(); \ + reg_t UNUSED rs1_num = insn.rs1(); \ + reg_t rs2_num = insn.rs2(); \ + for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \ + VI_LOOP_ELEMENT_SKIP(); + +#define VI_VZIP_VV_LOOP_END \ + } \ + P.VU.vstart->write(0); + +#define VI_VZIP_VV_LOOP(VS1_IDX, VS2_IDX) \ + VI_VZIP_VV_CHECK \ + VI_VZIP_VV_LOOP_BASE \ + if (sew == e8) { \ + ZVZIP_EXTRACT_VV(e8, VS1_IDX, VS2_IDX); \ + } else if (sew == e16) { \ + ZVZIP_EXTRACT_VV(e16, VS1_IDX, VS2_IDX); \ + } else if (sew == e32) { \ + ZVZIP_EXTRACT_VV(e32, VS1_IDX, VS2_IDX); \ + } else if (sew == e64) { \ + ZVZIP_EXTRACT_VV(e64, VS1_IDX, VS2_IDX); \ + } \ + VI_VZIP_VV_LOOP_END + +#define VI_VUNZIP_V_CHECK \ + require_vector(true); \ + require(P.VU.vflmul <= 4); \ + require_align(insn.rs2(), P.VU.vflmul * 2); \ + require_align(insn.rd(), P.VU.vflmul); \ + require_vm; \ + if (insn.rd() != insn.rs2()) { \ + require_noover(insn.rd(), P.VU.vflmul, insn.rs2(), P.VU.vflmul * 2); \ + } + +#define VI_VUNZIP_V_LOOP(VS2_IDX) \ + VI_VUNZIP_V_CHECK \ + VI_LOOP_BASE \ + if (sew == e8) { \ + ZVZIP_EXTRACT_V(e8, VS2_IDX); \ + } else if (sew == e16) { \ + ZVZIP_EXTRACT_V(e16, VS2_IDX); \ + } else if (sew == e32) { \ + ZVZIP_EXTRACT_V(e32, VS2_IDX); \ + } else if (sew == e64) { \ + ZVZIP_EXTRACT_V(e64, VS2_IDX); \ + } \ + VI_LOOP_END + +#define VI_VPAIR_VV_CHECK \ + require_vector(true); \ + require_align(insn.rd(), P.VU.vflmul); \ + require_align(insn.rs2(), P.VU.vflmul); \ + require_align(insn.rs1(), P.VU.vflmul); \ + require_vm; \ + require_noover(insn.rd(), P.VU.vflmul, insn.rs2(), P.VU.vflmul); \ + require_noover(insn.rd(), P.VU.vflmul, insn.rs1(), P.VU.vflmul); + +#define VI_VPAIR_VV_LOOP(VS1_IDX, VS2_IDX) \ + VI_VPAIR_VV_CHECK \ + VI_LOOP_BASE \ + if (sew == e8) { \ + ZVZIP_EXTRACT_VV(e8, VS1_IDX, VS2_IDX); \ + } else if (sew == e16) { \ + ZVZIP_EXTRACT_VV(e16, VS1_IDX, VS2_IDX); \ + } else if (sew == e32) { \ + ZVZIP_EXTRACT_VV(e32, VS1_IDX, VS2_IDX); \ + } else if (sew == e64) { \ + ZVZIP_EXTRACT_VV(e64, VS1_IDX, VS2_IDX); \ + } \ + VI_LOOP_END + +#endif