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++) {