fix(mpact): fix vector instruction bugs and refine trap logic

Refine RVV implementation in mpact simulator to address several
instruction bugs and trap handling mismatches:

1. Trap Handling: Append "&& is_interrupt" to existing trap conditions
   to resolve PC mismatch in ecall.
2. Mask Search: Correct the implementation for Vmsbf, Vmsif, and Vmsof
   mask search instructions.
3. Bitwise Ops: Update BitwiseMaskBinaryOp for vmand, vmnor, and vmxor.
4. vsetvli: Fix x0, x0 logic to preserve current_vl when max_vector_length
   remains unchanged.
5. Reduction: Fix data truncation in Vwredsum/u by aligning the
   accumulator with the destination's widening width.
6. Vslide:
   - Introduced is_down flag and corrected Vslideup/down logic.
   - Refined execution logic for Vslide1up/down single-element slide.

(Backported from mpact-riscv-vsi commit 6dac0e2a09d0845f1499f46ca2d05d24e1306605)
Note: The VlIndexed fix was omitted from this backport as it was natively fixed in google3 already.
PiperOrigin-RevId: 975873345
diff --git a/riscv/riscv_state.cc b/riscv/riscv_state.cc
index 3a2d616..69465e8 100644
--- a/riscv/riscv_state.cc
+++ b/riscv/riscv_state.cc
@@ -739,7 +739,7 @@
   // Get trap destination.
   int trap_vector_mode = tvec_csr->AsUint64() & 0x3ULL;
   uint64_t trap_target = tvec_csr->AsUint64() & ~0x3ULL;
