No public description

PiperOrigin-RevId: 967225262
Change-Id: Iab2f390d93552633c50869f0ed07f84522ab53b7
diff --git a/riscv/riscv_vector_fp_unary_instructions.cc b/riscv/riscv_vector_fp_unary_instructions.cc
index fbe3786..58c6d09 100644
--- a/riscv/riscv_vector_fp_unary_instructions.cc
+++ b/riscv/riscv_vector_fp_unary_instructions.cc
@@ -14,6 +14,7 @@
 
 #include "riscv/riscv_vector_fp_unary_instructions.h"
 
+#include <algorithm>
 #include <cmath>
 #include <cstdint>
 #include <limits>
@@ -70,27 +71,50 @@
   const int sew = rv_vector->selected_element_width();
   auto dest_op =
       static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
-  auto dest_db = dest_op->CopyDataBuffer();
   switch (sew) {
-    case 4:
-      for (int i = 0; i < vl; ++i) {
-        dest_db->Set<uint32_t>(
-            i, generic::GetInstructionSource<uint32_t>(inst, 0, 0));
+    case 4: {
+      using Vd = uint32_t;
+      int elements_per_vector =
+          rv_vector->vector_register_byte_length() / sizeof(Vd);
+      int max_regs = (vl + elements_per_vector - 1) / elements_per_vector;
+      int vector_index = 0;
+      for (int reg = 0; reg < max_regs; reg++) {
+        auto* dest_db = dest_op->CopyDataBuffer(reg);
+        auto dest_span = dest_db->Get<Vd>();
+        int element_count = std::min(elements_per_vector, vl - vector_index);
+        uint32_t val = generic::GetInstructionSource<uint32_t>(inst, 0, 0);
+        for (int i = 0; i < element_count; ++i) {
+          dest_span[i] = val;
+          vector_index++;
+        }
+        dest_db->Submit();
       }
       break;
-    case 8:
-      for (int i = 0; i < vl; ++i) {
-        dest_db->Set<uint64_t>(
-            i, generic::GetInstructionSource<uint64_t>(inst, 0, 0));
+    }
+    case 8: {
+      using Vd = uint64_t;
+      int elements_per_vector =
+          rv_vector->vector_register_byte_length() / sizeof(Vd);
+      int max_regs = (vl + elements_per_vector - 1) / elements_per_vector;
+      int vector_index = 0;
+      for (int reg = 0; reg < max_regs; reg++) {
+        auto* dest_db = dest_op->CopyDataBuffer(reg);
+        auto dest_span = dest_db->Get<Vd>();
+        int element_count = std::min(elements_per_vector, vl - vector_index);
+        uint64_t val = generic::GetInstructionSource<uint64_t>(inst, 0, 0);
+        for (int i = 0; i < element_count; ++i) {
+          dest_span[i] = val;
+          vector_index++;
+        }
+        dest_db->Submit();
       }
       break;
+    }
     default:
-      dest_db->DecRef();
-      LOG(ERROR) << "Vfmv.s.f: Illegal sew (" << sew << ")";
+      LOG(ERROR) << "Vfmv.v.f: Illegal sew (" << sew << ")";
       rv_vector->set_vector_exception();
       return;
   }
-  dest_db->Submit();
   rv_vector->clear_vstart();
 }
 
diff --git a/riscv/riscv_vector_permute_instructions.cc b/riscv/riscv_vector_permute_instructions.cc
index 090fb5a..f69903c 100644
--- a/riscv/riscv_vector_permute_instructions.cc
+++ b/riscv/riscv_vector_permute_instructions.cc
@@ -298,7 +298,14 @@
         // Compute result.
         Vd src_value = slide_value;
         int src_index = vector_index - offset;
-        if ((src_index > 0) && (src_index < rv_vector->max_vector_length())) {
+        // 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);
         }
         dest_span[i] = src_value;
diff --git a/riscv/test/riscv_vector_fp_unary_instructions_test.cc b/riscv/test/riscv_vector_fp_unary_instructions_test.cc
index a15e57b..0984864 100644
--- a/riscv/test/riscv_vector_fp_unary_instructions_test.cc
+++ b/riscv/test/riscv_vector_fp_unary_instructions_test.cc
@@ -55,6 +55,7 @@
 using ::mpact::sim::riscv::Vfcvtxufv;
 using ::mpact::sim::riscv::Vfmvfs;
 using ::mpact::sim::riscv::Vfmvsf;
+using ::mpact::sim::riscv::Vfmvvf;
 using ::mpact::sim::riscv::Vfncvtffw;
 using ::mpact::sim::riscv::Vfncvtfxuw;
 using ::mpact::sim::riscv::Vfncvtfxw;
@@ -733,6 +734,50 @@
   }
 }
 
+// Test vfmv.v.f instruction - broadcast scalar fp register across vector
+// register group.
+TEST_F(RiscVFPUnaryInstructionsTest, VfmvBroadcastScalar) {
+  SetSemanticFunction(&Vfmvvf);
+  AppendRegisterOperands<RVFpRegister>({kFs1Name}, {});
+  AppendVectorRegisterOperands({}, {kVd});
+  for (int byte_sew : {4, 8}) {
+    for (int lmul_index = 0; lmul_index < 7; lmul_index++) {
+      int lmul8 = kLmul8Values[lmul_index];
+      int vlen = lmul8 * kVectorLengthInBytes / (8 * byte_sew);
+      if (vlen == 0) vlen = 1;
+      uint32_t vtype =
+          (kSewSettingsByByteSize[byte_sew] << 3) | kLmulSettings[lmul_index];
+      ConfigureVectorUnit(vtype, vlen);
+      ClearVectorRegisterGroup(kVd, 8);
+      auto value = RandomValue<RVFpRegister::ValueType>();
+      freg_[kFs1]->data_buffer()->Set<RVFpRegister::ValueType>(0, value);
+      instruction_->Execute();
+      EXPECT_FALSE(rv_vector_->vector_exception());
+      int num_elements_per_reg = kVectorLengthInBytes / byte_sew;
+      for (int i = 0; i < vlen; i++) {
+        int reg_offset = i / num_elements_per_reg;
+        int elem_idx = i % num_elements_per_reg;
+        switch (byte_sew) {
+          case 4:
+            EXPECT_EQ(
+                vreg_[kVd + reg_offset]->data_buffer()->Get<uint32_t>(elem_idx),
+                static_cast<uint32_t>(value))
+                << "byte_sew: " << byte_sew << " lmul: " << lmul_index
+                << " i: " << i;
+            break;
+          case 8:
+            EXPECT_EQ(
+                vreg_[kVd + reg_offset]->data_buffer()->Get<uint64_t>(elem_idx),
+                static_cast<uint64_t>(value))
+                << "byte_sew: " << byte_sew << " lmul: " << lmul_index
+                << " i: " << i;
+            break;
+        }
+      }
+    }
+  }
+}
+
 // Test narrowing convert from unsigned integer to fp.
 TEST_F(RiscVFPUnaryInstructionsTest, Vfncvtfxuw) {
   SetSemanticFunction(&Vfncvtfxuw);