Fixes a bug in vector segment load when lmul > 1. PiperOrigin-RevId: 919138004 Change-Id: I7c395b100b6dbfb441e530f09e94cd65eed0d361
diff --git a/riscv/riscv32g_vec_encoding.cc b/riscv/riscv32g_vec_encoding.cc index 679fa5b..b9c6c64 100644 --- a/riscv/riscv32g_vec_encoding.cc +++ b/riscv/riscv32g_vec_encoding.cc
@@ -46,23 +46,39 @@ constexpr int kNumRegTable[8] = {8, 1, 2, 1, 4, 1, 2, 1}; template <typename RegType> -inline void GetVRegGroup(RiscVState* state, int reg_num, +inline void GetVRegGroup(RiscVState* state, int reg_num, int num_fields, std::vector<generic::RegisterBase*>* vreg_group) { // The number of registers in a vector register group depends on the register // index: 0, 8, 16, 24 each have 8 registers, 4, 12, 20, 28 each have 4, // 2, 6, 10, 14, 18, 22, 26, 30 each have two, and all odd numbered register // groups have only 1. + // For segmented load and store instructions there is a register group per + // field. Each register group size is limited by the NumRegTable limit, but + // the total number of registers can still be up to 8. int num_regs = kNumRegTable[reg_num % 8]; - for (int i = 0; i < num_regs; i++) { + for (int i = 0; i < num_regs * num_fields; i++) { auto vreg_name = absl::StrCat(RiscVState::kVregPrefix, reg_num + i); vreg_group->push_back(state->GetRegister<RegType>(vreg_name).first); } } + template <typename RegType> inline SourceOperandInterface* GetVectorRegisterSourceOp(RiscVState* state, int reg_num) { std::vector<generic::RegisterBase*> vreg_group; - GetVRegGroup<RegType>(state, reg_num, &vreg_group); + GetVRegGroup<RegType>(state, reg_num, /*num_fields=*/1, &vreg_group); + auto* v_src_op = new RV32VectorSourceOperand( + absl::Span<generic::RegisterBase*>(vreg_group), + absl::StrCat(RiscVState::kVregPrefix, reg_num)); + return v_src_op; +} + +template <typename RegType> +inline SourceOperandInterface* GetVectorRegisterSourceOpNf(RiscVState* state, + int reg_num, + int nf) { + std::vector<generic::RegisterBase*> vreg_group; + GetVRegGroup<RegType>(state, reg_num, nf, &vreg_group); auto* v_src_op = new RV32VectorSourceOperand( absl::Span<generic::RegisterBase*>(vreg_group), absl::StrCat(RiscVState::kVregPrefix, reg_num)); @@ -73,7 +89,18 @@ inline DestinationOperandInterface* GetVectorRegisterDestinationOp( RiscVState* state, int latency, int reg_num) { std::vector<generic::RegisterBase*> vreg_group; - GetVRegGroup<RegType>(state, reg_num, &vreg_group); + GetVRegGroup<RegType>(state, reg_num, /*num_fields=*/1, &vreg_group); + auto* v_dst_op = new RV32VectorDestinationOperand( + absl::Span<generic::RegisterBase*>(vreg_group), latency, + absl::StrCat(RiscVState::kVregPrefix, reg_num)); + return v_dst_op; +} + +template <typename RegType> +inline DestinationOperandInterface* GetVectorRegisterDestinationOpNf( + RiscVState* state, int latency, int reg_num, int nf) { + std::vector<generic::RegisterBase*> vreg_group; + GetVRegGroup<RegType>(state, reg_num, nf, &vreg_group); auto* v_dst_op = new RV32VectorDestinationOperand( absl::Span<generic::RegisterBase*>(vreg_group), latency, absl::StrCat(RiscVState::kVregPrefix, reg_num)); @@ -204,6 +231,13 @@ auto num = encoding::v_mem::ExtractVs3(inst_word_); return GetVectorRegisterSourceOp<RVVectorRegister>(state_, num); }); + Insert(source_op_getters_, SourceOpEnum::kVs3Nf, + [this]() -> SourceOperandInterface* { + auto nf = encoding::v_mem::ExtractNf(inst_word_) + 1; + auto num = encoding::v_mem::ExtractVs3(inst_word_); + return GetVectorRegisterSourceOpNf<RVVectorRegister>(state_, num, + nf); + }); Insert(source_op_getters_, SourceOpEnum::kSimm5, [this]() -> SourceOperandInterface* { @@ -264,6 +298,13 @@ return GetVectorRegisterDestinationOp<RVVectorRegister>( state_, latency, num); }); + Insert(dest_op_getters_, DestOpEnum::kVdNf, + [this](int latency) -> DestinationOperandInterface* { + auto nf = encoding::v_mem::ExtractNf(inst_word_) + 1; + auto num = encoding::v_mem::ExtractVd(inst_word_); + return GetVectorRegisterDestinationOpNf<RVVectorRegister>( + state_, latency, num, nf); + }); } void RiscV32GVecEncoding::InitializeSourceOperandGetters() {
diff --git a/riscv/riscv64g_vec_encoding.cc b/riscv/riscv64g_vec_encoding.cc index d235d5a..63f94fc 100644 --- a/riscv/riscv64g_vec_encoding.cc +++ b/riscv/riscv64g_vec_encoding.cc
@@ -52,23 +52,39 @@ } template <typename RegType> -inline void GetVRegGroup(RiscVState* state, int reg_num, +inline void GetVRegGroup(RiscVState* state, int reg_num, int num_fields, std::vector<generic::RegisterBase*>* vreg_group) { // The number of registers in a vector register group depends on the register // index: 0, 8, 16, 24 each have 8 registers, 4, 12, 20, 28 each have 4, // 2, 6, 10, 14, 18, 22, 26, 30 each have two, and all odd numbered register // groups have only 1. + // For segmented load and store instructions there is a register group per + // field. Each register group size is limited by the NumRegTable limit, but + // the total number of registers can still be up to 8. int num_regs = kNumRegTable[reg_num % 8]; - for (int i = 0; i < num_regs; i++) { + for (int i = 0; i < num_regs * num_fields; i++) { auto vreg_name = absl::StrCat(RiscVState::kVregPrefix, reg_num + i); vreg_group->push_back(state->GetRegister<RegType>(vreg_name).first); } } + template <typename RegType> inline SourceOperandInterface* GetVectorRegisterSourceOp(RiscVState* state, int reg_num) { std::vector<generic::RegisterBase*> vreg_group; - GetVRegGroup<RegType>(state, reg_num, &vreg_group); + GetVRegGroup<RegType>(state, reg_num, /*num_fields=*/1, &vreg_group); + auto* v_src_op = new RV32VectorSourceOperand( + absl::Span<generic::RegisterBase*>(vreg_group), + absl::StrCat(RiscVState::kVregPrefix, reg_num)); + return v_src_op; +} + +template <typename RegType> +inline SourceOperandInterface* GetVectorRegisterSourceOpNf(RiscVState* state, + int reg_num, + int nf) { + std::vector<generic::RegisterBase*> vreg_group; + GetVRegGroup<RegType>(state, reg_num, nf, &vreg_group); auto* v_src_op = new RV32VectorSourceOperand( absl::Span<generic::RegisterBase*>(vreg_group), absl::StrCat(RiscVState::kVregPrefix, reg_num)); @@ -79,7 +95,18 @@ inline DestinationOperandInterface* GetVectorRegisterDestinationOp( RiscVState* state, int latency, int reg_num) { std::vector<generic::RegisterBase*> vreg_group; - GetVRegGroup<RegType>(state, reg_num, &vreg_group); + GetVRegGroup<RegType>(state, reg_num, /*num_fields=*/1, &vreg_group); + auto* v_dst_op = new RV32VectorDestinationOperand( + absl::Span<generic::RegisterBase*>(vreg_group), latency, + absl::StrCat(RiscVState::kVregPrefix, reg_num)); + return v_dst_op; +} + +template <typename RegType> +inline DestinationOperandInterface* GetVectorRegisterDestinationOpNf( + RiscVState* state, int latency, int reg_num, int nf) { + std::vector<generic::RegisterBase*> vreg_group; + GetVRegGroup<RegType>(state, reg_num, nf, &vreg_group); auto* v_dst_op = new RV32VectorDestinationOperand( absl::Span<generic::RegisterBase*>(vreg_group), latency, absl::StrCat(RiscVState::kVregPrefix, reg_num)); @@ -688,6 +715,13 @@ auto num = encoding64::v_mem::ExtractVs3(inst_word_); return GetVectorRegisterSourceOp<RVVectorRegister>(state_, num); }); + Insert(source_op_getters_, SourceOpEnum::kVs3Nf, + [this]() -> SourceOperandInterface* { + auto nf = encoding64::v_mem::ExtractNf(inst_word_) + 1; + auto num = encoding64::v_mem::ExtractVs3(inst_word_); + return GetVectorRegisterSourceOpNf<RVVectorRegister>(state_, num, + nf); + }); Insert(source_op_getters_, SourceOpEnum::kSimm5, [this]() -> SourceOperandInterface* { @@ -750,6 +784,13 @@ return GetVectorRegisterDestinationOp<RVVectorRegister>( state_, latency, num); }); + Insert(dest_op_getters_, DestOpEnum::kVdNf, + [this](int latency) -> DestinationOperandInterface* { + auto nf = encoding64::v_mem::ExtractNf(inst_word_) + 1; + auto num = encoding64::v_mem::ExtractVd(inst_word_); + return GetVectorRegisterDestinationOpNf<RVVectorRegister>( + state_, latency, num, nf); + }); } // Parse the instruction word to determine the opcode.
diff --git a/riscv/riscv_getters_vector.h b/riscv/riscv_getters_vector.h index f68e2a6..3d16e87 100644 --- a/riscv/riscv_getters_vector.h +++ b/riscv/riscv_getters_vector.h
@@ -46,23 +46,38 @@ constexpr int kNumRegTable[8] = {8, 1, 2, 1, 4, 1, 2, 1}; template <typename RegType> -inline void GetVRegGroup(RiscVState* state, int reg_num, +inline void GetVRegGroup(RiscVState* state, int reg_num, int num_fields, std::vector<generic::RegisterBase*>* vreg_group) { // The number of registers in a vector register group depends on the register // index: 0, 8, 16, 24 each have 8 registers, 4, 12, 20, 28 each have 4, // 2, 6, 10, 14, 18, 22, 26, 30 each have two, and all odd numbered register // groups have only 1. + // For segmented load and store instructions there is a register group per + // field. Each register group size is limited by the NumRegTable limit, but + // the total number of registers can still be up to 8. int num_regs = kNumRegTable[reg_num % 8]; - for (int i = 0; i < num_regs; i++) { + for (int i = 0; i < num_regs * num_fields; i++) { auto vreg_name = absl::StrCat(RiscVState::kVregPrefix, reg_num + i); vreg_group->push_back(state->GetRegister<RegType>(vreg_name).first); } } + template <typename RegType> inline SourceOperandInterface* GetVectorRegisterSourceOp(RiscVState* state, int reg_num) { std::vector<generic::RegisterBase*> vreg_group; - GetVRegGroup<RegType>(state, reg_num, &vreg_group); + GetVRegGroup<RegType>(state, reg_num, /*num_fields=*/1, &vreg_group); + auto* v_src_op = new RV32VectorSourceOperand( + absl::Span<generic::RegisterBase*>(vreg_group), + absl::StrCat(RiscVState::kVregPrefix, reg_num)); + return v_src_op; +} +template <typename RegType> +inline SourceOperandInterface* GetVectorRegisterSourceOpNf(RiscVState* state, + int reg_num, + int nf) { + std::vector<generic::RegisterBase*> vreg_group; + GetVRegGroup<RegType>(state, reg_num, nf, &vreg_group); auto* v_src_op = new RV32VectorSourceOperand( absl::Span<generic::RegisterBase*>(vreg_group), absl::StrCat(RiscVState::kVregPrefix, reg_num)); @@ -73,7 +88,18 @@ inline DestinationOperandInterface* GetVectorRegisterDestinationOp( RiscVState* state, int latency, int reg_num) { std::vector<generic::RegisterBase*> vreg_group; - GetVRegGroup<RegType>(state, reg_num, &vreg_group); + GetVRegGroup<RegType>(state, reg_num, /*num_fields=*/1, &vreg_group); + auto* v_dst_op = new RV32VectorDestinationOperand( + absl::Span<generic::RegisterBase*>(vreg_group), latency, + absl::StrCat(RiscVState::kVregPrefix, reg_num)); + return v_dst_op; +} + +template <typename RegType> +inline DestinationOperandInterface* GetVectorRegisterDestinationOpNf( + RiscVState* state, int latency, int reg_num, int nf) { + std::vector<generic::RegisterBase*> vreg_group; + GetVRegGroup<RegType>(state, reg_num, nf, &vreg_group); auto* v_dst_op = new RV32VectorDestinationOperand( absl::Span<generic::RegisterBase*>(vreg_group), latency, absl::StrCat(RiscVState::kVregPrefix, reg_num)); @@ -151,6 +177,12 @@ auto num = Extractors::VMem::ExtractVs3(common->inst_word()); return GetVectorRegisterSourceOp<VectorRegister>(common->state(), num); }); + Insert(getter_map, *Enum::kVs3Nf, [common]() -> SourceOperandInterface* { + auto nf = Extractors::VMem::ExtractNf(common->inst_word()) + 1; + auto num = Extractors::VMem::ExtractVs3(common->inst_word()); + return GetVectorRegisterSourceOpNf<VectorRegister>(common->state(), num, + nf); + }); Insert(getter_map, *Enum::kSimm5, [common]() -> SourceOperandInterface* { const auto num = @@ -220,6 +252,13 @@ return GetVectorRegisterDestinationOp<VectorRegister>( common->state(), latency, num); }); + Insert(getter_map, *Enum::kVdNf, + [common](int latency) -> DestinationOperandInterface* { + auto nf = Extractors::VMem::ExtractNf(common->inst_word()) + 1; + auto num = Extractors::VMem::ExtractVd(common->inst_word()); + return GetVectorRegisterDestinationOpNf<VectorRegister>( + common->state(), latency, num, nf); + }); Insert(getter_map, *Enum::kFd, [common](int latency) -> DestinationOperandInterface* { const int num = Extractors::VArith::ExtractRd(common->inst_word());
diff --git a/riscv/riscv_vector.isa b/riscv/riscv_vector.isa index 1d48d73..7ac4c0e 100644 --- a/riscv/riscv_vector.isa +++ b/riscv/riscv_vector.isa
@@ -202,75 +202,75 @@ semfunc: "absl::bind_front(&VlIndexed, /*index_width*/ 8)", "&VlChild"; // Vector unit-stride segment load - vlsege8{(: rs1, vmask, nf:), (: nf : vd)}, - disasm: "vlseg%nf\\e.v", "%vd, (%rs1), %vmask", + vlsege8{(: rs1, vmask, nf:), (: nf : vd_nf)}, + disasm: "vlseg%nf\\e.v", "%vd_nf, (%rs1), %vmask", semfunc: "absl::bind_front(&VlSegment, /*element_width*/ 1)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 1)"; - vlsege16{(: rs1, vmask, nf:), (: nf : vd)}, - disasm: "vlseg%nf\\e.v", "%vd, (%rs1), %vmask", + vlsege16{(: rs1, vmask, nf:), (: nf : vd_nf)}, + disasm: "vlseg%nf\\e.v", "%vd_nf, (%rs1), %vmask", semfunc: "absl::bind_front(&VlSegment, /*element_width*/ 2)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 2)"; - vlsege32{(: rs1, vmask, nf:), (: nf : vd)}, - disasm: "vlseg%nf\\e.v", "%vd, (%rs1), %vmask", + vlsege32{(: rs1, vmask, nf:), (: nf : vd_nf)}, + disasm: "vlseg%nf\\e.v", "%vd_nf, (%rs1), %vmask", semfunc: "absl::bind_front(&VlSegment, /*element_width*/ 4)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 4)"; - vlsege64{(: rs1, vmask, nf:), (: nf : vd)}, - disasm: "vlseg%nf\\e.v", "%vd, (%rs1), %vmask", + vlsege64{(: rs1, vmask, nf:), (: nf : vd_nf)}, + disasm: "vlseg%nf\\e.v", "%vd_nf, (%rs1), %vmask", semfunc: "absl::bind_front(&VlSegment, /*element_width*/ 8)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 8)"; // Vector strided segment load. - vlssege8{(: rs1, rs2, vmask, nf: ), (: nf : vd)}, - disasm: "vlsseg%nf\\e8.v", "%vd, (%rs1), %rs2, %vmask", + vlssege8{(: rs1, rs2, vmask, nf: ), (: nf : vd_nf)}, + disasm: "vlsseg%nf\\e8.v", "%vd_nf, (%rs1), %rs2, %vmask", semfunc: "absl::bind_front(&VlSegmentStrided, /*element_width*/ 1)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 1)"; - vlssege16{(: rs1, rs2, vmask, nf: ), (: nf : vd)},/*element_width*/ - disasm: "vlsseg%nf\\e16.v", "%vd, (%rs1), %rs2, %vmask", + vlssege16{(: rs1, rs2, vmask, nf: ), (: nf : vd_nf)}, + disasm: "vlsseg%nf\\e16.v", "%vd_nf, (%rs1), %rs2, %vmask", semfunc: "absl::bind_front(&VlSegmentStrided, /*element_width*/ 2)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 2)"; - vlssege32{(: rs1, rs2, vmask, nf: ), (: nf : vd)}, - disasm: "vlsseg%nf\\e32.v", "%vd, (%rs1), %rs2, %vmask", + vlssege32{(: rs1, rs2, vmask, nf: ), (: nf : vd_nf)}, + disasm: "vlsseg%nf\\e32.v", "%vd_nf, (%rs1), %rs2, %vmask", semfunc: "absl::bind_front(&VlSegmentStrided, /*element_width*/ 4)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 4)"; - vlssege64{(: rs1, rs2, vmask, nf: ), (: nf : vd)}, - disasm: "vlsseg%nf\\e64.v", "%vd, (%rs1), %rs2, %vmask", + vlssege64{(: rs1, rs2, vmask, nf: ), (: nf : vd_nf)}, + disasm: "vlsseg%nf\\e64.v", "%vd_nf, (%rs1), %rs2, %vmask", semfunc: "absl::bind_front(&VlSegmentStrided, /*element_width*/ 8)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 8)"; // Vector indexed segment load unordered. - vluxsegei8{(: rs1, vs2, vmask, nf :), (: nf : vd)}, - disasm: "vluxseg%nf\\ei1.v", "%vd, (%rs1), %vs2, %vmask", + vluxsegei8{(: rs1, vs2, vmask, nf :), (: nf : vd_nf)}, + disasm: "vluxseg%nf\\ei1.v", "%vd_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VlSegmentIndexed, /*index_width*/ 1)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 1)"; - vluxsegei16{(: rs1, vs2, vmask, nf :), (: nf : vd)}, - disasm: "vluxseg%nf\\ei2.v", "%vd, (%rs1), %vs2, %vmask", + vluxsegei16{(: rs1, vs2, vmask, nf :), (: nf : vd_nf)}, + disasm: "vluxseg%nf\\ei2.v", "%vd_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VlSegmentIndexed, /*index_width*/ 2)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 2)"; - vluxsegei32{(: rs1, vs2, vmask, nf :), (: nf : vd)}, - disasm: "vluxseg%nf\\ei4.v", "%vd, (%rs1), %vs2, %vmask", + vluxsegei32{(: rs1, vs2, vmask, nf :), (: nf : vd_nf)}, + disasm: "vluxseg%nf\\ei4.v", "%vd_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VlSegmentIndexed, /*index_width*/ 4)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 4)"; - vluxsegei64{(: rs1, vs2, vmask, nf :), (: nf : vd)}, - disasm: "vluxseg%nf\\ei8.v", "%vd, (%rs1), %vs2, %vmask", + vluxsegei64{(: rs1, vs2, vmask, nf :), (: nf : vd_nf)}, + disasm: "vluxseg%nf\\ei8.v", "%vd_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VlSegmentIndexed, /*index_width*/ 8)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 8)"; // Vector indexed segment load ordered. - vloxsegei8{(: rs1, vs2, vmask, nf :), (: nf : vd)}, - disasm: "vluxseg%nf\\ei1.v", "%vd, (%rs1), %vs2, %vmask", + vloxsegei8{(: rs1, vs2, vmask, nf :), (: nf : vd_nf)}, + disasm: "vluxseg%nf\\ei1.v", "%vd_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VlSegmentIndexed, /*index_width*/ 1)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 1)"; - vloxsegei16{(: rs1, vs2, vmask, nf :), (: nf : vd)}, - disasm: "vluxseg%nf\\ei2.v", "%vd, (%rs1), %vs2, %vmask", + vloxsegei16{(: rs1, vs2, vmask, nf :), (: nf : vd_nf)}, + disasm: "vluxseg%nf\\ei2.v", "%vd_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VlSegmentIndexed, /*index_width*/ 2)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 2)"; - vloxsegei32{(: rs1, vs2, vmask, nf :), (: nf : vd)}, - disasm: "vluxseg%nf\\ei4.v", "%vd, (%rs1), %vs2, %vmask", + vloxsegei32{(: rs1, vs2, vmask, nf :), (: nf : vd_nf)}, + disasm: "vluxseg%nf\\ei4.v", "%vd_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VlSegmentIndexed, /*index_width*/ 4)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 4)"; - vloxsegei64{(: rs1, vs2, vmask, nf :), (: nf : vd)}, - disasm: "vluxseg%nf\\ei8.v", "%vd, (%rs1), %vs2, %vmask", + vloxsegei64{(: rs1, vs2, vmask, nf :), (: nf : vd_nf)}, + disasm: "vluxseg%nf\\ei8.v", "%vd_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VlSegmentIndexed, /*index_width*/ 8)", "absl::bind_front(&VlSegmentChild, /*element_width*/ 8)"; @@ -402,59 +402,59 @@ semfunc: "absl::bind_front(&VsIndexed, /*index_width*/ 8)"; // Vector unit-stride segment store. - vssege8{(: vs3, rs1, vmask, nf:)}, - disasm: "vsseg%nf\\e.v", "%vs3, (%rs1), %vmask", + vssege8{(: vs3_nf, rs1, vmask, nf:)}, + disasm: "vsseg%nf\\e.v", "%vs3_nf, (%rs1), %vmask", semfunc: "absl::bind_front(&VsSegment, /*element_width*/ 1)"; - vssege16{(: vs3, rs1, vmask, nf:)}, - disasm: "vsseg%nf\\e.v", "%vs3, (%rs1), %vmask", + vssege16{(: vs3_nf, rs1, vmask, nf:)}, + disasm: "vsseg%nf\\e.v", "%vs3_nf, (%rs1), %vmask", semfunc: "absl::bind_front(&VsSegment, /*element_width*/ 2)"; - vssege32{(: vs3, rs1, vmask, nf:)}, - disasm: "vsseg%nf\\e.v", "%vs3, (%rs1), %vmask", + vssege32{(: vs3_nf, rs1, vmask, nf:)}, + disasm: "vsseg%nf\\e.v", "%vs3_nf, (%rs1), %vmask", semfunc: "absl::bind_front(&VsSegment, /*element_width*/ 4)"; - vssege64{(: vs3, rs1, vmask, nf:)}, - disasm: "vsseg%nf\\e.v", "%vs3, (%rs1), %vmask", + vssege64{(: vs3_nf, rs1, vmask, nf:)}, + disasm: "vsseg%nf\\e.v", "%vs3_nf, (%rs1), %vmask", semfunc: "absl::bind_front(&VsSegment, /*element_width*/ 8)"; // Vector strided segment store. - vsssege8{(: vs3, rs1, rs2, vmask, nf: )}, - disasm: "vssseg%nf\\e8.v", "%vs3, (%rs1), %rs2, %vmask", + vsssege8{(: vs3_nf, rs1, rs2, vmask, nf: )}, + disasm: "vssseg%nf\\e8.v", "%vs3_nf, (%rs1), %rs2, %vmask", semfunc: "absl::bind_front(&VsSegmentStrided, /*element_width*/ 1)"; - vsssege16{(: vs3, rs1, rs2, vmask, nf: )}, - disasm: "vssseg%nf\\e16.v", "%vs3, (%rs1), %rs2, %vmask", + vsssege16{(: vs3_nf, rs1, rs2, vmask, nf: )}, + disasm: "vssseg%nf\\e16.v", "%vs3_nf, (%rs1), %rs2, %vmask", semfunc: "absl::bind_front(&VsSegmentStrided, /*element_width*/ 2)"; - vsssege32{(: vs3, rs1, rs2, vmask, nf: )}, - disasm: "vssseg%nf\\e32.v", "%vs3, (%rs1), %rs2, %vmask", + vsssege32{(: vs3_nf, rs1, rs2, vmask, nf: )}, + disasm: "vssseg%nf\\e32.v", "%vs3_nf, (%rs1), %rs2, %vmask", semfunc: "absl::bind_front(&VsSegmentStrided, /*element_width*/ 4)"; - vsssege64{(: vs3, rs1, rs2, vmask, nf: )}, - disasm: "vssseg%nf\\e64.v", "%vs3, (%rs1), %rs2, %vmask", + vsssege64{(: vs3_nf, rs1, rs2, vmask, nf: )}, + disasm: "vssseg%nf\\e64.v", "%vs3_nf, (%rs1), %rs2, %vmask", semfunc: "absl::bind_front(&VsSegmentStrided, /*element_width*/ 8)"; // Vector indexed segment store unordered. - vsuxsegei8{(: vs3, rs1, vs2, vmask, nf :)}, - disasm: "vsuxseg%nf\\ei1.v", "%vs3, (%rs1), %vs2, %vmask", + vsuxsegei8{(: vs3_nf, rs1, vs2, vmask, nf :)}, + disasm: "vsuxseg%nf\\ei1.v", "%vs3_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VsSegmentStrided, /*element_width*/ 1)"; - vsuxsegei16{(: vs3, rs1, vs2, vmask, nf :)}, - disasm: "vsuxseg%nf\\ei2.v", "%vs3, (%rs1), %vs2, %vmask", + vsuxsegei16{(: vs3_nf, rs1, vs2, vmask, nf :)}, + disasm: "vsuxseg%nf\\ei2.v", "%vs3_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VsSegmentStrided, /*element_width*/ 2)"; - vsuxsegei32{(: vs3, rs1, vs2, vmask, nf :)}, - disasm: "vsuxseg%nf\\ei4.v", "%vs3, (%rs1), %vs2, %vmask", + vsuxsegei32{(: vs3_nf, rs1, vs2, vmask, nf :)}, + disasm: "vsuxseg%nf\\ei4.v", "%vs3_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VsSegmentStrided, /*element_width*/ 4)"; - vsuxsegei64{(: vs3, rs1, vs2, vmask, nf :)}, - disasm: "vsuxseg%nf\\ei8.v", "%vs3, (%rs1), %vs2, %vmask", + vsuxsegei64{(: vs3_nf, rs1, vs2, vmask, nf :)}, + disasm: "vsuxseg%nf\\ei8.v", "%vs3_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VsSegmentStrided, /*element_width*/ 8)"; // Vector indexed segment store ordered. - vsoxsegei8{(: vs3, rs1, vs2, vmask, nf :)}, - disasm: "vsuxseg%nf\\ei1.v", "%vs3, (%rs1), %vs2, %vmask", + vsoxsegei8{(: vs3_nf, rs1, vs2, vmask, nf :)}, + disasm: "vsoxseg%nf\\ei1.v", "%vs3_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VsSegmentIndexed, /*index_width*/ 1)"; - vsoxsegei16{(: vs3, rs1, vs2, vmask, nf :)}, - disasm: "vsuxseg%nf\\ei2.v", "%vs3, (%rs1), %vs2, %vmask", + vsoxsegei16{(: vs3_nf, rs1, vs2, vmask, nf :)}, + disasm: "vsuxseg%nf\\ei2.v", "%vs3_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VsSegmentIndexed, /*index_width*/ 2)"; - vsoxsegei32{(: vs3, rs1, vs2, vmask, nf :)}, - disasm: "vsuxseg%nf\\ei4.v", "%vs3, (%rs1), %vs2, %vmask", + vsoxsegei32{(: vs3_nf, rs1, vs2, vmask, nf :)}, + disasm: "vsuxseg%nf\\ei4.v", "%vs3_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VsSegmentIndexed, /*index_width*/ 4)"; - vsoxsegei64{(: vs3, rs1, vs2, vmask, nf :)}, - disasm: "vsuxseg%nf\\ei8.v", "%vs3, (%rs1), %vs2, %vmask", + vsoxsegei64{(: vs3_nf, rs1, vs2, vmask, nf :)}, + disasm: "vsuxseg%nf\\ei8.v", "%vs3_nf, (%rs1), %vs2, %vmask", semfunc: "absl::bind_front(&VsSegmentIndexed, /*index_width*/ 8)"; // Integer OPIVV, OPIVX, OPIVI.
diff --git a/riscv/riscv_vector_memory_instructions.cc b/riscv/riscv_vector_memory_instructions.cc index 62a7316..72e8d2a 100644 --- a/riscv/riscv_vector_memory_instructions.cc +++ b/riscv/riscv_vector_memory_instructions.cc
@@ -108,8 +108,14 @@ std::min(vector_register_byte_length / element_size, num_segments); int num_regs = std::max(1, num_segments * element_size / vector_register_byte_length); - // Total number of registers written. - int total_regs = num_fields * num_regs; + // Compute emul, since this determines how many vector registers have been + // allocated for each field. + auto* rv_vector = static_cast<RiscVState*>(inst->state())->rv_vector(); + int emul = element_size * rv_vector->vector_length_multiplier() / + rv_vector->selected_element_width(); + int reg_mul = std::max(1, emul / 8); + // Total number of registers that may be written. + int total_regs = (num_fields - 1) * reg_mul + num_regs; // Verify that the dest_op has enough registers. Else signal error. auto* dest_op = static_cast<RV32VectorDestinationOperand*>(inst->Destination(0)); @@ -126,8 +132,7 @@ int load_data_index = 0; // Data is organized by field. So write back in that order. for (int field = 0; field < num_fields; field++) { - int start_reg = - field * num_regs + (start_segment / max_elements_per_vector); + int start_reg = field * reg_mul + (start_segment / max_elements_per_vector); int offset = start_segment % max_elements_per_vector; int remaining_data = num_segments; for (int reg = start_reg; reg < start_reg + num_regs; reg++) {