-  if (trap_vector_mode == 1) {
+  if (trap_vector_mode == 1 && is_interrupt) {
     trap_target += 4 * exception_code;
   }
 
diff --git a/riscv/riscv_vector_opm_instructions.cc b/riscv/riscv_vector_opm_instructions.cc
index 21e3157..234a01f 100644
--- a/riscv/riscv_vector_opm_instructions.cc
+++ b/riscv/riscv_vector_opm_instructions.cc
@@ -190,8 +190,6 @@
     RiscVVectorState* rv_vector, const Instruction* inst,
     std::function<uint8_t(uint8_t, uint8_t)> op) {
   if (rv_vector->vector_exception()) return;
-  int vstart = rv_vector->vstart();
-  int vlen = rv_vector->vector_length();
   // Get spans for vector source and destination registers.
   auto* vs2_op = static_cast<RV32VectorSourceOperand*>(inst->Source(0));
   auto vs2_span = vs2_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
@@ -202,24 +200,21 @@
   auto* vd_db = vd_op->CopyDataBuffer();
   auto vd_span = vd_db->Get<uint8_t>();
   // Compute start and end locations.
+
+  int vstart = rv_vector->vstart();
   int start_byte = vstart / 8;
   int start_offset = vstart % 8;
-  uint8_t start_mask = 0b1111'1111 << start_offset;
-  int end_byte = (vlen - 1) / 8;
-  int end_offset = (vlen - 1) % 8;
-  uint8_t end_mask = 0b1111'1111 >> (7 - end_offset);
-  // The start byte is computed first, applying a mask to mask out any preceding
-  // bits.
-  vd_span[start_byte] =
-      (op(vs2_span[start_byte], vs1_span[start_byte]) & start_mask) |
-      (vd_span[start_byte] & ~start_mask);
-  // Perform the bitwise operation on each byte between start and end.
-  for (int i = start_byte + 1; i < end_byte; i++) {
+
+  if (start_byte < vd_span.size()) {
+    uint8_t start_mask = 0b1111'1111 << start_offset;
+    vd_span[start_byte] =
+        (op(vs2_span[start_byte], vs1_span[start_byte]) & start_mask) |
+        (vd_span[start_byte] & ~start_mask);
+  }
+
+  for (int i = start_byte + 1; i < vd_span.size(); i++) {
     vd_span[i] = op(vs2_span[i], vs1_span[i]);
   }
-  // Perform the bitwise operation with a mask on the end byte.
-  vd_span[end_byte] = (op(vs2_span[end_byte], vs1_span[end_byte]) & end_mask) |
-                      (vd_span[end_byte] & ~end_mask);
   vd_db->Submit();
   rv_vector->clear_vstart();
 }
diff --git a/riscv/riscv_vector_permute_instructions.cc b/riscv/riscv_vector_permute_instructions.cc
index 9dda8e9..9710286 100644
--- a/riscv/riscv_vector_permute_instructions.cc
+++ b/riscv/riscv_vector_permute_instructions.cc
@@ -172,7 +172,8 @@
 
 // This helper function handles the vector slide up/down instructions.
 template <typename Vd>
-void VSlideHelper(RiscVVectorState* rv_vector, Instruction* inst, int offset) {
+void VSlideHelper(RiscVVectorState* rv_vector, Instruction* inst, int offset,
+                  bool is_down) {
   if (rv_vector->vector_exception()) return;
   int num_elements = rv_vector->vector_length();
   int elements_per_vector =
@@ -208,17 +209,25 @@
     for (int i = item_index;
          (i < element_count) && (vector_index < num_elements); i++) {
       // Get the mask value.
-      int mask_index = i >> 3;
-      int mask_offset = i & 0b111;
+      int mask_index = vector_index >> 3;
+      int mask_offset = vector_index & 0b111;
       bool mask_value = ((mask_span[mask_index] >> mask_offset) & 0b1);
-      int src_index = vector_index - offset;
-      if ((src_index >= 0) && (mask_value)) {
-        // Compute result.
-        Vd src_value = 0;
-        if (src_index < rv_vector->max_vector_length()) {
-          src_value = generic::GetInstructionSource<Vd>(inst, 0, src_index);
+      if (mask_value) {
+        if (is_down) {
+          uint64_t src_idx = (uint64_t)vector_index + offset;
+          if (src_idx < rv_vector->max_vector_length()) {
+            dest_span[i] =
+                generic::GetInstructionSource<Vd>(inst, 0, (int)src_idx);
+          } else {
+            dest_span[i] = 0;
+          }
+        } else {
+          if ((uint64_t)vector_index >= offset) {
+            uint64_t src_idx = (uint64_t)vector_index - offset;
+            dest_span[i] =
+                generic::GetInstructionSource<Vd>(inst, 0, (int)src_idx);
+          }
         }
-        dest_span[i] = src_value;
       }
       vector_index++;
     }
@@ -239,13 +248,13 @@
   // Slide up amount is positive.
   switch (sew) {
     case 1:
-      return VSlideHelper<uint8_t>(rv_vector, inst, int_offset);
+      return VSlideHelper<uint8_t>(rv_vector, inst, int_offset, false);
     case 2:
-      return VSlideHelper<uint16_t>(rv_vector, inst, int_offset);
+      return VSlideHelper<uint16_t>(rv_vector, inst, int_offset, false);
     case 4:
-      return VSlideHelper<uint32_t>(rv_vector, inst, int_offset);
+      return VSlideHelper<uint32_t>(rv_vector, inst, int_offset, false);
     case 8:
-      return VSlideHelper<uint64_t>(rv_vector, inst, int_offset);
+      return VSlideHelper<uint64_t>(rv_vector, inst, int_offset, false);
     default:
       rv_vector->set_vector_exception();
       LOG(ERROR) << "Illegal SEW value";
@@ -257,18 +266,17 @@
   using ValueType = RV32Register::ValueType;
   auto* rv_vector = static_cast<RiscVState*>(inst->state())->rv_vector();
   int sew = rv_vector->selected_element_width();
-  auto offset = generic::GetInstructionSource<ValueType>(inst, 1, 0);
   // Slide down amount is negative.
-  int int_offset = -static_cast<int>(offset);
+  auto offset = generic::GetInstructionSource<ValueType>(inst, 1, 0);
   switch (sew) {
     case 1:
-      return VSlideHelper<uint8_t>(rv_vector, inst, int_offset);
+      return VSlideHelper<uint8_t>(rv_vector, inst, offset, true);
     case 2:
-      return VSlideHelper<uint16_t>(rv_vector, inst, int_offset);
+      return VSlideHelper<uint16_t>(rv_vector, inst, offset, true);
     case 4:
-      return VSlideHelper<uint32_t>(rv_vector, inst, int_offset);
+      return VSlideHelper<uint32_t>(rv_vector, inst, offset, true);
     case 8:
-      return VSlideHelper<uint64_t>(rv_vector, inst, int_offset);
+      return VSlideHelper<uint64_t>(rv_vector, inst, offset, true);
     default:
       rv_vector->set_vector_exception();
       LOG(ERROR) << "Illegal SEW value";
@@ -311,28 +319,31 @@
     auto* dest_db = dest_op->CopyDataBuffer(reg);
     auto dest_span = dest_db->Get<Vd>();
     // Write data into register subject to masking.
-    int element_count = std::min(elements_per_vector, num_elements);
+    int element_count = elements_per_vector;
     for (int i = item_index;
          (i < element_count) && (vector_index < num_elements); i++) {
       // Get the mask value.
-      int mask_index = i >> 3;
-      int mask_offset = i & 0b111;
+      int mask_index = vector_index >> 3;
+      int mask_offset = vector_index & 0b111;
       bool mask_value = ((mask_span[mask_index] >> mask_offset) & 0b1) != 0;
+
       if (mask_value) {
         // Compute result.
-        Vd src_value = slide_value;
-        int src_index = vector_index - offset;
-        // Fix for slide1 instructions:
-        // 1. For vslide1up (offset=1), src_index=0 is valid (vs2[0]), so check
-        // src_index >= 0.
-        // 2. For vslide1down (offset=-1), when vector_index=vl-1, src_index=vl.
-        // We must use
-        //    slide_value if src_index >= vl (num_elements), not
-        //    max_vector_length (VLMAX).
-        if ((src_index >= 0) && (src_index < num_elements)) {
-          src_value = generic::GetInstructionSource<Vd>(inst, 0, src_index);
+        Vd result;
+        if (offset == 1) {  // slide1up
+          if (vector_index == 0)
+            result = slide_value;
+          else
+            result =
+                generic::GetInstructionSource<Vd>(inst, 0, vector_index - 1);
+        } else {  // slide1down
+          if (vector_index == num_elements - 1)
+            result = slide_value;
+          else
+            result =
+                generic::GetInstructionSource<Vd>(inst, 0, vector_index + 1);
         }
-        dest_span[i] = src_value;
+        dest_span[i] = result;
       }
       vector_index++;
     }
diff --git a/riscv/riscv_vector_reduction_instructions.cc b/riscv/riscv_vector_reduction_instructions.cc
index 53d099f..df8e82d 100644
--- a/riscv/riscv_vector_reduction_instructions.cc
+++ b/riscv/riscv_vector_reduction_instructions.cc
@@ -293,18 +293,18 @@
   int sew = rv_vector->selected_element_width();
   switch (sew) {
     case 1:
-      return RiscVBinaryReductionVectorOp<uint16_t, uint8_t, uint8_t>(
+      return RiscVBinaryReductionVectorOp<uint16_t, uint8_t, uint16_t>(
           rv_vector, inst, [](uint16_t acc, uint8_t vs2) -> uint16_t {
             return acc + static_cast<uint16_t>(vs2);
           });
     case 2:
-      return RiscVBinaryReductionVectorOp<uint32_t, uint16_t, uint16_t>(
+      return RiscVBinaryReductionVectorOp<uint32_t, uint16_t, uint32_t>(
           rv_vector, inst, [](uint32_t acc, uint16_t vs2) -> uint32_t {
             return acc + static_cast<uint32_t>(vs2);
           });
       return;
     case 4:
-      return RiscVBinaryReductionVectorOp<uint64_t, uint32_t, uint32_t>(
+      return RiscVBinaryReductionVectorOp<uint64_t, uint32_t, uint64_t>(
           rv_vector, inst, [](uint64_t acc, uint32_t vs2) -> uint64_t {
             return acc + static_cast<uint64_t>(vs2);
           });
@@ -323,18 +323,18 @@
   int sew = rv_vector->selected_element_width();
   switch (sew) {
     case 1:
-      return RiscVBinaryReductionVectorOp<int16_t, int8_t, int8_t>(
+      return RiscVBinaryReductionVectorOp<int16_t, int8_t, int16_t>(
           rv_vector, inst, [](int16_t acc, int8_t vs2) -> int16_t {
             return acc + static_cast<int16_t>(vs2);
           });
     case 2:
-      return RiscVBinaryReductionVectorOp<int32_t, int16_t, int16_t>(
+      return RiscVBinaryReductionVectorOp<int32_t, int16_t, int32_t>(
           rv_vector, inst, [](int32_t acc, int16_t vs2) -> int32_t {
             return acc + static_cast<int32_t>(vs2);
           });
       return;
     case 4:
-      return RiscVBinaryReductionVectorOp<int64_t, int32_t, int32_t>(
+      return RiscVBinaryReductionVectorOp<int64_t, int32_t, int64_t>(
           rv_vector, inst, [](int64_t acc, int32_t vs2) -> int64_t {
             return acc + static_cast<int64_t>(vs2);
           });
diff --git a/riscv/riscv_vector_unary_instructions.cc b/riscv/riscv_vector_unary_instructions.cc
index 9183614..6769b71 100644
--- a/riscv/riscv_vector_unary_instructions.cc
+++ b/riscv/riscv_vector_unary_instructions.cc
@@ -297,7 +297,6 @@
     rv_vector->set_vector_exception();
     return;
   }
-  int vlen = rv_vector->vector_length();
   auto src_op = static_cast<RV32VectorSourceOperand*>(inst->Source(0));
   auto src_span = src_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
   auto mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(1));
@@ -306,10 +305,11 @@
       static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
   auto* dest_db = dest_op->CopyDataBuffer(0);
   auto dest_span = dest_db->Get<uint8_t>();
+  int physical_bits = dest_span.size() * 8;
   bool before_first = true;
   int last = 0;
   // Set the bits before the first active 1.
-  for (int i = 0; i < vlen; i++) {
+  for (int i = 0; i < physical_bits; i++) {
     last = i;
     int index = i >> 3;
     int offset = i & 0b111;
@@ -322,11 +322,13 @@
       dest_span[index] |= 1 << offset;
     }
   }
-  // Clear the remaining bits.
-  for (int i = last; !before_first && (i < vlen); i++) {
+  for (int i = last; !before_first && (i < physical_bits); i++) {
     int index = i >> 3;
     int offset = i & 0b111;
-    dest_span[index] &= ~(1 << offset);
+    int mask_value = (mask_span[index] >> offset) & 0b1;
+    if (mask_value) {
+      dest_span[index] &= ~(1 << offset);
+    }
   }
   dest_db->Submit();
   rv_vector->clear_vstart();
@@ -339,7 +341,6 @@
     rv_vector->set_vector_exception();
     return;
   }
-  int vlen = rv_vector->vector_length();
   auto src_op = static_cast<RV32VectorSourceOperand*>(inst->Source(0));
   auto src_span = src_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
   auto mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(1));
@@ -348,8 +349,9 @@
       static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
   auto* dest_db = dest_op->CopyDataBuffer(0);
   auto dest_span = dest_db->Get<uint8_t>();
+  int physical_bits = dest_span.size() * 8;
   uint8_t value = 1;
-  for (int i = 0; i < vlen; i++) {
+  for (int i = 0; i < physical_bits; i++) {
     int index = i >> 3;
     int offset = i & 0b111;
     int mask_value = (mask_span[index] >> offset) & 0b1;
@@ -376,17 +378,18 @@
     rv_vector->set_vector_exception();
     return;
   }
-  int vlen = rv_vector->vector_length();
   auto src_op = static_cast<RV32VectorSourceOperand*>(inst->Source(0));
   auto src_span = src_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
   auto mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(1));
   auto mask_span = mask_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
   auto dest_op =
       static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
+
   auto* dest_db = dest_op->CopyDataBuffer(0);
   auto dest_span = dest_db->Get<uint8_t>();
+  int physical_bits = dest_span.size() * 8;
   bool first = true;
-  for (int i = 0; i < vlen; i++) {
+  for (int i = 0; i < physical_bits; i++) {
     int index = i >> 3;
     int offset = i & 0b111;
     int mask_value = (mask_span[index] >> offset) & 0b1;
diff --git a/riscv/test/riscv_vector_opm_instructions_test.cc b/riscv/test/riscv_vector_opm_instructions_test.cc
index 786e12f..8c8070d 100644
--- a/riscv/test/riscv_vector_opm_instructions_test.cc
+++ b/riscv/test/riscv_vector_opm_instructions_test.cc
@@ -120,7 +120,7 @@
           int mask_index = i >> 3;
           int mask_offset = i & 0b111;
           bool result = (dst_span[mask_index] >> mask_offset) & 0b1;
-          if ((i < vstart) || (i >= vlen)) {
+          if (i < vstart) {
             bool vd = (vd_value[mask_index] >> mask_offset) & 0b1;
             EXPECT_EQ(result, vd) << "[" << i << "] " << std::hex
                                   << "vd: " << (int)vd_value[mask_index]
diff --git a/riscv/test/riscv_vector_reduction_instructions_test.cc b/riscv/test/riscv_vector_reduction_instructions_test.cc
index 827419c..3943f4f 100644
--- a/riscv/test/riscv_vector_reduction_instructions_test.cc
+++ b/riscv/test/riscv_vector_reduction_instructions_test.cc
@@ -78,15 +78,15 @@
     // Input values for 8 registers.
     Vs2 vs2_value[vs2_size * 8];
     auto vs2_span = Span<Vs2>(vs2_value);
-    Vs2 vs1_value[vs2_size];
-    auto vs1_span = Span<Vs2>(vs1_value);
+    Vd vs1_value[kVectorLengthInBytes / sizeof(Vd)];
+    auto vs1_span = Span<Vd>(vs1_value);
     AppendVectorRegisterOperands({kVs2, kVs1, kVmask}, {kVd});
     // Initialize input values.
     FillArrayWithRandomValues<Vs2>(vs2_span);
-    vs1_span[0] = RandomValue<Vs2>();
+    vs1_span[0] = RandomValue<Vd>();
     auto mask_span = Span<const uint8_t>(kA5Mask);
     SetVectorRegisterValues<uint8_t>({{kVmaskName, mask_span}});
-    SetVectorRegisterValues<Vs2>({{kVs1Name, Span<const Vs2>(vs1_span)}});
+    SetVectorRegisterValues<Vd>({{kVs1Name, Span<const Vd>(vs1_span)}});
     // Initialize the accumulator with the value from vs1[0].
     for (int i = 0; i < 8; i++) {
       auto vs2_name = absl::StrCat("v", kVs2 + i);